Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / MS / Internal / IO / Packaging / PackageFilter.cs / 1 / PackageFilter.cs
//------------------------------------------------------------------------------ // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // Managed equivalent of IFilter implemenation for Package // // History: // 02/02/2004: BruceMac: Stubs // 03/28/2004: JohnLarc: Initial implementation // 08/26/2004: JohnLarc: Removed access to indexing filters from managed code. // 07/18/2005: ArindamB: Changed ContainerFilterImpl to PackageFilter, // which implements IFilter instead of ManagedFilterBase. //----------------------------------------------------------------------------- using System; using System.IO; using System.IO.Packaging; using System.Collections; using System.Diagnostics; // For Assert using System.Runtime.InteropServices; // For Marshal.ThrowExceptionForHR using System.Windows; // for ExceptionStringTable using Microsoft.Win32; // For RegistryKey using MS.Internal.Interop; // For STAT_CHUNK, etc. using MS.Internal; // For ContentType using MS.Internal.Utility; // For BindUriHelper namespace MS.Internal.IO.Packaging { #region PackageFilter ////// Managed Package Filter /// ////// This is where implementation goes /// internal class PackageFilter : IFilter { #region Nested Types ////// Indicates filtering progress. /// private enum Progress { FilteringNotStarted = 0, FilteringCoreProperties = 1, FilteringContent = 2, FilteringCompleted = 3 } #endregion Nested Types #region constructor ////// Constructor. /// /// package to filter internal PackageFilter(Package package) { if (package == null) { throw new ArgumentNullException("package"); } _package = package; _partIterator = _package.GetParts().GetEnumerator(); } #endregion constructor #region IFilter methods ////// IFilter.Init /// /// usage flags /// number of elements in aAttributes /// array of Managed FULLPROPSPEC structs to restrict responses ///flags ////// Returns systematically IFILTER_FLAGS_NONE insofar as flags are used to control property search, /// which is not supported (See GetValue). /// public IFILTER_FLAGS Init(IFILTER_INIT grfFlags, // IFILTER_INIT value uint cAttributes, // length of aAttributes FULLPROPSPEC[] aAttributes) // restrict responses to the specified attributes { _grfFlags = grfFlags; _cAttributes = cAttributes; _aAttributes = aAttributes; _partIterator.Reset(); _progress = Progress.FilteringNotStarted; return IFILTER_FLAGS.IFILTER_FLAGS_NONE; } ////// Returns description of the next chunk. /// ////// Chunk descriptor. /// ////// public STAT_CHUNK GetChunk() { // // _progress is Progress.FilteringNotStarted initially and // subsequently gets updated in MoveToNextFilter(). // if (_progress == Progress.FilteringNotStarted) { MoveToNextFilter(); } if (_progress == Progress.FilteringCompleted) { throw new COMException(SR.Get(SRID.FilterEndOfChunks), (int)FilterErrorCode.FILTER_E_END_OF_CHUNKS); } while(true) { try { STAT_CHUNK chunk = _currentFilter.GetChunk(); // // No exception raised. // If _currentFilter is internal filter, // this might be end of chunks if chunk.idChunk is 0. // if (!_isInternalFilter || chunk.idChunk != 0) { // // There are more chunks. // // // Consider value chunks only when filtering core properties. // Else, ignore the chunk and move to the next. // if (_progress == Progress.FilteringCoreProperties || (chunk.flags & CHUNKSTATE.CHUNK_VALUE) != CHUNKSTATE.CHUNK_VALUE) { // // Found the next chunk to return. // // Replace ID from auxiliary filter by unique ID across the package. chunk.idChunk = AllocateChunkID(); // Since pseudo-properties (a.k.a. internal values) are not supported, // all chunks we return are expected to have idChunkSource equal to idChunk. // (See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/indexsrv/html/ixufilt_8ib8.asp) chunk.idChunkSource = chunk.idChunk; // Some filters (such as the plain text filter) // will return "no break" before the first chunk. // However, the correct break type at the beginning // of a part is "end of paragraph". if (_firstChunkFromFilter) { chunk.breakType = CHUNK_BREAKTYPE.CHUNK_EOP; // This flag gets set in MoveToNextFilter. _firstChunkFromFilter = false; } return chunk; } } } // Ignore IO and COM exceptions raised by an external filter. catch (COMException) { // Most of the time, this will be a FILTER_E_END_OF_CHUNKS exception. // In general, we don't really care: when an external filter gets in trouble // we simply move to the next filter. } catch (IOException exc) { // Internal filters do not throw expected exceptions; so something bad // must have happened. Let the client code get the exception and possibly // choose to ignore it. if (_isInternalFilter) { throw exc; } } // // Either there was FILTER_E_END_OF_CHUNKS exception // from _currentFilter.GetChunk(), // or _isInternalFilter is true and the returned chunk has // idChunk as 0, which also indicates end of chunks. // // Move to the next filter. // MoveToNextFilter(); if (_progress == Progress.FilteringCompleted) { // // No more filters. Filtering completed. // Throw FILTER_E_END_OF_CHUNKS exception. // throw new COMException(SR.Get(SRID.FilterEndOfChunks), (int)FilterErrorCode.FILTER_E_END_OF_CHUNKS); } } } ////// On end of stream, this function will throw an exception so as to return FILTER_E_END_OF_CHUNKS /// to client code, in keeping with the IFilter specifications. /// ////// Non-fatal exceptions from external filters, identified for all practical purposes /// with COMException and IOException, are `swallowed by this method. /// ////// Gets text content corresponding to current chunk. /// public void GetText(ref uint bufferCharacterCount, IntPtr pBuffer) { if (_progress != Progress.FilteringContent) { throw new COMException(SR.Get(SRID.FilterGetTextNotSupported), (int)FilterErrorCode.FILTER_E_NO_TEXT); } _currentFilter.GetText(ref bufferCharacterCount, pBuffer); } ////// Gets the property value corresponding to current chunk. /// ///Property value public IntPtr GetValue() { if (_progress != Progress.FilteringCoreProperties) { throw new COMException(SR.Get(SRID.FilterGetValueNotSupported), (int)FilterErrorCode.FILTER_E_NO_VALUES); } return _currentFilter.GetValue(); } ////// BindRegion /// /// /// ////// The MSDN specification requires this function to return E_NOTIMPL for the time being. /// public IntPtr BindRegion(FILTERREGION origPos, ref Guid riid) { throw new NotImplementedException(SR.Get(SRID.FilterBindRegionNotImplemented)); } #endregion IFilter methods #region Private methods ////// Find a filter object given its CLSID. /// ////// IFilter GetFilterFromClsid(Guid clsid) { Type filterType = Type.GetTypeFromCLSID(clsid); IFilter filter; try { filter = (IFilter)Activator.CreateInstance(filterType); } catch(InvalidCastException) { // If the CLSID that was given is not a filter's CLSID, fail the creation silently. return null; } catch(COMException) { // If the creation failed at the COM level, fail silently. return null; } return filter; } ////// If the clsid is not a proper IFilter clsid, this function will return null. /// The caller will then ignore the current part and attempt to filter the next part. /// ////// Non-fatal exceptions from external filters, identified for all practical purposes /// with InvalidCastException, COMException and IOException, are `swallowed by this method. /// ////// Move iterator to the next part that has an associated filter and (re)initialize the /// relevant filter. /// ////// This function results in _progress and _currentFilter being updated. /// private void MoveToNextFilter() { // Reset _isInternalFilter. _isInternalFilter = false; switch (_progress) { case Progress.FilteringNotStarted: #region Progress.FilteringNotStarted // Filtering not started yet. Start with core properties filter. IndexingFilterMarshaler corePropertiesFilterMarshaler = new IndexingFilterMarshaler( new CorePropertiesFilter(_package.PackageProperties)); // Avoid exception on end of chunks from part filter. corePropertiesFilterMarshaler.ThrowOnEndOfChunks = false; _currentFilter = corePropertiesFilterMarshaler; _currentFilter.Init(_grfFlags, _cAttributes, _aAttributes); _isInternalFilter = true; // Update progress to indicate filtering core properties. _progress = Progress.FilteringCoreProperties; break; #endregion Progress.FilteringNotStarted case Progress.FilteringCoreProperties: #region Progress.FilteringCoreProperties // Core properties were being filtered. Next move to content filtering. #endregion Progress.FilteringCoreProperties case Progress.FilteringContent: #region Progress.FilteringContent // // Content being filtered. Move to next content part filter if it exists. // Update progress to indicate filtering content if there is a next content // filter, else to indicate filtering is completed. // if (_currentStream != null) { // Close the stream for the previous PackagePart. _currentStream.Close(); _currentStream = null; } for (_currentFilter = null; _partIterator.MoveNext(); _currentFilter = null) { PackagePart currentPart = (PackagePart)_partIterator.Current; ContentType contentType = currentPart.ValidatedContentType; // Find the filter's CLSID based on the MIME content type. string filterClsid = GetFilterClsid(contentType, currentPart.Uri); if (filterClsid != null) { _currentFilter = GetFilterFromClsid(new Guid(filterClsid)); if (_currentFilter != null) { _currentStream = currentPart.GetStream(); ManagedIStream stream = new ManagedIStream(_currentStream); try { IPersistStreamWithArrays filterLoader = (IPersistStreamWithArrays)_currentFilter; filterLoader.Load(stream); _currentFilter.Init(_grfFlags, _cAttributes, _aAttributes); // Filter found and properly initialized. Search is over. break; } catch (InvalidCastException) { // If a filter does not implement IPersistStream, then, by design, it should // be ignored. } catch (COMException) { // Any initialization bug giving rise to an exception in the initialization // code should be ignored, since this will be due to faulty external code. } catch (IOException) { // Initialization problem can be reported as IOException. See preceding comment. } } } // // No valid externally registered filters found for this content part. // If this is xaml part, use the internal XamlFilter. // if (BindUriHelper.IsXamlMimeType(contentType)) { if (_currentStream == null) { _currentStream = currentPart.GetStream(); } IndexingFilterMarshaler xamlFilterMarshaler = new IndexingFilterMarshaler(new XamlFilter(_currentStream)); // Avoid exception on end of chunks from part filter. xamlFilterMarshaler.ThrowOnEndOfChunks = false; _currentFilter = xamlFilterMarshaler; _currentFilter.Init(_grfFlags, _cAttributes, _aAttributes); _isInternalFilter = true; // Filter found and properly initialized. Search is over. break; } if (_currentStream != null) { _currentStream.Close(); _currentStream = null; } } if (_currentFilter == null) { // Update progress to indicate filtering is completed. _progress = Progress.FilteringCompleted; } else { // Tell GetChunk that we are getting input from a new filter. _firstChunkFromFilter = true; // Update progress to indicate content being filtered. _progress = Progress.FilteringContent; } break; #endregion Progress.FilteringContent case Progress.FilteringCompleted: #region Progress.FilteringCompleted Debug.Assert(false); break; #endregion Progress.FilteringCompleted default: #region Default Debug.Assert(false); break; #endregion Default } } ////// Allocates a unique and legal chunk ID. /// To be called prior to returning a chunk. /// ////// 0 is an illegal value, so this function never returns 0. /// After the counter reaches UInt32.MaxValue, it wraps around to 1. /// private uint AllocateChunkID() { Invariant.Assert(_currentChunkID <= UInt32.MaxValue); ++_currentChunkID; return _currentChunkID; } ////// Access the registry to get the filter's CLSID associated with contentType, /// unless contentType is empty, in which case the content type is inferred from /// the file's extension. /// private string GetFilterClsid(ContentType contentType, Uri partUri) { // Find the file type guid associated with the mime content or (as a second choice) with the extension. string fileTypeGuid = null; if (contentType != null && !ContentType.Empty.AreTypeAndSubTypeEqual(contentType)) { fileTypeGuid = FileTypeGuidFromMimeType(contentType); } else { string extension = GetPartExtension(partUri); if (extension != null) { fileTypeGuid = FileTypeGuidFromFileExtension(extension); } } // Get the default value of // /HKEY_CLASSES_ROOT/CLSID//PersistentAddinsRegistered/ . if (fileTypeGuid == null) { return null; } RegistryKey iFilterIidKey = FindSubkey( Registry.ClassesRoot, MakeRegistryPath(_IFilterAddinPath, fileTypeGuid)); if (iFilterIidKey == null) { return null; } return (string)iFilterIidKey.GetValue(null); } /// /// Interprets an array of strings [keyPath] and returns the corresponding subkey /// if it exists, and null if it doesn't. /// private static RegistryKey FindSubkey(RegistryKey containingKey, string[] keyPath) { RegistryKey currentKey = containingKey; for (int keyNameIndex = 0; keyNameIndex < keyPath.Length; ++keyNameIndex) { if (currentKey == null) { return null; } currentKey = currentKey.OpenSubKey(keyPath[keyNameIndex]); } return currentKey; } ////// Gets the content type's GUID and find the associated PersistentHandler GUID. /// private string FileTypeGuidFromMimeType(ContentType contentType) { // This method is invoked only if contentType has been found to be non-empty. Debug.Assert(contentType != null && contentType.ToString().Length > 0); // Get the string in value Extension of key \HKEY_CLASSES_ROOT\MIME\Database\Content Type\. RegistryKey mimeContentType = FindSubkey(Registry.ClassesRoot, _mimeContentTypeKey); RegistryKey mimeTypeKey = (mimeContentType == null ? null : mimeContentType.OpenSubKey(contentType.ToString())); if (mimeTypeKey == null) { return null; } string extension = (string)mimeTypeKey.GetValue(_extension); if (extension == null) { return null; } // Use the extension to find the type GUID. return FileTypeGuidFromFileExtension(extension); } /// /// Get the PersistentHandler GUID associated with the parameter dottedExtensionName. /// /// Extension name with a dot as the first character. private string FileTypeGuidFromFileExtension(string dottedExtensionName) { // This method is invoked only if the part name has been found to have an extension. Debug.Assert(dottedExtensionName != null); // Extract \HKEY_CLASSES_ROOT\\PersistentHandler and return its default value. RegistryKey persistentHandlerKey = FindSubkey( Registry.ClassesRoot, MakeRegistryPath(_persistentHandlerKey, dottedExtensionName)); return (persistentHandlerKey == null ? null : (string)persistentHandlerKey.GetValue(null)); } // Return uri's extension or null if no extension. private string GetPartExtension(Uri partUri) { // partUri is the part's path as exposed by its part uri, so it cannot be null. Invariant.Assert(partUri != null); string path = PackUriHelper.GetStringForPartUri(partUri); string extension = Path.GetExtension(path); if (extension == string.Empty) return null; return extension; } //This method replaces null entries in pathWithGaps by stopGaps items in order of occurance private static string[] MakeRegistryPath(string[] pathWithGaps, params string[] stopGaps) { Debug.Assert(pathWithGaps != null && stopGaps != null); string[] path = (string[]) pathWithGaps.Clone(); int nextStopGapToUse = 0; for (int i = 0; i < path.Length; ++i) { if (path[i] == null) { Debug.Assert(stopGaps.Length > nextStopGapToUse); // Values of pathWithGaps and stopGaps are entirely controlled by internal code. path[i] = stopGaps[nextStopGapToUse]; ++nextStopGapToUse; } } Debug.Assert(stopGaps.Length == nextStopGapToUse); return path; } #endregion Private methods #region Constants // Registry paths. // Paths are represented by string arrays. Null entries are to be replaced by strings in order to // get a valid path (see method MakeRegistryPath). // The following path contains the IFilter IID, which can be found in the public SDK file filter.h. readonly string[] _IFilterAddinPath = new string[] { "CLSID", null, // file type GUID expected "PersistentAddinsRegistered", "{89BCB740-6119-101A-BCB7-00DD010655AF}" }; readonly string[] _mimeContentTypeKey = new string[] { "MIME", "Database", "Content Type" }; readonly string[] _persistentHandlerKey = { null, // extension string expected "PersistentHandler" }; #endregion Constants #region Fields private Package _package; private uint _currentChunkID; //defaults to 0 private IEnumerator _partIterator; //defaults to null private IFilter _currentFilter; //defaults to null private Stream _currentStream; //defaults to null private bool _firstChunkFromFilter; //defaults to false private Progress _progress = Progress.FilteringNotStarted; private bool _isInternalFilter; //defaults to false private IFILTER_INIT _grfFlags; //defaults to 0 private uint _cAttributes; //defaults to 0 private FULLPROPSPEC[] _aAttributes; //defaults to null private const string _extension = "Extension"; #endregion Fields } #endregion PackageFilter } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // // // Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // Managed equivalent of IFilter implemenation for Package // // History: // 02/02/2004: BruceMac: Stubs // 03/28/2004: JohnLarc: Initial implementation // 08/26/2004: JohnLarc: Removed access to indexing filters from managed code. // 07/18/2005: ArindamB: Changed ContainerFilterImpl to PackageFilter, // which implements IFilter instead of ManagedFilterBase. //----------------------------------------------------------------------------- using System; using System.IO; using System.IO.Packaging; using System.Collections; using System.Diagnostics; // For Assert using System.Runtime.InteropServices; // For Marshal.ThrowExceptionForHR using System.Windows; // for ExceptionStringTable using Microsoft.Win32; // For RegistryKey using MS.Internal.Interop; // For STAT_CHUNK, etc. using MS.Internal; // For ContentType using MS.Internal.Utility; // For BindUriHelper namespace MS.Internal.IO.Packaging { #region PackageFilter ////// Managed Package Filter /// ////// This is where implementation goes /// internal class PackageFilter : IFilter { #region Nested Types ////// Indicates filtering progress. /// private enum Progress { FilteringNotStarted = 0, FilteringCoreProperties = 1, FilteringContent = 2, FilteringCompleted = 3 } #endregion Nested Types #region constructor ////// Constructor. /// /// package to filter internal PackageFilter(Package package) { if (package == null) { throw new ArgumentNullException("package"); } _package = package; _partIterator = _package.GetParts().GetEnumerator(); } #endregion constructor #region IFilter methods ////// IFilter.Init /// /// usage flags /// number of elements in aAttributes /// array of Managed FULLPROPSPEC structs to restrict responses ///flags ////// Returns systematically IFILTER_FLAGS_NONE insofar as flags are used to control property search, /// which is not supported (See GetValue). /// public IFILTER_FLAGS Init(IFILTER_INIT grfFlags, // IFILTER_INIT value uint cAttributes, // length of aAttributes FULLPROPSPEC[] aAttributes) // restrict responses to the specified attributes { _grfFlags = grfFlags; _cAttributes = cAttributes; _aAttributes = aAttributes; _partIterator.Reset(); _progress = Progress.FilteringNotStarted; return IFILTER_FLAGS.IFILTER_FLAGS_NONE; } ////// Returns description of the next chunk. /// ////// Chunk descriptor. /// ////// public STAT_CHUNK GetChunk() { // // _progress is Progress.FilteringNotStarted initially and // subsequently gets updated in MoveToNextFilter(). // if (_progress == Progress.FilteringNotStarted) { MoveToNextFilter(); } if (_progress == Progress.FilteringCompleted) { throw new COMException(SR.Get(SRID.FilterEndOfChunks), (int)FilterErrorCode.FILTER_E_END_OF_CHUNKS); } while(true) { try { STAT_CHUNK chunk = _currentFilter.GetChunk(); // // No exception raised. // If _currentFilter is internal filter, // this might be end of chunks if chunk.idChunk is 0. // if (!_isInternalFilter || chunk.idChunk != 0) { // // There are more chunks. // // // Consider value chunks only when filtering core properties. // Else, ignore the chunk and move to the next. // if (_progress == Progress.FilteringCoreProperties || (chunk.flags & CHUNKSTATE.CHUNK_VALUE) != CHUNKSTATE.CHUNK_VALUE) { // // Found the next chunk to return. // // Replace ID from auxiliary filter by unique ID across the package. chunk.idChunk = AllocateChunkID(); // Since pseudo-properties (a.k.a. internal values) are not supported, // all chunks we return are expected to have idChunkSource equal to idChunk. // (See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/indexsrv/html/ixufilt_8ib8.asp) chunk.idChunkSource = chunk.idChunk; // Some filters (such as the plain text filter) // will return "no break" before the first chunk. // However, the correct break type at the beginning // of a part is "end of paragraph". if (_firstChunkFromFilter) { chunk.breakType = CHUNK_BREAKTYPE.CHUNK_EOP; // This flag gets set in MoveToNextFilter. _firstChunkFromFilter = false; } return chunk; } } } // Ignore IO and COM exceptions raised by an external filter. catch (COMException) { // Most of the time, this will be a FILTER_E_END_OF_CHUNKS exception. // In general, we don't really care: when an external filter gets in trouble // we simply move to the next filter. } catch (IOException exc) { // Internal filters do not throw expected exceptions; so something bad // must have happened. Let the client code get the exception and possibly // choose to ignore it. if (_isInternalFilter) { throw exc; } } // // Either there was FILTER_E_END_OF_CHUNKS exception // from _currentFilter.GetChunk(), // or _isInternalFilter is true and the returned chunk has // idChunk as 0, which also indicates end of chunks. // // Move to the next filter. // MoveToNextFilter(); if (_progress == Progress.FilteringCompleted) { // // No more filters. Filtering completed. // Throw FILTER_E_END_OF_CHUNKS exception. // throw new COMException(SR.Get(SRID.FilterEndOfChunks), (int)FilterErrorCode.FILTER_E_END_OF_CHUNKS); } } } ////// On end of stream, this function will throw an exception so as to return FILTER_E_END_OF_CHUNKS /// to client code, in keeping with the IFilter specifications. /// ////// Non-fatal exceptions from external filters, identified for all practical purposes /// with COMException and IOException, are `swallowed by this method. /// ////// Gets text content corresponding to current chunk. /// public void GetText(ref uint bufferCharacterCount, IntPtr pBuffer) { if (_progress != Progress.FilteringContent) { throw new COMException(SR.Get(SRID.FilterGetTextNotSupported), (int)FilterErrorCode.FILTER_E_NO_TEXT); } _currentFilter.GetText(ref bufferCharacterCount, pBuffer); } ////// Gets the property value corresponding to current chunk. /// ///Property value public IntPtr GetValue() { if (_progress != Progress.FilteringCoreProperties) { throw new COMException(SR.Get(SRID.FilterGetValueNotSupported), (int)FilterErrorCode.FILTER_E_NO_VALUES); } return _currentFilter.GetValue(); } ////// BindRegion /// /// /// ////// The MSDN specification requires this function to return E_NOTIMPL for the time being. /// public IntPtr BindRegion(FILTERREGION origPos, ref Guid riid) { throw new NotImplementedException(SR.Get(SRID.FilterBindRegionNotImplemented)); } #endregion IFilter methods #region Private methods ////// Find a filter object given its CLSID. /// ////// IFilter GetFilterFromClsid(Guid clsid) { Type filterType = Type.GetTypeFromCLSID(clsid); IFilter filter; try { filter = (IFilter)Activator.CreateInstance(filterType); } catch(InvalidCastException) { // If the CLSID that was given is not a filter's CLSID, fail the creation silently. return null; } catch(COMException) { // If the creation failed at the COM level, fail silently. return null; } return filter; } ////// If the clsid is not a proper IFilter clsid, this function will return null. /// The caller will then ignore the current part and attempt to filter the next part. /// ////// Non-fatal exceptions from external filters, identified for all practical purposes /// with InvalidCastException, COMException and IOException, are `swallowed by this method. /// ////// Move iterator to the next part that has an associated filter and (re)initialize the /// relevant filter. /// ////// This function results in _progress and _currentFilter being updated. /// private void MoveToNextFilter() { // Reset _isInternalFilter. _isInternalFilter = false; switch (_progress) { case Progress.FilteringNotStarted: #region Progress.FilteringNotStarted // Filtering not started yet. Start with core properties filter. IndexingFilterMarshaler corePropertiesFilterMarshaler = new IndexingFilterMarshaler( new CorePropertiesFilter(_package.PackageProperties)); // Avoid exception on end of chunks from part filter. corePropertiesFilterMarshaler.ThrowOnEndOfChunks = false; _currentFilter = corePropertiesFilterMarshaler; _currentFilter.Init(_grfFlags, _cAttributes, _aAttributes); _isInternalFilter = true; // Update progress to indicate filtering core properties. _progress = Progress.FilteringCoreProperties; break; #endregion Progress.FilteringNotStarted case Progress.FilteringCoreProperties: #region Progress.FilteringCoreProperties // Core properties were being filtered. Next move to content filtering. #endregion Progress.FilteringCoreProperties case Progress.FilteringContent: #region Progress.FilteringContent // // Content being filtered. Move to next content part filter if it exists. // Update progress to indicate filtering content if there is a next content // filter, else to indicate filtering is completed. // if (_currentStream != null) { // Close the stream for the previous PackagePart. _currentStream.Close(); _currentStream = null; } for (_currentFilter = null; _partIterator.MoveNext(); _currentFilter = null) { PackagePart currentPart = (PackagePart)_partIterator.Current; ContentType contentType = currentPart.ValidatedContentType; // Find the filter's CLSID based on the MIME content type. string filterClsid = GetFilterClsid(contentType, currentPart.Uri); if (filterClsid != null) { _currentFilter = GetFilterFromClsid(new Guid(filterClsid)); if (_currentFilter != null) { _currentStream = currentPart.GetStream(); ManagedIStream stream = new ManagedIStream(_currentStream); try { IPersistStreamWithArrays filterLoader = (IPersistStreamWithArrays)_currentFilter; filterLoader.Load(stream); _currentFilter.Init(_grfFlags, _cAttributes, _aAttributes); // Filter found and properly initialized. Search is over. break; } catch (InvalidCastException) { // If a filter does not implement IPersistStream, then, by design, it should // be ignored. } catch (COMException) { // Any initialization bug giving rise to an exception in the initialization // code should be ignored, since this will be due to faulty external code. } catch (IOException) { // Initialization problem can be reported as IOException. See preceding comment. } } } // // No valid externally registered filters found for this content part. // If this is xaml part, use the internal XamlFilter. // if (BindUriHelper.IsXamlMimeType(contentType)) { if (_currentStream == null) { _currentStream = currentPart.GetStream(); } IndexingFilterMarshaler xamlFilterMarshaler = new IndexingFilterMarshaler(new XamlFilter(_currentStream)); // Avoid exception on end of chunks from part filter. xamlFilterMarshaler.ThrowOnEndOfChunks = false; _currentFilter = xamlFilterMarshaler; _currentFilter.Init(_grfFlags, _cAttributes, _aAttributes); _isInternalFilter = true; // Filter found and properly initialized. Search is over. break; } if (_currentStream != null) { _currentStream.Close(); _currentStream = null; } } if (_currentFilter == null) { // Update progress to indicate filtering is completed. _progress = Progress.FilteringCompleted; } else { // Tell GetChunk that we are getting input from a new filter. _firstChunkFromFilter = true; // Update progress to indicate content being filtered. _progress = Progress.FilteringContent; } break; #endregion Progress.FilteringContent case Progress.FilteringCompleted: #region Progress.FilteringCompleted Debug.Assert(false); break; #endregion Progress.FilteringCompleted default: #region Default Debug.Assert(false); break; #endregion Default } } ////// Allocates a unique and legal chunk ID. /// To be called prior to returning a chunk. /// ////// 0 is an illegal value, so this function never returns 0. /// After the counter reaches UInt32.MaxValue, it wraps around to 1. /// private uint AllocateChunkID() { Invariant.Assert(_currentChunkID <= UInt32.MaxValue); ++_currentChunkID; return _currentChunkID; } ////// Access the registry to get the filter's CLSID associated with contentType, /// unless contentType is empty, in which case the content type is inferred from /// the file's extension. /// private string GetFilterClsid(ContentType contentType, Uri partUri) { // Find the file type guid associated with the mime content or (as a second choice) with the extension. string fileTypeGuid = null; if (contentType != null && !ContentType.Empty.AreTypeAndSubTypeEqual(contentType)) { fileTypeGuid = FileTypeGuidFromMimeType(contentType); } else { string extension = GetPartExtension(partUri); if (extension != null) { fileTypeGuid = FileTypeGuidFromFileExtension(extension); } } // Get the default value of // /HKEY_CLASSES_ROOT/CLSID//PersistentAddinsRegistered/ . if (fileTypeGuid == null) { return null; } RegistryKey iFilterIidKey = FindSubkey( Registry.ClassesRoot, MakeRegistryPath(_IFilterAddinPath, fileTypeGuid)); if (iFilterIidKey == null) { return null; } return (string)iFilterIidKey.GetValue(null); } /// /// Interprets an array of strings [keyPath] and returns the corresponding subkey /// if it exists, and null if it doesn't. /// private static RegistryKey FindSubkey(RegistryKey containingKey, string[] keyPath) { RegistryKey currentKey = containingKey; for (int keyNameIndex = 0; keyNameIndex < keyPath.Length; ++keyNameIndex) { if (currentKey == null) { return null; } currentKey = currentKey.OpenSubKey(keyPath[keyNameIndex]); } return currentKey; } ////// Gets the content type's GUID and find the associated PersistentHandler GUID. /// private string FileTypeGuidFromMimeType(ContentType contentType) { // This method is invoked only if contentType has been found to be non-empty. Debug.Assert(contentType != null && contentType.ToString().Length > 0); // Get the string in value Extension of key \HKEY_CLASSES_ROOT\MIME\Database\Content Type\. RegistryKey mimeContentType = FindSubkey(Registry.ClassesRoot, _mimeContentTypeKey); RegistryKey mimeTypeKey = (mimeContentType == null ? null : mimeContentType.OpenSubKey(contentType.ToString())); if (mimeTypeKey == null) { return null; } string extension = (string)mimeTypeKey.GetValue(_extension); if (extension == null) { return null; } // Use the extension to find the type GUID. return FileTypeGuidFromFileExtension(extension); } /// /// Get the PersistentHandler GUID associated with the parameter dottedExtensionName. /// /// Extension name with a dot as the first character. private string FileTypeGuidFromFileExtension(string dottedExtensionName) { // This method is invoked only if the part name has been found to have an extension. Debug.Assert(dottedExtensionName != null); // Extract \HKEY_CLASSES_ROOT\\PersistentHandler and return its default value. RegistryKey persistentHandlerKey = FindSubkey( Registry.ClassesRoot, MakeRegistryPath(_persistentHandlerKey, dottedExtensionName)); return (persistentHandlerKey == null ? null : (string)persistentHandlerKey.GetValue(null)); } // Return uri's extension or null if no extension. private string GetPartExtension(Uri partUri) { // partUri is the part's path as exposed by its part uri, so it cannot be null. Invariant.Assert(partUri != null); string path = PackUriHelper.GetStringForPartUri(partUri); string extension = Path.GetExtension(path); if (extension == string.Empty) return null; return extension; } //This method replaces null entries in pathWithGaps by stopGaps items in order of occurance private static string[] MakeRegistryPath(string[] pathWithGaps, params string[] stopGaps) { Debug.Assert(pathWithGaps != null && stopGaps != null); string[] path = (string[]) pathWithGaps.Clone(); int nextStopGapToUse = 0; for (int i = 0; i < path.Length; ++i) { if (path[i] == null) { Debug.Assert(stopGaps.Length > nextStopGapToUse); // Values of pathWithGaps and stopGaps are entirely controlled by internal code. path[i] = stopGaps[nextStopGapToUse]; ++nextStopGapToUse; } } Debug.Assert(stopGaps.Length == nextStopGapToUse); return path; } #endregion Private methods #region Constants // Registry paths. // Paths are represented by string arrays. Null entries are to be replaced by strings in order to // get a valid path (see method MakeRegistryPath). // The following path contains the IFilter IID, which can be found in the public SDK file filter.h. readonly string[] _IFilterAddinPath = new string[] { "CLSID", null, // file type GUID expected "PersistentAddinsRegistered", "{89BCB740-6119-101A-BCB7-00DD010655AF}" }; readonly string[] _mimeContentTypeKey = new string[] { "MIME", "Database", "Content Type" }; readonly string[] _persistentHandlerKey = { null, // extension string expected "PersistentHandler" }; #endregion Constants #region Fields private Package _package; private uint _currentChunkID; //defaults to 0 private IEnumerator _partIterator; //defaults to null private IFilter _currentFilter; //defaults to null private Stream _currentStream; //defaults to null private bool _firstChunkFromFilter; //defaults to false private Progress _progress = Progress.FilteringNotStarted; private bool _isInternalFilter; //defaults to false private IFILTER_INIT _grfFlags; //defaults to 0 private uint _cAttributes; //defaults to 0 private FULLPROPSPEC[] _aAttributes; //defaults to null private const string _extension = "Extension"; #endregion Fields } #endregion PackageFilter } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PageFunction.cs
- EncoderParameter.cs
- TypeConverterAttribute.cs
- MulticastOption.cs
- CfgSemanticTag.cs
- FileVersionInfo.cs
- EventDescriptor.cs
- RadioButtonPopupAdapter.cs
- XPathNodePointer.cs
- ScriptIgnoreAttribute.cs
- ProxyHwnd.cs
- PointConverter.cs
- NamespaceEmitter.cs
- UntrustedRecipientException.cs
- Process.cs
- NetStream.cs
- PerformanceCounterPermission.cs
- XmlDownloadManager.cs
- FileDialog.cs
- SQLSingle.cs
- BooleanFacetDescriptionElement.cs
- ExtensionSimplifierMarkupObject.cs
- CollectionViewSource.cs
- PixelShader.cs
- RSAPKCS1KeyExchangeDeformatter.cs
- ServiceMetadataExtension.cs
- SelectionRange.cs
- MetadataCollection.cs
- JobPageOrder.cs
- CodeTypeDeclarationCollection.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- DataSvcMapFileSerializer.cs
- ProfilePropertySettings.cs
- InvokeProviderWrapper.cs
- FormattedTextSymbols.cs
- TypeToken.cs
- ListDictionary.cs
- GenericUriParser.cs
- StrokeCollectionDefaultValueFactory.cs
- SettingsPropertyValueCollection.cs
- FixedPageStructure.cs
- COM2TypeInfoProcessor.cs
- IndentedWriter.cs
- webclient.cs
- NavigateEvent.cs
- GlyphTypeface.cs
- IndependentlyAnimatedPropertyMetadata.cs
- ShaderRenderModeValidation.cs
- OracleRowUpdatedEventArgs.cs
- PreservationFileReader.cs
- XmlSchemaSimpleContent.cs
- OdbcRowUpdatingEvent.cs
- LinearGradientBrush.cs
- FunctionUpdateCommand.cs
- SerializationSectionGroup.cs
- RecognizedAudio.cs
- TextureBrush.cs
- AssertUtility.cs
- FixedPageProcessor.cs
- VisualCollection.cs
- XmlSchemaComplexType.cs
- InstalledFontCollection.cs
- ColorAnimationBase.cs
- StackOverflowException.cs
- LayoutManager.cs
- CopyCodeAction.cs
- CorruptingExceptionCommon.cs
- QuaternionAnimationUsingKeyFrames.cs
- ExpressionDumper.cs
- BooleanKeyFrameCollection.cs
- StopStoryboard.cs
- TableDetailsCollection.cs
- ConfigurationSectionCollection.cs
- InvalidateEvent.cs
- VBIdentifierName.cs
- Int32CAMarshaler.cs
- WebReference.cs
- DeclarationUpdate.cs
- SoapSchemaImporter.cs
- GenericRootAutomationPeer.cs
- Soap12FormatExtensions.cs
- PerfService.cs
- TextRangeAdaptor.cs
- CommentEmitter.cs
- EventLogEntryCollection.cs
- MsmqChannelFactoryBase.cs
- SystemTcpStatistics.cs
- SystemFonts.cs
- WebPartConnection.cs
- DataComponentMethodGenerator.cs
- RowCache.cs
- PointKeyFrameCollection.cs
- ConfigXmlAttribute.cs
- ExeContext.cs
- IdleTimeoutMonitor.cs
- ReversePositionQuery.cs
- StrokeFIndices.cs
- _SslState.cs
- BooleanFunctions.cs
- FixedSOMTable.cs