Trouble with Istorage

E

eric.houghland

Hello, I've read quite a bit about implementing this interface in .NET
and believe I have a good start. I am able to use StgIsStorageFile,
StgCreateStorage and StgOpenStorage.

I am now attempting to create a new storage file and then use CopyTo to
copy the contents of a different opened storage file into the new file.
I am getting an error: Invalid pointer error. (Exception from HRESULT:
0x80030009 (STG_E_INVALIDPOINTER)) when calling CopyTo.

Here's my code (VS2005):

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.IO;
using ComTypes = System.Runtime.InteropServices.ComTypes;

namespace SSE
{
class SSProcessor
{
[DllImport("ole32.dll")]
static extern int
StgIsStorageFile([MarshalAs(UnmanagedType.LPWStr)]
string pwcsName);

[DllImport("ole32.dll")]
static extern int
StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)]
string pwcsName, STGM grfMode, uint reserved, out IStorage
ppstgOpen);

[DllImport("ole32.dll")]
static extern int StgOpenStorage(
[MarshalAs(UnmanagedType.LPWStr)] string pwcsName
, IStorage pstgPriority
, STGM grfMode
, IntPtr snbExclude
, uint reserved
, out IStorage ppstgOpen);

private ArrayList fileList = new ArrayList();

public SSProcessor(ArrayList _fileList)
{
SetFileList(_fileList);
}

private void SetFileList(ArrayList _fileList)
{
fileList = _fileList;
}

public void CullFiles()
{
int count = 0;

foreach (FileSystemInfo file in fileList)
{
try
{
StgIsStorageFile(file.FullName);
count++;
}
catch
{
fileList.RemoveAt(count);
//add code to log non-storagefile items
}
}
}

//public enum STGTY : uint
//{
// STGTY_STORAGE = 1,
// STGTY_STREAM = 2,
// STGTY_LOCKBYTES = 3,
// STGTY_PROPERTY = 4
//}

public enum STGM : uint
{
STGM_READ = 0x00000000,
STGM_WRITE = 0x00000001,
STGM_READWRITE = 0x00000002,
STGM_SHARE_DENY_NONE = 0x00000040,
STGM_SHARE_DENY_READ = 0x00000030,
STGM_SHARE_DENY_WRITE = 0x00000020,
STGM_SHARE_EXCLUSIVE = 0x00000010,
STGM_PRIORITY = 0x00040000,
STGM_CREATE = 0x00001000,
STGM_CONVERT = 0x00020000,
STGM_FAILIFTHERE = 0x00000000,
STGM_DIRECT = 0x00000000,
STGM_TRANSACTED = 0x00010000,
STGM_NOSCRATCH = 0x00100000,
STGM_NOSNAPSHOT = 0x00200000,
STGM_SIMPLE = 0x08000000,
STGM_DIRECT_SWMR = 0x00400000,
STGM_DELETEONRELEASE = 0x04000000,
}

//public enum STGFMT : uint
//{
// STGFMT_STORAGE = 0,
// STGFMT_FILE = 3,
// STGFMT_ANY = 4,
// STGFMT_DOCFILE = 5
//}

public enum STGC : uint
{
STGC_DEFAULT = 0,
STGC_OVERWRITE = 1,
STGC_ONLYIFCURRENT = 2,
STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,
STGC_CONSOLIDATE = 8
}

public enum STATFLAG : uint
{
STATFLAG_DEFAULT = 0,
STATFLAG_NONAME = 1
}

//public enum STGMOVE : uint
//{
// STGMOVE_MOVE = 0,
// STGMOVE_COPY = 1
//}

