none
Does IStorage :: OpenStream work in VB?

    Question

  •  

    I have a VB definition for OpenStream copied from the web as follows

        Sub OpenStream(ByVal pwcsName As String,
                       ByVal reserved1 As IntPtr,
                       ByVal grfMode As UInteger,
                       ByVal reserved2 As UInteger,
                       ByRef ppstm As Istream)
    
           

    and my code contains

    Dim MyIstream as IStream 
    
    [Is].OpenStream(pwcsName, IntPtr.Zero, CUInt(STGM.READWRITE Or STGM.SHARE_EXCLUSIVE), 0, MyIStream)

    Running the code produces a run-time error  "Object reference not set to an instance of an object.", highlighting the final term MyIstream.

    Now I wonder whether my definition of OpenStream is correct. 

    The definition for  IStorage :: OpenStream only shows the C++ definition as follows

    HRESULT OpenStream(
      [in]  const WCHAR   *pwcsName,
      [in]        void    *reserved1,
      [in]        DWORD   grfMode,
      [in]        DWORD   reserved2,
      [out]       IStream **ppstm
    );

    From my C++ ignorant viewpoint I cannot see that the VB 

    ByRef ppstm As Istream

     is the same as the C++

      [out]       IStream **ppstm

    So my question is : If I can code an OpenStream in VB, how do I go about it?

    Yours hopefully


         




    • Edited by obsolent Friday, April 28, 2017 5:01 PM
    Friday, April 28, 2017 5:00 PM

Answers

  • Have you checked if [Is] is not Nothing?

    Also make sure that the VB definition of IStorage includes CreateStream before OpenStream, since the order and position of members is important.

    • Edited by Viorel_MVP Friday, April 28, 2017 7:42 PM
    • Marked as answer by obsolent Sunday, May 07, 2017 11:17 AM
    Friday, April 28, 2017 7:34 PM

