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