#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member global using System; global using System.Runtime.InteropServices; global using System.Threading; global using Vanara.InteropServices; global using CLFS_CONTAINER_ID = System.UInt32; global using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME; using Vanara.Extensions; namespace Vanara.PInvoke; /// Functions supporting the Windows Common Log File System. public static partial class ClfsW32 { /// Base log file name 3-letter extension. public const string CLFS_BASELOG_EXTENSION = ".blf"; /// Container name extended attribute entry name. public const string EA_CONTAINER_NAME = "ContainerName"; /// Container size extended attribute entry name. public const string EA_CONTAINER_SIZE = "ContainerSize"; private const string Lib_Clfsw32 = "clfsw32.dll"; /// Allocate a blocks for marshaled reads or writes /// Length of the cb buffer. /// The pv user context. [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate void CLFS_BLOCK_ALLOCATION(uint cbBufferLength, IntPtr pvUserContext); /// A callback function that frees log blocks. /// The pv buffer. /// The pv user context. [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate void CLFS_BLOCK_DEALLOCATION(IntPtr pvBuffer, IntPtr pvUserContext); /// The current state of a container. [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_CONTAINER_INFORMATION")] [Flags] public enum CLFS_CONTAINER_STATE : uint { /// The container is in the process of initializing. ClsContainerInitializing = 0x01, /// The container is allocated, but is not in the active region of the log. ClsContainerInactive = 0x02, /// The container is being used as storage for part of the log. ClsContainerActive = 0x04, /// The container is marked for deletion, but still contains part of the active log. ClsContainerActivePendingDelete = 0x08, /// The container is marked for archive. ClsContainerPendingArchive = 0x10, /// The container is marked for deletion, but still contains log data that is not archived. ClsContainerPendingArchiveAndDelete = 0x20, } /// /// Specifies a context mode type that indicates the direction and access methods that a client uses to scan a log. The context mode is /// set by using ReadLogRecord, and is embedded in the read context that these two functions return. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ne-clfs-clfs_context_mode typedef enum _CLFS_CONTEXT_MODE { ClfsContextNone = // 0x00, ClfsContextUndoNext, ClfsContextPrevious, ClfsContextForward } CLFS_CONTEXT_MODE, *PCLFS_CONTEXT_MODE, PPCLFS_CONTEXT_MODE; [PInvokeData("clfs.h", MSDNShortId = "NE:clfs._CLFS_CONTEXT_MODE")] public enum CLFS_CONTEXT_MODE { /// /// Value: /// 0x00 /// Do not move the cursor. /// ClfsContextNone, /// Move the cursor backward to the next undo record. ClfsContextUndoNext, /// Move the cursor to the previous log record from the current read context. ClfsContextPrevious, /// Move the cursor to the next client log record from the current read context. ClfsContextForward, } /// Common log file system public flags and constants. [PInvokeData("clfs.h")] [Flags] public enum CLFS_FLAG : uint { /// Assigns no flags. CLFS_FLAG_NO_FLAGS = 0x00000000, /// /// Assigns a physical location for all appended records in a log that have not been previously assigned a physical location. All /// these records are made available for reading from other marshaling contexts. /// CLFS_FLAG_FORCE_APPEND = 0x00000001, /// /// Assigns a physical location for all appended records in a log that have not been previously assigned a physical location. All /// these records are made available for reading from other marshaling contexts. Then, the records are flushed to disk. /// CLFS_FLAG_FORCE_FLUSH = 0x00000002, /// Appends the current record by using the space that is reserved in the marshaling area. CLFS_FLAG_USE_RESERVATION = 0x00000004, CLFS_FLAG_REENTRANT_FILE_SYSTEM = 0x00000008, CLFS_FLAG_NON_REENTRANT_FILTER = 0x00000010, CLFS_FLAG_REENTRANT_FILTER = 0x00000020, CLFS_FLAG_IGNORE_SHARE_ACCESS = 0x00000040, CLFS_FLAG_READ_IN_PROGRESS = 0x00000080, CLFS_FLAG_MINIFILTER_LEVEL = 0x00000100, CLFS_FLAG_HIDDEN_SYSTEM_LOG = 0x00000200, } /// /// Defines types of I/O statistics reported by CLFS and is used when a client calls GetLogIoStatistics. Currently, log flush rates are /// the only type of statistic reported, but this enumeration will reflect more types of statistics in the future. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ne-clfs-clfs_iostats_class typedef enum _CLFS_IOSTATS_CLASS { // ClfsIoStatsDefault = 0x0000, ClfsIoStatsMax = 0xFFFF } CLFS_IOSTATS_CLASS, *PCLFS_IOSTATS_CLASS, PPCLFS_IOSTATS_CLASS; [PInvokeData("clfs.h", MSDNShortId = "NE:clfs._CLFS_IOSTATS_CLASS")] public enum CLFS_IOSTATS_CLASS { /// /// Value: /// 0x0000 /// The default I/O statistics exported. /// ClfsIoStatsDefault = 0x0000, /// /// Value: /// 0xFFFF /// The log flush rate. /// ClfsIoStatsMax = 0xFFFF, } /// Specifies whether a log is ephemeral. // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ne-clfs-clfs_log_archive_mode typedef enum _CLFS_LOG_ARCHIVE_MODE { // ClfsLogArchiveEnabled = 0x01, ClfsLogArchiveDisabled = 0x02 } CLFS_LOG_ARCHIVE_MODE, *PCLFS_LOG_ARCHIVE_MODE; [PInvokeData("clfs.h", MSDNShortId = "NE:clfs._CLFS_LOG_ARCHIVE_MODE")] public enum CLFS_LOG_ARCHIVE_MODE { /// /// Value: /// 0x01 /// Enables log archive (ephemeral logs) support. /// ClfsLogArchiveEnabled = 1, /// /// Value: /// 0x02 /// Disables ephemeral logs. /// ClfsLogArchiveDisabled, } /// Marshalling Context Flag [PInvokeData("clfs.h")] [Flags] public enum CLFS_MARSHALLING_FLAG : uint { CLFS_MARSHALLING_FLAG_NONE = 0x00000000, CLFS_MARSHALLING_FLAG_DISABLE_BUFF_INIT = 0x00000001, } /// Container scan mode flags. [PInvokeData("clfs.h")] [Flags] public enum CLFS_SCAN_MODE : byte { /// /// Reinitializes the scan context, but does not allocate associated storage. The initialization is destructive, because all data /// that is stored in the current scan context is lost. /// CLFS_SCAN_INIT = 0x01, /// /// Causes the next call to ScanLogContainers to proceed in a forward direction. Cannot be used if CLFS_SCAN_BACKWARD is specified. /// CLFS_SCAN_FORWARD = 0x02, /// /// Causes the next call to ScanLogContainers to proceed in a backward direction. Cannot be used if CLFS_SCAN_FORWARD is specified. /// CLFS_SCAN_BACKWARD = 0x04, /// Uninitializes the scan context, and deallocates system storage that is associated with a scan context. CLFS_SCAN_CLOSE = 0x08, /// Indicates that the scan context is already initialized. CLFS_SCAN_INITIALIZED = 0x10, /// Indicates that the scanned container descriptors are pre-fetched and buffered. CLFS_SCAN_BUFFERED = 0x20, } /// Definition of record types. [PInvokeData("clfs.h")] [Flags] public enum CLS_RECORD_TYPE : byte { /// The default record type of ClfsDataRecord is used. ClfsNullRecord = 0x00, /// User data records are read. ClfsDataRecord = 0x01, /// Restart records are read. ClfsRestartRecord = 0x02, /// Both restart and data records are read. ClfsClientRecord = 0x03 } /// Determines whether two LSNs from the same stream are equal. /// A pointer to a CLFS_LSN structure to be compared with plsn2. /// A pointer to a CLFS_LSN structure to be compared with plsn1. /// Returns TRUE if the two LSNs are equal; otherwise, FALSE. /// /// CLFS_LSN_NULL (the smallest LSN) and CLFS_LSN_INVALID (larger than any valid LSN) are valid arguments to this function. /// LSNs from different streams are not comparable. Do not use this function to compare LSNs from different streams. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/nf-clfs-clfslsnequal CLFSUSER_API BOOLEAN LsnEqual( [in] const CLS_LSN *plsn1, // [in] const CLS_LSN *plsn2 ); [DllImport(Lib_Clfsw32, SetLastError = false, ExactSpelling = true)] [PInvokeData("clfs.h", MSDNShortId = "NF:clfs.ClfsLsnEqual")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool LsnEqual(in CLS_LSN plsn1, in CLS_LSN plsn2); /// Determines whether one LSN is greater than another LSN. The two LSNs must be from the same stream. /// A pointer to a CLFS_LSN structure to be compared with plsn2. /// A pointer to a CLFS_LSN structure to be compared with plsn1. /// TRUE if plsn1 is strictly greater than plsn2; otherwise, FALSE. /// /// CLFS_LSN_NULL (the smallest LSN) and CLFS_LSN_INVALID (larger than any valid LSN) are valid arguments to this function. /// LSNs from different streams are not comparable. Do not use this function to compare LSNs from different streams. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/nf-clfs-clfslsngreater CLFSUSER_API BOOLEAN LsnGreater( [in] const CLS_LSN // *plsn1, [in] const CLS_LSN *plsn2 ); [DllImport(Lib_Clfsw32, SetLastError = false, ExactSpelling = true)] [PInvokeData("clfs.h", MSDNShortId = "NF:clfs.ClfsLsnGreater")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool LsnGreater(in CLS_LSN plsn1, in CLS_LSN plsn2); /// Determines whether one LSN is less than another LSN. The two LSNs must be from the same stream. /// A pointer to a CLFS_LSN structure to be compared with plsn2. /// A pointer to a CLFS_LSN structure to be compared with plsn1. /// TRUE if plsn1 is strictly less than plsn2; otherwise, FALSE. /// /// CLFS_LSN_NULL (the smallest LSN) and CLFS_LSN_INVALID (larger than any valid LSN) are valid arguments to this function. /// LSNs from different streams are not comparable. Do not use this function to compare LSNs from different streams. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/nf-clfs-clfslsnless CLFSUSER_API BOOLEAN LsnLess( [in] const CLS_LSN *plsn1, // [in] const CLS_LSN *plsn2 ); [DllImport(Lib_Clfsw32, SetLastError = false, ExactSpelling = true)] [PInvokeData("clfs.h", MSDNShortId = "NF:clfs.ClfsLsnLess")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool LsnLess(in CLS_LSN plsn1, in CLS_LSN plsn2); /// Determines whether a specified LSN is equal to the smallest possible LSN, which is CLFS_LSN_NULL. /// A pointer to the CLFS_LSN structure to be tested. /// TRUE if plsn is equal to CLFS_LSN_NULL; otherwise, FALSE. // https://docs.microsoft.com/en-us/windows/win32/api/clfs/nf-clfs-clfslsnnull CLFSUSER_API BOOLEAN LsnNull( [in] const CLS_LSN *plsn ); [DllImport(Lib_Clfsw32, SetLastError = false, ExactSpelling = true)] [PInvokeData("clfs.h", MSDNShortId = "NF:clfs.ClfsLsnNull")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool LsnNull(in CLS_LSN plsn); /// Represents a node identifier. // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-clfs_node_id typedef struct _CLFS_NODE_ID { ULONG cType; ULONG cbNode; // } CLFS_NODE_ID, *PCLFS_NODE_ID; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLFS_NODE_ID")] [StructLayout(LayoutKind.Sequential)] public struct CLFS_NODE_ID { /// The CLFS node type. public uint cType; /// The size of the CLFS node, in bytes. public uint cbNode; } /// Used by the GetNextLogArchiveExtent function to return information about log archive extents. // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_archive_descriptor typedef struct _CLS_ARCHIVE_DESCRIPTOR { // ULONGLONG coffLow; ULONGLONG coffHigh; CLS_CONTAINER_INFORMATION infoContainer; } CLS_ARCHIVE_DESCRIPTOR, *PCLS_ARCHIVE_DESCRIPTOR, PPCLS_ARCHIVE_DESCRIPTOR; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_ARCHIVE_DESCRIPTOR")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct CLS_ARCHIVE_DESCRIPTOR { /// The offset in the container to the first byte of the archive extent. public ulong coffLow; /// The offset in the container to the last byte of the archive extent. public ulong coffHigh; /// /// The container information structure that describes the container associated with the archive extent. For more information, see CLFS_CONTAINER_INFORMATION. /// public CLS_CONTAINER_INFORMATION infoContainer; } /// /// Describes general information about a container. The CreateLogContainerScanContext and ScanLogContainers functions use container /// descriptors to scan and return information about all Common Log File System (CLFS) containers. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_container_information typedef struct _CLS_CONTAINER_INFORMATION { // ULONG FileAttributes; ULONGLONG CreationTime; ULONGLONG LastAccessTime; ULONGLONG LastWriteTime; LONGLONG ContainerSize; ULONG // FileNameActualLength; ULONG FileNameLength; WCHAR FileName[CLFS_MAX_CONTAINER_INFO]; CLFS_CONTAINER_STATE State; CLFS_CONTAINER_ID // PhysicalContainerId; CLFS_CONTAINER_ID LogicalContainerId; } CLS_CONTAINER_INFORMATION, *PCLS_CONTAINER_INFORMATION, PPCLS_CONTAINER_INFORMATION; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_CONTAINER_INFORMATION")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct CLS_CONTAINER_INFORMATION { /// /// The file system attributes. CLFS uses the following attributes: /// /// /// FILE_ATTRIBUTE_ARCHIVE - The log is not ephemeral. /// /// /// FILE_ATTRIBUTE_DEDICATED - The log is not multiplexed. /// /// /// FILE_ATTRIBUTE_READONLY - The file is read-only. Applications can read the file, but cannot write to it or delete it. /// /// /// CLFS ignores but preserves all other file attribute values. The /// SetFileAttributes /// topic lists the valid values for attributes. /// public FileFlagsAndAttributes FileAttributes; /// The time a file is created. public FILETIME CreationTime; /// The last time a container is read from or written to. public FILETIME LastAccessTime; /// The last time a container is written to. public FILETIME LastWriteTime; /// The size of a container, in bytes. public long ContainerSize; /// /// The size of the actual file name, in characters. /// This number is different than FileNameLength when the file name of the container is longer than MAX_PATH_LENGTH. /// public uint FileNameActualLength; /// The size of the file name in the FileName buffer, in characters. public uint FileNameLength; /// A pointer to a string that contains the file name for a container. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] public string FileName; /// /// The current state of a container. /// This member can be one of the following values. /// /// /// Value /// Meaning /// /// /// ClfsContainerInitializing /// The container is in the process of initializing. /// /// /// ClfsContainerInactive /// The container is allocated, but is not in the active region of the log. /// /// /// ClfsContainerActive /// The container is being used as storage for part of the log. /// /// /// ClfsContainerActivePendingDelete /// The container is marked for deletion, but still contains part of the active log. /// /// /// ClfsContainerPendingArchive /// The container is marked for archive. /// /// /// ClfsContainerPendingArchiveAndDelete /// The container is marked for deletion, but still contains log data that is not archived. /// /// /// public CLFS_CONTAINER_STATE State; /// The physical container identifier that cannot be changed. public CLFS_CONTAINER_ID PhysicalContainerId; /// The logical container identifier that changes every time the container is recycled. public CLFS_CONTAINER_ID LogicalContainerId; } /// Describes general information about a log. The GetLogFileInformation function returns the CLFS_INFORMATION structure. // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_information typedef struct _CLS_INFORMATION { LONGLONG // TotalAvailable; LONGLONG CurrentAvailable; LONGLONG TotalReservation; ULONGLONG BaseFileSize; ULONGLONG ContainerSize; ULONG // TotalContainers; ULONG FreeContainers; ULONG TotalClients; ULONG Attributes; ULONG FlushThreshold; ULONG SectorSize; CLS_LSN // MinArchiveTailLsn; CLS_LSN BaseLsn; CLS_LSN LastFlushedLsn; CLS_LSN LastLsn; CLS_LSN RestartLsn; GUID Identity; } CLS_INFORMATION, // *PCLS_INFORMATION, *PPCLS_INFORMATION; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_INFORMATION")] [StructLayout(LayoutKind.Sequential)] public struct CLS_INFORMATION { /// /// The total available space that is allocated to a log, in bytes. /// This member is the sum of the sizes of all containers that are allocated to the dedicated log. /// public long TotalAvailable; /// The space that is available in a log to append new records and reservation allocations, in bytes. public long CurrentAvailable; /// The total space in a log that is dedicated to reservation allocations. public long TotalReservation; /// The size of the base log, in bytes. public ulong BaseFileSize; /// The size of a container, in bytes. public ulong ContainerSize; /// The number of active containers that are associated with a dedicated log. public uint TotalContainers; /// The number of containers that are not in an active log. public uint FreeContainers; /// The number of log streams that are active in a physical log. public uint TotalClients; /// /// The log attributes that are set by using the fFlagsAndAttributes parameter of CreateLogFile when a log is created. /// public uint Attributes; /// /// The number of bytes of data that can remain pending on the internal flush queue before the Common Log File System (CLFS) /// automatically writes the data to disk. /// public uint FlushThreshold; /// /// The sector size of the underlying disk geometry, in bytes. /// The sector size is assumed to be a multiple of 512 and consistent across log containers. /// public uint SectorSize; /// The log sequence number (LSN) of the log archive tail. public CLS_LSN MinArchiveTailLsn; /// The LSN that marks the start of the active region of a log. public CLS_LSN BaseLsn; /// /// The value of LastFlushedLsn indicates that any LSNs smaller than the one specified are already flushed to disk. /// public CLS_LSN LastFlushedLsn; /// The value of LastLsn indicates that any LSNs smaller than the one specified are already appended to the log. public CLS_LSN LastLsn; /// /// The LSN of the last written restart record. /// If the log does not have a restart area, the LSN has the value of CLFS_LSN_INVALID. /// public CLS_LSN RestartLsn; /// The unique identifier for a log. public Guid Identity; } /// /// Defines the statistics that are reported by GetLogIoStatistics. Initially, statistics packets report only flush statistics, including /// the frequency of data and metadata flushes on a physical log and the amount of data and metadata flushed. The flush statistics are /// defined by the following I/O statistics packet types. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_io_statistics typedef struct _CLS_IO_STATISTICS { // CLS_IO_STATISTICS_HEADER hdrIoStats; ULONGLONG cFlush; ULONGLONG cbFlush; ULONGLONG cMetaFlush; ULONGLONG cbMetaFlush; } // CLS_IO_STATISTICS, *PCLS_IO_STATISTICS, PPCLS_IO_STATISTICS; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_IO_STATISTICS")] [StructLayout(LayoutKind.Sequential)] public struct CLS_IO_STATISTICS { /// The header for the statistics buffer. public CLS_IO_STATISTICS_HEADER hdrIoStats; /// The frequency of data flushes for the logging session. public ulong cFlush; /// The cumulative number of bytes of data flushed in the logging session. public ulong cbFlush; /// The frequency of metadata flushes for the logging session. public ulong cMetaFlush; /// The cumulative number of bytes of metadata flushed in the logging session. public ulong cbMetaFlush; } /// /// Header for information retrieved by the GetLogIoStatistics function, which defines the I/O performance counters of a log. /// /// This header is followed by the I/O statistics counters. // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_io_statistics_header typedef struct _CLS_IO_STATISTICS_HEADER { // UCHAR ubMajorVersion; UCHAR ubMinorVersion; CLFS_IOSTATS_CLASS eStatsClass; USHORT cbLength; ULONG coffData; } // CLS_IO_STATISTICS_HEADER, *PCLS_IO_STATISTICS_HEADER, PPCLS_IO_STATISTICS_HEADER; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_IO_STATISTICS_HEADER")] [StructLayout(LayoutKind.Sequential)] public struct CLS_IO_STATISTICS_HEADER { /// The major version of the statistics buffer. public byte ubMajorVersion; /// The minor version of the statistics buffer. public byte ubMinorVersion; /// /// The class of I/O statistics that is exported. Currently, flush statistics are the only statistics information exported. These /// statistics include the frequency of data and metadata flushes on a dedicated log and the amount of data and metadata flushed. /// Because flush statistics are the sole statistics class, this member is currently unused but will be used in the future. /// public CLFS_IOSTATS_CLASS eStatsClass; /// The length of the statistics buffer, including the header. public ushort cbLength; /// /// The offset of statistics counters from the beginning of the packet where the statistics data begins. This field allows /// transparent modifications to the header and length without affecting how the statistics data is accessed. /// public uint coffData; } /// Represents a valid log address. /// /// /// The LSN is the valid address that is unique to a client, and returned after the client appends a record to the log. The address /// remains valid if the system does not fail, or its marshaled log buffer is flushed successfully to disk. /// /// In log streams, LSNs increase monotonically. You cannot compare LSNs between log streams. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_lsn typedef struct _CLS_LSN { ULONGLONG Internal; } CLS_LSN, // *PCLS_LSN, PPCLS_LSN; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_LSN")] [StructLayout(LayoutKind.Sequential)] public struct CLS_LSN : IEquatable, IComparable { /// The log sequence number (LSN). public ulong Internal; /// Creates a log sequence number (LSN), given a container ID, a block offset, and a record sequence number. /// The container ID. This value must be an integer between 0x0 and 0xFFFFFFFF. /// The block offset. This value must be a multiple of 512. /// The record sequence number. This value must be an integer between 0 - 511. public CLS_LSN(CLFS_CONTAINER_ID cidContainer, uint offBlock, uint cRecord) => Internal = LsnCreate(cidContainer, offBlock, cRecord).Internal; /// Retrieves the logical container ID from this LSN. /// /// Returns the logical container ID. The logical container ID is not necessarily the same as the ID of the physical container on /// stable storage. /// public CLFS_CONTAINER_ID ContainerId => LsnContainer(this); /// Returns the sector-aligned block offset that is contained in this LSN. /// LsnBlockOffset returns the block offset. /// /// /// The block offset that is returned is a multiple of the sector size on the stable storage medium. For example, if the sector size /// is 1024 bytes, the block offset is a multiple of 1024. /// /// public uint BlockOffset => LsnBlockOffset(this); /// Retrieves the record sequence number. /// The record sequence number. public uint RecordSequence => LsnRecordSequence(this); /// Determines if this is equal to CLFS_LSN_INVALID. /// if plsn is equal to CLFS_LSN_INVALID; otherwise, . public bool IsInvalid => LsnInvalid(this); /// Determines if this is equal to the smallest possible LSN, which is CLFS_LSN_NULL. /// if plsn is equal to CLFS_LSN_NULL; otherwise, . public bool IsNull => LsnNull(this); /// Implements the operator ==. /// The left. /// The right. /// The result of the operator. public static bool operator ==(CLS_LSN left, CLS_LSN right) => left.Equals(right); /// Implements the operator !=. /// The left. /// The right. /// The result of the operator. public static bool operator !=(CLS_LSN left, CLS_LSN right) => !(left==right); /// Implements the operator >. /// The left. /// The right. /// The result of the operator. public static bool operator >(CLS_LSN left, CLS_LSN right) => LsnGreater(left, right); /// Implements the operator <. /// The left. /// The right. /// The result of the operator. public static bool operator <(CLS_LSN left, CLS_LSN right) => LsnLess(left, right); /// Implements the operator op_Increment. /// The value. /// The result of the operator. public static CLS_LSN operator ++(CLS_LSN value) => LsnIncrement(value); /// Implements the operator op_Decrement. /// The value. /// The result of the operator. public static CLS_LSN operator --(CLS_LSN value) => LsnDecrement(value); /// public int CompareTo(CLS_LSN other) => LsnLess(this, other) ? -1 : (LsnEqual(this, other) ? 0 : 1); /// public override bool Equals(object obj) => obj is CLS_LSN lSN && Equals(lSN); /// public bool Equals(CLS_LSN other) => LsnEqual(this, other); /// public override int GetHashCode() => 158955808+Internal.GetHashCode(); /// public override string ToString() => $"{{{Internal}}}"; /// Represents an invalid LSN. public static readonly CLS_LSN CLFS_LSN_INVALID = new() { Internal = 0xFFFFFFFF00000000UL }; /// Represents a NULL LSN. public static readonly CLS_LSN CLFS_LSN_NULL = default; } /// /// Contains information about the containers that are being scanned by ScanLogContainers, the kind of scan that is being performed, and /// a cursor to track which containers have been scanned. /// /// /// This structure is allocated by the client, initialized using CreateLogContainerScanContext, and then passed to ScanLogContainers in /// repeated calls. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_scan_context-r1 typedef struct _CLS_SCAN_CONTEXT { CLFS_NODE_ID // cidNode; HANDLE hLog; ULONG cIndex; ULONG cContainers; ULONG cContainersReturned; CLFS_SCAN_MODE eScanMode; PCLS_CONTAINER_INFORMATION // pinfoContainer; } CLS_SCAN_CONTEXT, *PCLS_SCAN_CONTEXT, PPCLS_SCAN_CONTEXT; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_SCAN_CONTEXT~r1")] [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode)] public struct CLS_SCAN_CONTEXT { /// The ID of the current node. For more information, see CLFS_NODE_ID. [FieldOffset(0)] public CLFS_NODE_ID cidNode; /// A handle to the log being scanned that is obtained from CreateLogFile with permissions to scan the log containers. [FieldOffset(8)] public HLOG hLog; /// The index of the current container. [FieldOffset(16)] public uint cIndex; /// /// The number of system-allocated CLFS_CONTAINER_INFORMATION structures in an array that is pointed to by pinfoContainer. /// /// That is, this member is the number of containers to scan with each scan call. The caller knows the scan is complete when the /// number of containers returned is less than this value. /// /// [FieldOffset(24)] public uint cContainers; /// The number of containers that are returned after a call to ScanLogContainers. [FieldOffset(32)] public uint cContainersReturned; /// /// The mode in which containers are scanned. /// Containers can be scanned in one of the following modes. /// /// /// Value /// Meaning /// /// /// CLFS_SCAN_INIT /// /// Initializes the scan context, but does not allocate associated storage. The initialization is destructive, because all data that /// is stored in the current scan context is lost. /// /// /// /// CLFS_SCAN_CLOSE /// Uninitializes the scan context and deallocates system storage that is associated with a scan context. /// /// /// CLFS_SCAN_FORWARD /// /// Causes the next call to ScanLogContainers to proceed in a forward direction. Cannot be used if CLFS_SCAN_BACKWARD is specified. /// /// /// /// CLFS_SCAN_BACKWARD /// /// Causes the next call to ScanLogContainers to proceed in a backward direction. Cannot be used if CLFS_SCAN_FORWARD is specified. /// /// /// /// [FieldOffset(40)] public CLFS_SCAN_MODE eScanMode; [FieldOffset(48)] private IntPtr _pinfoContainer; /// /// A pointer to a client-allocated array of CLFS_CONTAINER_INFORMATION structures to be filled by ScanLogContainers after each /// successful call. /// public CLS_CONTAINER_INFORMATION[] pinfoContainer => _pinfoContainer.ToArray((int)cContainersReturned); } /// /// Contains a user buffer, which is to become part of a log record, and its length. The ReserveAndAppendLog function uses /// CLFS_WRITE_ENTRY structures in the routine that appends log records to logs. This routine requires the client to specify a set /// of structures. ReserveAndAppendLog gathers these structures and formats them into a log record in a marshaling buffer, which /// is eventually flushed to the log. /// // https://docs.microsoft.com/en-us/windows/win32/api/clfs/ns-clfs-cls_write_entry typedef struct _CLS_WRITE_ENTRY { PVOID Buffer; ULONG // ByteLength; } CLS_WRITE_ENTRY, *PCLS_WRITE_ENTRY, PPCLS_WRITE_ENTRY; [PInvokeData("clfs.h", MSDNShortId = "NS:clfs._CLS_WRITE_ENTRY")] [StructLayout(LayoutKind.Sequential)] public struct CLS_WRITE_ENTRY { /// The log record data buffer. public IntPtr Buffer; /// The length of the log record data buffer, in bytes. public uint ByteLength; } }