All replies

  • No it makes no sense to use words from different languages in sentences.

    Most Chinese persons understand when you write:

     我在哪裡可以買到 a Big Mac. But you without Google translate probably not. 

    With program languages it is even more difficult. It does not use Google Translate automatically (how I made this because I'm not able to write Chinese)

    Therefore tell what you want to do, it seams easy in VB because it is about streaming. 


    Success
    Cor


    Friday, April 28, 2017 5:21 PM
  • Have you checked if [Is] is not Nothing?

    Also make sure that the VB definition of IStorage includes CreateStream before OpenStream, since the order and position of members is important.

    • Edited by Viorel_MVP Friday, April 28, 2017 7:42 PM
    • Marked as answer by obsolent Sunday, May 07, 2017 11:17 AM
    Friday, April 28, 2017 7:34 PM
  • Yes,  it works (tested on Windows 10, VS 2015, with a .doc file)

    copy-paste of declarations :

     <InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("0c733a30-2a1c-11ce-ade5-00aa0044773d")>
        Public Interface ISequentialStream
            Function Read(pv As IntPtr, cb As UInteger, ByRef pcbRead As UInteger) As Integer
            Function Write(pv As IntPtr, cb As UInteger, ByRef pcbWritten As UInteger) As Integer
        End Interface
        
           <ComImport>
        <Guid("0000000c-0000-0000-C000-000000000046")>
        <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Public Interface IStream
            Inherits ISequentialStream
            Function Seek(dlibMove As ULong, dwOrigin As UInteger, ByRef plibNewPosition As ULong) As Integer
            Function SetSize(libNewSize As ULong) As Integer
            Function CopyTo(<[In]> pstm As IStream, cb As ULong, ByRef pcbRead As ULong, ByRef pcbWritten As ULong) As Integer
            Function Commit(grfCommitFlags As UInteger) As Integer
            Function Revert() As Integer
            Function LockRegion(libOffset As ULong, cb As ULong, dwLockType As UInteger) As Integer
            Function UnlockRegion(libOffset As ULong, cb As ULong, dwLockType As UInteger) As Integer
            Function Stat(ByRef pstatstg As System.Runtime.InteropServices.ComTypes.STATSTG, grfStatFlag As UInteger) As Integer
            Function Clone(ByRef ppstm As IStream) As Integer
        End Interface
    
        <ComImport>
        <Guid("0000000d-0000-0000-C000-000000000046")>
        <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Public Interface IEnumSTATSTG
            <PreserveSig>
            Function [Next](celt As UInteger, <MarshalAs(UnmanagedType.LPArray), Out> rgelt As System.Runtime.InteropServices.ComTypes.STATSTG(), ByRef pceltFetched As UInteger) As UInteger
            Sub Skip(celt As UInteger)
            Sub Reset()
            Function Clone() As <MarshalAs(UnmanagedType.[Interface])> IEnumSTATSTG
        End Interface
    
        <ComImport>
        <Guid("0000000b-0000-0000-C000-000000000046")>
        <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Public Interface IStorage
            Function CreateStream(pwcsName As String, grfMode As UInteger, reserved1 As UInteger, reserved2 As UInteger, ByRef ppstm As IStream) As Integer
            Function OpenStream(pwcsName As String, reserved1 As IntPtr, grfMode As UInteger, reserved2 As UInteger, ByRef ppstm As IStream) As Integer
            Function CreateStorage(pwcsName As String, grfMode As UInteger, reserved1 As UInteger, reserved2 As UInteger, ByRef ppstg As IStorage) As Integer
            Function OpenStorage(pwcsName As String, pstgPriority As IStorage, grfMode As UInteger, snbExclude As IntPtr, reserved As UInteger, ByRef ppstg As IStorage) As Integer
            Function CopyTo(ciidExclude As UInteger, rgiidExclude As Guid, snbExclude As IntPtr, pstgDest As IStorage) As Integer
            Function MoveElementTo(pwcsName As String, pstgDest As IStorage, pwcsNewName As String, grfFlags As UInteger) As Integer
            Function Commit(grfCommitFlags As UInteger) As Integer
            Function Revert() As Integer
            Function EnumElements(reserved1 As UInteger, reserved2 As IntPtr, reserved3 As UInteger, ByRef ppenum As IEnumSTATSTG) As Integer
            Function DestroyElement(pwcsName As String) As Integer
            Function RenameElement(pwcsOldName As String, pwcsNewName As String) As Integer
            Function SetElementTimes(pwcsName As String, pctime As System.Runtime.InteropServices.ComTypes.FILETIME, patime As System.Runtime.InteropServices.ComTypes.FILETIME, pmtime As System.Runtime.InteropServices.ComTypes.FILETIME) As Integer
            Function SetClass(clsid As Guid) As Integer
            Function SetStateBits(grfStateBits As UInteger, grfMask As UInteger) As Integer
            Function Stat(ByRef pstatstg As System.Runtime.InteropServices.ComTypes.STATSTG, grfStatFlag As UInteger) As Integer
        End Interface

    • Edited by Castorix31 Friday, April 28, 2017 7:46 PM
    Friday, April 28, 2017 7:39 PM
  • Thank you very much - but I still get the same error (under VS2015 and W10).

    I would be most grateful if you could also provide the code equivalent to mine where you successfully opened the IStream for your .Doc file 

    Yours obsolent


    • Edited by obsolent Wednesday, May 03, 2017 2:38 PM
    Wednesday, May 03, 2017 2:37 PM
  • Dear Cor

    Thank you, but I am afraid your reply has become quite incomprehensible - probably as a result of being translated into English.

    Your obsolent

    Wednesday, May 03, 2017 2:41 PM
  • Dear Cor

    Thank you, but I am afraid your reply has become quite incomprehensible - probably as a result of being translated into English.

    Your obsolent

    Yea, 

    I tried to tell that if you mix up natural language, it becomes mostly not to understand. That is the same with program languages. Try to tell in your own English what you want to achieve with that OpenStream as Win32 code.

    The chance is high that somebody knows a more easy solution in complete VB using the .Net Framework. 


    Success
    Cor

    Wednesday, May 03, 2017 3:23 PM
  • Thank you very much - but I still get the same error (under VS2015 and W10).

    I would be most grateful if you could also provide the code equivalent to mine where you successfully opened the IStream for your .Doc file 

    Yours obsolent


    The test I did with a .doc file =>

    Dim pStorage As IStorage
    Dim hr As Integer
    
    Dim MyString As String = "C:\test.doc"
    hr = StgOpenStorage(MyString, IntPtr.Zero, STGM_READ Or STGM_SHARE_EXCLUSIVE, IntPtr.Zero, 0, pStorage)
    If (hr = 0) Then
        Dim pStream As IStream
        hr = pStorage.OpenStream("WordDocument", IntPtr.Zero, STGM_READ Or STGM_SHARE_EXCLUSIVE, 0, pStream)
        If (hr = 0) Then
            ' Code...
        End If
    End If

    Declaration of StgOpenStorage() =>
    <DllImportAttribute("ole32.dll")> <PreserveSigAttribute()>
        Public Shared Function StgOpenStorage(<InAttribute(), MarshalAs(UnmanagedType.LPWStr)> ByVal pwcsName As String, ByVal pstgPriority As IntPtr, ByVal grfMode As Int32, ByVal snbExclude As IntPtr, ByVal reserved As UInteger, ByRef ppstgOpen As IStorage) As Integer
        End Function


    Wednesday, May 03, 2017 4:51 PM
  • Have you looked at OpenMCDF, a C# project for the OLE Structured Storage (Compound Document) API? I would suspect that you can use it as is, but it could probably be converted to VB.NET as well:

    https://sourceforge.net/projects/openmcdf/


    Paul ~~~~ Microsoft MVP (Visual Basic)

    Wednesday, May 03, 2017 5:02 PM
  • Aaargh! I am an idiot!

    I was sure I did check {Is] for zero (and ignored your suggestion as a result) BUT I DID NOT. Sorry and thank you

    Sunday, May 07, 2017 11:17 AM