diff options
Diffstat (limited to 'src/WixToolset.Core.Native/CabInterop.cs')
-rw-r--r-- | src/WixToolset.Core.Native/CabInterop.cs | 312 |
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 | |||
3 | namespace 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 | } | ||