JustPaste.it

[PInvokeData("cfapi.h", MSDNShortId = "668C682E-47C2-41BC-A4F9-AA2F2B516F54")]
        [StructLayout(LayoutKind.Sequential, Pack = 1)]

        public struct CF_OPERATION_PARAMETERS
        {
            /// <summary/>
            public uint ParamSize;

            // Yes, this is strange, but needed to deal with struct size changing based on pointer size (40/48).
            private uint pad4_8;
            private ulong pad8_16;
            private ulong pad16_24;
            private ulong pad24_32;
            private IntPtr padp1;
            private IntPtr padp2;

            /// <summary/>
            public TRANSFERDATA TransferData { get => GetParam<TRANSFERDATA>(); set => SetParam(value); }

            /// <summary/>
            public RETRIEVEDATA RetrieveData { get => GetParam<RETRIEVEDATA>(); set => SetParam(value); }

            /// <summary/>
            public ACKDATA AckData { get => GetParam<ACKDATA>(); set => SetParam(value); }

            /// <summary/>
            public RESTARTHYDRATION RestartHydration { get => GetParam<RESTARTHYDRATION>(); set => SetParam(value); }

            /// <summary/>
            public TRANSFERPLACEHOLDERS TransferPlaceholders { get => GetParam<TRANSFERPLACEHOLDERS>(); set => SetParam(value); }

            /// <summary/>
            public ACKDEHYDRATE AckDehydrate { get => GetParam<ACKDEHYDRATE>(); set => SetParam(value); }

            /// <summary/>
            public ACKRENAME AckRename { get => GetParam<ACKRENAME>(); set => SetParam(value); }

            /// <summary/>
            public ACKDELETE AckDelete { get => GetParam<ACKDELETE>(); set => SetParam(value); }

            /// <summary>Gets the parameter value for this structure.</summary>
            /// <typeparam name="T">The type of the structure to retrieve.</typeparam>
            /// <returns>The requested structure.</returns>
            public unsafe T GetParam<T>() where T : struct
            {
                using var ptr = new PinnedObject(this);
                return ((IntPtr)ptr).ToStructure<T>(Marshal.SizeOf(typeof(CF_OPERATION_PARAMETERS)), 8);
            }

            /// <summary>Sets the parameter value for this structure.</summary>
            /// <typeparam name="T">The type of the structure to set.</typeparam>
            /// <param name="value">The value to set.</param>
            public void SetParam<T>(T value) where T : struct
            {
                unsafe
                {
                    fixed (ulong* p = &pad8_16)
                    {
                        ((IntPtr)(void*)p).Write(value, 0, Marshal.SizeOf(typeof(CF_OPERATION_PARAMETERS)) - 8);
                    }
                }
            }

            /// <summary>Creates a CF_OPERATION_PARAMETERS instance with the specified parameter value.</summary>
            /// <typeparam name="T">The parameter type.</typeparam>
            /// <param name="paramValue">The parameter value.</param>
            /// <returns>A CF_OPERATION_PARAMETERS instance initialized with <paramref name="paramValue"/> and the correct ParamSize.</returns>
            public static CF_OPERATION_PARAMETERS Create<T>(T paramValue = default) where T : struct
            {
                var op = new CF_OPERATION_PARAMETERS { ParamSize = CF_SIZE_OF_OP_PARAM<T>() };
                op.SetParam(paramValue);
                return op;
            }

            /// <summary>Gets the size value used in ParamSize given a specific parameter type.</summary>
            /// <typeparam name="T">The parameter type.</typeparam>
            /// <returns>The size of the structure.</returns>
            public static uint CF_SIZE_OF_OP_PARAM<T>() where T : struct => (uint)(Marshal.OffsetOf(typeof(CF_OPERATION_PARAMETERS), nameof(pad8_16)).ToInt32() + Marshal.SizeOf(typeof(T)));

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct TRANSFERDATA
            {
                /// <summary>Flags for transferring data.</summary>
                public CF_OPERATION_TRANSFER_DATA_FLAGS Flags;

                /// <summary>Status for transferring data. Set to STATUS_SUCCESS if the sync provider will transfer data to a placeholder.</summary>
                public NTStatus CompletionStatus;

                /// <summary>A valid user mode buffer.</summary>
                public IntPtr Buffer;

                /// <summary>The offset used with the <c>Length</c> to describe a range in the placeholder to which the data is transferred.</summary>
                public long Offset;

                /// <summary>The length in bytes of the <c>Buffer</c>.</summary>
                public long Length;
            }

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct RETRIEVEDATA
            {
                /// <summary>Flags for retrieving data.</summary>
                public CF_OPERATION_RETRIEVE_DATA_FLAGS Flags;

                /// <summary/>
                public IntPtr Buffer;

                /// <summary>The offset used with the <c>Length</c> to describe the range of data retrieved from a placeholder.</summary>
                public long Offset;

                /// <summary>The length in bytes of the <c>Buffer</c>.</summary>
                public long Length;

                /// <summary>The number of bytes retrieved on successful completion.</summary>
                public long ReturnedLength;
            }

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct ACKDATA
            {
                /// <summary>Flags for acknowledging data.</summary>
                public CF_OPERATION_ACK_DATA_FLAGS Flags;

                /// <summary>
                /// <para>Completion status of data acknowledgement.</para>
                /// <para>Set to STATUS_SUCCESS if the sync provider validates the data within the range to be acknowledged is good.</para>
                /// </summary>
                public NTStatus CompletionStatus;

                /// <summary>The offset in bytes of the placeholder data to be acknowledged.</summary>
                public long Offset;

                /// <summary>The length in bytes of data in the placeholder to be acknowledged.</summary>
                public long Length;
            }

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct RESTARTHYDRATION
            {
                /// <summary>Flags to restart placeholder hydration.</summary>
                public CF_OPERATION_RESTART_HYDRATION_FLAGS Flags;

                /// <summary>Optional. Contains updates to the files metadata.</summary>
                public IntPtr FsMetadata;

                /// <summary>Optional. When provided, the file identity is updated to this value. Otherwise, it remains the same.</summary>
                public IntPtr FileIdentity;

                /// <summary>Optional. This specifies the length of the <c>FileIdentity</c>.</summary>
                public uint FileIdentityLength;
            }

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct TRANSFERPLACEHOLDERS
            {
                /// <summary>Flags for transferring placeholders.</summary>
                public CF_OPERATION_TRANSFER_PLACEHOLDERS_FLAGS Flags;

                /// <summary>The completion status of the operation.</summary>
                public NTStatus CompletionStatus;

                /// <summary>Total number of placeholders.</summary>
                public long PlaceholderTotalCount;

                /// <summary>An array of placeholders to be transferred.</summary>
                ///[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Struct, SizeConst = 2)]
                public IntPtr PlaceholderArray;

                /// <summary>The number of placeholders being transferred.</summary>
                public uint PlaceholderCount;

                /// <summary>The placeholder entries that have been processed.</summary>
                public uint EntriesProcessed;

            }

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct ACKDEHYDRATE
            {
                /// <summary>Dehydrated data acknowledgment flags.</summary>
                public CF_OPERATION_ACK_DEHYDRATE_FLAGS Flags;

                /// <summary>The completion status of the operation.</summary>
                public NTStatus CompletionStatus;

                /// <summary>The file identity of the placeholder file to acknowledge dehydrated data for.</summary>
                public IntPtr FileIdentity;

                /// <summary>Length, in bytes, of the <c>FileIdentity</c>.</summary>
                public uint FileIdentityLength;
            }

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct ACKRENAME
            {
                /// <summary>Acknowledge rename placeholder flags.</summary>
                public CF_OPERATION_ACK_RENAME_FLAGS Flags;

                /// <summary>The completion status of the operation.</summary>
                public NTStatus CompletionStatus;
            }

            /// <summary/>
            [StructLayout(LayoutKind.Sequential)]
            public struct ACKDELETE
            {
                /// <summary>Acknowledge delete flags.</summary>
                public CF_OPERATION_ACK_DELETE_FLAGS Flags;

                /// <summary>The completion status of the operation.</summary>
                public NTStatus CompletionStatus;
            }
        }