ZipArchive.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Base / MS / Internal / IO / Zip / ZipArchive.cs / 1 / ZipArchive.cs

                            //------------------------------------------------------------------------------ 
//-------------   *** WARNING ***
//-------------    This file is part of a legally monitored development project.
//-------------    Do not check in changes to this project.  Do not raid bugs on this
//-------------    code in the main PS database.  Do not contact the owner of this 
//-------------    code directly.  Contact the legal team at �ZSLegal� for assistance.
//-------------   *** WARNING *** 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  This is an internal class that enables interactions with Zip archives 
//  for OPC scenarios
// 
// History:
//  11/19/2004: IgorBel: Initial creation.
//
//----------------------------------------------------------------------------- 

using System; 
using System.IO; 
using System.Diagnostics;
using System.Collections; 
using System.Globalization;
using System.Runtime.Serialization;
using System.Windows;
 
namespace MS.Internal.IO.Zip
{ 
    ///  
    ///  This is the main clas of the ZIP IO internal APIs. It has 2 stsatic constructors
    /// OpenOnFile and OpenOnStream. It provides client app with ability to manipulate 
    /// a Zip Archive (create, open, open/add/delete file items).
    /// 
    internal sealed class ZipArchive : IDisposable
    { 
        //------------------------------------------------------
        // 
        //  Public Members 
        //
        //----------------------------------------------------- 
        // None

        //------------------------------------------------------
        // 
        //  Internal Constructors
        // 
        //------------------------------------------------------ 
        // None
 
        //-----------------------------------------------------
        //
        // Internal API Methods (although these methods are marked as
        // Internal, they are part of the internal ZIP IO API surface 
        //
        //------------------------------------------------------ 
        ///  
        ///  Static constructor File based constructor. all parameteres are obvious.
        ///  This constructor wil  open the file in requested mode, and it will not do any futher parsing. 
        ///
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord. 
        /// 
        internal static ZipArchive OpenOnFile(string path, FileMode mode, FileAccess access, FileShare share, bool streaming) 
        { 
            if (mode == FileMode.OpenOrCreate || mode == FileMode.Open)
            { 
                // for OpenOrCreate cases we need to check whether it is an exisiting file of size 0.
                // Files of size 0 are onsidered invalid ZipArchives. If we skip this check here, later we wouldn't be able to distinguish
                // between brand new file being created as a result of OpenOrCreate mode, or old 0 length file being open as a result of
                // OpenOrCreate mode. 
                FileInfo fileInfo = new FileInfo(path);
 
                if (fileInfo.Exists && (fileInfo.Length == 0)) 
                {
                    throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive)); 
                }
            }

            ZipArchive archive = null; 
            FileStream archiveStream = null;
 
            // We would like to run initialization after openning stream in try/catch block 
            // so that if anything goes wrong we can close the stream (release file handler)
            try 
            {
                archiveStream = new FileStream(path, mode, access, share, 4096, streaming);

                ValidateModeAccessShareStreaming(archiveStream, mode, access, share, streaming); 

                archive = new ZipArchive(archiveStream, mode, access, streaming, true); 
            } 
            catch
            { 
                if (archiveStream != null)
                {
                    archiveStream.Close();
                } 

                throw; 
            } 

