diff --git a/bindings/bindings.go b/bindings/bindings.go index 34ba79e..e0f29d7 100644 --- a/bindings/bindings.go +++ b/bindings/bindings.go @@ -11,7 +11,7 @@ import ( "syscall" "time" - "github.com/balazsgrill/potatodrive/filesystem" + "github.com/balazsgrill/potatodrive/win/projfs/filesystem" "github.com/spf13/afero" "golang.org/x/sys/windows/registry" ) diff --git a/win/cfapi/functions.go b/win/cfapi/functions.go new file mode 100644 index 0000000..d3f83fb --- /dev/null +++ b/win/cfapi/functions.go @@ -0,0 +1,91 @@ +//go:build windows + +package cfapi + +import ( + "syscall" + "unsafe" +) + +var ( + cldapilib = syscall.NewLazyDLL("cldapi.dll") + cfCloseHandle = cldapilib.NewProc("CfCloseHandle") + cfConnectSyncRoot = cldapilib.NewProc("CfConnectSyncRoot") + cfConvertToPlaceholder = cldapilib.NewProc("CfConvertToPlaceholder") + cfCreatePlaceholders = cldapilib.NewProc("CfCreatePlaceholders") + cfDisconnectSyncRoot = cldapilib.NewProc("CfDisconnectSyncRoot") + cfExecute = cldapilib.NewProc("CfExecute") + cfGetCorrelationVector = cldapilib.NewProc("CfGetCorrelationVector") + cfGetPlaceholderInfo = cldapilib.NewProc("CfGetPlaceholderInfo") + cfGetPlaceholderRangeInfo = cldapilib.NewProc("CfGetPlaceholderRangeInfo") + cfGetPlaceholderRangeInfoForHydration = cldapilib.NewProc("CfGetPlaceholderRangeInfoForHydration") + cfGetPlaceholderStateFromAttributeTag = cldapilib.NewProc("CfGetPlaceholderStateFromAttributeTag") + cfGetPlaceholderStateFromFileInfo = cldapilib.NewProc("CfGetPlaceholderStateFromFileInfo") + cfGetPlaceholderStateFromFindData = cldapilib.NewProc("CfGetPlaceholderStateFromFindData") + cfGetPlatformInfo = cldapilib.NewProc("CfGetPlatformInfo") + cfGetSyncRootInfoByHandle = cldapilib.NewProc("CfGetSyncRootInfoByHandle") + cfGetSyncRootInfoByPath = cldapilib.NewProc("CfGetSyncRootInfoByPath") + cfGetTransferKey = cldapilib.NewProc("CfGetTransferKey") + cfGetWin32HandleFromProtectedHandle = cldapilib.NewProc("CfGetWin32HandleFromProtectedHandle") + cfHydratePlaceholder = cldapilib.NewProc("CfHydratePlaceholder") + cfOpenFileWithOplock = cldapilib.NewProc("CfOpenFileWithOplock") + cfQuerySyncProviderStatus = cldapilib.NewProc("CfQuerySyncProviderStatus") + cfReferenceProtectedHandle = cldapilib.NewProc("CfReferenceProtectedHandle") + cfRegisterSyncRoot = cldapilib.NewProc("CfRegisterSyncRoot") + cfReleaseProtectedHandle = cldapilib.NewProc("CfReleaseProtectedHandle") + cfReleaseTransferKey = cldapilib.NewProc("CfReleaseTransferKey") + cfReportProviderProgress = cldapilib.NewProc("CfReportProviderProgress") + cfReportProviderProgress2 = cldapilib.NewProc("CfReportProviderProgress2") + cfReportSyncStatus = cldapilib.NewProc("CfReportSyncStatus") + cfRevertPlaceholder = cldapilib.NewProc("CfRevertPlaceholder") + cfSetCorrelationVector = cldapilib.NewProc("CfSetCorrelationVector") + cfSetInSyncState = cldapilib.NewProc("CfSetInSyncState") + cfSetPinState = cldapilib.NewProc("CfSetPinState") + cfUnregisterSyncRoot = cldapilib.NewProc("CfUnregisterSyncRoot") + cfUpdatePlaceholder = cldapilib.NewProc("CfUpdatePlaceholder") + cfUpdateSyncProviderStatus = cldapilib.NewProc("CfUpdateSyncProviderStatus") +) + +func CfCloseHandle(Handle syscall.Handle) uintptr { + ret, _, _ := cfCloseHandle.Call(uintptr(Handle)) + return ret +} +func CfConnectSyncRoot(SyncRootPath uintptr, CallbackTable []CF_CALLBACK_REGISTRATION, CallbackContext uintptr, ConnectFlags CF_CONNECT_FLAGS, ConnectionKey *CF_CONNECTION_KEY) uintptr { + ret, _, _ := cfConnectSyncRoot.Call(SyncRootPath, uintptr(unsafe.Pointer(&CallbackTable[0])), CallbackContext, uintptr(ConnectFlags), uintptr(unsafe.Pointer(ConnectionKey))) + return ret +} + +func CfRegisterSyncRoot(SyncRootPath uintptr, Registration *CF_SYNC_REGISTRATION, Policies *CF_SYNC_POLICIES, RegisterFlags CF_REGISTER_FLAGS) uintptr { + ret, _, _ := cfRegisterSyncRoot.Call(SyncRootPath, uintptr(unsafe.Pointer(Registration)), uintptr(unsafe.Pointer(Policies)), uintptr(RegisterFlags)) + return ret +} + +func CfConvertToPlaceholder(FileHandle syscall.Handle, FileIdentity uintptr, FileIdentityLength uint32, ConvertFlags CF_CONVERT_FLAGS, ConvertUsn uintptr, Overlapped uintptr) uintptr { + ret, _, _ := cfConvertToPlaceholder.Call(uintptr(FileHandle), FileIdentity, uintptr(FileIdentityLength), uintptr(ConvertFlags), ConvertUsn, Overlapped) + return ret +} + +func CfCreatePlaceholders(BaseDirectoryPath uintptr, PlaceholderArray []CF_PLACEHOLDER_CREATE_INFO, PlaceholderCount uint32, CreateFlags CF_CREATE_FLAGS, EntriesProcessed *uint32) uintptr { + ret, _, _ := cfCreatePlaceholders.Call(BaseDirectoryPath, uintptr(unsafe.Pointer(&PlaceholderArray[0])), uintptr(PlaceholderCount), uintptr(CreateFlags), uintptr(unsafe.Pointer(EntriesProcessed))) + return ret +} + +func CfDisconnectSyncRoot(ConnectionKey CF_CONNECTION_KEY) uintptr { + ret, _, _ := cfDisconnectSyncRoot.Call(uintptr(ConnectionKey)) + return ret +} + +func CfExecute(OpInfo *CF_OPERATION_INFO, OpParams uintptr) uintptr { + ret, _, _ := cfExecute.Call(uintptr(unsafe.Pointer(OpInfo)), OpParams) + return ret +} + +func CfGetCorrelationVector(FileHandle syscall.Handle, CorrelationVector *CorrelationVector) uintptr { + ret, _, _ := cfGetCorrelationVector.Call(uintptr(unsafe.Pointer(CorrelationVector))) + return ret +} + +func CfGetPlaceholderInfo(FileHandle syscall.Handle, InfoClass CF_PLACEHOLDER_INFO_CLASS, InfoBuffer uintptr, InfoBufferLength uint32, ReturnedLength *uint32) uintptr { + ret, _, _ := cfGetPlaceholderInfo.Call(uintptr(FileHandle), uintptr(InfoClass), InfoBuffer, uintptr(InfoBufferLength), uintptr(unsafe.Pointer(ReturnedLength))) + return ret +} diff --git a/win/cfapi/types.go b/win/cfapi/types.go new file mode 100644 index 0000000..a5a2794 --- /dev/null +++ b/win/cfapi/types.go @@ -0,0 +1,570 @@ +//go:build windows + +package cfapi + +import "syscall" + +type CF_CONNECTION_KEY int64 +type CF_TRANSFER_KEY int64 +type CF_REQUEST_KEY int64 + +// from https://github.com/microsoft/CorrelationVector-Go/blob/master/correlationvector/correlationvector.go +// CorrelationVector represents a lightweight vector for identifying and measuring causality. +type CorrelationVector struct { + BaseVector string + Extension int32 + Version Version + IsImmutable bool +} + +// Version represents a version of the correlation vector protocol. +type Version int + +type CF_PROCESS_INFO struct { + StructSize uint32 + ProcessId uint32 + ImagePath uintptr + PackageName uintptr + ApplicationId uintptr +} + +type CF_CALLBACK_INFO struct { + StructSize uint32 + ConnectionKey CF_CONNECTION_KEY + CallbackContext uintptr + VolumeGuidName uintptr + VolumeDosName uintptr + VolumeSerialNumber uint32 + SyncRootFileId int64 + SyncRootIdentity uintptr + SyncRootIdentityLength uint32 + FileId int64 + FileSize int64 + FileIdentity uintptr + FileIdentityLength uint32 + NormalizedPath uintptr + TransferKey CF_TRANSFER_KEY + PriorityHint uint8 + CorrelationVector *CorrelationVector + ProcessInfo *CF_PROCESS_INFO + RequestKey CF_REQUEST_KEY +} + +type CF_CALLBACK_TYPE uint32 + +const ( + CF_CALLBACK_TYPE_FETCH_DATA CF_CALLBACK_TYPE = 0 + CF_CALLBACK_TYPE_VALIDATE_DATA CF_CALLBACK_TYPE = 1 + CF_CALLBACK_TYPE_CANCEL_FETCH_DATA CF_CALLBACK_TYPE = 2 + CF_CALLBACK_TYPE_FETCH_PLACEHOLDERS CF_CALLBACK_TYPE = 3 + CF_CALLBACK_TYPE_CANCEL_FETCH_PLACEHOLDERS CF_CALLBACK_TYPE = 4 + CF_CALLBACK_TYPE_NOTIFY_FILE_OPEN_COMPLETION CF_CALLBACK_TYPE = 5 + CF_CALLBACK_TYPE_NOTIFY_FILE_CLOSE_COMPLETION CF_CALLBACK_TYPE = 6 + CF_CALLBACK_TYPE_NOTIFY_DEHYDRATE CF_CALLBACK_TYPE = 7 + CF_CALLBACK_TYPE_NOTIFY_DEHYDRATE_COMPLETION CF_CALLBACK_TYPE = 8 + CF_CALLBACK_TYPE_NOTIFY_DELETE CF_CALLBACK_TYPE = 9 + CF_CALLBACK_TYPE_NOTIFY_DELETE_COMPLETION CF_CALLBACK_TYPE = 10 + CF_CALLBACK_TYPE_NOTIFY_RENAME CF_CALLBACK_TYPE = 11 + CF_CALLBACK_TYPE_NOTIFY_RENAME_COMPLETION CF_CALLBACK_TYPE = 12 + CF_CALLBACK_TYPE_NONE CF_CALLBACK_TYPE = 0xffffffff +) + +type CF_CALLBACK_REGISTRATION struct { + Type CF_CALLBACK_TYPE + Callback uintptr +} + +type CF_CALLBACK_CANCEL_FLAGS uint32 + +type CF_CALLBACK_PARAMETERS_Cancel struct { + ParamSize uint32 + Flags CF_CALLBACK_CANCEL_FLAGS + FetchData struct { + FileOffset int64 + Length int64 + } +} + +type CF_CALLBACK_FETCH_DATA_FLAGS uint32 + +const ( + CF_CALLBACK_FETCH_DATA_FLAG_NONE CF_CALLBACK_FETCH_DATA_FLAGS = 0x00000000 + CF_CALLBACK_FETCH_DATA_FLAG_RECOVERY CF_CALLBACK_FETCH_DATA_FLAGS = 0x00000001 + CF_CALLBACK_FETCH_DATA_FLAG_EXPLICIT_HYDRATION CF_CALLBACK_FETCH_DATA_FLAGS = 0x00000002 +) + +type CF_CALLBACK_DEHYDRATION_REASON uint32 + +const ( + CF_CALLBACK_DEHYDRATION_REASON_NONE CF_CALLBACK_DEHYDRATION_REASON = 0 + CF_CALLBACK_DEHYDRATION_REASON_USER_MANUAL CF_CALLBACK_DEHYDRATION_REASON = 1 + CF_CALLBACK_DEHYDRATION_REASON_SYSTEM_LOW_SPACE CF_CALLBACK_DEHYDRATION_REASON = 2 + CF_CALLBACK_DEHYDRATION_REASON_SYSTEM_INACTIVITY CF_CALLBACK_DEHYDRATION_REASON = 3 + CF_CALLBACK_DEHYDRATION_REASON_SYSTEM_OS_UPGRADE CF_CALLBACK_DEHYDRATION_REASON = 4 +) + +type CF_CALLBACK_PARAMETERS_FetchData struct { + ParamSize uint32 + Flags CF_CALLBACK_FETCH_DATA_FLAGS + RequiredFileOffset int64 + RequiredLength int64 + OptionalFileOffset int64 + OptionalLength int64 + LastDehydrationTime int64 + LastDehydrationReason CF_CALLBACK_DEHYDRATION_REASON +} + +type CF_CALLBACK_VALIDATE_DATA_FLAGS uint32 + +const ( + CF_CALLBACK_VALIDATE_DATA_FLAG_NONE CF_CALLBACK_VALIDATE_DATA_FLAGS = 0x00000000 + CF_CALLBACK_VALIDATE_DATA_FLAG_EXPLICIT_HYDRATION CF_CALLBACK_VALIDATE_DATA_FLAGS = 0x00000001 +) + +type CF_CALLBACK_PARAMETERS_ValidateData struct { + Flags CF_CALLBACK_VALIDATE_DATA_FLAGS + RequiredFileOffset int64 + RequiredLength int64 +} + +type CF_CALLBACK_FETCH_PLACEHOLDERS_FLAGS uint32 + +const ( + CF_CALLBACK_FETCH_PLACEHOLDERS_FLAG_NONE CF_CALLBACK_FETCH_PLACEHOLDERS_FLAGS = 0x00000000 +) + +type CF_CALLBACK_PARAMETERS_FetchPlaceholders struct { + ParamSize uint32 + Flags CF_CALLBACK_FETCH_PLACEHOLDERS_FLAGS + Pattern uintptr +} + +type CF_CALLBACK_OPEN_COMPLETION_FLAGS uint32 + +const ( + CF_CALLBACK_OPEN_COMPLETION_FLAG_NONE CF_CALLBACK_OPEN_COMPLETION_FLAGS = 0x00000000 + CF_CALLBACK_OPEN_COMPLETION_FLAG_PLACEHOLDER_UNKNOWN CF_CALLBACK_OPEN_COMPLETION_FLAGS = 0x00000001 + CF_CALLBACK_OPEN_COMPLETION_FLAG_PLACEHOLDER_UNSUPPORTED CF_CALLBACK_OPEN_COMPLETION_FLAGS = 0x00000002 +) + +type CF_CALLBACK_PARAMETERS_OpenCompletion struct { + ParamSize uint32 + Flags CF_CALLBACK_OPEN_COMPLETION_FLAGS +} + +type CF_CALLBACK_CLOSE_COMPLETION_FLAGS uint32 + +const ( + CF_CALLBACK_CLOSE_COMPLETION_FLAG_NONE CF_CALLBACK_CLOSE_COMPLETION_FLAGS = 0x00000000 + CF_CALLBACK_CLOSE_COMPLETION_FLAG_DELETED CF_CALLBACK_CLOSE_COMPLETION_FLAGS = 0x00000001 +) + +type CF_CALLBACK_PARAMETERS_CloseCompletion struct { + ParamSize uint32 + Flags CF_CALLBACK_CLOSE_COMPLETION_FLAGS +} + +type CF_CALLBACK_DEHYDRATE_FLAGS uint32 + +const ( + CF_CALLBACK_DEHYDRATE_FLAG_NONE CF_CALLBACK_DEHYDRATE_FLAGS = 0x00000000 + CF_CALLBACK_DEHYDRATE_FLAG_BACKGROUND CF_CALLBACK_DEHYDRATE_FLAGS = 0x00000001 +) + +type CF_CALLBACK_PARAMETERS_Dehydrate struct { + ParamSize uint32 + Flags CF_CALLBACK_DEHYDRATE_FLAGS + Reason CF_CALLBACK_DEHYDRATION_REASON +} + +type CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS uint32 + +const ( + CF_CALLBACK_DEHYDRATE_COMPLETION_FLAG_NONE CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS = 0x00000000 + CF_CALLBACK_DEHYDRATE_COMPLETION_FLAG_BACKGROUND CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS = 0x00000001 + CF_CALLBACK_DEHYDRATE_COMPLETION_FLAG_DEHYDRATED CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS = 0x00000002 +) + +type CF_CALLBACK_PARAMETERS_DehydrateCompletion struct { + ParamSize uint32 + Flags CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS + Reason CF_CALLBACK_DEHYDRATION_REASON +} + +type CF_CALLBACK_RENAME_COMPLETION_FLAGS uint32 + +const ( + CF_CALLBACK_RENAME_COMPLETION_FLAG_NONE CF_CALLBACK_RENAME_COMPLETION_FLAGS = 0x00000000 +) + +type CF_CALLBACK_PARAMETERS_RenameCompletion struct { + ParamSize uint32 + Flags CF_CALLBACK_RENAME_COMPLETION_FLAGS + SourcePath uintptr +} + +type CF_CALLBACK_RENAME_FLAGS uint32 + +const ( + CF_CALLBACK_RENAME_FLAG_NONE CF_CALLBACK_RENAME_FLAGS = 0x00000000 + CF_CALLBACK_RENAME_FLAG_IS_DIRECTORY CF_CALLBACK_RENAME_FLAGS = 0x00000001 + CF_CALLBACK_RENAME_FLAG_SOURCE_IN_SCOPE CF_CALLBACK_RENAME_FLAGS = 0x00000002 + CF_CALLBACK_RENAME_FLAG_TARGET_IN_SCOPE CF_CALLBACK_RENAME_FLAGS = 0x00000004 +) + +type CF_CALLBACK_PARAMETERS_Rename struct { + ParamSize uint32 + Flags CF_CALLBACK_RENAME_FLAGS + TargetPath uintptr +} + +type CF_CALLBACK_DELETE_COMPLETION_FLAGS uint32 + +const ( + CF_CALLBACK_DELETE_COMPLETION_FLAG_NONE CF_CALLBACK_DELETE_COMPLETION_FLAGS = 0x00000000 +) + +type CF_CALLBACK_PARAMETERS_DeleteCompletion struct { + ParamSize uint32 + Flags CF_CALLBACK_DELETE_COMPLETION_FLAGS +} + +type CF_CALLBACK_DELETE_FLAGS uint32 + +const ( + CF_CALLBACK_DELETE_FLAG_NONE CF_CALLBACK_DELETE_FLAGS = 0x00000000 + CF_CALLBACK_DELETE_FLAG_IS_DIRECTORY CF_CALLBACK_DELETE_FLAGS = 0x00000001 + CF_CALLBACK_DELETE_FLAG_IS_UNDELETE CF_CALLBACK_DELETE_FLAGS = 0x00000002 +) + +type CF_CALLBACK_PARAMETERS_Delete struct { + ParamSize uint32 + Flags CF_CALLBACK_DELETE_FLAGS +} + +type CF_SYNC_REGISTRATION struct { + StructSize uint32 + ProviderName uintptr + ProviderVersion uintptr + SyncRootIdentity uintptr + SyncRootIdentityLength uint32 + FileIdentity uintptr + FileIdentityLength uint32 + ProviderId syscall.GUID +} + +type CF_SYNC_POLICIES struct { + StructSize uint32 + Hydration CF_HYDRATION_POLICY + Population CF_POPULATION_POLICY + InSync CF_INSYNC_POLICY + HardLink CF_HARDLINK_POLICY + PlaceholderManagement CF_PLACEHOLDER_MANAGEMENT_POLICY +} + +type CF_HYDRATION_POLICY_PRIMARY_USHORT int16 + +const ( + CF_HYDRATION_POLICY_PARTIAL CF_HYDRATION_POLICY_PRIMARY_USHORT = 0x0000 + CF_HYDRATION_POLICY_PROGRESSIVE CF_HYDRATION_POLICY_PRIMARY_USHORT = 0x0001 + CF_HYDRATION_POLICY_FULL CF_HYDRATION_POLICY_PRIMARY_USHORT = 0x0002 + CF_HYDRATION_POLICY_ALWAYS_FULL CF_HYDRATION_POLICY_PRIMARY_USHORT = 0x0003 +) + +type CF_HYDRATION_POLICY_MODIFIER_USHORT int16 + +const ( + CF_HYDRATION_POLICY_MODIFIER_NONE CF_HYDRATION_POLICY_MODIFIER_USHORT = 0x0000 + CF_HYDRATION_POLICY_MODIFIER_VALIDATION_REQUIRED CF_HYDRATION_POLICY_MODIFIER_USHORT = 0x0001 + CF_HYDRATION_POLICY_MODIFIER_STREAMING_ALLOWED CF_HYDRATION_POLICY_MODIFIER_USHORT = 0x0002 + CF_HYDRATION_POLICY_MODIFIER_AUTO_DEHYDRATION_ALLOWED CF_HYDRATION_POLICY_MODIFIER_USHORT = 0x0004 + CF_HYDRATION_POLICY_MODIFIER_ALLOW_FULL_RESTART_HYDRATION CF_HYDRATION_POLICY_MODIFIER_USHORT = 0x0008 +) + +type CF_HYDRATION_POLICY struct { + Primary CF_HYDRATION_POLICY_PRIMARY_USHORT + Modifier CF_HYDRATION_POLICY_MODIFIER_USHORT +} + +type CF_POPULATION_POLICY_PRIMARY_USHORT int16 + +const ( + CF_POPULATION_POLICY_PARTIAL CF_POPULATION_POLICY_PRIMARY_USHORT = 0x0000 + CF_POPULATION_POLICY_FULL CF_POPULATION_POLICY_PRIMARY_USHORT = 0x0002 + CF_POPULATION_POLICY_ALWAYS_FULL CF_POPULATION_POLICY_PRIMARY_USHORT = 0x0003 +) + +type CF_POPULATION_POLICY_MODIFIER_USHORT int16 + +const ( + CF_POPULATION_POLICY_MODIFIER_NONE CF_POPULATION_POLICY_MODIFIER_USHORT = 0x0000 +) + +type CF_POPULATION_POLICY struct { + Primary CF_POPULATION_POLICY_PRIMARY_USHORT + Modifier CF_POPULATION_POLICY_MODIFIER_USHORT +} + +type CF_INSYNC_POLICY uint32 + +const ( + CF_INSYNC_POLICY_NONE CF_INSYNC_POLICY = 0x00000000 + CF_INSYNC_POLICY_TRACK_FILE_CREATION_TIME CF_INSYNC_POLICY = 0x00000001 + CF_INSYNC_POLICY_TRACK_FILE_READONLY_ATTRIBUTE CF_INSYNC_POLICY = 0x00000002 + CF_INSYNC_POLICY_TRACK_FILE_HIDDEN_ATTRIBUTE CF_INSYNC_POLICY = 0x00000004 + CF_INSYNC_POLICY_TRACK_FILE_SYSTEM_ATTRIBUTE CF_INSYNC_POLICY = 0x00000008 + CF_INSYNC_POLICY_TRACK_DIRECTORY_CREATION_TIME CF_INSYNC_POLICY = 0x00000010 + CF_INSYNC_POLICY_TRACK_DIRECTORY_READONLY_ATTRIBUTE CF_INSYNC_POLICY = 0x00000020 + CF_INSYNC_POLICY_TRACK_DIRECTORY_HIDDEN_ATTRIBUTE CF_INSYNC_POLICY = 0x00000040 + CF_INSYNC_POLICY_TRACK_DIRECTORY_SYSTEM_ATTRIBUTE CF_INSYNC_POLICY = 0x00000080 + CF_INSYNC_POLICY_TRACK_FILE_LAST_WRITE_TIME CF_INSYNC_POLICY = 0x00000100 + CF_INSYNC_POLICY_TRACK_DIRECTORY_LAST_WRITE_TIME CF_INSYNC_POLICY = 0x00000200 + CF_INSYNC_POLICY_TRACK_FILE_ALL CF_INSYNC_POLICY = 0x0055550f + CF_INSYNC_POLICY_TRACK_DIRECTORY_ALL CF_INSYNC_POLICY = 0x00aaaaf0 + CF_INSYNC_POLICY_TRACK_ALL CF_INSYNC_POLICY = 0x00ffffff + CF_INSYNC_POLICY_PRESERVE_INSYNC_FOR_SYNC_ENGINE CF_INSYNC_POLICY = 0x80000000 +) + +type CF_HARDLINK_POLICY uint32 + +const ( + CF_HARDLINK_POLICY_NONE CF_HARDLINK_POLICY = 0x00000000 + CF_HARDLINK_POLICY_ALLOWED CF_HARDLINK_POLICY = 0x00000001 +) + +type CF_PLACEHOLDER_MANAGEMENT_POLICY uint32 + +const ( + CF_PLACEHOLDER_MANAGEMENT_POLICY_DEFAULT CF_PLACEHOLDER_MANAGEMENT_POLICY = 0x00000000 + CF_PLACEHOLDER_MANAGEMENT_POLICY_CREATE_UNRESTRICTED CF_PLACEHOLDER_MANAGEMENT_POLICY = 0x00000001 + CF_PLACEHOLDER_MANAGEMENT_POLICY_CONVERT_TO_UNRESTRICTED CF_PLACEHOLDER_MANAGEMENT_POLICY = 0x00000002 + CF_PLACEHOLDER_MANAGEMENT_POLICY_UPDATE_UNRESTRICTED CF_PLACEHOLDER_MANAGEMENT_POLICY = 0x00000004 +) + +type CF_REGISTER_FLAGS uint32 + +const ( + CF_REGISTER_FLAG_NONE CF_REGISTER_FLAGS = 0x00000000 + CF_REGISTER_FLAG_UPDATE CF_REGISTER_FLAGS = 0x00000001 + CF_REGISTER_FLAG_DISABLE_ON_DEMAND_POPULATION_ON_ROOT CF_REGISTER_FLAGS = 0x00000002 + CF_REGISTER_FLAG_MARK_IN_SYNC_ON_ROOT CF_REGISTER_FLAGS = 0x00000004 +) + +type CF_CONNECT_FLAGS uint32 + +const ( + CF_CONNECT_FLAG_NONE CF_CONNECT_FLAGS = 0x00000000 + CF_CONNECT_FLAG_REQUIRE_PROCESS_INFO CF_CONNECT_FLAGS = 0x00000002 + CF_CONNECT_FLAG_REQUIRE_FULL_FILE_PATH CF_CONNECT_FLAGS = 0x00000004 + CF_CONNECT_FLAG_BLOCK_SELF_IMPLICIT_HYDRATION CF_CONNECT_FLAGS = 0x00000008 +) + +type CF_CONVERT_FLAGS uint32 + +const ( + CF_CONVERT_FLAG_NONE CF_CONVERT_FLAGS = 0x00000000 + CF_CONVERT_FLAG_MARK_IN_SYNC CF_CONVERT_FLAGS = 0x00000001 + CF_CONVERT_FLAG_DEHYDRATE CF_CONVERT_FLAGS = 0x00000002 + CF_CONVERT_FLAG_ENABLE_ON_DEMAND_POPULATION CF_CONVERT_FLAGS = 0x00000004 + CF_CONVERT_FLAG_ALWAYS_FULL CF_CONVERT_FLAGS = 0x00000008 + CF_CONVERT_FLAG_FORCE_CONVERT_TO_CLOUD_FILE CF_CONVERT_FLAGS = 0x00000010 +) + +type USN int64 + +type CF_PLACEHOLDER_CREATE_INFO struct { + RelativeFileName uintptr + FsMetadata CF_FS_METADATA + FileIdentity uintptr + FileIdentityLength uint32 + Flags CF_PLACEHOLDER_CREATE_FLAGS + Result uintptr + CreateUsn USN +} + +type CF_FS_METADATA struct { + BasicInfo FILE_BASIC_INFO + FileSize int64 +} + +// https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-file_basic_info +type FILE_BASIC_INFO struct { + CreationTime int64 + LastAccessTime int64 + LastWriteTime int64 + ChangeTime int64 + FileAttributes int32 +} + +type CF_PLACEHOLDER_CREATE_FLAGS uint32 + +const ( + CF_PLACEHOLDER_CREATE_FLAG_NONE CF_PLACEHOLDER_CREATE_FLAGS = 0x00000000 + CF_PLACEHOLDER_CREATE_FLAG_DISABLE_ON_DEMAND_POPULATION CF_PLACEHOLDER_CREATE_FLAGS = 0x00000001 + CF_PLACEHOLDER_CREATE_FLAG_MARK_IN_SYNC CF_PLACEHOLDER_CREATE_FLAGS = 0x00000002 + CF_PLACEHOLDER_CREATE_FLAG_SUPERSEDE CF_PLACEHOLDER_CREATE_FLAGS = 0x00000004 + CF_PLACEHOLDER_CREATE_FLAG_ALWAYS_FULL CF_PLACEHOLDER_CREATE_FLAGS = 0x00000008 +) + +type CF_CREATE_FLAGS uint32 + +const ( + CF_CREATE_FLAG_NONE CF_CREATE_FLAGS = 0x00000000 + CF_CREATE_FLAG_STOP_ON_ERROR CF_CREATE_FLAGS = 0x00000001 +) + +type CF_OPERATION_INFO struct { + StructSize uint32 + Type CF_OPERATION_TYPE + ConnectionKey CF_CONNECTION_KEY + TransferKey CF_TRANSFER_KEY + CorrelationVector *CorrelationVector + SyncStatus *CF_SYNC_STATUS + RequestKey CF_REQUEST_KEY +} + +type CF_OPERATION_TYPE uint32 + +const ( + CF_OPERATION_TYPE_TRANSFER_DATA CF_OPERATION_TYPE = 0 + CF_OPERATION_TYPE_RETRIEVE_DATA CF_OPERATION_TYPE = 1 + CF_OPERATION_TYPE_ACK_DATA CF_OPERATION_TYPE = 2 + CF_OPERATION_TYPE_RESTART_HYDRATION CF_OPERATION_TYPE = 3 + CF_OPERATION_TYPE_TRANSFER_PLACEHOLDERS CF_OPERATION_TYPE = 4 + CF_OPERATION_TYPE_ACK_DEHYDRATE CF_OPERATION_TYPE = 5 + CF_OPERATION_TYPE_ACK_DELETE CF_OPERATION_TYPE = 6 + CF_OPERATION_TYPE_ACK_RENAME CF_OPERATION_TYPE = 7 +) + +type CF_SYNC_STATUS struct { + StructSize uint32 + Code uint32 + DescriptionOffset uint32 + DescriptionLength uint32 + DeviceIdOffset uint32 + DeviceIdLength uint32 +} + +type NTSTATUS uint32 + +type CF_OPERATION_TRANSFER_DATA_FLAGS uint32 + +const ( + CF_OPERATION_TRANSFER_DATA_FLAG_NONE CF_OPERATION_TRANSFER_DATA_FLAGS = 0x00000000 +) + +type CF_OPERATION_PARAMETERS_TransferData struct { + ParamSize uint32 + Flags CF_OPERATION_TRANSFER_DATA_FLAGS + CompletionStatus NTSTATUS + Buffer uintptr + Offset int64 + Length int64 +} + +type CF_OPERATION_RETRIEVE_DATA_FLAGS uint32 + +const ( + CF_OPERATION_RETRIEVE_DATA_FLAG_NONE CF_OPERATION_RETRIEVE_DATA_FLAGS = 0x00000000 +) + +type CF_OPERATION_PARAMETERS_RetrieveData struct { + ParamSize uint32 + Flags CF_OPERATION_RETRIEVE_DATA_FLAGS + Buffer uintptr + Offset int64 + Length int64 + ReturnedLength int64 +} + +type CF_OPERATION_ACK_DATA_FLAGS uint32 + +const ( + CF_OPERATION_ACK_DATA_FLAG_NONE CF_OPERATION_ACK_DATA_FLAGS = 0x00000000 +) + +type CF_OPERATION_PARAMETERS_AckData struct { + ParamSize uint32 + Flags CF_OPERATION_ACK_DATA_FLAGS + CompletionStatus NTSTATUS + Offset int64 + Length int64 +} + +type CF_OPERATION_RESTART_HYDRATION_FLAGS uint32 + +const ( + CF_OPERATION_RESTART_HYDRATION_FLAG_NONE CF_OPERATION_RESTART_HYDRATION_FLAGS = 0x00000000 + CF_OPERATION_RESTART_HYDRATION_FLAG_MARK_IN_SYNC CF_OPERATION_RESTART_HYDRATION_FLAGS = 0x00000001 +) + +type CF_OPERATION_PARAMETERS_RestartHydration struct { + ParamSize uint32 + Flags CF_OPERATION_RESTART_HYDRATION_FLAGS + FsMetadata *CF_FS_METADATA + FileIdentity uintptr + FileIdentityLength uint32 +} + +type CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS uint32 + +const ( + CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_NONE CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS = 0x00000000 + CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_STOP_ON_ERROR CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS = 0x00000001 + CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAG_DISABLE_ON_DEMAND_POPULATION CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS = 0x00000002 +) + +type CF_OPERATION_PARAMETERS_TransferPlaceholders struct { + ParamSize uint32 + Flags CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS + CompletionStatus NTSTATUS + PlaceholderTotalCount int64 + PlaceholderArray *CF_PLACEHOLDER_CREATE_INFO + PlaceholderCount uint32 + EntriesProcessed uint32 +} + +type CF_OPERATION_ACK_DEHYDRATE_FLAGS uint32 + +const ( + CF_OPERATION_ACK_DEHYDRATE_FLAG_NONE CF_OPERATION_ACK_DEHYDRATE_FLAGS = 0x00000000 +) + +type CF_OPERATION_PARAMETERS_AckDehydrate struct { + ParamSize uint32 + Flags CF_OPERATION_ACK_DEHYDRATE_FLAGS + CompletionStatus NTSTATUS + FileIdentity uintptr + FileIdentityLength uint32 +} + +type CF_OPERATION_ACK_DELETE_FLAGS uint32 + +const ( + CF_OPERATION_ACK_DELETE_FLAG_NONE CF_OPERATION_ACK_DELETE_FLAGS = 0x00000000 +) + +type CF_OPERATION_PARAMETERS_AckDelete struct { + ParamSize uint32 + Flags CF_OPERATION_ACK_DELETE_FLAGS + CompletionStatus NTSTATUS +} + +type CF_OPERATION_ACK_RENAME_FLAGS uint32 + +const ( + CF_OPERATION_ACK_RENAME_FLAG_NONE CF_OPERATION_ACK_RENAME_FLAGS = 0x00000000 +) + +type CF_OPERATION_PARAMETERS_AckRename struct { + ParamSize uint32 + Flags CF_OPERATION_ACK_RENAME_FLAGS + CompletionStatus NTSTATUS +} + +type CF_PLACEHOLDER_INFO_CLASS uint32 + +const ( + CF_PLACEHOLDER_INFO_BASIC CF_PLACEHOLDER_INFO_CLASS = 0 + CF_PLACEHOLDER_INFO_STANDARD CF_PLACEHOLDER_INFO_CLASS = 1 +) diff --git a/projfs/README.md b/win/projfs/README.md similarity index 100% rename from projfs/README.md rename to win/projfs/README.md diff --git a/filesystem/filesystem.go b/win/projfs/filesystem/filesystem.go similarity index 96% rename from filesystem/filesystem.go rename to win/projfs/filesystem/filesystem.go index 2bd261a..562ce36 100644 --- a/filesystem/filesystem.go +++ b/win/projfs/filesystem/filesystem.go @@ -12,7 +12,7 @@ import ( "C" - "github.com/balazsgrill/potatodrive/projfs" + "github.com/balazsgrill/potatodrive/win/projfs" "github.com/google/uuid" "github.com/spf13/afero" ) @@ -22,6 +22,8 @@ import ( "fmt" "path/filepath" "strings" + + "github.com/balazsgrill/potatodrive/win" ) type VirtualizationInstance struct { @@ -81,7 +83,7 @@ func (instance *VirtualizationInstance) start(rootPath string, filesystem afero. options := &projfs.PRJ_STARTVIRTUALIZING_OPTIONS{ NotificationMappings: &projfs.PRJ_NOTIFICATION_MAPPING{ NotificationBitMask: projfs.PRJ_NOTIFY_NEW_FILE_CREATED | projfs.PRJ_NOTIFY_FILE_OVERWRITTEN | projfs.PRJ_NOTIFY_FILE_HANDLE_CLOSED_FILE_DELETED | projfs.PRJ_NOTIFY_FILE_HANDLE_CLOSED_FILE_MODIFIED, - NotificationRoot: projfs.GetPointer(""), + NotificationRoot: win.GetPointer(""), }, NotificationMappingsCount: 1, PoolThreadCount: 4, diff --git a/filesystem/filesystem_test.go b/win/projfs/filesystem/filesystem_test.go similarity index 94% rename from filesystem/filesystem_test.go rename to win/projfs/filesystem/filesystem_test.go index a99ebbe..aabe3e7 100644 --- a/filesystem/filesystem_test.go +++ b/win/projfs/filesystem/filesystem_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/balazsgrill/potatodrive/filesystem" + "github.com/balazsgrill/potatodrive/win/projfs/filesystem" "github.com/spf13/afero" ) diff --git a/projfs/functions.go b/win/projfs/functions.go similarity index 91% rename from projfs/functions.go rename to win/projfs/functions.go index 1805c2d..2b106d1 100644 --- a/projfs/functions.go +++ b/win/projfs/functions.go @@ -6,6 +6,8 @@ import ( "fmt" "syscall" "unsafe" + + "github.com/balazsgrill/potatodrive/win" ) var ( @@ -60,7 +62,7 @@ func PrjCompleteCommand(namespaceVirtualizationContext PRJ_NAMESPACE_VIRTUALIZAT } func PrjDeleteFile(namespaceVirtualizationContext PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT, destinationFileName string, updateFlags uint32, failureReason *PRJ_UPDATE_FAILURE_CAUSES) uintptr { - sf := GetPointer(destinationFileName) + sf := win.GetPointer(destinationFileName) res, _, _ := prjDeleteFile.Call(uintptr(namespaceVirtualizationContext), sf, uintptr(updateFlags), uintptr(unsafe.Pointer(failureReason))) return res } @@ -71,26 +73,26 @@ func PrjDoesNameContainWildCards(searchExpression uintptr) bool { } func PrjFileNameCompare(f1 string, f2 string) int32 { - sf1 := GetPointer(f1) - sf2 := GetPointer(f2) + sf1 := win.GetPointer(f1) + sf2 := win.GetPointer(f2) i1, _, _ := prjFileNameCompare.Call(sf1, sf2) return int32(i1) } func PrjFileNameMatch(name string, pattern uintptr) bool { - sf1 := GetPointer(name) + sf1 := win.GetPointer(name) i1, _, _ := prjFileNameMatch.Call(sf1, pattern) return i1 != 0 } func PrjFillDirEntryBuffer(filename string, fileBasicInfo *PRJ_FILE_BASIC_INFO, dirEntryBufferHandle PRJ_DIR_ENTRY_BUFFER_HANDLE) uintptr { - sf1 := GetPointer(filename) + sf1 := win.GetPointer(filename) res, _, _ := prjFillDirEntryBuffer.Call(sf1, uintptr(unsafe.Pointer(fileBasicInfo)), uintptr(dirEntryBufferHandle)) return res } func PrjFillDirEntryBuffer2(dirEntryBufferHandle PRJ_DIR_ENTRY_BUFFER_HANDLE, filename string, fileBasicInfo *PRJ_FILE_BASIC_INFO, extendedInfo *PRJ_EXTENDED_INFO) uintptr { - sf1 := GetPointer(filename) + sf1 := win.GetPointer(filename) res, _, _ := prjFillDirEntryBuffer2.Call(uintptr(dirEntryBufferHandle), sf1, uintptr(unsafe.Pointer(fileBasicInfo)), uintptr(unsafe.Pointer(extendedInfo))) return res } @@ -101,23 +103,23 @@ func PrjFreeAlignedBuffer(buffer *any) uintptr { } func PrjGetOnDiskFileState(filename string, fileState *PRJ_FILE_STATE) uintptr { - sf1 := GetPointer(filename) + sf1 := win.GetPointer(filename) res, _, _ := prjGetOnDiskFileState.Call(sf1, uintptr(unsafe.Pointer(fileState))) return res } func PrjMarkDirectoryAsPlaceholder(rootPathName string, targetPathName string, versionInfo *PRJ_PLACEHOLDER_VERSION_INFO, virtualizationInstanceID *syscall.GUID) uintptr { - sf1 := GetPointer(rootPathName) + sf1 := win.GetPointer(rootPathName) var sf2 uintptr if targetPathName != "" { - sf2 = GetPointer(targetPathName) + sf2 = win.GetPointer(targetPathName) } res, _, _ := prjMarkDirectoryAsPlaceholder.Call(sf1, sf2, uintptr(unsafe.Pointer(versionInfo)), uintptr(unsafe.Pointer(virtualizationInstanceID))) return res } func PrjStartVirtualizing(virtualizationRootPath string, callbacks *PRJ_CALLBACKS, instanceContext any, options *PRJ_STARTVIRTUALIZING_OPTIONS, namespaceVirtualizationContext *PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT) uintptr { - sf1 := GetPointer(virtualizationRootPath) + sf1 := win.GetPointer(virtualizationRootPath) res, _, _ := prjStartVirtualizing.Call(sf1, uintptr(unsafe.Pointer(callbacks.to_raw())), uintptr(unsafe.Pointer(&instanceContext)), uintptr(unsafe.Pointer(options)), uintptr(unsafe.Pointer(namespaceVirtualizationContext))) return res } @@ -127,7 +129,7 @@ func PrjStopVirtualizing(namespaceVirtualizationContext PRJ_NAMESPACE_VIRTUALIZA } func PrjUpdateFileIfNeeded(namespaceVirtualizationContext PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT, destinationFileName string, placeholderInfo *PRJ_PLACEHOLDER_INFO, placeholderInfoSize uint32, updateFlags PRJ_UPDATE_TYPES, failureReason *PRJ_UPDATE_FAILURE_CAUSES) uintptr { - sf1 := GetPointer(destinationFileName) + sf1 := win.GetPointer(destinationFileName) res, _, _ := prjUpdateFileIfNeeded.Call(uintptr(namespaceVirtualizationContext), sf1, uintptr(unsafe.Pointer(placeholderInfo)), uintptr(placeholderInfoSize), uintptr(updateFlags), uintptr(unsafe.Pointer(failureReason))) return res } @@ -138,13 +140,13 @@ func PrjWriteFileData(namespaceVirtualizationContext PRJ_NAMESPACE_VIRTUALIZATIO } func PrjWritePlaceholderInfo(namespaceVirtualizationContext PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT, destinationFileName string, placeholderInfo *PRJ_PLACEHOLDER_INFO, placeholderInfoSize uint32) uintptr { - sf1 := GetPointer(destinationFileName) + sf1 := win.GetPointer(destinationFileName) res, _, _ := prjWritePlaceholderInfo.Call(uintptr(namespaceVirtualizationContext), sf1, uintptr(unsafe.Pointer(placeholderInfo)), uintptr(placeholderInfoSize)) return res } func PrjWritePlaceholderInfo2(namespaceVirtualizationContext PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT, destinationFileName string, placeholderInfo *PRJ_PLACEHOLDER_INFO, placeholderInfoSize uint32, ExtendedInfo *PRJ_EXTENDED_INFO) uintptr { - sf1 := GetPointer(destinationFileName) + sf1 := win.GetPointer(destinationFileName) res, _, _ := prjWritePlaceholderInfo2.Call(uintptr(namespaceVirtualizationContext), sf1, uintptr(unsafe.Pointer(placeholderInfo)), uintptr(placeholderInfoSize), uintptr(unsafe.Pointer(ExtendedInfo))) return res } diff --git a/projfs/provider.go b/win/projfs/provider.go similarity index 100% rename from projfs/provider.go rename to win/projfs/provider.go diff --git a/projfs/types.go b/win/projfs/types.go similarity index 96% rename from projfs/types.go rename to win/projfs/types.go index 17a3a35..1bc785d 100644 --- a/projfs/types.go +++ b/win/projfs/types.go @@ -2,7 +2,11 @@ package projfs -import "syscall" +import ( + "syscall" + + "github.com/balazsgrill/potatodrive/win" +) import "C" type PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT syscall.Handle @@ -109,7 +113,7 @@ type PRJ_CALLBACK_DATA struct { } func (data *PRJ_CALLBACK_DATA) GetFilePathName() string { - return GetString(data.FilePathName) + return win.GetString(data.FilePathName) } type PRJ_CALLBACKS struct { diff --git a/projfs/strings.go b/win/strings.go similarity index 91% rename from projfs/strings.go rename to win/strings.go index c1ce7c7..60d59e6 100644 --- a/projfs/strings.go +++ b/win/strings.go @@ -1,6 +1,6 @@ //go:build windows -package projfs +package win import ( "syscall"