none
Virtual file transfer RRS feed

  • Question

  • Hi all, in my application i try to realise transfering virtual files to windows explorer, for these needs i use i have to implement IStream interface. Here is it's implementation on C#:

    public Class IStreamWraper: System.Runtime.InterropServices.ComTypes.Istream
    {
    
    public Stream InnerStream;
    public string name;
    
    public IStreamWrapper(Stream NetworkStream, string name_ = null)
        {
    
            InnerStream = NetworkStream;
            name = name_;
        }
    
        public void CopyTo(System.Runtime.InteropServices.ComTypes.IStream istr, long i1, IntPtr ptr1, IntPtr ptr2)
        {
            throw new NotImplementedException();
        }
    
        public void Seek(long dlibMove, int dwOrigin, System.IntPtr plibNewPosition)
        {
            Marshal.WriteInt64(plibNewPosition, InnerStream.Seek(dlibMove, (SeekOrigin) dwOrigin));
        }
    
        public void SetSize(long l1)
        {
            throw new NotImplementedException();
        }
    
        public void Commit(int i1)
        {
            throw new NotImplementedException();
        }
    
    
        public void Revert()
        {
            throw new NotImplementedException();
        }
        public void Write(byte[] pv, int cb, System.IntPtr pcbRead)
        {
            InnerStream.Write(pv, 0, cb);
            Marshal.WriteInt64(pcbRead, cb);
            //Marshal.WriteInt32(pcbRead, (Int32)InnerStream.Write(pv, 0, cb));
        }
    
        public void Read(byte[] pv, int cb, System.IntPtr pcbRead)
        {
            Marshal.WriteInt64(pcbRead, (Int64)InnerStream.Read(pv, 0, cb));
        }
    
    
        public void UnlockRegion(long l1, long l2, int i1)
        {
            throw new NotImplementedException();
        }
    
        public void LockRegion(long l1, long l2, int i1)
        {
            throw new NotImplementedException();
        }
    
        public void Clone(out System.Runtime.InteropServices.ComTypes.IStream istream)
        {
            istream = (IStreamWrapper)(new IStreamWrapper(InnerStream));
        }
    
        public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG st, int i)
        {
            st = new System.Runtime.InteropServices.ComTypes.STATSTG();
    
        }
    }


    Then i form dataobject in next way:

    public void SetData(short dataFormat, int index, Stream stream1)
    {
        _dataObjects.Add(
            new DataObject
            {
                FORMATETC = new FORMATETC
                {
                    cfFormat = dataFormat,
                    ptd = IntPtr.Zero,
                    dwAspect = DVASPECT.DVASPECT_CONTENT,
                    lindex = index,
                    tymed = TYMED.TYMED_ISTREAM
                },
                GetData = () =>
                {
                    // Create IStream for data
                    var ptr = IntPtr.Zero;
    
                    //if use CreateStreamOnHGlobal everething works fine 
                    //var iStream = NativeMethods.CreateStreamOnHGlobal(IntPtr.Zero, true);
                    //var contents = Enumerable.Range('a', 26).Select(i => (byte)i).ToArray();
                    //iStream.Write(contents, contents.Length, IntPtr.Zero);
    
    
                    //IStreamWrapper iStream = new IStreamWrapper(stream1);
                    IStream iStream = new IStreamWrapper(stream1);
    
                    ptr = Marshal.GetComInterfaceForObject(iStream, typeof(IStream));
                    Marshal.ReleaseComObject(iStream);
                    return new Tuple<IntPtr, int>(ptr, NativeMethods.S_OK);
                },
            });
    }

    And then i pass this object to WinAPI function

    public static extern void DoDragDrop(System.Runtime.InteropServices.ComTypes.IDataObject dataObject, IDropSource dropSource, int allowedEffects, int[] finalEffect);


    instead of using my own Istram wraper there is abilty to create already implemented Istream with the help of WinAPI function: 

    CreateStreamOnHGlobal 

    And everething works fine but when i use my wraper windows returns error :Bad Parameter

    then It is logicaly to think that problem in my implementation but i don't know where.

    • Moved by Quist Zhang Friday, October 12, 2012 7:15 AM More appropriate in CLR forum (From:Visual Studio Tools for Office)
    Thursday, October 11, 2012 5:12 PM

