aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Core.Native/CabInterop.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Core.Native/CabInterop.cs')
-rw-r--r--src/WixToolset.Core.Native/CabInterop.cs312
1 files changed, 312 insertions, 0 deletions
diff --git a/src/WixToolset.Core.Native/CabInterop.cs b/src/WixToolset.Core.Native/CabInterop.cs
new file mode 100644
index 00000000..6ad11c67
--- /dev/null
+++ b/src/WixToolset.Core.Native/CabInterop.cs
@@ -0,0 +1,312 @@
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.Diagnostics.CodeAnalysis;
7 using System.Text;
8 using System.Runtime.InteropServices;
9 // using WixToolset.Msi;
10 // using WixToolset.Msi.Interop;
11
12 /// <summary>
13 /// The native methods.
14 /// </summary>
15 public sealed class NativeMethods
16 {
17 /// <summary>
18 /// Starts creating a cabinet.
19 /// </summary>
20 /// <param name="cabinetName">Name of cabinet to create.</param>
21 /// <param name="cabinetDirectory">Directory to create cabinet in.</param>
22 /// <param name="maxFiles">Maximum number of files that will be added to cabinet.</param>
23 /// <param name="maxSize">Maximum size of the cabinet.</param>
24 /// <param name="maxThreshold">Maximum threshold in the cabinet.</param>
25 /// <param name="compressionType">Type of compression to use in the cabinet.</param>
26 /// <param name="contextHandle">Handle to opened cabinet.</param>
27 [DllImport("winterop.dll", EntryPoint = "CreateCabBegin", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
28 public static extern void CreateCabBegin(string cabinetName, string cabinetDirectory, uint maxFiles, uint maxSize, uint maxThreshold, uint compressionType, out IntPtr contextHandle);
29
30 /// <summary>
31 /// Adds a file to an open cabinet.
32 /// </summary>
33 /// <param name="file">Full path to file to add to cabinet.</param>
34 /// <param name="token">Name of file in cabinet.</param>
35 /// <param name="contextHandle">Handle to open cabinet.</param>
36 // [DllImport("winterop.dll", EntryPoint = "CreateCabAddFile", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
37 // public static extern void CreateCabAddFile(string file, string token, MsiInterop.MSIFILEHASHINFO fileHash, IntPtr contextHandle);
38
39 /// <summary>
40 /// Closes a cabinet.
41 /// </summary>
42 /// <param name="contextHandle">Handle to open cabinet to close.</param>
43 /// <param name="newCabNamesCallBackAddress">Address of Binder's cabinet split callback</param>
44 [DllImport("winterop.dll", EntryPoint = "CreateCabFinish", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
45 public static extern void CreateCabFinish(IntPtr contextHandle, IntPtr newCabNamesCallBackAddress);
46
47 /// <summary>
48 /// Cancels cabinet creation.
49 /// </summary>
50 /// <param name="contextHandle">Handle to open cabinet to cancel.</param>
51 [DllImport("winterop.dll", EntryPoint = "CreateCabCancel", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
52 public static extern void CreateCabCancel(IntPtr contextHandle);
53
54 /// <summary>
55 /// Initializes cabinet extraction.
56 /// </summary>
57 [DllImport("winterop.dll", EntryPoint = "ExtractCabBegin", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
58 public static extern void ExtractCabBegin();
59
60 /// <summary>
61 /// Extracts files from cabinet.
62 /// </summary>
63 /// <param name="cabinet">Path to cabinet to extract files from.</param>
64 /// <param name="extractDirectory">Directory to extract files to.</param>
65 [DllImport("winterop.dll", EntryPoint = "ExtractCab", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, PreserveSig = false)]
66 public static extern void ExtractCab(string cabinet, string extractDirectory);
67
68 /// <summary>
69 /// Cleans up after cabinet extraction.
70 /// </summary>
71 [DllImport("winterop.dll", EntryPoint = "ExtractCabFinish", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
72 public static extern void ExtractCabFinish();
73
74 /// <summary>
75 /// Initializes cabinet enumeration.
76 /// </summary>
77 [DllImport("winterop.dll", EntryPoint = "EnumerateCabBegin", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
78 public static extern void EnumerateCabBegin();
79
80 /// <summary>
81 /// Enumerates files from cabinet.
82 /// </summary>
83 /// <param name="cabinet">Path to cabinet to enumerate files from.</param>
84 /// <param name="notify">callback that gets each file.</param>
85 [DllImport("winterop.dll", EntryPoint = "EnumerateCab", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, PreserveSig = false)]
86 public static extern void EnumerateCab(string cabinet, CabInterop.PFNNOTIFY notify);
87
88 /// <summary>
89 /// Cleans up after cabinet enumeration.
90 /// </summary>
91 [DllImport("winterop.dll", EntryPoint = "EnumerateCabFinish", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
92 public static extern void EnumerateCabFinish();
93
94 /// <summary>
95 /// Resets the DACL on an array of files to "empty".
96 /// </summary>
97 /// <param name="files">Array of file reset ACL to "empty".</param>
98 /// <param name="fileCount">Number of file paths in array.</param>
99 [DllImport("winterop.dll", EntryPoint = "ResetAcls", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
100 public static extern void ResetAcls(string[] files, uint fileCount);
101
102 /// <summary>
103 /// Gets the hash of the pCertContext->pCertInfo->SubjectPublicKeyInfo using ::CryptHashPublicKeyInfo() which does not seem
104 /// to be exposed by .NET Frameowkr.
105 /// </summary>
106 /// <param name="certContext">Pointer to a CERT_CONTEXT struct with public key information to hash.</param>
107 /// <param name="fileCount">Number of file paths in array.</param>
108 [DllImport("winterop.dll", EntryPoint = "HashPublicKeyInfo", CharSet = CharSet.Unicode, ExactSpelling = true, PreserveSig = false)]
109 public static extern void HashPublicKeyInfo(IntPtr certContext, byte[] publicKeyInfoHashed, ref uint sizePublicKeyInfoHashed);
110
111 /// <summary>
112 /// Converts file time to a local file time.
113 /// </summary>
114 /// <param name="fileTime">file time</param>
115 /// <param name="localTime">local file time</param>
116 /// <returns>true if successful, false otherwise</returns>
117 [DllImport("kernel32.dll", SetLastError = true)]
118 [return: MarshalAs(UnmanagedType.Bool)]
119 public static extern bool FileTimeToLocalFileTime(ref long fileTime, ref long localTime);
120
121 /// <summary>
122 /// Converts file time to a MS-DOS time.
123 /// </summary>
124 /// <param name="fileTime">file time</param>
125 /// <param name="wFatDate">MS-DOS date</param>
126 /// <param name="wFatTime">MS-DOS time</param>
127 /// <returns>true if successful, false otherwise</returns>
128 [DllImport("kernel32.dll", SetLastError = true)]
129 [return: MarshalAs(UnmanagedType.Bool)]
130 public static extern bool FileTimeToDosDateTime(ref long fileTime, out ushort wFatDate, out ushort wFatTime);
131 }
132
133 /// <summary>
134 /// Interop class for the winterop.dll.
135 /// </summary>
136 public static class CabInterop
137 {
138 /// <summary>
139 /// Delegate type that's called by cabinet api for every file in cabinet.
140 /// </summary>
141 /// <param name="fdint">NOTIFICATIONTYPE</param>
142 /// <param name="pfdin">NOTIFICATION</param>
143 /// <returns>0 for success, -1 otherwise</returns>
144 public delegate Int32 PFNNOTIFY(NOTIFICATIONTYPE fdint, NOTIFICATION pfdin);
145
146 /// <summary>
147 /// Wraps FDINOTIFICATIONTYPE.
148 /// </summary>
149 public enum NOTIFICATIONTYPE : int
150 {
151 /// <summary>Info about the cabinet.</summary>
152 CABINET_INFO,
153 /// <summary>One or more files are continued.</summary>
154 PARTIAL_FILE,
155 /// <summary>Called for each file in cabinet.</summary>
156 COPY_FILE,
157 /// <summary>Called after all of the data has been written to a target file.</summary>
158 CLOSE_FILE_INFO,
159 /// <summary>A file is continued to the next cabinet.</summary>
160 NEXT_CABINET,
161 /// <summary>Called once after a call to FDICopy() starts scanning a CAB's CFFILE entries, and again when there are no more CFFILE entries.</summary>
162 ENUMERATE,
163 }
164
165 /// <summary>
166 /// Converts DateTime to MS-DOS date and time which cabinet uses.
167 /// </summary>
168 /// <param name="dateTime">DateTime</param>
169 /// <param name="cabDate">MS-DOS date</param>
170 /// <param name="cabTime">MS-DOS time</param>
171 public static void DateTimeToCabDateAndTime(DateTime dateTime, out ushort cabDate, out ushort cabTime)
172 {
173 // dateTime.ToLocalTime() does not match FileTimeToLocalFileTime() for some reason.
174 // so we need to call FileTimeToLocalFileTime() from kernel32.dll.
175 long filetime = dateTime.ToFileTime();
176 long localTime = 0;
177 NativeMethods.FileTimeToLocalFileTime(ref filetime, ref localTime);
178 NativeMethods.FileTimeToDosDateTime(ref localTime, out cabDate, out cabTime);
179 }
180
181 /// <summary>
182 /// Wraps FDINOTIFICATION.
183 /// </summary>
184 [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
185 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
186 public class NOTIFICATION
187 {
188 private int cb;
189 [MarshalAs(UnmanagedType.LPStr)]
190 private string psz1;
191 [MarshalAs(UnmanagedType.LPStr)]
192 private string psz2;
193 [MarshalAs(UnmanagedType.LPStr)]
194 private string psz3;
195 private IntPtr pv;
196
197 private IntPtr hf;
198
199 private ushort date;
200 private ushort time;
201 private ushort attribs;
202 private ushort setID;
203 private ushort cabinet;
204 private ushort folder;
205 private int fdie;
206
207 /// <summary>
208 /// Uncompressed size of file.
209 /// </summary>
210 public int Cb
211 {
212 get { return this.cb; }
213 }
214
215 /// <summary>
216 /// File name in cabinet.
217 /// </summary>
218 public String Psz1
219 {
220 get { return this.psz1; }
221 }
222
223 /// <summary>
224 /// Name of next disk.
225 /// </summary>
226 public string Psz2
227 {
228 get { return this.psz2; }
229 }
230
231 /// <summary>
232 /// Points to a 256 character buffer.
233 /// </summary>
234 public string Psz3
235 {
236 get { return this.psz3; }
237 }
238
239 /// <summary>
240 /// Value for client.
241 /// </summary>
242 public IntPtr Pv
243 {
244 get { return this.pv; }
245 }
246
247 /// <summary>
248 /// Not used.
249 /// </summary>
250 public Int32 Hf
251 {
252 get { return (Int32)this.hf; }
253 }
254
255 /// <summary>
256 /// Last modified MS-DOS date.
257 /// </summary>
258 public ushort Date
259 {
260 get { return this.date; }
261 }
262
263 /// <summary>
264 /// Last modified MS-DOS time.
265 /// </summary>
266 public ushort Time
267 {
268 get { return this.time; }
269 }
270
271 /// <summary>
272 /// File attributes.
273 /// </summary>
274 public ushort Attribs
275 {
276 get { return this.attribs; }
277 }
278
279 /// <summary>
280 /// Cabinet set ID (a random 16-bit number).
281 /// </summary>
282 public ushort SetID
283 {
284 get { return this.setID; }
285 }
286
287 /// <summary>
288 /// Cabinet number within cabinet set (0-based).
289 /// </summary>
290 public ushort Cabinet
291 {
292 get { return this.cabinet; }
293 }
294
295 /// <summary>
296 /// File's folder index.
297 /// </summary>
298 public ushort Folder
299 {
300 get { return this.folder; }
301 }
302
303 /// <summary>
304 /// Error code.
305 /// </summary>
306 public int Fdie
307 {
308 get { return this.fdie; }
309 }
310 }
311 }
312}