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); } } }
/// <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 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); } }
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); }