aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.Compression.Cab/NativeMethods.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/dtf/WixToolset.Dtf.Compression.Cab/NativeMethods.cs407
1 files changed, 407 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.Compression.Cab/NativeMethods.cs b/src/dtf/WixToolset.Dtf.Compression.Cab/NativeMethods.cs
new file mode 100644
index 00000000..562e96dd
--- /dev/null
+++ b/src/dtf/WixToolset.Dtf.Compression.Cab/NativeMethods.cs
@@ -0,0 +1,407 @@
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.Dtf.Compression.Cab
4{
5using System;
6using System.Text;
7using System.Security;
8using System.Runtime.InteropServices;
9using System.Diagnostics.CodeAnalysis;
10
11/// <summary>
12/// Native DllImport methods and related structures and constants used for
13/// cabinet creation and extraction via cabinet.dll.
14/// </summary>
15internal static class NativeMethods
16{
17 /// <summary>
18 /// A direct import of constants, enums, structures, delegates, and functions from fci.h.
19 /// Refer to comments in fci.h for documentation.
20 /// </summary>
21 internal static class FCI
22 {
23 internal const int MIN_DISK = 32768;
24 internal const int MAX_DISK = Int32.MaxValue;
25 internal const int MAX_FOLDER = 0x7FFF8000;
26 internal const int MAX_FILENAME = 256;
27 internal const int MAX_CABINET_NAME = 256;
28 internal const int MAX_CAB_PATH = 256;
29 internal const int MAX_DISK_NAME = 256;
30
31 internal const int CPU_80386 = 1;
32
33 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate IntPtr PFNALLOC(int cb);
34 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void PFNFREE(IntPtr pv);
35
36 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNOPEN(string path, int oflag, int pmode, out int err, IntPtr pv);
37 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNREAD(int fileHandle, IntPtr memory, int cb, out int err, IntPtr pv);
38 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNWRITE(int fileHandle, IntPtr memory, int cb, out int err, IntPtr pv);
39 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNCLOSE(int fileHandle, out int err, IntPtr pv);
40 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNSEEK(int fileHandle, int dist, int seekType, out int err, IntPtr pv);
41 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNDELETE(string path, out int err, IntPtr pv);
42
43 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNGETNEXTCABINET(IntPtr pccab, uint cbPrevCab, IntPtr pv);
44 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNFILEPLACED(IntPtr pccab, string path, long fileSize, int continuation, IntPtr pv);
45 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNGETOPENINFO(string path, out short date, out short time, out short pattribs, out int err, IntPtr pv);
46 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNSTATUS(STATUS typeStatus, uint cb1, uint cb2, IntPtr pv);
47 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNGETTEMPFILE(IntPtr tempNamePtr, int tempNameSize, IntPtr pv);
48
49 /// <summary>
50 /// Error codes that can be returned by FCI.
51 /// </summary>
52 internal enum ERROR : int
53 {
54 NONE,
55 OPEN_SRC,
56 READ_SRC,
57 ALLOC_FAIL,
58 TEMP_FILE,
59 BAD_COMPR_TYPE,
60 CAB_FILE,
61 USER_ABORT,
62 MCI_FAIL,
63 }
64
65 /// <summary>
66 /// FCI compression algorithm types and parameters.
67 /// </summary>
68 internal enum TCOMP : ushort
69 {
70 MASK_TYPE = 0x000F,
71 TYPE_NONE = 0x0000,
72 TYPE_MSZIP = 0x0001,
73 TYPE_QUANTUM = 0x0002,
74 TYPE_LZX = 0x0003,
75 BAD = 0x000F,
76
77 MASK_LZX_WINDOW = 0x1F00,
78 LZX_WINDOW_LO = 0x0F00,
79 LZX_WINDOW_HI = 0x1500,
80 SHIFT_LZX_WINDOW = 0x0008,
81
82 MASK_QUANTUM_LEVEL = 0x00F0,
83 QUANTUM_LEVEL_LO = 0x0010,
84 QUANTUM_LEVEL_HI = 0x0070,
85 SHIFT_QUANTUM_LEVEL = 0x0004,
86
87 MASK_QUANTUM_MEM = 0x1F00,
88 QUANTUM_MEM_LO = 0x0A00,
89 QUANTUM_MEM_HI = 0x1500,
90 SHIFT_QUANTUM_MEM = 0x0008,
91
92 MASK_RESERVED = 0xE000,
93 }
94
95 /// <summary>
96 /// Reason for FCI status callback.
97 /// </summary>
98 internal enum STATUS : uint
99 {
100 FILE = 0,
101 FOLDER = 1,
102 CABINET = 2,
103 }
104
105 [SuppressMessage("Microsoft.Globalization", "CA2101:SpecifyMarshalingForPInvokeStringArguments")]
106 [DllImport("cabinet.dll", EntryPoint = "FCICreate", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
107 internal static extern Handle Create(IntPtr perf, PFNFILEPLACED pfnfcifp, PFNALLOC pfna, PFNFREE pfnf, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, PFNDELETE pfndelete, PFNGETTEMPFILE pfnfcigtf, [MarshalAs(UnmanagedType.LPStruct)] CCAB pccab, IntPtr pv);
108
109 [DllImport("cabinet.dll", EntryPoint = "FCIAddFile", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
110 internal static extern int AddFile(Handle hfci, string pszSourceFile, IntPtr pszFileName, [MarshalAs(UnmanagedType.Bool)] bool fExecute, PFNGETNEXTCABINET pfnfcignc, PFNSTATUS pfnfcis, PFNGETOPENINFO pfnfcigoi, TCOMP typeCompress);
111
112 [DllImport("cabinet.dll", EntryPoint = "FCIFlushCabinet", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
113 internal static extern int FlushCabinet(Handle hfci, [MarshalAs(UnmanagedType.Bool)] bool fGetNextCab, PFNGETNEXTCABINET pfnfcignc, PFNSTATUS pfnfcis);
114
115 [DllImport("cabinet.dll", EntryPoint = "FCIFlushFolder", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
116 internal static extern int FlushFolder(Handle hfci, PFNGETNEXTCABINET pfnfcignc, PFNSTATUS pfnfcis);
117
118 [SuppressUnmanagedCodeSecurity]
119 [DllImport("cabinet.dll", EntryPoint = "FCIDestroy", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
120 [return: MarshalAs(UnmanagedType.Bool)]
121 internal static extern bool Destroy(IntPtr hfci);
122
123 /// <summary>
124 /// Cabinet information structure used for FCI initialization and GetNextCabinet callback.
125 /// </summary>
126 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
127 internal class CCAB
128 {
129 internal int cb = MAX_DISK;
130 internal int cbFolderThresh = MAX_FOLDER;
131 internal int cbReserveCFHeader;
132 internal int cbReserveCFFolder;
133 internal int cbReserveCFData;
134 internal int iCab;
135 internal int iDisk;
136 internal int fFailOnIncompressible;
137 internal short setID;
138 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_DISK_NAME )] internal string szDisk = String.Empty;
139 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_CABINET_NAME)] internal string szCab = String.Empty;
140 [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_CAB_PATH )] internal string szCabPath = String.Empty;
141 }
142
143 /// <summary>
144 /// Ensures that the FCI handle is safely released.
145 /// </summary>
146 internal class Handle : SafeHandle
147 {
148 /// <summary>
149 /// Creates a new unintialized handle. The handle will be initialized
150 /// when it is marshalled back from native code.
151 /// </summary>
152 internal Handle()
153 : base(IntPtr.Zero, true)
154 {
155 }
156
157 /// <summary>
158 /// Checks if the handle is invalid. An FCI handle is invalid when it is zero.
159 /// </summary>
160 public override bool IsInvalid
161 {
162 get
163 {
164 return this.handle == IntPtr.Zero;
165 }
166 }
167
168 /// <summary>
169 /// Releases the handle by calling FDIDestroy().
170 /// </summary>
171 /// <returns>True if the release succeeded.</returns>
172 protected override bool ReleaseHandle()
173 {
174 return FCI.Destroy(this.handle);
175 }
176 }
177 }
178
179 /// <summary>
180 /// A direct import of constants, enums, structures, delegates, and functions from fdi.h.
181 /// Refer to comments in fdi.h for documentation.
182 /// </summary>
183 internal static class FDI
184 {
185 internal const int MAX_DISK = Int32.MaxValue;
186 internal const int MAX_FILENAME = 256;
187 internal const int MAX_CABINET_NAME = 256;
188 internal const int MAX_CAB_PATH = 256;
189 internal const int MAX_DISK_NAME = 256;
190
191 internal const int CPU_80386 = 1;
192
193 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate IntPtr PFNALLOC(int cb);
194 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate void PFNFREE(IntPtr pv);
195
196 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNOPEN(string path, int oflag, int pmode);
197 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNREAD(int hf, IntPtr pv, int cb);
198 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNWRITE(int hf, IntPtr pv, int cb);
199 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNCLOSE(int hf);
200 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNSEEK(int hf, int dist, int seektype);
201
202 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate int PFNNOTIFY(NOTIFICATIONTYPE fdint, NOTIFICATION fdin);
203
204 /// <summary>
205 /// Error codes that can be returned by FDI.
206 /// </summary>
207 internal enum ERROR : int
208 {
209 NONE,
210 CABINET_NOT_FOUND,
211 NOT_A_CABINET,
212 UNKNOWN_CABINET_VERSION,
213 CORRUPT_CABINET,
214 ALLOC_FAIL,
215 BAD_COMPR_TYPE,
216 MDI_FAIL,
217 TARGET_FILE,
218 RESERVE_MISMATCH,
219 WRONG_CABINET,
220 USER_ABORT,
221 }
222
223 /// <summary>
224 /// Type of notification message for the FDI Notify callback.
225 /// </summary>
226 internal enum NOTIFICATIONTYPE : int
227 {
228 CABINET_INFO,
229 PARTIAL_FILE,
230 COPY_FILE,
231 CLOSE_FILE_INFO,
232 NEXT_CABINET,
233 ENUMERATE,
234 }
235
236 [DllImport("cabinet.dll", EntryPoint = "FDICreate", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
237 internal static extern Handle Create([MarshalAs(UnmanagedType.FunctionPtr)] PFNALLOC pfnalloc, [MarshalAs(UnmanagedType.FunctionPtr)] PFNFREE pfnfree, PFNOPEN pfnopen, PFNREAD pfnread, PFNWRITE pfnwrite, PFNCLOSE pfnclose, PFNSEEK pfnseek, int cpuType, IntPtr perf);
238
239 [DllImport("cabinet.dll", EntryPoint = "FDICopy", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
240 internal static extern int Copy(Handle hfdi, string pszCabinet, string pszCabPath, int flags, PFNNOTIFY pfnfdin, IntPtr pfnfdid, IntPtr pvUser);
241
242 [SuppressUnmanagedCodeSecurity]
243 [DllImport("cabinet.dll", EntryPoint = "FDIDestroy", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
244 [return: MarshalAs(UnmanagedType.Bool)]
245 internal static extern bool Destroy(IntPtr hfdi);
246
247 [DllImport("cabinet.dll", EntryPoint = "FDIIsCabinet", CharSet = CharSet.Ansi, BestFitMapping = false, ThrowOnUnmappableChar = true, CallingConvention = CallingConvention.Cdecl)]
248 [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable", Justification="FDI file handles definitely remain 4 bytes on 64bit platforms.")]
249 internal static extern int IsCabinet(Handle hfdi, int hf, out CABINFO pfdici);
250
251 /// <summary>
252 /// Cabinet information structure filled in by FDI IsCabinet.
253 /// </summary>
254 [StructLayout(LayoutKind.Sequential)]
255 internal struct CABINFO
256 {
257 internal int cbCabinet;
258 internal short cFolders;
259 internal short cFiles;
260 internal short setID;
261 internal short iCabinet;
262 internal int fReserve;
263 internal int hasprev;
264 internal int hasnext;
265 }
266
267 /// <summary>
268 /// Cabinet notification details passed to the FDI Notify callback.
269 /// </summary>
270 [SuppressMessage("Microsoft.Performance", "CA1812:AvoidUninstantiatedInternalClasses")]
271 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
272 internal class NOTIFICATION
273 {
274 internal int cb;
275 internal IntPtr psz1;
276 internal IntPtr psz2;
277 internal IntPtr psz3;
278 internal IntPtr pv;
279
280 internal IntPtr hf_ptr;
281
282 internal short date;
283 internal short time;
284 internal short attribs;
285 internal short setID;
286 internal short iCabinet;
287 internal short iFolder;
288 internal int fdie;
289
290 // Unlike all the other file handles in FCI/FDI, this one is
291 // actually pointer-sized. Use a property to pretend it isn't.
292 internal int hf
293 {
294 get { return (int) this.hf_ptr; }
295 }
296 }
297
298 /// <summary>
299 /// Ensures that the FDI handle is safely released.
300 /// </summary>
301 internal class Handle : SafeHandle
302 {
303 /// <summary>
304 /// Creates a new unintialized handle. The handle will be initialized
305 /// when it is marshalled back from native code.
306 /// </summary>
307 internal Handle()
308 : base(IntPtr.Zero, true)
309 {
310 }
311
312 /// <summary>
313 /// Checks if the handle is invalid. An FDI handle is invalid when it is zero.
314 /// </summary>
315 public override bool IsInvalid
316 {
317 get
318 {
319 return this.handle == IntPtr.Zero;
320 }
321 }
322
323 /// <summary>
324 /// Releases the handle by calling FDIDestroy().
325 /// </summary>
326 /// <returns>True if the release succeeded.</returns>
327 protected override bool ReleaseHandle()
328 {
329 return FDI.Destroy(this.handle);
330 }
331 }
332 }
333
334 /// <summary>
335 /// Error info structure for FCI and FDI.
336 /// </summary>
337 /// <remarks>Before being passed to FCI or FDI, this structure is
338 /// pinned in memory via a GCHandle. The pinning is necessary
339 /// to be able to read the results, since the ERF structure doesn't
340 /// get marshalled back out after an error.</remarks>
341 [StructLayout(LayoutKind.Sequential)]
342 internal class ERF
343 {
344 private int erfOper;
345 private int erfType;
346 private int fError;
347
348 /// <summary>
349 /// Gets or sets the cabinet error code.
350 /// </summary>
351 internal int Oper
352 {
353 get
354 {
355 return this.erfOper;
356 }
357
358 set
359 {
360 this.erfOper = value;
361 }
362 }
363
364 /// <summary>
365 /// Gets or sets the Win32 error code.
366 /// </summary>
367 internal int Type
368 {
369 get
370 {
371 return this.erfType;
372 }
373
374 set
375 {
376 this.erfType = value;
377 }
378 }
379
380 /// <summary>
381 /// GCHandle doesn't like the bool type, so use an int underneath.
382 /// </summary>
383 internal bool Error
384 {
385 get
386 {
387 return this.fError != 0;
388 }
389
390 set
391 {
392 this.fError = value ? 1 : 0;
393 }
394 }
395
396 /// <summary>
397 /// Clears the error information.
398 /// </summary>
399 internal void Clear()
400 {
401 this.Oper = 0;
402 this.Type = 0;
403 this.Error = false;
404 }
405 }
406}
407}