using System; using System.IO; using System.Runtime.InteropServices; using System.Text; namespace Vanara.PInvoke { /// Items from the cabinet.dll public static partial class Cabinet { /// public const int CB_MAX_CAB_PATH = 256; /// public const int CB_MAX_CABINET_NAME = 256; /// public const int CB_MAX_CHUNK = 32768; /// public const int CB_MAX_DISK = 0x7fffffff; /// public const int CB_MAX_DISK_NAME = 256; /// public const int CB_MAX_FILENAME = 256; /// [PInvokeData("fci.h")] public const int tcompSHIFT_LZX_WINDOW = 8; /// [PInvokeData("fci.h")] public const int tcompSHIFT_QUANTUM_LEVEL = 4; /// [PInvokeData("fci.h")] public const int tcompSHIFT_QUANTUM_MEM = 8; /// /// The FNFCIALLOC provides the declaration for the application-defined callback function to allocate memory within an FCI context. /// /// Bytes to be allocated from the stack. /// pointer to the allocated space /// /// The function accepts parameters similar to malloc. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcialloc [PInvokeData("fci.h", MSDNShortId = "339ac9d2-60bc-4a90-8a46-6fbb073be9d1")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate IntPtr PFNALLOC(uint cb); /// /// The FNFCICLOSE macro provides the declaration for the application-defined callback function to close a file in an FCI context. /// /// The file handle. /// The error. /// An application-defined value. /// Returns 0 if the file was successfully closed. A return value of –1 indicates an error. /// The function accepts parameters similar to _close, with the addition of err and pv. // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfciclose [PInvokeData("fci.h", MSDNShortId = "c4edf6ca-0b16-4e30-933b-934f8930c6d6")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int PFNFCICLOSE(IntPtr hf, out int err, IntPtr pv); /// /// The FNFCIDELETE macro provides the declaration for the application-defined callback function to delete a file in the FCI context. /// /// The name of the file to be deleted. /// The error. /// An application-defined value. /// Returns 0 if the file was successfully deleted. A return value of –1 indicates an error. /// The function accepts parameters similar to remove, with the addition of err and pv. // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcidelete [PInvokeData("fci.h", MSDNShortId = "5c85ad86-2794-4f7c-8c10-18fea3519b11")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int PFNFCIDELETE(string pszFile, out int err, IntPtr pv); /// /// The FNFCIFILEPLACED macro provides the declaration for the application-defined callback function to notify when a file is /// placed in the cabinet. /// /// Pointer to the CCAB structure containing the parameters of the cabinet on which the file has been stored. /// The name of the file to be replaced. /// The length of the file. /// true if this is a later segment of a continued file /// An application-defined value. /// Returns 0 if the file was successfully replaced. A return value of –1 indicates an error. // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcifileplaced [PInvokeData("fci.h", MSDNShortId = "f8a1bcfc-8a13-49cf-a3e7-caec6c6421b0")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int PFNFCIFILEPLACED(ref CCAB pccab, string pszFile, int cbFile, [MarshalAs(UnmanagedType.Bool)] bool fContinuation, IntPtr pv); /// /// The FNFCIGETNEXTCABINET macro provides the declaration for the application-defined callback function to request /// information for the next cabinet. /// /// Points to copy of old ccab structure to modify. /// Estimate of size of previous cabinet. /// An application-defined value. /// on success. /// /// /// The CCAB structure referenced by this function is relevant to the most recently completed cabinet. However, with each successful /// operation the iCab field contained within this structure will have incremented by 1. Additionally, the next cabinet will be /// created using the fields in this structure. The szCab, in particular, should be modified as necessary. In particular, the szCab /// field, which specifies the cabinet name, should be changed for each cabinet. /// /// When creating multiple cabinets, typically the iCab field is used to create the name. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcigetnextcabinet [PInvokeData("fci.h", MSDNShortId = "d56fb63e-91bf-4991-a954-176211697a2e")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [return: MarshalAs(UnmanagedType.Bool)] public delegate bool PFNFCIGETNEXTCABINET(ref CCAB pccab, uint cbPrevCab, IntPtr pv); /// /// The FNFCIGETOPENINFO macro provides the declaration for the application-defined callback function to open a file and /// retrieve file date, time, and attribute. /// /// complete path to filename. /// location to return FAT-style date code. /// location to return FAT-style time code. /// location to return FAT-style attributes. /// The error. /// An application-defined value. /// Return value is file handle of open file to read, or INVALID_FILE_HANDLE on failure. /// The function should open the file using the file open function compatible with those passed into FCICreate. // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcigetopeninfo [PInvokeData("fci.h", MSDNShortId = "5baccb69-7872-4d67-ad74-70cdd7459f8d")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate IntPtr PFNFCIGETOPENINFO(string pszName, ref ushort pdate, ref ushort ptime, ref ushort pattribs, out int err, IntPtr pv); /// /// The FNFCIGETTEMPFILE macro provides the declaration for the application-defined callback function to obtain a temporary /// file name. /// /// Buffer to receive complete tempfile name. /// Size of pszTempName buffer. /// An application-defined value. /// on success. /// /// The function can return a filename that already exists by the time it is opened. For this reason, the caller should be prepared /// to make several attempts to create temporary files. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcigettempfile [PInvokeData("fci.h", MSDNShortId = "8978f688-d8f1-437a-b298-eed1e7dac012")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [return: MarshalAs(UnmanagedType.Bool)] public delegate bool PFNFCIGETTEMPFILE(IntPtr pszTempName, int cbTempName, IntPtr pv); /// /// The FNFCIOPEN macro provides the declaration for the application-defined callback function to open a file in an FCI context. /// /// File name. /// The kind of operations allowed. /// Permission mode. /// The error. /// An application-defined value. /// Return value is file handle of open file to read, or INVALID_FILE_HANDLE on failure. /// The function accepts parameters similar to _open. // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfciopen [PInvokeData("fci.h", MSDNShortId = "72cf50cb-c895-4953-9c4d-f8ddaa294f2a")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate IntPtr PFNFCIOPEN(string pszFile, RunTimeLib.FileOpConstant oflag, RunTimeLib.FilePermissionConstant pmode, out int err, IntPtr pv); /// /// The FNFCIREAD macro provides the declaration for the application-defined callback function to read data from a file in an /// FCI context. /// /// File descriptor referring to the open file. /// Storage location for data. /// Maximum number of bytes to read. /// The error. /// An application-defined value. /// returns the number of bytes read /// /// The function accepts parameters similar to _read with the addition to err and pv. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfciread [PInvokeData("fci.h", MSDNShortId = "dd4e97ff-efbc-462b-b954-bc3260fa1513")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate uint PFNFCIREAD(IntPtr hf, [Out] IntPtr memory, uint cb, out int err, IntPtr pv); /// /// The FNFCISEEK macro provides the declaration for the application-defined callback function to move a file pointer to the /// specified location in an FCI context. /// /// File descriptor referring to an open file. /// Number of bytes from origin. /// Initial position.. /// The error. /// An application-defined value. /// returns the offset, in bytes, of the new position from the beginning of the file. /// /// The function accepts parameters similar to _lseek with the addition to err and pv. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfciseek [PInvokeData("fci.h", MSDNShortId = "e5a14c98-4de6-452e-8993-afb7964aeee7")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int PFNFCISEEK(IntPtr hf, int dist, System.IO.SeekOrigin seektype, out int err, IntPtr pv); /// /// The FNFCISTATUS macro provides the declaration for the application-defined callback function to update the user. /// /// The type status. /// /// File: Size of compressed block. Folder: Amount of folder copied to cabinet so far. Cabinet: Estimated cabinet size that was /// previously passed to fnfciGetNextCabinet(). /// /// File: Size of uncompressed block. Folder: Total size of folder. Cabinet: Actual cabinet size. /// An application-defined value. /// Returns -1 to signal that FCI should abort; Returns anything other than -1 on success. /// /// If typeStatus equals statusCabinet the returned value indicates the desired size for the cabinet file. FCI updates the /// maximum cabinet size remaining using this returned value. This allows a client to generate multiple cabinets per disk, and have /// FCI limit the size accordingly. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcistatus [PInvokeData("fci.h", MSDNShortId = "529fd3c8-9783-4dbe-9268-a9137935cf9b")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate int PFNFCISTATUS(CabinetFileStatus typeStatus, uint cb1, uint cb2, IntPtr pv); /// /// The FNFCIWRITE macro provides the declaration for the application-defined callback function to write data to a file in an /// FCI context. /// /// File descriptor of file into which data is written. /// Data to be written. /// Number of bytes. /// The error. /// An application-defined value. /// returns the number of bytes actually written. /// The function accepts parameters similar to _write. // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfciwrite [PInvokeData("fci.h", MSDNShortId = "ca4c3b5b-1ed5-4f12-8317-c1e1dac5f816")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate uint PFNFCIWRITE(IntPtr hf, [In] IntPtr memory, uint cb, out int err, IntPtr pv); /// /// The FNFCIFREE macro provides the declaration for the application-defined callback function to free previously allocated /// memory in an FCI context. /// /// The pointer to the memory to be freed. /// /// The function accepts parameters similar to free. /// Examples /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fnfcifree [PInvokeData("fci.h", MSDNShortId = "48f052e2-7786-430a-b3dc-afcfdffae387")] [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public delegate void PFNFREE(IntPtr memory); /// Used by . [PInvokeData("fci.h")] public enum CabinetFileStatus { /// compressing a block into a folder File, /// adding a folder to a cabinet Folder, /// writing out a complete cabinet Cabinet } /// An FCI/FDI error code. [PInvokeData("fci.h")] public enum FCIERROR { /// No Error. FCIERR_NONE = 0x00, /// Failure opening the file to be stored in the cabinet. FCIERR_OPEN_SRC = 0x01, /// Failure reading the file to be stored in the cabinet. FCIERR_READ_SRC = 0x02, /// Out of memory in FCI. FCIERR_ALLOC_FAIL = 0x03, /// Could not create a temporary file. FCIERR_TEMP_FILE = 0x04, /// Unknown compression type. FCIERR_BAD_COMPR_TYPE = 0x05, /// Could not create the cabinet file. FCIERR_CAB_FILE = 0x06, /// FCI aborted. FCIERR_USER_ABORT = 0x07, /// Failure compressing data. FCIERR_MCI_FAIL = 0x08, /// Data-size or file-count exceeded CAB format limits. FCIERR_CAB_FORMAT_LIMIT = 0x09, } /// The compression type to use. [PInvokeData("fci.h")] [Flags] public enum TCOMP { /// tcompMASK_TYPE = 0x000F, /// No compression. tcompTYPE_NONE = 0x0000, /// Microsoft ZIP compression. tcompTYPE_MSZIP = 0x0001, /// tcompTYPE_QUANTUM = 0x0002, /// tcompTYPE_LZX = 0x0003, /// tcompBAD = 0x000F, /// tcompMASK_LZX_WINDOW = 0x1F00, /// tcompLZX_WINDOW_LO = 0x0F00, /// tcompLZX_WINDOW_HI = 0x1500, /// tcompMASK_QUANTUM_LEVEL = 0x00F0, /// tcompQUANTUM_LEVEL_LO = 0x0010, /// tcompQUANTUM_LEVEL_HI = 0x0070, /// tcompMASK_QUANTUM_MEM = 0x1F00, /// tcompQUANTUM_MEM_LO = 0x0A00, /// tcompQUANTUM_MEM_HI = 0x1500, /// tcompMASK_RESERVED = 0xE000, } /// The FCIAddFile adds a file to the cabinet under construction. /// A valid FCI context handle returned by the FCICreate function. /// The name of the file to add; this value should include path information. /// The name under which to store the file in the cabinet. /// If set TRUE, the file will be executed when extracted. /// /// Pointer to an application-defined callback function to obtain specifications on the next cabinet to create. The function should /// be declared using the FNFCIGETNEXTCABINET macro. /// /// /// Pointer to an application-defined callback function to update the progress information available to the user. The function /// should be declared using the FNFCISTATUS macro. /// /// /// Pointer to an application-defined callback function to open a file and retrieve the file date, time, and attributes. The /// function should be declared using the FNFCIGETOPENINFO macro. /// /// /// The compression type to use. /// Note To indicate LZX compression, use the TCOMPfromLZXWindow macro. /// /// /// Value /// Meaning /// /// /// tcompTYPE_NONE 0x0000 /// No compression. /// /// /// tcompTYPE_MSZIP 0x0001 /// Microsoft ZIP compression. /// /// /// /// /// If the function succeeds, it returns TRUE; otherwise, FALSE. /// Extended error information is provided in the ERF structure used to create the FCI context. /// /// /// When set, the _A_EXEC attribute is added to the file entry in the CAB. This mechanism is used in some Microsoft self-extracting /// executables, and could be used for this purpose in any custom extraction application. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fciaddfile BOOL DIAMONDAPI FCIAddFile( HFCI hfci, LPSTR // pszSourceFile, LPSTR pszFileName, BOOL fExecute, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis, PFNFCIGETOPENINFO // pfnfcigoi, TCOMP typeCompress ); [DllImport(Lib.Cabinet, SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [PInvokeData("fci.h", MSDNShortId = "f99e8718-853b-4d35-98ae-61a8333dbaba")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FCIAddFile([In] HFCI hfci, string pszSourceFile, string pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fExecute, [In] PFNFCIGETNEXTCABINET pfnfcignc, [In] PFNFCISTATUS pfnfcis, [In] PFNFCIGETOPENINFO pfnfcigoi, TCOMP typeCompress); /// The FCICreate function creates an FCI context. /// Pointer to an ERF structure that receives the error information. /// /// Pointer to an application-defined callback function to notify when a file is placed in the cabinet. The function should be /// declared using the FNFCIFILEPLACED macro. /// /// /// Pointer to an application-defined callback function to allocate memory. The function should be declared using the FNFCIALLOC macro. /// /// /// Pointer to an application-defined callback function to free previously allocated memory. The function should be delcared using /// the FNFCIFREE macro. /// /// /// Pointer to an application-defined callback function to open a file. The function should be declared using the FNFCIOPEN macro. /// /// /// Pointer to an application-defined callback function to read data from a file. The function should be declared using the /// FNFCIREAD macro. /// /// /// Pointer to an application-defined callback function to write data to a file. The function should be declared using the /// FNFCIWRITE macro. /// /// /// Pointer to an application-defined callback function to close a file. The function should be declared using the FNFCICLOSE macro. /// /// /// Pointer to an application-defined callback function to move a file pointer to the specific location. The function should be /// declared using the FNFCISEEK macro. /// /// /// Pointer to an application-defined callback function to delete a file. The function should be declared using the FNFCIDELETE macro. /// /// /// Pointer to an application-defined callback function to retrieve a temporary file name. The function should be declared using the /// FNFCIGETTEMPFILE macro. /// /// Pointer to a CCAB structure that contains the parameters for creating a cabinet. /// Pointer to an application-defined value that is passed to callback functions. /// /// If the function succeeds, it returns a non- NULL HFCI context pointer; otherwise, NULL. /// Extended error information is provided in the ERF structure. /// /// /// FCI supports multiple simultaneous contexts. As a result it is possible to create or extract multiple cabinets at the same time /// within the same application. If the application is multithreaded, it is also possible to run a different context in each thread; /// however, an application cannot use the same context simultaneously in multiple threads. For example, FCIAddFile cannot be called /// from two different threads, using the same FCI context. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fcicreate HFCI DIAMONDAPI FCICreate( PERF perf, PFNFCIFILEPLACED // pfnfcifp, PFNFCIALLOC pfna, PFNFCIFREE pfnf, PFNFCIOPEN pfnopen, PFNFCIREAD pfnread, PFNFCIWRITE pfnwrite, PFNFCICLOSE pfnclose, // PFNFCISEEK pfnseek, PFNFCIDELETE pfndelete, PFNFCIGETTEMPFILE pfnfcigtf, PCCAB pccab, void *pv ); [DllImport(Lib.Cabinet, SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [PInvokeData("fci.h", MSDNShortId = "bfcea06d-2f09-405c-955c-0f56149148f2")] public static extern SafeHFCI FCICreate(ref ERF perf, [In] PFNFCIFILEPLACED pfnfcifp, [In] PFNALLOC pfna, [In] PFNFREE pfnf, [In] PFNFCIOPEN pfnopen, [In] PFNFCIREAD pfnread, [In] PFNFCIWRITE pfnwrite, [In] PFNFCICLOSE pfnclose, [In] PFNFCISEEK pfnseek, [In] PFNFCIDELETE pfndelete, [In] PFNFCIGETTEMPFILE pfnfcigtf, in CCAB pccab, [In, Optional] IntPtr pv); /// /// The FCIDestroy function deletes an open FCI context, freeing any memory and temporary files associated with the context. /// /// A valid FCI context handle returned by the FCICreate function. /// /// If the function succeeds, it returns TRUE; otherwise, FALSE. /// Extended error information is provided in the ERF structure used to create the FCI context. /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fcidestroy BOOL DIAMONDAPI FCIDestroy( HFCI hfci ); [DllImport(Lib.Cabinet, SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [PInvokeData("fci.h", MSDNShortId = "bb1a6294-664f-450f-b8ec-d6f8957d920e")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FCIDestroy([In] HFCI hfci); /// The FCIFlushCabinet function completes the current cabinet. /// A valid FCI context handle returned by theFCICreate function. /// Specifies whether the function pointed to by the supplied GetNextCab parameter will be called. /// /// Pointer to an application-defined callback function to obtain specifications on the next cabinet to create. The function should /// be declared using the FNFCIGETNEXTCABINET macro. /// /// /// Pointer to an application-defined callback function to update the user. The function should be declared using the FNFCISTATUS macro. /// /// /// If the function succeeds, it returns TRUE; otherwise, FALSE. /// Extended error information is provided in the ERF structure used to create the FCI context. /// /// /// /// The FCIFlushCabinet API forces the current cabinet under construction to be completed immediately and then written to /// disk. Further calls to FCIAddFile will result in files being added to another cabinet. /// /// /// In the event the current cabinet has reached the application-specified media size limit, the pending data within an FCI's /// internal buffers will be placed into another cabinet. /// /// /// The fGetNextCab flag determines whether the function pointed to by the GetNextCab parameter will be called. If fGetNextCab is /// set TRUE, GetNextCab is called to obtain continuation information. If FALSE, then GetNextCab is called only in the /// event the cabinet overflows. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fciflushcabinet BOOL DIAMONDAPI FCIFlushCabinet( HFCI hfci, BOOL // fGetNextCab, PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis ); [DllImport(Lib.Cabinet, SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [PInvokeData("fci.h", MSDNShortId = "dc586260-180e-4a6b-accf-2ddd62ac1335")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FCIFlushCabinet([In] HFCI hfci, [MarshalAs(UnmanagedType.Bool)] bool fGetNextCab, [In] PFNFCIGETNEXTCABINET pfnfcignc, [In] PFNFCISTATUS pfnfcis); /// The FCIFlushFolder function forces the current folder under construction to be completed immediately. /// A valid FCI context handle returned by the FCICreate function. /// /// Pointer to an application-defined callback function to obtain specifications on the next cabinet to create. The function should /// be declared using the FNFCIGETNEXTCABINET macro. /// /// /// Pointer to an application-defined callback function to update the user. The function should be declared using the FNFCISTATUS macro. /// /// /// If the function succeeds, it returns TRUE; otherwise, FASLE. /// Extended error information is provided in the ERF structure used to create the FCI context. /// /// /// /// The FCIFlushFolder API forces the folder currently under construction to be completed immediately; effectively resetting /// the compression history if a compression method is in use. /// /// /// The callback function indicated by GetNextCab will be called if the cabinet overflows, which occurs if the pending data buffered /// inside an FCI causes the application-specified cabinet media size to be exceeded. /// /// // https://docs.microsoft.com/en-us/windows/desktop/api/fci/nf-fci-fciflushfolder BOOL DIAMONDAPI FCIFlushFolder( HFCI hfci, // PFNFCIGETNEXTCABINET pfnfcignc, PFNFCISTATUS pfnfcis ); [DllImport(Lib.Cabinet, SetLastError = false, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] [PInvokeData("fci.h", MSDNShortId = "dc9c226e-e309-48c3-9edb-3f0a040c0c18")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool FCIFlushFolder([In] HFCI hfci, [In] PFNFCIGETNEXTCABINET pfnfcignc, [In] PFNFCISTATUS pfnfcis); /// The CCAB structure contains cabinet information. // https://docs.microsoft.com/en-us/windows/desktop/api/fci/ns-fci-ccab typedef struct { ULONG cb; ULONG cbFolderThresh; UINT // cbReserveCFHeader; UINT cbReserveCFFolder; UINT cbReserveCFData; int iCab; int iDisk; int fFailOnIncompressible; USHORT setID; // char szDisk[CB_MAX_DISK_NAME]; char szCab[CB_MAX_CABINET_NAME]; char szCabPath[CB_MAX_CAB_PATH]; } CCAB; [PInvokeData("fci.h", MSDNShortId = "e25cb72b-4c96-40e9-9fd5-2920e4a01d3a")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct CCAB { /// The maximum size, in bytes, of a cabinet created by FCI. public uint cb; /// The maximum size, in bytes, that a folder will contain before a new folder is created. public uint cbFolderThresh; /// The size, in bytes, of the CFHeader reserve area. Possible value range is 0-255. public uint cbReserveCFHeader; /// The size, in bytes, of the CFFolder reserve area. Possible value range is 0-255. public uint cbReserveCFFolder; /// The size, in bytes, of the CFData reserve area. Possible value range is 0-255. public uint cbReserveCFData; /// The number of created cabinets. public int iCab; /// The number of disks. public int iDisk; /// TRUE if fail if a block is incompressible. [MarshalAs(UnmanagedType.Bool)] public bool fFailOnIncompressible; /// A value that represents the association between a collection of linked cabinet files. public ushort setID; /// The name of the disk on which the cabinet is placed. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CB_MAX_DISK_NAME)] public string szDisk; /// /// The name of the cabinet. /// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CB_MAX_CABINET_NAME)] public string szCab; /// /// The full path that indicates where to create the cabinet. /// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CB_MAX_CAB_PATH)] public string szCabPath; /// Initializes a new instance of the struct. /// The full path to the cabinet to create. /// A value that represents the association between a collection of linked cabinet files. /// The number of disks. /// The maximum size, in bytes, of a cabinet created by FCI. public CCAB(string cabFullPath, ushort setId = 1, int disk = 1, uint maxSize = CB_MAX_DISK) { cb = cbFolderThresh = maxSize; setID = setId; iDisk = disk; cbReserveCFData = cbReserveCFFolder = cbReserveCFHeader = 0; iCab = 0; fFailOnIncompressible = false; szDisk = string.Empty; szCab = Path.GetFileName(cabFullPath); szCabPath = Path.GetDirectoryName(cabFullPath); if (szCabPath[szCabPath.Length - 1] != Path.DirectorySeparatorChar) szCabPath += Path.DirectorySeparatorChar; } } /// Provides a handle to a file compression interface. [StructLayout(LayoutKind.Sequential)] public struct HFCI : IHandle { private readonly IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HFCI(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static HFCI NULL => new(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(HFCI h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HFCI(IntPtr h) => new(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HFCI h1, HFCI h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HFCI h1, HFCI h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HFCI h && handle == h.handle; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a for that is disposed using . public class SafeHFCI : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHFCI(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHFCI() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HFCI(SafeHFCI h) => h.handle; /// protected override bool InternalReleaseHandle() => FCIDestroy(handle); } } }