/*
 * Copyright 2002 Ove Kaaven
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

import "unknwn.idl";

interface IStream;
interface IEnumString;
interface IRunningObjectTable;
interface IMoniker;
interface IAdviseSink;
interface IAsyncManager;

/* FIXME: COSERVERINFO should be moved here from wtypes.idl */

/******************** Fundamentals ********************/

[
  local,
  object,
  uuid(00000003-0000-0000-C000-000000000046)
]
interface IMarshal : IUnknown
{
  typedef [unique] IMarshal *LPMARSHAL;

  HRESULT GetUnmarshalClass(
    [in] REFIID riid,
    [in, unique] void *pv,
    [in] DWORD dwDestContext,
    [in, unique] void *pvDestContext,
    [in] DWORD mshlflags,
    [out] CLSID *pCid);

  HRESULT GetMarshalSizeMax(
    [in] REFIID riid,
    [in, unique] void *pv,
    [in] DWORD dwDestContext,
    [in, unique] void *pvDestContext,
    [in] DWORD mshlflags,
    [out] DWORD *pSize);

  HRESULT MarshalInterface(
    [in, unique] IStream *pStm,
    [in] REFIID riid,
    [in, unique] void *pv,
    [in] DWORD dwDestContext,
    [in, unique] void *pvDestContext,
    [in] DWORD mshlflags);

  HRESULT UnmarshalInterface(
    [in, unique] IStream *pStm,
    [in] REFIID riid,
    [out] void **ppv);

  HRESULT ReleaseMarshalData(
    [in, unique] IStream *pStm);

  HRESULT DisconnectObject(
    [in] DWORD dwReserved);
}

[
  local,
  object,
  uuid(00000018-0000-0000-C000-000000000046)
]
interface IStdMarshalInfo : IUnknown
{
  typedef [unique] IStdMarshalInfo *LPSTDMARSHALINFO;

  HRESULT GetClassForHandler(
    [in] DWORD dwDestContext,
    [in, unique] void *pvDestContext,
    [out] CLSID *pClsid);
}

[
  local,
  object,
  uuid(00000019-0000-0000-C000-000000000046)
]
interface IExternalConnection : IUnknown
{
  typedef [unique] IExternalConnection *LPEXTERNALCONNECTION;

  typedef enum tagEXTCONN {
    EXTCONN_STRONG   = 0x0001,
    EXTCONN_WEAK     = 0x0002,
    EXTCONN_CALLABLE = 0x0004
  } EXTCONN;

  DWORD AddConnection(
    [in] DWORD extconn,
    [in] DWORD reserved);

  DWORD ReleaseConnection(
    [in] DWORD extconn,
    [in] DWORD reserved,
    [in] BOOL fLastReleaseCloses);
}

[
  local,
  object,
  uuid(00000020-0000-0000-C000-000000000046)
]
interface IMultiQI : IUnknown
{
  typedef [unique] IMultiQI *LPMULTIQI;

  typedef struct tagMULTI_QI {
    const IID *pIID;
    IUnknown *pItf;
    HRESULT hr;
  } MULTI_QI;

  HRESULT QueryMultipleInterfaces(
    [in] ULONG cMQIs,
    [in, out] MULTI_QI *pMQIs);
}

[
  local,
  object,
  uuid(00000002-0000-0000-C000-000000000046)
]
interface IMalloc : IUnknown
{
  typedef [unique] IMalloc *LPMALLOC;

  LPVOID Alloc(
    [in] ULONG cb);

  LPVOID Realloc(
    [in] LPVOID pv,
    [in] ULONG cb);

  void Free(
    [in] LPVOID pv);

  ULONG GetSize(
    [in] LPVOID pv);

  int DidAlloc(LPVOID pv);

  void HeapMinimize();
}

[
  local,
  object,
  uuid(0000001d-0000-0000-C000-000000000046)
]
interface IMallocSpy : IUnknown
{
  typedef [unique] IMallocSpy *LPMALLOCSPY;

  ULONG PreAlloc(
    [in] ULONG cbRequest);

  LPVOID PostAlloc(
    [in] LPVOID pActual);

  LPVOID PreFree(
    [in] LPVOID pRequest,
    [in] BOOL fSpyed);

  void PostFree(
    [in] BOOL fSpyed);

  ULONG PreRealloc(
    [in] LPVOID pRequest,
    [in] ULONG cbRequest,
    [out] LPVOID *ppNewRequest,
    [in] BOOL fSpyed);

  LPVOID PostRealloc(
    [in] LPVOID pActual,
    [in] BOOL fSpyed);

  LPVOID PreGetSize(
    [in] LPVOID pRequest,
    [in] BOOL fSpyed);

  ULONG PostGetSize(
    [in] ULONG cbActual,
    [in] BOOL fSpyed);

  LPVOID PreDidAlloc(
    [in] LPVOID pRequest,
    [in] BOOL fSpyed);

  int PostDidAlloc(
    [in] LPVOID pRequest,
    [in] BOOL fSpyed,
    [in] int fActual);

  void PreHeapMinimize();

  void PostHeapMinimize();
}

[
  object,
  uuid(00000100-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumUnknown : IUnknown
{
  typedef [unique] IEnumUnknown *LPENUMUNKNOWN;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out] IUnknown **rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    IUnknown **rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumUnknown **ppenum);
}

[
  object,
  uuid(00000022-0000-0000-C000-000000000046),
  version(1.0),
  pointer_default(unique)
]
interface ISurrogate : IUnknown
{
  typedef [unique] ISurrogate *LPSURROGATE;

  HRESULT LoadDllServer(
    [in] REFCLSID Clsid);
  HRESULT FreeSurrogate();
}

[
  local,
  object,
  uuid(00000146-0000-0000-C000-000000000046)
]
interface IGlobalInterfaceTable : IUnknown
{
  typedef [unique] IGlobalInterfaceTable *LPGLOBALINTERFACETABLE;

  HRESULT RegisterInterfaceInGlobal(
    [in] IUnknown *pUnk,
    [in] REFIID riid,
    [out] DWORD *pdwCookie);

  HRESULT RevokeInterfaceFromGlobal(
    [in] DWORD dwCookie);

  HRESULT GetInterfaceFromGlobal(
    [in] DWORD dwCookie,
    [in] REFIID riid,
    [out, iid_is(riid)] void **ppv);
}

/******************** Monikers ********************/

