Problem using StgOpenStorageEx

StewartBW 1,480 Reputation points
2025-05-06T20:43:32.44+00:00

Hey experts,

I'm going to update the guid of an Outlook msg file from "00020d0b-0000-0000-c000-000000000046" to "0006f046-0000-0000-c000-000000000046" and save the file with a new file name/extension.

All my tries with StgOpenStorageEx failed, anyone can correct me, no idea what to do next :(

    Const STGFMT_STORAGE As UInteger = 0 ' OLE Storage Format
    Const STGM_READ As Integer = &H0
    Const STGM_WRITE As Integer = &H1
    Const STGM_SHARE_EXCLUSIVE As Integer = &H10
    Const STGM_CREATE As Integer = &H1000
    Private ReadOnly CLSID_OLEMSG As Guid = New Guid("0006f046-0000-0000-c000-000000000046")
    Private ReadOnly CLSID_OLEOFT As Guid = New Guid("0006f046-0000-0000-c000-000000000046") ' Adjust accordingly
    <DllImport("ole32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)>
    Public Function StgOpenStorageEx(ByVal pwcsName As String, ByVal grfMode As UInteger, ByVal pstgfmt As UInteger, ByVal reserved As UInteger, ByVal pStgOptions As IntPtr, ByVal riid As Guid, ByRef ppObject As IntPtr) As UInteger
    End Function
    <DllImport("ole32.dll", SetLastError:=True)>
    Public Function StgCreateStorageEx(ByVal pwcsName As String, ByVal grfMode As UInteger, ByVal pstgfmt As UInteger, ByVal reserved As UInteger, ByVal pStgOptions As IntPtr, ByVal riid As Guid, ByRef ppObject As IntPtr) As UInteger
    End Function
    Public Sub SetCLSID(ByVal InputFile As String, ByVal OutputFile As String)
        If Not File.Exists(InputFile) Then
            MsgBox("File not found: " & InputFile)
            Exit Sub
        End If
        Dim pStg As IntPtr = IntPtr.Zero
        Dim pOftStg As IntPtr = IntPtr.Zero
        Try
            ' Open the MSG file
            Dim hr As UInteger = StgOpenStorageEx(InputFile, STGM_READ Or STGM_SHARE_EXCLUSIVE, STGFMT_STORAGE, 0, IntPtr.Zero, CLSID_OLEMSG, pStg)
            If hr <> 0 Then
                Throw New ExternalException("Failed to open storage", CInt(hr))
            End If
            ' Create a new OFT file
            hr = StgCreateStorageEx(OutputFile, &H1 Or &H1000, 0, 0, IntPtr.Zero, CLSID_OLEOFT, pOftStg)
            If hr <> 0 Then
                Throw New ExternalException("Failed to create OFT storage", CInt(hr))
            End If
        Catch ex As Exception
            MsgBox("An error occurred: " & ex.Message)
        Finally
            ' Cleanup if necessary
            If pStg <> IntPtr.Zero Then
                Marshal.Release(pStg)
            End If
            If pOftStg <> IntPtr.Zero Then
                Marshal.Release(pOftStg)
            End If
        End Try
    End Sub

Thanks all :)

VB
VB
An object-oriented programming language developed by Microsoft that is implemented on the .NET Framework. Previously known as Visual Basic .NET.
2,845 questions
{count} votes

Accepted answer
  1. RLWA32 48,896 Reputation points
    2025-05-07T00:51:55.61+00:00

    I used the IStorage declaration from pinvoke.net and made some minor convenience changes for the methods used. I did not attempt to verify the accuracy of the entire declaration.

    In the interest of safety the following code copies an input file and changes the output file's clsid. I have no doubt that in-place editing is available but I'll leave that modification to you.

    Imports System.Runtime.InteropServices
    Imports System.Runtime.InteropServices.ComTypes
    Module Module1
        Const STGFMT_STORAGE As UInteger = 0 ' OLE Storage Format
        Const STGM_READ As Integer = &H0
        Const STGM_WRITE As Integer = &H1
        Const STGM_SHARE_EXCLUSIVE As Integer = &H10
        Const STGM_CREATE As Integer = &H1000
        Private ReadOnly IID_IStorage As Guid = New Guid("0000000b-0000-0000-C000-000000000046")
        Private ReadOnly CLSID_OLEOFT As Guid = New Guid("0006f046-0000-0000-c000-000000000046") ' Adjust accordingly
        <DllImport("ole32.dll", CharSet:=CharSet.Unicode)>
        Public Function StgOpenStorageEx(ByVal pwcsName As String,
                                         ByVal grfMode As UInteger,
                                         ByVal stgfmt As UInteger,
                                         ByVal grfattrs As UInteger,
                                         ByVal pStgOptions As IntPtr,
                                         ByVal pSecurity As IntPtr,
                                         ByRef riid As Guid,
                                         ByRef ppObject As IStorage) As UInteger
        End Function
        <DllImport("ole32.dll", CharSet:=CharSet.Unicode)>
        Public Function StgCreateStorageEx(ByVal pwcsName As String,
                                           ByVal grfMode As UInteger,
                                           ByVal stgfmt As UInteger,
                                           ByVal grfattrs As UInteger,
                                           ByVal pStgOptions As IntPtr,
                                           ByVal pSecurity As IntPtr,
                                           ByRef riid As Guid,
                                           ByRef ppObject As IStorage) As UInteger
        End Function
    
        <ComImportAttribute(),
        Guid("0000000b-0000-0000-c000-000000000046"),
        InterfaceType(ComInterfaceType.InterfaceIsIUnknown)>
        Interface IStorage
            Sub CreateStream(ByVal pwcsName As String,
                         ByVal grfMode As UInteger,
                         ByVal reserved1 As UInteger,
                         ByVal reserved2 As UInteger,
                         ByRef ppstm As IStream)
    
            Sub OpenStream(ByVal pwcsName As String,
                       ByVal reserved1 As IntPtr,
                       ByVal grfMode As UInteger,
                       ByVal reserved2 As UInteger,
                       ByRef ppstm As IStream)
    
            Sub CreateStorage(ByVal pwcsName As String,
                          ByVal grfMode As UInteger,
                          ByVal reserved1 As UInteger,
                          ByVal reserved2 As UInteger,
                          ByRef ppstg As IStorage)
    
            Sub OpenStorage(ByVal pwcsName As String,
                        ByVal pstgPriority As IStorage,
                        ByVal grfMode As UInteger,
                        ByVal snbExclude As IntPtr,
                        ByVal reserved As UInteger,
                        ByRef ppstg As IStorage)
    
            Sub CopyTo(ByVal ciidExclude As UInteger,
                   ByVal rgiidExclude As IntPtr,
                   ByVal snbExclude As IntPtr,
                   ByVal pstgDest As IStorage)
    
            Sub MoveElementTo(ByVal pwcsName As String,
                          ByVal pstgDest As IStorage,
                          ByVal pwcsNewName As String,
                          ByVal grfFlags As UInteger)
    
            Sub Commit(ByVal grfCommitFlags As UInteger)
    
            Sub Revert()
    
            Sub EnumElements(ByVal reserved1 As UInteger,
                         ByVal reserved2 As IntPtr,
                         ByVal reserved3 As UInteger,
                         ByRef ppenum As IntPtr) ' IEnumSTATSTG
    
            Sub DestroyElement(ByVal pwcsName As String)
    
            Sub RenameElement(ByVal pwcsOldName As String,
                          ByVal pwcsNewName As String)
    
            Sub SetElementTimes(ByVal pwcsName As String,
                            ByVal pctime As ComTypes.FILETIME,
                            ByVal patime As ComTypes.FILETIME,
                            ByVal pmtime As ComTypes.FILETIME)
    
            Sub SetClass(ByRef clsid As Guid)
    
            Sub SetStateBits(ByVal grfStateBits As UInteger,
                         ByVal grfMask As UInteger)
    
            Sub Stat(ByRef pstatstg As ComTypes.STATSTG,
                 ByVal grfStatFlag As UInteger)
        End Interface
    
    
    
        Sub Main()
            Dim pstgIn As IStorage = Nothing
            Dim pstgOut As IStorage = Nothing
    
            Try
                Dim hr = StgOpenStorageEx("Input file", STGM_READ Or STGM_SHARE_EXCLUSIVE, STGFMT_STORAGE, 0, IntPtr.Zero, IntPtr.Zero, IID_IStorage, pstgIn)
                If hr <> 0 Then
                    Throw New ExternalException("StgOpenStorageEx error", hr)
                End If
                ' Create a new OFT file
                hr = StgCreateStorageEx("Output file", STGM_CREATE Or STGM_WRITE Or STGM_SHARE_EXCLUSIVE, STGFMT_STORAGE, 0, IntPtr.Zero, IntPtr.Zero, IID_IStorage, pstgOut)
                If hr <> 0 Then
                    Throw New ExternalException("StgCreateStorageEx error", hr)
                End If
    
                pstgIn.CopyTo(0, IntPtr.Zero, IntPtr.Zero, pstgOut)
                pstgOut.SetClass(CLSID_OLEOFT)
                pstgOut.Commit(0)
            Catch ex As Exception
                MsgBox("An error occurred: " & ex.Message)
            Finally
                ' Cleanup if necessary
                If pstgIn IsNot Nothing Then
                    Marshal.ReleaseComObject(pstgIn)
                End If
                If pstgOut IsNot Nothing Then
                    Marshal.ReleaseComObject(pstgOut)
                End If
            End Try
        End Sub
    End Module
    
    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.