            return archive; 
        }

        /// 
        ///  Static constructor Stream based constructor. all parameteres are obvious. 
        ///  This constructor wil not do any futher parsing.
        /// 
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory 
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord. 
        /// 
        internal static ZipArchive OpenOnStream(Stream stream, FileMode mode, FileAccess access, bool streaming)
        {
            // we can assume FileShare.None, as there is absolutely nothing we can do 
            // about other people working with the underlying storage
            ValidateModeAccessShareStreaming(stream, mode, access, FileShare.None, streaming); 
 
            if (stream.CanSeek)
            { 
                bool emptyStream = (stream.Length == 0);

                switch (mode)
                { 
                    // for Open cases we need to check whether it is an existing file of size 0.
                    // Streams of size 0 are considered invalid ZipArchives. 
                    case FileMode.Open: 
                        if (emptyStream)
                        { 
                            throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive));
                        }
                        break;
 
                    // for Create cases, we need to check if the stream is empty or not
                    case FileMode.CreateNew: 
                        if (!emptyStream) 
                        {
                            throw new IOException(SR.Get(SRID.CreateNewOnNonEmptyStream)); 
                        }
                        break;
                    case FileMode.Create:
                        if (!emptyStream) 
                        {
                            // discard existing data 
                            stream.SetLength(0); 
                        }
                        break; 
                }
            }

            return new ZipArchive(stream, mode, access, streaming, false); 
        }
 
 
        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that (assuming no duplicates were found). It will create in appropriate
        /// in memory Local FileHeaders and Central Directory Headers.
        ///  
        internal ZipFileInfo AddFile(string zipFileName, CompressionMethodEnum compressionMethod, DeflateOptionEnum deflateOption)
        { 
            CheckDisposed(); 

            if (_openAccess == FileAccess.Read) 
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode));
            }
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 
 
            if ((compressionMethod != CompressionMethodEnum.Stored) &&
                (compressionMethod != CompressionMethodEnum.Deflated)) 
            {
                throw new ArgumentOutOfRangeException("compressionMethod");
            }
 
            // non-contiguous range requires more complex test
            if (deflateOption < DeflateOptionEnum.Normal || ( 
                deflateOption > DeflateOptionEnum.SuperFast && deflateOption != DeflateOptionEnum.None)) 
            {
                throw new ArgumentOutOfRangeException("deflateOption"); 
            }

            // Check for duplicates ,
            if (FileExists(zipFileName)) 
            {
                throw new System.InvalidOperationException(SR.Get(SRID.AttemptedToCreateDuplicateFileName)); 
            } 

            // Create Local File Block through Block Manager 
            ZipIOLocalFileBlock fileBlock = _blockManager.CreateLocalFileBlock(zipFileName, compressionMethod, deflateOption);

            //build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo,
            // that were given out  and invalidate any collection that was returned on GetFiles calls 
            ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock);
            ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo); 
 
            return zipFileInfo;
        } 

        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that (assuming the file was found). It will parse the apropriate local file block
        /// header and data descriptor (if present). 
        ///  
        internal ZipFileInfo GetFile(string zipFileName)
        { 
            CheckDisposed();

            if (_openAccess == FileAccess.Write)
            { 
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode));
            } 
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 

            // try to get it from the ZipFileInfo dictionary
            if (ZipFileInfoDictionary.Contains(zipFileName))
            { 
                // this ZipFileInfo was already built through AddFile or GetFile(s)
                // we have this cached 
                return (ZipFileInfo)(ZipFileInfoDictionary[zipFileName]); 
            }
            else 
            {
                // we need to check whether it is present in the central directory
                if (!FileExists(zipFileName))
                { 
                    throw new InvalidOperationException(SR.Get(SRID.FileDoesNotExists));
                } 
 
                // Load Local File Block through Block Manager
                ZipIOLocalFileBlock fileBlock = _blockManager.LoadLocalFileBlock(zipFileName); 

                // build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo,
                // that were given out  and invalidate any collection that was returned on GetFiles calls
                ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock); 

                //this should invalidate any outstanding collections 
                ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo); 

                return zipFileInfo; 
            }
        }

        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that it will check whether central directory contains the file. 
        /// It will not attempt the parsing of the local file headers / descriptors.
        ///  
        internal bool FileExists (string zipFileName)
        {
            CheckDisposed();
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 
 
            return _blockManager.CentralDirectoryBlock.FileExists(zipFileName);
        } 


        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that it will check whether central directory contains the file. 
        /// If it is present it will parse local fileheader, and remove their in memory 
        /// representation
        ///  
        internal void DeleteFile (string zipFileName)
        {
            CheckDisposed();
 
            if (_openAccess == FileAccess.Read)
            { 
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode)); 
            }
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName);

            if (FileExists(zipFileName)) // is it in central Directory ? 
            {
                ZipFileInfo fileInfoToBeDeleted  = GetFile(zipFileName); 
 
                //this should invalidate any outstanding collections
                // and update central directory status as appropriate 
                ZipFileInfoDictionary.Remove(zipFileName);

                //this should remove the local file block
                // from the blockManager's collection 
                _blockManager.RemoveLocalFileBlock(fileInfoToBeDeleted.LocalFileBlock);
            } 
        } 

        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that it will go through allfiles in the central directory and parse their
        /// local headers and desciptors one by one. 
        /// 
        internal ZipFileInfoCollection GetFiles() 
        { 
            CheckDisposed();
 
            if (_openAccess == FileAccess.Write)
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode));
            } 

            // We need to scan through the central Directory, and for each file 
            // call GetFile(fileName), which will result in adding missing (not loaded) 
            // information to the ZipFileInfoDictionary.
            foreach(string fileName in _blockManager.CentralDirectoryBlock.GetFileNamesCollection()) 
            {
                GetFile(fileName);  // fileName must be validated and normalized at this
                                            // point by the central directory parsing routine
            } 
            return new ZipFileInfoCollection(ZipFileInfoDictionary.Values);
        } 
 
        /// 
        ///  This method will result in a complete Flushing of any outstanding data in buffers and 
        /// any streams ever returned by the GetStream calls.This call results in Archive file that
        /// has a completely valid state. If application were to crash right afte the Flush is complete,
        /// the resulting files would be a "valid" Zip archive
        ///  
        internal void Flush()
        { 
            CheckDisposed(); 
            _blockManager.Save(false);
        } 

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects
        /// ZipFileInfo, Streams ZipArchive. 
        /// 
        internal void Close() 
        { 
            Dispose();
        } 

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects
        /// ZipFileInfo, Streams ZipArchive. 
        /// 
        public void Dispose() 
        { 
            Dispose(true);
            // GC.SuppressFinalize(this);  // Because this class is sealed and there is no Finalizer, 
                                                        // there is no need for this call. Leaving it in case we decide to unseal it
        }

        ///  
        /// Throw if version needed to extract is not supported
        ///  
        /// version to inspect 
        static internal void VerifyVersionNeededToExtract(UInt16 version)
        { 
            // strictly enforce this list
            switch (version)
            {
                case (UInt16)ZipIOVersionNeededToExtract.StoredData: break; 
                case (UInt16)ZipIOVersionNeededToExtract.VolumeLabel: break;
                case (UInt16)ZipIOVersionNeededToExtract.DeflatedData: break; 
                case (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat: break; 
                default:
                    throw new NotSupportedException(SR.Get(SRID.NotSupportedVersionNeededToExtract)); 
            }
        }

        //----------------------------------------------------- 
        //
        //  Internal Properties 
        // 
        //-----------------------------------------------------
        ///  
        /// Read only property, that returns the value of FileAccess that
        /// was passed into the OpenOnFile or OpenOnStream call
        /// 
        internal FileAccess OpenAccess 
        {
            get 
            { 
                CheckDisposed();
                return _openAccess; 
            }
        }

//  This functionality commented out in order to comply with FX Cop rule 
//  AvoidUncalledPrivateCode. However, because of a chance that this functionality
//  might eventually get public exposure we would like to keep this code around 
#if ZIP_IO_PUBLIC 

        ///  
        /// Returns Comment field from the End Of Central Directory Record.
        /// Therefore, call to this property might result in some parsing.
        /// If the End Of Central Directory isn't parsed yet, it will be as a
        /// result of querying this property. 
        /// 
        internal string Comment 
        { 
            get
            { 
                CheckDisposed();
                return _blockManager.EndOfCentralDirectoryBlock.Comment;
            }
        } 
#endif
 
 
        //-----------------------------------------------------
        // 
        // Internal NON API Methods (these methods are marked as
        // Internal, and they are trully internal and not the part of the
        // internal ZIP IO API surface
        // 
        //------------------------------------------------------
 
        //----------------------------------------------------- 
        //
        //  Private Constructors 
        //
        //------------------------------------------------------
        /// 
        /// This private constructor isonly supposed to be called by the 
        /// OpenOnFile and OpenOnStream static members.
        ///  
        ///  
        /// 
        ///  
        /// 
        /// true if this class is responsible for closing the archiveStream
        private ZipArchive(Stream archiveStream, FileMode mode, FileAccess access, bool streaming, bool ownStream)
        { 
            // as this contructor is only called from the static member
            // all checks should have been done before 
 
            _blockManager = new ZipIOBlockManager(archiveStream, streaming, ownStream);
 
            _openMode = mode;
            _openAccess = access;

            // In case of "create" we also need to create at least an end of Central Directory Record. 
            // For FileMode OpenOrCreate we use stream Length to distinguish open and create scenarios.
            // Implications of this decision is that existing file of size 0 opened in OpenOrCreate Mode 
            // will be treated as a newly/created file. 
            if ((_openMode == FileMode.CreateNew) ||
               (_openMode == FileMode.Create) || 
               ((_openMode == FileMode.OpenOrCreate) && archiveStream.Length == 0))
            {
                _blockManager.CreateEndOfCentralDirectoryBlock();
            } 
            else
            { 
                _blockManager.LoadEndOfCentralDirectoryBlock(); 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Methods 
        //
        //----------------------------------------------------- 
 
        /// 
        /// Dispose(bool) 
        /// 
        /// 
        private void Dispose(bool disposing)
        { 
            if (disposing)
            { 
                if (!_disposedFlag) 
                {
                    try 
                    {
                        // allow this in Debug mode to catch any place where we accidentally
                        // make something dirty when we are read-only
#if !DEBUG 
                        if (_openAccess == FileAccess.ReadWrite || _openAccess == FileAccess.Write)
#endif 
                        { 
                            _blockManager.Save(true);
                        } 

                        ((IDisposable)_blockManager).Dispose();
                    }
                    finally 
                    {
                        _disposedFlag = true; 
                    } 
                }
            } 
        }

        /// 
        /// This is function is called by the OpenOnFile and OpenOnStream in order 
        /// to validate parameteresgiven to those functions. The combinations of valid
        /// parameters is quite complex and not obvious, so after basic range checks, 
        /// it is actually using a lookup table to answer the question whether the given 
        /// parameter  combination is valid or not.
        ///  
        static private void ValidateModeAccessShareStreaming(Stream stream, FileMode mode, FileAccess access, FileShare share, bool streaming)
        {
            if (stream == null)
            { 
                throw new ArgumentNullException("stream");
            } 
 
            ////////////
            // filter out values that are out of enum ranges first 
            ////////////
            ValidateModeAccessShareValidEnums(mode, access, share);

            //////////// 
            // filter out values that are not supported regardless of other parameters
            // but still validate enum members 
            //////////// 
            ValidateModeAccessShareSupportedEnums(mode, share);
 
            ////////////
            // let's makes sure that given stream is capable of supporting required functionality
            ////////////
            ValidateModeAccessStreamStreamingCombinations(stream, access, streaming); 

            //////////// 
            //let's make sure that comnbintaion of mode, access,share,,streaming 
            // parameters is supported
            //////////// 
            int intMode =  Convert.ToInt32(mode, CultureInfo.InvariantCulture);
            int intAccess = Convert.ToInt32(access, CultureInfo.InvariantCulture);
            int intShare = Convert.ToInt32(share, CultureInfo.InvariantCulture);
            int intStreaming = Convert.ToInt32(streaming, CultureInfo.InvariantCulture); 
            for(int i=0; i<_validOpenParameters.GetLength(0); i++)
            { 
                if ((_validOpenParameters [i,0] == intMode) && 
                    (_validOpenParameters [i,1] == intAccess) &&
                    (_validOpenParameters [i,2] == intShare) && 
                    (_validOpenParameters [i,3] == intStreaming))
                {
                    return;
                } 
            }
 
            throw new ArgumentException(SR.Get(SRID.UnsupportedCombinationOfModeAccessShareStreaming)); 
        }
 
        static private void ValidateModeAccessStreamStreamingCombinations(Stream stream, FileAccess access, bool streaming)
        {
            ////////////
            // let's makes sure that given stream is capable of supporting required functionality 
            ////////////
            if ((access== FileAccess.Read || access == FileAccess.ReadWrite) && !stream.CanRead) 
            { 
                throw new ArgumentException(SR.Get(SRID.CanNotReadDataFromStreamWhichDoesNotSupportReading));
            } 

            // if user want to be able to write stream needs to support it
            if ((access == FileAccess.Write || access == FileAccess.ReadWrite) && !stream.CanWrite)
            { 
                throw new ArgumentException(SR.Get(SRID.CanNotWriteDataToStreamWhichDoesNotSupportWriting));
            } 
 
            // if user works in non-streaming mode we need to Seek on underlying stream
            if (! streaming && !stream.CanSeek) 
            {
                throw new ArgumentException(SR.Get(SRID.CanNotOperateOnStreamWhichDoesNotSupportSeeking));
            }
        } 

        static private void ValidateModeAccessShareSupportedEnums(FileMode mode, FileShare share) 
        { 
            ////////////
            // filter out values that are not supported regardless of other parameters 
            // but still validate enum members
            ////////////
             if (mode == FileMode.Append || mode == FileMode.Truncate)
            { 
                throw new NotSupportedException(SR.Get(SRID.TruncateAppendModesNotSupported));
            } 
            else if (share != FileShare.Read && share != FileShare.None) 
            {
                // later as we get to streaming other FileShare values will be supported too 
                throw new NotSupportedException (SR.Get(SRID.OnlyFileShareReadAndFileShareNoneSupported));
            }
        }
 
        static private void ValidateModeAccessShareValidEnums(FileMode mode, FileAccess access, FileShare share)
        { 
            //////////// 
            // filter out values that are out of enum ranges first
            //////////// 
            if ((mode != FileMode.Append) && (mode != FileMode.Create) && (mode != FileMode.CreateNew) && (mode != FileMode.Open)
                && (mode != FileMode.OpenOrCreate) && (mode != FileMode.Truncate))
            {
                throw new ArgumentOutOfRangeException("mode"); 
            }
            else if ((access != FileAccess.Read) && (access != FileAccess.ReadWrite) && (access != FileAccess.Write)) 
            { 
                throw new ArgumentOutOfRangeException("access");
            } 
            else if ((share != FileShare.Delete) && (share != FileShare.Inheritable) && (share != FileShare.None) &&
                (share != FileShare.Read) && (share != FileShare.ReadWrite) && (share != FileShare.Write))
            {
                throw new ArgumentOutOfRangeException("share"); 
            }
        } 
 
        /// 
        /// Throws exception if object already Disposed/Closed. 
        /// 
        private void CheckDisposed()
        {
            if (_disposedFlag) 
            {
                throw new ObjectDisposedException(null, SR.Get(SRID.ZipArchiveDisposed)); 
            } 
        }
 
        //------------------------------------------------------
        //
        //  Private Properties
        // 
        //-----------------------------------------------------
        ///  
        /// This private property is used as a mean to achieve lazy memory allocation for the 
        /// hashtable that maintains a cahce of the returned instrances of ZipFileInfo(s).
        /// This hashtable uses file names as keys in the case insensitive and culture invariant fashion 
        /// 
        private IDictionary ZipFileInfoDictionary
        {
            get 
            {
                if (_zipFileInfoDictionary == null) 
                { 
                                // ordinal case sensitive comparison
                    _zipFileInfoDictionary = new Hashtable(_zipFileInfoDictionaryInitialSize, StringComparer.Ordinal); 
                }
                return _zipFileInfoDictionary;
            }
        } 

        //----------------------------------------------------- 
        // 
        //  Private Fields
        // 
        //-----------------------------------------------------

        // This 2 dimensional table is used by the ValidateModeAccessShareStreaming
        // function as a set of valid parameter combinations 
        static private int[,] _validOpenParameters = new int[,]
        {   // FileMode                             // FileAccess                     / FileShare                     // streaming 
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.None,        1}, 
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.Read,        1},
            {(int)FileMode.Create,             (int)FileAccess.ReadWrite, (int)FileShare.None,        0}, 
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.None,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.Read,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.ReadWrite, (int)FileShare.None,        0},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        0},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        0}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Write,        1},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.ReadWrite, 1}, 
            {(int)FileMode.Open,               (int)FileAccess.ReadWrite,  (int)FileShare.None,        0},
            {(int)FileMode.OpenOrCreate,  (int)FileAccess.ReadWrite,  (int)FileShare.None,        0}
        };
 
        // modes that were used for openning (OpenOnStream or OpenOnFile),
        // there is no way to change these values after class is constructed 
        private FileMode _openMode; 
        private FileAccess  _openAccess;
 
        private bool _disposedFlag;

        // reference to the ZipIOBlockManager, this reference is instantiated as
        // a part of the OpenOnFile/OpenOnStream contruction 
        private ZipIOBlockManager _blockManager;
 
        // this is a Dictionary of all the ZipFileInfos that were given out. 
        // It uses file name as key in case insensitive and culture invariant fashion.
        // all members of the class are supposed to use this field indirectly through 
        // ZipFileInfoDictionary property, as ZipFileInfoDictionary is respnsible
        // for lazy allocation of the hashtable.
        private IDictionary _zipFileInfoDictionary;
        private const int _zipFileInfoDictionaryInitialSize = 50; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------ 
