diff options
Diffstat (limited to 'src/WixToolset.Core/Cab/WixCreateCab.cs')
-rw-r--r-- | src/WixToolset.Core/Cab/WixCreateCab.cs | 249 |
1 files changed, 0 insertions, 249 deletions
diff --git a/src/WixToolset.Core/Cab/WixCreateCab.cs b/src/WixToolset.Core/Cab/WixCreateCab.cs deleted file mode 100644 index 4ebdd1c0..00000000 --- a/src/WixToolset.Core/Cab/WixCreateCab.cs +++ /dev/null | |||
@@ -1,249 +0,0 @@ | |||
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 | |||
3 | namespace WixToolset.Core.Cab | ||
4 | { | ||
5 | using System; | ||
6 | using System.Globalization; | ||
7 | using System.IO; | ||
8 | using System.Runtime.InteropServices; | ||
9 | using WixToolset.Core.Bind; | ||
10 | using WixToolset.Core.Native; | ||
11 | using WixToolset.Data; | ||
12 | |||
13 | /// <summary> | ||
14 | /// Wrapper class around interop with wixcab.dll to compress files into a cabinet. | ||
15 | /// </summary> | ||
16 | public sealed class WixCreateCab : IDisposable | ||
17 | { | ||
18 | private static readonly string CompressionLevelVariable = "WIX_COMPRESSION_LEVEL"; | ||
19 | private IntPtr handle = IntPtr.Zero; | ||
20 | private bool disposed; | ||
21 | private int maxSize; | ||
22 | |||
23 | /// <summary> | ||
24 | /// Creates a cabinet. | ||
25 | /// </summary> | ||
26 | /// <param name="cabName">Name of cabinet to create.</param> | ||
27 | /// <param name="cabDir">Directory to create cabinet in.</param> | ||
28 | /// <param name="maxFiles">Maximum number of files that will be added to cabinet.</param> | ||
29 | /// <param name="maxSize">Maximum size of cabinet.</param> | ||
30 | /// <param name="maxThresh">Maximum threshold for each cabinet.</param> | ||
31 | /// <param name="compressionLevel">Level of compression to apply.</param> | ||
32 | public WixCreateCab(string cabName, string cabDir, int maxFiles, int maxSize, int maxThresh, CompressionLevel compressionLevel) | ||
33 | { | ||
34 | string compressionLevelVariable = Environment.GetEnvironmentVariable(CompressionLevelVariable); | ||
35 | this.maxSize = maxSize; | ||
36 | |||
37 | try | ||
38 | { | ||
39 | // Override authored compression level if environment variable is present. | ||
40 | if (!String.IsNullOrEmpty(compressionLevelVariable)) | ||
41 | { | ||
42 | compressionLevel = WixCreateCab.CompressionLevelFromString(compressionLevelVariable); | ||
43 | } | ||
44 | } | ||
45 | catch (WixException) | ||
46 | { | ||
47 | throw new WixException(WixErrors.IllegalEnvironmentVariable(CompressionLevelVariable, compressionLevelVariable)); | ||
48 | } | ||
49 | |||
50 | if (String.IsNullOrEmpty(cabDir)) | ||
51 | { | ||
52 | cabDir = Directory.GetCurrentDirectory(); | ||
53 | } | ||
54 | |||
55 | try | ||
56 | { | ||
57 | NativeMethods.CreateCabBegin(cabName, cabDir, (uint)maxFiles, (uint)maxSize, (uint)maxThresh, (uint)compressionLevel, out this.handle); | ||
58 | } | ||
59 | catch (COMException ce) | ||
60 | { | ||
61 | // If we get a "the file exists" error, we must have a full temp directory - so report the issue | ||
62 | if (0x80070050 == unchecked((uint)ce.ErrorCode)) | ||
63 | { | ||
64 | throw new WixException(WixErrors.FullTempDirectory("WSC", Path.GetTempPath())); | ||
65 | } | ||
66 | |||
67 | throw; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /// <summary> | ||
72 | /// Destructor for cabinet creation. | ||
73 | /// </summary> | ||
74 | ~WixCreateCab() | ||
75 | { | ||
76 | this.Dispose(); | ||
77 | } | ||
78 | |||
79 | /// <summary> | ||
80 | /// Converts a compression level from its string to its enum value. | ||
81 | /// </summary> | ||
82 | /// <param name="compressionLevel">Compression level as a string.</param> | ||
83 | /// <returns>CompressionLevel enum value</returns> | ||
84 | public static CompressionLevel CompressionLevelFromString(string compressionLevel) | ||
85 | { | ||
86 | switch (compressionLevel.ToLower(CultureInfo.InvariantCulture)) | ||
87 | { | ||
88 | case "low": | ||
89 | return CompressionLevel.Low; | ||
90 | case "medium": | ||
91 | return CompressionLevel.Medium; | ||
92 | case "high": | ||
93 | return CompressionLevel.High; | ||
94 | case "none": | ||
95 | return CompressionLevel.None; | ||
96 | case "mszip": | ||
97 | return CompressionLevel.Mszip; | ||
98 | default: | ||
99 | throw new WixException(WixErrors.IllegalCompressionLevel(compressionLevel)); | ||
100 | } | ||
101 | } | ||
102 | |||
103 | /// <summary> | ||
104 | /// Adds a file to the cabinet. | ||
105 | /// </summary> | ||
106 | /// <param name="fileFacade">The file facade of the file to add.</param> | ||
107 | public void AddFile(FileFacade fileFacade) | ||
108 | { | ||
109 | MsiInterop.MSIFILEHASHINFO hashInterop = new MsiInterop.MSIFILEHASHINFO(); | ||
110 | |||
111 | if (null != fileFacade.Hash) | ||
112 | { | ||
113 | hashInterop.FileHashInfoSize = 20; | ||
114 | hashInterop.Data0 = (int)fileFacade.Hash[2]; | ||
115 | hashInterop.Data1 = (int)fileFacade.Hash[3]; | ||
116 | hashInterop.Data2 = (int)fileFacade.Hash[4]; | ||
117 | hashInterop.Data3 = (int)fileFacade.Hash[5]; | ||
118 | |||
119 | this.AddFile(fileFacade.WixFile.Source, fileFacade.File.File, hashInterop); | ||
120 | } | ||
121 | else | ||
122 | { | ||
123 | this.AddFile(fileFacade.WixFile.Source, fileFacade.File.File); | ||
124 | } | ||
125 | } | ||
126 | |||
127 | /// <summary> | ||
128 | /// Adds a file to the cabinet. | ||
129 | /// </summary> | ||
130 | /// <param name="file">The file to add.</param> | ||
131 | /// <param name="token">The token for the file.</param> | ||
132 | public void AddFile(string file, string token) | ||
133 | { | ||
134 | this.AddFile(file, token, null); | ||
135 | } | ||
136 | |||
137 | /// <summary> | ||
138 | /// Adds a file to the cabinet with an optional MSI file hash. | ||
139 | /// </summary> | ||
140 | /// <param name="file">The file to add.</param> | ||
141 | /// <param name="token">The token for the file.</param> | ||
142 | /// <param name="fileHash">The MSI file hash of the file.</param> | ||
143 | private void AddFile(string file, string token, MsiInterop.MSIFILEHASHINFO fileHash) | ||
144 | { | ||
145 | try | ||
146 | { | ||
147 | NativeMethods.CreateCabAddFile(file, token, fileHash, this.handle); | ||
148 | } | ||
149 | catch (COMException ce) | ||
150 | { | ||
151 | if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL | ||
152 | { | ||
153 | throw new WixException(WixErrors.CreateCabAddFileFailed()); | ||
154 | } | ||
155 | else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL | ||
156 | { | ||
157 | throw new WixException(WixErrors.CreateCabInsufficientDiskSpace()); | ||
158 | } | ||
159 | else | ||
160 | { | ||
161 | throw; | ||
162 | } | ||
163 | } | ||
164 | catch (DirectoryNotFoundException) | ||
165 | { | ||
166 | throw new WixFileNotFoundException(file); | ||
167 | } | ||
168 | catch (FileNotFoundException) | ||
169 | { | ||
170 | throw new WixFileNotFoundException(file); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | /// <summary> | ||
175 | /// Complete/commit the cabinet - this must be called before Dispose so that errors will be | ||
176 | /// reported on the same thread. | ||
177 | /// This Complete should be used with no Cabinet splitting as it has the split cabinet names callback address as Zero | ||
178 | /// </summary> | ||
179 | public void Complete() | ||
180 | { | ||
181 | this.Complete(IntPtr.Zero); | ||
182 | } | ||
183 | |||
184 | /// <summary> | ||
185 | /// Complete/commit the cabinet - this must be called before Dispose so that errors will be | ||
186 | /// reported on the same thread. | ||
187 | /// </summary> | ||
188 | /// <param name="newCabNamesCallBackAddress">Address of Binder's callback function for Cabinet Splitting</param> | ||
189 | public void Complete(IntPtr newCabNamesCallBackAddress) | ||
190 | { | ||
191 | if (IntPtr.Zero != this.handle) | ||
192 | { | ||
193 | try | ||
194 | { | ||
195 | if (newCabNamesCallBackAddress != IntPtr.Zero && this.maxSize != 0) | ||
196 | { | ||
197 | NativeMethods.CreateCabFinish(this.handle, newCabNamesCallBackAddress); | ||
198 | } | ||
199 | else | ||
200 | { | ||
201 | NativeMethods.CreateCabFinish(this.handle, IntPtr.Zero); | ||
202 | } | ||
203 | |||
204 | GC.SuppressFinalize(this); | ||
205 | this.disposed = true; | ||
206 | } | ||
207 | catch (COMException ce) | ||
208 | { | ||
209 | if (0x80004005 == unchecked((uint)ce.ErrorCode)) // E_FAIL | ||
210 | { | ||
211 | // This error seems to happen, among other situations, when cabbing more than 0xFFFF files | ||
212 | throw new WixException(WixErrors.FinishCabFailed()); | ||
213 | } | ||
214 | else if (0x80070070 == unchecked((uint)ce.ErrorCode)) // ERROR_DISK_FULL | ||
215 | { | ||
216 | throw new WixException(WixErrors.CreateCabInsufficientDiskSpace()); | ||
217 | } | ||
218 | else | ||
219 | { | ||
220 | throw; | ||
221 | } | ||
222 | } | ||
223 | finally | ||
224 | { | ||
225 | this.handle = IntPtr.Zero; | ||
226 | } | ||
227 | } | ||
228 | } | ||
229 | |||
230 | /// <summary> | ||
231 | /// Cancels ("rolls back") the creation of the cabinet. | ||
232 | /// Don't throw WiX errors from here, because we're in a different thread, and they won't be reported correctly. | ||
233 | /// </summary> | ||
234 | public void Dispose() | ||
235 | { | ||
236 | if (!this.disposed) | ||
237 | { | ||
238 | if (IntPtr.Zero != this.handle) | ||
239 | { | ||
240 | NativeMethods.CreateCabCancel(this.handle); | ||
241 | this.handle = IntPtr.Zero; | ||
242 | } | ||
243 | |||
244 | GC.SuppressFinalize(this); | ||
245 | this.disposed = true; | ||
246 | } | ||
247 | } | ||
248 | } | ||
249 | } | ||