/// <summary> /// Opens an OLE storage file. /// </summary> /// <param name="path">Path to a storage file.</param> /// <returns>An instance of the <see cref="Storage"/> class.</returns> /// <exception cref="FileNotFoundException">The file path does not exist.</exception> /// <exception cref="InvalidDataException">The file is not an OLE storage file..</exception> /// <exception cref="Win32Exception">Windows errors returned by OLE storage.</exception> internal static Storage OpenStorage(string path) { // Make sure the file exists. if (!File.Exists(path)) { throw new FileNotFoundException(path); } // Try to open the file as an OLE storage file. NativeMethods.IStorage stg = null; Guid iid = NativeMethods.IID_IStorage; int ret = NativeMethods.StgOpenStorageEx(path, NativeMethods.STGM.STGM_READ | NativeMethods.STGM.STGM_SHARE_DENY_WRITE, NativeMethods.STGFMT.STGFMT_STORAGE, 0, IntPtr.Zero, IntPtr.Zero, ref iid, out stg); if (NativeMethods.STG_E_FILEALREADYEXISTS == ret) { // 0x80030050 is a rather odd error string, so return something more appropriate. var message = string.Format(CultureInfo.CurrentCulture, Properties.Resources.Error_InvalidStorage, path); throw new InvalidDataException(message, new Win32Exception(ret)); } else if (0 != ret) { throw new Win32Exception(ret); } else { return(new Storage(stg)); } }
private Storage(Stream storageStream, FileAccess fileAccess = FileAccess.Read) { NativeMethods.IStorage memoryStorage = null; NativeMethods.ILockBytes memoryStorageBytes = null; try { // Read stream into buffer var buffer = new byte[storageStream.Length]; storageStream.Read(buffer, 0, buffer.Length); // Create a ILockBytes (unmanaged byte array) and write buffer into it NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out memoryStorageBytes); memoryStorageBytes.WriteAt(0, buffer, buffer.Length, null); // Ensure provided stream data is an IStorage if (NativeMethods.StgIsStorageILockBytes(memoryStorageBytes) != 0) { // ReSharper disable once LocalizableElement throw new ArgumentException("The provided stream is not a valid IStorage", "storageStream"); } var accesMode = NativeMethods.STGM.READWRITE; FileAccess = fileAccess; switch (fileAccess) { case FileAccess.Read: accesMode = NativeMethods.STGM.READ; break; case FileAccess.Write: case FileAccess.ReadWrite: accesMode = NativeMethods.STGM.READWRITE; break; } // Open and load IStorage on the ILockBytes NativeMethods.StgOpenStorageOnILockBytes(memoryStorageBytes, null, accesMode | NativeMethods.STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out memoryStorage); // ReSharper disable once DoNotCallOverridableMethodsInConstructor LoadStorage(memoryStorage); } catch { if (memoryStorage != null) { Marshal.ReleaseComObject(memoryStorage); } throw; } finally { if (memoryStorageBytes != null) { Marshal.ReleaseComObject(memoryStorageBytes); } } }
private static void ReadIStorageIntoStream(IntPtr handle, Stream stream) { //To handle a IStorage it needs to be written into a second unmanaged memory mapped storage //and then the data can be read from memory into a managed byte and returned as a MemoryStream NativeMethods.ILockBytes iLockBytes = null; NativeMethods.IStorage iStorageNew = null; IntPtr ptrRead = IntPtr.Zero; try { //Marshal pointer to an IStorage object NativeMethods.IStorage iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(handle); //Create an ILockBytes object on a HGlobal, then create a IStorage object on top of the ILockBytes object iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true); iStorageNew = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0); //Copy the IStorage object into the new IStorage object iStorage.CopyTo(0, null, IntPtr.Zero, iStorageNew); iLockBytes.Flush(); iStorageNew.Commit(0); //Get length of ILockBytes byte array System.Runtime.InteropServices.ComTypes.STATSTG stat = new System.Runtime.InteropServices.ComTypes.STATSTG(); iLockBytes.Stat(out stat, 1); long length = stat.cbSize; //Read bytes into stream ptrRead = Marshal.AllocCoTaskMem(sizeof(int)); byte[] buffer = new byte[4096]; //4 KB buffer int offset = 0; int bytesRead; while (true) { iLockBytes.ReadAt(offset, buffer, buffer.Length, ptrRead); bytesRead = Marshal.ReadInt32(ptrRead); if (bytesRead == 0) { break; } stream.Write(buffer, 0, bytesRead); offset += bytesRead; } } finally { //Release all unmanaged objects Marshal.FreeCoTaskMem(ptrRead); if (iStorageNew != null) { Marshal.ReleaseComObject(iStorageNew); } if (iLockBytes != null) { Marshal.ReleaseComObject(iLockBytes); } } }
internal static extern int StgOpenStorageEx( string pwcsName, [MarshalAs(UnmanagedType.U4)] NativeMethods.STGM grfMode, [MarshalAs(UnmanagedType.U4)] NativeMethods.STGFMT stgfmt, [MarshalAs(UnmanagedType.U4)] int grfAttrs, IntPtr pStgOptions, IntPtr reserved2, ref Guid riid, out NativeMethods.IStorage ppObjectOpen);
/// <summary> /// Processes sub streams and storages on the specified storage. /// </summary> /// <param name="storage"> The storage to get sub streams and storages for. </param> protected virtual void LoadStorage(NativeMethods.IStorage storage) { if (storage == null) { throw new ArgumentNullException("storage", "Storage can not be null"); } _storage = storage; // Ensures memory is released ReferenceManager.AddItem(storage); NativeMethods.IEnumSTATSTG storageElementEnum = null; try { // Enum all elements of the storage storage.EnumElements(0, IntPtr.Zero, 0, out storageElementEnum); // Iterate elements while (true) { // Get 1 element out of the COM enumerator uint elementStatCount; var elementStats = new STATSTG[1]; storageElementEnum.Next(1, elementStats, out elementStatCount); // Break loop if element not retrieved if (elementStatCount != 1) { break; } var elementStat = elementStats[0]; switch (elementStat.type) { case 1: // Element is a storage, add its statistics object to the storage dictionary _subStorageStatistics.Add(elementStat.pwcsName, elementStat); break; case 2: // Element is a stream, add its statistics object to the stream dictionary _streamStatistics.Add(elementStat.pwcsName, elementStat); break; } } } finally { // Free memory if (storageElementEnum != null) { Marshal.ReleaseComObject(storageElementEnum); } } }
/// <summary> /// Disposes this object /// </summary> /// <param name="disposing"></param> protected virtual void Dispose(bool disposing) { if (disposing) { Disposing(); } if (_storage == null) { return; } ReferenceManager.RemoveItem(_storage); Marshal.ReleaseComObject(_storage); _storage = null; }
public NativeMethods.IStorage GetStorage(string Path) { if (STGRefs.ContainsKey(Path.ToUpper())) { return(STGRefs[Path.ToUpper()]); } NativeMethods.IStorage newStorage; string[] chunks = Path.Split('\\'); string name = chunks.Last(); string parentPath = Path.Replace("\\" + name, ""); NativeMethods.IStorage parentStorage = GetStorage(parentPath); parentStorage.OpenStorage(name, null, NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, IntPtr.Zero, 0, out newStorage); STGRefs[Path.ToUpper()] = newStorage; return(newStorage); }
/// <summary> /// Retrieves the data associated with the specified data format at the specified index. /// </summary> /// <param name="format">The format of the data to retrieve. See <see cref="T:System.Windows.Forms.DataFormats"></see> for predefined formats.</param> /// <param name="index">The index of the data to retrieve.</param> /// <returns> /// A <see cref="MemoryStream"/> containing the raw data for the specified data format at the specified index. /// </returns> public MemoryStream GetData(string format, int index) { //create a FORMATETC struct to request the data with FORMATETC formatetc = new FORMATETC(); formatetc.cfFormat = (short)DataFormats.GetDataFormat(format).Id; formatetc.dwAspect = DVASPECT.DVASPECT_CONTENT; formatetc.lindex = index; formatetc.ptd = new IntPtr(0); formatetc.tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL; //create STGMEDIUM to output request results into STGMEDIUM medium = new STGMEDIUM(); //using the Com IDataObject interface get the data using the defined FORMATETC this.comUnderlyingDataObject.GetData(ref formatetc, out medium); //retrieve the data depending on the returned store type switch (medium.tymed) { case TYMED.TYMED_ISTORAGE: //to handle a IStorage it needs to be written into a second unmanaged //memory mapped storage and then the data can be read from memory into //a managed byte and returned as a MemoryStream NativeMethods.IStorage iStorage = null; NativeMethods.IStorage iStorage2 = null; NativeMethods.ILockBytes iLockBytes = null; System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat; try { //marshal the returned pointer to a IStorage object iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(medium.unionmember); Marshal.Release(medium.unionmember); //create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true); iStorage2 = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0); //copy the returned IStorage into the new IStorage iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2); iLockBytes.Flush(); iStorage2.Commit(0); //get the STATSTG of the ILockBytes to determine how many bytes were written to it iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG(); iLockBytes.Stat(out iLockBytesStat, 1); int iLockBytesSize = (int)iLockBytesStat.cbSize; //read the data from the ILockBytes (unmanaged byte array) into a managed byte array byte[] iLockBytesContent = new byte[iLockBytesSize]; iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null); //wrapped the managed byte array into a memory stream and return it return(new MemoryStream(iLockBytesContent)); } finally { //release all unmanaged objects Marshal.ReleaseComObject(iStorage2); Marshal.ReleaseComObject(iLockBytes); Marshal.ReleaseComObject(iStorage); } case TYMED.TYMED_ISTREAM: //to handle a IStream it needs to be read into a managed byte and //returned as a MemoryStream IStream iStream = null; System.Runtime.InteropServices.ComTypes.STATSTG iStreamStat; try { //marshal the returned pointer to a IStream object iStream = (IStream)Marshal.GetObjectForIUnknown(medium.unionmember); Marshal.Release(medium.unionmember); //get the STATSTG of the IStream to determine how many bytes are in it iStreamStat = new System.Runtime.InteropServices.ComTypes.STATSTG(); iStream.Stat(out iStreamStat, 0); int iStreamSize = (int)iStreamStat.cbSize; //read the data from the IStream into a managed byte array byte[] iStreamContent = new byte[iStreamSize]; iStream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero); //wrapped the managed byte array into a memory stream and return it return(new MemoryStream(iStreamContent)); } finally { //release all unmanaged objects Marshal.ReleaseComObject(iStream); } case TYMED.TYMED_HGLOBAL: //to handle a HGlobal the exisitng "GetDataFromHGLOBLAL" method is invoked via //reflection return((MemoryStream)this.getDataFromHGLOBLALMethod.Invoke(this.oleUnderlyingDataObject, new object[] { DataFormats.GetDataFormat((short)formatetc.cfFormat).Name, medium.unionmember })); } return(null); }
private Storage(NativeMethods.IStorage stg) { this.storage = stg; this.classId = Guid.Empty; }
/// <summary> /// Closes the OLE storage file. /// </summary> public void Dispose() { this.storage = null; GC.SuppressFinalize(this); }
/// <summary> /// Closes the OLE storage file. /// </summary> public void Dispose() { this.storage = null; GC.SuppressFinalize(this); }
/// <summary> /// Processes sub streams and storages on the specified storage. /// </summary> /// <param name="storage"> The storage to get sub streams and storages for. </param> protected virtual void LoadStorage(NativeMethods.IStorage storage) { if (storage == null) throw new ArgumentNullException("storage", "Storage can not be null"); _storage = storage; // Ensures memory is released ReferenceManager.AddItem(storage); NativeMethods.IEnumSTATSTG storageElementEnum = null; try { // Enum all elements of the storage storage.EnumElements(0, IntPtr.Zero, 0, out storageElementEnum); // Iterate elements while (true) { // Get 1 element out of the COM enumerator uint elementStatCount; var elementStats = new STATSTG[1]; storageElementEnum.Next(1, elementStats, out elementStatCount); // Break loop if element not retrieved if (elementStatCount != 1) break; var elementStat = elementStats[0]; switch (elementStat.type) { case 1: // Element is a storage, add its statistics object to the storage dictionary _subStorageStatistics.Add(elementStat.pwcsName, elementStat); break; case 2: // Element is a stream, add its statistics object to the stream dictionary _streamStatistics.Add(elementStat.pwcsName, elementStat); break; } } } finally { // Free memory if (storageElementEnum != null) Marshal.ReleaseComObject(storageElementEnum); } }
public Storage(IStorage RootStorage) { this.RootStorage = RootStorage; STGRefs["ROOT"] = this.RootStorage; }
public MemoryStream GetData(string format, int index) { FORMATETC formatetc = new FORMATETC() { cfFormat = (short)DataFormats.GetDataFormat(format).Id, dwAspect = DVASPECT.DVASPECT_CONTENT, lindex = index, ptd = new IntPtr(0), tymed = TYMED.TYMED_ISTREAM | TYMED.TYMED_ISTORAGE | TYMED.TYMED_HGLOBAL }; STGMEDIUM medium = new STGMEDIUM(); this.comUnderlyingDataObject.GetData(ref formatetc, out medium); switch (medium.tymed) { case TYMED.TYMED_ISTORAGE: NativeMethods.IStorage iStorage = null; NativeMethods.IStorage iStorage2 = null; NativeMethods.ILockBytes iLockBytes = null; System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat; try { iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(medium.unionmember); Marshal.Release(medium.unionmember); iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true); iStorage2 = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0); iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2); iLockBytes.Flush(); iStorage2.Commit(0); iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG(); iLockBytes.Stat(out iLockBytesStat, 1); int iLockBytesSize = (int)iLockBytesStat.cbSize; byte[] iLockBytesContent = new byte[iLockBytesSize]; iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null); return(new MemoryStream(iLockBytesContent)); } finally { Marshal.ReleaseComObject(iStorage2); Marshal.ReleaseComObject(iLockBytes); Marshal.ReleaseComObject(iStorage); } case TYMED.TYMED_ISTREAM: IStream iStream = null; System.Runtime.InteropServices.ComTypes.STATSTG iStreamStat; try { iStream = (IStream)Marshal.GetObjectForIUnknown(medium.unionmember); Marshal.Release(medium.unionmember); iStreamStat = new System.Runtime.InteropServices.ComTypes.STATSTG(); iStream.Stat(out iStreamStat, 0); int iStreamSize = (int)iStreamStat.cbSize; byte[] iStreamContent = new byte[iStreamSize]; iStream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero); return(new MemoryStream(iStreamContent)); } finally { Marshal.ReleaseComObject(iStream); } case TYMED.TYMED_HGLOBAL: return((MemoryStream)this.getDataFromHGLOBALMethod.Invoke(this.oleUnderlyingDataObject, new object[] { DataFormats.GetDataFormat((short)formatetc.cfFormat).Name, medium.unionmember })); } return(null); }
private Storage(NativeMethods.IStorage storage) { // ReSharper disable once DoNotCallOverridableMethodsInConstructor LoadStorage(storage); }
/// <summary> /// Disposes this object /// </summary> /// <param name="disposing"></param> protected virtual void Dispose(bool disposing) { if (disposing) Disposing(); if (_storage == null) return; ReferenceManager.RemoveItem(_storage); Marshal.ReleaseComObject(_storage); _storage = null; }
private static void ReadIStorageIntoStream(IntPtr handle, Stream stream) { //To handle a IStorage it needs to be written into a second unmanaged memory mapped storage //and then the data can be read from memory into a managed byte and returned as a MemoryStream NativeMethods.IStorage iStorage = null; NativeMethods.IStorage iStorage2 = null; NativeMethods.ILockBytes iLockBytes = null; System.Runtime.InteropServices.ComTypes.STATSTG iLockBytesStat; try { //Marshal the returned pointer to a IStorage object iStorage = (NativeMethods.IStorage)Marshal.GetObjectForIUnknown(handle); Marshal.Release(handle); //Create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store iLockBytes = NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true); iStorage2 = NativeMethods.StgCreateDocfileOnILockBytes(iLockBytes, 0x00001012, 0); //Copy the returned IStorage into the new IStorage iStorage.CopyTo(0, null, IntPtr.Zero, iStorage2); iLockBytes.Flush(); iStorage2.Commit(0); //Get the STATSTG of the ILockBytes to determine how many bytes were written to it iLockBytesStat = new System.Runtime.InteropServices.ComTypes.STATSTG(); iLockBytes.Stat(out iLockBytesStat, 1); int iLockBytesSize = (int)iLockBytesStat.cbSize; //Read the data from the ILockBytes (unmanaged byte array) into a managed byte array //byte[] iLockBytesContent = new byte[iLockBytesSize]; //iLockBytes.ReadAt(0, iLockBytesContent, iLockBytesContent.Length, null); //Read bytes into stream IntPtr ptrRead = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(int))); byte[] buffer = new byte[1024]; int offset = 0; int bytesRead; while (true) { iLockBytes.ReadAt(offset, buffer, buffer.Length, ptrRead); bytesRead = Marshal.ReadInt32(ptrRead); if (bytesRead == 0) { break; } stream.Write(buffer, 0, bytesRead); offset += bytesRead; } stream.Seek(0, SeekOrigin.Begin); //Wrap the managed byte array into a memory stream and return it //return new MemoryStream(iLockBytesContent); } finally { //release all unmanaged objects Marshal.ReleaseComObject(iStorage2); Marshal.ReleaseComObject(iLockBytes); Marshal.ReleaseComObject(iStorage); } }
/// <summary> /// Processes sub streams and storages on the specified storage. /// </summary> /// <param name="storage">The storage to get sub streams and storages for.</param> protected virtual void LoadStorage(NativeMethods.IStorage storage) { this.storage = storage; //ensures memory is released ReferenceManager.AddItem(this.storage); NativeMethods.IEnumSTATSTG storageElementEnum = null; try { //enum all elements of the storage storage.EnumElements(0, IntPtr.Zero, 0, out storageElementEnum); //iterate elements while (true) { //get 1 element out of the com enumerator uint elementStatCount; ComTypes.STATSTG[] elementStats = new ComTypes.STATSTG[1]; storageElementEnum.Next(1, elementStats, out elementStatCount); //break loop if element not retrieved if (elementStatCount != 1) { break; } ComTypes.STATSTG elementStat = elementStats[0]; switch (elementStat.type) { case 1: //element is a storage. add its statistics object to the storage dictionary subStorageStatistics.Add(elementStat.pwcsName, elementStat); break; case 2: //element is a stream. add its statistics object to the stream dictionary streamStatistics.Add(elementStat.pwcsName, elementStat); break; } } } finally { //free memory if (storageElementEnum != null) { Marshal.ReleaseComObject(storageElementEnum); } } }
private Storage(NativeMethods.IStorage stg) { this.storage = stg; this.classId = Guid.Empty; }