示例#1
0
        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);
                }
            }
        }
示例#3
0
        /// <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);
            }
        }
示例#5
0
        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);
        }