FilterLoader.cs
上传用户:huiyue
上传日期:2022-04-08
资源大小:1429k
文件大小:9k
源码类别:

搜索引擎

开发平台:

ASP/ASPX

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using Microsoft.Win32;
  5. using System.IO;
  6. using System.Runtime.InteropServices.ComTypes;
  7. using System.Runtime.InteropServices;
  8. namespace EPocalipse.IFilter
  9. {
  10.   /// <summary>
  11.   /// FilterLoader finds the dll and ClassID of the COM object responsible  
  12.   /// for filtering a specific file extension. 
  13.   /// It then loads that dll, creates the appropriate COM object and returns 
  14.   /// a pointer to an IFilter instance
  15.   /// </summary>
  16.   /// <remarks>
  17.   /// Developing IFilter Add-ins
  18.   /// http://msdn2.microsoft.com/en-us/library/aa965717.aspx
  19.   /// </remarks>
  20.   static class FilterLoader
  21.   {
  22.     #region CacheEntry
  23.     private class CacheEntry
  24.     {
  25.       public string DllName;
  26.       public string ClassName;
  27.       public CacheEntry(string dllName, string className)
  28.       {
  29.         DllName=dllName;
  30.         ClassName=className;
  31.       }
  32.     }
  33.     #endregion
  34.     static Dictionary<string, CacheEntry> _cache=new Dictionary<string, CacheEntry>();
  35.     #region Registry Read String helper
  36.     static string ReadStrFromHKLM(string key)
  37.     {
  38.       return ReadStrFromHKLM(key,null);
  39.     }
  40.     static string ReadStrFromHKLM(string key, string value)
  41.     {
  42.       RegistryKey rk=Registry.LocalMachine.OpenSubKey(key);
  43.       if (rk==null)
  44.         return null;
  45.       using (rk)
  46.       {
  47.         return (string)rk.GetValue(value);
  48.       }
  49.     }
  50.     #endregion
  51.     /// <summary>
  52.     /// finds an IFilter implementation for a file type
  53.     /// </summary>
  54.     /// <param name="ext">The extension of the file</param>
  55.     /// <returns>an IFilter instance used to retreive text from that file type</returns>
  56.     private static IFilter LoadIFilter(string ext)
  57.     {
  58.       string dllName, filterPersistClass;
  59.       //Find the dll and ClassID
  60.       if (GetFilterDllAndClass(ext, out dllName, out filterPersistClass))
  61.       {
  62.         //load the dll and return an IFilter instance.
  63.         return LoadFilterFromDll(dllName, filterPersistClass);
  64.       }
  65.       return null;
  66.     }
  67.     internal static IFilter LoadAndInitIFilter(string fileName)
  68.     {
  69.       return LoadAndInitIFilter(fileName,Path.GetExtension(fileName));
  70.     }
  71.     internal static IFilter LoadAndInitIFilter(string fileName, string extension)
  72.     {
  73.       IFilter filter=LoadIFilter(extension);
  74.       if (filter==null)
  75.         return null;
  76.       IPersistFile persistFile=(filter as IPersistFile);
  77.       if (persistFile!=null)
  78.       {
  79.         persistFile.Load(fileName, 0);
  80.         IFILTER_FLAGS flags;
  81.         IFILTER_INIT iflags =
  82.                     IFILTER_INIT.CANON_HYPHENS |
  83.                     IFILTER_INIT.CANON_PARAGRAPHS |
  84.                     IFILTER_INIT.CANON_SPACES |
  85.                     IFILTER_INIT.APPLY_INDEX_ATTRIBUTES |
  86.                     IFILTER_INIT.HARD_LINE_BREAKS |
  87.                     IFILTER_INIT.FILTER_OWNED_VALUE_OK;
  88.          iflags =
  89.           IFILTER_INIT.CANON_HYPHENS |
  90.           IFILTER_INIT.CANON_PARAGRAPHS |
  91.           IFILTER_INIT.CANON_SPACES |
  92.           IFILTER_INIT.HARD_LINE_BREAKS |
  93.           IFILTER_INIT.FILTER_OWNED_VALUE_OK |
  94.           IFILTER_INIT.APPLY_INDEX_ATTRIBUTES |
  95.           IFILTER_INIT.APPLY_CRAWL_ATTRIBUTES |
  96.           IFILTER_INIT.APPLY_OTHER_ATTRIBUTES |
  97.           IFILTER_INIT.FILTER_OWNED_VALUE_OK; // added [CD]
  98.         if (filter.Init(iflags, 0, IntPtr.Zero, out flags)==IFilterReturnCode.S_OK)
  99.           return filter;
  100.       }
  101.       //If we failed to retreive an IPersistFile interface or to initialize 
  102.       //the filter, we release it and return null.
  103.       Marshal.ReleaseComObject(filter);
  104.       return null;
  105.     }
  106.     private static IFilter LoadFilterFromDll(string dllName, string filterPersistClass)
  107.     {
  108.       //Get a classFactory for our classID
  109.       IClassFactory classFactory=ComHelper.GetClassFactory(dllName, filterPersistClass);
  110.       if (classFactory==null)
  111.         return null;
  112.       //And create an IFilter instance using that class factory
  113.       // http://msdn2.microsoft.com/en-us/library/aa965717.aspx
  114.       // The first identifies all filters' persistent handler, IID_IFilter, which is {89BCB740-6119-101A-BCB7-00DD010655AF}. This CLSID is constant for all filters that implement IFilter.
  115.       Guid IFilterGUID=new Guid("89BCB740-6119-101A-BCB7-00DD010655AF");
  116.       Object obj;
  117.       classFactory.CreateInstance(null, ref IFilterGUID, out obj);
  118.       return (obj as IFilter);
  119.     }
  120.     private static bool GetFilterDllAndClass(string ext, out string dllName, out string filterPersistClass)
  121.     {
  122.       if (!GetFilterDllAndClassFromCache(ext, out dllName, out filterPersistClass))
  123.       {
  124.         string persistentHandlerClass;
  125.         persistentHandlerClass=GetPersistentHandlerClass(ext,true);
  126.         if (persistentHandlerClass!=null)
  127.         {
  128.           GetFilterDllAndClassFromPersistentHandler(persistentHandlerClass,
  129.             out dllName, out filterPersistClass);
  130.         }
  131.         AddExtensionToCache(ext, dllName, filterPersistClass);
  132.       }
  133.       return (dllName!=null && filterPersistClass!=null); 
  134.     }
  135.     private static void AddExtensionToCache(string ext, string dllName, string filterPersistClass)
  136.     {
  137.       lock (_cache)
  138.       {
  139.         _cache.Add(ext.ToLower(), new CacheEntry(dllName, filterPersistClass));
  140.       }
  141.     }
  142.     private static bool GetFilterDllAndClassFromPersistentHandler(string persistentHandlerClass, out string dllName, out string filterPersistClass)
  143.     {
  144.       dllName=null;
  145.       filterPersistClass=null;
  146.       //Read the CLASS ID of the IFilter persistent handler
  147.       filterPersistClass=ReadStrFromHKLM(@"SoftwareClassesCLSID" + persistentHandlerClass + 
  148.         @"PersistentAddinsRegistered{89BCB740-6119-101A-BCB7-00DD010655AF}");
  149.       if (String.IsNullOrEmpty(filterPersistClass))
  150.           return false;
  151.       //Read the dll name 
  152.       dllName=ReadStrFromHKLM(@"SoftwareClassesCLSID" + filterPersistClass + 
  153.         @"InprocServer32");
  154.       return (!String.IsNullOrEmpty(dllName));
  155.     }
  156.     private static string GetPersistentHandlerClass(string ext, bool searchContentType)
  157.     {
  158.       //Try getting the info from the file extension
  159.       string persistentHandlerClass=GetPersistentHandlerClassFromExtension(ext);
  160.       if (String.IsNullOrEmpty(persistentHandlerClass))
  161.         //try getting the info from the document type 
  162.         persistentHandlerClass=GetPersistentHandlerClassFromDocumentType(ext);
  163.       if (searchContentType && String.IsNullOrEmpty(persistentHandlerClass))
  164.         //Try getting the info from the Content Type
  165.         persistentHandlerClass=GetPersistentHandlerClassFromContentType(ext);
  166.       return persistentHandlerClass;
  167.     }
  168.     private static string GetPersistentHandlerClassFromContentType(string ext)
  169.     {
  170.       string contentType=ReadStrFromHKLM(@"SoftwareClasses"+ext,"Content Type");
  171.       if (String.IsNullOrEmpty(contentType))
  172.         return null;
  173.       
  174.       string contentTypeExtension=ReadStrFromHKLM(@"SoftwareClassesMIMEDatabaseContent Type"+contentType,
  175.           "Extension");
  176.       if (ext.Equals(contentTypeExtension, StringComparison.CurrentCultureIgnoreCase))
  177.         return null; //No need to look further. This extension does not have any persistent handler
  178.     
  179.       //We know the extension that is assciated with that content type. Simply try again with the new extension
  180.       return GetPersistentHandlerClass(contentTypeExtension, false); //Don't search content type this time.
  181.     }
  182.     private static string GetPersistentHandlerClassFromDocumentType(string ext)
  183.     {
  184.       //Get the DocumentType of this file extension
  185.       string docType=ReadStrFromHKLM(@"SoftwareClasses"+ext);
  186.       if (String.IsNullOrEmpty(docType))
  187.         return null;
  188.       
  189.       //Get the Class ID for this document type
  190.       string docClass=ReadStrFromHKLM(@"SoftwareClasses" + docType + @"CLSID");
  191.       if (String.IsNullOrEmpty(docType))
  192.         return null;
  193.       //Now get the PersistentHandler for that Class ID
  194.       return ReadStrFromHKLM(@"SoftwareClassesCLSID" + docClass + @"PersistentHandler");
  195.     }
  196.     private static string GetPersistentHandlerClassFromExtension(string ext)
  197.     {
  198.       return ReadStrFromHKLM(@"SoftwareClasses"+ext+@"PersistentHandler");
  199.     }
  200.     private static bool GetFilterDllAndClassFromCache(string ext, out string dllName, out string filterPersistClass)
  201.     {
  202.       string lowerExt=ext.ToLower();
  203.       lock (_cache)
  204.       {
  205.         CacheEntry cacheEntry;
  206.         if (_cache.TryGetValue(lowerExt, out cacheEntry))
  207.         {
  208.           dllName=cacheEntry.DllName;
  209.           filterPersistClass=cacheEntry.ClassName;
  210.           return true;
  211.         }
  212.       }
  213.       dllName=null;
  214.       filterPersistClass=null;
  215.       return false;
  216.     }
  217.   }
  218. }