Uso de ifilter en C# y recuperación de archivo de la base de datos en lugar del sistema de archivos

StackOverflow https://stackoverflow.com/questions/7313828

  •  26-10-2019
  •  | 
  •  

Pregunta

Para una aplicación web C#, quiero indexar texto de archivos PDF, DOC, etc. almacenados en una base de datos.

He estado experimentando con Un ejemplo de ifilter en el proyecto de código Lo que funciona muy bien para los archivos del sistema de archivos, pero mis archivos se almacenan en una base de datos MS-SQL.

¿Alguien puede ayudarme a localizar una muestra para extraer texto de los archivos almacenados en una base de datos o tener una idea sobre cómo modificar el código del proyecto del código para que funcione con una base de datos en lugar del sistema de archivos?

¿Fue útil?

Solución

¡Finalmente, después de muchas horas, descubrí cómo hacer que esto funcionara! Necesitaba ejecutar IFILTER en el contenido PDF almacenado en una base de datos y quería evitar guardar los datos en archivos temporales.

Primero intenté usar el BindifilterFromStream API para crear un Ifilter para el contenido almacenado en una transmisión, pero parece que no funciona correctamente (al menos no para este escenario). Así que no vayas de esa manera.

En su lugar, debe crear un iFilter para una extensión de archivo (o acceder a él de otra manera). Entonces puedes acceder al Ipersiststream Interfaz COM y úsela para cargar el contenido PDF en el IFILTER. El resto funciona igual que para los archivos. Sin embargo, tenga en cuenta que la API IPersistStream puede no ser implementada por cada IFILTER. Sin embargo, funciona para Adobe PDF Ifilter.

El código debería verse así (eliminé algunas verificaciones de código de retorno para que el código sea más legible, sin embargo, debe verificar todos los códigos de retorno posibles).

private string ParseIFilter(Stream s)
{
   // Get an IFilter for a file or file extension
   IFilter filter = null;
   FilterReturnCodes result = NativeMethods.LoadIFilter(".pdf", null, ref filter);
   if (result != FilterReturnCodes.S_OK)
   {
      Marshal.ThrowExceptionForHR((int)result);
   }

   // Copy the content to global memory
   byte[] buffer = new byte[s.Length];
   s.Read(buffer, 0, buffer.Length);
   IntPtr nativePtr = Marshal.AllocHGlobal(buffer.Length);
   Marshal.Copy(buffer, 0, nativePtr, buffer.Length);

   // Create a COM stream
   System.Runtime.InteropServices.ComTypes.IStream comStream;
   NativeMethods.CreateStreamOnHGlobal(nativePtr, true, out comStream);

   // Load the contents to the iFilter using IPersistStream interface
   var persistStream = (IPersistStream)filter;
   persistStream.Load(comStream);

   // Initialize iFilter
   FilterFlags filterFlags;
   FilterReturnCodes result = filter.Init(
      FilterInit.IFILTER_INIT_INDEXING_ONLY, 0, IntPtr.Zero, out filterFlags);

   return ExtractTextFromIFilter(filter);
}

La extracción de texto del filtro se ve así en mi código. Hay muchos ejemplos de esto en la web y se puede implementar de muchas maneras dependiendo de lo que necesite.

private string ExtractTextFromIFilter(IFilter filter)
{
   var sb = new StringBuilder();

   while (true)
   {
      StatChunk chunk;
      result = filter.GetChunk(out chunk);

      if (result == FilterReturnCodes.S_OK)
      {
         if (chunk.flags == ChunkState.CHUNK_TEXT)
         {
            sb.Append(ExtractTextFromChunk(filter, chunk));
         }

         continue;
      }

      if (result == FilterReturnCodes.FILTER_E_END_OF_CHUNKS)
      {
         return sb.ToString();
      }

      Marshal.ThrowExceptionForHR((int)result);
   }
}

