// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. #if false namespace WixToolset.Cab.Interop { using System; using System.Diagnostics.CodeAnalysis; using System.Text; using System.Runtime.InteropServices; using WixToolset.Msi; using WixToolset.Msi.Interop; /// /// The native methods. /// public sealed class NativeMethods { /// /// Starts creating a cabinet. /// /// Name of cabinet to create. /// Directory to create cabinet in. /// Maximum number of files that will be added to cabinet. /// Maximum size of the cabinet. /// Maximum threshold in the cabinet. /// Type of compression to use in the cabinet. /// Handle to opened cabinet. [DllImport("winterop.dll", EntryPoint = "CreateCabBegin", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void CreateCabBegin(string cabinetName, string cabinetDirectory, uint maxFiles, uint maxSize, uint maxThreshold, uint compressionType, out IntPtr contextHandle); /// /// Adds a file to an open cabinet. /// /// Full path to file to add to cabinet. /// Name of file in cabinet. /// Handle to open cabinet. [DllImport("winterop.dll", EntryPoint = "CreateCabAddFile", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void CreateCabAddFile(string file, string token, MsiInterop.MSIFILEHASHINFO fileHash, IntPtr contextHandle); /// /// Closes a cabinet. /// /// Handle to open cabinet to close. /// Address of Binder's cabinet split callback [DllImport("winterop.dll", EntryPoint = "CreateCabFinish", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void CreateCabFinish(IntPtr contextHandle, IntPtr newCabNamesCallBackAddress); /// /// Cancels cabinet creation. /// /// Handle to open cabinet to cancel. [DllImport("winterop.dll", EntryPoint = "CreateCabCancel", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void CreateCabCancel(IntPtr contextHandle); /// /// Initializes cabinet extraction. /// [DllImport("winterop.dll", EntryPoint = "ExtractCabBegin", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void ExtractCabBegin(); /// /// Extracts files from cabinet. /// /// Path to cabinet to extract files from. /// Directory to extract files to. [DllImport("winterop.dll", EntryPoint = "ExtractCab", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, PreserveSig = false)] internal static extern void ExtractCab(string cabinet, string extractDirectory); /// /// Cleans up after cabinet extraction. /// [DllImport("winterop.dll", EntryPoint = "ExtractCabFinish", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] internal static extern void ExtractCabFinish(); /// /// Initializes cabinet enumeration. /// [DllImport("winterop.dll", EntryPoint = "EnumerateCabBegin", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void EnumerateCabBegin(); /// /// Enumerates files from cabinet. /// /// Path to cabinet to enumerate files from. /// callback that gets each file. [DllImport("winterop.dll", EntryPoint = "EnumerateCab", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, PreserveSig = false)] internal static extern void EnumerateCab(string cabinet, CabInterop.PFNNOTIFY notify); /// /// Cleans up after cabinet enumeration. /// [DllImport("winterop.dll", EntryPoint = "EnumerateCabFinish", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] internal static extern void EnumerateCabFinish(); /// /// Resets the DACL on an array of files to "empty". /// /// Array of file reset ACL to "empty". /// Number of file paths in array. [DllImport("winterop.dll", EntryPoint = "ResetAcls", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void ResetAcls(string[] files, uint fileCount); /// /// Gets the hash of the pCertContext->pCertInfo->SubjectPublicKeyInfo using ::CryptHashPublicKeyInfo() which does not seem /// to be exposed by .NET Frameowkr. /// /// Pointer to a CERT_CONTEXT struct with public key information to hash. /// Number of file paths in array. [DllImport("winterop.dll", EntryPoint = "HashPublicKeyInfo", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)] internal static extern void HashPublicKeyInfo(IntPtr certContext, byte[] publicKeyInfoHashed, ref uint sizePublicKeyInfoHashed); /// /// Converts file time to a local file time. /// /// file time /// local file time /// true if successful, false otherwise [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool FileTimeToLocalFileTime(ref long fileTime, ref long localTime); /// /// Converts file time to a MS-DOS time. /// /// file time /// MS-DOS date /// MS-DOS time /// true if successful, false otherwise [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool FileTimeToDosDateTime(ref long fileTime, out ushort wFatDate, out ushort wFatTime); } /// /// Interop class for the winterop.dll. /// internal static class CabInterop { /// /// Delegate type that's called by cabinet api for every file in cabinet. /// /// NOTIFICATIONTYPE /// NOTIFICATION /// 0 for success, -1 otherwise public delegate Int32 PFNNOTIFY(NOTIFICATIONTYPE fdint, NOTIFICATION pfdin); /// /// Wraps FDINOTIFICATIONTYPE. /// public enum NOTIFICATIONTYPE : int { /// Info about the cabinet. CABINET_INFO, /// One or more files are continued. PARTIAL_FILE, /// Called for each file in cabinet. COPY_FILE, /// Called after all of the data has been written to a target file. CLOSE_FILE_INFO, /// A file is continued to the next cabinet. NEXT_CABINET, /// Called once after a call to FDICopy() starts scanning a CAB's CFFILE entries, and again when there are no more CFFILE entries. ENUMERATE, } /// /// Converts DateTime to MS-DOS date and time which cabinet uses. /// /// DateTime /// MS-DOS date /// MS-DOS time public static void DateTimeToCabDateAndTime(DateTime dateTime, out ushort cabDate, out ushort cabTime) { // dateTime.ToLocalTime() does not match FileTimeToLocalFileTime() for some reason. // so we need to call FileTimeToLocalFileTime() from kernel32.dll. long filetime = dateTime.ToFileTime(); long localTime = 0; NativeMethods.FileTimeToLocalFileTime(ref filetime, ref localTime); NativeMethods.FileTimeToDosDateTime(ref localTime, out cabDate, out cabTime); } /// /// Wraps FDINOTIFICATION. /// [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")] [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class NOTIFICATION { private int cb; [MarshalAs(UnmanagedType.LPStr)] private string psz1; [MarshalAs(UnmanagedType.LPStr)] private string psz2; [MarshalAs(UnmanagedType.LPStr)] private string psz3; private IntPtr pv; private IntPtr hf; private ushort date; private ushort time; private ushort attribs; private ushort setID; private ushort cabinet; private ushort folder; private int fdie; /// /// Uncompressed size of file. /// public int Cb { get { return this.cb; } } /// /// File name in cabinet. /// public String Psz1 { get { return this.psz1; } } /// /// Name of next disk. /// public string Psz2 { get { return this.psz2; } } /// /// Points to a 256 character buffer. /// public string Psz3 { get { return this.psz3; } } /// /// Value for client. /// public IntPtr Pv { get { return this.pv; } } /// /// Not used. /// public Int32 Hf { get { return (Int32)this.hf; } } /// /// Last modified MS-DOS date. /// public ushort Date { get { return this.date; } } /// /// Last modified MS-DOS time. /// public ushort Time { get { return this.time; } } /// /// File attributes. /// public ushort Attribs { get { return this.attribs; } } /// /// Cabinet set ID (a random 16-bit number). /// public ushort SetID { get { return this.setID; } } /// /// Cabinet number within cabinet set (0-based). /// public ushort Cabinet { get { return this.cabinet; } } /// /// File's folder index. /// public ushort Folder { get { return this.folder; } } /// /// Error code. /// public int Fdie { get { return this.fdie; } } } } } #endif