using System; using System.IO; using System.Runtime.InteropServices; using System.Text; namespace Vanara.PInvoke { /// Functions and structures from Lz32.dll public static partial class Lz32 { private const string Lib_Lz32 = "lz32.dll"; /// Style flags for . [PInvokeData("WinBase.h", MSDNShortId = "aa365430")] [Flags] public enum LZ_OF : ushort { /// /// Ignored. /// To produce a dialog box containing a Cancel button, use OF_PROMPT. /// OF_CANCEL = 0x00000800, /// /// Creates a new file. /// If the file exists, it is truncated to zero (0) length. /// OF_CREATE = 0x00001000, /// Deletes a file. OF_DELETE = 0x00000200, /// /// Opens a file and then closes it. /// Use this to test for the existence of a file. /// OF_EXIST = 0x00004000, /// Fills the OFSTRUCT structure, but does not do anything else. OF_PARSE = 0x00000100, /// /// Displays a dialog box if a requested file does not exist. /// /// A dialog box informs a user that the system cannot find a file, and it contains Retry and Cancel buttons. The Cancel button /// directs OpenFile to return a file-not-found error message. /// /// OF_PROMPT = 0x00002000, /// Opens a file for reading only. OF_READ = 0x00000000, /// Opens a file with read/write permissions. OF_READWRITE = 0x00000002, /// Opens a file by using information in the reopen buffer. OF_REOPEN = 0x00008000, /// /// For MS-DOS–based file systems, opens a file with compatibility mode, allows any process on a specified computer to open the /// file any number of times. /// /// Other efforts to open a file with other sharing modes fail. This flag is mapped to the FILE_SHARE_READ|FILE_SHARE_WRITE /// flags of the CreateFile function. /// /// OF_SHARE_COMPAT = 0x00000000, /// /// Opens a file without denying read or write access to other processes. /// /// On MS-DOS-based file systems, if the file has been opened in compatibility mode by any other process, the function fails. /// /// This flag is mapped to the FILE_SHARE_READ|FILE_SHARE_WRITE flags of the CreateFile function. /// OF_SHARE_DENY_NONE = 0x00000040, /// /// Opens a file and denies read access to other processes. /// /// On MS-DOS-based file systems, if the file has been opened in compatibility mode, or for read access by any other process, /// the function fails. /// /// This flag is mapped to the FILE_SHARE_WRITE flag of the CreateFile function. /// OF_SHARE_DENY_READ = 0x00000030, /// /// Opens a file and denies write access to other processes. /// /// On MS-DOS-based file systems, if a file has been opened in compatibility mode, or for write access by any other process, the /// function fails. /// /// This flag is mapped to the FILE_SHARE_READ flag of the CreateFile function. /// OF_SHARE_DENY_WRITE = 0x00000020, /// /// Opens a file with exclusive mode, and denies both read/write access to other processes. If a file has been opened in any /// other mode for read/write access, even by the current process, the function fails. /// OF_SHARE_EXCLUSIVE = 0x00000010, /// /// Verifies that the date and time of a file are the same as when it was opened previously. /// This is useful as an extra check for read-only files. /// OF_VERIFY = 0x00000400, /// Opens a file for write access only. OF_WRITE = 0x00000001, } /// Return values for LZ functions. [PInvokeData("lzexpand.h")] public enum LZERROR : int { /// The handle identifying the source file is not valid. The file cannot be read. LZERROR_BADINHANDLE = -1, /// The handle identifying the destination file is not valid. The file cannot be written. LZERROR_BADOUTHANDLE = -2, /// The source file format is not valid. LZERROR_READ = -3, /// There is insufficient space for the output file. LZERROR_WRITE = -4, /// The maximum number of open compressed files has been exceeded or local memory cannot be allocated. LZERROR_GLOBALLOC = -5, /// The LZ file handle cannot be locked down. LZERROR_GLOBLOCK = -6, /// One of the input parameters is not valid. LZERROR_BADVALUE = -7, /// The file is compressed with an unrecognized compression algorithm. LZERROR_UNKNOWNALG = -8, } /// Retrieves the original name of a compressed file, if the file was compressed by the Lempel-Ziv algorithm. /// The name of the compressed file. /// A pointer to a buffer that receives the original name of the compressed file. /// /// If the function succeeds, the return value is 1. /// /// If the function fails, the return value is LZERROR_BADVALUE. There is no extended error information for this function; do not /// call GetLastError. /// /// /// NoteGetExpandedName calls neither SetLastError nor SetLastErrorEx; thus, its failure does not affect a thread's /// last-error code. /// /// /// /// /// The contents of the buffer pointed to by the lpszBuffer parameter is the original file name if the file was compressed by using /// the /r option. If the /r option was not used, this function duplicates the name in the lpszSource parameter into /// the lpszBuffer buffer. /// /// In Windows 8 and Windows Server 2012, this function is supported by the following technologies. /// /// /// Technology /// Supported /// /// /// Server Message Block (SMB) 3.0 protocol /// Yes /// /// /// SMB 3.0 Transparent Failover (TFO) /// Yes /// /// /// SMB 3.0 with Scale-out File Shares (SO) /// Yes /// /// /// Cluster Shared Volume File System (CsvFS) /// Yes /// /// /// Resilient File System (ReFS) /// Yes /// /// /// /// Note /// /// The lzexpand.h header defines GetExpandedName as an alias which automatically selects the ANSI or Unicode version of this /// function based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that /// not encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions /// for Function Prototypes. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/lzexpand/nf-lzexpand-getexpandednamea INT GetExpandedNameA( LPSTR lpszSource, // LPSTR lpszBuffer ); [DllImport(Lib_Lz32, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("lzexpand.h", MSDNShortId = "NF:lzexpand.GetExpandedNameA")] public static extern int GetExpandedName([In, MarshalAs(UnmanagedType.LPTStr)] string lpszSource, [Out, MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszBuffer); /// Closes a file that was opened by using the LZOpenFile function. /// A handle to the file to be closed. /// None /// /// /// The handle identifying the file must be retrieved by calling the LZOpenFile function. If the handle is retrieved by calling the /// CreateFile or OpenFile function, an error occurs. /// /// /// If the file has been compressed by the Lempel-Ziv algorithm and opened by using LZOpenFile, LZClose frees any global heap /// space that was allocated to expand the file. /// /// In Windows 8 and Windows Server 2012, this function is supported by the following technologies. /// /// /// Technology /// Supported /// /// /// Server Message Block (SMB) 3.0 protocol /// Yes /// /// /// SMB 3.0 Transparent Failover (TFO) /// Yes /// /// /// SMB 3.0 with Scale-out File Shares (SO) /// Yes /// /// /// Cluster Shared Volume File System (CsvFS) /// Yes /// /// /// Resilient File System (ReFS) /// Yes /// /// /// CsvFs will do redirected IO for compressed files. /// // https://docs.microsoft.com/en-us/windows/win32/api/lzexpand/nf-lzexpand-lzclose void LZClose( INT hFile ); [DllImport(Lib_Lz32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lzexpand.h", MSDNShortId = "NF:lzexpand.LZClose")] public static extern void LZClose(HLZFILE hFile); /// /// Copies a source file to a destination file. If the source file has been compressed by the Lempel-Ziv algorithm, this function /// creates a decompressed destination file. If the source file is not compressed, this function duplicates the original file. /// /// A handle to the source file. /// A handle to the destination file. /// /// If the function succeeds, the return value specifies the size, in bytes, of the destination file. /// /// If the function fails, the return value is an LZERROR_* code. These codes have values less than zero. Note that LZCopy /// calls neither SetLastError nor SetLastErrorEx; thus, its failure does not affect a thread's last-error code. /// /// The following is a list of error codes that LZCopy can return upon failure. /// /// /// Return code /// Description /// /// /// LZERROR_BADINHANDLE /// The handle identifying the source file is not valid. The file cannot be read. /// /// /// LZERROR_BADOUTHANDLE /// The handle identifying the destination file is not valid. The file cannot be written. /// /// /// LZERROR_GLOBALLOC /// The maximum number of open compressed files has been exceeded or local memory cannot be allocated. /// /// /// LZERROR_GLOBLOCK /// The LZ file handle cannot be locked down. /// /// /// LZERROR_READ /// The source file format is not valid. /// /// /// There is no extended error information for this function; do not call GetLastError. /// /// /// The handles identifying the source and destination files must be retrieved by calling the LZInit or LZOpenFile function. /// If the function succeeds, the file identified by the hfDest parameter is always uncompressed. /// In Windows 8 and Windows Server 2012, this function is supported by the following technologies. /// /// /// Technology /// Supported /// /// /// Server Message Block (SMB) 3.0 protocol /// Yes /// /// /// SMB 3.0 Transparent Failover (TFO) /// Yes /// /// /// SMB 3.0 with Scale-out File Shares (SO) /// Yes /// /// /// Cluster Shared Volume File System (CsvFS) /// Yes /// /// /// Resilient File System (ReFS) /// Yes /// /// /// CsvFs will do redirected IO for compressed files. /// // https://docs.microsoft.com/en-us/windows/win32/api/lzexpand/nf-lzexpand-lzcopy LONG LZCopy( INT hfSource, INT hfDest ); [DllImport(Lib_Lz32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lzexpand.h", MSDNShortId = "NF:lzexpand.LZCopy")] public static extern int LZCopy(HLZFILE hfSource, HLZFILE hfDest); /// /// Allocates memory for the internal data structures required to decompress files, and then creates and initializes them. /// /// A handle to the file. /// /// If the function succeeds, the return value is a new LZ file handle. /// /// If the function fails, the return value is an LZERROR_* code. These codes have values less than zero. Note that LZInit /// calls neither SetLastError nor SetLastErrorEx; thus, its failure does not affect a thread's last-error code. /// /// The following is the list of the error codes that LZInit can return upon failure. /// /// /// Return code /// Description /// /// /// LZERROR_BADINHANDLE /// The handle identifying the source file is not valid. The file cannot be read. /// /// /// LZERROR_GLOBALLOC /// The maximum number of open compressed files has been exceeded or local memory cannot be allocated. /// /// /// LZERROR_GLOBLOCK /// The LZ file handle cannot be locked down. /// /// /// LZERROR_UNKNOWNALG /// The file is compressed with an unrecognized compression algorithm. /// /// /// There is no extended error information for this function; do not call GetLastError. /// /// /// /// A maximum of 16 compressed files can be open at any given time. Similarly, a maximum of 16 uncompressed files can be open at any /// given time. An application should be careful to close the handle returned by LZInit when it is done using the file; /// otherwise, the application can inadvertently hit the 16-file limit. /// /// /// The handle this function returns is compatible only with the functions in Lz32.dll; it should not be used for other file operations. /// /// In Windows 8 and Windows Server 2012, this function is supported by the following technologies. /// /// /// Technology /// Supported /// /// /// Server Message Block (SMB) 3.0 protocol /// Yes /// /// /// SMB 3.0 Transparent Failover (TFO) /// Yes /// /// /// SMB 3.0 with Scale-out File Shares (SO) /// Yes /// /// /// Cluster Shared Volume File System (CsvFS) /// Yes /// /// /// Resilient File System (ReFS) /// Yes /// /// /// CsvFs will do redirected IO for compressed files. /// // https://docs.microsoft.com/en-us/windows/win32/api/lzexpand/nf-lzexpand-lzinit INT LZInit( INT hfSource ); [DllImport(Lib_Lz32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lzexpand.h", MSDNShortId = "NF:lzexpand.LZInit")] public static extern int LZInit(/*HFILE*/ int hfSource); /// Creates, opens, reopens, or deletes the specified file. /// The name of the file. /// /// /// A pointer to the OFSTRUCT structure that is to receive information about the file when the file is first opened. The structure /// can be used in subsequent calls to the LZOpenFile function to see the open file. /// /// /// The szPathName member of this structure contains characters from the original equipment manufacturer (OEM) character set. /// /// /// /// The action to be taken. This parameter can be one or more of the following values. /// /// /// Value /// Meaning /// /// /// OF_CANCEL 0x0800 /// /// Ignored. Provided only for compatibility with 16-bit Windows. Use the OF_PROMPT style to display a dialog box containing a /// Cancel button. /// /// /// /// OF_CREATE 0x1000 /// Directs LZOpenFile to create a new file. If the file already exists, it is truncated to zero length. /// /// /// OF_DELETE 0x0200 /// Deletes the file. /// /// /// OF_EXIST 0x4000 /// Opens the file and then closes it to test for a file's existence. /// /// /// OF_PARSE 0x0100 /// Fills the OFSTRUCT structure but carries out no other action. /// /// /// OF_PROMPT 0x2000 /// /// Displays a dialog box if the requested file does not exist. The dialog box informs the user that the system cannot find the /// file, and it contains Retry and Cancel buttons. Clicking the Cancel button directs LZOpenFile to return a file not found error message. /// /// /// /// OF_READ 0x0000 /// Opens the file for reading only. /// /// /// OF_READWRITE 0x0002 /// Opens the file for reading and writing. /// /// /// OF_REOPEN 0x8000 /// Opens the file using information in the reopen buffer. /// /// /// OF_SHARE_DENY_NONE 0x0040 /// /// Opens the file without denying other processes read or write access to the file. LZOpenFile fails if the file has been opened in /// compatibility mode by any other process. /// /// /// /// OF_SHARE_DENY_READ 0x0030 /// /// Opens the file and denies other processes read access to the file. LZOpenFile fails if the file has been opened in compatibility /// mode or has been opened for read access by any other process. /// /// /// /// OF_SHARE_DENY_WRITE 0x0020 /// /// Opens the file and denies other processes write access to the file. LZOpenFile fails if the file has been opened in /// compatibility mode or has been opened for write access by any other process. /// /// /// /// OF_SHARE_EXCLUSIVE 0x0010 /// /// Opens the file in exclusive mode, denying other processes both read and write access to the file. LZOpenFile fails if the file /// has been opened in any other mode for read or write access, even by the current process. /// /// /// /// OF_WRITE 0x0001 /// Opens the file for writing only. /// /// /// /// /// /// If the function succeeds and the value specified by the wStyle parameter is not OF_READ, the return value is a handle /// identifying the file. If the file is compressed and opened with wStyle set to OF_READ, the return value is a special file handle. /// /// /// If the function fails, the return value is an LZERROR_* code. These codes have values less than zero. There is no /// extended error information for this function; do not call GetLastError. /// /// /// NoteLZOpenFile calls neither SetLastError nor SetLastErrorEx; thus, its failure does not affect a thread's /// last-error code. /// /// The following is the list of the error codes that LZOpenFile can return upon failure. /// /// /// Return code/value /// Description /// /// /// LZERROR_BADINHANDLE -1 /// The handle identifying the source file is not valid. The file cannot be read. /// /// /// LZERROR_GLOBALLOC -5 /// The maximum number of open compressed files has been exceeded or local memory cannot be allocated. /// /// /// /// /// /// If the wStyle parameter is the OF_READ flag (or OF_READ and any of the OF_SHARE_* flags) and the file is /// compressed, LZOpenFile calls the LZInit function, which performs the required initialization for the decompression operations. /// /// /// The handle this function returns is compatible only with the functions in Lz32.dll; it should not be used for other file operations. /// /// /// If LZOpenFile is unable to open the file specified by lpFileName, on some versions of Windows it attempts to open a file /// with almost the same file name, except the last character is replaced with an underscore (""). Thus, if an attempt to open /// "MyProgram.exe" fails, LZOpenFile tries to open "MyProgram.ex". Installation packages often substitute the underscore for /// the last letter of a file name extension to indicate that the file is compressed. For example, "MyProgram.exe" compressed might /// be named "MyProgram.ex_". To determine the name of the file opened (if any), examine the szPathName member of the /// OFSTRUCT structure in the lpReOpenBuf parameter. /// /// In Windows 8 and Windows Server 2012, this function is supported by the following technologies. /// /// /// Technology /// Supported /// /// /// Server Message Block (SMB) 3.0 protocol /// Yes /// /// /// SMB 3.0 Transparent Failover (TFO) /// Yes /// /// /// SMB 3.0 with Scale-out File Shares (SO) /// Yes /// /// /// Cluster Shared Volume File System (CsvFS) /// Yes /// /// /// Resilient File System (ReFS) /// Yes /// /// /// CsvFs will do redirected IO for compressed files. /// /// Note /// /// The lzexpand.h header defines LZOpenFile as an alias which automatically selects the ANSI or Unicode version of this function /// based on the definition of the UNICODE preprocessor constant. Mixing usage of the encoding-neutral alias with code that not /// encoding-neutral can lead to mismatches that result in compilation or runtime errors. For more information, see Conventions for /// Function Prototypes. /// /// /// // https://docs.microsoft.com/en-us/windows/win32/api/lzexpand/nf-lzexpand-lzopenfilea INT LZOpenFileA( LPSTR lpFileName, LPOFSTRUCT // lpReOpenBuf, WORD wStyle ); [DllImport(Lib_Lz32, SetLastError = false, CharSet = CharSet.Auto)] [PInvokeData("lzexpand.h", MSDNShortId = "NF:lzexpand.LZOpenFileA")] public static extern int LZOpenFile([In, MarshalAs(UnmanagedType.LPTStr)] string lpFileName, ref OFSTRUCT lpReOpenBuf, LZ_OF wStyle); /// Reads (at most) the specified number of bytes from a file and copies them into a buffer. /// A handle to the file. /// /// A pointer to a buffer that receives the bytes read from the file. Ensure that this buffer is larger than cbRead. /// /// The count of bytes to be read. /// /// If the function succeeds, the return value specifies the number of bytes read. /// /// If the function fails, the return value is an LZERROR_* code. These codes have values less than zero. Note that LZRead /// calls neither SetLastError nor SetLastErrorEx; thus, its failure does not affect a thread's last-error code. /// /// The following is the list of error codes that LZRead can return upon failure. /// /// /// Return code /// Description /// /// /// LZERROR_BADINHANDLE /// The handle identifying the source file is not valid. The file cannot be read. /// /// /// LZERROR_BADOUTHANDLE /// The handle identifying the destination file is not valid. The file cannot be written. /// /// /// LZERROR_BADVALUE /// One of the input parameters is not valid. /// /// /// LZERROR_GLOBALLOC /// The maximum number of open compressed files has been exceeded or local memory cannot be allocated. /// /// /// LZERROR_GLOBLOCK /// The LZ file handle cannot be locked down. /// /// /// LZERROR_READ /// The source file format is not valid. /// /// /// LZERROR_WRITE /// There is insufficient space for the output file. /// /// /// There is no extended error information for this function; do not call GetLastError. /// /// /// The handle identifying the file must be retrieved by calling either the LZInit or LZOpenFile function. /// /// If the file is compressed, LZRead operates on an expanded image of the file and copies the bytes of data into the /// specified buffer. /// /// In Windows 8 and Windows Server 2012, this function is supported by the following technologies. /// /// /// Technology /// Supported /// /// /// Server Message Block (SMB) 3.0 protocol /// Yes /// /// /// SMB 3.0 Transparent Failover (TFO) /// Yes /// /// /// SMB 3.0 with Scale-out File Shares (SO) /// Yes /// /// /// Cluster Shared Volume File System (CsvFS) /// Yes /// /// /// Resilient File System (ReFS) /// Yes /// /// /// CsvFs will do redirected IO for compressed files. /// // https://docs.microsoft.com/en-us/windows/win32/api/lzexpand/nf-lzexpand-lzread INT LZRead( INT hFile, CHAR *lpBuffer, INT cbRead ); [DllImport(Lib_Lz32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lzexpand.h", MSDNShortId = "NF:lzexpand.LZRead")] public static extern int LZRead(HLZFILE hFile, [Out] IntPtr lpBuffer, int cbRead); /// Moves a file pointer the specified number of bytes from a starting position. /// A handle to the file. /// The number of bytes by which to move the file pointer. /// /// The starting position of the pointer. This parameter must be one of the following values. /// /// /// Value /// Meaning /// /// /// 0 /// Moves the file pointer lOffset bytes from the beginning of the file. /// /// /// 1 /// Moves the file pointer lOffset bytes from the current position. /// /// /// 2 /// Moves the file pointer lOffset bytes from the end of the file. /// /// /// /// /// If the function succeeds, the return value specifies the offset from the beginning of the file to the new pointer position. /// /// If the function fails, the return value is an LZERROR_* code. These codes have values less than zero. Note that LZSeek /// calls neither SetLastError nor SetLastErrorEx; thus, its failure does not affect a thread's last-error code. /// /// The following is the list of error codes that LZSeek can return upon failure. /// /// /// Return code /// Description /// /// /// LZERROR_BADINHANDLE /// The handle identifying the source file is not valid. The file cannot be read. /// /// /// LZERROR_BADVALUE /// One of the parameters is outside the range of acceptable values. /// /// /// LZERROR_GLOBLOCK /// The LZ file handle cannot be locked down. /// /// /// There is no extended error information for this function; do not call GetLastError. /// /// /// The handle identified by the hFile parameter must be retrieved by calling either the LZInit or LZOpenFile function. /// In Windows 8 and Windows Server 2012, this function is supported by the following technologies. /// /// /// Technology /// Supported /// /// /// Server Message Block (SMB) 3.0 protocol /// Yes /// /// /// SMB 3.0 Transparent Failover (TFO) /// Yes /// /// /// SMB 3.0 with Scale-out File Shares (SO) /// Yes /// /// /// Cluster Shared Volume File System (CsvFS) /// Yes /// /// /// Resilient File System (ReFS) /// Yes /// /// /// CsvFs will do redirected IO for compressed files. /// // https://docs.microsoft.com/en-us/windows/win32/api/lzexpand/nf-lzexpand-lzseek LONG LZSeek( INT hFile, LONG lOffset, INT iOrigin ); [DllImport(Lib_Lz32, SetLastError = false, ExactSpelling = true)] [PInvokeData("lzexpand.h", MSDNShortId = "NF:lzexpand.LZSeek")] public static extern int LZSeek(HLZFILE hFile, int lOffset, SeekOrigin iOrigin); /// Provides a handle to a compressed file. [StructLayout(LayoutKind.Sequential)] public struct HLZFILE : IHandle { private readonly int handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HLZFILE(int preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with 0. public static HLZFILE NULL => new(0); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == 0; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator int(HLZFILE h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HLZFILE(int h) => new(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HLZFILE h1, HLZFILE h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HLZFILE h1, HLZFILE h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HLZFILE h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => (IntPtr)handle; } } }