This commit is contained in:
226
PROMS/EPocalipse.IFilter/FilterLoader.cs
Normal file
226
PROMS/EPocalipse.IFilter/FilterLoader.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Microsoft.Win32;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace EPocalipse.IFilter
|
||||
{
|
||||
/// <summary>
|
||||
/// FilterLoader finds the dll and ClassID of the COM object responsible
|
||||
/// for filtering a specific file extension.
|
||||
/// It then loads that dll, creates the appropriate COM object and returns
|
||||
/// a pointer to an IFilter instance
|
||||
/// </summary>
|
||||
static class FilterLoader
|
||||
{
|
||||
#region CacheEntry
|
||||
private class CacheEntry
|
||||
{
|
||||
public string DllName;
|
||||
public string ClassName;
|
||||
|
||||
public CacheEntry(string dllName, string className)
|
||||
{
|
||||
DllName=dllName;
|
||||
ClassName=className;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
static Dictionary<string, CacheEntry> _cache=new Dictionary<string, CacheEntry>();
|
||||
|
||||
#region Registry Read String helper
|
||||
static string ReadStrFromHKLM(string key)
|
||||
{
|
||||
return ReadStrFromHKLM(key,null);
|
||||
}
|
||||
static string ReadStrFromHKLM(string key, string value)
|
||||
{
|
||||
RegistryKey rk=Registry.LocalMachine.OpenSubKey(key);
|
||||
if (rk==null)
|
||||
return null;
|
||||
|
||||
using (rk)
|
||||
{
|
||||
return (string)rk.GetValue(value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// finds an IFilter implementation for a file type
|
||||
/// </summary>
|
||||
/// <param name="ext">The extension of the file</param>
|
||||
/// <returns>an IFilter instance used to retreive text from that file type</returns>
|
||||
private static IFilter LoadIFilter(string ext)
|
||||
{
|
||||
string dllName, filterPersistClass;
|
||||
|
||||
//Find the dll and ClassID
|
||||
if (GetFilterDllAndClass(ext, out dllName, out filterPersistClass))
|
||||
{
|
||||
//load the dll and return an IFilter instance.
|
||||
return LoadFilterFromDll(dllName, filterPersistClass);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
internal static IFilter LoadAndInitIFilter(string fileName)
|
||||
{
|
||||
return LoadAndInitIFilter(fileName,Path.GetExtension(fileName));
|
||||
}
|
||||
|
||||
internal static IFilter LoadAndInitIFilter(string fileName, string extension)
|
||||
{
|
||||
IFilter filter=LoadIFilter(extension);
|
||||
if (filter==null)
|
||||
return null;
|
||||
IPersistFile persistFile=(filter as IPersistFile);
|
||||
if (persistFile!=null)
|
||||
{
|
||||
persistFile.Load(fileName, 0);
|
||||
IFILTER_FLAGS flags;
|
||||
IFILTER_INIT iflags =
|
||||
IFILTER_INIT.CANON_HYPHENS |
|
||||
IFILTER_INIT.CANON_PARAGRAPHS |
|
||||
IFILTER_INIT.CANON_SPACES |
|
||||
IFILTER_INIT.APPLY_INDEX_ATTRIBUTES |
|
||||
IFILTER_INIT.HARD_LINE_BREAKS |
|
||||
IFILTER_INIT.FILTER_OWNED_VALUE_OK;
|
||||
|
||||
if (filter.Init(iflags, 0, IntPtr.Zero, out flags)==IFilterReturnCode.S_OK)
|
||||
return filter;
|
||||
}
|
||||
//If we failed to retreive an IPersistFile interface or to initialize
|
||||
//the filter, we release it and return null.
|
||||
Marshal.ReleaseComObject(filter);
|
||||
return null;
|
||||
}
|
||||
|
||||
private static IFilter LoadFilterFromDll(string dllName, string filterPersistClass)
|
||||
{
|
||||
//Get a classFactory for our classID
|
||||
IClassFactory classFactory=ComHelper.GetClassFactory(dllName, filterPersistClass);
|
||||
if (classFactory==null)
|
||||
return null;
|
||||
|
||||
//And create an IFilter instance using that class factory
|
||||
Guid IFilterGUID=new Guid("89BCB740-6119-101A-BCB7-00DD010655AF");
|
||||
Object obj;
|
||||
classFactory.CreateInstance(null, ref IFilterGUID, out obj);
|
||||
return (obj as IFilter);
|
||||
}
|
||||
|
||||
private static bool GetFilterDllAndClass(string ext, out string dllName, out string filterPersistClass)
|
||||
{
|
||||
if (!GetFilterDllAndClassFromCache(ext, out dllName, out filterPersistClass))
|
||||
{
|
||||
string persistentHandlerClass;
|
||||
|
||||
persistentHandlerClass=GetPersistentHandlerClass(ext,true);
|
||||
if (persistentHandlerClass!=null)
|
||||
{
|
||||
GetFilterDllAndClassFromPersistentHandler(persistentHandlerClass,
|
||||
out dllName, out filterPersistClass);
|
||||
}
|
||||
AddExtensionToCache(ext, dllName, filterPersistClass);
|
||||
}
|
||||
return (dllName!=null && filterPersistClass!=null);
|
||||
}
|
||||
|
||||
private static void AddExtensionToCache(string ext, string dllName, string filterPersistClass)
|
||||
{
|
||||
lock (_cache)
|
||||
{
|
||||
_cache.Add(ext.ToLower(), new CacheEntry(dllName, filterPersistClass));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool GetFilterDllAndClassFromPersistentHandler(string persistentHandlerClass, out string dllName, out string filterPersistClass)
|
||||
{
|
||||
dllName=null;
|
||||
filterPersistClass=null;
|
||||
|
||||
//Read the CLASS ID of the IFilter persistent handler
|
||||
filterPersistClass=ReadStrFromHKLM(@"Software\Classes\CLSID\" + persistentHandlerClass +
|
||||
@"\PersistentAddinsRegistered\{89BCB740-6119-101A-BCB7-00DD010655AF}");
|
||||
if (String.IsNullOrEmpty(filterPersistClass))
|
||||
return false;
|
||||
|
||||
//Read the dll name
|
||||
dllName=ReadStrFromHKLM(@"Software\Classes\CLSID\" + filterPersistClass +
|
||||
@"\InprocServer32");
|
||||
return (!String.IsNullOrEmpty(dllName));
|
||||
}
|
||||
|
||||
private static string GetPersistentHandlerClass(string ext, bool searchContentType)
|
||||
{
|
||||
//Try getting the info from the file extension
|
||||
string persistentHandlerClass=GetPersistentHandlerClassFromExtension(ext);
|
||||
if (String.IsNullOrEmpty(persistentHandlerClass))
|
||||
//try getting the info from the document type
|
||||
persistentHandlerClass=GetPersistentHandlerClassFromDocumentType(ext);
|
||||
if (searchContentType && String.IsNullOrEmpty(persistentHandlerClass))
|
||||
//Try getting the info from the Content Type
|
||||
persistentHandlerClass=GetPersistentHandlerClassFromContentType(ext);
|
||||
return persistentHandlerClass;
|
||||
}
|
||||
|
||||
private static string GetPersistentHandlerClassFromContentType(string ext)
|
||||
{
|
||||
string contentType=ReadStrFromHKLM(@"Software\Classes\"+ext,"Content Type");
|
||||
if (String.IsNullOrEmpty(contentType))
|
||||
return null;
|
||||
|
||||
string contentTypeExtension=ReadStrFromHKLM(@"Software\Classes\MIME\Database\Content Type\"+contentType,
|
||||
"Extension");
|
||||
if (ext.Equals(contentTypeExtension, StringComparison.CurrentCultureIgnoreCase))
|
||||
return null; //No need to look further. This extension does not have any persistent handler
|
||||
|
||||
//We know the extension that is assciated with that content type. Simply try again with the new extension
|
||||
return GetPersistentHandlerClass(contentTypeExtension, false); //Don't search content type this time.
|
||||
}
|
||||
|
||||
private static string GetPersistentHandlerClassFromDocumentType(string ext)
|
||||
{
|
||||
//Get the DocumentType of this file extension
|
||||
string docType=ReadStrFromHKLM(@"Software\Classes\"+ext);
|
||||
if (String.IsNullOrEmpty(docType))
|
||||
return null;
|
||||
|
||||
//Get the Class ID for this document type
|
||||
string docClass=ReadStrFromHKLM(@"Software\Classes\" + docType + @"\CLSID");
|
||||
if (String.IsNullOrEmpty(docType))
|
||||
return null;
|
||||
|
||||
//Now get the PersistentHandler for that Class ID
|
||||
return ReadStrFromHKLM(@"Software\Classes\CLSID\" + docClass + @"\PersistentHandler");
|
||||
}
|
||||
|
||||
private static string GetPersistentHandlerClassFromExtension(string ext)
|
||||
{
|
||||
return ReadStrFromHKLM(@"Software\Classes\"+ext+@"\PersistentHandler");
|
||||
}
|
||||
|
||||
private static bool GetFilterDllAndClassFromCache(string ext, out string dllName, out string filterPersistClass)
|
||||
{
|
||||
string lowerExt=ext.ToLower();
|
||||
lock (_cache)
|
||||
{
|
||||
CacheEntry cacheEntry;
|
||||
if (_cache.TryGetValue(lowerExt, out cacheEntry))
|
||||
{
|
||||
dllName=cacheEntry.DllName;
|
||||
filterPersistClass=cacheEntry.ClassName;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
dllName=null;
|
||||
filterPersistClass=null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user