@joebigelow / wix-1 / commits / 052cc1fa

Remove dead code

Rob Mensching committed Jun 10, 2020 at 07:44 UTC 052cc1fac3bf9b6ff2b1cb264410d76d9f35f21e
2 files changed -1510
src/WixToolset.Core.WindowsInstaller/Patch.cs deleted
-1239
@@ -1,1239 +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 -#if DELETE
4 -
5 -namespace WixToolset.Data
6 -{
7 - using System;
8 - using System.Collections.Generic;
9 - using System.Diagnostics.CodeAnalysis;
10 - using WixToolset.Core.WindowsInstaller;
11 - using WixToolset.Data.WindowsInstaller;
12 - using WixToolset.Extensibility;
13 -
14 - /// <summary>
15 - /// Contains output tables and logic for building an MSP package.
16 - /// </summary>
17 - public class Patch
18 - {
19 - private List<IInspectorExtension> inspectorExtensions;
20 - private WindowsInstallerData patch;
21 - private TableDefinitionCollection tableDefinitions;
22 -
23 - public WindowsInstallerData PatchOutput
24 - {
25 - get { return this.patch; }
26 - }
27 -
28 - public Patch()
29 - {
30 - this.inspectorExtensions = new List<IInspectorExtension>();
31 - this.tableDefinitions = new TableDefinitionCollection(WindowsInstallerStandardInternal.GetTableDefinitions());
32 - }
33 -
34 - /// <summary>
35 - /// Adds an extension.
36 - /// </summary>
37 - /// <param name="extension">The extension to add.</param>
38 - public void AddExtension(IInspectorExtension extension)
39 - {
40 - this.inspectorExtensions.Add(extension);
41 - }
42 -
43 - public void Load(string patchPath)
44 - {
45 - this.patch = WindowsInstallerData.Load(patchPath, false);
46 - }
47 -
48 - /// <summary>
49 - /// Include transforms in a patch.
50 - /// </summary>
51 - /// <param name="transforms">List of transforms to attach.</param>
52 - [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")]
53 - public void AttachTransforms(List<PatchTransform> transforms)
54 - {
55 - // Track if at least one transform gets attached.
56 - bool attachedTransform = false;
57 -
58 - if (transforms == null || transforms.Count == 0)
59 - {
60 - throw new WixException(WixErrors.PatchWithoutTransforms());
61 - }
62 -
63 - // Get the patch id from the WixPatchId table.
64 - string patchId = null;
65 - string clientPatchId = null;
66 - Table wixPatchIdTable = this.patch.Tables["WixPatchId"];
67 - if (null != wixPatchIdTable && 0 < wixPatchIdTable.Rows.Count)
68 - {
69 - Row patchIdRow = wixPatchIdTable.Rows[0];
70 - if (null != patchIdRow)
71 - {
72 - patchId = patchIdRow[0].ToString();
73 - clientPatchId = patchIdRow[1].ToString();
74 - }
75 - }
76 -
77 - if (null == patchId)
78 - {
79 - throw new WixException(WixErrors.ExpectedPatchIdInWixMsp());
80 - }
81 - if (null == clientPatchId)
82 - {
83 - throw new WixException(WixErrors.ExpectedClientPatchIdInWixMsp());
84 - }
85 -
86 - // enumerate patch.Media to map diskId to Media row
87 - Table patchMediaTable = patch.Tables["Media"];
88 -
89 - if (null == patchMediaTable || patchMediaTable.Rows.Count == 0)
90 - {
91 - throw new WixException(WixErrors.ExpectedMediaRowsInWixMsp());
92 - }
93 -
94 - Hashtable mediaRows = new Hashtable(patchMediaTable.Rows.Count);
95 - foreach (MediaRow row in patchMediaTable.Rows)
96 - {
97 - int media = row.DiskId;
98 - mediaRows[media] = row;
99 - }
100 -
101 - // enumerate patch.WixPatchBaseline to map baseline to diskId
102 - Table patchBaselineTable = patch.Tables["WixPatchBaseline"];
103 -
104 - int numPatchBaselineRows = (null != patchBaselineTable) ? patchBaselineTable.Rows.Count : 0;
105 -
106 - Hashtable baselineMedia = new Hashtable(numPatchBaselineRows);
107 - if (patchBaselineTable != null)
108 - {
109 - foreach (Row row in patchBaselineTable.Rows)
110 - {
111 - string baseline = (string)row[0];
112 - int media = (int)row[1];
113 - int validationFlags = (int)row[2];
114 - if (baselineMedia.Contains(baseline))
115 - {
116 - this.OnMessage(WixErrors.SamePatchBaselineId(row.SourceLineNumbers, baseline));
117 - }
118 - baselineMedia[baseline] = new int[] { media, validationFlags };
119 - }
120 - }
121 -
122 - // populate MSP summary information
123 - Table patchSummaryInfo = patch.EnsureTable(this.tableDefinitions["_SummaryInformation"]);
124 -
125 - // Remove properties that will be calculated or are reserved.
126 - for (int i = patchSummaryInfo.Rows.Count - 1; i >= 0; i--)
127 - {
128 - Row row = patchSummaryInfo.Rows[i];
129 - switch ((SummaryInformation.Patch)row[0])
130 - {
131 - case SummaryInformation.Patch.ProductCodes:
132 - case SummaryInformation.Patch.TransformNames:
133 - case SummaryInformation.Patch.PatchCode:
134 - case SummaryInformation.Patch.InstallerRequirement:
135 - case SummaryInformation.Patch.Reserved11:
136 - case SummaryInformation.Patch.Reserved14:
137 - case SummaryInformation.Patch.Reserved16:
138 - patchSummaryInfo.Rows.RemoveAt(i);
139 - break;
140 - }
141 - }
142 -
143 - // Index remaining summary properties.
144 - SummaryInfoRowCollection summaryInfo = new SummaryInfoRowCollection(patchSummaryInfo);
145 -
146 - // PID_CODEPAGE
147 - if (!summaryInfo.Contains((int)SummaryInformation.Patch.CodePage))
148 - {
149 - // set the code page by default to the same code page for the
150 - // string pool in the database.
151 - Row codePage = patchSummaryInfo.CreateRow(null);
152 - codePage[0] = (int)SummaryInformation.Patch.CodePage;
153 - codePage[1] = this.patch.Codepage.ToString(CultureInfo.InvariantCulture);
154 - }
155 -
156 - // GUID patch code for the patch.
157 - Row revisionRow = patchSummaryInfo.CreateRow(null);
158 - revisionRow[0] = (int)SummaryInformation.Patch.PatchCode;
159 - revisionRow[1] = patchId;
160 -
161 - // Indicates the minimum Windows Installer version that is required to install the patch.
162 - Row wordsRow = patchSummaryInfo.CreateRow(null);
163 - wordsRow[0] = (int)SummaryInformation.Patch.InstallerRequirement;
164 - wordsRow[1] = ((int)SummaryInformation.InstallerRequirement.Version31).ToString(CultureInfo.InvariantCulture);
165 -
166 - if (!summaryInfo.Contains((int)SummaryInformation.Patch.Security))
167 - {
168 - Row security = patchSummaryInfo.CreateRow(null);
169 - security[0] = (int)SummaryInformation.Patch.Security;
170 - security[1] = "4"; // Read-only enforced
171 - }
172 -
173 - // use authored comments or default to DisplayName (required)
174 - string comments = null;
175 -
176 - Table msiPatchMetadataTable = patch.Tables["MsiPatchMetadata"];
177 - Hashtable metadataTable = new Hashtable();
178 - if (null != msiPatchMetadataTable)
179 - {
180 - foreach (Row row in msiPatchMetadataTable.Rows)
181 - {
182 - metadataTable.Add(row.Fields[1].Data.ToString(), row.Fields[2].Data.ToString());
183 - }
184 -
185 - if (!summaryInfo.Contains((int)SummaryInformation.Patch.Title) && metadataTable.Contains("DisplayName"))
186 - {
187 - string displayName = (string)metadataTable["DisplayName"];
188 -
189 - Row title = patchSummaryInfo.CreateRow(null);
190 - title[0] = (int)SummaryInformation.Patch.Title;
191 - title[1] = displayName;
192 -
193 - // default comments use DisplayName as-is (no loc)
194 - comments = displayName;
195 - }
196 -
197 - if (!summaryInfo.Contains((int)SummaryInformation.Patch.CodePage) && metadataTable.Contains("CodePage"))
198 - {
199 - Row codePage = patchSummaryInfo.CreateRow(null);
200 - codePage[0] = (int)SummaryInformation.Patch.CodePage;
201 - codePage[1] = metadataTable["CodePage"];
202 - }
203 -
204 - if (!summaryInfo.Contains((int)SummaryInformation.Patch.PackageName) && metadataTable.Contains("Description"))
205 - {
206 - Row subject = patchSummaryInfo.CreateRow(null);
207 - subject[0] = (int)SummaryInformation.Patch.PackageName;
208 - subject[1] = metadataTable["Description"];
209 - }
210 -
211 - if (!summaryInfo.Contains((int)SummaryInformation.Patch.Manufacturer) && metadataTable.Contains("ManufacturerName"))
212 - {
213 - Row author = patchSummaryInfo.CreateRow(null);
214 - author[0] = (int)SummaryInformation.Patch.Manufacturer;
215 - author[1] = metadataTable["ManufacturerName"];
216 - }
217 - }
218 -
219 - // special metadata marshalled through the build
220 - Table wixPatchMetadataTable = patch.Tables["WixPatchMetadata"];
221 - Hashtable wixMetadataTable = new Hashtable();
222 - if (null != wixPatchMetadataTable)
223 - {
224 - foreach (Row row in wixPatchMetadataTable.Rows)
225 - {
226 - wixMetadataTable.Add(row.Fields[0].Data.ToString(), row.Fields[1].Data.ToString());
227 - }
228 -
229 - if (wixMetadataTable.Contains("Comments"))
230 - {
231 - comments = (string)wixMetadataTable["Comments"];
232 - }
233 - }
234 -
235 - // write the package comments to summary info
236 - if (!summaryInfo.Contains((int)SummaryInformation.Patch.Comments) && null != comments)
237 - {
238 - Row commentsRow = patchSummaryInfo.CreateRow(null);
239 - commentsRow[0] = (int)SummaryInformation.Patch.Comments;
240 - commentsRow[1] = comments;
241 - }
242 -
243 - // enumerate transforms
244 - Dictionary<string, object> productCodes = new Dictionary<string, object>();
245 - ArrayList transformNames = new ArrayList();
246 - ArrayList validTransform = new ArrayList();
247 - int transformCount = 0;
248 - foreach (PatchTransform mainTransform in transforms)
249 - {
250 - string baseline = null;
251 - int media = -1;
252 - int validationFlags = 0;
253 -
254 - if (baselineMedia.Contains(mainTransform.Baseline))
255 - {
256 - int[] baselineData = (int[])baselineMedia[mainTransform.Baseline];
257 - int newMedia = baselineData[0];
258 - if (media != -1 && media != newMedia)
259 - {
260 - throw new InvalidOperationException(String.Format(CultureInfo.CurrentUICulture, WixStrings.EXP_TransformAuthoredIntoMultipleMedia, media, newMedia));
261 - }
262 - baseline = mainTransform.Baseline;
263 - media = newMedia;
264 - validationFlags = baselineData[1];
265 - }
266 -
267 - if (media == -1)
268 - {
269 - // transform's baseline not attached to any Media
270 - continue;
271 - }
272 -
273 - Table patchRefTable = patch.Tables["WixPatchRef"];
274 - if (patchRefTable != null && patchRefTable.Rows.Count > 0)
275 - {
276 - if (!Patch.ReduceTransform(mainTransform.Transform, patchRefTable))
277 - {
278 - // transform has none of the content authored into this patch
279 - continue;
280 - }
281 - }
282 -
283 - // Validate the transform doesn't break any patch specific rules.
284 - mainTransform.Validate();
285 -
286 - // ensure consistent File.Sequence within each Media
287 - MediaRow mediaRow = (MediaRow)mediaRows[media];
288 -
289 - // Ensure that files are sequenced after the last file in any transform.
290 - Table transformMediaTable = mainTransform.Transform.Tables["Media"];
291 - if (null != transformMediaTable && 0 < transformMediaTable.Rows.Count)
292 - {
293 - foreach (MediaRow transformMediaRow in transformMediaTable.Rows)
294 - {
295 - if (mediaRow.LastSequence < transformMediaRow.LastSequence)
296 - {
297 - // The Binder will pre-increment the sequence.
298 - mediaRow.LastSequence = transformMediaRow.LastSequence;
299 - }
300 - }
301 - }
302 -
303 - // Use the Media/@DiskId if greater for backward compatibility.
304 - if (mediaRow.LastSequence < mediaRow.DiskId)
305 - {
306 - mediaRow.LastSequence = mediaRow.DiskId;
307 - }
308 -
309 - // ignore media table from transform.
310 - mainTransform.Transform.Tables.Remove("Media");
311 - mainTransform.Transform.Tables.Remove("WixMedia");
312 - mainTransform.Transform.Tables.Remove("MsiDigitalSignature");
313 -
314 - string productCode;
315 - Output pairedTransform = this.BuildPairedTransform(patchId, clientPatchId, mainTransform.Transform, mediaRow, validationFlags, out productCode);
316 - productCodes[productCode] = null;
317 - DictionaryEntry entry = new DictionaryEntry();
318 - entry.Key = productCode;
319 - entry.Value = mainTransform.Transform;
320 - validTransform.Add(entry);
321 -
322 - // attach these transforms to the patch object
323 - // TODO: is this an acceptable way to auto-generate transform stream names?
324 - string transformName = baseline + "." + (++transformCount).ToString(CultureInfo.InvariantCulture);
325 - patch.SubStorages.Add(new SubStorage(transformName, mainTransform.Transform));
326 - patch.SubStorages.Add(new SubStorage("#" + transformName, pairedTransform));
327 - transformNames.Add(":" + transformName);
328 - transformNames.Add(":#" + transformName);
329 - attachedTransform = true;
330 - }
331 -
332 - if (!attachedTransform)
333 - {
334 - throw new WixException(WixErrors.PatchWithoutValidTransforms());
335 - }
336 -
337 - // Validate that a patch authored as removable is actually removable
338 - if (metadataTable.Contains("AllowRemoval"))
339 - {
340 - if ("1" == metadataTable["AllowRemoval"].ToString())
341 - {
342 - ArrayList tables = Patch.GetPatchUninstallBreakingTables();
343 - bool result = true;
344 - foreach (DictionaryEntry entry in validTransform)
345 - {
346 - result &= this.CheckUninstallableTransform(entry.Key.ToString(), (Output)entry.Value, tables);
347 - }
348 -
349 - if (!result)
350 - {
351 - throw new WixException(WixErrors.PatchNotRemovable());
352 - }
353 - }
354 - }
355 -
356 - // Finish filling tables with transform-dependent data.
357 - // Semicolon delimited list of the product codes that can accept the patch.
358 - Table wixPatchTargetTable = patch.Tables["WixPatchTarget"];
359 - if (null != wixPatchTargetTable)
360 - {
361 - Dictionary<string, object> targets = new Dictionary<string, object>();
362 - bool replace = true;
363 - foreach (Row wixPatchTargetRow in wixPatchTargetTable.Rows)
364 - {
365 - string target = wixPatchTargetRow[0].ToString();
366 - if (0 == String.CompareOrdinal("*", target))
367 - {
368 - replace = false;
369 - }
370 - else
371 - {
372 - targets[target] = null;
373 - }
374 - }
375 -
376 - // Replace the target ProductCodes with the authored list.
377 - if (replace)
378 - {
379 - productCodes = targets;
380 - }
381 - else
382 - {
383 - // Copy the authored target ProductCodes into the list.
384 - foreach (string target in targets.Keys)
385 - {
386 - productCodes[target] = null;
387 - }
388 - }
389 - }
390 -
391 - string[] uniqueProductCodes = new string[productCodes.Keys.Count];
392 - productCodes.Keys.CopyTo(uniqueProductCodes, 0);
393 -
394 - Row templateRow = patchSummaryInfo.CreateRow(null);
395 - templateRow[0] = (int)SummaryInformation.Patch.ProductCodes;
396 - templateRow[1] = String.Join(";", uniqueProductCodes);
397 -
398 - // Semicolon delimited list of transform substorage names in the order they are applied.
399 - Row savedbyRow = patchSummaryInfo.CreateRow(null);
400 - savedbyRow[0] = (int)SummaryInformation.Patch.TransformNames;
401 - savedbyRow[1] = String.Join(";", (string[])transformNames.ToArray(typeof(string)));
402 - }
403 -
404 - /// <summary>
405 - /// Ensure transform is uninstallable.
406 - /// </summary>
407 - /// <param name="productCode">Product code in transform.</param>
408 - /// <param name="transform">Transform generated by torch.</param>
409 - /// <param name="tables">Tables to be checked</param>
410 - /// <returns>True if the transform is uninstallable</returns>
411 - private bool CheckUninstallableTransform(string productCode, Output transform, ArrayList tables)
412 - {
413 - bool ret = true;
414 - foreach (string table in tables)
415 - {
416 - Table wixTable = transform.Tables[table];
417 - if (null != wixTable)
418 - {
419 - foreach (Row row in wixTable.Rows)
420 - {
421 - if (row.Operation == RowOperation.Add)
422 - {
423 - ret = false;
424 - string primaryKey = row.GetPrimaryKey('/');
425 - if (null == primaryKey)
426 - {
427 - primaryKey = string.Empty;
428 - }
429 - this.OnMessage(WixErrors.NewRowAddedInTable(row.SourceLineNumbers, productCode, wixTable.Name, primaryKey));
430 - }
431 - }
432 - }
433 - }
434 -
435 - return ret;
436 - }
437 -
438 - /// <summary>
439 - /// Tables affect patch uninstall.
440 - /// </summary>
441 - /// <returns>list of tables to be checked</returns>
442 - private static ArrayList GetPatchUninstallBreakingTables()
443 - {
444 - ArrayList tables = new ArrayList();
445 - tables.Add("AppId");
446 - tables.Add("BindImage");
447 - tables.Add("Class");
448 - tables.Add("Complus");
449 - tables.Add("CreateFolder");
450 - tables.Add("DuplicateFile");
451 - tables.Add("Environment");
452 - tables.Add("Extension");
453 - tables.Add("Font");
454 - tables.Add("IniFile");
455 - tables.Add("IsolatedComponent");
456 - tables.Add("LockPermissions");
457 - tables.Add("MIME");
458 - tables.Add("MoveFile");
459 - tables.Add("MsiLockPermissionsEx");
460 - tables.Add("MsiServiceConfig");
461 - tables.Add("MsiServiceConfigFailureActions");
462 - tables.Add("ODBCAttribute");
463 - tables.Add("ODBCDataSource");
464 - tables.Add("ODBCDriver");
465 - tables.Add("ODBCSourceAttribute");
466 - tables.Add("ODBCTranslator");
467 - tables.Add("ProgId");
468 - tables.Add("PublishComponent");
469 - tables.Add("RemoveIniFile");
470 - tables.Add("SelfReg");
471 - tables.Add("ServiceControl");
472 - tables.Add("ServiceInstall");
473 - tables.Add("TypeLib");
474 - tables.Add("Verb");
475 -
476 - return tables;
477 - }
478 -
479 - /// <summary>
480 - /// Reduce the transform according to the patch references.
481 - /// </summary>
482 - /// <param name="transform">transform generated by torch.</param>
483 - /// <param name="patchRefTable">Table contains patch family filter.</param>
484 - /// <returns>true if the transform is not empty</returns>
485 - public static bool ReduceTransform(Output transform, Table patchRefTable)
486 - {
487 - // identify sections to keep
488 - Hashtable oldSections = new Hashtable(patchRefTable.Rows.Count);
489 - Hashtable newSections = new Hashtable(patchRefTable.Rows.Count);
490 - Hashtable tableKeyRows = new Hashtable();
491 - ArrayList sequenceList = new ArrayList();
492 - Hashtable componentFeatureAddsIndex = new Hashtable();
493 - Hashtable customActionTable = new Hashtable();
494 - Hashtable directoryTableAdds = new Hashtable();
495 - Hashtable featureTableAdds = new Hashtable();
496 - Hashtable keptComponents = new Hashtable();
497 - Hashtable keptDirectories = new Hashtable();
498 - Hashtable keptFeatures = new Hashtable();
499 - Hashtable keptLockPermissions = new Hashtable();
500 - Hashtable keptMsiLockPermissionExs = new Hashtable();
501 -
502 - Dictionary<string, List<string>> componentCreateFolderIndex = new Dictionary<string, List<string>>();
503 - Dictionary<string, List<Row>> directoryLockPermissionsIndex = new Dictionary<string, List<Row>>();
504 - Dictionary<string, List<Row>> directoryMsiLockPermissionsExIndex = new Dictionary<string, List<Row>>();
505 -
506 - foreach (Row patchRefRow in patchRefTable.Rows)
507 - {
508 - string tableName = (string)patchRefRow[0];
509 - string key = (string)patchRefRow[1];
510 -
511 - // Short circuit filtering if all changes should be included.
512 - if ("*" == tableName && "*" == key)
513 - {
514 - Patch.RemoveProductCodeFromTransform(transform);
515 - return true;
516 - }
517 -
518 - Table table = transform.Tables[tableName];
519 - if (table == null)
520 - {
521 - // table not found
522 - continue;
523 - }
524 -
525 - // index this table
526 - if (!tableKeyRows.Contains(tableName))
527 - {
528 - Hashtable newKeyRows = new Hashtable();
529 - foreach (Row newRow in table.Rows)
530 - {
531 - newKeyRows[newRow.GetPrimaryKey('/')] = newRow;
532 - }
533 - tableKeyRows[tableName] = newKeyRows;
534 - }
535 - Hashtable keyRows = (Hashtable)tableKeyRows[tableName];
536 -
537 - Row row = (Row)keyRows[key];
538 - if (row == null)
539 - {
540 - // row not found
541 - continue;
542 - }
543 -
544 - // Differ.sectionDelimiter
545 - string[] sections = row.SectionId.Split('/');
546 - oldSections[sections[0]] = row;
547 - newSections[sections[1]] = row;
548 - }
549 -
550 - // throw away sections not referenced
551 - int keptRows = 0;
552 - Table directoryTable = null;
553 - Table featureTable = null;
554 - Table lockPermissionsTable = null;
555 - Table msiLockPermissionsTable = null;
556 -
557 - foreach (Table table in transform.Tables)
558 - {
559 - if ("_SummaryInformation" == table.Name)
560 - {
561 - continue;
562 - }
563 -
564 - if (table.Name == "AdminExecuteSequence"
565 - || table.Name == "AdminUISequence"
566 - || table.Name == "AdvtExecuteSequence"
567 - || table.Name == "InstallUISequence"
568 - || table.Name == "InstallExecuteSequence")
569 - {
570 - sequenceList.Add(table);
571 - continue;
572 - }
573 -
574 - for (int i = 0; i < table.Rows.Count; i++)
575 - {
576 - Row row = table.Rows[i];
577 -
578 - if (table.Name == "CreateFolder")
579 - {
580 - string createFolderComponentId = (string)row[1];
581 -
582 - List<string> directoryList;
583 - if (!componentCreateFolderIndex.TryGetValue(createFolderComponentId, out directoryList))
584 - {
585 - directoryList = new List<string>();
586 - componentCreateFolderIndex.Add(createFolderComponentId, directoryList);
587 - }
588 -
589 - directoryList.Add((string)row[0]);
590 - }
591 -
592 - if (table.Name == "CustomAction")
593 - {
594 - customActionTable.Add(row[0], row);
595 - }
596 -
597 - if (table.Name == "Directory")
598 - {
599 - directoryTable = table;
600 - if (RowOperation.Add == row.Operation)
601 - {
602 - directoryTableAdds.Add(row[0], row);
603 - }
604 - }
605 -
606 - if (table.Name == "Feature")
607 - {
608 - featureTable = table;
609 - if (RowOperation.Add == row.Operation)
610 - {
611 - featureTableAdds.Add(row[0], row);
612 - }
613 - }
614 -
615 - if (table.Name == "FeatureComponents")
616 - {
617 - if (RowOperation.Add == row.Operation)
618 - {
619 - string featureId = (string)row[0];
620 - string componentId = (string)row[1];
621 -
622 - if (componentFeatureAddsIndex.ContainsKey(componentId))
623 - {
624 - ArrayList featureList = (ArrayList)componentFeatureAddsIndex[componentId];
625 - featureList.Add(featureId);
626 - }
627 - else
628 - {
629 - ArrayList featureList = new ArrayList();
630 - componentFeatureAddsIndex.Add(componentId, featureList);
631 - featureList.Add(featureId);
632 - }
633 - }
634 - }
635 -
636 - if (table.Name == "LockPermissions")
637 - {
638 - lockPermissionsTable = table;
639 - if ("CreateFolder" == (string)row[1])
640 - {
641 - string directoryId = (string)row[0];
642 -
643 - List<Row> rowList;
644 - if (!directoryLockPermissionsIndex.TryGetValue(directoryId, out rowList))
645 - {
646 - rowList = new List<Row>();
647 - directoryLockPermissionsIndex.Add(directoryId, rowList);
648 - }
649 -
650 - rowList.Add(row);
651 - }
652 - }
653 -
654 - if (table.Name == "MsiLockPermissionsEx")
655 - {
656 - msiLockPermissionsTable = table;
657 - if ("CreateFolder" == (string)row[1])
658 - {
659 - string directoryId = (string)row[0];
660 -
661 - List<Row> rowList;
662 - if (!directoryMsiLockPermissionsExIndex.TryGetValue(directoryId, out rowList))
663 - {
664 - rowList = new List<Row>();
665 - directoryMsiLockPermissionsExIndex.Add(directoryId, rowList);
666 - }
667 -
668 - rowList.Add(row);
669 - }
670 - }
671 -
672 - if (null == row.SectionId)
673 - {
674 - table.Rows.RemoveAt(i);
675 - i--;
676 - }
677 - else
678 - {
679 - string[] sections = row.SectionId.Split('/');
680 - // ignore the row without section id.
681 - if (0 == sections[0].Length && 0 == sections[1].Length)
682 - {
683 - table.Rows.RemoveAt(i);
684 - i--;
685 - }
686 - else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
687 - {
688 - if ("Component" == table.Name)
689 - {
690 - keptComponents.Add((string)row[0], row);
691 - }
692 -
693 - if ("Directory" == table.Name)
694 - {
695 - keptDirectories.Add(row[0], row);
696 - }
697 -
698 - if ("Feature" == table.Name)
699 - {
700 - keptFeatures.Add(row[0], row);
701 - }
702 -
703 - keptRows++;
704 - }
705 - else
706 - {
707 - table.Rows.RemoveAt(i);
708 - i--;
709 - }
710 - }
711 - }
712 - }
713 -
714 - keptRows += ReduceTransformSequenceTable(sequenceList, oldSections, newSections, customActionTable);
715 -
716 - if (null != directoryTable)
717 - {
718 - foreach (Row componentRow in keptComponents.Values)
719 - {
720 - string componentId = (string)componentRow[0];
721 -
722 - if (RowOperation.Add == componentRow.Operation)
723 - {
724 - // make sure each added component has its required directory and feature heirarchy.
725 - string directoryId = (string)componentRow[2];
726 - while (null != directoryId && directoryTableAdds.ContainsKey(directoryId))
727 - {
728 - Row directoryRow = (Row)directoryTableAdds[directoryId];
729 -
730 - if (!keptDirectories.ContainsKey(directoryId))
731 - {
732 - directoryTable.Rows.Add(directoryRow);
733 - keptDirectories.Add(directoryRow[0], null);
734 - keptRows++;
735 - }
736 -
737 - directoryId = (string)directoryRow[1];
738 - }
739 -
740 - if (componentFeatureAddsIndex.ContainsKey(componentId))
741 - {
742 - foreach (string featureId in (ArrayList)componentFeatureAddsIndex[componentId])
743 - {
744 - string currentFeatureId = featureId;
745 - while (null != currentFeatureId && featureTableAdds.ContainsKey(currentFeatureId))
746 - {
747 - Row featureRow = (Row)featureTableAdds[currentFeatureId];
748 -
749 - if (!keptFeatures.ContainsKey(currentFeatureId))
750 - {
751 - featureTable.Rows.Add(featureRow);
752 - keptFeatures.Add(featureRow[0], null);
753 - keptRows++;
754 - }
755 -
756 - currentFeatureId = (string)featureRow[1];
757 - }
758 - }
759 - }
760 - }
761 -
762 - // Hook in changes LockPermissions and MsiLockPermissions for folders for each component that has been kept.
763 - foreach (string keptComponentId in keptComponents.Keys)
764 - {
765 - List<string> directoryList;
766 - if (componentCreateFolderIndex.TryGetValue(keptComponentId, out directoryList))
767 - {
768 - foreach (string directoryId in directoryList)
769 - {
770 - List<Row> lockPermissionsRowList;
771 - if (directoryLockPermissionsIndex.TryGetValue(directoryId, out lockPermissionsRowList))
772 - {
773 - foreach (Row lockPermissionsRow in lockPermissionsRowList)
774 - {
775 - string key = lockPermissionsRow.GetPrimaryKey('/');
776 - if (!keptLockPermissions.ContainsKey(key))
777 - {
778 - lockPermissionsTable.Rows.Add(lockPermissionsRow);
779 - keptLockPermissions.Add(key, null);
780 - keptRows++;
781 - }
782 - }
783 - }
784 -
785 - List<Row> msiLockPermissionsExRowList;
786 - if (directoryMsiLockPermissionsExIndex.TryGetValue(directoryId, out msiLockPermissionsExRowList))
787 - {
788 - foreach (Row msiLockPermissionsExRow in msiLockPermissionsExRowList)
789 - {
790 - string key = msiLockPermissionsExRow.GetPrimaryKey('/');
791 - if (!keptMsiLockPermissionExs.ContainsKey(key))
792 - {
793 - msiLockPermissionsTable.Rows.Add(msiLockPermissionsExRow);
794 - keptMsiLockPermissionExs.Add(key, null);
795 - keptRows++;
796 - }
797 - }
798 - }
799 - }
800 - }
801 - }
802 - }
803 - }
804 -
805 - keptRows += ReduceTransformSequenceTable(sequenceList, oldSections, newSections, customActionTable);
806 -
807 - // Delete tables that are empty.
808 - ArrayList tablesToDelete = new ArrayList();
809 - foreach (Table table in transform.Tables)
810 - {
811 - if (0 == table.Rows.Count)
812 - {
813 - tablesToDelete.Add(table.Name);
814 - }
815 - }
816 -
817 - // delete separately to avoid messing up enumeration
818 - foreach (string tableName in tablesToDelete)
819 - {
820 - transform.Tables.Remove(tableName);
821 - }
822 -
823 - return keptRows > 0;
824 - }
825 -
826 - /// <summary>
827 - /// Remove the ProductCode property from the transform.
828 - /// </summary>
829 - /// <param name="transform">The transform.</param>
830 - /// <remarks>
831 - /// Changing the ProductCode is not supported in a patch.
832 - /// </remarks>
833 - private static void RemoveProductCodeFromTransform(Output transform)
834 - {
835 - Table propertyTable = transform.Tables["Property"];
836 - if (null != propertyTable)
837 - {
838 - for (int i = 0; i < propertyTable.Rows.Count; ++i)
839 - {
840 - Row propertyRow = propertyTable.Rows[i];
841 - string property = (string)propertyRow[0];
842 -
843 - if ("ProductCode" == property)
844 - {
845 - propertyTable.Rows.RemoveAt(i);
846 - break;
847 - }
848 - }
849 - }
850 - }
851 -
852 - /// <summary>
853 - /// Check if the section is in a PatchFamily.
854 - /// </summary>
855 - /// <param name="oldSection">Section id in target wixout</param>
856 - /// <param name="newSection">Section id in upgrade wixout</param>
857 - /// <param name="oldSections">Hashtable contains section id should be kept in the baseline wixout.</param>
858 - /// <param name="newSections">Hashtable contains section id should be kept in the upgrade wixout.</param>
859 - /// <returns>true if section in patch family</returns>
860 - private static bool IsInPatchFamily(string oldSection, string newSection, Hashtable oldSections, Hashtable newSections)
861 - {
862 - bool result = false;
863 -
864 - if ((String.IsNullOrEmpty(oldSection) && newSections.Contains(newSection)) || (String.IsNullOrEmpty(newSection) && oldSections.Contains(oldSection)))
865 - {
866 - result = true;
867 - }
868 - else if (!String.IsNullOrEmpty(oldSection) && !String.IsNullOrEmpty(newSection) && (oldSections.Contains(oldSection) || newSections.Contains(newSection)))
869 - {
870 - result = true;
871 - }
872 -
873 - return result;
874 - }
875 -
876 - /// <summary>
877 - /// Reduce the transform sequence tables.
878 - /// </summary>
879 - /// <param name="sequenceList">ArrayList of tables to be reduced</param>
880 - /// <param name="oldSections">Hashtable contains section id should be kept in the baseline wixout.</param>
881 - /// <param name="newSections">Hashtable contains section id should be kept in the target wixout.</param>
882 - /// <param name="customAction">Hashtable contains all the rows in the CustomAction table.</param>
883 - /// <returns>Number of rows left</returns>
884 - private static int ReduceTransformSequenceTable(ArrayList sequenceList, Hashtable oldSections, Hashtable newSections, Hashtable customAction)
885 - {
886 - int keptRows = 0;
887 -
888 - foreach (Table currentTable in sequenceList)
889 - {
890 - for (int i = 0; i < currentTable.Rows.Count; i++)
891 - {
892 - Row row = currentTable.Rows[i];
893 - string actionName = row.Fields[0].Data.ToString();
894 - string[] sections = row.SectionId.Split('/');
895 - bool isSectionIdEmpty = (sections[0].Length == 0 && sections[1].Length == 0);
896 -
897 - if (row.Operation == RowOperation.None)
898 - {
899 - // ignore the rows without section id.
900 - if (isSectionIdEmpty)
901 - {
902 - currentTable.Rows.RemoveAt(i);
903 - i--;
904 - }
905 - else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
906 - {
907 - keptRows++;
908 - }
909 - else
910 - {
911 - currentTable.Rows.RemoveAt(i);
912 - i--;
913 - }
914 - }
915 - else if (row.Operation == RowOperation.Modify)
916 - {
917 - bool sequenceChanged = row.Fields[2].Modified;
918 - bool conditionChanged = row.Fields[1].Modified;
919 -
920 - if (sequenceChanged && !conditionChanged)
921 - {
922 - keptRows++;
923 - }
924 - else if (!sequenceChanged && conditionChanged)
925 - {
926 - if (isSectionIdEmpty)
927 - {
928 - currentTable.Rows.RemoveAt(i);
929 - i--;
930 - }
931 - else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
932 - {
933 - keptRows++;
934 - }
935 - else
936 - {
937 - currentTable.Rows.RemoveAt(i);
938 - i--;
939 - }
940 - }
941 - else if (sequenceChanged && conditionChanged)
942 - {
943 - if (isSectionIdEmpty)
944 - {
945 - row.Fields[1].Modified = false;
946 - keptRows++;
947 - }
948 - else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
949 - {
950 - keptRows++;
951 - }
952 - else
953 - {
954 - row.Fields[1].Modified = false;
955 - keptRows++;
956 - }
957 - }
958 - }
959 - else if (row.Operation == RowOperation.Delete)
960 - {
961 - if (isSectionIdEmpty)
962 - {
963 - // it is a stardard action which is added by wix, we should keep this action.
964 - row.Operation = RowOperation.None;
965 - keptRows++;
966 - }
967 - else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
968 - {
969 - keptRows++;
970 - }
971 - else
972 - {
973 - if (customAction.ContainsKey(actionName))
974 - {
975 - currentTable.Rows.RemoveAt(i);
976 - i--;
977 - }
978 - else
979 - {
980 - // it is a stardard action, we should keep this action.
981 - row.Operation = RowOperation.None;
982 - keptRows++;
983 - }
984 - }
985 - }
986 - else if (row.Operation == RowOperation.Add)
987 - {
988 - if (isSectionIdEmpty)
989 - {
990 - keptRows++;
991 - }
992 - else if (IsInPatchFamily(sections[0], sections[1], oldSections, newSections))
993 - {
994 - keptRows++;
995 - }
996 - else
997 - {
998 - if (customAction.ContainsKey(actionName))
999 - {
1000 - currentTable.Rows.RemoveAt(i);
1001 - i--;
1002 - }
1003 - else
1004 - {
1005 - keptRows++;
1006 - }
1007 - }
1008 - }
1009 - }
1010 - }
1011 -
1012 - return keptRows;
1013 - }
1014 -
1015 - /// <summary>
1016 - /// Create the #transform for the given main transform.
1017 - /// </summary>
1018 - /// <param name="patchId">Patch GUID from patch authoring.</param>
1019 - /// <param name="clientPatchId">Easily referenced identity for this patch.</param>
1020 - /// <param name="mainTransform">Transform generated by torch.</param>
1021 - /// <param name="mediaRow">Media authored into patch.</param>
1022 - /// <param name="validationFlags">Transform validation flags for the summary information stream.</param>
1023 - /// <param name="productCode">Output string to receive ProductCode.</param>
1024 - [SuppressMessage("Microsoft.Globalization", "CA1303:DoNotPassLiteralsAsLocalizedParameters", MessageId = "System.InvalidOperationException.#ctor(System.String)")]
1025 - public Output BuildPairedTransform(string patchId, string clientPatchId, Output mainTransform, MediaRow mediaRow, int validationFlags, out string productCode)
1026 - {
1027 - productCode = null;
1028 - Output pairedTransform = new Output(null);
1029 - pairedTransform.Type = OutputType.Transform;
1030 - pairedTransform.Codepage = mainTransform.Codepage;
1031 -
1032 - // lookup productVersion property to correct summaryInformation
1033 - string newProductVersion = null;
1034 - Table mainPropertyTable = mainTransform.Tables["Property"];
1035 - if (null != mainPropertyTable)
1036 - {
1037 - foreach (Row row in mainPropertyTable.Rows)
1038 - {
1039 - if ("ProductVersion" == (string)row[0])
1040 - {
1041 - newProductVersion = (string)row[1];
1042 - }
1043 - }
1044 - }
1045 -
1046 - // TODO: build class for manipulating SummaryInformation table
1047 - Table mainSummaryTable = mainTransform.Tables["_SummaryInformation"];
1048 - // add required properties
1049 - Hashtable mainSummaryRows = new Hashtable();
1050 - foreach (Row mainSummaryRow in mainSummaryTable.Rows)
1051 - {
1052 - mainSummaryRows[mainSummaryRow[0]] = mainSummaryRow;
1053 - }
1054 - if (!mainSummaryRows.Contains((int)SummaryInformation.Transform.ValidationFlags))
1055 - {
1056 - Row mainSummaryRow = mainSummaryTable.CreateRow(null);
1057 - mainSummaryRow[0] = (int)SummaryInformation.Transform.ValidationFlags;
1058 - mainSummaryRow[1] = validationFlags.ToString(CultureInfo.InvariantCulture);
1059 - }
1060 -
1061 - // copy summary information from core transform
1062 - Table pairedSummaryTable = pairedTransform.EnsureTable(this.tableDefinitions["_SummaryInformation"]);
1063 - foreach (Row mainSummaryRow in mainSummaryTable.Rows)
1064 - {
1065 - string value = (string)mainSummaryRow[1];
1066 - switch ((SummaryInformation.Transform)mainSummaryRow[0])
1067 - {
1068 - case SummaryInformation.Transform.ProductCodes:
1069 - string[] propertyData = value.Split(';');
1070 - string oldProductVersion = propertyData[0].Substring(38);
1071 - string upgradeCode = propertyData[2];
1072 - productCode = propertyData[0].Substring(0, 38);
1073 - if (newProductVersion == null)
1074 - {
1075 - newProductVersion = oldProductVersion;
1076 - }
1077 -
1078 - // force mainTranform to old;new;upgrade and pairedTransform to new;new;upgrade
1079 - mainSummaryRow[1] = String.Concat(productCode, oldProductVersion, ';', productCode, newProductVersion, ';', upgradeCode);
1080 - value = String.Concat(productCode, newProductVersion, ';', productCode, newProductVersion, ';', upgradeCode);
1081 - break;
1082 - case SummaryInformation.Transform.ValidationFlags:
1083 - // use validation flags authored into the patch XML
1084 - mainSummaryRow[1] = value = validationFlags.ToString(CultureInfo.InvariantCulture);
1085 - break;
1086 - }
1087 - Row pairedSummaryRow = pairedSummaryTable.CreateRow(null);
1088 - pairedSummaryRow[0] = mainSummaryRow[0];
1089 - pairedSummaryRow[1] = value;
1090 - }
1091 -
1092 - if (productCode == null)
1093 - {
1094 - throw new InvalidOperationException(WixStrings.EXP_CouldnotDetermineProductCodeFromTransformSummaryInfo);
1095 - }
1096 -
1097 - // copy File table
1098 - Table mainFileTable = mainTransform.Tables["File"];
1099 - if (null != mainFileTable && 0 < mainFileTable.Rows.Count)
1100 - {
1101 - // We require file source information.
1102 - Table mainWixFileTable = mainTransform.Tables["WixFile"];
1103 - if (null == mainWixFileTable)
1104 - {
1105 - throw new WixException(WixErrors.AdminImageRequired(productCode));
1106 - }
1107 -
1108 - RowDictionary<FileRow> mainFileRows = new RowDictionary<FileRow>(mainFileTable);
1109 -
1110 - Table pairedFileTable = pairedTransform.EnsureTable(mainFileTable.Definition);
1111 - foreach (WixFileRow mainWixFileRow in mainWixFileTable.Rows)
1112 - {
1113 - FileRow mainFileRow = mainFileRows[mainWixFileRow.File];
1114 -
1115 - // set File.Sequence to non null to satisfy transform bind
1116 - mainFileRow.Sequence = 1;
1117 -
1118 - // delete's don't need rows in the paired transform
1119 - if (mainFileRow.Operation == RowOperation.Delete)
1120 - {
1121 - continue;
1122 - }
1123 -
1124 - FileRow pairedFileRow = (FileRow)pairedFileTable.CreateRow(null);
1125 - pairedFileRow.Operation = RowOperation.Modify;
1126 - for (int i = 0; i < mainFileRow.Fields.Length; i++)
1127 - {
1128 - pairedFileRow[i] = mainFileRow[i];
1129 - }
1130 -
1131 - // override authored media for patch bind
1132 - mainWixFileRow.DiskId = mediaRow.DiskId;
1133 -
1134 - // suppress any change to File.Sequence to avoid bloat
1135 - mainFileRow.Fields[7].Modified = false;
1136 -
1137 - // force File row to appear in the transform
1138 - switch (mainFileRow.Operation)
1139 - {
1140 - case RowOperation.Modify:
1141 - case RowOperation.Add:
1142 - // set msidbFileAttributesPatchAdded
1143 - pairedFileRow.Attributes |= MsiInterop.MsidbFileAttributesPatchAdded;
1144 - pairedFileRow.Fields[6].Modified = true;
1145 - pairedFileRow.Operation = mainFileRow.Operation;
1146 - break;
1147 - default:
1148 - pairedFileRow.Fields[6].Modified = false;
1149 - break;
1150 - }
1151 - }
1152 - }
1153 -
1154 - // add Media row to pairedTransform
1155 - Table pairedMediaTable = pairedTransform.EnsureTable(this.tableDefinitions["Media"]);
1156 - Row pairedMediaRow = pairedMediaTable.CreateRow(null);
1157 - pairedMediaRow.Operation = RowOperation.Add;
1158 - for (int i = 0; i < mediaRow.Fields.Length; i++)
1159 - {
1160 - pairedMediaRow[i] = mediaRow[i];
1161 - }
1162 -
1163 - // add PatchPackage for this Media
1164 - Table pairedPackageTable = pairedTransform.EnsureTable(this.tableDefinitions["PatchPackage"]);
1165 - pairedPackageTable.Operation = TableOperation.Add;
1166 - Row pairedPackageRow = pairedPackageTable.CreateRow(null);
1167 - pairedPackageRow.Operation = RowOperation.Add;
1168 - pairedPackageRow[0] = patchId;
1169 - pairedPackageRow[1] = mediaRow.DiskId;
1170 -
1171 - // add property to both identify client patches and whether those patches are removable or not
1172 - int allowRemoval = 0;
1173 - Table msiPatchMetadataTable = this.patch.Tables["MsiPatchMetadata"];
1174 - if (null != msiPatchMetadataTable)
1175 - {
1176 - foreach (Row msiPatchMetadataRow in msiPatchMetadataTable.Rows)
1177 - {
1178 - // get the value of the standard AllowRemoval property, if present
1179 - string company = (string)msiPatchMetadataRow[0];
1180 - if ((null == company || 0 == company.Length) && "AllowRemoval" == (string)msiPatchMetadataRow[1])
1181 - {
1182 - allowRemoval = Int32.Parse((string)msiPatchMetadataRow[2], CultureInfo.InvariantCulture);
1183 - }
1184 - }
1185 - }
1186 -
1187 - // add the property to the patch transform's Property table
1188 - Table pairedPropertyTable = pairedTransform.EnsureTable(this.tableDefinitions["Property"]);
1189 - pairedPropertyTable.Operation = TableOperation.Add;
1190 - Row pairedPropertyRow = pairedPropertyTable.CreateRow(null);
1191 - pairedPropertyRow.Operation = RowOperation.Add;
1192 - pairedPropertyRow[0] = string.Concat(clientPatchId, ".AllowRemoval");
1193 - pairedPropertyRow[1] = allowRemoval.ToString(CultureInfo.InvariantCulture);
1194 -
1195 - // add this patch code GUID to the patch transform to identify
1196 - // which patches are installed, including in multi-patch
1197 - // installations.
1198 - pairedPropertyRow = pairedPropertyTable.CreateRow(null);
1199 - pairedPropertyRow.Operation = RowOperation.Add;
1200 - pairedPropertyRow[0] = string.Concat(clientPatchId, ".PatchCode");
1201 - pairedPropertyRow[1] = patchId;
1202 -
1203 - // add PATCHNEWPACKAGECODE to apply to admin layouts
1204 - pairedPropertyRow = pairedPropertyTable.CreateRow(null);
1205 - pairedPropertyRow.Operation = RowOperation.Add;
1206 - pairedPropertyRow[0] = "PATCHNEWPACKAGECODE";
1207 - pairedPropertyRow[1] = patchId;
1208 -
1209 - // add PATCHNEWSUMMARYCOMMENTS and PATCHNEWSUMMARYSUBJECT to apply to admin layouts
1210 - Table _summaryInformationTable = this.patch.Tables["_SummaryInformation"];
1211 - if (null != _summaryInformationTable)
1212 - {
1213 - foreach (Row row in _summaryInformationTable.Rows)
1214 - {
1215 - if (3 == (int)row[0]) // PID_SUBJECT
1216 - {
1217 - pairedPropertyRow = pairedPropertyTable.CreateRow(null);
1218 - pairedPropertyRow.Operation = RowOperation.Add;
1219 - pairedPropertyRow[0] = "PATCHNEWSUMMARYSUBJECT";
1220 - pairedPropertyRow[1] = row[1];
1221 - }
1222 - else if (6 == (int)row[0]) // PID_COMMENTS
1223 - {
1224 - pairedPropertyRow = pairedPropertyTable.CreateRow(null);
1225 - pairedPropertyRow.Operation = RowOperation.Add;
1226 - pairedPropertyRow[0] = "PATCHNEWSUMMARYCOMMENTS";
1227 - pairedPropertyRow[1] = row[1];
1228 - }
1229 - }
1230 - }
1231 -
1232 - return pairedTransform;
1233 -
1234 - throw new NotImplementedException();
1235 - }
1236 - }
1237 -}
1238 -
1239 -#endif
src/WixToolset.Core.WindowsInstaller/PatchTransform.cs deleted
-271
@@ -1,271 +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 -#if DELETE
4 -
5 -namespace WixToolset
6 -{
7 - using System;
8 - using System.Collections;
9 - using System.Globalization;
10 - using System.Text;
11 - using System.Text.RegularExpressions;
12 - using WixToolset.Data;
13 - using WixToolset.Extensibility;
14 -
15 - public class PatchTransform
16 - {
17 - private string baseline;
18 - private Intermediate transform;
19 - private string transformPath;
20 -
21 - public string Baseline
22 - {
23 - get { return this.baseline; }
24 - }
25 -
26 - public Intermediate Transform
27 - {
28 - get
29 - {
30 - if (null == this.transform)
31 - {
32 - this.transform = Intermediate.Load(this.transformPath, false);
33 - }
34 -
35 - return this.transform;
36 - }
37 - }
38 -
39 - public string TransformPath
40 - {
41 - get { return this.transformPath; }
42 - }
43 -
44 - public PatchTransform(string transformPath, string baseline)
45 - {
46 - this.transformPath = transformPath;
47 - this.baseline = baseline;
48 - }
49 -
50 - /// <summary>
51 - /// Validates that the differences in the transform are valid for patch transforms.
52 - /// </summary>
53 - public void Validate()
54 - {
55 - // Changing the ProdocutCode in a patch transform is not recommended.
56 - Table propertyTable = this.Transform.Tables["Property"];
57 - if (null != propertyTable)
58 - {
59 - foreach (Row row in propertyTable.Rows)
60 - {
61 - // Only interested in modified rows; fast check.
62 - if (RowOperation.Modify == row.Operation)
63 - {
64 - if (0 == String.CompareOrdinal("ProductCode", (string)row[0]))
65 - {
66 - this.OnMessage(WixWarnings.MajorUpgradePatchNotRecommended());
67 - }
68 - }
69 - }
70 - }
71 -
72 - // If there is nothing in the component table we can return early because the remaining checks are component based.
73 - Table componentTable = this.Transform.Tables["Component"];
74 - if (null == componentTable)
75 - {
76 - return;
77 - }
78 -
79 - // Index Feature table row operations
80 - Table featureTable = this.Transform.Tables["Feature"];
81 - Table featureComponentsTable = this.Transform.Tables["FeatureComponents"];
82 - Hashtable featureOps = null;
83 - if (null != featureTable)
84 - {
85 - int capacity = featureTable.Rows.Count;
86 - featureOps = new Hashtable(capacity);
87 -
88 - foreach (Row row in featureTable.Rows)
89 - {
90 - featureOps[(string)row[0]] = row.Operation;
91 - }
92 - }
93 - else
94 - {
95 - featureOps = new Hashtable();
96 - }
97 -
98 - // Index Component table and check for keypath modifications
99 - Hashtable deletedComponent = new Hashtable();
100 - Hashtable componentKeyPath = new Hashtable();
101 - foreach (Row row in componentTable.Rows)
102 - {
103 - string id = row.Fields[0].Data.ToString();
104 - string keypath = (null == row.Fields[5].Data) ? String.Empty : row.Fields[5].Data.ToString();
105 -
106 - componentKeyPath.Add(id, keypath);
107 - if (RowOperation.Delete == row.Operation)
108 - {
109 - deletedComponent.Add(id, row);
110 - }
111 - else if (RowOperation.Modify == row.Operation)
112 - {
113 - if (row.Fields[1].Modified)
114 - {
115 - // Changing the guid of a component is equal to deleting the old one and adding a new one.
116 - deletedComponent.Add(id, row);
117 - }
118 -
119 - // If the keypath is modified its an error
120 - if (row.Fields[5].Modified)
121 - {
122 - this.OnMessage(WixErrors.InvalidKeypathChange(row.SourceLineNumbers, id, this.transformPath));
123 - }
124 - }
125 - }
126 -
127 - // Verify changes in the file table
128 - Table fileTable = this.Transform.Tables["File"];
129 - if (null != fileTable)
130 - {
131 - Hashtable componentWithChangedKeyPath = new Hashtable();
132 - foreach (Row row in fileTable.Rows)
133 - {
134 - if (RowOperation.None != row.Operation)
135 - {
136 - string fileId = row.Fields[0].Data.ToString();
137 - string componentId = row.Fields[1].Data.ToString();
138 -
139 - // If this file is the keypath of a component
140 - if (String.Equals((string)componentKeyPath[componentId], fileId, StringComparison.Ordinal))
141 - {
142 - if (row.Fields[2].Modified)
143 - {
144 - // You cant change the filename of a file that is the keypath of a component.
145 - this.OnMessage(WixErrors.InvalidKeypathChange(row.SourceLineNumbers, componentId, this.transformPath));
146 - }
147 -
148 - if (!componentWithChangedKeyPath.ContainsKey(componentId))
149 - {
150 - componentWithChangedKeyPath.Add(componentId, fileId);
151 - }
152 - }
153 -
154 - if (RowOperation.Delete == row.Operation)
155 - {
156 - // If the file is removed from a component that is not deleted.
157 - if (!deletedComponent.ContainsKey(componentId))
158 - {
159 - bool foundRemoveFileEntry = false;
160 - string filename = Common.GetName((string)row[2], false, true);
161 -
162 - Table removeFileTable = this.Transform.Tables["RemoveFile"];
163 - if (null != removeFileTable)
164 - {
165 - foreach (Row removeFileRow in removeFileTable.Rows)
166 - {
167 - if (RowOperation.Delete == removeFileRow.Operation)
168 - {
169 - continue;
170 - }
171 -
172 - if (componentId == (string)removeFileRow[1])
173 - {
174 - // Check if there is a RemoveFile entry for this file
175 - if (null != removeFileRow[2])
176 - {
177 - string removeFileName = Common.GetName((string)removeFileRow[2], false, true);
178 -
179 - // Convert the MSI format for a wildcard string to Regex format.
180 - removeFileName = removeFileName.Replace('.', '|').Replace('?', '.').Replace("*", ".*").Replace("|", "\\.");
181 -
182 - Regex regex = new Regex(removeFileName, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
183 - if (regex.IsMatch(filename))
184 - {
185 - foundRemoveFileEntry = true;
186 - break;
187 - }
188 - }
189 - }
190 - }
191 - }
192 -
193 - if (!foundRemoveFileEntry)
194 - {
195 - this.OnMessage(WixWarnings.InvalidRemoveFile(row.SourceLineNumbers, fileId, componentId));
196 - }
197 - }
198 - }
199 - }
200 - }
201 - }
202 -
203 - if (0 < deletedComponent.Count)
204 - {
205 - // Index FeatureComponents table.
206 - Hashtable featureComponents = new Hashtable();
207 -
208 - if (null != featureComponentsTable)
209 - {
210 - foreach (Row row in featureComponentsTable.Rows)
211 - {
212 - ArrayList features;
213 - string componentId = row.Fields[1].Data.ToString();
214 -
215 - if (featureComponents.Contains(componentId))
216 - {
217 - features = (ArrayList)featureComponents[componentId];
218 - }
219 - else
220 - {
221 - features = new ArrayList();
222 - featureComponents.Add(componentId, features);
223 - }
224 - features.Add(row.Fields[0].Data.ToString());
225 - }
226 - }
227 -
228 - // Check to make sure if a component was deleted, the feature was too.
229 - foreach (DictionaryEntry entry in deletedComponent)
230 - {
231 - if (featureComponents.Contains(entry.Key.ToString()))
232 - {
233 - ArrayList features = (ArrayList)featureComponents[entry.Key.ToString()];
234 - foreach (string featureId in features)
235 - {
236 - if (!featureOps.ContainsKey(featureId) || RowOperation.Delete != (RowOperation)featureOps[featureId])
237 - {
238 - // The feature was not deleted.
239 - this.OnMessage(WixErrors.InvalidRemoveComponent(((Row)entry.Value).SourceLineNumbers, entry.Key.ToString(), featureId, this.transformPath));
240 - }
241 - }
242 - }
243 - }
244 - }
245 -
246 - // Warn if new components are added to existing features
247 - if (null != featureComponentsTable)
248 - {
249 - foreach (Row row in featureComponentsTable.Rows)
250 - {
251 - if (RowOperation.Add == row.Operation)
252 - {
253 - // Check if the feature is in the Feature table
254 - string feature_ = (string)row[0];
255 - string component_ = (string)row[1];
256 -
257 - // Features may not be present if not referenced
258 - if (!featureOps.ContainsKey(feature_) || RowOperation.Add != (RowOperation)featureOps[feature_])
259 - {
260 - this.OnMessage(WixWarnings.NewComponentAddedToExistingFeature(row.SourceLineNumbers, component_, feature_, this.transformPath));
261 - }
262 - }
263 - }
264 - }
265 -
266 - throw new NotImplementedException();
267 - }
268 - }
269 -}
270 -
271 -#endif
\ No newline at end of file