//-------------   *** WARNING ***
//-------------    This file is part of a legally monitored development project.
//-------------    Do not check in changes to this project.  Do not raid bugs on this
//-------------    code in the main PS database.  Do not contact the owner of this 
//-------------    code directly.  Contact the legal team at �ZSLegal� for assistance.
//-------------   *** WARNING *** 
//----------------------------------------------------------------------------- 

//----------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//  This is an internal class that enables interactions with Zip archives 
//  for OPC scenarios
// 
// History:
//  11/19/2004: IgorBel: Initial creation.
//
//----------------------------------------------------------------------------- 

using System; 
using System.IO; 
using System.Diagnostics;
using System.Collections; 
using System.Globalization;
using System.Runtime.Serialization;
using System.Windows;
 
namespace MS.Internal.IO.Zip
{ 
    ///  
    ///  This is the main clas of the ZIP IO internal APIs. It has 2 stsatic constructors
    /// OpenOnFile and OpenOnStream. It provides client app with ability to manipulate 
    /// a Zip Archive (create, open, open/add/delete file items).
    /// 
    internal sealed class ZipArchive : IDisposable
    { 
        //------------------------------------------------------
        // 
        //  Public Members 
        //
        //----------------------------------------------------- 
        // None

        //------------------------------------------------------
        // 
        //  Internal Constructors
        // 
        //------------------------------------------------------ 
        // None
 