[
  object,
  uuid(0000000e-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IBindCtx : IUnknown
{
  typedef [unique] IBindCtx *LPBINDCTX;
  typedef [unique] IBindCtx *LPBC;

  typedef struct tagBIND_OPTS {
    DWORD cbStruct;
    DWORD grfFlags;
    DWORD grfMode;
    DWORD dwTickCountDeadline;
  } BIND_OPTS, *LPBIND_OPTS;

  /* FIXME: C++ crap */
  typedef struct tagBIND_OPTS2 {
    DWORD cbStruct;
    DWORD grfFlags;
    DWORD grfMode;
    DWORD dwTickCountDeadline;
    DWORD dwTrackFlags;
    DWORD dwClassContext;
    LCID  locale;
    COSERVERINFO *pServerInfo;
  } BIND_OPTS2, *LPBIND_OPTS2;

  typedef enum tagBIND_FLAGS {
    BIND_MAYBOTHERUSER   = 1,
    BIND_JUSTTESTEXISTENCE = 2
  } BIND_FLAGS;

  HRESULT RegisterObjectBound(
    [in, unique] IUnknown *punk);

  HRESULT RevokeObjectBound(
    [in, unique] IUnknown *punk);

  HRESULT ReleaseBoundObjects();

  [local]
  HRESULT SetBindOptions(
    [in] BIND_OPTS *pbindopts);

  [call_as(SetBindOptions)]
  HRESULT RemoteSetBindOptions(
    [in] BIND_OPTS2 *pbindopts);

  [local]
  HRESULT GetBindOptions(
    [in, out] BIND_OPTS *pbindopts);

  [call_as(GetBindOptions)]
  HRESULT RemoteGetBindOptions(
    [in, out] BIND_OPTS2 *pbindopts);

  HRESULT GetRunningObjectTable(
    [out] IRunningObjectTable **pprot);

  HRESULT RegisterObjectParam(
    [in] LPOLESTR pszKey,
    [in, unique] IUnknown *punk);

  HRESULT GetObjectParam(
    [in] LPOLESTR pszKey,
    [out] IUnknown **ppunk);

  HRESULT EnumObjectParam(
    [out] IEnumString **ppenum);

  HRESULT RevokeObjectParam(
    [in] LPOLESTR pszKey);
}

[
  object,
  uuid(00000102-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumMoniker : IUnknown
{
  typedef [unique] IEnumMoniker *LPENUMMONIKER;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    IMoniker **rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    IMoniker **rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumMoniker **ppenum);
}

[
  object,
  uuid(00000126-0000-0000-C000-000000000046)
]
interface IRunnableObject : IUnknown
{
  typedef [unique] IRunnableObject *LPRUNNABLEOBJECT;

  HRESULT GetRunningClass(
    [out] LPCLSID lpClsid);

  HRESULT Run(
    [in] LPBINDCTX pbc);

  [local]
  BOOL IsRunning();

  [call_as(IsRunning)]
  HRESULT RemoteIsRunning();

  HRESULT LockRunning(
    [in] BOOL fLock,
    [in] BOOL fLastUnlockCloses);

  HRESULT SetContainedObject(
    [in] BOOL fContained);
}

/* GetObject is defined in wingdi.h as WINELIB_NAME_AW(GetObject),
 * which resolves to a compilation failure if __WINESRC__ is defined,
 * but GetObject is used as a valid method name below, so we have
 * to undefine it if __WINESRC__ is defined */
cpp_quote("#ifdef __WINESRC__")
cpp_quote("#undef GetObject")
cpp_quote("#endif")

[
  object,
  uuid(00000010-0000-0000-C000-000000000046)
]
interface IRunningObjectTable : IUnknown
{
  typedef [unique] IRunningObjectTable *LPRUNNINGOBJECTTABLE;

  HRESULT Register(
    [in] DWORD grfFlags,
    [in, unique] IUnknown *punkObject,
    [in, unique] IMoniker *pmkObjectName,
    [out] DWORD *pdwRegister);

  HRESULT Revoke(
    [in] DWORD dwRegister);

  HRESULT IsRunning(
    [in, unique] IMoniker *pmkObjectName);

  HRESULT GetObject(
    [in, unique] IMoniker *pmkObjectName,
    [out] IUnknown **ppunkObject);

  HRESULT NoteChangeTime(
    [in] DWORD dwRegister,
    [in] FILETIME *pfiletime);

  HRESULT GetTimeOfLastChange(
    [in, unique] IMoniker *pmkObjectName,
    [out] FILETIME *pfiletime);

  HRESULT EnumRunning(
    [out] IEnumMoniker **ppenumMoniker);
}

[
  object,
  uuid(0000010c-0000-0000-C000-000000000046)
]
interface IPersist : IUnknown
{
  typedef [unique] IPersist *LPPERSIST;

  HRESULT GetClassID(
    [out] CLSID *pClassID);
}

[
  object,
  uuid(00000109-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IPersistStream : IPersist
{
  typedef [unique] IPersistStream *LPPERSISTSTREAM;

  HRESULT IsDirty();

  HRESULT Load(
    [in, unique] IStream *pStm);

  HRESULT Save(
    [in, unique] IStream *pStm,
    [in] BOOL fClearDirty);

  HRESULT GetSizeMax(
    [out] ULARGE_INTEGER *pcbSize);
}

[
  object,
  uuid(0000000f-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IMoniker : IPersistStream
{
  typedef [unique] IMoniker *LPMONIKER;

  typedef enum tagMKSYS {
    MKSYS_NONE             = 0,
    MKSYS_GENERICCOMPOSITE = 1,
    MKSYS_FILEMONIKER      = 2,
    MKSYS_ANTIMONIKER      = 3,
    MKSYS_ITEMMONIKER      = 4,
    MKSYS_POINTERMONIKER   = 5,
    /* MKSYS_URLMONIKER       = 6, */ /* defined in urlmon.idl */
    MKSYS_CLASSMONIKER     = 7
  } MKSYS;

  typedef [v1_enum] enum tagMKREDUCE {
    MKRREDUCE_ONE         = 3 << 16,
    MKRREDUCE_TOUSER      = 2 << 16,
    MKRREDUCE_THROUGHUSER = 1 << 16,
    MKRREDUCE_ALL         = 0
  } MKRREDUCE;

  [local]
  HRESULT BindToObject(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [in] REFIID riidResult,
    [out, iid_is(riidResult)] void **ppvResult);

  [call_as(BindToObject)]
  HRESULT RemoteBindToObject(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [in] REFIID riidResult,
    [out, iid_is(riidResult)] IUnknown **ppvResult);

  [local]
  HRESULT BindToStorage(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [in] REFIID riid,
    [out, iid_is(riid)] void **ppvObj);

  [call_as(BindToStorage)]
  HRESULT RemoteBindToStorage(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [in] REFIID riid,
    [out, iid_is(riid)] IUnknown **ppvObj);

  HRESULT Reduce(
    [in, unique] IBindCtx *pbc,
    [in] DWORD dwReduceHowFar,
    [in, out, unique] IMoniker **ppmkToLeft,
    [out] IMoniker **ppmkReduced);

  HRESULT ComposeWith(
    [in, unique] IMoniker *pmkRight,
    [in] BOOL fOnlyIfNotGeneric,
    [out] IMoniker **ppmkComposite);

  HRESULT Enum(
    [in] BOOL fForward,
    [out] IEnumMoniker **ppenumMoniker);

  HRESULT IsEqual(
    [in, unique] IMoniker *pmkOtherMoniker);

  HRESULT Hash(
    [out] DWORD *pdwHash);

  HRESULT IsRunning(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [in, unique] IMoniker *pmkNewlyRunning);

  HRESULT GetTimeOfLastChange(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [out] FILETIME *pFileTime);

  HRESULT Inverse(
    [out] IMoniker **ppmk);

  HRESULT CommonPrefixWith(
    [in, unique] IMoniker *pmkOther,
    [out] IMoniker **ppmkPrefix);

  HRESULT RelativePathTo(
    [in, unique] IMoniker *pmkOther,
    [out] IMoniker **ppmkRelPath);

  HRESULT GetDisplayName(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [out] LPOLESTR *ppszDisplayName);

  HRESULT ParseDisplayName(
    [in, unique] IBindCtx *pbc,
    [in, unique] IMoniker *pmkToLeft,
    [in] LPOLESTR pszDisplayName,
    [out] ULONG *pchEaten,
    [out] IMoniker **ppmkOut);

  HRESULT IsSystemMoniker(
    [out] DWORD *pdwMksys);
}

[
  object,
  uuid(f29f6bc0-5021-11ce-aa15-00006901293f),
  pointer_default(unique)
]
interface IROTData : IUnknown
{
  HRESULT GetComparisonData(
    [out, size_is(cbMax)] byte *pbData,
    [in] ULONG cbMax,
    [out] ULONG *pcbData);
}

[
  object,
  uuid(00000101-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumString : IUnknown
{
  typedef [unique] IEnumString *LPENUMSTRING;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    LPOLESTR *rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    LPOLESTR *rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumString **ppenum);
}

[
  object,
  uuid(00000140-0000-0000-C000-000000000046)
]
interface IClassActivator : IUnknown
{
  HRESULT GetClassObject(
    [in] REFCLSID rclsid,
    [in] DWORD dwClassContext,
    [in] LCID locale,
    [in] REFIID riid,
    [out, iid_is(riid)] void **ppv);
}

/******************** Storage ********************/

[
  object,
  uuid(0c733a30-2a1c-11ce-ade5-00aa0044773d),
  pointer_default(unique)
]
interface ISequentialStream : IUnknown
{
  [local]
  HRESULT Read(
    [out, size_is(cb), length_is(*pcbRead)]
    void *pv,
    [in] ULONG cb,
    [out] ULONG *pcbRead);

  [call_as(Read)]
  HRESULT RemoteRead(
    [out, size_is(cb), length_is(*pcbRead)]
    byte *pv,
    [in] ULONG cb,
    [out] ULONG *pcbRead);

  [local]
  HRESULT Write(
    [in, size_is(cb)] const void *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);

  [call_as(Write)]
  HRESULT RemoteWrite(
    [in, size_is(cb)] const byte *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);
}

[
  object,
  uuid(0000000c-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IStream : ISequentialStream
{
  typedef [unique] IStream *LPSTREAM;

  typedef struct tagSTATSTG {
    LPOLESTR pwcsName;
    DWORD type;
    ULARGE_INTEGER cbSize;
    FILETIME mtime;
    FILETIME ctime;
    FILETIME atime;
    DWORD grfMode;
    DWORD grfLocksSupported;
    CLSID clsid;
    DWORD grfStateBits;
    DWORD reserved;
  } STATSTG;

  typedef enum tagSTGTY {
    STGTY_STORAGE   = 1,
    STGTY_STREAM    = 2,
    STGTY_LOCKBYTES = 3,
    STGTY_PROPERTY  = 4
  } STGTY;

  typedef enum tagSTREAM_SEEK {
    STREAM_SEEK_SET = 0,
    STREAM_SEEK_CUR = 1,
    STREAM_SEEK_END = 2
  } STREAM_SEEK;

  /* these are defined in Linux's fcntl.h,
   * undefine them to avoid conflicts */
  cpp_quote("#undef LOCK_MAND")
  cpp_quote("#undef LOCK_READ")
  cpp_quote("#undef LOCK_WRITE")
  cpp_quote("#undef LOCK_RW")

  typedef enum tagLOCKTYPE {
    LOCK_WRITE      = 1,
    LOCK_EXCLUSIVE  = 2,
    LOCK_ONLYONCE   = 4
  } LOCKTYPE;

  [local]
  HRESULT Seek(
    [in] LARGE_INTEGER dlibMove,
    [in] DWORD dwOrigin,
    [out] ULARGE_INTEGER *plibNewPosition);

  [call_as(Seek)]
  HRESULT RemoteSeek(
    [in] LARGE_INTEGER dlibMove,
    [in] DWORD dwOrigin,
    [out] ULARGE_INTEGER *plibNewPosition);

  HRESULT SetSize(
    [in] ULARGE_INTEGER libNewSize);

  [local]
  HRESULT CopyTo(
    [in, unique] IStream *pstm,
    [in] ULARGE_INTEGER cb,
    [out] ULARGE_INTEGER *pcbRead,
    [out] ULARGE_INTEGER *pcbWritten);

  [call_as(CopyTo)]
  HRESULT RemoteCopyTo(
    [in, unique] IStream *pstm,
    [in] ULARGE_INTEGER cb,
    [out] ULARGE_INTEGER *pcbRead,
    [out] ULARGE_INTEGER *pcbWritten);

  HRESULT Commit(
    [in] DWORD grfCommitFlags);

  HRESULT Revert();

  HRESULT LockRegion(
    [in] ULARGE_INTEGER libOffset,
    [in] ULARGE_INTEGER cb,
    [in] DWORD dwLockType);

  HRESULT UnlockRegion(
    [in] ULARGE_INTEGER libOffset,
    [in] ULARGE_INTEGER cb,
    [in] DWORD dwLockType);

  HRESULT Stat(
    [out] STATSTG *pstatstg,
    [in] DWORD grfStatFlag);

  HRESULT Clone(
    [out] IStream **ppstm);
}

[
  object,
  uuid(0000000d-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumSTATSTG : IUnknown
{
  typedef [unique] IEnumSTATSTG *LPENUMSTATSTG;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATSTG *rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATSTG *rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumSTATSTG **ppenum);
}

[
  object,
  uuid(0000000b-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IStorage : IUnknown
{
  typedef [unique] IStorage *LPSTORAGE;

  typedef struct tagRemSNB {
    unsigned long ulCntStr;
    unsigned long ulCntChar;
    [size_is(ulCntChar)] OLECHAR rgString[];
  } RemSNB;

  typedef [unique] RemSNB *wireSNB;
  typedef [wire_marshal(wireSNB)] OLECHAR **SNB;

  HRESULT CreateStream(
    [in] LPCOLESTR pwcsName,
    [in] DWORD grfMode,
    [in] DWORD reserved1,
    [in] DWORD reserved2,
    [out] IStream **ppstm);

  [local]
  HRESULT OpenStream(
    [in] LPCOLESTR pwcsName,
    [in, unique] void *reserved1,
    [in] DWORD grfMode,
    [in] DWORD reserved2,
    [out] IStream **ppstm);

  [call_as(OpenStream)]
  HRESULT RemoteOpenStream(
    [in] LPCOLESTR pwcsName,
    [in] unsigned long cbReserved1,
    [in, unique, size_is(cbReserved1)] byte *reserved1,
    [in] DWORD grfMode,
    [in] DWORD reserved2,
    [out] IStream **ppstm);

  HRESULT CreateStorage(
    [in] LPCOLESTR pwcsName,
    [in] DWORD grfMode,
    [in] DWORD dwStgFmt,
    [in] DWORD reserved2,
    [out] IStorage **ppstg);

  HRESULT OpenStorage(
    [in, unique] LPCOLESTR pwcsName,
    [in, unique] IStorage *pstgPriority,
    [in] DWORD grfMode,
    [in, unique] SNB snbExclude,
    [in] DWORD reserved,
    [out] IStorage **ppstg);

  HRESULT CopyTo(
    [in] DWORD ciidExclude,
    [in, unique, size_is(ciidExclude)] const IID *rgiidExclude,
    [in, unique] SNB snbExclude,
    [in, unique] IStorage *pstgDest);

  HRESULT MoveElementTo(
    [in] LPCOLESTR pwcsName,
    [in, unique] IStorage *pstgDest,
    [in] LPCOLESTR pwcsNewName,
    [in] DWORD grfFlags);

  HRESULT Commit(
    [in] DWORD grfCommitFlags);

  HRESULT Revert();

  [local]
  HRESULT EnumElements(
    [in] DWORD reserved1,
    [in, unique, size_is(1)] void *reserved2,
    [in] DWORD reserved3,
    [out] IEnumSTATSTG **ppenum);

  [call_as(EnumElements)]
  HRESULT RemoteEnumElements(
    [in] DWORD reserved1,
    [in] unsigned long cbReserved2,
    [in, unique, size_is(cbReserved2)] byte *reserved2,
    [in] DWORD reserved3,
    [out] IEnumSTATSTG **ppenum);

  HRESULT DestroyElement(
    [in] LPCOLESTR pwcsName);

  HRESULT RenameElement(
    [in] LPCOLESTR pwcsOldName,
    [in] LPCOLESTR pwcsNewName);

  HRESULT SetElementTimes(
    [in, unique] LPCOLESTR pwcsName,
    [in, unique] const FILETIME *pctime,
    [in, unique] const FILETIME *patime,
    [in, unique] const FILETIME *pmtime);

  HRESULT SetClass(
    [in] REFCLSID clsid);

  HRESULT SetStateBits(
    [in] DWORD grfStateBits,
    [in] DWORD grfMask);

  HRESULT Stat(
    [out] STATSTG *pstatstg,
    [in] DWORD grfStatFlag);
}

[
  object,
  uuid(0000010b-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IPersistFile : IPersist
{
  typedef [unique] IPersistFile *LPPERSISTFILE;

  HRESULT IsDirty();

  HRESULT Load(
    [in] LPCOLESTR pszFileName,
    [in] DWORD dwMode);

  HRESULT Save(
    [in, unique] LPCOLESTR pszFileName,
    [in] BOOL fRemember);

  HRESULT SaveCompleted(
    [in, unique] LPCOLESTR pszFileName);

  HRESULT GetCurFile(
    [out] LPOLESTR *ppszFileName);
}

[
  object,
  uuid(0000010a-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IPersistStorage : IPersist
{
  typedef [unique] IPersistStorage *LPPERSISTSTORAGE;

  HRESULT IsDirty();

  HRESULT InitNew(
    [in, unique] IStorage *pStg);

  HRESULT Load(
    [in, unique] IStorage *pStg);

  HRESULT Save(
    [in, unique] IStorage *pStgSave,
    [in] BOOL fSameAsLoad);

  HRESULT SaveCompleted(
    [in, unique] IStorage *pStgNew);

  HRESULT HandsOffStorage();
}

[
  object,
  uuid(00000012-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IRootStorage : IUnknown
{
  typedef [unique] IRootStorage *LPROOTSTORAGE;

  HRESULT SwitchToFile(
    [in] LPOLESTR pszFile);
}

[
  object,
  uuid(0000000a-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface ILockBytes : IUnknown
{
  typedef [unique] ILockBytes *LPLOCKBYTES;

  [local]
  HRESULT ReadAt(
    [in] ULARGE_INTEGER ulOffset,
    [out, size_is(cb), length_is(*pcbRead)]
    void *pv,
    [in] ULONG cb,
    [out] ULONG *pcbRead);

  [call_as(ReadAt)]
  HRESULT RemoteReadAt(
    [in] ULARGE_INTEGER ulOffset,
    [out, size_is(cb), length_is(*pcbRead)]
    byte *pv,
    [in] ULONG cb,
    [out] ULONG *pcbRead);

  [local]
  HRESULT WriteAt(
    [in] ULARGE_INTEGER ulOffset,
    [in, size_is(cb)] const void *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);

  [call_as(WriteAt)]
  HRESULT RemoteWriteAt(
    [in] ULARGE_INTEGER ulOffset,
    [in, size_is(cb)] const byte *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);

  HRESULT Flush();

  HRESULT SetSize(
    [in] ULARGE_INTEGER cb);

  HRESULT LockRegion(
    [in] ULARGE_INTEGER libOffset,
    [in] ULARGE_INTEGER cb,
    [in] DWORD dwLockType);

  HRESULT UnlockRegion(
    [in] ULARGE_INTEGER libOffset,
    [in] ULARGE_INTEGER cb,
    [in] DWORD dwLockType);

  HRESULT Stat(
    [out] STATSTG *pstatstg,
    [in] DWORD grfStatFlag);
}

[
  object,
  uuid(99caf010-415e-11cf-8814-00aa00b569f5),
  pointer_default(unique)
]
interface IFillLockBytes : IUnknown
{
  [local]
  HRESULT FillAppend(
    [in, size_is(cb)] const void *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);

  [call_as(FillAppend)]
  HRESULT RemoteFillAppend(
    [in, size_is(cb)] const byte *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);

  [local]
  HRESULT FillAt(
    [in] ULARGE_INTEGER ulOffset,
    [in, size_is(cb)] const void *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);

  [call_as(FillAt)]
  HRESULT RemoteFillAt(
    [in] ULARGE_INTEGER ulOffset,
    [in, size_is(cb)] const byte *pv,
    [in] ULONG cb,
    [out] ULONG *pcbWritten);

  HRESULT SetFillSize(
    [in] ULARGE_INTEGER ulSize);

  HRESULT Terminate(
    [in] BOOL bCanceled);
}

[
  object,
  uuid(a9d758a0-4617-11cf-95fc-00aa00680db4),
  pointer_default(unique)
]
interface IProgressNotify : IUnknown
{
  HRESULT OnProgress(
    [in] DWORD dwProgressCurrent,
    [in] DWORD dwProgressMaximum,
    [in] BOOL fAccurate,
    [in] BOOL fOwner);
}

[
  local,
  object,
  uuid(0e6d4d90-6738-11cf-9608-00aa00680db4),
  pointer_default(unique)
]
interface ILayoutStorage : IUnknown
{
  typedef struct tagStorageLayout {
    DWORD LayoutType;
    OLECHAR *pwcsElementName;
    LARGE_INTEGER cOffset;
    LARGE_INTEGER cBytes;
  } StorageLayout;

  HRESULT LayoutScript(
    [in] StorageLayout *pStorageLayout,
    [in] DWORD nEntries,
    [in] DWORD glfInterleavedFlag);

  HRESULT BeginMonitor();

  HRESULT EndMonitor();

  HRESULT ReLayoutDocfile(
    [in] OLECHAR *pwcsNewDfName);

  HRESULT ReLayoutDocfileOnILockBytes(
    [in] ILockBytes *pILockBytes);
}

/******************** Data Object ********************/

[
  object,
  uuid(00000103-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumFORMATETC : IUnknown
{
  typedef [unique] IEnumFORMATETC *LPENUMFORMATETC;

  typedef struct tagDVTARGETDEVICE {
    DWORD tdSize;
    WORD tdDriverNameOffset;
    WORD tdDeviceNameOffset;
    WORD tdPortNameOffset;
    WORD tdExtDevmodeOffset;
    [size_is(tdSize - sizeof(DWORD) - 4*sizeof(WORD))]
    BYTE tdData[];
  } DVTARGETDEVICE;

  typedef CLIPFORMAT *LPCLIPFORMAT;

  typedef struct tagFORMATETC {
    CLIPFORMAT cfFormat;
    [unique] DVTARGETDEVICE *ptd;
    DWORD dwAspect;
    LONG lindex;
    DWORD tymed;
  } FORMATETC, *LPFORMATETC;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    FORMATETC *rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    FORMATETC *rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumFORMATETC **ppenum);
}

[
  object,
  uuid(00000105-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumSTATDATA : IUnknown
{
  typedef [unique] IEnumSTATDATA *LPENUMSTATDATA;

  typedef enum tagADVF {
    ADVF_NODATA            = 1,
    ADVF_PRIMEFIRST        = 2,
    ADVF_ONLYONCE          = 4,
    ADVF_DATAONSTOP        = 64,
    ADVFCACHE_NOHANDLER    = 8,
    ADVFCACHE_FORCEBUILTIN = 16,
    ADVFCACHE_ONSAVE       = 32
  } ADVF;

  typedef struct tagSTATDATA
  {
    FORMATETC formatetc;
    DWORD advf;
    [unique] IAdviseSink *pAdvSink;
    DWORD dwConnection;
  } STATDATA, *LPSTATDATA;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATDATA *rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATDATA *rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumSTATDATA **ppenum);
}

[
  object,
  uuid(0000010f-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IAdviseSink : IUnknown
{
  typedef IAdviseSink *LPADVISESINK;

  typedef [v1_enum] enum tagTYMED {
    TYMED_HGLOBAL  = 1,
    TYMED_FILE     = 2,
    TYMED_ISTREAM  = 4,
    TYMED_ISTORAGE = 8,
    TYMED_GDI      = 16,
    TYMED_MFPICT   = 32,
    TYMED_ENHMF    = 64,
    TYMED_NULL     = 0
  } TYMED;

  typedef struct tagRemSTGMEDIUM {
    DWORD tymed;
    DWORD dwHandleType;
    unsigned long pData;
    unsigned long pUnkForRelease;
    unsigned long cbData;
    [size_is(cbData)] byte data[];
  } RemSTGMEDIUM;

  /* FIXME: C/C++ nameless union version */
  typedef struct tagSTGMEDIUM {
    DWORD tymed;
    [switch_is(tymed)] union {
    [case(TYMED_GDI)]      HBITMAP hBitmap;
    [case(TYMED_MFPICT)]   HMETAFILEPICT hMetaFilePict;
    [case(TYMED_ENHMF)]    HENHMETAFILE hEnhMetaFile;
    [case(TYMED_HGLOBAL)]  HGLOBAL hGlobal;
    [case(TYMED_FILE)]     LPOLESTR lpszFileName;
    [case(TYMED_ISTREAM)]  IStream *pstm;
    [case(TYMED_ISTORAGE)] IStorage *pstg;
    [default]              ;
    };
    [unique] IUnknown *pUnkForRelease;
  } uSTGMEDIUM;

/* copied from wingdi.h */
#define OBJ_PEN             1
#define OBJ_BRUSH           2
#define OBJ_DC              3
#define OBJ_METADC          4
#define OBJ_PAL             5
#define OBJ_FONT            6
#define OBJ_BITMAP          7
#define OBJ_REGION          8
#define OBJ_METAFILE        9
#define OBJ_MEMDC           10
#define OBJ_EXTPEN          11
#define OBJ_ENHMETADC       12
#define OBJ_ENHMETAFILE     13

  typedef union _GDI_OBJECT switch(DWORD ObjectType) u {
    case OBJ_BITMAP: wireHBITMAP hBitmap;
    case OBJ_PAL:    wireHPALETTE hPalette;
    default:         wireHGLOBAL hGeneric;
  } GDI_OBJECT;

  typedef struct _userSTGMEDIUM {
    union switch(DWORD tymed) u {
    case TYMED_NULL:     ;
    case TYMED_MFPICT:   wireHMETAFILEPICT hMetaFilePict;
    case TYMED_ENHMF:    wireHENHMETAFILE hHEnhMetaFile;
    case TYMED_GDI:      GDI_OBJECT *hGdiHandle;
    case TYMED_HGLOBAL:  wireHGLOBAL hGlobal;
    case TYMED_FILE:     LPOLESTR lpszFileName;
    case TYMED_ISTREAM:  BYTE_BLOB *pstm;
    case TYMED_ISTORAGE: BYTE_BLOB *pstg;
    };
    IUnknown *pUnkForRelease;
  } userSTGMEDIUM;

  typedef [unique] userSTGMEDIUM *wireSTGMEDIUM;
  typedef [wire_marshal(wireSTGMEDIUM)] uSTGMEDIUM STGMEDIUM;

  typedef [unique] userSTGMEDIUM *wireASYNC_STGMEDIUM;
  typedef [wire_marshal(wireASYNC_STGMEDIUM)] STGMEDIUM ASYNC_STGMEDIUM;

  typedef STGMEDIUM *LPSTGMEDIUM;

  typedef struct _userFLAG_STGMEDIUM {
    long ContextFlags;
    long fPassOwnership;
    userSTGMEDIUM Stgmed;
  } userFLAG_STGMEDIUM;

  typedef [unique] userFLAG_STGMEDIUM *wireFLAG_STGMEDIUM;

  typedef [wire_marshal(wireFLAG_STGMEDIUM)] struct _FLAG_STGMEDIUM {
    long ContextFlags;
    long fPassOwnership;
    STGMEDIUM Stgmed;
  } FLAG_STGMEDIUM;

  [local]
  void OnDataChange(
    [in, unique] FORMATETC *pFormatetc,
    [in, unique] STGMEDIUM *pStgmed);

  [call_as(OnDataChange), async]
  HRESULT  RemoteOnDataChange(
    [in] IAsyncManager **ppIAM,
    [in, unique] FORMATETC *pFormatetc,
    [in, unique] ASYNC_STGMEDIUM *pStgmed);

  [local]
  void OnViewChange(
    [in] DWORD dwAspect,
    [in] LONG lindex);

  [call_as(OnViewChange), async]
  HRESULT RemoteOnViewChange(
    [in] IAsyncManager **ppIAM,
    [in] DWORD dwAspect,
    [in] LONG lindex);

  [local]
  void OnRename(
    [in] IMoniker *pmk);

  [call_as(OnRename), async]
  HRESULT RemoteOnRename(
    [in] IAsyncManager **ppIAM,
    [in] IMoniker *pmk);

  [local]
  void OnSave();

  [call_as(OnSave), async]
  HRESULT RemoteOnSave(
    [in] IAsyncManager **ppIAM);

  [local]
  void OnClose();

  [call_as(OnClose)]
  HRESULT RemoteOnClose();
}

[
  object,
  uuid(00000125-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IAdviseSink2 : IAdviseSink
{
  typedef [unique] IAdviseSink2 *LPADVISESINK2;

  [local]
  void OnLinkSrcChange(
    [in, unique] IMoniker *pmk);

  [call_as(OnLinkSrcChange), async]
  HRESULT RemoteOnLinkSrcChange(
    [in] IAsyncManager **ppIAM,
    [in, unique] IMoniker *pmk);
}

[
  object,
  uuid(0000010e-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IDataObject : IUnknown
{
  typedef [unique] IDataObject *LPDATAOBJECT;

  typedef enum tagDATADIR {
    DATADIR_GET = 1,
    DATADIR_SET = 2
  } DATADIR;

  [local]
  HRESULT GetData(
    [in, unique] FORMATETC *pformatetcIn,
    [out] STGMEDIUM *pmedium);

  [call_as(GetData)]
  HRESULT RemoteGetData(
    [in, unique] FORMATETC *pformatetcIn,
    [out] STGMEDIUM *pRemoteMedium);

  [local]
  HRESULT GetDataHere(
    [in, unique] FORMATETC *pformatetc,
    [in, out] STGMEDIUM *pmedium);

  [call_as(GetDataHere)]
  HRESULT RemoteGetDataHere(
    [in, unique] FORMATETC *pformatetc,
    [in, out] STGMEDIUM *pRemoteMedium);

  HRESULT QueryGetData(
    [in, unique] FORMATETC *pformatetc);

  HRESULT GetCanonicalFormatEtc(
    [in, unique] FORMATETC *pformatectIn,
    [out] FORMATETC *pformatetcOut);

  [local]
  HRESULT SetData(
    [in, unique] FORMATETC *pformatetc,
    [in, unique] STGMEDIUM *pmedium,
    [in] BOOL fRelease);

  [call_as(SetData)]
  HRESULT RemoteSetData(
    [in, unique] FORMATETC *pformatetc,
    [in, unique] FLAG_STGMEDIUM *pmedium,
    [in] BOOL fRelease);

  HRESULT EnumFormatEtc(
    [in] DWORD dwDirection,
    [out] IEnumFORMATETC **ppenumFormatEtc);

  HRESULT DAdvise(
    [in] FORMATETC *pformatetc,
    [in] DWORD advf,
    [in, unique] IAdviseSink *pAdvSink,
    [out] DWORD *pdwConnection);

  HRESULT DUnadvise(
    [in] DWORD dwConnection);

  HRESULT EnumDAdvise(
    [out] IEnumSTATDATA **ppenumAdvise);
}

[
  local,
  object,
  uuid(00000110-0000-0000-C000-000000000046)
]
interface IDataAdviseHolder : IUnknown
{
  typedef [unique] IDataAdviseHolder *LPDATAADVISEHOLDER;

  HRESULT Advise(
    [in, unique] IDataObject *pDataObject,
    [in, unique] FORMATETC *pFetc,
    [in] DWORD advf,
    [in, unique] IAdviseSink *pAdvise,
    [out] DWORD *pdwConnection);

  HRESULT Unadvise(
    [in] DWORD dwConnection);

  HRESULT EnumAdvise(
    [out] IEnumSTATDATA **ppenumAdvise);

  HRESULT SendOnDataChange(
    [in, unique] IDataObject *pDataObject,
    [in] DWORD dwReserved,
    [in] DWORD advf);
}

/******************** Remoting ********************/

[
  local,
  object,
  uuid(00000016-0000-0000-C000-000000000046)
]
interface IMessageFilter : IUnknown
{
  typedef [unique] IMessageFilter *LPMESSAGEFILTER;

  typedef enum tagCALLTYPE {
    CALLTYPE_TOPLEVEL = 1,
    CALLTYPE_NESTED   = 2,
    CALLTYPE_ASYNC    = 3,
    CALLTYPE_TOPLEVEL_CALLPENDING = 4,
    CALLTYPE_ASYNC_CALLPENDING    = 5
  } CALLTYPE;

  typedef enum tagSERVERCALL {
    SERVERCALL_ISHANDLED  = 0,
    SERVERCALL_REJECTED   = 1,
    SERVERCALL_RETRYLATER = 2
  } SERVERCALL;

  typedef enum tagPENDINGTYPE {
    PENDINGTYPE_TOPLEVEL = 1,
    PENDINGTYPE_NESTED   = 2
  } PENDINGTYPE;

  typedef enum tagPENDINGMSG {
    PENDINGMSG_CANCELCALL     = 0,
    PENDINGMSG_WAITNOPROCESS  = 1,
    PENDINGMSG_WAITDEFPROCESS = 2
  } PENDINGMSG;

  typedef struct tagINTERFACEINFO {
    IUnknown *pUnk;
    IID iid;
    WORD wMethod;
  } INTERFACEINFO, *LPINTERFACEINFO;

  DWORD HandleInComingCall(
    [in] DWORD dwCallType,
    [in] HTASK htaskCaller,
    [in] DWORD dwTickCount,
    [in] LPINTERFACEINFO lpInterfaceInfo);

  DWORD RetryRejectedCall(
    [in] HTASK htaskCallee,
    [in] DWORD dwTickCount,
    [in] DWORD dwRejectType);

  DWORD MessagePending(
    [in] HTASK htaskCallee,
    [in] DWORD dwTickCount,
    [in] DWORD dwPendingType);
}

[
  local,
  object,
  uuid(D5F56B60-593B-101A-B569-08002B2DBF7A)
]
interface IRpcChannelBuffer : IUnknown
{
  typedef [unique] IRpcChannelBuffer *LPRPCCHANNELBUFFER;

  typedef unsigned long RPCOLEDATAREP;

  typedef struct tagRPCOLEMESSAGE {
    void *reserved1;
    RPCOLEDATAREP dataRepresentation;
    void *Buffer;
    ULONG cbBuffer;
    ULONG iMethod;
    void *reserved2[5];
    ULONG rpcFlags;
  } RPCOLEMESSAGE;

  typedef RPCOLEMESSAGE *PRPCOLEMESSAGE;

  HRESULT GetBuffer(
    [in] RPCOLEMESSAGE *pMessage,
    [in] REFIID riid);

  HRESULT SendReceive(
    [in,out] RPCOLEMESSAGE *pMessage,
    [out] ULONG *pStatus);

  HRESULT FreeBuffer(
    [in] RPCOLEMESSAGE *pMessage);

  HRESULT GetDestCtx(
    [out] DWORD *pdwDestContext,
    [out] void **ppvDestContext);

  HRESULT IsConnected();
}

[
  local,
  object,
  uuid(594f31d0-7f19-11d0-b194-00a0c90dc8bf)
]
interface IRpcChannelBuffer2 : IRpcChannelBuffer
{
  typedef [unique] IRpcChannelBuffer2 *LPRPCCHANNELBUFFER2;

  HRESULT GetProtocolVersion(
    [in,out] DWORD *pdwVersion);
}

[
  local,
  object,
  uuid(25B15600-0115-11d0-BF0D-00AA00B8DFD2)
]
interface IRpcChannelBuffer3 : IRpcChannelBuffer2
{
  typedef [unique] IRpcChannelBuffer3 *LPRPCCHANNELBUFFER3;

  HRESULT Send(
    [in,out] RPCOLEMESSAGE *pMsg,
    [out] ULONG *pulStatus);

  HRESULT Receive(
    [in,out] RPCOLEMESSAGE *pMsg,
    [in] ULONG ulSize,
    [out] ULONG *pulStatus);

  HRESULT Cancel(
    [in] RPCOLEMESSAGE *pMsg);

  HRESULT GetCallContext(
    [in] RPCOLEMESSAGE *pMsg,
    [in] REFIID riid,
    [out] void **pInterface);

  HRESULT GetDestCtxEx(
    [in] RPCOLEMESSAGE *pMsg,
    [out] DWORD *pdwDestContext,
    [out] void **ppvDestContext);

  HRESULT GetState(
    [in] RPCOLEMESSAGE *pMsg,
    [out] DWORD *pState);

  HRESULT RegisterAsync(
    [in] RPCOLEMESSAGE *pMsg,
    [in] IAsyncManager *pAsyncMgr);
}

[
  local,
  object,
  uuid(D5F56A34-593B-101A-B569-08002B2DBF7A)
]
interface IRpcProxyBuffer : IUnknown
{
  typedef [unique] IRpcProxyBuffer *LPRPCPROXYBUFFER;

  HRESULT Connect(
    [in, unique] IRpcChannelBuffer *pRpcChannelBuffer);

  void Disconnect();
}

[
  local,
  object,
  uuid(D5F56AFC-593B-101A-B569-08002B2DBF7A)
]
interface IRpcStubBuffer : IUnknown
{
  typedef [unique] IRpcStubBuffer *LPRPCSTUBBUFFER;

  HRESULT Connect(
    [in] IUnknown *pUnkServer);

  void Disconnect();

  HRESULT Invoke(
    [in] RPCOLEMESSAGE *_prpcmsg,
    [in] IRpcChannelBuffer *_pRpcChannelBuffer);

  IRpcStubBuffer *IsIIDSupported(
    [in] REFIID riid);

  ULONG CountRefs();

  HRESULT DebugServerQueryInterface(
    void **ppv);

  void DebugServerRelease(
    void *pv);
}

[
  local,
  object,
  uuid(D5F569D0-593B-101A-B569-08002B2DBF7A)
]
interface IPSFactoryBuffer : IUnknown
{
  typedef [unique] IPSFactoryBuffer *LPPSFACTORYBUFFER;

  HRESULT CreateProxy(
    [in] IUnknown *pUnkOuter,
    [in] REFIID riid,
    [out] IRpcProxyBuffer **ppProxy,
    [out] void **ppv);

  HRESULT CreateStub(
    [in] REFIID riid,
    [in, unique] IUnknown *pUnkServer,
    [out] IRpcStubBuffer **ppStub);
}

[
  local,
  object,
  uuid(1008c4a0-7613-11cf-9af1-0020af6e72f4)
]
interface IChannelHook : IUnknown
{
  typedef [unique] IChannelHook *LPCHANNELHOOK;

  typedef struct SChannelHookCallInfo {
    IID iid;
    DWORD cbSize;
    GUID uCausality;
    DWORD dwServerPid;
    DWORD iMethod;
    void *pObject;
  } SChannelHookCallInfo;

  void ClientGetSize(
    [in] REFGUID uExtent,
    [in] REFIID riid,
    [out] ULONG *pDataSize);

  void ClientFillBuffer(
    [in] REFGUID uExtent,
    [in] REFIID riid,
    [in, out] ULONG *pDataSize,
    [in] void *pDataBuffer);

  void ClientNotify(
    [in] REFGUID uExtent,
    [in] REFIID riid,
    [in] ULONG cbDataSize,
    [in] void *pDataBuffer,
    [in] DWORD lDataRep,
    [in] HRESULT hrFault);

  void ServerNotify(
    [in] REFGUID uExtent,
    [in] REFIID riid,
    [in] ULONG cbDataSize,
    [in] void *pDataBuffer,
    [in] DWORD lDataRep);

  void ServerGetSize(
    [in] REFGUID uExtent,
    [in] REFIID riid,
    [in] HRESULT hrFault,
    [out] ULONG *pDataSize);

  void ServerFillBuffer(
    [in] REFGUID uExtent,
    [in] REFIID riid,
    [in, out] ULONG *pDataSize,
    [in] void *pDataBuffer,
    [in] HRESULT hrFault );
}

/******************** Property Storage ********************/

interface IEnumSTATPROPSTG;
interface IEnumSTATPROPSETSTG;

[
  object,
  uuid(00000138-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IPropertyStorage : IUnknown
{
  typedef [unique] IPropertyStorage *LPPROPERTYSTORAGE;

  extern const FMTID FMTID_SummaryInformation;
  extern const FMTID FMTID_DocSummaryInformation;
  extern const FMTID FMTID_UserDefinedProperties;

  const DWORD PROPSETFLAG_DEFAULT = 0;
  const DWORD PROPSETFLAG_NONSIMPLE = 1;
  const DWORD PROPSETFLAG_ANSI = 2;
  const DWORD PROPSETFLAG_UNBUFFERED = 4;

  typedef struct tagPROPVARIANT PROPVARIANT;

  #define TYPEDEF_CA(type, name) \
    typedef struct tag##name { \
      ULONG cElems; \
      [size_is(cElems)] \
      type *pElems; \
    } name

  TYPEDEF_CA(unsigned char, CAUB);
  TYPEDEF_CA(short, CAI);
  TYPEDEF_CA(USHORT, CAUI);
  TYPEDEF_CA(long, CAL);
  TYPEDEF_CA(ULONG, CAUL);
  TYPEDEF_CA(float, CAFLT);
  TYPEDEF_CA(double, CADBL);
  TYPEDEF_CA(CY, CACY);
  TYPEDEF_CA(DATE, CADATE);
  TYPEDEF_CA(BSTR, CABSTR);
  TYPEDEF_CA(BSTRBLOB, CABSTRBLOB);
  TYPEDEF_CA(VARIANT_BOOL, CABOOL);
  TYPEDEF_CA(SCODE,  CASCODE);
  TYPEDEF_CA(PROPVARIANT, CAPROPVARIANT);
  TYPEDEF_CA(LARGE_INTEGER, CAH);
  TYPEDEF_CA(ULARGE_INTEGER, CAUH);
  TYPEDEF_CA(LPSTR, CALPSTR);
  TYPEDEF_CA(LPWSTR, CALPWSTR);
  TYPEDEF_CA(FILETIME, CAFILETIME);
  TYPEDEF_CA(CLIPDATA, CACLIPDATA);
  TYPEDEF_CA(CLSID, CACLSID);

  struct tagPROPVARIANT {
    VARTYPE vt;
    WORD wReserved1;
    WORD wReserved2;
    WORD wReserved3;
    [switch_is(vt & 0x1fff)] union {
    [case(VT_EMPTY, VT_NULL)]             ;
    [case(VT_I1)]                         char cVal;
    [case(VT_UI1)]                        UCHAR bVal;
    [case(VT_I2)]                         short iVal;
    [case(VT_UI2)]                        USHORT uiVal;
    [case(VT_BOOL)]                       VARIANT_BOOL boolVal;
#if 0 /* illegal in C++ */
    [case(VT_ILLEGAL)]                    _VARIANT_BOOL bool;
#endif
    [case(VT_I4)]                         long lVal;
    [case(VT_UI4)]                        ULONG ulVal;
    [case(VT_R4)]                         float fltVal;
    [case(VT_ERROR)]                      SCODE scode;
    [case(VT_I8)]                         LARGE_INTEGER hVal;
    [case(VT_UI8)]                        ULARGE_INTEGER uhVal;
    [case(VT_R8)]                         double dblVal;
    [case(VT_CY)]                         CY cyVal;
    [case(VT_DATE)]                       DATE date;
    [case(VT_FILETIME)]                   FILETIME filetime;
    [case(VT_CLSID)]                      CLSID *puuid;
    [case(VT_BLOB, VT_BLOB_OBJECT)]       BLOB blob;
    [case(VT_CF)]                         CLIPDATA *pclipdata;
    [case(VT_STREAM, VT_STREAMED_OBJECT)] IStream *pStream;
    [case(VT_STORAGE, VT_STORED_OBJECT)]  IStorage *pStorage;
    [case(VT_BSTR)]                       BSTR bstrVal;
    [case(VT_BSTR_BLOB)]                  BSTRBLOB bstrblobVal;
    [case(VT_LPSTR)]                      LPSTR pszVal;
    [case(VT_LPWSTR)]                     LPWSTR pwszVal;
    [case(VT_UI1|VT_VECTOR)]              CAUB caub;
    [case(VT_I2|VT_VECTOR)]               CAI cai;
    [case(VT_UI2|VT_VECTOR)]              CAUI caui;
    [case(VT_BOOL|VT_VECTOR)]             CABOOL cabool;
    [case(VT_I4|VT_VECTOR)]               CAL cal;
    [case(VT_UI4|VT_VECTOR)]              CAUL caul;
    [case(VT_R4|VT_VECTOR)]               CAFLT caflt;
    [case(VT_ERROR|VT_VECTOR)]            CASCODE cascode;
    [case(VT_I8|VT_VECTOR)]               CAH cah;
    [case(VT_UI8|VT_VECTOR)]              CAUH cauh;
    [case(VT_R8|VT_VECTOR)]               CADBL cadbl;
    [case(VT_CY|VT_VECTOR)]               CACY cacy;
    [case(VT_DATE|VT_VECTOR)]             CADATE cadate;
    [case(VT_FILETIME|VT_VECTOR)]         CAFILETIME cafiletime;
    [case(VT_CLSID|VT_VECTOR)]            CACLSID cauuid;
    [case(VT_CF|VT_VECTOR)]               CACLIPDATA caclipdata;
    [case(VT_BSTR|VT_VECTOR)]             CABSTR cabstr;
    [case(VT_BSTR_BLOB|VT_VECTOR)]        CABSTRBLOB cabstrblob;
    [case(VT_LPSTR|VT_VECTOR)]            CALPSTR calpstr;
    [case(VT_LPWSTR|VT_VECTOR)]           CALPWSTR calpwstr;
    [case(VT_VARIANT|VT_VECTOR)]          CAPROPVARIANT capropvar;
    };
  };

  typedef struct tagPROPVARIANT *LPPROPVARIANT;

  /* FIXME: bunches of property IDs */

  const ULONG PRSPEC_INVALID = 0xffffffff;
  const ULONG PRSPEC_LPWSTR = 0;
  const ULONG PRSPEC_PROPID = 1;

  typedef struct tagPROPSPEC {
    ULONG ulKind;
    [switch_is(ulKind)] union {
    [case(PRSPEC_PROPID)] PROPID propid;
    [case(PRSPEC_LPWSTR)] LPOLESTR lpwstr;
    [default]             ;
    };
  } PROPSPEC;

  typedef struct tagSTATPROPSTG {
    LPOLESTR lpwstrName;
    PROPID propid;
    VARTYPE vt;
  } STATPROPSTG;

  /* FIXME: macros */

  typedef struct tagSTATPROPSETSTG {
    FMTID fmtid;
    CLSID clsid;
    DWORD grfFlags;
    FILETIME mtime;
    FILETIME ctime;
    FILETIME atime;
    DWORD dwOSVersion;
  } STATPROPSETSTG;

  HRESULT ReadMultiple(
    [in] ULONG cpspec,
    [in, size_is(cpspec)] const PROPSPEC rgpspec[],
    [out, size_is(cpspec)] PROPVARIANT rgpropvar[]);

  HRESULT WriteMultiple(
    [in] ULONG cpspec,
    [in, size_is(cpspec)] const PROPSPEC rgpspec[],
    [in, size_is(cpspec)] const PROPVARIANT rgpropvar[],
    [in] PROPID propidNameFirst);

  HRESULT DeleteMultiple(
    [in] ULONG cpspec,
    [in, size_is(cpspec)] const PROPSPEC rgpspec[]);

  HRESULT ReadPropertyNames(
    [in] ULONG cpropid,
    [in, size_is(cpropid)] const PROPID rgpropid[],
    [out, size_is(cpropid)] LPOLESTR rglpwstrName[]);

  HRESULT WritePropertyNames(
    [in] ULONG cpropid,
    [in, size_is(cpropid)] const PROPID rgpropid[],
    [in, size_is(cpropid)] const LPOLESTR rglpwstrName[]);

  HRESULT DeletePropertyNames(
    [in] ULONG cpropid,
    [in, size_is(cpropid)] const PROPID rgpropid[]);

  HRESULT Commit(
    [in] DWORD grfCommitFlags);

  HRESULT Revert();

  HRESULT Enum(
    [out] IEnumSTATPROPSTG **ppenum);

  HRESULT SetTimes(
    [in] const FILETIME *pctime,
    [in] const FILETIME *patime,
    [in] const FILETIME *pmtime);

  HRESULT SetClass(
    [in] REFCLSID clsid);

  HRESULT Stat(
    [out] STATPROPSETSTG *statpsstg);
}

[
  object,
  uuid(0000013A-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IPropertySetStorage : IUnknown
{
  typedef [unique] IPropertySetStorage *LPPROPERTYSETSTORAGE;

  HRESULT Create(
    [in] REFFMTID rfmtid,
    [in, unique] const CLSID *pclsid,
    [in] DWORD grfFlags,
    [in] DWORD grfMode,
    [out] IPropertyStorage **ppprstg);

  HRESULT Open(
    [in] REFFMTID rfmtid,
    [in] DWORD grfMode,
    [out] IPropertyStorage **ppprstg);

  HRESULT Delete(
    [in] REFFMTID rfmtid);

  HRESULT Enum(
    [out] IEnumSTATPROPSETSTG **ppenum);
}

[
  object,
  uuid(00000139-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumSTATPROPSTG : IUnknown
{
  typedef [unique] IEnumSTATPROPSTG *LPENUMSTATPROPSTG;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATPROPSTG *rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATPROPSTG *rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumSTATPROPSTG **ppenum);
}

[
  object,
  uuid(0000013B-0000-0000-C000-000000000046),
  pointer_default(unique)
]
interface IEnumSTATPROPSETSTG : IUnknown
{
  typedef [unique] IEnumSTATPROPSETSTG *LPENUMSTATPROPSETSTG;

  [local]
  HRESULT Next(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATPROPSETSTG *rgelt,
    [out] ULONG *pceltFetched);

  [call_as(Next)]
  HRESULT RemoteNext(
    [in] ULONG celt,
    [out, size_is(celt), length_is(*pceltFetched)]
    STATPROPSETSTG *rgelt,
    [out] ULONG *pceltFetched);

  HRESULT Skip(
    [in] ULONG celt);

  HRESULT Reset();

  HRESULT Clone(
    [out] IEnumSTATPROPSETSTG **ppenum);
}

/******************** Connection Points ********************/
/* FIXME */

/******************** DCOM ********************/

[
  local,
  object,
  uuid(0000013D-0000-0000-C000-000000000046)
]
interface IClientSecurity : IUnknown
{
  typedef struct tagSOLE_AUTHENTICATION_SERVICE {
    DWORD dwAuthnSvc;
    DWORD dwAuthzSvc;
    OLECHAR *pPrincipalName;
    HRESULT hr;
  } SOLE_AUTHENTICATION_SERVICE;

  typedef SOLE_AUTHENTICATION_SERVICE *PSOLE_AUTHENTICATION_SERVICE;

  typedef enum tagEOLE_AUTHENTICATION_CAPABILITIES {
    EOAC_NONE           = 0x0,
    EOAC_MUTUAL_AUTH    = 0x1,
    EOAC_CLOAKING       = 0x10,
    EOAC_SECURE_REFS    = 0x2,
    EOAC_ACCESS_CONTROL = 0x4,
    EOAC_APPID          = 0x8
  } EOLE_AUTHENTICATION_CAPABILITIES;

  HRESULT QueryBlanket(
    [in] IUnknown *pProxy,
    [out] DWORD *pAuthnSvc,
    [out] DWORD *pAuthzSvc,
    [out] OLECHAR **pServerPrincName,
    [out] DWORD *pAuthnLevel,
    [out] DWORD *pImpLevel,
    [out] void **pAuthInfo,
    [out] DWORD *pCapabilites);

  HRESULT SetBlanket(
    [in] IUnknown *pProxy,
    [in] DWORD AuthnSvc,
    [in] DWORD AuthzSvc,
    [in] OLECHAR *pServerPrincName,
    [in] DWORD AuthnLevel,
    [in] DWORD ImpLevel,
    [in] void *pAuthInfo,
    [in] DWORD Capabilities);

  HRESULT CopyProxy(
    [in] IUnknown *pProxy,
    [out] IUnknown **ppCopy);
}

[
  local,
  object,
  uuid(0000013E-0000-0000-C000-000000000046)
]
interface IServerSecurity : IUnknown
{
  HRESULT QueryBlanket(
    [out] DWORD *pAuthnSvc,
    [out] DWORD *pAuthzSvc,
    [out] OLECHAR **pServerPrincName,
    [out] DWORD *pAuthnLevel,
    [out] DWORD *pImpLevel,
    [out] void **pPrivs,
    [out] DWORD *pCapabilities);

  HRESULT ImpersonateClient();

  HRESULT RevertToSelf();

  BOOL IsImpersonating();
}

[
  local,
  object,
  uuid(00000024-0000-0000-C000-000000000046)
]
interface IAsyncSetup : IUnknown
{
  HRESULT GetAsyncManager(
    [in] REFIID riid,
    [in] IUnknown *pOuter,
    [in] DWORD dwFlags,
    [out] IUnknown **ppInner,
    [out] IAsyncManager **ppAsyncMgr);
}

[
  local,
  object,
  uuid(0000002A-0000-0000-C000-000000000046)
]
interface IAsyncManager : IUnknown
{
  typedef enum tagDCOM_CALL_STATE {
    DCOM_NONE          = 0,
    DCOM_CALL_COMPLETE = 1,
    DCOM_CALL_CANCELED = 2
  } DCOM_CALL_STATE;

  HRESULT CompleteCall(
    [in] HRESULT Result);
  HRESULT GetCallContext(
    [in] REFIID riid,
    [out] void **pInterface);
  HRESULT GetState(
    [out] ULONG *pulStateFlags);
}
