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);
}
}
}
}