        //-----------------------------------------------------
        //
        // Internal API Methods (although these methods are marked as
        // Internal, they are part of the internal ZIP IO API surface 
        //
        //------------------------------------------------------ 
        ///  
        ///  Static constructor File based constructor. all parameteres are obvious.
        ///  This constructor wil  open the file in requested mode, and it will not do any futher parsing. 
        ///
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord. 
        /// 
        internal static ZipArchive OpenOnFile(string path, FileMode mode, FileAccess access, FileShare share, bool streaming) 
        { 
            if (mode == FileMode.OpenOrCreate || mode == FileMode.Open)
            { 
                // for OpenOrCreate cases we need to check whether it is an exisiting file of size 0.
                // Files of size 0 are onsidered invalid ZipArchives. If we skip this check here, later we wouldn't be able to distinguish
                // between brand new file being created as a result of OpenOrCreate mode, or old 0 length file being open as a result of
                // OpenOrCreate mode. 
                FileInfo fileInfo = new FileInfo(path);
 
                if (fileInfo.Exists && (fileInfo.Length == 0)) 
                {
                    throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive)); 
                }
            }

            ZipArchive archive = null; 
            FileStream archiveStream = null;
 
            // We would like to run initialization after openning stream in try/catch block 
            // so that if anything goes wrong we can close the stream (release file handler)
            try 
            {
                archiveStream = new FileStream(path, mode, access, share, 4096, streaming);

                ValidateModeAccessShareStreaming(archiveStream, mode, access, share, streaming); 

                archive = new ZipArchive(archiveStream, mode, access, streaming, true); 
            } 
            catch
            { 
                if (archiveStream != null)
                {
                    archiveStream.Close();
                } 

                throw; 
            } 

