StgOpenStorage

C# Signature:

[DllImport("ole32.dll")]
static extern int StgOpenStorageEx([MarshalAs(UnmanagedType.LPWStr)] string
   pwcsName, uint grfMode, uint stgfmt, uint grfAttrs, ref STGOPTIONS
   pStgOptions, IntPtr reserved2, [In] ref Guid riid,
   [MarshalAs(UnmanagedType.IUnknown)] out object ppObjectOpen);

Alternative Managed API:

public static void ReadOSSFile(string fileName, XmlWriter writer)
    {
        int checkResult = StgIsStorageFile(fileName);
        Preconditions.RequireArgument(checkResult == 0, 
            "The specified file is not an OLE Structured Storage file.");

        StorageInfo storageRoot = GetStorageRoot(fileName);
        try
        {
            WriteStorage(storageRoot, fileName, writer);
        }
        finally
        {
            CloseStorageRoot(storageRoot);
        }
    }

    private static StorageInfo GetStorageRoot(string fileName)
    {
        StorageInfo storageRoot = (StorageInfo)InvokeStorageRootMethod(null, 
            "Open", fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
        if (storageRoot == null)
        {
            Utilities.ThrowInvalidStateFmt("Unable to open \"{0}\" as a structured storage file.", fileName);
        }
        return storageRoot;
    }

    private static void CloseStorageRoot(StorageInfo storageRoot)
    {
        InvokeStorageRootMethod(storageRoot, "Close");
    }

    private static object InvokeStorageRootMethod(StorageInfo storageRoot, string methodName, params object[] methodArgs)
    {
        //We need the StorageRoot class to directly open an OSS file.  Unfortunately, it's internal.
        //So we'll have to use Reflection to access it.  This code was inspired by:
        //http://henbo.spaces.live.com/blog/cns!2E073207A544E12!200.entry
        //Note: In early WinFX CTPs the StorageRoot class was public because it was documented
        //here: http://msdn2.microsoft.com/en-us/library/aa480157.aspx

        Type storageRootType = typeof(StorageInfo).Assembly.GetType("System.IO.Packaging.StorageRoot", true, false);
        object result = storageRootType.InvokeMember(methodName,
            BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
            null, storageRoot, methodArgs);
        return result;
    }

    private static void WriteStorage(StorageInfo storageInfo, string storageName, XmlWriter writer)
    {
        writer.WriteStartElement("storage");
        writer.WriteAttributeString("name", storageName);

        StorageInfo[] subStorages = storageInfo.GetSubStorages();
        foreach (StorageInfo subStorage in subStorages)
        {
            WriteStorage(subStorage, subStorage.Name, writer);
        }

        StreamInfo[] streams = storageInfo.GetStreams();
        foreach (StreamInfo stream in streams)
        {
            string hexData = ConvertStreamBytesToHex(stream);
            writer.WriteStartElement("stream");
            writer.WriteAttributeString("name", stream.Name);
            writer.WriteAttributeString("data", hexData);
            writer.WriteEndElement();
        }

        writer.WriteEndElement();
    }

    private static string ConvertStreamBytesToHex(StreamInfo streamInfo)
    {
        using (Stream streamReader = streamInfo.GetStream(FileMode.Open, FileAccess.Read))
        {
            StringBuilder sb = new StringBuilder();
            int currentRead;
            while ((currentRead = streamReader.ReadByte()) >= 0)
            {
                byte currentByte = (byte)currentRead;
                sb.AppendFormat("{0:X2}", currentByte);
            }
            return sb.ToString();
        }
    }

    [DllImport("ole32.dll", CharSet = CharSet.Unicode)]
    private static extern int StgIsStorageFile(string fileName);

Última actualización