File: Core\CSharp\MS\Win32\UnsafeNativeMethodsPenimc.cs
Project: wpf\src\PresentationCore.csproj (PresentationCore)
//#define OLD_ISF
using System;
using System.Security;
using System.Security.Permissions;
using System.Threading;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Windows.Interop;
using MS.Internal;
using MS.Internal.PresentationCore;
using MS.Win32;
 
namespace MS.Win32.Penimc
{
    internal static class UnsafeNativeMethods
    {
        // DDVSO:514949
        // The flags in this region are all in support of COM hardening to add resilience
        // to (OSGVSO:10779198).
        // They are special arguments to COM calls that allow us to re-purpose them for 
        // functions relating to this hardening.
        #region PenIMC Operations Flags
 
        /// <summary>
        /// Instruct IPimcManager2.GetTablet to release the external lock on itself.
        /// </summary>
        private const UInt32 ReleaseManagerExt = 0xFFFFDEAD;
 
        /// <summary>
        /// Instruct IPimcTablet2.GetCursorButtonCount to release the external lock on itself.
        /// </summary>
        private const int ReleaseTabletExt = -1;
 
        /// <summary>
        /// Instruct IPimcTablet2.GetCursorButtonCount to return the GIT key for the WISP Tablet.
        /// </summary>
        private const int GetWispTabletKey = -2;
 
        /// <summary>
        /// Instruct IPimcTablet2.GetCursorButtonCount to return the GIT key for the WISP Tablet Manager.
        /// </summary>
        private const int GetWispManagerKey = -3;
 
        /// <summary>
        /// Instruct IPimcTablet2.GetCursorButtonCount to acquire the external lock on itself.
        /// </summary>
        private const int LockTabletExt = -4;
 
        /// <summary>
        /// Instruct IPimcContext2.GetPacketPropertyInfo to return the GIT key for the WISP Tablet Context.
        /// </summary>
        private const int GetWispContextKey = -1;
 
        #endregion
 
        #region Stylus Input Thread Manager
 
        /// <summary>
        /// The GIT key to use when managing the WISP Tablet Manager objects
        /// </summary>
        /// <SecurityNote>
        ///     Critical:  This field can be used to manipulate the GIT entries for WISP objects.
        /// </SecurityNote>
        [SecurityCritical]
        [ThreadStatic]
        private static UInt32? _wispManagerKey;
 
        /// <summary>
        /// Whether or not the WISP Tablet Manager server object has been locked in the MTA.
        /// </summary>
        [ThreadStatic]
        private static bool _wispManagerLocked = false;
 
        /// <SecurityNote>
        /// Critical to prevent inadvertant spread to transparent code
        /// </SecurityNote>
        [SecurityCritical]
        [ThreadStatic]
        private static IPimcManager2 _pimcManagerThreadStatic;
 
        #endregion
 
        /// <summary>
        /// Make sure we load penimc.dll from WPF's installed location to avoid two instances of it.
        /// </summary>
        /// <SecurityNote>
        /// Critical: Calls NativeLibraryLoader.EnsureLoaded
        /// </SecurityNote>
        [SecurityCritical]
        static UnsafeNativeMethods()
        {
            // This static contructor was added to make sure we load the proper version of Penimc.dll.  
            // 
            // Details:
            // P/invoke will use LoadLibrary to load penimc.dll and it will check the current
            // application directory before checking the system32 directory where this DLL
            // is installed to.  If penimc.dll happens to be in the application directory as well
            // as the system32 directory we'll actually end up loaded two versions of
            // penimc.dll.  One that we'd use for P/invokes and one that we'd use for COM.
            // If this happens then our Stylus code will fail since it relies on both P/invoke and COM
            // calls to talk to penimc.dll and it requires just one instance of this DLL to work.
            //
            // DDVSO:474688
            // We cannot rely on COM to load PenIMC.  The CoCreate call can re-enter, potentially deadlocking.
            //
            // 1) CoCreate is COM Pumped and re-enters off of an EnableCore call
            // 2) Message for, say, device changed or tablet added is received.
            // 3) Work is sent to the PenThread and the UI thread waits on it
            // 4) PenThread accesses MS.Win32.Penimc.UnsafeNativeMethods
            // 
            // At this point, the static constructor has not finished and the CLR blocks the PenThread on the 
            // completion of the constructor.  However, the UI thread cannot complete the constructor call until 
            // the PenThread returns.
            // 
            // Instead, use LoadLibrary with a full path here to ensure it won't load local binaries and we don't re-enter.
            WpfLibraryLoader.EnsureLoaded(ExternDll.Penimc);
        }
 
        /// <summary>
        /// Returns IPimcManager2 interface.  Creates this object the first time per thread.
        /// </summary>
        /// <SecurityNote>
        /// Critical  - returns critial data _pimcManager.
        /// </SecurityNote>
        internal static IPimcManager2 PimcManager
        {
            [SecurityCritical]
            get
            {
                if (_pimcManagerThreadStatic == null)
                {
                    _pimcManagerThreadStatic = CreatePimcManager();
                }
                return _pimcManagerThreadStatic;
            }
        }
 
        /// <summary>
        /// Creates a new instance of PimcManager.
        /// </summary>
        /// <SecurityNote>
        /// Critical calls interop code that uses suppress unmanaged code security attributes
        /// </SecurityNote>
        [SecurityCritical]
        private static IPimcManager2 CreatePimcManager()
        {
            // Instantiating PimcManager using "new PimcManager()" results
            // in calling CoCreateInstanceForApp from an immersive process
            // (like designer). Such a call would fail because PimcManager is not
            // in ---- for that call. Hence we call CoCreateInstance directly.
            // Note: Normally WPF is not supported for immersive processes
            // but designer is an exception.
            Guid clsid = Guid.Parse(PimcConstants.PimcManager2CLSID);
            Guid iid = Guid.Parse(PimcConstants.IPimcManager2IID);
            object pimcManagerObj = CoCreateInstance(ref clsid,
                                                     null,
                                                     0x1, /*CLSCTX_INPROC_SERVER*/
                                                     ref iid);
            return ((IPimcManager2)pimcManagerObj);
        }
 
        #region COM Locking/Unlocking Functions
 
        #region General
 
        /// <summary>
        /// Calls WISP GIT lock functions on Win8+.
        /// On Win7 these will always fail since WISP objects are always proxies (WISP is out of proc).
        /// </summary>
        /// <param name="gitKey">The GIT key for the object to lock.</param>
        /// <SecurityNote>
        ///     Critical:   Calls LockWispObjectFromGit
        /// </SecurityNote>
        [SecurityCritical]
        internal static void CheckedLockWispObjectFromGit(UInt32 gitKey)
        {
            if (OSVersionHelper.IsOsWindows8OrGreater)
            {
                if (!LockWispObjectFromGit(gitKey))
                {
                    throw new InvalidOperationException();
                }
            }
        }
 
        /// <summary>
        /// Calls WISP GIT unlock functions on Win8+.
        /// On Win7 these will always fail since WISP objects are always proxies (WISP is out of proc).
        /// </summary>
        /// <param name="gitKey">The GIT key for the object to unlock.</param>
        /// <SecurityNote>
        ///     Critical:   Calls UnlockWispObjectFromGit
        /// </SecurityNote>
        [SecurityCritical]
        internal static void CheckedUnlockWispObjectFromGit(UInt32 gitKey)
        {
            if (OSVersionHelper.IsOsWindows8OrGreater)
            {
                if (!UnlockWispObjectFromGit(gitKey))
                {
                    throw new InvalidOperationException();
                }
            }
        }
 
        #endregion
 
        #region Manager
 
        /// <summary>
        /// DDVSO:514949
        /// Calls into GetTablet with a special flag that indicates we should release
        /// the lock obtained previously by a CoLockObjectExternal call.
        /// </summary>
        /// <param name="manager">The manager to release the lock for.</param>'
        /// <SecurityNote>
        ///     Critical:       Accesses IPimcManager2.
        /// </SecurityNote>
        [SecurityCritical]
        private static void ReleaseManagerExternalLockImpl(IPimcManager2 manager)
        {
            IPimcTablet2 unused = null;
            manager.GetTablet(ReleaseManagerExt, out unused);
        }
 
        /// <summary>
        /// DDVSO:514949
        /// Calls into GetTablet with a special flag that indicates we should release
        /// the lock obtained previously by a CoLockObjectExternal call.
        /// </summary>
        /// <param name="manager">The manager to release the lock for.</param>'
        /// <SecurityNote>
        ///     Critical:       Accesses IPimcManager2.
        /// </SecurityNote>
        [SecurityCritical]
        internal static void ReleaseManagerExternalLock()
        {
            if (_pimcManagerThreadStatic != null)
            {
                ReleaseManagerExternalLockImpl(_pimcManagerThreadStatic);
            }
        }
 
        /// <summary>
        /// Queries and sets the GIT key for the WISP Tablet Manager
        /// </summary>
        /// <param name="tablet">The tablet to call through</param>
        /// <SecurityNote>
        ///     Critical:       Accesses IPimcTablet2.
        /// </SecurityNote>
        [SecurityCritical]
        internal static void SetWispManagerKey(IPimcTablet2 tablet)
        {
            UInt32 latestKey = QueryWispKeyFromTablet(GetWispManagerKey, tablet);
 
            // Assert here to ensure that every call through to this specific manager has the same
            // key.  This should be guaranteed since these calls are always done on the thread the tablet
            // is created on and all tablets created on a particular thread should be through the same
            // manager.
            Invariant.Assert(!_wispManagerKey.HasValue || _wispManagerKey.Value == latestKey);
 
            _wispManagerKey = latestKey;
        }
 
        /// <summary>
        /// Calls down into PenIMC in order to lock the WISP Tablet Manager.
        /// </summary>
        [SecurityCritical]
        internal static void LockWispManager()
        {
            if (!_wispManagerLocked && _wispManagerKey.HasValue)
            {
                CheckedLockWispObjectFromGit(_wispManagerKey.Value);
                _wispManagerLocked = true;
            }
        }
 
        /// <summary>
        /// Calls down into PenIMC in order to unlock the WISP Tablet Manager.
        /// </summary>
        [SecurityCritical]
        internal static void UnlockWispManager()
        {
            if (_wispManagerLocked && _wispManagerKey.HasValue)
            {
                CheckedUnlockWispObjectFromGit(_wispManagerKey.Value);
                _wispManagerLocked = false;
            }
        }
 
        #endregion
 
        #region Tablet
 
        /// <summary>
        /// DDVSO:514949
        /// Calls into GetCursorButtonCount with a special flag that indicates we should acquire
        /// the external lock by a CoLockObjectExternal call.
        /// </summary>
        /// <param name="manager">The tablet to acquire the lock for.</param>'
        /// <SecurityNote>
        ///     Critical:       Accesses IPimcTablet2.
        /// </SecurityNote>
        [SecurityCritical]
        internal static void AcquireTabletExternalLock(IPimcTablet2 tablet)
        {
            int unused = 0;
 
            // Call through with special param to release the external lock on the tablet.
            tablet.GetCursorButtonCount(LockTabletExt, out unused);
        }
 
        /// <summary>
        /// DDVSO:514949
        /// Calls into GetCursorButtonCount with a special flag that indicates we should release
        /// the lock obtained previously by a CoLockObjectExternal call.
        /// </summary>
        /// <param name="manager">The tablet to release the lock for.</param>'
        /// <SecurityNote>
        ///     Critical:       Accesses IPimcTablet2.
        /// </SecurityNote>
        [SecurityCritical]
        internal static void ReleaseTabletExternalLock(IPimcTablet2 tablet)
        {
            int unused = 0;
 
            // Call through with special param to release the external lock on the tablet.
            tablet.GetCursorButtonCount(ReleaseTabletExt, out unused);
        }
 
        /// <summary>
        /// Queries the GIT key from the PenIMC Tablet
        /// </summary>
        /// <param name="keyType">The kind of key to instruct the tablet to return</param>
        /// <param name="tablet">The tablet to call through</param>
        /// <returns>The GIT key for the requested operation</returns>
        /// <SecurityNote>
        ///     Critical:       Accesses IPimcTablet2.
        /// </SecurityNote>
        [SecurityCritical]
        private static UInt32 QueryWispKeyFromTablet(int keyType, IPimcTablet2 tablet)
        {
            int key = 0;
 
            tablet.GetCursorButtonCount(keyType, out key);
 
            if(key == 0)
            {
                throw new InvalidOperationException();
            }
 
            return (UInt32)key;
        }
 
        /// <summary>
        /// Queries the GIT key for the WISP Tablet
        /// </summary>
        /// <param name="tablet">The tablet to call through</param>
        /// <returns>The GIT key for the WISP Tablet</returns>
        /// <SecurityNote>
        ///     Critical:       Accesses IPimcTablet2.
        /// </SecurityNote>
        [SecurityCritical]
        internal static UInt32 QueryWispTabletKey(IPimcTablet2 tablet)
        {
            return QueryWispKeyFromTablet(GetWispTabletKey, tablet);
        }
 
        #endregion
 
        #region Context
 
        /// <summary>
        /// Queries the GIT key for the WISP Tablet Context
        /// </summary>
        /// <param name="context">The context to query through</param>
        /// <returns>The GIT key for the WISP Tablet Context</returns>
        ///  <SecurityNote>
        ///     Critical:       Accesses IPimcContext2.
        /// </SecurityNote>
        [SecurityCritical]
        internal static UInt32 QueryWispContextKey(IPimcContext2 context)
        {
            int key = 0;
            Guid unused = Guid.Empty;
            int unused2 = 0;
            int unused3 = 0;
            float unused4 = 0;
 
            context.GetPacketPropertyInfo(GetWispContextKey, out unused, out key, out unused2, out unused3, out unused4);
 
            if (key == 0)
            {
                throw new InvalidOperationException();
            }
 
            return (UInt32)key;
        }
 
        #endregion
 
        #endregion
 
#if OLD_ISF
        /// <summary>
        /// Managed wrapper for IsfCompressPropertyData
        /// </summary>
        /// <param name="pbInput">Input byte array</param>
        /// <param name="cbInput">number of bytes in byte array</param>
        /// <param name="pnAlgoByte">
        /// In: Preferred algorithm Id
        /// Out: Best algorithm with parameters
        /// </param>
        /// <param name="pcbOutput">
        /// In: output buffer size (of pbOutput)
        /// Out: Actual number of bytes needed for compressed data
        /// </param>
        /// <param name="pbOutput">Buffer to hold the output</param>
        /// <returns>Status</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        internal static extern int IsfCompressPropertyData(
                [In] byte [] pbInput,
                uint cbInput, 
                ref byte pnAlgoByte, 
                ref uint pcbOutput, 
                [In, Out] byte [] pbOutput
            );
 
        /// <summary>
        /// Managed wrapper for IsfDecompressPropertyData
        /// </summary>
        /// <param name="pbCompressed">Input buffer to be decompressed</param>
        /// <param name="cbCompressed">Number of bytes in the input buffer to be decompressed</param>
        /// <param name="pcbOutput">
        /// In: Output buffer capacity
        /// Out: Actual number of bytes required to hold uncompressed bytes
        /// </param>
        /// <param name="pbOutput">Output buffer</param>
        /// <param name="pnAlgoByte">Algorithm id and parameters</param>
        /// <returns>Status</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        internal static extern int IsfDecompressPropertyData(
                [In] byte [] pbCompressed,   
                uint cbCompressed,   
                ref uint pcbOutput,  
                [In, Out] byte [] pbOutput, 
                ref byte pnAlgoByte 
            );
 
        /// <summary>
        /// Managed wrapper for IsfCompressPacketData
        /// </summary>
        /// <param name="hCompress">Handle to the compression engine (null is ok)</param>
        /// <param name="pbInput">Input buffer</param>
        /// <param name="cInCount">Number of bytes in the input buffer</param>
        /// <param name="pnAlgoByte">
        /// In: Preferred compression algorithm byte
        /// Out: Actual compression algorithm byte
        /// </param>
        /// <param name="pcbOutput">
        /// In: Output buffer capacity
        /// Out: Actual number of bytes required to hold compressed bytes
        /// </param>
        /// <param name="pbOutput">Output buffer</param>
        /// <returns>Status</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        internal static extern int IsfCompressPacketData(
                CompressorSafeHandle hCompress,
                [In] int [] pbInput,
                [In] uint cInCount,
                ref byte pnAlgoByte,
                ref uint pcbOutput,
                [In, Out] byte [] pbOutput
            );
 
        /// <summary>
        /// Managed wrapper for IsfDecompressPacketData
        /// </summary>
        /// <param name="hCompress">Handle to the compression engine (null is ok)</param>
        /// <param name="pbCompressed">Input buffer of compressed bytes</param>
        /// <param name="pcbCompressed">
        /// In: Size of the input buffer
        /// Out: Actual number of compressed bytes decompressed.
        /// </param>
        /// <param name="cInCount">Count of int's in the compressed buffer</param>
        /// <param name="pbOutput">Output buffer to receive the decompressed int's</param>
        /// <param name="pnAlgoData">Algorithm bytes</param>
        /// <returns>Status</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        internal static extern int IsfDecompressPacketData(
                CompressorSafeHandle hCompress,
                [In] byte [] pbCompressed,
                ref uint pcbCompressed,
                uint cInCount,
                [In, Out] int [] pbOutput,
                ref byte pnAlgoData
            );
 
        /// <summary>
        /// Managed wrapper for IsfLoadCompressor
        /// </summary>
        /// <param name="pbInput">Input buffer where compressor is saved</param>
        /// <param name="pcbInput">
        /// In: Size of the input buffer
        /// Out: Number of bytes in the input buffer decompressed to construct compressor
        /// </param>
        /// <returns>Handle to the compression engine loaded</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        internal static extern CompressorSafeHandle IsfLoadCompressor(
                [In] byte [] pbInput,
                ref uint pcbInput
            );
 
        /// <summary>
        /// Managed wrapper for IsfReleaseCompressor
        /// </summary>
        /// <param name="hCompress">Handle to the Compression Engine to be released</param>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        internal static extern void IsfReleaseCompressor(
                IntPtr hCompress
            );
#endif
 
        /// <summary>
        /// Managed wrapper for GetPenEvent
        /// </summary>
        /// <param name="commHandle">Win32 event handle to wait on for new stylus input.</param>
        /// <param name="handleReset">Win32 event the signals a reset.</param>
        /// <param name="evt">Stylus event that was triggered.</param>
        /// <param name="stylusPointerId">Stylus Device ID that triggered input.</param>
        /// <param name="cPackets">Count of packets returned.</param>
        /// <param name="cbPacket">Byte count of packet data returned.</param>
        /// <param name="pPackets">Array of ints containing the packet data.</param>
        /// <returns>true if succeeded, false if failed or shutting down.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetPenEvent(
            IntPtr      commHandle,
            IntPtr      handleReset,
            out int     evt,
            out int     stylusPointerId,
            out int     cPackets,
            out int     cbPacket,
            out IntPtr  pPackets);
 
        /// <summary>
        /// Managed wrapper for GetPenEventMultiple
        /// </summary>
        /// <param name="cCommHandles">Count of elements in commHandles.</param>
        /// <param name="commHandles">Array of Win32 event handles to wait on for new stylus input.</param>
        /// <param name="handleReset">Win32 event the signals a reset.</param>
        /// <param name="iHandle">Index to the handle that triggered return.</param>
        /// <param name="evt">Stylus event that was triggered.</param>
        /// <param name="stylusPointerId">Stylus Device ID that triggered input.</param>
        /// <param name="cPackets">Count of packets returned.</param>
        /// <param name="cbPacket">Byte count of packet data returned.</param>
        /// <param name="pPackets">Array of ints containing the packet data.</param>
        /// <returns>true if succeeded, false if failed or shutting down.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetPenEventMultiple(
            int         cCommHandles,
            IntPtr[]    commHandles,
            IntPtr      handleReset,
            out int     iHandle,
            out int     evt,
            out int     stylusPointerId,
            out int     cPackets,
            out int     cbPacket,
            out IntPtr  pPackets);
 
        /// <summary>
        /// Managed wrapper for GetLastSystemEventData
        /// </summary>
        /// <param name="commHandle">Specifies PimcContext object handle to get event data on.</param>
        /// <param name="evt">ID of system event that was triggered.</param>
        /// <param name="modifier">keyboar modifier (unused).</param>
        /// <param name="key">Keyboard key (unused).</param>
        /// <param name="x">X position in device units of gesture.</param>
        /// <param name="y">Y position in device units of gesture.</param>
        /// <param name="cursorMode">Mode of the cursor.</param>
        /// <param name="buttonState">State of stylus buttons (flick returns custom data in this).</param>
        /// <returns>true if succeeded, false if failed.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetLastSystemEventData(
            IntPtr      commHandle,
            out int     evt,
            out int     modifier,
            out int     key,
            out int     x,
            out int     y,
            out int     cursorMode,
            out int     buttonState);
 
        /// <summary>
        /// Managed wrapper for CreateResetEvent
        /// </summary>
        /// <param name="handle">Win32 event handle created.</param>
        /// <returns>true if succeeded, false if failed.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool CreateResetEvent(out IntPtr handle);
 
        /// <summary>
        /// Managed wrapper for DestroyResetEvent
        /// </summary>
        /// <param name="handle">Win32 event handle to destroy.</param>
        /// <returns>true if succeeded, false if failed.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool DestroyResetEvent(IntPtr handle);
 
        /// <summary>
        /// Managed wrapper for RaiseResetEvent
        /// </summary>
        /// <param name="handle">Win32 event handle to set.</param>
        /// <returns>true if succeeded, false if failed.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet=CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool RaiseResetEvent(IntPtr handle);
 
        /// <summary>
        /// Managed wrapper for LockObjectExtFromGit
        /// </summary>
        /// <param name="gitKey">The key used to refer to this object in the GIT.</param>
        /// <returns>true if succeeded, false if failed.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool LockWispObjectFromGit(UInt32 gitKey);
 
        /// <summary>
        /// Managed wrapper for UnlockObjectExtFromGit
        /// </summary>
        /// <param name="gitKey">The key used to refer to this object in the GIT.</param>
        /// <returns>true if succeeded, false if failed.</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [DllImport(ExternDll.Penimc, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnlockWispObjectFromGit(UInt32 gitKey);
 
        /// <summary>
        /// Managed wrapper for CoCreateInstance
        /// </summary>
        /// <param name="clsid">CLSID of the COM class to be instantiated</param>
        /// <param name="punkOuter">Aggregate object</param>
        /// <param name="context">Context in which the newly created object will run</param>
        /// <param name="iid">Identifier of the Interface</param>
        /// <returns>Returns the COM object created by CoCreateInstance</returns>
        /// <SecurityNote>
        /// Critical as suppressing UnmanagedCodeSecurity
        /// </SecurityNote>
        [SecurityCritical, SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Interface)][DllImport(ExternDll.Ole32, ExactSpelling=true, PreserveSig=false)]
        private static extern object CoCreateInstance(
            [In]
            ref Guid clsid,
            [MarshalAs(UnmanagedType.Interface)]
            object punkOuter,
            int context,
            [In]
            ref Guid iid);
    }
 