            return archive; 
        }

        /// 
        ///  Static constructor Stream based constructor. all parameteres are obvious. 
        ///  This constructor wil not do any futher parsing.
        /// 
        /// In the case of Create/CreateNew, it will also prebuild in cached in-memory 
        /// EndOfCentralDirectoryRecord (which is a minimal zip file requirement), so that if user
        /// chooses to close right after he will get a file with just EndOfCentralDirectoryRecord. 
        /// 
        internal static ZipArchive OpenOnStream(Stream stream, FileMode mode, FileAccess access, bool streaming)
        {
            // we can assume FileShare.None, as there is absolutely nothing we can do 
            // about other people working with the underlying storage
            ValidateModeAccessShareStreaming(stream, mode, access, FileShare.None, streaming); 
 
            if (stream.CanSeek)
            { 
                bool emptyStream = (stream.Length == 0);

                switch (mode)
                { 
                    // for Open cases we need to check whether it is an existing file of size 0.
                    // Streams of size 0 are considered invalid ZipArchives. 
                    case FileMode.Open: 
                        if (emptyStream)
                        { 
                            throw new FileFormatException(SR.Get(SRID.ZipZeroSizeFileIsNotValidArchive));
                        }
                        break;
 
                    // for Create cases, we need to check if the stream is empty or not
                    case FileMode.CreateNew: 
                        if (!emptyStream) 
                        {
                            throw new IOException(SR.Get(SRID.CreateNewOnNonEmptyStream)); 
                        }
                        break;
                    case FileMode.Create:
                        if (!emptyStream) 
                        {
                            // discard existing data 
                            stream.SetLength(0); 
                        }
                        break; 
                }
            }

            return new ZipArchive(stream, mode, access, streaming, false); 
        }
 
 
        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that (assuming no duplicates were found). It will create in appropriate
        /// in memory Local FileHeaders and Central Directory Headers.
        ///  
        internal ZipFileInfo AddFile(string zipFileName, CompressionMethodEnum compressionMethod, DeflateOptionEnum deflateOption)
        { 
            CheckDisposed(); 

            if (_openAccess == FileAccess.Read) 
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode));
            }
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 
 
            if ((compressionMethod != CompressionMethodEnum.Stored) &&
                (compressionMethod != CompressionMethodEnum.Deflated)) 
            {
                throw new ArgumentOutOfRangeException("compressionMethod");
            }
 
            // non-contiguous range requires more complex test
            if (deflateOption < DeflateOptionEnum.Normal || ( 
                deflateOption > DeflateOptionEnum.SuperFast && deflateOption != DeflateOptionEnum.None)) 
            {
                throw new ArgumentOutOfRangeException("deflateOption"); 
            }

            // Check for duplicates ,
            if (FileExists(zipFileName)) 
            {
                throw new System.InvalidOperationException(SR.Get(SRID.AttemptedToCreateDuplicateFileName)); 
            } 

            // Create Local File Block through Block Manager 
            ZipIOLocalFileBlock fileBlock = _blockManager.CreateLocalFileBlock(zipFileName, compressionMethod, deflateOption);

            //build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo,
            // that were given out  and invalidate any collection that was returned on GetFiles calls 
            ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock);
            ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo); 
 
            return zipFileInfo;
        } 

        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that (assuming the file was found). It will parse the apropriate local file block
        /// header and data descriptor (if present). 
        ///  
        internal ZipFileInfo GetFile(string zipFileName)
        { 
            CheckDisposed();

            if (_openAccess == FileAccess.Write)
            { 
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode));
            } 
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 

            // try to get it from the ZipFileInfo dictionary
            if (ZipFileInfoDictionary.Contains(zipFileName))
            { 
                // this ZipFileInfo was already built through AddFile or GetFile(s)
                // we have this cached 
                return (ZipFileInfo)(ZipFileInfoDictionary[zipFileName]); 
            }
            else 
            {
                // we need to check whether it is present in the central directory
                if (!FileExists(zipFileName))
                { 
                    throw new InvalidOperationException(SR.Get(SRID.FileDoesNotExists));
                } 
 
                // Load Local File Block through Block Manager
                ZipIOLocalFileBlock fileBlock = _blockManager.LoadLocalFileBlock(zipFileName); 

                // build new ZipFileInfo and add reference to the collection, so we can keep track of the instances of the ZipFileInfo,
                // that were given out  and invalidate any collection that was returned on GetFiles calls
                ZipFileInfo zipFileInfo = new ZipFileInfo(this, fileBlock); 

                //this should invalidate any outstanding collections 
                ZipFileInfoDictionary.Add(zipFileInfo.Name, zipFileInfo); 

                return zipFileInfo; 
            }
        }

        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet). 
        /// After that it will check whether central directory contains the file. 
        /// It will not attempt the parsing of the local file headers / descriptors.
        ///  
        internal bool FileExists (string zipFileName)
        {
            CheckDisposed();
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName); 
 
            return _blockManager.CentralDirectoryBlock.FileExists(zipFileName);
        } 


        /// 
        ///  This method will result in a complete parsing of the EndOfCentralDirectory 
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that it will check whether central directory contains the file. 
        /// If it is present it will parse local fileheader, and remove their in memory 
        /// representation
        ///  
        internal void DeleteFile (string zipFileName)
        {
            CheckDisposed();
 
            if (_openAccess == FileAccess.Read)
            { 
                throw new InvalidOperationException(SR.Get(SRID.CanNotWriteInReadOnlyMode)); 
            }
 
            // Validate parameteres
            zipFileName = ZipIOBlockManager.ValidateNormalizeFileName(zipFileName);

            if (FileExists(zipFileName)) // is it in central Directory ? 
            {
                ZipFileInfo fileInfoToBeDeleted  = GetFile(zipFileName); 
 
                //this should invalidate any outstanding collections
                // and update central directory status as appropriate 
                ZipFileInfoDictionary.Remove(zipFileName);

                //this should remove the local file block
                // from the blockManager's collection 
                _blockManager.RemoveLocalFileBlock(fileInfoToBeDeleted.LocalFileBlock);
            } 
        } 

        ///  
        ///  This method will result in a complete parsing of the EndOfCentralDirectory
        /// and CentralDirectory records (if it hasn't been done yet).
        /// After that it will go through allfiles in the central directory and parse their
        /// local headers and desciptors one by one. 
        /// 
        internal ZipFileInfoCollection GetFiles() 
        { 
            CheckDisposed();
 
            if (_openAccess == FileAccess.Write)
            {
                throw new InvalidOperationException(SR.Get(SRID.CanNotReadInWriteOnlyMode));
            } 

            // We need to scan through the central Directory, and for each file 
            // call GetFile(fileName), which will result in adding missing (not loaded) 
            // information to the ZipFileInfoDictionary.
            foreach(string fileName in _blockManager.CentralDirectoryBlock.GetFileNamesCollection()) 
            {
                GetFile(fileName);  // fileName must be validated and normalized at this
                                            // point by the central directory parsing routine
            } 
            return new ZipFileInfoCollection(ZipFileInfoDictionary.Values);
        } 
 
        /// 
        ///  This method will result in a complete Flushing of any outstanding data in buffers and 
        /// any streams ever returned by the GetStream calls.This call results in Archive file that
        /// has a completely valid state. If application were to crash right afte the Flush is complete,
        /// the resulting files would be a "valid" Zip archive
        ///  
        internal void Flush()
        { 
            CheckDisposed(); 
            _blockManager.Save(false);
        } 

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects
        /// ZipFileInfo, Streams ZipArchive. 
        /// 
        internal void Close() 
        { 
            Dispose();
        } 

        /// 
        /// Results in a complete Flush of all the outstanding buffers and closing/disposing all of the objects
        /// ZipFileInfo, Streams ZipArchive. 
        /// 
        public void Dispose() 
        { 
            Dispose(true);
            // GC.SuppressFinalize(this);  // Because this class is sealed and there is no Finalizer, 
                                                        // there is no need for this call. Leaving it in case we decide to unseal it
        }

        ///  
        /// Throw if version needed to extract is not supported
        ///  
        /// version to inspect 
        static internal void VerifyVersionNeededToExtract(UInt16 version)
        { 
            // strictly enforce this list
            switch (version)
            {
                case (UInt16)ZipIOVersionNeededToExtract.StoredData: break; 
                case (UInt16)ZipIOVersionNeededToExtract.VolumeLabel: break;
                case (UInt16)ZipIOVersionNeededToExtract.DeflatedData: break; 
                case (UInt16)ZipIOVersionNeededToExtract.Zip64FileFormat: break; 
                default:
                    throw new NotSupportedException(SR.Get(SRID.NotSupportedVersionNeededToExtract)); 
            }
        }

        //----------------------------------------------------- 
        //
        //  Internal Properties 
        // 
        //-----------------------------------------------------
        ///  
        /// Read only property, that returns the value of FileAccess that
        /// was passed into the OpenOnFile or OpenOnStream call
        /// 
        internal FileAccess OpenAccess 
        {
            get 
            { 
                CheckDisposed();
                return _openAccess; 
            }
        }

