From 3f583916719eeef598d10a5d4e14ef14f008243b Mon Sep 17 00:00:00 2001
From: Rob Mensching
Date: Tue, 11 May 2021 07:36:37 -0700
Subject: Merge Dtf
---
.../WixToolset.Dtf.WindowsInstaller/SourceList.cs | 525 +++++++++++++++++++++
1 file changed, 525 insertions(+)
create mode 100644 src/dtf/WixToolset.Dtf.WindowsInstaller/SourceList.cs
(limited to 'src/dtf/WixToolset.Dtf.WindowsInstaller/SourceList.cs')
diff --git a/src/dtf/WixToolset.Dtf.WindowsInstaller/SourceList.cs b/src/dtf/WixToolset.Dtf.WindowsInstaller/SourceList.cs
new file mode 100644
index 00000000..16ec22e8
--- /dev/null
+++ b/src/dtf/WixToolset.Dtf.WindowsInstaller/SourceList.cs
@@ -0,0 +1,525 @@
+// 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.
+
+namespace WixToolset.Dtf.WindowsInstaller
+{
+ using System;
+ using System.Text;
+ using System.Collections.Generic;
+ using System.Globalization;
+ using System.Diagnostics.CodeAnalysis;
+
+ ///
+ /// A list of sources for an installed product or patch.
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")]
+ public class SourceList : ICollection
+ {
+ private Installation installation;
+ private SourceMediaList mediaList;
+
+ internal SourceList(Installation installation)
+ {
+ this.installation = installation;
+ }
+
+ ///
+ /// Gets the list of disks registered for the media source of
+ /// the patch or product installation.
+ ///
+ public SourceMediaList MediaList
+ {
+ get
+ {
+ if (this.mediaList == null)
+ {
+ this.mediaList = new SourceMediaList(this.installation);
+ }
+ return this.mediaList;
+ }
+ }
+
+ ///
+ /// Gets the number of network and URL sources in the list.
+ ///
+ public int Count
+ {
+ get
+ {
+ int count = 0;
+ IEnumerator e = this.GetEnumerator();
+ while (e.MoveNext())
+ {
+ count++;
+ }
+ return count;
+ }
+ }
+
+ ///
+ /// Gets a boolean value indicating whether the list is read-only.
+ /// A SourceList is never read-only.
+ ///
+ /// read-only status of the list
+ public bool IsReadOnly
+ {
+ get { return false; }
+ }
+
+ ///
+ /// Adds a network or URL source to the source list of the installed product.
+ ///
+ /// Path to the source to be added. This parameter is
+ /// expected to contain only the path without the filename.
+ ///
+ /// If this method is called with a new source, the installer adds the source
+ /// to the end of the source list.
+ ///
+ /// If this method is called with a source already existing in the source
+ /// list, it has no effect.
+ ///
+ /// Win32 MSI APIs:
+ /// MsiSourceListAddSource,
+ /// MsiSourceListAddSourceEx
+ ///
+ ///
+ public void Add(string item)
+ {
+ if (!this.Contains(item))
+ {
+ this.Insert(item, 0);
+ }
+ }
+
+ ///
+ /// Adds or reorders a network or URL source for the product or patch.
+ ///
+ /// Path to the source to be added. This parameter is
+ /// expected to contain only the path without the filename.
+ /// Specifies the priority order in which the source
+ /// will be inserted
+ ///
+ /// If this method is called with a new source and
+ /// is set to 0, the installer adds the source to the end of the source list.
+ ///
+ /// If this method is called with a source already existing in the source
+ /// list and is set to 0, the installer retains the
+ /// source's existing index.
+ ///
+ /// If the method is called with an existing source in the source list
+ /// and is set to a non-zero value, the source is
+ /// removed from its current location in the list and inserted at the position
+ /// specified by Index, before any source that already exists at that position.
+ ///
+ /// If the method is called with a new source and Index is set to a
+ /// non-zero value, the source is inserted at the position specified by
+ /// , before any source that already exists at
+ /// that position. The index value for all sources in the list after the
+ /// index specified by Index are updated to ensure unique index values and
+ /// the pre-existing order is guaranteed to remain unchanged.
+ ///
+ /// If is greater than the number of sources
+ /// in the list, the source is placed at the end of the list with an index
+ /// value one larger than any existing source.
+ ///
+ /// Win32 MSI API:
+ /// MsiSourceListAddSourceEx
+ ///
+ public void Insert(string item, int index)
+ {
+ if (item == null)
+ {
+ throw new ArgumentNullException("item");
+ }
+
+ NativeMethods.SourceType type = item.Contains("://") ? NativeMethods.SourceType.Url : NativeMethods.SourceType.Network;
+
+ uint ret = NativeMethods.MsiSourceListAddSourceEx(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) type | (uint) this.installation.InstallationType,
+ item,
+ (uint) index);
+ if (ret != 0)
+ {
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ }
+
+ ///
+ /// Clears sources of all types: network, url, and media.
+ ///
+ ///
+ /// Win32 MSI API:
+ /// MsiSourceListClearAll
+ ///
+ public void Clear()
+ {
+ this.ClearSourceType(NativeMethods.SourceType.Url);
+ this.ClearSourceType(NativeMethods.SourceType.Network);
+ this.MediaList.Clear();
+ }
+
+ ///
+ /// Removes all network sources from the list. URL sources are not affected.
+ ///
+ ///
+ /// Win32 MSI API:
+ /// MsiSourceListClearAllEx
+ ///
+ public void ClearNetworkSources()
+ {
+ this.ClearSourceType(NativeMethods.SourceType.Network);
+ }
+
+ ///
+ /// Removes all URL sources from the list. Network sources are not affected.
+ ///
+ ///
+ /// Win32 MSI API:
+ /// MsiSourceListClearAllEx
+ ///
+ public void ClearUrlSources()
+ {
+ this.ClearSourceType(NativeMethods.SourceType.Url);
+ }
+
+ ///
+ /// Checks if the specified source exists in the list.
+ ///
+ /// case-insensitive source to look for
+ /// true if the source exists in the list, false otherwise
+ public bool Contains(string item)
+ {
+ if (String.IsNullOrEmpty(item))
+ {
+ throw new ArgumentNullException("item");
+ }
+
+ foreach (string s in this)
+ {
+ if (s.Equals(item, StringComparison.OrdinalIgnoreCase))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Copies the network and URL sources from this list into an array.
+ ///
+ /// destination array to be filed
+ /// offset into the destination array where copying begins
+ public void CopyTo(string[] array, int arrayIndex)
+ {
+ foreach (string source in this)
+ {
+ array[arrayIndex++] = source;
+ }
+ }
+
+ ///
+ /// Removes a network or URL source.
+ ///
+ ///
+ /// Win32 MSI API:
+ /// MsiSourceListClearSource
+ ///
+ public bool Remove(string item)
+ {
+ if (String.IsNullOrEmpty(item))
+ {
+ throw new ArgumentNullException("item");
+ }
+
+ NativeMethods.SourceType type = item.Contains("://") ? NativeMethods.SourceType.Url : NativeMethods.SourceType.Network;
+
+ uint ret = NativeMethods.MsiSourceListClearSource(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) type | (uint) this.installation.InstallationType,
+ item);
+ if (ret != 0)
+ {
+ // TODO: Figure out when to return false.
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ return true;
+ }
+
+ ///
+ /// Enumerates the network and URL sources in the source list of the patch or product installation.
+ ///
+ ///
+ /// Win32 MSI API:
+ /// MsiSourceListEnumSources
+ ///
+ public IEnumerator GetEnumerator()
+ {
+ StringBuilder sourceBuf = new StringBuilder(256);
+ uint sourceBufSize = (uint) sourceBuf.Capacity;
+ for (uint i = 0; true; i++)
+ {
+ uint ret = this.EnumSources(sourceBuf, i, NativeMethods.SourceType.Network);
+ if (ret == (uint) NativeMethods.Error.NO_MORE_ITEMS)
+ {
+ break;
+ }
+ else if (ret != 0)
+ {
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ else
+ {
+ yield return sourceBuf.ToString();
+ }
+ }
+
+ for (uint i = 0; true; i++)
+ {
+ uint ret = this.EnumSources(sourceBuf, i, NativeMethods.SourceType.Url);
+ if (ret == (uint) NativeMethods.Error.NO_MORE_ITEMS)
+ {
+ break;
+ }
+ else if (ret != 0)
+ {
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ else
+ {
+ yield return sourceBuf.ToString();
+ }
+ }
+ }
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+ {
+ return this.GetEnumerator();
+ }
+
+ ///
+ /// Forces the installer to search the source list for a valid
+ /// source the next time a source is required. For example, when the
+ /// installer performs an installation or reinstallation, or when it
+ /// requires the path for a component that is set to run from source.
+ ///
+ ///
+ /// Win32 MSI APIs:
+ /// MsiSourceListForceResolution,
+ /// MsiSourceListForceResolutionEx
+ ///
+ public void ForceResolution()
+ {
+ uint ret = NativeMethods.MsiSourceListForceResolutionEx(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) this.installation.InstallationType);
+ if (ret != 0)
+ {
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ }
+
+ ///
+ /// Gets or sets the path relative to the root of the installation media.
+ ///
+ public string MediaPackagePath
+ {
+ get
+ {
+ return this["MediaPackagePath"];
+ }
+ set
+ {
+ this["MediaPackagePath"] = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the prompt template that is used when prompting the user
+ /// for installation media.
+ ///
+ public string DiskPrompt
+ {
+ get
+ {
+ return this["DiskPrompt"];
+ }
+ set
+ {
+ this["DiskPrompt"] = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the most recently used source location for the product.
+ ///
+ public string LastUsedSource
+ {
+ get
+ {
+ return this["LastUsedSource"];
+ }
+ set
+ {
+ this["LastUsedSource"] = value;
+ }
+ }
+
+ ///
+ /// Gets or sets the name of the Windows Installer package or patch package
+ /// on the source.
+ ///
+ public string PackageName
+ {
+ get
+ {
+ return this["PackageName"];
+ }
+ set
+ {
+ this["PackageName"] = value;
+ }
+ }
+
+ ///
+ /// Gets the type of the last-used source.
+ ///
+ ///
+ ///
+ /// - "n" = network location
+ /// - "u" = URL location
+ /// - "m" = media location
+ /// - (empty string) = no last used source
+ ///
+ ///
+ public string LastUsedType
+ {
+ get
+ {
+ return this["LastUsedType"];
+ }
+ }
+
+ ///
+ /// Gets or sets source list information properties of a product or patch installation.
+ ///
+ /// The source list information property name.
+ /// An unknown product, patch, or property was requested
+ ///
+ /// Win32 MSI API:
+ /// MsiSourceListGetInfo
+ ///
+ public string this[string property]
+ {
+ get
+ {
+ StringBuilder buf = new StringBuilder("");
+ uint bufSize = 0;
+ uint ret = NativeMethods.MsiSourceListGetInfo(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) this.installation.InstallationType,
+ property,
+ buf,
+ ref bufSize);
+ if (ret != 0)
+ {
+ if (ret == (uint) NativeMethods.Error.MORE_DATA)
+ {
+ buf.Capacity = (int) ++bufSize;
+ ret = NativeMethods.MsiSourceListGetInfo(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) this.installation.InstallationType,
+ property,
+ buf,
+ ref bufSize);
+ }
+
+ if (ret != 0)
+ {
+ if (ret == (uint) NativeMethods.Error.UNKNOWN_PRODUCT ||
+ ret == (uint) NativeMethods.Error.UNKNOWN_PROPERTY)
+ {
+ throw new ArgumentOutOfRangeException("property");
+ }
+ else
+ {
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ }
+ }
+ return buf.ToString();
+ }
+ set
+ {
+ uint ret = NativeMethods.MsiSourceListSetInfo(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) this.installation.InstallationType,
+ property,
+ value);
+ if (ret != 0)
+ {
+ if (ret == (uint) NativeMethods.Error.UNKNOWN_PRODUCT ||
+ ret == (uint) NativeMethods.Error.UNKNOWN_PROPERTY)
+ {
+ throw new ArgumentOutOfRangeException("property");
+ }
+ else
+ {
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ }
+ }
+ }
+
+ private void ClearSourceType(NativeMethods.SourceType type)
+ {
+ uint ret = NativeMethods.MsiSourceListClearAllEx(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) type | (uint) this.installation.InstallationType);
+ if (ret != 0)
+ {
+ throw InstallerException.ExceptionFromReturnCode(ret);
+ }
+ }
+
+ private uint EnumSources(StringBuilder sourceBuf, uint i, NativeMethods.SourceType sourceType)
+ {
+ int enumType = (this.installation.InstallationType | (int) sourceType);
+ uint sourceBufSize = (uint) sourceBuf.Capacity;
+ uint ret = NativeMethods.MsiSourceListEnumSources(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) enumType,
+ i,
+ sourceBuf,
+ ref sourceBufSize);
+ if (ret == (uint) NativeMethods.Error.MORE_DATA)
+ {
+ sourceBuf.Capacity = (int) ++sourceBufSize;
+ ret = NativeMethods.MsiSourceListEnumSources(
+ this.installation.InstallationCode,
+ this.installation.UserSid,
+ this.installation.Context,
+ (uint) enumType,
+ i,
+ sourceBuf,
+ ref sourceBufSize);
+ }
+ return ret;
+ }
+ }
+}
--
cgit v1.2.3-55-g6feb