[ComImport]
[Guid("0000000d-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IEnumSTATSTG
{
// The user needs to allocate an STATSTG array whose size
is celt.
[PreserveSig]
uint
Next(
uint celt,
//[MarshalAs(UnmanagedType.LPArray), Out]
ComTypes.STATSTG rgelt,
out uint pceltFetched
);

void Skip(uint celt);

void Reset();

[return: MarshalAs(UnmanagedType.Interface)]
IEnumSTATSTG Clone();
}

[ComImport]
[Guid("0000000b-0000-0000-C000-000000000046")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IStorage
{
void CreateStream(
/* [string][in] */ string pwcsName,
/* [in] */ STGM grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out IStream ppstm);

void OpenStream(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IntPtr reserved1,
/* [in] */ STGM grfMode,
/* [in] */ uint reserved2,
/* [out] */ out IStream ppstm);

void CreateStorage(
/* [string][in] */ string pwcsName,
/* [in] */ STGM grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out IStorage ppstg);

void OpenStorage(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgPriority,
/* [in] */ STGM grfMode,
/* [unique][in] */ IntPtr snbExclude,
/* [in] */ uint reserved,
/* [out] */ out IStorage ppstg);

void CopyTo(
/* [in] */ uint ciidExclude,
/* [size_is][unique][in] */ Guid rgiidExclude,
/* [unique][in] */ IntPtr snbExclude,
/* [unique][in] */ IStorage pstgDest);

void MoveElementTo(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgDest,
/* [string][in] */ string pwcsNewName,
/* [in] */ uint grfFlags);

void Commit(
/* [in] */ STGC grfCommitFlags);

void Revert();

void EnumElements(
/* [in] */ uint reserved1,
/* [size_is][unique][in] */ IntPtr reserved2,
/* [in] */ uint reserved3,
/* [out] */ out IEnumSTATSTG ppenum);

void DestroyElement(
/* [string][in] */ string pwcsName);

void RenameElement(
/* [string][in] */ string pwcsOldName,
/* [string][in] */ string pwcsNewName);

void SetElementTimes(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ ComTypes.FILETIME pctime,
/* [unique][in] */ ComTypes.FILETIME patime,
/* [unique][in] */ ComTypes.FILETIME pmtime);

void SetClass(
/* [in] */ Guid clsid);

void SetStateBits(
/* [in] */ uint grfStateBits,
/* [in] */ uint grfMask);

void Stat(
/* [out] */ out ComTypes.STATSTG pstatstg,
/* [in] */ STATFLAG grfStatFlag);
}

public void ProcessFiles()
{
IStorage stg;
IStorage stg_new;

ComTypes.STATSTG s = new ComTypes.STATSTG();

foreach (FileSystemInfo file in fileList)
{
StgCreateDocfile(file.FullName + "_new",
STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE,
0, out stg_new);
StgOpenStorage(file.FullName, null, STGM.STGM_READWRITE
| STGM.STGM_SHARE_EXCLUSIVE,
IntPtr.Zero, 0, out stg);

stg.Stat(out s, STATFLAG.STATFLAG_DEFAULT);

// stg_new.SetClass(s.clsid);

stg.CopyTo(0, s.clsid, IntPtr.Zero, stg_new);
}
}
}
}
 
A

airs

Pretty much I'm just wondering if this is the correct way to use
CopyTo:

public void ProcessFiles()
{
IStorage stg;
IStorage stg_new;

ComTypes.STATSTG s = new ComTypes.STATSTG();

foreach (FileSystemInfo file in fileList)
{
StgCreateDocfile(file.FullName + "_new",
STGM.STGM_READWRITE | STGM.STGM_SHARE_EXCLUSIVE,
0, out stg_new);
StgOpenStorage(file.FullName, null, STGM.STGM_READWRITE

| STGM.STGM_SHARE_EXCLUSIVE,
IntPtr.Zero, 0, out stg);

stg.Stat(out s, STATFLAG.STATFLAG_DEFAULT);
// stg_new.SetClass(s.clsid);
stg.CopyTo(0, s.clsid, IntPtr.Zero, stg_new);
}
 
Z

Zefta

I've been working on a team that is working on the exact same problem.
We've managed to get this working by instantiating the IStorage Class
just as you did below. Let me know if you'd like me to forward our
in-house expert on Structured Storage.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top