// 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.Collections.Generic; using System.Text; using System.Globalization; using System.Diagnostics.CodeAnalysis; /// /// A list of source media for an installed product or patch. /// [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] public class SourceMediaList : ICollection { private Installation installation; internal SourceMediaList(Installation installation) { this.installation = installation; } /// /// Gets the number of source media 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 SourceMediaList is never read-only. /// /// read-only status of the list public bool IsReadOnly { get { return false; } } /// /// Adds or updates a disk of the media source for the product or patch. /// ///

/// Win32 MSI API: /// MsiSourceListAddMediaDisk ///

public void Add(MediaDisk item) { uint ret = NativeMethods.MsiSourceListAddMediaDisk( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint) this.installation.InstallationType, (uint) item.DiskId, item.VolumeLabel, item.DiskPrompt); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } } /// /// Removes all source media from the list. /// ///

/// Win32 MSI API: /// MsiSourceListClearAllEx ///

public void Clear() { uint ret = NativeMethods.MsiSourceListClearAllEx( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint) NativeMethods.SourceType.Media | (uint) this.installation.InstallationType); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } } /// /// Checks if the specified media disk id exists in the list. /// /// disk id of the media to look for /// true if the media exists in the list, false otherwise public bool Contains(int diskId) { foreach (MediaDisk mediaDisk in this) { if (mediaDisk.DiskId == diskId) { return true; } } return false; } bool ICollection.Contains(MediaDisk mediaDisk) { return this.Contains(mediaDisk.DiskId); } /// /// Copies the source media info from this list into an array. /// /// destination array to be filed /// offset into the destination array where copying begins public void CopyTo(MediaDisk[] array, int arrayIndex) { foreach (MediaDisk mediaDisk in this) { array[arrayIndex++] = mediaDisk; } } /// /// Removes a specified disk from the set of registered disks. /// /// ID of the disk to remove ///

/// Win32 MSI API: /// MsiSourceListClearMediaDisk ///

public bool Remove(int diskId) { uint ret = NativeMethods.MsiSourceListClearMediaDisk( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint) this.installation.InstallationType, (uint) diskId); if (ret != 0) { // TODO: Figure out when to return false. throw InstallerException.ExceptionFromReturnCode(ret); } return true; } bool ICollection.Remove(MediaDisk mediaDisk) { return this.Remove(mediaDisk.DiskId); } /// /// Enumerates the source media in the source list of the patch or product installation. /// ///

/// Win32 MSI API: /// MsiSourceListEnumMediaDisks ///

public IEnumerator GetEnumerator() { uint diskId; StringBuilder volumeBuf = new StringBuilder(40); uint volumeBufSize = (uint) volumeBuf.Capacity; StringBuilder promptBuf = new StringBuilder(80); uint promptBufSize = (uint) promptBuf.Capacity; for (uint i = 0; true; i++) { uint ret = NativeMethods.MsiSourceListEnumMediaDisks( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint) this.installation.InstallationType, i, out diskId, volumeBuf, ref volumeBufSize, promptBuf, ref promptBufSize); if (ret == (uint) NativeMethods.Error.MORE_DATA) { volumeBuf.Capacity = (int) ++volumeBufSize; promptBuf.Capacity = (int) ++promptBufSize; ret = NativeMethods.MsiSourceListEnumMediaDisks( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint) this.installation.InstallationType, i, out diskId, volumeBuf, ref volumeBufSize, promptBuf, ref promptBufSize); } if (ret == (uint) NativeMethods.Error.NO_MORE_ITEMS) { break; } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } yield return new MediaDisk((int) diskId, volumeBuf.ToString(), promptBuf.ToString()); } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } }