indexingfiltermarshaler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / IO / Packaging / indexingfiltermarshaler.cs / 1305600 / indexingfiltermarshaler.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: 
//   Class which acts as adaptor between IManagedFilter and IFilter. 
//   Used by PackageFilter for XamlFilter and CorePropertiesFilter.
//   Used by EncryptedPackageFilter for CorePropertiesFilter. 
//
// History:
//  02/25/2004: JohnLarc: Creation, using BruceMac's code from XamlFilter, ContainerFilter, and ManagedFilterMarshalingHelper.
//  08/26/2004: JohnLarc: Removed access to indexing filters from managed code. 
//  07/18/2005: ArindamB: Removed IPersistStream and IPersistFile interfaces.
// 
//----------------------------------------------------------------------------- 

using System.Diagnostics; 
using System;
using System.Runtime.InteropServices;
using System.Collections;
using System.Windows;                     // for ExceptionStringTable 
using System.Security;                    // for SecurityCritical
 
using MS.Internal.Interop;                // for STAT_CHUNK, etc. 
using MS.Internal;                        // for Invariant
using MS.Win32; 

namespace MS.Internal.IO.Packaging
{
    #region IndexingFilterMarshaler 
    /// 
    /// Adapter for IManagedFilter. Used to obtain an IFilter interface from an IManagedFilter. 
    ///  
    /// 
    /// IManagedFilter is supported by filters which have purely managed implementation and don't work 
    /// with interop entities. Callers like PackageFilter and EncryptedPackageFilter which support
    /// IFilter interfaces interact with IManagedFilters like XamlFilter, PackageCorePropertiesFilter
    /// and EncryptedPackageCorePropertiesFilter through IndexingFilterMarshaler.
    ///  
    internal class IndexingFilterMarshaler : IFilter
    { 
        #region Static members. 
        /// 
        /// pre-defined GUID for storage properties on file system files (as per MSDN) 
        /// 
        internal static Guid PSGUID_STORAGE = new Guid(0xb725f130, 0x47ef, 0x101a, 0xa5, 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac);

        /// Cache frequently used size values to incur reflection cost just once. 
        internal const Int32 _int16Size = 2;
 
        ///  
        /// Constructor.
        ///  
        /// IManagedFilter implementation
        internal IndexingFilterMarshaler(IManagedFilter managedFilter)
        {
            if (managedFilter == null) 
            {
                throw new ArgumentNullException("managedFilter"); 
            } 

            _implementation = managedFilter; 
        }

        /// 
        /// Init 
        /// 
        /// length of aAttributes 
        /// array of FULLPROPSPEC structs 
        /// managed array
        internal static ManagedFullPropSpec[] MarshalFullPropSpecArray( 
            uint cAttributes,    // length of aAttributes
            FULLPROPSPEC[] aAttributes)
        {
            // If there are attributes, these override the flags 
            if (cAttributes > 0)
            { 
                // Attributes count and array should match. 
                // This has already been checked for by XpsFilter.
                Invariant.Assert(aAttributes != null); 

                ManagedFullPropSpec[] initAttributes = new ManagedFullPropSpec[checked((int)cAttributes)];

                // convert to managed equivalents to isolate the marshaling effort 
                for (int i = 0; i < cAttributes; i++)
                { 
                    // convert and add to local list 
                    initAttributes[i] = new ManagedFullPropSpec(aAttributes[i]);
                } 

                return initAttributes;
            }
            else 
                return null;
        } 
 
        /// 
        /// StringToPtr 
        /// 
        /// Converts a managed string into the format useful for IFilter.GetText
        /// string to convert
        /// maximum number of characters to convert 
        /// pointer to write to
        ///  
        /// This method, if exposed to partially trusted callers, can lead to arbitrary memory writing. 
        /// Critical    - This code could be used to attempt to build a string from arbitrary data.
        ///   This code is not intended to be used from PT code. 
        ///   Not designed to be accessible from public surface at all. Invoked (indirectly) by unmanaged client code.
        /// 
        [SecurityCritical]
        internal static void MarshalStringToPtr(string s, ref uint bufCharacterCount, IntPtr p) 
        {
            // bufCharacterCount is never supposed to be zero at this level. 
            Invariant.Assert(bufCharacterCount != 0); 

            // ensure the interface rules are followed 
            // string must also be null terminated so we restrict the length to buf size - 1
            if ((uint)(s.Length) > bufCharacterCount - 1)
                throw new InvalidOperationException(SR.Get(SRID.FilterGetTextBufferOverflow));
 
            // Return the number of characters written, including the terminating null.
            bufCharacterCount = (UInt32)s.Length + 1; 
 
            // convert string to unmanaged string and write into provided buffer
            Marshal.Copy(s.ToCharArray(), 0, p, s.Length); 

            // null terminate (16bit's of zero to replace one Unicode character)
            Marshal.WriteInt16(p, s.Length * _int16Size, 0);
        } 

        ///  
        /// Marshal Managed to Native PROPSPEC 
        /// 
        ///  
        /// 
        ///
        ///     Critical: calls Marshal.StringToCoTaskMemUni which LinkDemands, and writes string into unmanaged memory.
        /// 
        [SecurityCritical]
        internal static void MarshalPropSpec(ManagedPropSpec propSpec, ref PROPSPEC native) 
        { 
            native.propType = (uint)propSpec.PropType;
            switch (propSpec.PropType) 
            {
                case PropSpecType.Id:
                    native.union.propId = (uint)propSpec.PropId;
                    break; 

                case PropSpecType.Name: 
                    native.union.name = Marshal.StringToCoTaskMemUni(propSpec.PropName); 
                    break;
 
                default:
                    Invariant.Assert(false); // propSpec.PropType is set by internal code in the filter logic.
                    break;
            } 
        }
 
        ///  
        /// Marshal Managed to Native FULLPROPSPEC
        ///  
        /// 
        /// 
        ///
        ///     Critical: calls MarshalPropSpec which is Critical.  Returns a pointer to unmanaged memory. 
        ///
        [SecurityCritical] 
        internal static void MarshalFullPropSpec(ManagedFullPropSpec fullPropSpec, ref FULLPROPSPEC native) 
        {
            native.guid = fullPropSpec.Guid; 
            MarshalPropSpec(fullPropSpec.Property, ref native.property);
        }

        ///  
        /// GetChunk
        ///  
        /// An interop STAT_CHUNK from a ManagedChunk 
        ///
        ///     Critical: calls MarshalFullPropSpec which is Critical.  Returns a pointer to unmanaged memory. 
        ///
        [SecurityCritical]
        internal static STAT_CHUNK MarshalChunk(ManagedChunk chunk)
        { 
            STAT_CHUNK native = new STAT_CHUNK();
 
            native.idChunk = chunk.ID; 
            Invariant.Assert(chunk.BreakType >= CHUNK_BREAKTYPE.CHUNK_NO_BREAK && chunk.BreakType <= CHUNK_BREAKTYPE.CHUNK_EOC);
            native.breakType = chunk.BreakType; 
            Invariant.Assert(
                chunk.Flags >= 0
                &&
                chunk.Flags <= (CHUNKSTATE.CHUNK_TEXT | CHUNKSTATE.CHUNK_VALUE | CHUNKSTATE.CHUNK_FILTER_OWNED_VALUE)); 
            native.flags = chunk.Flags;
            native.locale = chunk.Locale; 
            native.idChunkSource = chunk.ChunkSource; 
            native.cwcStartSource = chunk.StartSource;
            native.cwcLenSource = chunk.LenSource; 
            MarshalFullPropSpec(chunk.Attribute, ref native.attribute);

            return native;
        } 

        ///  
        /// MarshalPropVariant 
        /// 
        /// Object to marshal, should be DateTime or String 
        /// newly allocated PROPVARIANT structure
        ///
        ///     Critical: calls Marshal.StringToCoTaskMemAnsi which LinkDemands, and writes string into unmanaged memory.
        /// 
        [SecurityCritical]
        internal static IntPtr MarshalPropVariant(Object obj) 
        { 
            IntPtr pszVal = IntPtr.Zero;
            IntPtr pNative = IntPtr.Zero; 

            try
            {
                PROPVARIANT v; 

                if (obj is string) 
                { 
                    pszVal = Marshal.StringToCoTaskMemAnsi((string)obj);
 
                    v = new PROPVARIANT();
                    v.vt = VARTYPE.VT_LPSTR;
                    v.union.pszVal = pszVal;
                } 
                else if (obj is DateTime)
                { 
                    v = new PROPVARIANT(); 
                    v.vt = VARTYPE.VT_FILETIME;
                    long longFileTime = ((DateTime)obj).ToFileTime(); 
                    v.union.filetime.dwLowDateTime = (Int32)longFileTime;
                    v.union.filetime.dwHighDateTime = (Int32)((longFileTime >> 32) & 0xFFFFFFFF);
                }
                else 
                {
                    throw new InvalidOperationException( 
                        SR.Get(SRID.FilterGetValueMustBeStringOrDateTime)); 
                }
 
                // allocate an unmanaged PROPVARIANT to return
                pNative = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(PROPVARIANT)));
                // Per MSDN, AllocCoTaskMem never returns null. One can't be too careful, though.
                Invariant.Assert(pNative != null); 