#if OLD_ISF
    internal class CompressorSafeHandle: SafeHandle
    {
        /// <SecurityNote>
        /// Critical: This code calls into a base class which is protected by link demand and by inheritance demand
        /// </SecurityNote>
        [SecurityCritical]
        private CompressorSafeHandle() 
            : this(true)
        {
        }
 
        /// <SecurityNote>
        /// Critical: This code calls into a base class which is protected by link demand and by inheritance demand
        /// </SecurityNote>
        [SecurityCritical]
        private CompressorSafeHandle(bool ownHandle) 
            : base(IntPtr.Zero, ownHandle)
        {
        }
 
        // Do not provide a finalizer - SafeHandle's critical finalizer will
        // call ReleaseHandle for you.
        /// <SecurityNote>
        /// Critical:This code calls into a base class which is protected by link demand an by inheritance demand
        /// TreatAsSafe: It's safe to give out a boolean value.
        /// </SecurityNote>
        public override bool IsInvalid
        {
            [SecurityCritical, SecurityTreatAsSafe]
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            get
            {
                return IsClosed || handle == IntPtr.Zero;
            }
        }
 
        /// <SecurityNote>
        /// Critical: This code calls into a base class which is protected by link demand and by inheritance demand.
        /// </SecurityNote>
        [SecurityCritical]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        override protected bool ReleaseHandle()
        {
            //
            // return code from this is void. 
            // internally it just calls delete on 
            // the compressor pointer
            //
            UnsafeNativeMethods.IsfReleaseCompressor(handle);
            handle = IntPtr.Zero;
            return true;
        }
    
        /// <SecurityNote>
        /// Critical: This code calls into a base class which is protected by link demand and by inheritance demand.
        /// </SecurityNote>
        public static CompressorSafeHandle Null
        {
            [SecurityCritical]
            get
            {
              return new CompressorSafeHandle(false);
            }
        }
    }
#endif
}