//  This functionality commented out in order to comply with FX Cop rule 
//  AvoidUncalledPrivateCode. However, because of a chance that this functionality
//  might eventually get public exposure we would like to keep this code around 
#if ZIP_IO_PUBLIC 

        ///  
        /// Returns Comment field from the End Of Central Directory Record.
        /// Therefore, call to this property might result in some parsing.
        /// If the End Of Central Directory isn't parsed yet, it will be as a
        /// result of querying this property. 
        /// 
        internal string Comment 
        { 
            get
            { 
                CheckDisposed();
                return _blockManager.EndOfCentralDirectoryBlock.Comment;
            }
        } 
#endif
 
 
        //-----------------------------------------------------
        // 
        // Internal NON API Methods (these methods are marked as
        // Internal, and they are trully internal and not the part of the
        // internal ZIP IO API surface
        // 
        //------------------------------------------------------
 
        //----------------------------------------------------- 
        //
        //  Private Constructors 
        //
        //------------------------------------------------------
        /// 
        /// This private constructor isonly supposed to be called by the 
        /// OpenOnFile and OpenOnStream static members.
        ///  
        ///  
        /// 
        ///  
        /// 
        /// true if this class is responsible for closing the archiveStream
        private ZipArchive(Stream archiveStream, FileMode mode, FileAccess access, bool streaming, bool ownStream)
        { 
            // as this contructor is only called from the static member
            // all checks should have been done before 
 
            _blockManager = new ZipIOBlockManager(archiveStream, streaming, ownStream);
 
            _openMode = mode;
            _openAccess = access;

            // In case of "create" we also need to create at least an end of Central Directory Record. 
            // For FileMode OpenOrCreate we use stream Length to distinguish open and create scenarios.
            // Implications of this decision is that existing file of size 0 opened in OpenOrCreate Mode 
            // will be treated as a newly/created file. 
            if ((_openMode == FileMode.CreateNew) ||
               (_openMode == FileMode.Create) || 
               ((_openMode == FileMode.OpenOrCreate) && archiveStream.Length == 0))
            {
                _blockManager.CreateEndOfCentralDirectoryBlock();
            } 
            else
            { 
                _blockManager.LoadEndOfCentralDirectoryBlock(); 
            }
        } 

        //------------------------------------------------------
        //
        //  Private Methods 
        //
        //----------------------------------------------------- 
 
        /// 
        /// Dispose(bool) 
        /// 
        /// 
        private void Dispose(bool disposing)
        { 
            if (disposing)
            { 
                if (!_disposedFlag) 
                {
                    try 
                    {
                        // allow this in Debug mode to catch any place where we accidentally
                        // make something dirty when we are read-only
#if !DEBUG 
                        if (_openAccess == FileAccess.ReadWrite || _openAccess == FileAccess.Write)
#endif 
                        { 
                            _blockManager.Save(true);
                        } 

                        ((IDisposable)_blockManager).Dispose();
                    }
                    finally 
                    {
                        _disposedFlag = true; 
                    } 
                }
            } 
        }

        /// 
        /// This is function is called by the OpenOnFile and OpenOnStream in order 
        /// to validate parameteresgiven to those functions. The combinations of valid
        /// parameters is quite complex and not obvious, so after basic range checks, 
        /// it is actually using a lookup table to answer the question whether the given 
        /// parameter  combination is valid or not.
        ///  
        static private void ValidateModeAccessShareStreaming(Stream stream, FileMode mode, FileAccess access, FileShare share, bool streaming)
        {
            if (stream == null)
            { 
                throw new ArgumentNullException("stream");
            } 
 
            ////////////
            // filter out values that are out of enum ranges first 
            ////////////
            ValidateModeAccessShareValidEnums(mode, access, share);

            //////////// 
            // filter out values that are not supported regardless of other parameters
            // but still validate enum members 
            //////////// 
            ValidateModeAccessShareSupportedEnums(mode, share);
 
            ////////////
            // let's makes sure that given stream is capable of supporting required functionality
            ////////////
            ValidateModeAccessStreamStreamingCombinations(stream, access, streaming); 

            //////////// 
            //let's make sure that comnbintaion of mode, access,share,,streaming 
            // parameters is supported
            //////////// 
            int intMode =  Convert.ToInt32(mode, CultureInfo.InvariantCulture);
            int intAccess = Convert.ToInt32(access, CultureInfo.InvariantCulture);
            int intShare = Convert.ToInt32(share, CultureInfo.InvariantCulture);
            int intStreaming = Convert.ToInt32(streaming, CultureInfo.InvariantCulture); 
            for(int i=0; i<_validOpenParameters.GetLength(0); i++)
            { 
                if ((_validOpenParameters [i,0] == intMode) && 
                    (_validOpenParameters [i,1] == intAccess) &&
                    (_validOpenParameters [i,2] == intShare) && 
                    (_validOpenParameters [i,3] == intStreaming))
                {
                    return;
                } 
            }
 
            throw new ArgumentException(SR.Get(SRID.UnsupportedCombinationOfModeAccessShareStreaming)); 
        }
 
        static private void ValidateModeAccessStreamStreamingCombinations(Stream stream, FileAccess access, bool streaming)
        {
            ////////////
            // let's makes sure that given stream is capable of supporting required functionality 
            ////////////
            if ((access== FileAccess.Read || access == FileAccess.ReadWrite) && !stream.CanRead) 
            { 
                throw new ArgumentException(SR.Get(SRID.CanNotReadDataFromStreamWhichDoesNotSupportReading));
            } 

            // if user want to be able to write stream needs to support it
            if ((access == FileAccess.Write || access == FileAccess.ReadWrite) && !stream.CanWrite)
            { 
                throw new ArgumentException(SR.Get(SRID.CanNotWriteDataToStreamWhichDoesNotSupportWriting));
            } 
 
            // if user works in non-streaming mode we need to Seek on underlying stream
            if (! streaming && !stream.CanSeek) 
            {
                throw new ArgumentException(SR.Get(SRID.CanNotOperateOnStreamWhichDoesNotSupportSeeking));
            }
        } 

        static private void ValidateModeAccessShareSupportedEnums(FileMode mode, FileShare share) 
        { 
            ////////////
            // filter out values that are not supported regardless of other parameters 
            // but still validate enum members
            ////////////
             if (mode == FileMode.Append || mode == FileMode.Truncate)
            { 
                throw new NotSupportedException(SR.Get(SRID.TruncateAppendModesNotSupported));
            } 
            else if (share != FileShare.Read && share != FileShare.None) 
            {
                // later as we get to streaming other FileShare values will be supported too 
                throw new NotSupportedException (SR.Get(SRID.OnlyFileShareReadAndFileShareNoneSupported));
            }
        }
 
        static private void ValidateModeAccessShareValidEnums(FileMode mode, FileAccess access, FileShare share)
        { 
            //////////// 
            // filter out values that are out of enum ranges first
            //////////// 
            if ((mode != FileMode.Append) && (mode != FileMode.Create) && (mode != FileMode.CreateNew) && (mode != FileMode.Open)
                && (mode != FileMode.OpenOrCreate) && (mode != FileMode.Truncate))
            {
                throw new ArgumentOutOfRangeException("mode"); 
            }
            else if ((access != FileAccess.Read) && (access != FileAccess.ReadWrite) && (access != FileAccess.Write)) 
            { 
                throw new ArgumentOutOfRangeException("access");
            } 
            else if ((share != FileShare.Delete) && (share != FileShare.Inheritable) && (share != FileShare.None) &&
                (share != FileShare.Read) && (share != FileShare.ReadWrite) && (share != FileShare.Write))
            {
                throw new ArgumentOutOfRangeException("share"); 
            }
        } 
 
        /// 
        /// Throws exception if object already Disposed/Closed. 
        /// 
        private void CheckDisposed()
        {
            if (_disposedFlag) 
            {
                throw new ObjectDisposedException(null, SR.Get(SRID.ZipArchiveDisposed)); 
            } 
        }
 
        //------------------------------------------------------
        //
        //  Private Properties
        // 
        //-----------------------------------------------------
        ///  
        /// This private property is used as a mean to achieve lazy memory allocation for the 
        /// hashtable that maintains a cahce of the returned instrances of ZipFileInfo(s).
        /// This hashtable uses file names as keys in the case insensitive and culture invariant fashion 
        /// 
        private IDictionary ZipFileInfoDictionary
        {
            get 
            {
                if (_zipFileInfoDictionary == null) 
                { 
                                // ordinal case sensitive comparison
                    _zipFileInfoDictionary = new Hashtable(_zipFileInfoDictionaryInitialSize, StringComparer.Ordinal); 
                }
                return _zipFileInfoDictionary;
            }
        } 

        //----------------------------------------------------- 
        // 
        //  Private Fields
        // 
        //-----------------------------------------------------

        // This 2 dimensional table is used by the ValidateModeAccessShareStreaming
        // function as a set of valid parameter combinations 
        static private int[,] _validOpenParameters = new int[,]
        {   // FileMode                             // FileAccess                     / FileShare                     // streaming 
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.None,        1}, 
            {(int)FileMode.Create,             (int)FileAccess.Write,        (int)FileShare.Read,        1},
            {(int)FileMode.Create,             (int)FileAccess.ReadWrite, (int)FileShare.None,        0}, 
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.None,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.Write,        (int)FileShare.Read,        1},
            {(int)FileMode.CreateNew,       (int)FileAccess.ReadWrite, (int)FileShare.None,        0},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.None,        0},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        1}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Read,        0}, 
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.Write,        1},
            {(int)FileMode.Open,               (int)FileAccess.Read,         (int)FileShare.ReadWrite, 1}, 
            {(int)FileMode.Open,               (int)FileAccess.ReadWrite,  (int)FileShare.None,        0},
            {(int)FileMode.OpenOrCreate,  (int)FileAccess.ReadWrite,  (int)FileShare.None,        0}
        };
 
        // modes that were used for openning (OpenOnStream or OpenOnFile),
        // there is no way to change these values after class is constructed 
        private FileMode _openMode; 
        private FileAccess  _openAccess;
 
        private bool _disposedFlag;

        // reference to the ZipIOBlockManager, this reference is instantiated as
        // a part of the OpenOnFile/OpenOnStream contruction 
        private ZipIOBlockManager _blockManager;
 
        // this is a Dictionary of all the ZipFileInfos that were given out. 
        // It uses file name as key in case insensitive and culture invariant fashion.
        // all members of the class are supposed to use this field indirectly through 
        // ZipFileInfoDictionary property, as ZipFileInfoDictionary is respnsible
        // for lazy allocation of the hashtable.
        private IDictionary _zipFileInfoDictionary;
        private const int _zipFileInfoDictionaryInitialSize = 50; 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK