// 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.Core.Cab { using System; using System.Collections.Generic; using WixToolset.Core.Native; using Handle = System.Int32; /// /// Wrapper class around interop with wixcab.dll to enumerate files from a cabinet. /// public sealed class WixEnumerateCab : IDisposable { private bool disposed; private List fileInfoList; private CabInterop.PFNNOTIFY pfnNotify; /// /// Creates a cabinet enumerator. /// public WixEnumerateCab() { this.pfnNotify = new CabInterop.PFNNOTIFY(this.Notify); NativeMethods.EnumerateCabBegin(); } /// /// Destructor for cabinet enumeration. /// ~WixEnumerateCab() { this.Dispose(); } /// /// Enumerates all files in a cabinet. /// /// path to cabinet /// list of CabinetFileInfo public List Enumerate(string cabinetFile) { this.fileInfoList = new List(); // the callback (this.Notify) will populate the list for each file in cabinet NativeMethods.EnumerateCab(cabinetFile, this.pfnNotify); return this.fileInfoList; } /// /// Disposes the managed and unmanaged objects in this object. /// public void Dispose() { if (!this.disposed) { NativeMethods.EnumerateCabFinish(); GC.SuppressFinalize(this); this.disposed = true; } } /// /// Delegate that's called for every file in cabinet. /// /// NOTIFICATIONTYPE /// NOTIFICATION /// System.Int32 internal Handle Notify(CabInterop.NOTIFICATIONTYPE fdint, CabInterop.NOTIFICATION pfdin) { // This is FDI's way of notifying us of how many files total are in the cab, accurate even // if the files are split into multiple folders - use it to allocate the precise size we need if (CabInterop.NOTIFICATIONTYPE.ENUMERATE == fdint && 0 == this.fileInfoList.Count) { this.fileInfoList.Capacity = pfdin.Folder; } if (fdint == CabInterop.NOTIFICATIONTYPE.COPY_FILE) { CabinetFileInfo fileInfo = new CabinetFileInfo(pfdin.Psz1, pfdin.Date, pfdin.Time, pfdin.Cb); this.fileInfoList.Add(fileInfo); } return 0; // tell cabinet api to skip this file. } } }