Last active
June 24, 2024 13:57
-
-
Save udaken/2eddee945d68d11ec71526b45a811148 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Runtime.InteropServices; | |
| using Microsoft.Win32.SafeHandles; | |
| namespace ProjectedFSLib | |
| { | |
| static class Native | |
| { | |
| public static T? PtrToStructure<T>(IntPtr ptr) where T : struct | |
| => ptr == IntPtr.Zero ? default : Marshal.PtrToStructure<T>(ptr); | |
| } | |
| public enum HResult : int | |
| { | |
| Ok = 0, | |
| Pending = -2147023899, | |
| OutOfMemory = -2147024882, | |
| InsufficientBuffer = -2147024774, | |
| FileNotFound = -2147024894, | |
| VirtualizationUnavaliable = -2147024527, | |
| InternalError = -2147023537, | |
| AlreadyInitialized = -2147023649, | |
| AccessDenied = -2147024891, | |
| CannotDelete = -805306079, | |
| Directory = -2147024629, | |
| DirNotEmpty = -2147024751, | |
| Handle = -2147024890, | |
| InvalidArg = -2147024809, | |
| PathNotFound = -2147024893, | |
| ReparsePointEncountered = -2147020501, | |
| VirtualizationInvalidOp = -2147024511 | |
| } | |
| #region Common structures | |
| /// <summary> | |
| /// PRJ_NOTIFY_TYPES | |
| /// </summary> | |
| [Flags] | |
| public enum PRJ_NOTIFY_TYPES : uint | |
| { | |
| NONE = 0x00000000, | |
| SUPPRESS_NOTIFICATIONS = 0x00000001, | |
| FILE_OPENED = 0x00000002, | |
| NEW_FILE_CREATED = 0x00000004, | |
| FILE_OVERWRITTEN = 0x00000008, | |
| PRE_DELETE = 0x00000010, | |
| PRE_RENAME = 0x00000020, | |
| PRE_SET_HARDLINK = 0x00000040, | |
| FILE_RENAMED = 0x00000080, | |
| HARDLINK_CREATED = 0x00000100, | |
| FILE_HANDLE_CLOSED_NO_MODIFICATION = 0x00000200, | |
| FILE_HANDLE_CLOSED_FILE_MODIFIED = 0x00000400, | |
| FILE_HANDLE_CLOSED_FILE_DELETED = 0x00000800, | |
| FILE_PRE_CONVERT_TO_FULL = 0x00001000, | |
| USE_EXISTING_MASK = 0xFFFFFFFF, | |
| } | |
| /// <summary> | |
| /// PRJ_NOTIFICATION | |
| /// </summary> | |
| [Flags] | |
| public enum PRJ_NOTIFICATION | |
| { | |
| FILE_OPENED = 0x00000002, | |
| NEW_FILE_CREATED = 0x00000004, | |
| FILE_OVERWRITTEN = 0x00000008, | |
| PRE_DELETE = 0x00000010, | |
| PRE_RENAME = 0x00000020, | |
| PRE_SET_HARDLINK = 0x00000040, | |
| FILE_RENAMED = 0x00000080, | |
| HARDLINK_CREATED = 0x00000100, | |
| FILE_HANDLE_CLOSED_NO_MODIFICATION = 0x00000200, | |
| FILE_HANDLE_CLOSED_FILE_MODIFIED = 0x00000400, | |
| FILE_HANDLE_CLOSED_FILE_DELETED = 0x00000800, | |
| FILE_PRE_CONVERT_TO_FULL = 0x00001000, | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT | |
| { | |
| public IntPtr Pointer; | |
| } | |
| public struct PRJ_DIR_ENTRY_BUFFER_HANDLE | |
| { | |
| public IntPtr Pointer; | |
| } | |
| #endregion | |
| #region Virtualization instance APIs | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_NOTIFICATION_MAPPING | |
| { | |
| public PRJ_NOTIFY_TYPES NotificationBitMask; | |
| //[MarshalAs(UnmanagedType.LPWStr)] | |
| public IntPtr NotificationRoot; | |
| } | |
| public enum StartvirtualizingFlags | |
| { | |
| NONE = 0x00000000, | |
| USE_NEGATIVE_PATH_CACHE = 0x00000001, | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_STARTVIRTUALIZING_OPTIONS | |
| { | |
| public StartvirtualizingFlags Flags; | |
| public uint PoolThreadCount; | |
| public uint ConcurrentThreadCount; | |
| //PRJ_NOTIFICATION_MAPPING | |
| public IntPtr NotificationMappings; | |
| [MarshalAs(UnmanagedType.U4)] | |
| public int NotificationMappingsCount; | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_VIRTUALIZATION_INSTANCE_INFO | |
| { | |
| public Guid InstanceID; | |
| public uint WriteAlignment; | |
| } | |
| internal static partial class ProjectedFSLib | |
| { | |
| private const string dllName = "projectedfslib.dll"; | |
| /* | |
| STDAPI | |
| PrjStartVirtualizing( | |
| _In_ PCWSTR virtualizationRootPath, | |
| _In_ const PRJ_CALLBACKS* callbacks, | |
| _In_opt_ const void* instanceContext, | |
| _In_opt_ const PRJ_STARTVIRTUALIZING_OPTIONS* options, | |
| _Outptr_ PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT* namespaceVirtualizationContext | |
| ); | |
| */ | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjStartVirtualizing( | |
| string virtualizationRootPath, | |
| in PRJ_CALLBACKS callbacks, | |
| [Optional] IntPtr instanceContext, | |
| [Optional] in PRJ_STARTVIRTUALIZING_OPTIONS options, | |
| out PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext | |
| ); | |
| [DllImport(dllName, PreserveSig = true)] | |
| public static extern void PrjStopVirtualizing( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjClearNegativePathCache( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| out uint totalEntryNumber | |
| ); | |
| /* | |
| STDAPI | |
| PrjGetVirtualizationInstanceInfo( | |
| _In_ PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| _Out_ PRJ_VIRTUALIZATION_INSTANCE_INFO* virtualizationInstanceInfo | |
| ); | |
| */ | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjGetVirtualizationInstanceInfo( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| out PRJ_VIRTUALIZATION_INSTANCE_INFO virtualizationInstanceInfo | |
| ); | |
| } | |
| #endregion | |
| #region region Placeholder and File APIs | |
| public enum PRJ_PLACEHOLDER_ID | |
| { | |
| PRJ_PLACEHOLDER_ID_LENGTH = 128 | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_PLACEHOLDER_VERSION_INFO | |
| { | |
| [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)PRJ_PLACEHOLDER_ID.PRJ_PLACEHOLDER_ID_LENGTH)] | |
| public byte[] ProviderID; | |
| [MarshalAs(UnmanagedType.ByValArray, SizeConst = (int)PRJ_PLACEHOLDER_ID.PRJ_PLACEHOLDER_ID_LENGTH)] | |
| public byte[] ContentID; | |
| } | |
| static partial class ProjectedFSLib | |
| { | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjMarkDirectoryAsPlaceholder( | |
| string rootPathName, | |
| [Optional] string targetPathName, | |
| [Optional] IntPtr versionInfo, | |
| in Guid virtualizationInstanceID | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjMarkDirectoryAsPlaceholder( | |
| string rootPathName, | |
| [Optional] string targetPathName, | |
| [Optional] in PRJ_PLACEHOLDER_VERSION_INFO versionInfo, | |
| in Guid virtualizationInstanceID | |
| ); | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_FILE_BASIC_INFO | |
| { | |
| [MarshalAs(UnmanagedType.U1)] | |
| public bool IsDirectory; | |
| public long FileSize; | |
| public long CreationTime; | |
| public long LastAccessTime; | |
| public long LastWriteTime; | |
| public long ChangeTime; | |
| public uint FileAttributes; | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_PLACEHOLDER_INFO | |
| { | |
| public PRJ_FILE_BASIC_INFO FileBasicInfo; | |
| public struct EaInformation_ | |
| { | |
| public uint EaBufferSize; | |
| public uint OffsetToFirstEa; | |
| } | |
| public EaInformation_ EaInformation; | |
| public struct SecurityInformation_ | |
| { | |
| public uint SecurityBufferSize; | |
| public uint OffsetToSecurityDescriptor; | |
| } | |
| public SecurityInformation_ SecurityInformation; | |
| public struct StreamsInformation_ | |
| { | |
| public uint StreamsInfoBufferSize; | |
| public uint OffsetToFirstStreamInfo; | |
| } | |
| public StreamsInformation_ StreamsInformation; | |
| public PRJ_PLACEHOLDER_VERSION_INFO VersionInfo; | |
| [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] | |
| public byte[] VariableData; | |
| } | |
| static partial class ProjectedFSLib | |
| { | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjWritePlaceholderInfo( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| string destinationFileName, | |
| // PRJ_PLACEHOLDER_INFO | |
| IntPtr placeholderInfo, | |
| uint placeholderInfoSize | |
| ); | |
| } | |
| [Flags] | |
| public enum PRJ_UPDATE_TYPES | |
| { | |
| NONE = 0x00000000, | |
| ALLOW_DIRTY_METADATA = 0x00000001, | |
| ALLOW_DIRTY_DATA = 0x00000002, | |
| ALLOW_TOMBSTONE = 0x00000004, | |
| RESERVED1 = 0x00000008, | |
| RESERVED2 = 0x00000010, | |
| ALLOW_READ_ONLY = 0x00000020, | |
| MAX_VAL = (ALLOW_READ_ONLY << 1), | |
| } | |
| [Flags] | |
| public enum PRJ_UPDATE_FAILURE_CAUSES | |
| { | |
| NONE = 0x00000000, | |
| DIRTY_METADATA = 0x00000001, | |
| DIRTY_DATA = 0x00000002, | |
| TOMBSTONE = 0x00000004, | |
| READ_ONLY = 0x00000008, | |
| } | |
| static partial class ProjectedFSLib | |
| { | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjUpdateFileIfNeeded( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| string destinationFileName, | |
| // PRJ_PLACEHOLDER_INFO | |
| IntPtr placeholderInfo, | |
| uint placeholderInfoSize, | |
| [Optional] PRJ_UPDATE_TYPES updateFlags, | |
| [Optional] out PRJ_UPDATE_FAILURE_CAUSES failureReason | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjDeleteFile( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| string destinationFileName, | |
| [Optional] PRJ_UPDATE_TYPES updateFlags, | |
| [Optional] out PRJ_UPDATE_FAILURE_CAUSES failureReason | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjWriteFileData( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| in Guid dataStreamId, | |
| IntPtr buffer, | |
| ulong byteOffset, | |
| uint length | |
| ); | |
| } | |
| [Flags] | |
| public enum PRJ_FILE_STATE | |
| { | |
| PLACEHOLDER = 0x00000001, | |
| HYDRATED_PLACEHOLDER = 0x00000002, | |
| DIRTY_PLACEHOLDER = 0x00000004, | |
| FULL = 0x00000008, | |
| TOMBSTONE = 0x00000010, | |
| } | |
| static partial class ProjectedFSLib | |
| { | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjGetOnDiskFileState( | |
| string destinationFileName, | |
| out PRJ_FILE_STATE fileState | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = true)] | |
| public static extern SafeAlignedBuffer PrjAllocateAlignedBuffer( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| [MarshalAs(UnmanagedType.SysUInt)]ulong size | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = true)] | |
| public static extern void PrjFreeAlignedBuffer( | |
| IntPtr buffer | |
| ); | |
| } | |
| #endregion | |
| #region Callback support | |
| [Flags] | |
| public enum PRJ_CALLBACK_DATA_FLAGS | |
| { | |
| ENUM_RESTART_SCAN = 0x00000001, | |
| ENUM_RETURN_SINGLE_ENTRY = 0x00000002 | |
| } | |
| [StructLayout(LayoutKind.Sequential)] | |
| public struct PRJ_CALLBACK_DATA | |
| { | |
| public uint Size; | |
| public PRJ_CALLBACK_DATA_FLAGS Flags; | |
| public PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT NamespaceVirtualizationContext; | |
| public int CommandId; | |
| public Guid FileId; | |
| public Guid DataStreamId; | |
| [MarshalAs(UnmanagedType.LPWStr)] | |
| public string FilePathName; | |
| readonly IntPtr _VersionInfo; | |
| public PRJ_PLACEHOLDER_VERSION_INFO? VersionInfo | |
| => Native.PtrToStructure<PRJ_PLACEHOLDER_VERSION_INFO>(_VersionInfo); | |
| public uint TriggeringProcessId; | |
| [MarshalAs(UnmanagedType.LPWStr)] | |
| public string TriggeringProcessImageFileName; | |
| public IntPtr InstanceContext; | |
| } | |
| public delegate HResult PRJ_START_DIRECTORY_ENUMERATION_CB( | |
| in PRJ_CALLBACK_DATA callbackData, | |
| in Guid enumerationId | |
| ); | |
| public delegate HResult PRJ_GET_DIRECTORY_ENUMERATION_CB( | |
| in PRJ_CALLBACK_DATA callbackData, | |
| in Guid enumerationId, | |
| [Optional] string searchExpression, | |
| PRJ_DIR_ENTRY_BUFFER_HANDLE dirEntryBufferHandle | |
| ); | |
| public delegate HResult PRJ_END_DIRECTORY_ENUMERATION_CB( | |
| in PRJ_CALLBACK_DATA callbackData, | |
| in Guid enumerationId | |
| ); | |
| public delegate HResult PRJ_GET_PLACEHOLDER_INFO_CB( | |
| in PRJ_CALLBACK_DATA callbackData | |
| ); | |
| public delegate HResult PRJ_GET_FILE_DATA_CB( | |
| in PRJ_CALLBACK_DATA callbackData, | |
| ulong byteOffset, | |
| uint length | |
| ); | |
| public delegate HResult PRJ_QUERY_FILE_NAME_CB( | |
| in PRJ_CALLBACK_DATA callbackData | |
| ); | |
| [StructLayout(LayoutKind.Explicit)] | |
| public struct PRJ_NOTIFICATION_PARAMETERS | |
| { | |
| public struct PostCreate_ | |
| { | |
| public PRJ_NOTIFY_TYPES NotificationMask; | |
| } | |
| [FieldOffset(0)] | |
| public PostCreate_ PostCreate; | |
| public struct FileRenamed_ | |
| { | |
| public PRJ_NOTIFY_TYPES NotificationMask; | |
| } | |
| [FieldOffset(0)] | |
| public FileRenamed_ FileRenamed; | |
| public struct FileDeletedOnHandleClose_ | |
| { | |
| [MarshalAs(UnmanagedType.U1)] | |
| public bool IsFileModified; | |
| } | |
| [FieldOffset(0)] | |
| public FileDeletedOnHandleClose_ FileDeletedOnHandleClose; | |
| } | |
| public delegate HResult PRJ_NOTIFICATION_CB( | |
| in PRJ_CALLBACK_DATA callbackData, | |
| [MarshalAs(UnmanagedType.U1)] bool isDirectory, | |
| PRJ_NOTIFICATION notification, | |
| [Optional] string destinationFileName, | |
| [Optional] in PRJ_NOTIFICATION_PARAMETERS operationParameters | |
| ); | |
| public delegate void PRJ_CANCEL_COMMAND_CB( | |
| in PRJ_CALLBACK_DATA callbackData | |
| ); | |
| public struct PRJ_CALLBACKS | |
| { | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_START_DIRECTORY_ENUMERATION_CB StartDirectoryEnumerationCallback; | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_END_DIRECTORY_ENUMERATION_CB EndDirectoryEnumerationCallback; | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_GET_DIRECTORY_ENUMERATION_CB GetDirectoryEnumerationCallback; | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_GET_PLACEHOLDER_INFO_CB GetPlaceholderInfoCallback; | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_GET_FILE_DATA_CB GetFileDataCallback; | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_QUERY_FILE_NAME_CB QueryFileNameCallback; | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_NOTIFICATION_CB NotificationCallback; | |
| [MarshalAs(UnmanagedType.FunctionPtr)] | |
| public PRJ_CANCEL_COMMAND_CB CancelCommandCallback; | |
| } | |
| public enum PRJ_COMPLETE_COMMAND_TYPE | |
| { | |
| NOTIFICATION = 1, | |
| ENUMERATION = 2 | |
| } | |
| [StructLayout(LayoutKind.Explicit)] | |
| public struct PRJ_COMPLETE_COMMAND_EXTENDED_PARAMETERS | |
| { | |
| [FieldOffset(0)] | |
| public PRJ_COMPLETE_COMMAND_TYPE CommandType; | |
| public struct Notification_ | |
| { | |
| public PRJ_NOTIFY_TYPES NotificationMask; | |
| } | |
| [FieldOffset(4)] | |
| public Notification_ Notification; | |
| public struct Enumeration_ | |
| { | |
| public PRJ_DIR_ENTRY_BUFFER_HANDLE DirEntryBufferHandle; | |
| } | |
| [FieldOffset(4)] | |
| public Enumeration_ Enumeration; | |
| } | |
| static partial class ProjectedFSLib | |
| { | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjCompleteCommand( | |
| PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT namespaceVirtualizationContext, | |
| int commandId, | |
| HResult completionResult, | |
| [Optional] in PRJ_COMPLETE_COMMAND_EXTENDED_PARAMETERS extendedParameters | |
| ); | |
| #endregion | |
| #region Enumeration APIs | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = false)] | |
| public static extern void PrjFillDirEntryBuffer( | |
| string fileName, | |
| [Optional] in PRJ_FILE_BASIC_INFO fileBasicInfo, | |
| PRJ_DIR_ENTRY_BUFFER_HANDLE dirEntryBufferHandle | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = true)] | |
| [return: MarshalAs(UnmanagedType.U1)] | |
| public static extern bool PrjFileNameMatch( | |
| string fileNameToCheck, | |
| string pattern | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = true)] | |
| public static extern int PrjFileNameCompare( | |
| string fileName1, | |
| string fileName2 | |
| ); | |
| [DllImport(dllName, CharSet = CharSet.Unicode, PreserveSig = true)] | |
| [return: MarshalAs(UnmanagedType.U1)] | |
| public static extern bool PrjDoesNameContainWildCards( | |
| string fileName | |
| ); | |
| } | |
| #endregion | |
| public class SafeAlignedBuffer : SafeBuffer | |
| { | |
| protected SafeAlignedBuffer(bool ownsHandle) : base(ownsHandle) | |
| { | |
| } | |
| protected override bool ReleaseHandle() | |
| { | |
| if(handle != IntPtr.Zero) | |
| ProjectedFSLib.PrjFreeAlignedBuffer(handle); | |
| return true; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment