//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // // gpaperin //------------------------------------------------------------------------------ using System.Text; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Runtime.CompilerServices; using System.Runtime.ConstrainedExecution; using Microsoft.Win32.SafeHandles; using System.Security.Permissions; using System.Diagnostics.Contracts; using System.Security; namespace System.IO.Compression { /// /// This class provides declaration for constants and PInvokes as well as some basic tools for exposing the /// native CLRCompression.dll (effectively, ZLib) library to managed code. /// /// This file can be included into any managed project that needs to reference CLRCompression.dll. /// Thus, it is located together with the CLRCompression build files that produce the unmanaged CLRCompression.dll /// /// ** How to refer to this file from your build project: ** /// /// - The master copy of this file is located under /// ndp\fx\src\CLRCompression\System\IO\Compression\ZLibNative.cs . /// (together with all native CLRCompression sources which are under ndp\fx\src\CLRCompression\zlib-1.2.3\) /// /// - The CLRCompression assembly build project for will publish this file to /// \\InterAPIsCandidates\NDP_FX\inc\ . /// Projects within the NDP_FX partition can consume this file from there. /// /// - After every change, this file must also be published to /// InternalApis\NDP_FX\inc\ . /// Projects outside NDP_FX can consume this files from that location. /// /// In either case, the msbuild variable $(NDP_FXIncPath) should include the one of the above directories that /// is appropriate for the project. /// /// Projects outside the FX partition can declare a dependency on NDP_FX in their /// partition.settings.targets, which will cause the right path to be automatically added to their include path list. /// /// Projects inside FX can also use $(InterAPIsCandidatesPath)\inc\ instead of $(NDP_FXIncPath) if the latter is broken. /// /// If some additional ZLib functionality needs to be exposed in future, there are (at least) 3 files that need /// to be updated: /// 1) clrcompression.def : To list the DLL entry points. /// 2) clrcompression.nativeproj : To list all the required ZLib source files /// (sources that are not required for the currently exposed functionality are commented out). /// 3) This file (ZLibNative.cs) : To include PInvoke declarations / delegates for all necessary routines. /// /// /// See also: How to choose a compression level (in comments to CompressionLevel. /// internal static class ZLibNative { #region File name constants public const string ZLibNativeDllName = "clrcompression.dll"; private const string Kernel32DllName = "kernel32.dll"; #endregion // File name constants #region Constants defined in zlib.h public const string ZLibVersion = "1.2.3"; // This is the NULL pointer for using with ZLib pointers; // we prefer it to IntPtr.Zero to mimic the definition of Z_NULL in zlib.h: internal static readonly IntPtr ZNullPtr = (IntPtr) ((Int32) 0); public enum FlushCode : int { NoFlush = 0, PartialFlush = 1, SyncFlush = 2, FullFlush = 3, Finish = 4, Block = 5, //Trees = 6 // Only in ZLib 1.2.4 and later } public enum ErrorCode : int { Ok = 0, StreamEnd = 1, NeedDictionary = 2, ErrorNo = -1, StreamError = -2, DataError = -3, MemError = -4, BufError = -5, VersionError = -6 } /// ///

ZLib can accept any integer value between 0 and 9 (inclusive) as a valid compression level parameter: /// 1 gives best speed, 9 gives best compression, 0 gives no compression at all (the input data is simply copied a block at a time). /// CompressionLevel.DefaultCompression = -1 requests a default compromise between speed and compression /// (currently equivalent to level 6).

/// ///

How to choose a compression level:

/// ///

The names NoCompression, BestSpeed, BestCompression are taken over from the corresponding /// ZLib definitions. However, extensive compression performance tests on real data show that they do not describe the reality well. /// We have run a large number of tests on different data sets including binary data, English language text, JPEG images and source code. /// The results show:

/// ///

We recommend using one of the three following combinations:
/// (See also the constants Deflate_DefaultWindowBits and Deflate_DefaultMemLevel below.)

/// ///

Optimal Compression:

///

ZLibNative.CompressionLevel compressionLevel = (ZLibNative.CompressionLevel) 6;
/// Int32 windowBits = 15; // or -15 if no headers required
/// Int32 memLevel = 8;
/// ZLibNative.CompressionStrategy strategy = ZLibNative.CompressionStrategy.DefaultStrategy;

/// ///

Fastest compression:

///

ZLibNative.CompressionLevel compressionLevel = (ZLibNative.CompressionLevel) 1;
/// Int32 windowBits = 15; // or -15 if no headers required
/// Int32 memLevel = 8;
/// ZLibNative.CompressionStrategy strategy = ZLibNative.CompressionStrategy.DefaultStrategy;

/// ///

No compression (even faster, useful for data that cannot be compressed such some image formats):

///

ZLibNative.CompressionLevel compressionLevel = (ZLibNative.CompressionLevel) 0;
/// Int32 windowBits = 15; // or -15 if no headers required
/// Int32 memLevel = 7;
/// ZLibNative.CompressionStrategy strategy = ZLibNative.CompressionStrategy.DefaultStrategy;

///
public enum CompressionLevel : int { NoCompression = 0, BestSpeed = 1, BestCompression = 9, // Refer to "How to choose a compression level" above. DefaultCompression = -1 } /// ///

From the ZLib manual:

///

CompressionStrategy is used to tune the compression algorithm.
/// Use the value DefaultStrategy for normal data, Filtered for data produced by a filter (or predictor), /// HuffmanOnly to force Huffman encoding only (no string match), or Rle to limit match distances to one /// (run-length encoding). Filtered data consists mostly of small values with a somewhat random distribution. In this case, the /// compression algorithm is tuned to compress them better. The effect of Filtered is to force more Huffman coding and] /// less string matching; it is somewhat intermediate between DefaultStrategy and HuffmanOnly. /// Rle is designed to be almost as fast as HuffmanOnly, but give better compression for PNG image data. /// The strategy parameter only affects the compression ratio but not the correctness of the compressed output even if it is not set /// appropriately. Fixed prevents the use of dynamic Huffman codes, allowing for a simpler decoder for special applications.

/// ///

For NetFx use:

///

We have investigated compression scenarios for a bunch of different requently occuring compression data and found that in all /// cases we invesigated so far, DefaultStrategy provided best results

///

See also: How to choose a compression level (in comments to CompressionLevel.

///
public enum CompressionStrategy : int { Filtered = 1, HuffmanOnly = 2, Rle = 3, Fixed = 4, DefaultStrategy = 0 } /// /// In version 1.2.3, ZLib provides on the Deflated-CompressionMethod. /// public enum CompressionMethod : int { Deflated = 8 } #endregion // Constants defined in zlib.h #region Defaults for ZLib parameters /// ///

From the ZLib manual:

///

ZLib's windowBits parameter is the base two logarithm of the window size (the size of the history buffer). /// It should be in the range 8..15 for this version of the library. Larger values of this parameter result in better compression /// at the expense of memory usage. The default value is 15 if deflateInit is used instead.
/// Note: /// windowBits can also be –8..–15 for raw deflate. In this case, -windowBits determines the window size. /// Deflate will then generate raw deflate data with no ZLib header or trailer, and will not compute an adler32 check value.
/// windowBits can also be greater than 15 for optional gzip encoding. Add 16 to windowBits to write a simple /// GZip header and trailer around the compressed data instead of a ZLib wrapper. The GZip header will have no file name, no extra data, /// no comment, no modification time (set to zero), no header crc, and the operating system will be set to 255 (unknown). /// If a GZip stream is being written, ZStream.adler is a crc32 instead of an adler32.

///

See also: How to choose a compression level (in comments to CompressionLevel.

///
public const int Deflate_DefaultWindowBits = -15; // Leagl values are 8..15 and -8..-15. 15 is the window size, // negative val causes deflate to produce raw deflate data (no zlib header). /// ///

From the ZLib manual:

///

The memLevel parameter specifies how much memory should be allocated for the internal compression state. /// memLevel = 1 uses minimum memory but is slow and reduces compression ratio; memLevel = 9 uses maximum /// memory for optimal speed. The default value is 8.

///

See also: How to choose a compression level (in comments to CompressionLevel.

///
public const int Deflate_DefaultMemLevel = 8; // Memory usage by deflate. Legal range: [1..9]. 8 is ZLib default. // More is faster and better compression with more memory usage. #endregion // Defaults for ZLib parameters #region ZLib stream descriptor data structure /// /// Do not construct instances of ZStream explicitly. /// Always use ZLibNative.DeflateInit2_ or ZLibNative.InflateInit2_ instead. /// Those methods will wrap this structure into a SafeHandle and thus make sure that it is always disposed correctly. /// [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)] internal struct ZStream { internal IntPtr nextIn; //Bytef *next_in; /* next input byte */ internal UInt32 availIn; //uInt avail_in; /* number of bytes available at next_in */ internal UInt32 totalIn; //uLong total_in; /* total nb of input bytes read so far */ internal IntPtr nextOut; //Bytef *next_out; /* next output byte should be put there */ internal UInt32 availOut; //uInt avail_out; /* remaining free space at next_out */ internal UInt32 totalOut; //uLong total_out; /* total nb of bytes output so far */ internal IntPtr msg; //char *msg; /* last error message, NULL if no error */ internal IntPtr state; //struct internal_state FAR *state; /* not visible by applications */ internal IntPtr zalloc; //alloc_func zalloc; /* used to allocate the internal state */ internal IntPtr zfree; //free_func zfree; /* used to free the internal state */ internal IntPtr opaque; //voidpf opaque; /* private data object passed to zalloc and zfree */ internal Int32 dataType; //int data_type; /* best guess about the data type: binary or text */ internal UInt32 adler; //uLong adler; /* adler32 value of the uncompressed data */ internal UInt32 reserved; //uLong reserved; /* reserved for future use */ } #endregion // ZLib stream descriptor data structure #region PInvoke declarations for wrapped native functions [UnmanagedFunctionPointer(CallingConvention.StdCall)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] private delegate ErrorCode DeflateInit2_Delegate(ref ZStream stream, CompressionLevel level, CompressionMethod method, int windowBits, int memLevel, CompressionStrategy strategy, [MarshalAs(UnmanagedType.LPStr)] string version, int streamSize); [UnmanagedFunctionPointer(CallingConvention.StdCall)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] private delegate ErrorCode DeflateDelegate(ref ZStream stream, FlushCode flush); [UnmanagedFunctionPointer(CallingConvention.StdCall)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] private delegate ErrorCode DeflateEndDelegate(ref ZStream stream); [UnmanagedFunctionPointer(CallingConvention.StdCall)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] private delegate ErrorCode InflateInit2_Delegate(ref ZStream stream, int windowBits, [MarshalAs(UnmanagedType.LPStr)] string version, int streamSize); [UnmanagedFunctionPointer(CallingConvention.StdCall)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] private delegate ErrorCode InflateDelegate(ref ZStream stream, FlushCode flush); [UnmanagedFunctionPointer(CallingConvention.StdCall)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] private delegate ErrorCode InflateEndDelegate(ref ZStream stream); [UnmanagedFunctionPointer(CallingConvention.StdCall)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] private delegate Int32 ZlibCompileFlagsDelegate(); #endregion // PInvoke declarations for wrapped native functions #region Declarations of Windows API needed to load the native library // As described at the top of this file, this file may be used in several managed DLLs that require ZLib // functionality. Thus we cannot rely on a specific internal XXXNativeMethod class to declare Windows APIs. // Instead, let us declare them explicitly: private class NativeMethods { [DllImport(Kernel32DllName, CharSet=CharSet.Ansi, BestFitMapping=false)] [ResourceExposure(ResourceScope.Process)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] internal static extern IntPtr GetProcAddress(SafeLibraryHandle moduleHandle, String procName); [DllImport(Kernel32DllName, CharSet=CharSet.Unicode, SetLastError=true)] [ResourceExposure(ResourceScope.Machine)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] internal static extern SafeLibraryHandle LoadLibrary(String libPath); #if !FEATURE_NETCORE [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] #endif [DllImport(Kernel32DllName, ExactSpelling=true)] [SuppressUnmanagedCodeSecurity] [SecurityCritical] internal static extern bool FreeLibrary(IntPtr moduleHandle); } #endregion // Declarations of Windows API needed to load the native library #region Handle to native DLL in memory // Handle type: [SecurityCritical] private class SafeLibraryHandle : SafeHandleZeroOrMinusOneIsInvalid { [SecurityCritical] internal SafeLibraryHandle() : base(true) { } #if !FEATURE_NETCORE [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] #endif [SecurityCritical] protected override bool ReleaseHandle() { bool res = ZLibNative.NativeMethods.FreeLibrary(handle); handle = IntPtr.Zero; return res; } } // private class SafeLibraryHandle #endregion // Handle to native DLL in memory /** * Do not remove the nested typing of types inside of System.IO.Compression.ZLibNative. * This was done on purpose to: * * - Achieve the right encapsulation in a situation where ZLibNative may be compiled division-wide * into different assemblies that wish to consume CLRCompression. Since internal * scope is effectively like public scope when compiling ZLibNative into a higher * level assembly, we need a combination of inner types and private-scope members to achieve * the right encapsulation. * * - Achieve late dynamic loading of CLRCompression.dll at the right time. * The native assembly will not be loaded unless it is actually used since the loading is performed by a static * constructor of an inner type that is not directly referenced by user code. * * In Dev12 we would like to create a proper feature for loading native assemblies from user-specified * directories in order to PInvoke into them. This would preferably happen in the native interop/PInvoke * layer; if not we can add a Framework level feature. */ #region ZLib Stream Handle type /// /// The ZLibStreamHandle could be a CriticalFinalizerObject rather than a /// SafeHandleMinusOneIsInvalid. This would save an IntPtr field since /// ZLibStreamHandle does not actually use its handle field. /// Instead it uses a private ZStream zStream field which is the actual handle data /// structure requiring critical finalization. /// However, we would like to take advantage if the better debugability offered by the fact that a /// releaseHandleFailed MDA is raised if the ReleaseHandle method returns /// false, which can for instance happen if the underlying ZLib XxxxEnd /// routines return an failure error code. /// [SecurityCritical] public sealed class ZLibStreamHandle : SafeHandleMinusOneIsInvalid { #region Library loading and initialisation [SecurityCritical] private static class NativeZLibDLLStub { #region Function pointers to native functions: [SecurityCritical] internal static DeflateInit2_Delegate deflateInit2_Delegate; [SecurityCritical] internal static DeflateDelegate deflateDelegate; [SecurityCritical] internal static DeflateEndDelegate deflateEndDelegate; [SecurityCritical] internal static InflateInit2_Delegate inflateInit2_Delegate; [SecurityCritical] internal static InflateDelegate inflateDelegate; [SecurityCritical] internal static InflateEndDelegate inflateEndDelegate; [SecurityCritical] internal static ZlibCompileFlagsDelegate zlibCompileFlagsDelegate; #endregion // Function pointers to native functions: #region Initialisation code #if !FEATURE_NETCORE // Security rules for CoreSys say the class is security critical, therefore this cannot be security safe critical. [SecuritySafeCritical] #endif private static void LoadZLibDLL() { #if !FEATURE_NETCORE new FileIOPermission(PermissionState.Unrestricted).Assert(); #endif String fxDir = RuntimeEnvironment.GetRuntimeDirectory(); String zlibDllPath = Path.Combine(fxDir, ZLibNativeDllName); if (!File.Exists(zlibDllPath)) throw new DllNotFoundException(ZLibNativeDllName); SafeLibraryHandle libHndl = ZLibNative.NativeMethods.LoadLibrary(zlibDllPath); if (libHndl.IsInvalid) { Int32 hresult = Marshal.GetHRForLastWin32Error(); Marshal.ThrowExceptionForHR(hresult, new IntPtr(-1)); // If Marshal.ThrowExceptionForHR did not throw, we still need to make sure to throw: throw new InvalidOperationException(); } ZLibStreamHandle.zlibLibraryHandle = libHndl; } [SecurityCritical] private static DT CreateDelegate
(String entryPointName) { IntPtr entryPoint = ZLibNative.NativeMethods.GetProcAddress(ZLibStreamHandle.zlibLibraryHandle, entryPointName); if (IntPtr.Zero == entryPoint) throw new EntryPointNotFoundException(ZLibNativeDllName + "!" + entryPointName); return (DT) (Object) Marshal.GetDelegateForFunctionPointer(entryPoint, typeof(DT)); } #if !FEATURE_NETCORE // Security rules for CoreSys say the class is security critical, therefore this cannot be security safe critical. [SecuritySafeCritical] #endif private static void InitDelegates() { Contract.Assert(null != ZLibStreamHandle.zlibLibraryHandle); Contract.Assert(!ZLibStreamHandle.zlibLibraryHandle.IsInvalid); deflateInit2_Delegate = CreateDelegate("deflateInit2_"); deflateDelegate = CreateDelegate("deflate"); deflateEndDelegate = CreateDelegate("deflateEnd"); inflateInit2_Delegate = CreateDelegate("inflateInit2_"); inflateDelegate = CreateDelegate("inflate"); inflateEndDelegate = CreateDelegate("inflateEnd"); zlibCompileFlagsDelegate = CreateDelegate("zlibCompileFlags"); #if !SILVERLIGHT RuntimeHelpers.PrepareDelegate(deflateInit2_Delegate); RuntimeHelpers.PrepareDelegate(deflateDelegate); RuntimeHelpers.PrepareDelegate(deflateEndDelegate); RuntimeHelpers.PrepareDelegate(inflateInit2_Delegate); RuntimeHelpers.PrepareDelegate(inflateDelegate); RuntimeHelpers.PrepareDelegate(inflateEndDelegate); RuntimeHelpers.PrepareDelegate(zlibCompileFlagsDelegate); #endif // !SILVERLIGHT } [SecuritySafeCritical] static NativeZLibDLLStub() { LoadZLibDLL(); InitDelegates(); } #endregion // Initialisation code } // private static class NativeZLibDLLStub // Handle reference: [SecurityCritical] private static SafeLibraryHandle zlibLibraryHandle; #endregion // Library loading and initialisation #region ZLibStream-SafeHandle-related routines public enum State { NotInitialized, InitializedForDeflate, InitializedForInflate, Disposed } private ZStream zStream; [SecurityCritical] private volatile State initializationState; public ZLibStreamHandle() : base(true) { this.zStream = new ZStream(); this.zStream.zalloc = ZNullPtr; this.zStream.zfree = ZNullPtr; this.zStream.opaque = ZNullPtr; this.initializationState = State.NotInitialized; this.handle = IntPtr.Zero; } public State InitializationState { [Pure] [SecurityCritical] get { return initializationState; } } #if !FEATURE_NETCORE [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] #endif [SecurityCritical] protected override bool ReleaseHandle() { // We are in a finalizer thread at the end of the App and the finalization of the dynamically loaded ZLib happend // to be scheduled first. In such case we have no hope of properly freeing zStream. If the process is dying - we // do not care. In other cases somethign went badly wrong anyway: if (zlibLibraryHandle == null || zlibLibraryHandle.IsInvalid) return false; switch (InitializationState) { case State.NotInitialized: return true; case State.InitializedForDeflate: return (DeflateEnd() == ZLibNative.ErrorCode.Ok); case State.InitializedForInflate: return (InflateEnd() == ZLibNative.ErrorCode.Ok); case State.Disposed: return true; default: return false; // This should never happen. Did we forget one of the State enum values in the switch? } } #endregion // ZLibStream-SafeHandle-related routines #region Expose fields on ZStream for use by user / Fx code (add more as required) public IntPtr NextIn { [SecurityCritical] get { return zStream.nextIn; } [SecurityCritical] set { zStream.nextIn = value; } } public UInt32 AvailIn { [SecurityCritical] get { return zStream.availIn; } [SecurityCritical] set { zStream.availIn = value; } } public UInt32 TotalIn { [SecurityCritical] get { return zStream.totalIn; } } public IntPtr NextOut { [SecurityCritical] get { return zStream.nextOut; } [SecurityCritical] set { zStream.nextOut = value; } } public UInt32 AvailOut { [SecurityCritical] get { return zStream.availOut; } [SecurityCritical] set { zStream.availOut = value; } } public UInt32 TotalOut { [SecurityCritical] get { return zStream.totalOut; } } public Int32 DataType { [SecurityCritical] get { return zStream.dataType; } } public UInt32 Adler { [SecurityCritical] get { return zStream.adler; } } #endregion // Expose fields on ZStream for use by user / Fx code (add more as required) #region Expose ZLib functions for use by user / Fx code (add more as required) [Pure] [SecurityCritical] private void EnsureNotDisposed() { if (InitializationState == State.Disposed) throw new ObjectDisposedException(this.GetType().Name); } [Pure] [SecurityCritical] private void EnsureState(State requiredState) { if (InitializationState != requiredState) throw new InvalidOperationException("InitializationState != " + requiredState.ToString()); } [SecurityCritical] public ErrorCode DeflateInit2_(CompressionLevel level, int windowBits, int memLevel, CompressionStrategy strategy) { EnsureNotDisposed(); EnsureState(State.NotInitialized); ErrorCode errC; bool addRefSuccess = false; #if !FEATURE_NETCORE RuntimeHelpers.PrepareConstrainedRegions(); #endif try { } finally { errC = NativeZLibDLLStub.deflateInit2_Delegate(ref zStream, level, CompressionMethod.Deflated, windowBits, memLevel, strategy, ZLibVersion, Marshal.SizeOf(zStream)); initializationState = State.InitializedForDeflate; zlibLibraryHandle.DangerousAddRef(ref addRefSuccess); } Contract.Assert(addRefSuccess, "zlibLibraryHandle.DangerousAddRef in DeflateInit2_ should always succeed, but it did not."); return errC; } [SecurityCritical] public ErrorCode Deflate(FlushCode flush) { EnsureNotDisposed(); EnsureState(State.InitializedForDeflate); return NativeZLibDLLStub.deflateDelegate(ref zStream, flush); } [SecurityCritical] public ErrorCode DeflateEnd() { EnsureNotDisposed(); EnsureState(State.InitializedForDeflate); ErrorCode errC; #if !FEATURE_NETCORE RuntimeHelpers.PrepareConstrainedRegions(); #endif try { } finally { errC = NativeZLibDLLStub.deflateEndDelegate(ref zStream); initializationState = State.Disposed; zlibLibraryHandle.DangerousRelease(); } return errC; } [SecurityCritical] public ErrorCode InflateInit2_(int windowBits) { EnsureNotDisposed(); EnsureState(State.NotInitialized); ErrorCode errC; bool addRefSuccess = false; #if !FEATURE_NETCORE RuntimeHelpers.PrepareConstrainedRegions(); #endif try { } finally { errC = NativeZLibDLLStub.inflateInit2_Delegate(ref zStream, windowBits, ZLibVersion, Marshal.SizeOf(zStream)); initializationState = State.InitializedForInflate; zlibLibraryHandle.DangerousAddRef(ref addRefSuccess); } Contract.Assert(addRefSuccess, "zlibLibraryHandle.DangerousAddRef in InflateInit2_ should always succeed, but it did not."); return errC; } [SecurityCritical] public ErrorCode Inflate(FlushCode flush) { EnsureNotDisposed(); EnsureState(State.InitializedForInflate); return NativeZLibDLLStub.inflateDelegate(ref zStream, flush); } [SecurityCritical] public ErrorCode InflateEnd() { EnsureNotDisposed(); EnsureState(State.InitializedForInflate); ErrorCode errC; #if !FEATURE_NETCORE RuntimeHelpers.PrepareConstrainedRegions(); #endif try { } finally { errC = NativeZLibDLLStub.inflateEndDelegate(ref zStream); initializationState = State.Disposed; zlibLibraryHandle.DangerousRelease(); } return errC; } [SecurityCritical] public string GetErrorMessage() { // This can work even after XxflateEnd(). if (ZNullPtr.Equals(zStream.msg)) return String.Empty; unsafe { String msgStr = new String((SByte*) zStream.msg); return msgStr; } } #endregion // Expose ZLib functions for use by user / Fx code (add more as required) [SecurityCritical] internal static Int32 ZLibCompileFlags() { return NativeZLibDLLStub.zlibCompileFlagsDelegate(); } } // class ZLibStreamHandle #endregion // ZLib Stream Handle type #region public factory methods for ZLibStreamHandle [SecurityCritical] public static ErrorCode CreateZLibStreamForDeflate(out ZLibStreamHandle zLibStreamHandle) { return CreateZLibStreamForDeflate(out zLibStreamHandle, CompressionLevel.DefaultCompression, Deflate_DefaultWindowBits, Deflate_DefaultMemLevel, CompressionStrategy.DefaultStrategy); } [SecurityCritical] public static ErrorCode CreateZLibStreamForDeflate(out ZLibStreamHandle zLibStreamHandle, CompressionLevel level, int windowBits, int memLevel, CompressionStrategy strategy) { zLibStreamHandle = new ZLibStreamHandle(); return zLibStreamHandle.DeflateInit2_(level, windowBits, memLevel, strategy); } [SecurityCritical] public static ErrorCode CreateZLibStreamForInflate(out ZLibStreamHandle zLibStreamHandle) { return CreateZLibStreamForInflate(out zLibStreamHandle, Deflate_DefaultWindowBits); } [SecurityCritical] public static ErrorCode CreateZLibStreamForInflate(out ZLibStreamHandle zLibStreamHandle, int windowBits) { zLibStreamHandle = new ZLibStreamHandle(); return zLibStreamHandle.InflateInit2_(windowBits); } #endregion // public factory methods for ZLibStreamHandle #region public utility APIs [SecurityCritical] public static Int32 ZLibCompileFlags() { return ZLibStreamHandle.ZLibCompileFlags(); } #endregion // public utility APIs } // internal class ZLibNative } // namespace System.IO.Compression // file ZLibNative.cs