aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.Native/Cabinet.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/WixToolset.Core.Native/Cabinet.cs199
1 files changed, 199 insertions, 0 deletions
diff --git a/src/WixToolset.Core.Native/Cabinet.cs b/src/WixToolset.Core.Native/Cabinet.cs
new file mode 100644
index 00000000..27b0ec74
--- /dev/null
+++ b/src/WixToolset.Core.Native/Cabinet.cs
@@ -0,0 +1,199 @@
1// 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.
2
3namespace WixToolset.Core.Native
4{
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8
9 /// <summary>
10 /// Wrapper class around interop with wixcab.dll to compress files into a cabinet.
11 /// </summary>
12 public sealed class Cabinet
13 {
14 private const string CompressionLevelVariable = "WIX_COMPRESSION_LEVEL";
15 private static readonly char[] TextLineSplitter = new[] { '\t' };
16
17 public Cabinet(string path)
18 {
19 this.Path = path;
20 }
21
22 public string Path { get; }
23
24 /// <summary>
25 /// Creates a cabinet.
26 /// </summary>
27 /// <param name="cabPath">Path of cabinet to create.</param>
28 /// <param name="compressionLevel">Level of compression to apply.</param>
29 /// <param name="maxFiles">Maximum number of files that will be added to cabinet.</param>
30 /// <param name="maxSize">Maximum size of cabinet.</param>
31 /// <param name="maxThresh">Maximum threshold for each cabinet.</param>
32 public void Compress(IEnumerable<CabinetCompressFile> files, CabinetCompressionLevel compressionLevel, int maxSize = 0, int maxThresh = 0)
33 {
34 var compressionLevelVariable = Environment.GetEnvironmentVariable(CompressionLevelVariable);
35
36 // Override authored compression level if environment variable is present.
37 if (!String.IsNullOrEmpty(compressionLevelVariable))
38 {
39 if (!Enum.TryParse(compressionLevelVariable, true, out compressionLevel))
40 {
41 //throw new WixException(WixErrors.IllegalEnvironmentVariable(CompressionLevelVariable, compressionLevelVariable));
42 throw new ArgumentException();
43 }
44 }
45
46 var wixnative = new WixNativeExe("smartcab", this.Path, Convert.ToInt32(compressionLevel), files.Count(), maxSize, maxThresh);
47
48 foreach (var file in files)
49 {
50 wixnative.AddStdinLine(file.ToWixNativeStdinLine());
51 }
52
53 wixnative.Run();
54
55#if TOOD_ERROR_HANDLING
56 catch (COMException ce)
57 {
58 // If we get a "the file exists" error, we must have a full temp directory - so report the issue
59 if (0x80070050 == unchecked((uint)ce.ErrorCode))
60 {
61 throw new WixException(WixErrors.FullTempDirectory("WSC", Path.GetTempPath()));
62 }
63
64 throw;
65 }
66#endif
67 }
68
69 /// <summary>
70 /// Enumerates all files in a cabinet.
71 /// </summary>
72 /// <returns>>List of CabinetFileInfo</returns>
73 public List<CabinetFileInfo> Enumerate()
74 {
75 var wixnative = new WixNativeExe("enumcab", this.Path);
76 var lines = wixnative.Run();
77
78 var fileInfoList = new List<CabinetFileInfo>();
79
80 foreach (var line in lines)
81 {
82 if (String.IsNullOrEmpty(line))
83 {
84 continue;
85 }
86
87 var data = line.Split(TextLineSplitter, StringSplitOptions.None);
88
89 var size = Convert.ToInt32(data[1]);
90 var date = Convert.ToInt32(data[2]);
91 var time = Convert.ToInt32(data[3]);
92
93 fileInfoList.Add(new CabinetFileInfo(data[0], size, date, time));
94 }
95
96 return fileInfoList;
97 }
98
99 /// <summary>
100 /// Extracts all the files from a cabinet to a directory.
101 /// </summary>
102 /// <param name="outputFolder">Directory to extract files to.</param>
103 public void Extract(string outputFolder)
104 {
105 if (!outputFolder.EndsWith("\\", StringComparison.Ordinal))
106 {
107 outputFolder += "\\";
108 }
109
110 var wixnative = new WixNativeExe("extractcab", this.Path, outputFolder);
111 wixnative.Run();
112 }
113
114#if TOOD_ERROR_HANDLING
115 /// <summary>
116 /// Adds a file to the cabinet with an optional MSI file hash.
117 /// </summary>
118 /// <param name="file">The file to add.</param>
119 /// <param name="token">The token for the file.</param>
120 /// <param name="fileHash">The MSI file hash of the file.</param>
121 //private void AddFile(string file, string token, MsiInterop.MSIFILEHASHINFO fileHash)
122 //{
123 // try
124 // {
125 // NativeMethods.CreateCabAddFile(file, token, fileHash, this.handle);
126 // }
127 // catch (COMException ce)
128 // {
129 // if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL
130 // {
131 // throw new WixException(WixErrors.CreateCabAddFileFailed());
132 // }
133 // else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL
134 // {
135 // throw new WixException(WixErrors.CreateCabInsufficientDiskSpace());
136 // }
137 // else
138 // {
139 // throw;
140 // }
141 // }
142 // catch (DirectoryNotFoundException)
143 // {
144 // throw new WixFileNotFoundException(file);
145 // }
146 // catch (FileNotFoundException)
147 // {
148 // throw new WixFileNotFoundException(file);
149 // }
150 //}
151
152 /// <summary>
153 /// Complete/commit the cabinet - this must be called before Dispose so that errors will be
154 /// reported on the same thread.
155 /// </summary>
156 /// <param name="newCabNamesCallBackAddress">Address of Binder's callback function for Cabinet Splitting</param>
157 public void Complete(IntPtr newCabNamesCallBackAddress)
158 {
159 if (IntPtr.Zero != this.handle)
160 {
161 try
162 {
163 if (newCabNamesCallBackAddress != IntPtr.Zero && this.maxSize != 0)
164 {
165 NativeMethods.CreateCabFinish(this.handle, newCabNamesCallBackAddress);
166 }
167 else
168 {
169 NativeMethods.CreateCabFinish(this.handle, IntPtr.Zero);
170 }
171
172 GC.SuppressFinalize(this);
173 this.disposed = true;
174 }
175 catch (COMException ce)
176 {
177 //if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL
178 //{
179 // // This error seems to happen, among other situations, when cabbing more than 0xFFFF files
180 // throw new WixException(WixErrors.FinishCabFailed());
181 //}
182 //else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL
183 //{
184 // throw new WixException(WixErrors.CreateCabInsufficientDiskSpace());
185 //}
186 //else
187 //{
188 // throw;
189 //}
190 }
191 finally
192 {
193 this.handle = IntPtr.Zero;
194 }
195 }
196 }
197#endif
198 }
199}