public class SaveGraph
{
[DllImport("ole32.dll")]
static extern int StgCreateDocfile([MarshalAs(UnmanagedType.LPWStr)]
string pwcsName, StgmConstants grfMode, uint reserved, out IStorage ppstgOpen);
//Code based on MSDA
/// <summary>
/// Save graph filter
/// </summary>
/// <param name="pGraph">pointer to graph filter</param>
/// <param name="wszPath">Path to save</param>
/// <returns></returns>
public int SaveGraphFile(IGraphBuilder pGraph, string wszPath)
{
const string wszStreamName = "ActiveMovieGraph";
int hr;
IStorage pStorage;
hr = StgCreateDocfile( wszPath,
StgmConstants.STGM_CREATE | StgmConstants.STGM_TRANSACTED |
StgmConstants.STGM_READWRITE | StgmConstants.STGM_SHARE_EXCLUSIVE,
0, out pStorage);
if (hr < 0)
{
return hr;
}
IStream pStream;
hr = pStorage.CreateStream( wszStreamName,
StgmConstants.STGM_WRITE | StgmConstants.STGM_CREATE | StgmConstants.STGM_SHARE_EXCLUSIVE,
0, 0, out pStream);
if (hr < 0)
{
pStorage = null;
return hr;
}
IPersistStream pPersist;
pPersist = (IPersistStream)pGraph;
hr = pPersist.Save(pStream, true);
pStream = null;
pPersist = null;
if (hr>=0)
{
hr = pStorage.Commit(StgcConstants.STGC_DEFAULT);
}
pStorage = null;
return hr;
}
}
/*
* Code below based on pinvoke.net and msdn. Modified to comfortably benefited from it.
*
* WARNING: It should not be regarded as a complete and error-free implementation !
* Modifications only for the purpose of this sample
*
*/
[Flags]
public enum StgmConstants : uint
{
STGM_READ = 0x0,
STGM_WRITE = 0x1,
STGM_READWRITE = 0x2,
STGM_SHARE_DENY_NONE = 0x40,
STGM_SHARE_DENY_READ = 0x30,
STGM_SHARE_DENY_WRITE = 0x20,
STGM_SHARE_EXCLUSIVE = 0x10,
STGM_PRIORITY = 0x40000,
STGM_CREATE = 0x1000,
STGM_CONVERT = 0x20000,
STGM_FAILIFTHERE = 0x0,
STGM_DIRECT = 0x0,
STGM_TRANSACTED = 0x10000,
STGM_NOSCRATCH = 0x100000,
STGM_NOSNAPSHOT = 0x200000,
STGM_SIMPLE = 0x8000000,
STGM_DIRECT_SWMR = 0x400000,
STGM_DELETEONRELEASE = 0x4000000
}
public enum StgcConstants : uint
{
STGC_DEFAULT = 0,
STGC_OVERWRITE = 1,
STGC_ONLYIFCURRENT = 2,
STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4,
STGC_CONSOLIDATE = 8
}
[ComImport]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("00000109-0000-0000-C000-000000000046")]
public interface IPersistStream
{
[PreserveSig]
int GetClassID(out Guid pClassID);
[PreserveSig()]
int IsDirty();
[PreserveSig]
int Load([In, MarshalAs(UnmanagedType.Interface)] IStream pStm);
[PreserveSig]
int Save([In, MarshalAs(UnmanagedType.Interface)] IStream pStm, [In, MarshalAs(UnmanagedType.Bool)] bool fClearDirty);
[PreserveSig]
int GetSizeMax([Out] out UInt64 pcbSize);
}
[StructLayout(LayoutKind.Sequential)]
public struct FILETIME
{
public uint DateTimeLow;
public uint DateTimeHigh;
}
public struct STATSTG
{
[MarshalAs(UnmanagedType.LPTStr)]
public string pwcsName;
public int type;
public long cbSize;
public FILETIME mtime;
public FILETIME ctime;
public FILETIME atime;
public int grfMode;
public int grfLocksSupported;
public Guid clsid;
public int grfStateBits;
public int reserved;
}
[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]
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)]
interface IStorage
{
[PreserveSig]
int CreateStream(
/* [string][in] */ string pwcsName,
/* [in] */ StgmConstants grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out IStream ppstm);
[PreserveSig]
int OpenStream(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IntPtr reserved1,
/* [in] */ uint grfMode,
/* [in] */ uint reserved2,
/* [out] */ out IStream ppstm);
[PreserveSig]
int CreateStorage(
/* [string][in] */ string pwcsName,
/* [in] */ uint grfMode,
/* [in] */ uint reserved1,
/* [in] */ uint reserved2,
/* [out] */ out IStorage ppstg);
[PreserveSig]
int OpenStorage(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgPriority,
/* [in] */ uint grfMode,
/* [unique][in] */ IntPtr snbExclude,
/* [in] */ uint reserved,
/* [out] */ out IStorage ppstg);
[PreserveSig]
int CopyTo(
/* [in] */ uint ciidExclude,
/* [size_is][unique][in] */ Guid rgiidExclude, // should this be an array?
/* [unique][in] */ IntPtr snbExclude,
/* [unique][in] */ IStorage pstgDest);
[PreserveSig]
int MoveElementTo(
/* [string][in] */ string pwcsName,
/* [unique][in] */ IStorage pstgDest,
/* [string][in] */ string pwcsNewName,
/* [in] */ uint grfFlags);
[PreserveSig]
int Commit(
/* [in] */ StgcConstants grfCommitFlags);
[PreserveSig]
int Revert();
[PreserveSig]
int EnumElements(
/* [in] */ uint reserved1,
/* [size_is][unique][in] */ IntPtr reserved2,
/* [in] */ uint reserved3,
/* [out] */ out IEnumSTATSTG ppenum);
[PreserveSig]
int DestroyElement(
/* [string][in] */ string pwcsName);
[PreserveSig]
int RenameElement(
/* [string][in] */ string pwcsOldName,
/* [string][in] */ string pwcsNewName);
[PreserveSig]
int SetElementTimes(
/* [string][unique][in] */ string pwcsName,
/* [unique][in] */ FILETIME pctime,
/* [unique][in] */ FILETIME patime,
/* [unique][in] */ FILETIME pmtime);
[PreserveSig]
int SetClass(
/* [in] */ Guid clsid);
[PreserveSig]
int SetStateBits(
/* [in] */ uint grfStateBits,
/* [in] */ uint grfMask);
[PreserveSig]
int Stat(
/* [out] */ out STATSTG pstatstg,
/* [in] */ uint grfStatFlag);
}