                // marshal the managed PROPVARIANT into the unmanaged block and return it 
                Marshal.StructureToPtr(v, pNative, false); 
            }
            catch 
            {
                if (pszVal != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(pszVal); 
                }
 
                if (pNative != IntPtr.Zero) 
                {
                    Marshal.FreeCoTaskMem(pNative); 
                }

                throw;
            } 

            return pNative; 
        } 
        #endregion Static members.
 
        #region IFilter implementation
        /// 
        /// Init
        ///  
        /// usage flags
        /// length of aAttributes 
        /// array of FULLPROPSPEC structs 
        /// flags
        public IFILTER_FLAGS Init(IFILTER_INIT grfFlags,       // IFILTER_INIT value 
            uint cAttributes,               // length of aAttributes
            FULLPROPSPEC[] aAttributes)     // restrict responses to the specified attributes
        {
            ManagedFullPropSpec[] managedArray = MarshalFullPropSpecArray( 
                                                 cAttributes, aAttributes);
 
            return _implementation.Init(grfFlags, managedArray); 
        }
 
        /// 
        /// GetChunk
        /// 
        /// the next chunk 
        ///
        ///     Critical: calls MarshalChunk which is Critical.  Returns a pointer to unmanaged memory. 
        /// 
        [SecurityCritical]
        public STAT_CHUNK GetChunk() 
        {
            // Get the managed chunk
            ManagedChunk managedChunk = _implementation.GetChunk();
 
            if (managedChunk == null)
            { 
                // End of chunks. 

                if (ThrowOnEndOfChunks) 
                {
                    // Throw exception.
                    throw new COMException(SR.Get(SRID.FilterEndOfChunks),
                        (int)FilterErrorCode.FILTER_E_END_OF_CHUNKS); 
                }
 
                // Return STAT_CHUNK with idChunk as 0. 

                STAT_CHUNK chunk = new STAT_CHUNK(); 
                chunk.idChunk = 0;
                return chunk;

            } 

            // Valid chunk. Return corresponding STAT_CHUNK. 
            return MarshalChunk(managedChunk); 
        }
 
        /// 
        ///    GetText
        /// 
        /// Buffer size in Unicode characters (not bytes) 
        /// Pre-allocated buffer for us to write into.  String must be null-terminated.
        ///  
        /// Critical    - Invokes the critical method MarshalStringToPtr, which could be used to attempt to build a string from arbitrary data. 
        ///   This code is not intended to be called from PT code.
        ///   Not designed to be accessible from public surface at all. Invoked (indirectly) by unmanaged client code. 
        /// 
        [SecurityCritical]
        public void GetText(ref uint bufCharacterCount, IntPtr pBuffer)
        { 
            // NOTE: bufCharacterCount and pBuffer are already validated by XpsFilter.
            // In future, if this class is exposed publicly or used in a way other than 
            // through XpsFilter, proper checks needs to be present either here or in the caller. 

            // get the managed string and marshal 
            MarshalStringToPtr(_implementation.GetText((int)bufCharacterCount - 1),
                ref bufCharacterCount, pBuffer);
        }
 
        /// 
        /// GetValue 
        ///  
        /// newly allocated PROPVARIANT structure
        /// 
        ///     Critical: calls MarshalPropVariant which is Critical.  Returns a pointer to unmanaged memory.
        ///
        [SecurityCritical]
        public IntPtr GetValue() 
        {
            return MarshalPropVariant(_implementation.GetValue()); 
        } 

        ///  
        /// BindRegion
        /// 
        /// 
        ///  
        /// 
        /// The MSDN specification requires this function to return E_NOTIMPL for the time being. 
        ///  
        public IntPtr BindRegion(FILTERREGION origPos, ref Guid riid)
        { 
            // The following exception maps to E_NOTIMPL.
            throw new NotImplementedException(SR.Get(SRID.FilterBindRegionNotImplemented));
        }
        #endregion IFilter implementation 

        #region Properties 
 
        /// 
        /// If set to true, FILTER_E_END_OF_CHUNKS exception is thrown 
        /// by IFilter.GetChunk() on end of chunks.
        /// If false, a STAT_CHUNK with idChunk as 0 is returned instead.
        /// 
        internal bool ThrowOnEndOfChunks 
        {
            get 
            { 
                return _throwOnEndOfChunks;
            } 

            set
            {
                _throwOnEndOfChunks = value; 
            }
        } 
 
        #endregion Properties
 
        #region Fields

        private IManagedFilter _implementation;
        private bool _throwOnEndOfChunks = true; 

        #endregion Fields 
    } 
    #endregion IndexingFilterMarshaler
} 

// 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