private virtual string ExtractTextFromChunk(IFilter filter, StatChunk chunk)
{
   var sb = new StringBuilder();

   var result = FilterReturnCodes.S_OK;
   while (result == FilterReturnCodes.S_OK)
   {
      int sizeBuffer = 16384;
      var buffer = new StringBuilder(sizeBuffer);
      result = filter.GetText(ref sizeBuffer, buffer);

      if ((result == FilterReturnCodes.S_OK) || (result == FilterReturnCodes.FILTER_S_LAST_TEXT))
      {
         if((sizeBuffer > 0) && (buffer.Length > 0))
         {
            sb.Append(buffer.ToString(0, sizeBuffer));
         }
      }

      if (result == FilterReturnCodes.FILTER_E_NO_TEXT)
      {
         return string.Empty;
      }

      if ((result == FilterReturnCodes.FILTER_S_LAST_TEXT) || (result == FilterReturnCodes.FILTER_E_NO_MORE_TEXT))
      {
         return sb.ToString();
      }
   }

   return sb.ToString();
}

Y aquí están las definiciones de métodos nativos y las estructuras utilizadas por ellos.

internal static class NativeMethods
{
    [DllImport("query.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    public static extern FilterReturnCodes LoadIFilter(
        string pwcsPath,
        [MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter,
        ref IFilter ppIUnk);

    [DllImport("ole32.dll")]
    public static extern int CreateStreamOnHGlobal(IntPtr hGlobal, bool fDeleteOnRelease, out IStream ppstm);
}

[ComImport, Guid("89BCB740-6119-101A-BCB7-00DD010655AF")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IFilter
{
    [PreserveSig]
    FilterReturnCodes Init(FilterInit grfFlags, int cAttributes, IntPtr aAttributes, out FilterFlags pdwFlags);

    [PreserveSig]
    FilterReturnCodes GetChunk(out StatChunk pStat);

    [PreserveSig]
    FilterReturnCodes GetText(
        ref int pcwcBuffer,
        [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder awcBuffer);

    [PreserveSig]
    FilterReturnCodes GetValue(ref IntPtr propVal);

    [PreserveSig]
    FilterReturnCodes BindRegion(ref FilterRegion origPos, ref Guid riid, ref object ppunk);
}

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0000010c-0000-0000-C000-000000000046")]
public interface IPersist
{
    void GetClassID(out Guid pClassID);
}

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("00000109-0000-0000-C000-000000000046")]
public interface IPersistStream : IPersist
{
    new void GetClassID(out Guid pClassID);

    [PreserveSig]
    int IsDirty();

    void Load([In] IStream pStm);

    void Save(
        [In] IStream pStm,
        [In, MarshalAs(UnmanagedType.Bool)] bool fClearDirty);

    void GetSizeMax(out long pcbSize);
}

public struct StatChunk
{
    public int idChunk;
    [MarshalAs(UnmanagedType.U4)]
    public ChunkBreaktype breakType;
    [MarshalAs(UnmanagedType.U4)]
    public ChunkState flags;
    public int locale;
    public FullPropSpec attribute;
    public int idChunkSource;
    public int cwcStartSource;
    public int cwcLenSource;
}

public enum ChunkBreaktype
{
    CHUNK_NO_BREAK = 0,
    CHUNK_EOW = 1,
    CHUNK_EOS = 2,
    CHUNK_EOP = 3,
    CHUNK_EOC = 4
}

public enum ChunkState
{
    CHUNK_TEXT = 0x1,
    CHUNK_VALUE = 0x2,
    CHUNK_FILTER_OWNED_VALUE = 0x4
}

[Flags]
public enum FilterFlags
{
    IFILTER_FLAGS_OLE_PROPERTIES = 1
}

[Flags]
public enum FilterInit
{
    IFILTER_INIT_CANON_PARAGRAPHS = 1,
    IFILTER_INIT_HARD_LINE_BREAKS = 2,
    IFILTER_INIT_CANON_HYPHENS = 4,
    IFILTER_INIT_CANON_SPACES = 8,
    IFILTER_INIT_APPLY_INDEX_ATTRIBUTES = 16,
    IFILTER_INIT_APPLY_CRAWL_ATTRIBUTES = 256,
    IFILTER_INIT_APPLY_OTHER_ATTRIBUTES = 32,
    IFILTER_INIT_INDEXING_ONLY = 64,
    IFILTER_INIT_SEARCH_LINKS = 128,
    IFILTER_INIT_FILTER_OWNED_VALUE_OK = 512
}

public struct FilterRegion
{
    public int idChunk;
    public int cwcStart;
    public int cwcExtent;
}

public enum FilterReturnCodes : uint
{
    S_OK = 0,
    E_ACCESSDENIED = 0x80070005,
    E_HANDLE = 0x80070006,
    E_INVALIDARG = 0x80070057,
    E_OUTOFMEMORY = 0x8007000E,
    E_NOTIMPL = 0x80004001,
    E_FAIL = 0x80000008,
    FILTER_E_PASSWORD = 0x8004170B,
    FILTER_E_UNKNOWNFORMAT = 0x8004170C,
    FILTER_E_NO_TEXT = 0x80041705,
    FILTER_E_NO_VALUES = 0x80041706,
    FILTER_E_END_OF_CHUNKS = 0x80041700,
    FILTER_E_NO_MORE_TEXT = 0x80041701,
    FILTER_E_NO_MORE_VALUES = 0x80041702,
    FILTER_E_ACCESS = 0x80041703,
    FILTER_W_MONIKER_CLIPPED = 0x00041704,
    FILTER_E_EMBEDDING_UNAVAILABLE = 0x80041707,
    FILTER_E_LINK_UNAVAILABLE = 0x80041708,
    FILTER_S_LAST_TEXT = 0x00041709,
    FILTER_S_LAST_VALUES = 0x0004170A
}

public struct FullPropSpec
{
    public Guid guidPropSet;
    public PropSpec psProperty;
}

[StructLayout(LayoutKind.Explicit)]
public struct PropSpec
{
    [FieldOffset(0)]
    public int ulKind;     

    [FieldOffset(4)]
    public int propid;

    [FieldOffset(4)]
    public IntPtr lpwstr;
}

Otros consejos

He trabajado en el pasado para proporcionar un IFIlter destinado a proporcionar cualquier acceso de herramienta de búsqueda/indexación al contenido de texto dentro de un archivo DWG de AutoCAD. Puedes leer algo de mi aventura aquí: http://blogs.msdn.com/b/ifilter/archive/2006/12/25/chronicles-of-an-iFilter-development-inception-to-deployment.aspx

El código al que se refiere es antiguo, pero sigue siendo válido. Sin embargo, ahora hay más interfaces en uso junto a GetTextFromFile. Deberá usar el lector de transmisión, leer en ipersiststream en el enlace que mencioné anteriormente. Si entiendo lo que desea hacer, deberá abrir el archivo como flujo de la base de datos y presentar esta transmisión al Indexer o el Ifilter de su elección.

Buena suerte, Marco

Esperaba hacer lo mismo, pero terminé agregando otra columna a la tabla de la base de datos para TextContent. Guardé el contenido binario en un archivo temporal, utilicé la biblioteca de codeProject Epocalisde.ifilter dll para encontrar el texto y lo agregué a la columna TextContent.

Sobre la base de un ejemplo de Mareks, aquí está mi toma, que utiliza una implementación del Istream interfaz en lugar de asignar memoria a través de Marshal.AllocHGlobal Para crear una transmisión de com.

Funciona con el Adobe PDF Ifilter 64 11.0.01 y un montón de formatos como .doc, .docx, .html, .odt, .rtf, la lista continua.

Ejemplo completo:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

namespace TextExtraction
{
    class Program
    {
        static void Main(string[] args)
        {
            var file = new FileInfo(@"C:\Path\To\Some.doc");

            using (var stream = file.OpenRead())
            {
                var filter = Load(stream, file.Extension);
                if (filter != null)
                {
                    var text = GetText(filter);
                    Console.WriteLine(text);
                }
            }

            Console.WriteLine("Press your favorite key to exit");
            Console.ReadKey();
        }

        private static IFilter Load(Stream stream, string extension)
        {
            IFilter filter = null;

            if (NativeMethods.LoadIFilter(extension, null, ref filter) == HRESULT.S_OK)
            {
                if (filter is IPersistStream persistStream)
                {
                    persistStream.Load(new ManagedStream(stream));

                    if (filter.Init(IFILTER_INIT.IFILTER_INIT_APPLY_INDEX_ATTRIBUTES, 0, IntPtr.Zero, out IFILTER_FLAGS filterFlags) == IFilterReturnCodes.S_OK)
                    {
                        return filter;
                    }
                }
            }

            return null;
        }

        private static string GetText(IFilter filter)
        {
            var text = new StringBuilder();

            while (filter.GetChunk(out var chunk) == IFilterReturnCodes.S_OK)
            {
                ReadChunk(filter, chunk, text);
            }

            return text.ToString();
        }

        private static void ReadChunk(IFilter filter, STAT_CHUNK chunk, StringBuilder text)
        {
            var textResult = IFilterReturnCodes.S_OK;
            while (textResult == IFilterReturnCodes.S_OK)
            {
                var bufferSize = 4096U;
                var buffer = new char[bufferSize];
                textResult = filter.GetText(ref bufferSize, buffer);

                if ((textResult == IFilterReturnCodes.S_OK || textResult == IFilterReturnCodes.FILTER_S_LAST_TEXT) && bufferSize > 0)
                {
                    if (chunk.breakType == CHUNK_BREAKTYPE.CHUNK_EOP)
                    {
                        text.Append('\n');
                    }

                    text.Append(buffer, 0, (int) bufferSize);
                }
            }
        }

        [Guid("89BCB740-6119-101A-BCB7-00DD010655AF")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IFilter
        {
            [PreserveSig]
            IFilterReturnCodes Init(IFILTER_INIT grfFlags, int cAttributes, IntPtr aAttributes,
                out IFILTER_FLAGS pdwFlags);

            [PreserveSig]
            IFilterReturnCodes GetChunk(out STAT_CHUNK pStat);

            [PreserveSig]
            IFilterReturnCodes GetText(ref uint pcwcBuffer, [Out, MarshalAs(UnmanagedType.LPArray)]
                char[] awcBuffer);

            [PreserveSig]
            IFilterReturnCodes GetValue(ref IntPtr propVal);

            [PreserveSig]
            IFilterReturnCodes BindRegion(ref FILTERREGION origPos, ref Guid riid, ref object ppunk);
        }

        [Guid("0000010C-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IPersist
        {
            void GetClassID(out Guid pClassID);
        }

        [Guid("00000109-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IPersistStream : IPersist
        {
            new void GetClassID(out Guid pClassID);

            [PreserveSig]
            int IsDirty();

            void Load([In] IStream pStm);

            void Save([In] IStream pStm, [In, MarshalAs(UnmanagedType.Bool)] bool fClearDirty);

            void GetSizeMax(out long pcbSize);
        }

        [Guid("0000000C-0000-0000-C000-000000000046")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        public interface IStream
        {
            [PreserveSig]
            HRESULT Read([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] [Out]
                byte[] pv, int cb, IntPtr pcbRead);

            [PreserveSig]
            HRESULT Write([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]
                byte[] pv, int cb, IntPtr pcbWritten);

            [PreserveSig]
            HRESULT Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);

            [PreserveSig]
            HRESULT SetSize(long libNewSize);

            HRESULT CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten);

            [PreserveSig]
            HRESULT Commit(int grfCommitFlags);

            [PreserveSig]
            HRESULT Revert();

            [PreserveSig]
            HRESULT LockRegion(long libOffset, long cb, int dwLockType);

            [PreserveSig]
            HRESULT UnlockRegion(long libOffset, long cb, int dwLockType);

            [PreserveSig]
            HRESULT Stat(out STATSTG pstatstg, int grfStatFlag);

            [PreserveSig]
            HRESULT Clone(out IStream ppstm);
        }

        public class ManagedStream : IStream
        {
            private readonly Stream _stream;

            public ManagedStream(Stream stream)
            {
                _stream = stream ?? throw new ArgumentNullException(nameof(stream));
            }

            public HRESULT Clone(out IStream ppstm)
            {
                ppstm = null;
                return HRESULT.E_NOTIMPL;
            }

            public HRESULT Commit(int grfCommitFlags)
            {
                return HRESULT.E_NOTIMPL;
            }

            public HRESULT CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten)
            {
                return HRESULT.E_NOTIMPL;
            }

            public HRESULT LockRegion(long libOffset, long cb, int dwLockType)
            {
                return HRESULT.E_NOTIMPL;
            }

            public HRESULT Read(byte[] pv, int cb, IntPtr pcbRead)
            {
                var bytesRead = _stream.Read(pv, 0, cb);
                if (pcbRead != IntPtr.Zero)
                {
                    Marshal.WriteInt32(pcbRead, bytesRead);
                }

                return HRESULT.S_OK;
            }

            public HRESULT Revert()
            {
                return HRESULT.E_NOTIMPL;
            }

            public HRESULT Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition)
            {
                SeekOrigin seekOrigin;

                switch (dwOrigin)
                {
                    case (int) STREAM_SEEK.STREAM_SEEK_SET:
                        seekOrigin = SeekOrigin.Begin;
                        break;
                    case (int) STREAM_SEEK.STREAM_SEEK_CUR:
                        seekOrigin = SeekOrigin.Current;
                        break;
                    case (int) STREAM_SEEK.STREAM_SEEK_END:
                        seekOrigin = SeekOrigin.End;
                        break;
                    default:
                        return HRESULT.E_FAIL;
                }

                var position = _stream.Seek(dlibMove, seekOrigin);

                if (plibNewPosition != IntPtr.Zero)
                {
                    Marshal.WriteInt64(plibNewPosition, position);
                }

                return HRESULT.S_OK;
            }

            public HRESULT SetSize(long libNewSize)
            {
                return HRESULT.E_NOTIMPL;
            }

            public HRESULT Stat(out STATSTG pstatstg, int grfStatFlag)
            {
                pstatstg = new STATSTG
                {
                    type = (int) STGTY.STGTY_STREAM,
                    cbSize = _stream.Length,
                    grfMode = (int) STGM.STGM_READ
                };

                if (_stream.CanRead && _stream.CanWrite)
                {
                    pstatstg.grfMode |= (int) STGM.STGM_READWRITE;
                }
                else if (_stream.CanRead)
                {
                    pstatstg.grfMode |= (int) STGM.STGM_READ;
                }
                else if (_stream.CanWrite)
                {
                    pstatstg.grfMode |= (int) STGM.STGM_WRITE;
                }
                else
                {
                    return HRESULT.E_ACCESSDENIED;
                }

                return HRESULT.S_OK;
            }

            public HRESULT UnlockRegion(long libOffset, long cb, int dwLockType)
            {
                return HRESULT.E_NOTIMPL;
            }

            public HRESULT Write(byte[] pv, int cb, IntPtr pcbWritten)
            {
                return HRESULT.E_NOTIMPL;
            }
        }

        public class NativeMethods
        {
            [DllImport("query.dll", SetLastError = true, CharSet = CharSet.Unicode)]
            public static extern HRESULT LoadIFilter(string pwcsPath, [MarshalAs(UnmanagedType.IUnknown)] object pUnkOuter, ref IFilter ppIUnk);
        }

        public struct FILETIME
        {
            public uint DateTimeLow;
            public uint DateTimeHigh;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct FILTERREGION
        {
            public ulong idChunk;
            public ulong cwcStart;
            public ulong cwcExtent;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct FULLPROPSPEC
        {
            public Guid guidPropSet;
            public PROPSPEC psProperty;
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct PROPSPEC
        {
            [FieldOffset(0)]
            public PROPSPECKIND ulKind;

            [FieldOffset(4)]
            public uint propid;

            [FieldOffset(4)]
            public IntPtr lpwstr;
        }

        public struct STAT_CHUNK
        {
            public int idChunk;

            [MarshalAs(UnmanagedType.U4)]
            public CHUNK_BREAKTYPE breakType;

            [MarshalAs(UnmanagedType.U4)]
            public CHUNKSTATE flags;

            public int locale;

            public FULLPROPSPEC attribute;

            public int idChunkSource;

            public int cwcStartSource;

            public int cwcLenSource;
        }

        public struct STATSTG
        {
            [MarshalAs(UnmanagedType.LPTStr)]
            public string pwcsName;
            public int type;
            public long cbSize;
            public FILETIME mtime;
            public FILETIME ctime;
            public FILETIME atime;
            public int grfMode;
            public int grfLocksSupported;
            public Guid clsid;
            public int grfStateBits;
            public int reserved;
        }

        [Flags]
        public enum IFilterReturnCodes : uint
        {
            S_OK = 0,
            E_ACCESSDENIED = 0x80070005,
            E_HANDLE = 0x80070006,
            E_INVALIDARG = 0x80070057,
            E_OUTOFMEMORY = 0x8007000E,
            E_NOTIMPL = 0x80004001,
            E_FAIL = 0x80000008,

            FILTER_E_PASSWORD = 0x8004170B,
            FILTER_E_UNKNOWNFORMAT = 0x8004170C,
            FILTER_E_NO_TEXT = 0x80041705,
            FILTER_E_NO_VALUES = 0x80041706,
            FILTER_E_END_OF_CHUNKS = 0x80041700,
            FILTER_E_NO_MORE_TEXT = 0x80041701,
            FILTER_E_NO_MORE_VALUES = 0x80041702,
            FILTER_E_ACCESS = 0x80041703,
            FILTER_W_MONIKER_CLIPPED = 0x00041704,
            FILTER_E_EMBEDDING_UNAVAILABLE = 0x80041707,
            FILTER_E_LINK_UNAVAILABLE = 0x80041708,
            FILTER_S_LAST_TEXT = 0x00041709,
            FILTER_S_LAST_VALUES = 0x0004170A
        }

        [Flags]
        public enum CHUNK_BREAKTYPE : uint
        {
            CHUNK_NO_BREAK = 0,
            CHUNK_EOW = 1,
            CHUNK_EOS = 2,
            CHUNK_EOP = 3,
            CHUNK_EOC = 4
        }

        [Flags]
        public enum CHUNKSTATE : uint
        {
            CHUNK_TEXT = 0x1,
            CHUNK_VALUE = 0x2,
            CHUNK_FILTER_OWNED_VALUE = 0x4
        }

        [Flags]
        public enum HRESULT : uint
        {
            S_OK = 0x00000000,
            E_NOTIMPL = 0x80004001,
            E_NOINTERFACE = 0x80004002,
            E_POINTER = 0x80004003,
            E_ABORT = 0x80004004,
            E_FAIL = 0x80004005,
            E_UNEXPECTED = 0x8000FFFF,
            E_ACCESSDENIED = 0x80070005,
            E_HANDLE = 0x80070006,
            E_OUTOFMEMORY = 0x8007000E,
            E_INVALIDARG = 0x80070057
        }

        [Flags]
        public enum IFILTER_FLAGS
        {
            IFILTER_FLAGS_OLE_PROPERTIES = 1
        }

        [Flags]
        public enum IFILTER_INIT
        {
            IFILTER_INIT_CANON_PARAGRAPHS = 1,
            IFILTER_INIT_HARD_LINE_BREAKS = 2,
            IFILTER_INIT_CANON_HYPHENS = 4,
            IFILTER_INIT_CANON_SPACES = 8,
            IFILTER_INIT_APPLY_INDEX_ATTRIBUTES = 16,
            IFILTER_INIT_APPLY_CRAWL_ATTRIBUTES = 256,
            IFILTER_INIT_APPLY_OTHER_ATTRIBUTES = 32,
            IFILTER_INIT_INDEXING_ONLY = 64,
            IFILTER_INIT_SEARCH_LINKS = 128,
            IFILTER_INIT_FILTER_OWNED_VALUE_OK = 512,
            IFILTER_INIT_FILTER_AGGRESSIVE_BREAK = 1024,
            IFILTER_INIT_DISABLED_EMBEDDED = 2048,
            IFILTER_INIT_EMIT_FORMATTING = 4096
        }

        [Flags]
        public enum PROPSPECKIND : ulong
        {
            PRSPEC_LPWSTR = 0,
            PRSPEC_PROPID = 1
        }

        [Flags]
        public enum STGM : ulong
        {
            STGM_READ = 0x00000000L,
            STGM_WRITE = 0x00000001L,
            STGM_READWRITE = 0x00000002L,
            STGM_SHARE_DENY_NONE = 0x00000040L,
            STGM_SHARE_DENY_READ = 0x00000030L,
            STGM_SHARE_DENY_WRITE = 0x00000020L,
            STGM_SHARE_EXCLUSIVE = 0x00000010L,
            STGM_PRIORITY = 0x00040000L,
            STGM_CREATE = 0x00001000L,
            STGM_CONVERT = 0x00020000L,
            STGM_FAILIFTHERE = 0x00000000L,
            STGM_DIRECT = 0x00000000L,
            STGM_TRANSACTED = 0x00010000L,
            STGM_NOSCRATCH = 0x00100000L,
            STGM_NOSNAPSHOT = 0x00200000L,
            STGM_SIMPLE = 0x08000000L,
            STGM_DIRECT_SWMR = 0x00400000L,
            STGM_DELETEONRELEASE = 0x04000000L
        }

        [Flags]
        public enum STGTY : int
        {
            STGTY_STORAGE = 1,
            STGTY_STREAM = 2,
            STGTY_LOCKBYTES = 3,
            STGTY_PROPERTY = 4
        }

        [Flags]
        public enum STREAM_SEEK : int
        {
            STREAM_SEEK_SET = 0,
            STREAM_SEEK_CUR = 1,
            STREAM_SEEK_END = 2
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top