All replies

  • Hi Nervi,

    Welcome to the MSDN Forum.

    I am trying to involve some other one in this thread, please wait it patiently.

    Our  managed forum is focused on break fix issues that are neither urgent, nor complex. If the issue is urgent to your business, it is recommended that you contact Microsoft Customer Spport Services(CSS) via telephone so that a dedicated Support Professional can assist you in a more efficient manner. Please be advised that contacting phone support will be a charged call. 

    to obtain the phone numbers for specific technology request please take a look at the web site listed below.

    http://support.microsoft.com/default.aspx?scid=fh;EN-US;PHONENUMBERS  

    If you are outside the US please seehttp://support.microsoft.com for regional support phone numbers.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Friday, October 12, 2012 7:46 AM
    Moderator
  • The IStream interface is defined as:

    using System;

    using System.Runtime.InteropServices;

    namespace System.Runtime.InteropServices.ComTypes

    {

        // Summary:

        //     Provides the managed definition of the IStream interface, with ISequentialStream

        //     functionality.

        [Guid("0000000c-0000-0000-C000-000000000046")]

        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

        public interface IStream

        {

            // Summary:

            //     Creates a new stream object with its own seek pointer that references the

            //     same bytes as the original stream.

            //

            // Parameters:

            //   ppstm:

            //     When this method returns, contains the new stream object. This parameter

            //     is passed uninitialized.

            void Clone(out IStream ppstm);

            //

            // Summary:

            //     Ensures that any changes made to a stream object that is open in transacted

            //     mode are reflected in the parent storage.

            //

            // Parameters:

            //   grfCommitFlags:

            //     A value that controls how the changes for the stream object are committed.

            void Commit(int grfCommitFlags);

            //

            // Summary:

            //     Copies a specified number of bytes from the current seek pointer in the stream

            //     to the current seek pointer in another stream.

            //

            // Parameters:

            //   pstm:

            //     A reference to the destination stream.

            //

            //   cb:

            //     The number of bytes to copy from the source stream.

            //

            //   pcbRead:

            //     On successful return, contains the actual number of bytes read from the source.

            //

            //   pcbWritten:

            //     On successful return, contains the actual number of bytes written to the

            //     destination.

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

            //

            // Summary:

            //     Restricts access to a specified range of bytes in the stream.

            //

            // Parameters:

            //   libOffset:

            //     The byte offset for the beginning of the range.

            //

            //   cb:

            //     The length of the range, in bytes, to restrict.

            //

            //   dwLockType:

            //     The requested restrictions on accessing the range.

            void LockRegion(long libOffset, long cb, int dwLockType);

            //

            // Summary:

            //     Reads a specified number of bytes from the stream object into memory starting

            //     at the current seek pointer.

            //

            // Parameters:

            //   pv:

            //     When this method returns, contains the data read from the stream. This parameter

            //     is passed uninitialized.

            //

            //   cb:

            //     The number of bytes to read from the stream object.

            //

            //   pcbRead:

            //     A pointer to a ULONG variable that receives the actual number of bytes read

            //     from the stream object.

            void Read(byte[] pv, int cb, IntPtr pcbRead);

            //

            // Summary:

            //     Discards all changes that have been made to a transacted stream since the

            //     last System.Runtime.InteropServices.ComTypes.IStream.Commit(System.Int32)

            //     call.

            void Revert();

            //

            // Summary:

            //     Changes the seek pointer to a new location relative to the beginning of the

            //     stream, to the end of the stream, or to the current seek pointer.

            //

            // Parameters:

            //   dlibMove:

            //     The displacement to add to dwOrigin.

            //

            //   dwOrigin:

            //     The origin of the seek. The origin can be the beginning of the file, the

            //     current seek pointer, or the end of the file.

            //

            //   plibNew"font-family:Consolas;font-size:9.5pt;">        //     On successful return, contains the offset of the seek pointer from the beginning

            //     of the stream.

            void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition);

            //

            // Summary:

            //     Changes the size of the stream object.

            //

            // Parameters:

            //   libNewSize:

            //     The new size of the stream as a number of bytes.

            void SetSize(long libNewSize);

            //

            // Summary:

            //     Retrieves the System.Runtime.InteropServices.STATSTG structure for this stream.

            //

            // Parameters:

            //   pstatstg:

            //     When this method returns, contains a STATSTG structure that describes this

            //     stream object. This parameter is passed uninitialized.

            //

            //   grfStatFlag:

            //     Members in the STATSTG structure that this method does not return, thus saving

            //     some memory allocation operations.

            void Stat(out STATSTG pstatstg, int grfStatFlag);

            //

            // Summary:

            //     Removes the access restriction on a range of bytes previously restricted

            //     with the System.Runtime.InteropServices.ComTypes.IStream.LockRegion(System.Int64,System.Int64,System.Int32)

            //     method.

            //

            // Parameters:

            //   libOffset:

            //     The byte offset for the beginning of the range.

            //

            //   cb:

            //     The length, in bytes, of the range to restrict.

            //

            //   dwLockType:

            //     The access restrictions previously placed on the range.

            void UnlockRegion(long libOffset, long cb, int dwLockType);

            //

            // Summary:

            //     Writes a specified number of bytes into the stream object starting at the

            //     current seek pointer.

            //

            // Parameters:

            //   pv:

            //     The buffer to write this stream to.

            //

            //   cb:

            //     The number of bytes to write to the stream.

            //

            //   pcbWritten:

            //     On successful return, contains the actual number of bytes written to the

            //     stream object. If the caller sets this pointer to System.IntPtr.Zero, this

            //     method does not provide the actual number of bytes written.

            void Write(byte[] pv, int cb, IntPtr pcbWritten);

        }

    }

    The implementation of  IStreamWraper that derives from IStream appears to be correct as because I do not get any errors creating an IStreamWraper object and passing in say a file stream object.

    Example (this works fine for me):

            public static Tuple<IntPtr, int> SetData(short dataFormat, int index, Stream stream1)

            {

                var ptr = IntPtr.Zero;

                TestIStream.IStreamWraper iStream = new TestIStream.IStreamWraper(stream1);

                ptr = Marshal.GetComInterfaceForObject(iStream, typeof(IStream));

                Marshal.ReleaseComObject(iStream);

                return new Tuple<IntPtr, int>(ptr, 0);

            }

    We might need to get a building repro code from the customer to see as to what is failing with "Bad Parameter".

    Friday, November 16, 2012 11:45 PM
  • Hello Nerviwki,

    Do you require any further assistance on your IStream interface issue?

    If you still get errors with your specific implementation of IStream interface please send me a building repro code that shows the "Bad Parameter" error.

    Thank you.

    Shamik

    Monday, November 26, 2012 8:35 PM
  • Hi Shamik Mi,

    My problem is similar to this blog. I am writing a bytes of code from P.C to Mobile device using WPF and c#. While writing file i am facing the below exception at targetStream.Commit(0). I am attaching my code snippet below. Any help will be Appreciable!!

    Exception= Error HRESULT E_FAIL has been returned from a call to a COM component

    StackTrace=   at System.Runtime.InteropServices.ComTypes.IStream.Commit(Int32 grfCommitFlags)

    public void TransferContentToDevice(string filePath, String strNewFileName, string parentObjectId)
            {
                IPortableDeviceContent content;
                this._device.Content(out content);

                IPortableDeviceValues values =
                    GetRequiredPropertiesForContentType(filePath, strNewFileName, parentObjectId);

                PortableDeviceApiLib.IStream tempStream = null;
                uint optimalTransferSizeBytes = 1;
                content.CreateObjectWithPropertiesAndData(
                    values,
                    out tempStream,
                    ref optimalTransferSizeBytes,
                    null);

                System.Runtime.InteropServices.ComTypes.IStream targetStream =
                    (System.Runtime.InteropServices.ComTypes.IStream)tempStream;
                int totalWritten = 0;
                int writeCount = 0;
                var buffer = new byte[optimalTransferSizeBytes];
                int cbWritten = 0;
                IntPtr pcbWritten;
                unsafe
                {
                    pcbWritten = new IntPtr(&cbWritten);
                }
                int bytesRead = 0;
                var sourceStream =
                            new FileStream(filePath, FileMode.Open, FileAccess.Read);

                while (true)
                {
                    try
                    {
                        bytesRead = sourceStream.Read(buffer, 0, (int)optimalTransferSizeBytes);
                        if (bytesRead < 1)
                        {
                            break;
                        }
                    }
                    catch (Exception exe)
                    {
                        throw exe;
                    }
                    int written = 00;
                    int errorCount = 0;
                    while (written < bytesRead)
                    {
                        if (tempStream == null)
                        {
                            optimalTransferSizeBytes = 1;
                            content.CreateObjectWithPropertiesAndData(
                                        values,
                                        out tempStream,
                                        ref optimalTransferSizeBytes,
                                        null);

                            targetStream = (System.Runtime.InteropServices.ComTypes.IStream)tempStream;
                        }
                        try
                        {

                            //targetStream.Write(buffer, (int)optimalTransferSizeBytes, pcbWritten);                            
                            if (bytesRead < (int)optimalTransferSizeBytes)
                            {
                                targetStream.Write(buffer, bytesRead, pcbWritten);
                            }
                            else
                            {
                                targetStream.Write(buffer, (int)optimalTransferSizeBytes, pcbWritten);
                            }
                            writeCount++;
                            totalWritten = cbWritten + totalWritten;
                            written = written + cbWritten;
                          
                        }
                        catch (COMException comException)
                        {
                            _logger.Error("Transfer content COMException= {0}, totalwritten={1}, writecount={2} StackTrace={3} ", comException.Message, totalWritten, writeCount, comException.StackTrace);
                            if (tempStream != null)
                                Marshal.ReleaseComObject(tempStream);
                            tempStream = null;
                            targetStream = null;
                            if ((uint)comException.ErrorCode == PortableDeviceErrorCodes.ERROR_BUSY)
                            {
                                Thread.Sleep(500);
                                continue;
                                //TransferContentToDevice(filePath, strNewFileName, parentObjectId);
                            }
                            errorCount++;
                            if (errorCount >  3)
                                throw comException;
                            Thread.Sleep(10000);
                        }
                }
                if (targetStream != null)
                    Thread.Sleep(500);
                    targetStream.Commit(0);
                if (tempStream != null)
                    Marshal.ReleaseComObject(tempStream);
            }

     

    Monday, April 27, 2015 2:57 PM