1 // =========================================================================
2 //
3 // INTEL CONFIDENTIAL
4 // Copyright 2005 - 2015
5 // Intel Corporation All Rights Reserved.
6 //
7 // =========================================================================
8 // The source code contained or described herein and all documents
9 // related to the source code ("Material") are owned by Intel Corporation
10 // or its suppliers or licensors. Title to the Material remains with
11 // Intel Corporation or its suppliers and licensors. The Material contains
12 // trade secrets and proprietary and confidential information of Intel or
13 // its suppliers and licensors. The Material is protected by worldwide
14 // copyright and trade secret laws and treaty provisions. No part of the
15 // Material may be used, copied, reproduced, modified, published, uploaded,
16 // posted, transmitted, distributed, or disclosed in any way without Intel’s
17 // prior express written permission.
18 //
19 // No license under any patent, copyright, trade secret or other intellectual
20 // property right is granted to or conferred upon you by disclosure or
21 // delivery of the Materials, either expressly, by implication, inducement,
22 // estoppel or otherwise. Any license under such intellectual property rights
23 // must be express and approved by Intel in writing.
24 // ==========================================================================
25
26 using System;
27 using System.Collections.Generic;
28 using System.Diagnostics;
29 using System.IO;
30 using System.Linq;
31 using System.Reflection;
32 using System.Text;
33 using System.Threading;
34 using Microsoft.Deployment.Compression;
35 using Microsoft.Deployment.Compression.Cab;
36 using Microsoft.Tools.WindowsInstallerXml;
37 using Microsoft.Tools.WindowsInstallerXml.Bootstrapper;
38 using SysProcess = System.Diagnostics.Process;
39
40 namespace Intel.Deployment.Bootstrapper.Models
41 {
42 internal class ExtractModel : BaseModel
43 {
44 #region Events
45 public event EventHandler<ProgressEventArgs> Progress;
46 public event EventHandler<SuccessEventArgs> ExtractComplete;
47 #endregion
48
49 #region Fields
50 private string _BundleExe;
51 private string _BAAssemblyLocation;
52 private string _PayloadLocation;
53 #endregion
54
55 #region Properties
56 private string BundleExe
57 {
58 get
59 {
60 if (this._BundleExe == null)
61 {
62 this._BundleExe = SysProcess.GetCurrentProcess().MainModule.FileName;
63 Log.WriteLine("Retreived bundle exe file location: " + this._BundleExe);
64 }
65 return this._BundleExe;
66 }
67 }
68
69 private string BAAssemblyLocation
70 {
71 get
72 {
73 if (this._BAAssemblyLocation == null)
74 {
75 this._BAAssemblyLocation = Assembly.GetExecutingAssembly().Location;
76 Log.WriteLine("Retreived MBA assembly file location: " + this._BAAssemblyLocation);
77 }
78 return this._BAAssemblyLocation;
79 }
80 }
81 private string PayloadLocation
82 {
83 get
84 {
85 if (this._PayloadLocation == null)
86 {
(5) Event example_checked: |
Example 1: "System.IO.Directory.GetParent(this.BAAssemblyLocation)" has its value checked in "System.IO.Directory.GetParent(this.BAAssemblyLocation)". |
Also see events: |
[returned_null][null_method_call] |
87 this._PayloadLocation = Directory.GetParent(this.BAAssemblyLocation)?.FullName;
88 Log.WriteLine("Retreived payload location: " + this._PayloadLocation);
89 }
90 return this._PayloadLocation;
91 }
92 }
93 #endregion
94
95 #region Methods - Extract
96 public void BeginExtract(string location)
97 {
98 var thread = new Thread(() =>
99 {
100 try { this.Extract(location); }
101 catch (Exception ex) { Log.WriteException(ex); }
102 });
103 thread.Start();
104 }
105 public void Extract(string location)
106 {
107 int error = this.DoExtract(new Folder(location));
108
109 this.OnExtractComplete(error);
110 }
111 private int DoExtract(Folder folder)
112 {
113 try
114 {
115 //Unbind the msi packages to a temporary folder.
116 using (var unbindFolder = UnbindToTempFolder())
117 {
118 var msiFolder = unbindFolder.GetSubfolder("AttachedContainer");
119
120 foreach (var mapping in GetExtractionMappings(msiFolder))
121 {
122 var destination = folder.GetSubfolder(mapping.Destination);
123
124 string driversCabPath = Path.Combine(msiFolder.Path, mapping.CabFile);
125
126 RunExtractionAndDeleteCab(driversCabPath, destination.Path);
127 }
128 }
129
130 return Win32Error.Success;
131 }
132 catch (Exception exc)
133 {
134 Log.WriteException(exc);
135 return Error.Extract;
136 }
137 }
138 #endregion
139
140 #region Methods - ExtractMup
141 public void BeginExtractMup(string location)
142 {
143 var thread = new Thread(() =>
144 {
145 try { this.ExtractMup(location); }
146 catch (Exception ex) { Log.WriteException(ex); }
147 });
148 thread.Start();
149 }
150 public void ExtractMup(string location)
151 {
152 int error = this.DoExtractMup(new Folder(location));
153
154 this.OnExtractComplete(error);
155 }
156 private int DoExtractMup(Folder folder)
157 {
158 try
159 {
160 using (var tempFolder = TempFolder.Create())
161 {
162 DoExtract(tempFolder);
163
164 var allInfs = Directory.GetFiles(tempFolder.Path, "*.inf", SearchOption.AllDirectories);
165 var MupMapping = Intel.Tools.MSBuildTasks.CreateMup.MupHelper.GetMupMapping(allInfs);
166
167 foreach(var mupEntry in MupMapping)
168 {
169 string destinationPath = Path.Combine(folder.Path, mupEntry.Value);
170 Directory.CreateDirectory(Path.GetDirectoryName(destinationPath));
171 File.Copy(mupEntry.Key, destinationPath, true);
172 }
173 }
174
175 return Win32Error.Success;
176 }
177 catch (Exception exc)
178 {
179 Log.WriteException(exc);
180 return Error.Extract;
181 }
182 }
183 #endregion
184
185 #region Methods - Event Handlers
186 private void OnProgress(object sender, ArchiveProgressEventArgs e)
187 {
188 lock (this)
189 {
190 try
191 {
192 this.OnProgress((int)(100 * ((double)e.FileBytesProcessed / (double)e.TotalFileBytes)));
193 }
194 //Catch any exceptions, progress bars can safely be ignored.
195 catch { }
196 }
197 }
198
199 private void OnProgress(int progress)
200 {
201 var handler = this.Progress;
202 if (handler != null)
203 {
204 handler(this, new ProgressEventArgs(progress, progress));
205 }
206 }
207
208 private void OnExtractComplete(int error)
209 {
210 Log.WriteLine("Extraction complete. error: '{0}'", error);
211
212 var handler = this.ExtractComplete;
213 if (handler != null)
214 {
215 handler(this, new SuccessEventArgs(error));
216 }
217 }
218 #endregion
219
220 #region Methods - Helpers
221 private TempFolder UnbindToTempFolder()
222 {
223 //Get a temporary location.
224 var tempFolder = TempFolder.Create();
225 Log.WriteLine("Unbinding to temporary folder: " + tempFolder.Path);
226 string attachedContainerSource = this.Engine.StringVariables["WixBundleOriginalSource"];
227 Log.WriteLine("Unbinding from: " + attachedContainerSource);
228
229 //Extract to the temporary location.
230 var unbinder = new Unbinder();
231 unbinder.Unbind(attachedContainerSource, OutputType.Bundle, tempFolder.Path);
232 unbinder.DeleteTempFiles();
233
234 Log.WriteLine("Completed unbinding.");
235 return tempFolder;
236 }
237
238 private List<ExtractionMapping> GetExtractionMappings(Folder msiFolder)
239 {
240 string key, value,
241 valueDest, valueCab, valueCondition;
242 string[] valueSplit,
243 msiFiles = msiFolder.GetFiles(false);
244 var list = new List<ExtractionMapping>();
245
246 foreach (var msiFile in msiFiles)
247 {
248 key = string.Format("IIF_ExtractionMapping_{0}", Path.GetFileName(msiFile));
249
250 if (this.Engine.StringVariables.Contains(key))
251 {
252 value = this.Engine.StringVariables[key];
253 valueSplit = value.Split(new[] { ';' });
254
255 if (valueSplit.Length != 3 || string.IsNullOrEmpty(valueSplit[1]))
256 {
257 throw new Exception("Incorrectly formed extraction mapping: " + value);
258 }
259
260 valueDest = valueSplit[0].Trim();
261 valueCab = valueSplit[1].Trim();
262 valueCondition = valueSplit[2].Trim();
263
264 if (string.IsNullOrEmpty(valueCondition)) valueCondition = "1"; //True
265
266 if (this.Engine.EvaluateCondition(valueCondition))
267 {
268 list.Add(new ExtractionMapping(msiFile, valueDest, valueCab));
269 }
270 }
271 }
272
273 return list;
274 }
275
276 private void RunExtractionAndDeleteCab(string cabFile, string destination)
277 {
278 //If the driver cab file exists...
279 if (File.Exists(cabFile))
280 {
281 Log.WriteLine("Unpacking cab: " + cabFile);
282 var cabInfo = new CabInfo(cabFile);
283 cabInfo.Unpack(destination, OnProgress);
284
285 Log.WriteLine("Deleting file: " + cabFile);
286 File.Delete(cabFile);
287 }
288 else
289 {
290 //...otherwise, extract the drivers from the msi database file as though it is the cab itself.
291 throw new FileNotFoundException("Drivers cab file not found: " + cabFile);
292 }
293 }
294
295 private struct ExtractionMapping
296 {
297 public string MsiFile;
298 public string Destination;
299 public string CabFile;
300
301 public ExtractionMapping(string msiFile, string destination, string cabFile)
302 {
303 this.MsiFile = msiFile;
304 this.Destination = destination;
305 this.CabFile = cabFile;
306 }
307 }
308 #endregion
309 }
310 }
311