FILETIME mtime;
FILETIME ctime;
FILETIME atime;
+ DWORD dwOSVersion;
} STATPROPSETSTG;
typedef enum tagEXTCONN {
EXTCONN_STRONG=1,
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
STDMETHOD(ReadMultiple)(THIS_ ULONG,PROPSPEC const*,PROPVARIANT*) PURE;
- STDMETHOD(WriteMultiple)(THIS_ ULONG,PROPSPEC const*,PROPVARIANT*,PROPID) PURE;
+ STDMETHOD(WriteMultiple)(THIS_ ULONG,const PROPSPEC *,const PROPVARIANT *,PROPID) PURE;
STDMETHOD(DeleteMultiple)(THIS_ ULONG,PROPSPEC const*) PURE;
STDMETHOD(ReadPropertyNames)(THIS_ ULONG,PROPID const*,LPWSTR*) PURE;
STDMETHOD(WritePropertyNames)(THIS_ ULONG,PROPID const*,LPWSTR const*) PURE;
STDMETHOD(DeletePropertyNames)(THIS_ ULONG,PROPID const*) PURE;
- STDMETHOD(SetClass)(THIS_ REFCLSID) PURE;
STDMETHOD(Commit)(THIS_ DWORD) PURE;
STDMETHOD(Revert)(THIS) PURE;
STDMETHOD(Enum)(THIS_ IEnumSTATPROPSTG**) PURE;
- STDMETHOD(Stat)(THIS_ STATPROPSTG*) PURE;
STDMETHOD(SetTimes)(THIS_ FILETIME const*,FILETIME const*,FILETIME const*) PURE;
+ STDMETHOD(SetClass)(THIS_ REFCLSID) PURE;
+ STDMETHOD(Stat)(THIS_ STATPROPSETSTG*) PURE;
};
#undef INTERFACE
STDMETHOD(QueryInterface)(THIS_ REFIID,PVOID*) PURE;
STDMETHOD_(ULONG,AddRef)(THIS) PURE;
STDMETHOD_(ULONG,Release)(THIS) PURE;
- STDMETHOD(Create)(THIS_ REFFMTID,CLSID*,DWORD,DWORD,LPPROPERTYSTORAGE*) PURE;
+ STDMETHOD(Create)(THIS_ REFFMTID,const CLSID*,DWORD,DWORD,LPPROPERTYSTORAGE*) PURE;
STDMETHOD(Open)(THIS_ REFFMTID,DWORD,LPPROPERTYSTORAGE*) PURE;
STDMETHOD(Delete)(THIS_ REFFMTID) PURE;
STDMETHOD(Enum)(THIS_ IEnumSTATPROPSETSTG**) PURE;
VPATH = @srcdir@\r
MODULE = ole32.dll\r
IMPORTS = advapi32 user32 gdi32 rpcrt4 kernel32 ntdll\r
-EXTRALIBS = -luuid\r
+EXTRALIBS = -luuid $(LIBUNICODE)\r
\r
C_SRCS = \\r
antimoniker.c \\r
compositemoniker.c \\r
datacache.c \\r
defaulthandler.c \\r
+ dictionary.c \\r
errorinfo.c \\r
filemoniker.c \\r
ftmarshal.c \\r
#include "windef.h"\r
#include "winbase.h"\r
#include "winerror.h"\r
-#include "wine/unicode.h"\r
#include "objbase.h"\r
#include "wine/debug.h"\r
#include "moniker.h"\r
\r
} AntiMonikerImpl;\r
\r
-/********************************************************************************/\r
-/* AntiMoniker prototype functions : */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);\r
-static ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker* iface);\r
-static ULONG WINAPI AntiMonikerImpl_Release(IMoniker* iface);\r
-\r
-/* IPersist prototype functions */\r
-static HRESULT WINAPI AntiMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);\r
-\r
-/* IPersistStream prototype functions */\r
-static HRESULT WINAPI AntiMonikerImpl_IsDirty(IMoniker* iface);\r
-static HRESULT WINAPI AntiMonikerImpl_Load(IMoniker* iface, IStream* pStm);\r
-static HRESULT WINAPI AntiMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);\r
-static HRESULT WINAPI AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);\r
-\r
-/* IMoniker prototype functions */\r
-static HRESULT WINAPI AntiMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI AntiMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI AntiMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);\r
-static HRESULT WINAPI AntiMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);\r
-static HRESULT WINAPI AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);\r
-static HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);\r
-static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);\r
-static HRESULT WINAPI AntiMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);\r
-static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pAntiTime);\r
-static HRESULT WINAPI AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);\r
-static HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);\r
-static HRESULT WINAPI AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);\r
-static HRESULT WINAPI AntiMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);\r
-static HRESULT WINAPI AntiMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);\r
-static HRESULT WINAPI AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);\r
-\r
-/********************************************************************************/\r
-/* IROTData prototype functions */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI AntiMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);\r
-static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData* iface);\r
-static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface);\r
-\r
-/* IROTData prototype function */\r
-static HRESULT WINAPI AntiMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);\r
-\r
-/* Local function used by AntiMoniker implementation */\r
-HRESULT WINAPI AntiMonikerImpl_Construct(AntiMonikerImpl* iface);\r
-HRESULT WINAPI AntiMonikerImpl_Destroy(AntiMonikerImpl* iface);\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the AntiMonikerImpl class which include IPersist,*/\r
-/* IPersistStream and IMoniker functions. */\r
-static IMonikerVtbl VT_AntiMonikerImpl =\r
-{\r
- AntiMonikerImpl_QueryInterface,\r
- AntiMonikerImpl_AddRef,\r
- AntiMonikerImpl_Release,\r
- AntiMonikerImpl_GetClassID,\r
- AntiMonikerImpl_IsDirty,\r
- AntiMonikerImpl_Load,\r
- AntiMonikerImpl_Save,\r
- AntiMonikerImpl_GetSizeMax,\r
- AntiMonikerImpl_BindToObject,\r
- AntiMonikerImpl_BindToStorage,\r
- AntiMonikerImpl_Reduce,\r
- AntiMonikerImpl_ComposeWith,\r
- AntiMonikerImpl_Enum,\r
- AntiMonikerImpl_IsEqual,\r
- AntiMonikerImpl_Hash,\r
- AntiMonikerImpl_IsRunning,\r
- AntiMonikerImpl_GetTimeOfLastChange,\r
- AntiMonikerImpl_Inverse,\r
- AntiMonikerImpl_CommonPrefixWith,\r
- AntiMonikerImpl_RelativePathTo,\r
- AntiMonikerImpl_GetDisplayName,\r
- AntiMonikerImpl_ParseDisplayName,\r
- AntiMonikerImpl_IsSystemMoniker\r
-};\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the IROTData class. */\r
-static IROTDataVtbl VT_ROTDataImpl =\r
-{\r
- AntiMonikerROTDataImpl_QueryInterface,\r
- AntiMonikerROTDataImpl_AddRef,\r
- AntiMonikerROTDataImpl_Release,\r
- AntiMonikerROTDataImpl_GetComparaisonData\r
-};\r
\r
/*******************************************************************************\r
* AntiMoniker_QueryInterface\r
*******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)\r
{\r
AntiMonikerImpl *This = (AntiMonikerImpl *)iface;\r
\r
- TRACE("(%p,%p,%p)\n",This,riid,ppvObject);\r
+ TRACE("(%p,%p,%p)\n",This,riid,ppvObject);\r
\r
- /* Perform a sanity check on the parameters.*/\r
+ /* Perform a sanity check on the parameters.*/\r
if ( (This==0) || (ppvObject==0) )\r
return E_INVALIDARG;\r
\r
- /* Initialize the return parameter */\r
- *ppvObject = 0;\r
+ /* Initialize the return parameter */\r
+ *ppvObject = 0;\r
\r
- /* Compare the riid with the interface IDs implemented by this object.*/\r
- if (IsEqualIID(&IID_IUnknown, riid) ||\r
- IsEqualIID(&IID_IPersist, riid) ||\r
- IsEqualIID(&IID_IPersistStream, riid) ||\r
- IsEqualIID(&IID_IMoniker, riid)\r
- )\r
- *ppvObject = iface;\r
+ /* Compare the riid with the interface IDs implemented by this object.*/\r
+ if (IsEqualIID(&IID_IUnknown, riid) ||\r
+ IsEqualIID(&IID_IPersist, riid) ||\r
+ IsEqualIID(&IID_IPersistStream, riid) ||\r
+ IsEqualIID(&IID_IMoniker, riid))\r
+ *ppvObject = iface;\r
else if (IsEqualIID(&IID_IROTData, riid))\r
*ppvObject = (IROTData*)&(This->lpvtbl2);\r
\r
- /* Check that we obtained an interface.*/\r
+ /* Check that we obtained an interface.*/\r
if ((*ppvObject)==0)\r
return E_NOINTERFACE;\r
\r
- /* Query Interface always increases the reference count by one when it is successful */\r
- AntiMonikerImpl_AddRef(iface);\r
+ /* always increase the reference count by one when it is successful */\r
+ IMoniker_AddRef(iface);\r
\r
- return S_OK;\r
+ return S_OK;\r
}\r
\r
/******************************************************************************\r
* AntiMoniker_AddRef\r
******************************************************************************/\r
-ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker* iface)\r
+static ULONG WINAPI\r
+AntiMonikerImpl_AddRef(IMoniker* iface)\r
{\r
AntiMonikerImpl *This = (AntiMonikerImpl *)iface;\r
\r
/******************************************************************************\r
* AntiMoniker_Release\r
******************************************************************************/\r
-ULONG WINAPI AntiMonikerImpl_Release(IMoniker* iface)\r
+static ULONG WINAPI\r
+AntiMonikerImpl_Release(IMoniker* iface)\r
{\r
AntiMonikerImpl *This = (AntiMonikerImpl *)iface;\r
ULONG ref;\r
ref = InterlockedDecrement(&This->ref);\r
\r
/* destroy the object if there's no more reference on it */\r
- if (ref == 0) AntiMonikerImpl_Destroy(This);\r
+ if (ref == 0) HeapFree(GetProcessHeap(),0,This);\r
\r
return ref;\r
}\r
/******************************************************************************\r
* AntiMoniker_GetClassID\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)\r
{\r
TRACE("(%p,%p),stub!\n",iface,pClassID);\r
\r
/******************************************************************************\r
* AntiMoniker_IsDirty\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_IsDirty(IMoniker* iface)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_IsDirty(IMoniker* iface)\r
{\r
/* Note that the OLE-provided implementations of the IPersistStream::IsDirty\r
method in the OLE-provided moniker interfaces always return S_FALSE because\r
/******************************************************************************\r
* AntiMoniker_Load\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Load(IMoniker* iface,IStream* pStm)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_Load(IMoniker* iface,IStream* pStm)\r
{\r
DWORD constant=1,dwbuffer;\r
HRESULT res;\r
/******************************************************************************\r
* AntiMoniker_Save\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)\r
{\r
DWORD constant=1;\r
HRESULT res;\r
\r
/******************************************************************************\r
* AntiMoniker_GetSizeMax\r
+ *\r
+ * PARAMS\r
+ * pcbSize [out] Pointer to size of stream needed to save object\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_GetSizeMax(IMoniker* iface,\r
- ULARGE_INTEGER* pcbSize)/* Pointer to size of stream needed to save object */\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)\r
{\r
TRACE("(%p,%p)\n",iface,pcbSize);\r
\r
\r
/* for more details see AntiMonikerImpl_Save coments */\r
\r
- /* Normaly the sizemax must be the size of DWORD ! but I tested this function it ususlly return 16 bytes */\r
- /* more than the number of bytes used by AntiMoniker::Save function */\r
+ /*\r
+ * Normally the sizemax must be sizeof DWORD, but\r
+ * I tested this function it usually return 16 bytes\r
+ * more than the number of bytes used by AntiMoniker::Save function\r
+ */\r
pcbSize->u.LowPart = sizeof(DWORD)+16;\r
\r
pcbSize->u.HighPart=0;\r
return S_OK;\r
}\r
\r
-/******************************************************************************\r
- * AntiMoniker_Construct (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Construct(AntiMonikerImpl* This)\r
-{\r
-\r
- TRACE("(%p)\n",This);\r
-\r
- /* Initialize the virtual fgunction table. */\r
- This->lpvtbl1 = &VT_AntiMonikerImpl;\r
- This->lpvtbl2 = &VT_ROTDataImpl;\r
- This->ref = 0;\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * AntiMoniker_Destroy (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Destroy(AntiMonikerImpl* This)\r
-{\r
- TRACE("(%p)\n",This);\r
-\r
- return HeapFree(GetProcessHeap(),0,This);\r
-}\r
-\r
/******************************************************************************\r
* AntiMoniker_BindToObject\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_BindToObject(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvResult)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,\r
+ REFIID riid, VOID** ppvResult)\r
{\r
TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);\r
return E_NOTIMPL;\r
/******************************************************************************\r
* AntiMoniker_BindToStorage\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_BindToStorage(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvResult)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,\r
+ REFIID riid, VOID** ppvResult)\r
{\r
TRACE("(%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,riid,ppvResult);\r
return E_NOTIMPL;\r
/******************************************************************************\r
* AntiMoniker_Reduce\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Reduce(IMoniker* iface,\r
- IBindCtx* pbc,\r
- DWORD dwReduceHowFar,\r
- IMoniker** ppmkToLeft,\r
- IMoniker** ppmkReduced)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,\r
+ IMoniker** ppmkToLeft, IMoniker** ppmkReduced)\r
{\r
TRACE("(%p,%p,%ld,%p,%p)\n",iface,pbc,dwReduceHowFar,ppmkToLeft,ppmkReduced);\r
\r
/******************************************************************************\r
* AntiMoniker_ComposeWith\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_ComposeWith(IMoniker* iface,\r
- IMoniker* pmkRight,\r
- BOOL fOnlyIfNotGeneric,\r
- IMoniker** ppmkComposite)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,\r
+ BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)\r
{\r
\r
TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);\r
/******************************************************************************\r
* AntiMoniker_Enum\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)\r
{\r
TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);\r
\r
/******************************************************************************\r
* AntiMoniker_IsEqual\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)\r
{\r
DWORD mkSys;\r
\r
/******************************************************************************\r
* AntiMoniker_Hash\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
+static HRESULT WINAPI AntiMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
{\r
if (pdwHash==NULL)\r
return E_POINTER;\r
/******************************************************************************\r
* AntiMoniker_IsRunning\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_IsRunning(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- IMoniker* pmkNewlyRunning)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,\r
+ IMoniker* pmkNewlyRunning)\r
{\r
IRunningObjectTable* rot;\r
HRESULT res;\r
res=IBindCtx_GetRunningObjectTable(pbc,&rot);\r
\r
if (FAILED(res))\r
- return res;\r
+ return res;\r
\r
res = IRunningObjectTable_IsRunning(rot,iface);\r
\r
/******************************************************************************\r
* AntiMoniker_GetTimeOfLastChange\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,\r
+static HRESULT WINAPI AntiMonikerImpl_GetTimeOfLastChange(IMoniker* iface,\r
IBindCtx* pbc,\r
IMoniker* pmkToLeft,\r
FILETIME* pAntiTime)\r
/******************************************************************************\r
* AntiMoniker_Inverse\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)\r
{\r
TRACE("(%p,%p)\n",iface,ppmk);\r
\r
/******************************************************************************\r
* AntiMoniker_CommonPrefixWith\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)\r
{\r
DWORD mkSys;\r
\r
/******************************************************************************\r
* AntiMoniker_RelativePathTo\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)\r
{\r
TRACE("(%p,%p,%p)\n",iface,pmOther,ppmkRelPath);\r
\r
/******************************************************************************\r
* AntiMoniker_GetDisplayName\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_GetDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR *ppszDisplayName)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)\r
{\r
static const WCHAR back[]={'\\','.','.',0};\r
\r
if (*ppszDisplayName==NULL)\r
return E_OUTOFMEMORY;\r
\r
- strcpyW(*ppszDisplayName,back);\r
+ lstrcpyW(*ppszDisplayName,back);\r
\r
return S_OK;\r
}\r
/******************************************************************************\r
* AntiMoniker_ParseDisplayName\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_ParseDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR pszDisplayName,\r
- ULONG* pchEaten,\r
- IMoniker** ppmkOut)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, LPOLESTR pszDisplayName,\r
+ ULONG* pchEaten, IMoniker** ppmkOut)\r
{\r
TRACE("(%p,%p,%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,pszDisplayName,pchEaten,ppmkOut);\r
return E_NOTIMPL;\r
/******************************************************************************\r
* AntiMoniker_IsSystemMoniker\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)\r
+static HRESULT WINAPI\r
+AntiMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)\r
{\r
TRACE("(%p,%p)\n",iface,pwdMksys);\r
\r
/*******************************************************************************\r
* AntiMonikerIROTData_QueryInterface\r
*******************************************************************************/\r
-HRESULT WINAPI AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)\r
+static HRESULT WINAPI\r
+AntiMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)\r
{\r
-\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
\r
TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);\r
/***********************************************************************\r
* AntiMonikerIROTData_AddRef\r
*/\r
-ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)\r
+static ULONG WINAPI AntiMonikerROTDataImpl_AddRef(IROTData *iface)\r
{\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
\r
/***********************************************************************\r
* AntiMonikerIROTData_Release\r
*/\r
-ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)\r
+static ULONG WINAPI AntiMonikerROTDataImpl_Release(IROTData* iface)\r
{\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
\r
/******************************************************************************\r
* AntiMonikerIROTData_GetComparaisonData\r
******************************************************************************/\r
-HRESULT WINAPI AntiMonikerROTDataImpl_GetComparaisonData(IROTData* iface,\r
- BYTE* pbData,\r
- ULONG cbMax,\r
- ULONG* pcbData)\r
+static HRESULT WINAPI\r
+AntiMonikerROTDataImpl_GetComparaisonData(IROTData* iface, BYTE* pbData,\r
+ ULONG cbMax, ULONG* pcbData)\r
{\r
FIXME("(),stub!\n");\r
return E_NOTIMPL;\r
}\r
\r
+/********************************************************************************/\r
+/* Virtual function table for the AntiMonikerImpl class which include IPersist,*/\r
+/* IPersistStream and IMoniker functions. */\r
+static IMonikerVtbl VT_AntiMonikerImpl =\r
+{\r
+ AntiMonikerImpl_QueryInterface,\r
+ AntiMonikerImpl_AddRef,\r
+ AntiMonikerImpl_Release,\r
+ AntiMonikerImpl_GetClassID,\r
+ AntiMonikerImpl_IsDirty,\r
+ AntiMonikerImpl_Load,\r
+ AntiMonikerImpl_Save,\r
+ AntiMonikerImpl_GetSizeMax,\r
+ AntiMonikerImpl_BindToObject,\r
+ AntiMonikerImpl_BindToStorage,\r
+ AntiMonikerImpl_Reduce,\r
+ AntiMonikerImpl_ComposeWith,\r
+ AntiMonikerImpl_Enum,\r
+ AntiMonikerImpl_IsEqual,\r
+ AntiMonikerImpl_Hash,\r
+ AntiMonikerImpl_IsRunning,\r
+ AntiMonikerImpl_GetTimeOfLastChange,\r
+ AntiMonikerImpl_Inverse,\r
+ AntiMonikerImpl_CommonPrefixWith,\r
+ AntiMonikerImpl_RelativePathTo,\r
+ AntiMonikerImpl_GetDisplayName,\r
+ AntiMonikerImpl_ParseDisplayName,\r
+ AntiMonikerImpl_IsSystemMoniker\r
+};\r
+\r
+/********************************************************************************/\r
+/* Virtual function table for the IROTData class. */\r
+static IROTDataVtbl VT_ROTDataImpl =\r
+{\r
+ AntiMonikerROTDataImpl_QueryInterface,\r
+ AntiMonikerROTDataImpl_AddRef,\r
+ AntiMonikerROTDataImpl_Release,\r
+ AntiMonikerROTDataImpl_GetComparaisonData\r
+};\r
+\r
+/******************************************************************************\r
+ * AntiMoniker_Construct (local function)\r
+ *******************************************************************************/\r
+static HRESULT AntiMonikerImpl_Construct(AntiMonikerImpl* This)\r
+{\r
+\r
+ TRACE("(%p)\n",This);\r
+\r
+ /* Initialize the virtual fgunction table. */\r
+ This->lpvtbl1 = &VT_AntiMonikerImpl;\r
+ This->lpvtbl2 = &VT_ROTDataImpl;\r
+ This->ref = 0;\r
+\r
+ return S_OK;\r
+}\r
+\r
/******************************************************************************\r
* CreateAntiMoniker [OLE32.@]\r
******************************************************************************/\r
return STG_E_INSUFFICIENTMEMORY;\r
\r
hr = AntiMonikerImpl_Construct(newAntiMoniker);\r
-\r
- if (FAILED(hr)){\r
-\r
+ if (FAILED(hr))\r
+ {\r
HeapFree(GetProcessHeap(),0,newAntiMoniker);\r
return hr;\r
}\r
#include "winerror.h"\r
#include "windef.h"\r
#include "winbase.h"\r
-#include "wine/unicode.h"\r
#include "objbase.h"\r
#include "wine/debug.h"\r
\r
} BindCtxImpl;\r
\r
/* IBindCtx prototype functions : */\r
-\r
-/* IUnknown functions*/\r
-static HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject);\r
-static ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface);\r
-static ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface);\r
-/* IBindCtx functions */\r
-static HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk);\r
-static HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk);\r
-static HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface);\r
-static HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts);\r
-static HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts);\r
-static HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot);\r
-static HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk);\r
-static HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk);\r
-static HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** ppenum);\r
-static HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR pszkey);\r
-/* Local functions*/\r
-HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This);\r
-HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This);\r
-HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This,IUnknown* punk,LPOLESTR pszkey,DWORD *index);\r
-\r
-/* Virtual function table for the BindCtx class. */\r
-static IBindCtxVtbl VT_BindCtxImpl =\r
- {\r
- BindCtxImpl_QueryInterface,\r
- BindCtxImpl_AddRef,\r
- BindCtxImpl_Release,\r
- BindCtxImpl_RegisterObjectBound,\r
- BindCtxImpl_RevokeObjectBound,\r
- BindCtxImpl_ReleaseBoundObjects,\r
- BindCtxImpl_SetBindOptions,\r
- BindCtxImpl_GetBindOptions,\r
- BindCtxImpl_GetRunningObjectTable,\r
- BindCtxImpl_RegisterObjectParam,\r
- BindCtxImpl_GetObjectParam,\r
- BindCtxImpl_EnumObjectParam,\r
- BindCtxImpl_RevokeObjectParam\r
-};\r
+static HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx*);\r
+static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl*, IUnknown*, LPOLESTR, DWORD *);\r
\r
/*******************************************************************************\r
* BindCtx_QueryInterface\r
*******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject)\r
+static HRESULT WINAPI\r
+BindCtxImpl_QueryInterface(IBindCtx* iface,REFIID riid,void** ppvObject)\r
{\r
- BindCtxImpl *This = (BindCtxImpl *)iface;\r
-\r
- TRACE("(%p,%p,%p)\n",This,riid,ppvObject);\r
-\r
- /* Perform a sanity check on the parameters.*/\r
- if ( (This==0) || (ppvObject==0) )\r
- return E_INVALIDARG;\r
+ BindCtxImpl *This = (BindCtxImpl *)iface;\r
\r
- /* Initialize the return parameter.*/\r
- *ppvObject = 0;\r
+ TRACE("(%p,%p,%p)\n",This,riid,ppvObject);\r
\r
- /* Compare the riid with the interface IDs implemented by this object.*/\r
- if (IsEqualIID(&IID_IUnknown, riid))\r
- *ppvObject = (IBindCtx*)This;\r
- else\r
- if (IsEqualIID(&IID_IBindCtx, riid))\r
- *ppvObject = (IBindCtx*)This;\r
+ /* Perform a sanity check on the parameters.*/\r
+ if ( (This==0) || (ppvObject==0) )\r
+ return E_INVALIDARG;\r
\r
- /* Check that we obtained an interface.*/\r
- if ((*ppvObject)==0)\r
- return E_NOINTERFACE;\r
+ /* Initialize the return parameter.*/\r
+ *ppvObject = 0;\r
\r
- /* Query Interface always increases the reference count by one when it is successful */\r
- BindCtxImpl_AddRef(iface);\r
+ /* Compare the riid with the interface IDs implemented by this object.*/\r
+ if (IsEqualIID(&IID_IUnknown, riid) ||\r
+ IsEqualIID(&IID_IBindCtx, riid))\r
+ {\r
+ *ppvObject = (IBindCtx*)This;\r
+ IBindCtx_AddRef(iface);\r
+ return S_OK;\r
+ }\r
\r
- return S_OK;\r
+ return E_NOINTERFACE;\r
}\r
\r
/******************************************************************************\r
* BindCtx_AddRef\r
******************************************************************************/\r
-ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface)\r
+static ULONG WINAPI BindCtxImpl_AddRef(IBindCtx* iface)\r
{\r
BindCtxImpl *This = (BindCtxImpl *)iface;\r
\r
return InterlockedIncrement(&This->ref);\r
}\r
\r
+/******************************************************************************\r
+ * BindCtx_Destroy (local function)\r
+ *******************************************************************************/\r
+static HRESULT BindCtxImpl_Destroy(BindCtxImpl* This)\r
+{\r
+ TRACE("(%p)\n",This);\r
+\r
+ /* free the table space memory */\r
+ HeapFree(GetProcessHeap(),0,This->bindCtxTable);\r
+\r
+ /* free the bindctx structure */\r
+ HeapFree(GetProcessHeap(),0,This);\r
+\r
+ return S_OK;\r
+}\r
+\r
/******************************************************************************\r
* BindCtx_Release\r
******************************************************************************/\r
-ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)\r
+static ULONG WINAPI BindCtxImpl_Release(IBindCtx* iface)\r
{\r
BindCtxImpl *This = (BindCtxImpl *)iface;\r
ULONG ref;\r
TRACE("(%p)\n",This);\r
\r
ref = InterlockedDecrement(&This->ref);\r
-\r
- if (ref == 0){\r
+ if (ref == 0)\r
+ {\r
/* release all registered objects */\r
BindCtxImpl_ReleaseBoundObjects((IBindCtx*)This);\r
\r
}\r
\r
\r
-/******************************************************************************\r
- * BindCtx_Construct (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_Construct(BindCtxImpl* This)\r
-{\r
- TRACE("(%p)\n",This);\r
-\r
- /* Initialize the virtual function table.*/\r
- This->lpVtbl = &VT_BindCtxImpl;\r
- This->ref = 0;\r
-\r
- /* Initialize the BIND_OPTS2 structure */\r
- This->bindOption2.cbStruct = sizeof(BIND_OPTS2);\r
- This->bindOption2.grfFlags = 0;\r
- This->bindOption2.grfMode = STGM_READWRITE;\r
- This->bindOption2.dwTickCountDeadline = 0;\r
-\r
- This->bindOption2.dwTrackFlags = 0;\r
- This->bindOption2.dwClassContext = CLSCTX_SERVER;\r
- This->bindOption2.locale = 1033;\r
- This->bindOption2.pServerInfo = 0;\r
-\r
- /* Initialize the bindctx table */\r
- This->bindCtxTableSize=BLOCK_TAB_SIZE;\r
- This->bindCtxTableLastIndex=0;\r
- This->bindCtxTable= HeapAlloc(GetProcessHeap(), 0,This->bindCtxTableSize*sizeof(BindCtxObject));\r
-\r
- if (This->bindCtxTable==NULL)\r
- return E_OUTOFMEMORY;\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * BindCtx_Destroy (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_Destroy(BindCtxImpl* This)\r
-{\r
- TRACE("(%p)\n",This);\r
-\r
- /* free the table space memory */\r
- HeapFree(GetProcessHeap(),0,This->bindCtxTable);\r
-\r
- /* free the bindctx structure */\r
- HeapFree(GetProcessHeap(),0,This);\r
-\r
- return S_OK;\r
-}\r
-\r
-\r
/******************************************************************************\r
* BindCtx_RegisterObjectBound\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk)\r
+static HRESULT WINAPI\r
+BindCtxImpl_RegisterObjectBound(IBindCtx* iface,IUnknown* punk)\r
{\r
BindCtxImpl *This = (BindCtxImpl *)iface;\r
DWORD lastIndex=This->bindCtxTableLastIndex;\r
/******************************************************************************\r
* BindCtx_RevokeObjectBound\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)\r
+static HRESULT WINAPI\r
+BindCtxImpl_RevokeObjectBound(IBindCtx* iface, IUnknown* punk)\r
{\r
DWORD index,j;\r
\r
/******************************************************************************\r
* BindCtx_ReleaseBoundObjects\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)\r
+static HRESULT WINAPI\r
+BindCtxImpl_ReleaseBoundObjects(IBindCtx* iface)\r
{\r
DWORD i;\r
\r
/******************************************************************************\r
* BindCtx_SetBindOptions\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_SetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts)\r
+static HRESULT WINAPI\r
+BindCtxImpl_SetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts)\r
{\r
BindCtxImpl *This = (BindCtxImpl *)iface;\r
\r
/******************************************************************************\r
* BindCtx_GetBindOptions\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_GetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts)\r
+static HRESULT WINAPI\r
+BindCtxImpl_GetBindOptions(IBindCtx* iface,BIND_OPTS *pbindopts)\r
{\r
BindCtxImpl *This = (BindCtxImpl *)iface;\r
\r
/******************************************************************************\r
* BindCtx_GetRunningObjectTable\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot)\r
+static HRESULT WINAPI\r
+BindCtxImpl_GetRunningObjectTable(IBindCtx* iface,IRunningObjectTable** pprot)\r
{\r
HRESULT res;\r
\r
/******************************************************************************\r
* BindCtx_RegisterObjectParam\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)\r
+static HRESULT WINAPI\r
+BindCtxImpl_RegisterObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown* punk)\r
{\r
DWORD index=0;\r
BindCtxImpl *This = (BindCtxImpl *)iface;\r
\r
This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=NULL;\r
\r
- else{\r
+ else\r
+ {\r
\r
This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj=\r
HeapAlloc(GetProcessHeap(),0,(sizeof(WCHAR)*(1+lstrlenW(pszkey))));\r
\r
if (This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj==NULL)\r
return E_OUTOFMEMORY;\r
- strcpyW(This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj,pszkey);\r
+ lstrcpyW(This->bindCtxTable[This->bindCtxTableLastIndex].pkeyObj,pszkey);\r
}\r
\r
This->bindCtxTableLastIndex++;\r
\r
- if (This->bindCtxTableLastIndex == This->bindCtxTableSize){ /* table is full ! must be resized */\r
+ if (This->bindCtxTableLastIndex == This->bindCtxTableSize)\r
+ {\r
+ /* table is full ! must be resized */\r
\r
This->bindCtxTableSize+=BLOCK_TAB_SIZE; /* new table size */\r
-\r
- if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE)){\r
+ if (This->bindCtxTableSize > (MAX_TAB_SIZE-BLOCK_TAB_SIZE))\r
+ {\r
FIXME("This->bindCtxTableSize: %ld is out of data limite \n",This->bindCtxTableSize);\r
return E_FAIL;\r
}\r
/******************************************************************************\r
* BindCtx_GetObjectParam\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)\r
+static HRESULT WINAPI\r
+BindCtxImpl_GetObjectParam(IBindCtx* iface,LPOLESTR pszkey, IUnknown** punk)\r
{\r
DWORD index;\r
BindCtxImpl *This = (BindCtxImpl *)iface;\r
/******************************************************************************\r
* BindCtx_RevokeObjectParam\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)\r
+static HRESULT WINAPI\r
+BindCtxImpl_RevokeObjectParam(IBindCtx* iface,LPOLESTR ppenum)\r
{\r
DWORD index,j;\r
\r
/******************************************************************************\r
* BindCtx_EnumObjectParam\r
******************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)\r
+static HRESULT WINAPI\r
+BindCtxImpl_EnumObjectParam(IBindCtx* iface,IEnumString** pszkey)\r
{\r
FIXME("(%p,%p),stub!\n",iface,pszkey);\r
return E_NOTIMPL;\r
/********************************************************************************\r
* GetObjectIndex (local function)\r
********************************************************************************/\r
-HRESULT WINAPI BindCtxImpl_GetObjectIndex(BindCtxImpl* This,\r
+static HRESULT BindCtxImpl_GetObjectIndex(BindCtxImpl* This,\r
IUnknown* punk,\r
LPOLESTR pszkey,\r
DWORD *index)\r
\r
if (punk==NULL)\r
/* search object identified by a register key */\r
- for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++){\r
-\r
+ for(i=0; ( (i<This->bindCtxTableLastIndex) && (!found));i++)\r
+ {\r
if(This->bindCtxTable[i].regType==1){\r
\r
if ( ( (This->bindCtxTable[i].pkeyObj==NULL) && (pszkey==NULL) ) ||\r
return S_FALSE;\r
}\r
\r
+/* Virtual function table for the BindCtx class. */\r
+static IBindCtxVtbl VT_BindCtxImpl =\r
+{\r
+ BindCtxImpl_QueryInterface,\r
+ BindCtxImpl_AddRef,\r
+ BindCtxImpl_Release,\r
+ BindCtxImpl_RegisterObjectBound,\r
+ BindCtxImpl_RevokeObjectBound,\r
+ BindCtxImpl_ReleaseBoundObjects,\r
+ BindCtxImpl_SetBindOptions,\r
+ BindCtxImpl_GetBindOptions,\r
+ BindCtxImpl_GetRunningObjectTable,\r
+ BindCtxImpl_RegisterObjectParam,\r
+ BindCtxImpl_GetObjectParam,\r
+ BindCtxImpl_EnumObjectParam,\r
+ BindCtxImpl_RevokeObjectParam\r
+};\r
+\r
+/******************************************************************************\r
+ * BindCtx_Construct (local function)\r
+ *******************************************************************************/\r
+static HRESULT BindCtxImpl_Construct(BindCtxImpl* This)\r
+{\r
+ TRACE("(%p)\n",This);\r
+\r
+ /* Initialize the virtual function table.*/\r
+ This->lpVtbl = &VT_BindCtxImpl;\r
+ This->ref = 0;\r
+\r
+ /* Initialize the BIND_OPTS2 structure */\r
+ This->bindOption2.cbStruct = sizeof(BIND_OPTS2);\r
+ This->bindOption2.grfFlags = 0;\r
+ This->bindOption2.grfMode = STGM_READWRITE;\r
+ This->bindOption2.dwTickCountDeadline = 0;\r
+\r
+ This->bindOption2.dwTrackFlags = 0;\r
+ This->bindOption2.dwClassContext = CLSCTX_SERVER;\r
+ This->bindOption2.locale = 1033;\r
+ This->bindOption2.pServerInfo = 0;\r
+\r
+ /* Initialize the bindctx table */\r
+ This->bindCtxTableSize=BLOCK_TAB_SIZE;\r
+ This->bindCtxTableLastIndex=0;\r
+ This->bindCtxTable = HeapAlloc(GetProcessHeap(), 0,\r
+ This->bindCtxTableSize*sizeof(BindCtxObject));\r
+\r
+ if (This->bindCtxTable==NULL)\r
+ return E_OUTOFMEMORY;\r
+\r
+ return S_OK;\r
+}\r
+\r
/******************************************************************************\r
* CreateBindCtx16\r
******************************************************************************/\r
TRACE("(%ld,%p)\n",reserved,ppbc);\r
\r
newBindCtx = HeapAlloc(GetProcessHeap(), 0, sizeof(BindCtxImpl));\r
-\r
if (newBindCtx == 0)\r
return E_OUTOFMEMORY;\r
\r
hr = BindCtxImpl_Construct(newBindCtx);\r
-\r
- if (FAILED(hr)){\r
-\r
+ if (FAILED(hr))\r
+ {\r
HeapFree(GetProcessHeap(),0,newBindCtx);\r
return hr;\r
}\r
/*\r
* Prototypes for the methods of the OLEClipboard class.\r
*/\r
-extern void OLEClipbrd_Initialize();\r
-extern void OLEClipbrd_UnInitialize();\r
-static OLEClipbrd* OLEClipbrd_Construct();\r
+void OLEClipbrd_Initialize(void);\r
+void OLEClipbrd_UnInitialize(void);\r
+static OLEClipbrd* OLEClipbrd_Construct(void);\r
static void OLEClipbrd_Destroy(OLEClipbrd* ptrToDestroy);\r
-static HWND OLEClipbrd_CreateWindow();\r
+static HWND OLEClipbrd_CreateWindow(void);\r
static void OLEClipbrd_DestroyWindow(HWND hwnd);\r
LRESULT CALLBACK OLEClipbrd_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);\r
static HRESULT OLEClipbrd_RenderFormat( IDataObject *pIDataObject, LPFORMATETC pFormatetc );\r
* OLEClipbrd_Initialize()\r
* Initializes the OLE clipboard.\r
*/\r
-void OLEClipbrd_Initialize()\r
+void OLEClipbrd_Initialize(void)\r
{\r
/*\r
* Create the clipboard if necessary\r
* OLEClipbrd_UnInitialize()\r
* Un-Initializes the OLE clipboard\r
*/\r
-void OLEClipbrd_UnInitialize()\r
+void OLEClipbrd_UnInitialize(void)\r
{\r
TRACE("()\n");\r
/*\r
std.tymed = pFormatetc->tymed = TYMED_ISTORAGE;\r
\r
hStorage = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE, 0);\r
+ if (hStorage == NULL)\r
+ HANDLE_ERROR( E_OUTOFMEMORY );\r
hr = CreateILockBytesOnHGlobal(hStorage, FALSE, &ptrILockBytes);\r
hr = StgCreateDocfileOnILockBytes(ptrILockBytes, STGM_SHARE_EXCLUSIVE|STGM_READWRITE, 0, &std.u.pstg);\r
\r
if (FAILED(hr = IDataObject_GetDataHere(theOleClipboard->pIDataObjectSrc, pFormatetc, &std)))\r
{\r
WARN("() : IDataObject_GetDataHere failed to render clipboard data! (%lx)\n", hr);\r
+ GlobalFree(hStorage);\r
return hr;\r
}\r
\r
else\r
{\r
if (FAILED(hr = IDataObject_GetData(pIDataObject, pFormatetc, &std)))\r
- {\r
- WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);\r
- return hr;\r
- }\r
+ {\r
+ WARN("() : IDataObject_GetData failed to render clipboard data! (%lx)\n", hr);\r
+ GlobalFree(hStorage);\r
+ return hr;\r
+ }\r
\r
/* To put a copy back on the clipboard */\r
\r
pGlobalSrc = GlobalLock(hGlobalSrc);\r
pGlobalDest = GlobalLock(hGlobalDest);\r
if ( !pGlobalSrc || !pGlobalDest )\r
+ {\r
+ GlobalFree(hGlobalDest);\r
return 0;\r
+ }\r
\r
memcpy(pGlobalDest, pGlobalSrc, cBytes);\r
\r
* and create an IEnumFORMATETC enumerator from this list.\r
*/\r
cfmt = CountClipboardFormats();\r
- afmt = (FORMATETC *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
+ afmt = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,\r
sizeof(FORMATETC) * cfmt);\r
/*\r
* Open the Windows clipboard, associating it with our hidden window\r
DWORD size=cfmt * sizeof(FORMATETC);\r
LPMALLOC pIMalloc;\r
\r
- ef = (IEnumFORMATETCImpl*)HeapAlloc(GetProcessHeap(),\r
- HEAP_ZERO_MEMORY,\r
- sizeof(IEnumFORMATETCImpl));\r
+ ef = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IEnumFORMATETCImpl));\r
if (!ef)\r
return NULL;\r
\r
};\r
static CRITICAL_SECTION csOpenDllList = { &dll_cs_debug, -1, 0, 0, 0, 0 };\r
\r
-static const WCHAR wszAptWinClass[] = {'W','I','N','E','_','O','L','E','3','2','_','A','P','T','_','C','L','A','S','S',0};\r
-static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);\r
+static const WCHAR wszAptWinClass[] = {'O','l','e','M','a','i','n','T','h','r','e','a','d','W','n','d','C','l','a','s','s',' ',\r
+ '0','x','#','#','#','#','#','#','#','#',' ',0};\r
+static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);\r
\r
static void COMPOBJ_DLLList_Add(HANDLE hLibrary);\r
static void COMPOBJ_DllList_FreeUnused(int Timeout);\r
* was unmarshalled.\r
*/\r
memset(&wclass, 0, sizeof(wclass));\r
- wclass.lpfnWndProc = COM_AptWndProc;\r
+ wclass.lpfnWndProc = apartment_wndproc;\r
wclass.hInstance = OLE32_hInstance;\r
wclass.lpszClassName = wszAptWinClass;\r
RegisterClassW(&wclass);\r
struct oletls *info = NtCurrentTeb()->ReservedForOle;\r
if (info)\r
{\r
- if (info->apt) COM_ApartmentRelease(info->apt);\r
+ if (info->apt) apartment_release(info->apt);\r
if (info->errorinfo) IErrorInfo_Release(info->errorinfo);\r
if (info->state) IUnknown_Release(info->state);\r
HeapFree(GetProcessHeap(), 0, info);\r
apt->remunk_exported = FALSE;\r
apt->oidc = 1;\r
InitializeCriticalSection(&apt->cs);\r
+ DEBUG_SET_CRITSEC_NAME(&apt->cs, "apartment");\r
\r
apt->model = model;\r
\r
/* gets and existing apartment if one exists or otherwise creates an apartment\r
* structure which stores OLE apartment-local information and stores a pointer\r
* to it in the thread-local storage */\r
-static APARTMENT *get_or_create_apartment(DWORD model)\r
+static APARTMENT *apartment_get_or_create(DWORD model)\r
{\r
APARTMENT *apt = COM_CurrentApt();\r
\r
if (MTA)\r
{\r
TRACE("entering the multithreaded apartment %s\n", wine_dbgstr_longlong(MTA->oxid));\r
- COM_ApartmentAddRef(MTA);\r
+ apartment_addref(MTA);\r
}\r
else\r
MTA = apartment_construct(model);\r
return apt;\r
}\r
\r
-DWORD COM_ApartmentAddRef(struct apartment *apt)\r
+DWORD apartment_addref(struct apartment *apt)\r
{\r
DWORD refs = InterlockedIncrement(&apt->refs);\r
TRACE("%s: before = %ld\n", wine_dbgstr_longlong(apt->oxid), refs - 1);\r
return refs;\r
}\r
\r
-DWORD COM_ApartmentRelease(struct apartment *apt)\r
+DWORD apartment_release(struct apartment *apt)\r
{\r
DWORD ret;\r
\r
\r
TRACE("destroying apartment %p, oxid %s\n", apt, wine_dbgstr_longlong(apt->oxid));\r
\r
- MARSHAL_Disconnect_Proxies(apt);\r
+ /* no locking is needed for this apartment, because no other thread\r
+ * can access it at this point */\r
+\r
+ apartment_disconnectproxies(apt);\r
\r
if (apt->win) DestroyWindow(apt->win);\r
\r
\r
if (apt->filter) IUnknown_Release(apt->filter);\r
\r
+ DEBUG_CLEAR_CRITSEC_NAME(&apt->cs);\r
DeleteCriticalSection(&apt->cs);\r
CloseHandle(apt->thread);\r
+\r
HeapFree(GetProcessHeap(), 0, apt);\r
}\r
\r
return ret;\r
}\r
\r
-/* The given OXID must be local to this process: you cannot use\r
- * apartment windows to send RPCs to other processes. This all needs\r
- * to move to rpcrt4.\r
+/* The given OXID must be local to this process: \r
*\r
* The ref parameter is here mostly to ensure people remember that\r
* they get one, you should normally take a ref for thread safety.\r
*/\r
-APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref)\r
+APARTMENT *apartment_findfromoxid(OXID oxid, BOOL ref)\r
{\r
APARTMENT *result = NULL;\r
struct list *cursor;\r
if (apt->oxid == oxid)\r
{\r
result = apt;\r
- if (ref) COM_ApartmentAddRef(result);\r
+ if (ref) apartment_addref(result);\r
break;\r
}\r
}\r
/* gets the apartment which has a given creator thread ID. The caller must\r
* release the reference from the apartment as soon as the apartment pointer\r
* is no longer required. */\r
-APARTMENT *COM_ApartmentFromTID(DWORD tid)\r
+APARTMENT *apartment_findfromtid(DWORD tid)\r
{\r
APARTMENT *result = NULL;\r
struct list *cursor;\r
if (apt->tid == tid)\r
{\r
result = apt;\r
- COM_ApartmentAddRef(result);\r
+ apartment_addref(result);\r
break;\r
}\r
}\r
return result;\r
}\r
\r
-HWND COM_GetApartmentWin(OXID oxid, BOOL ref)\r
-{\r
- APARTMENT *apt;\r
-\r
- apt = COM_ApartmentFromOXID(oxid, ref);\r
- if (!apt) return NULL;\r
-\r
- return apt->win;\r
-}\r
-\r
-static LRESULT CALLBACK COM_AptWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
+static LRESULT CALLBACK apartment_wndproc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
{\r
switch (msg)\r
{\r
case DM_EXECUTERPC:\r
- return RPC_ExecuteCall((RPCOLEMESSAGE *)wParam, (IRpcStubBuffer *)lParam);\r
+ return RPC_ExecuteCall((struct dispatch_params *)lParam);\r
default:\r
return DefWindowProcW(hWnd, msg, wParam, lParam);\r
}\r
\r
if (openDllList == NULL) {\r
/* empty list -- add first node */\r
- openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));\r
+ openDllList = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));\r
openDllList->hLibrary=hLibrary;\r
openDllList->next = NULL;\r
} else {\r
if (!found) {\r
/* dll not found, add it */\r
tmp = openDllList;\r
- openDllList = (OpenDll*)HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));\r
+ openDllList = HeapAlloc(GetProcessHeap(),0, sizeof(OpenDll));\r
openDllList->hLibrary = hLibrary;\r
openDllList->next = tmp;\r
}\r
\r
if (!(apt = COM_CurrentInfo()->apt))\r
{\r
- apt = get_or_create_apartment(dwCoInit);\r
+ apt = apartment_get_or_create(dwCoInit);\r
if (!apt) return E_OUTOFMEMORY;\r
}\r
else if (dwCoInit != apt->model)\r
\r
if (!--info->inits)\r
{\r
- COM_ApartmentRelease(info->apt);\r
+ apartment_release(info->apt);\r
info->apt = NULL;\r
}\r
\r
if (!apt)\r
return CO_E_NOTINITIALIZED;\r
\r
- apartment_disconnect_object(apt, lpUnk);\r
+ apartment_disconnectobject(apt, lpUnk);\r
\r
/* Note: native is pretty broken here because it just silently\r
* fails, without returning an appropriate error code if the object was\r
}\r
}\r
HeapFree(GetProcessHeap(), 0, buf2);\r
+ RegCloseKey(xhkey);\r
}\r
\r
- RegCloseKey(xhkey);\r
return ret;\r
}\r
\r
-HRESULT WINAPI CLSIDFromProgID16(\r
- LPCOLESTR16 progid, /* [in] program id as found in registry */\r
- LPCLSID riid /* [out] associated CLSID */\r
-) {\r
+/******************************************************************************\r
+ * CLSIDFromProgID [COMPOBJ.61]\r
+ *\r
+ * Converts a program ID into the respective GUID.\r
+ *\r
+ * PARAMS\r
+ * progid [I] program id as found in registry\r
+ * riid [O] associated CLSID\r
+ *\r
+ * RETURNS\r
+ * Success: S_OK\r
+ * Failure: CO_E_CLASSSTRING - the given ProgID cannot be found.\r
+ */\r
+HRESULT WINAPI CLSIDFromProgID16(LPCOLESTR16 progid, LPCLSID riid)\r
+{\r
char *buf,buf2[80];\r
DWORD buf2len;\r
HRESULT err;\r
\r
/******************************************************************************\r
* CLSIDFromProgID [OLE32.@]\r
- * CLSIDFromProgID [COMPOBJ.61]\r
*\r
* Converts a program id into the respective GUID.\r
*\r
*\r
* We only search the registry, not ids registered with\r
* CoRegisterPSClsid.\r
- * Also, native returns S_OK for interfaces with an key in HKCR\Interface, but\r
+ * Also, native returns S_OK for interfaces with a key in HKCR\Interface, but\r
* without a ProxyStubClsid32 key and leaves garbage in pclsid. This should be\r
* considered a bug in native unless an application depends on this (unlikely).\r
*/\r
if (FAILED(hr)) ERR("-- failed with 0x%08lx\n", hr);\r
return hr;\r
}\r
+\r
+\r
+/***********************************************************************\r
+ * CoWaitForMultipleHandles [OLE32.@]\r
+ *\r
+ * Waits for one or more handles to become signaled.\r
+ *\r
+ * PARAMS\r
+ * dwFlags [I] Flags. See notes.\r
+ * dwTimeout [I] Timeout in milliseconds.\r
+ * cHandles [I] Number of handles pointed to by pHandles.\r
+ * pHandles [I] Handles to wait for.\r
+ * lpdwindex [O] Index of handle that was signaled.\r
+ *\r
+ * RETURNS\r
+ * Success: S_OK.\r
+ * Failure: RPC_S_CALLPENDING on timeout.\r
+ *\r
+ * NOTES\r
+ *\r
+ * The dwFlags parameter can be zero or more of the following:\r
+ *| COWAIT_WAITALL - Wait for all of the handles to become signaled.\r
+ *| COWAIT_ALERTABLE - Allows a queued APC to run during the wait.\r
+ *\r
+ * SEE ALSO\r
+ * MsgWaitForMultipleObjects, WaitForMultipleObjects.\r
+ */\r
+HRESULT WINAPI CoWaitForMultipleHandles(DWORD dwFlags, DWORD dwTimeout,\r
+ ULONG cHandles, const HANDLE* pHandles, LPDWORD lpdwindex)\r
+{\r
+ HRESULT hr = S_OK;\r
+ DWORD wait_flags = (dwFlags & COWAIT_WAITALL) ? MWMO_WAITALL : 0 |\r
+ (dwFlags & COWAIT_ALERTABLE ) ? MWMO_ALERTABLE : 0;\r
+ DWORD start_time = GetTickCount();\r
+\r
+ TRACE("(0x%08lx, 0x%08lx, %ld, %p, %p)\n", dwFlags, dwTimeout, cHandles,\r
+ pHandles, lpdwindex);\r
+\r
+ while (TRUE)\r
+ {\r
+ DWORD now = GetTickCount();\r
+ DWORD res;\r
+ \r
+ if ((dwTimeout != INFINITE) && (start_time + dwTimeout >= now))\r
+ {\r
+ hr = RPC_S_CALLPENDING;\r
+ break;\r
+ }\r
+\r
+ TRACE("waiting for rpc completion or window message\n");\r
+\r
+ res = MsgWaitForMultipleObjectsEx(cHandles, pHandles,\r
+ (dwTimeout == INFINITE) ? INFINITE : start_time + dwTimeout - now,\r
+ QS_ALLINPUT, wait_flags);\r
+\r
+ if (res == WAIT_OBJECT_0 + cHandles) /* messages available */\r
+ {\r
+ MSG msg;\r
+ while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))\r
+ {\r
+ /* FIXME: filter the messages here */\r
+ TRACE("received message whilst waiting for RPC: 0x%04x\n", msg.message);\r
+ TranslateMessage(&msg);\r
+ DispatchMessageW(&msg);\r
+ }\r
+ }\r
+ else if ((res >= WAIT_OBJECT_0) && (res < WAIT_OBJECT_0 + cHandles))\r
+ {\r
+ /* handle signaled, store index */\r
+ *lpdwindex = (res - WAIT_OBJECT_0);\r
+ break;\r
+ }\r
+ else if (res == WAIT_TIMEOUT)\r
+ {\r
+ hr = RPC_S_CALLPENDING;\r
+ break;\r
+ }\r
+ else\r
+ {\r
+ ERR("Unexpected wait termination: %ld, %ld\n", res, GetLastError());\r
+ hr = E_UNEXPECTED;\r
+ break;\r
+ }\r
+ }\r
+ TRACE("-- 0x%08lx\n", hr);\r
+ return hr;\r
+}\r
\r
/* Thread-safety Annotation Legend:\r
*\r
- * RO - The value is read only. It never changes after creation, so no\r
- * locking is required.\r
- * LOCK - The value is written to only using Interlocked* functions.\r
- * CS - The value is read or written to with a critical section held.\r
- * The identifier following "CS" is the specific critical section that\r
- * must be used.\r
+ * RO - The value is read only. It never changes after creation, so no\r
+ * locking is required.\r
+ * LOCK - The value is written to only using Interlocked* functions.\r
+ * CS - The value is read or written to inside a critical section.\r
+ * The identifier following "CS" is the specific critical setion that\r
+ * must be used.\r
+ * MUTEX - The value is read or written to with a mutex held.\r
+ * The identifier following "MUTEX" is the specific mutex that\r
+ * must be used.\r
*/\r
\r
typedef enum ifstub_state\r
IID iid; /* interface ID (RO) */\r
IPID ipid; /* imported interface ID (RO) */\r
LPRPCPROXYBUFFER proxy; /* interface proxy (RO) */\r
- DWORD refs; /* imported (public) references (CS parent->cs) */\r
+ DWORD refs; /* imported (public) references (MUTEX parent->remoting_mutex) */\r
IRpcChannelBuffer *chan; /* channel to object (CS parent->cs) */\r
};\r
\r
CRITICAL_SECTION cs; /* thread safety for this object and children */\r
ULONG sorflags; /* STDOBJREF flags (RO) */\r
IRemUnknown *remunk; /* proxy to IRemUnknown used for lifecycle management (CS cs) */\r
+ HANDLE remoting_mutex; /* mutex used for synchronizing access to IRemUnknown */\r
};\r
\r
/* this needs to become a COM object that implements IRemUnknown */\r
extern HRESULT WINE_StringFromCLSID(const CLSID *id,LPSTR idstr);\r
HRESULT WINAPI __CLSIDFromStringA(LPCSTR idstr, CLSID *id);\r
\r
-HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt);\r
HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);\r
\r
/* Stub Manager */\r
struct ifstub *stub_manager_new_ifstub(struct stub_manager *m, IRpcStubBuffer *sb, IUnknown *iptr, REFIID iid);\r
struct stub_manager *get_stub_manager(APARTMENT *apt, OID oid);\r
struct stub_manager *get_stub_manager_from_object(APARTMENT *apt, void *object);\r
-void apartment_disconnect_object(APARTMENT *apt, void *object);\r
BOOL stub_manager_notify_unmarshal(struct stub_manager *m);\r
BOOL stub_manager_is_table_marshaled(struct stub_manager *m);\r
void stub_manager_release_marshal_data(struct stub_manager *m, ULONG refs);\r
-HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags);\r
HRESULT ipid_to_stub_manager(const IPID *ipid, APARTMENT **stub_apt, struct stub_manager **stubmgr_ret);\r
IRpcStubBuffer *ipid_to_apt_and_stubbuffer(const IPID *ipid, APARTMENT **stub_apt);\r
HRESULT start_apartment_remote_unknown(void);\r
\r
+HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags);\r
+\r
/* RPC Backend */\r
\r
+struct dispatch_params;\r
+\r
void RPC_StartRemoting(struct apartment *apt);\r
HRESULT RPC_CreateClientChannel(const OXID *oxid, const IPID *ipid, IRpcChannelBuffer **pipebuf);\r
-HRESULT RPC_ExecuteCall(RPCOLEMESSAGE *msg, IRpcStubBuffer *stub);\r
+HRESULT RPC_ExecuteCall(struct dispatch_params *params);\r
HRESULT RPC_RegisterInterface(REFIID riid);\r
void RPC_UnregisterInterface(REFIID riid);\r
void RPC_StartLocalServer(REFCLSID clsid, IStream *stream);\r
\r
/* Apartment Functions */\r
\r
-APARTMENT *COM_ApartmentFromOXID(OXID oxid, BOOL ref);\r
-APARTMENT *COM_ApartmentFromTID(DWORD tid);\r
-DWORD COM_ApartmentAddRef(struct apartment *apt);\r
-DWORD COM_ApartmentRelease(struct apartment *apt);\r
+APARTMENT *apartment_findfromoxid(OXID oxid, BOOL ref);\r
+APARTMENT *apartment_findfromtid(DWORD tid);\r
+DWORD apartment_addref(struct apartment *apt);\r
+DWORD apartment_release(struct apartment *apt);\r
+HRESULT apartment_disconnectproxies(struct apartment *apt);\r
+void apartment_disconnectobject(struct apartment *apt, void *object);\r
+static inline HRESULT apartment_getoxid(struct apartment *apt, OXID *oxid)\r
+{\r
+ *oxid = apt->oxid;\r
+ return S_OK;\r
+}\r
+\r
\r
-/* messages used by the apartment window (not compatible with native) */\r
-#define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = (RPCOLEMESSAGE *), LPARAM = (IRpcStubBuffer *) */\r
+/* DCOM messages used by the apartment window (not compatible with native) */\r
+#define DM_EXECUTERPC (WM_USER + 0) /* WPARAM = 0, LPARAM = (struct dispatch_params *) */\r
\r
/*\r
* Per-thread values are stored in the TEB on offset 0xF80,\r
\r
#define ICOM_THIS_MULTI(impl,field,iface) impl* const This=(impl*)((char*)(iface) - offsetof(impl,field))\r
\r
+/* helpers for debugging */\r
+#ifdef __i386__\r
+# define DEBUG_SET_CRITSEC_NAME(cs, name) (cs)->DebugInfo->Spare[1] = (DWORD)(__FILE__ ": " name)\r
+# define DEBUG_CLEAR_CRITSEC_NAME(cs) (cs)->DebugInfo->Spare[1] = 0\r
+#else\r
+# define DEBUG_SET_CRITSEC_NAME(cs, name)\r
+# define DEBUG_CLEAR_CRITSEC_NAME(cs)\r
+#endif\r
+\r
#endif /* __WINE_OLE_COMPOBJ_H */\r
/*\r
- * CompositeMonikers implementation\r
+ * CompositeMonikers implementation\r
*\r
- * Copyright 1999 Noomen Hamza\r
+ * Copyright 1999 Noomen Hamza\r
*\r
* This library is free software; you can redistribute it and/or\r
* modify it under the terms of the GNU Lesser General Public\r
} EnumMonikerImpl;\r
\r
\r
-/********************************************************************************/\r
-/* CompositeMoniker prototype functions : */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject);\r
-static ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface);\r
-static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface);\r
-\r
-/* IPersist prototype functions */\r
-static HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface, CLSID *pClassID);\r
-\r
-/* IPersistStream prototype functions */\r
-static HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface);\r
-static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface, IStream* pStm);\r
-static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty);\r
-static HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize);\r
-\r
-/* IMoniker prototype functions */\r
-static HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult);\r
-static HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,IBindCtx* pbc, DWORD dwReduceHowFar,IMoniker** ppmkToLeft, IMoniker** ppmkReduced);\r
-static HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,IMoniker* pmkRight,BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite);\r
-static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker);\r
-static HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker);\r
-static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash);\r
-static HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning);\r
-static HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pCompositeTime);\r
-static HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk);\r
-static HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkPrefix);\r
-static HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath);\r
-static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName);\r
-static HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut);\r
-static HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys);\r
-\r
-/********************************************************************************/\r
-/* IROTData prototype functions */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData* iface,REFIID riid,VOID** ppvObject);\r
-static ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData* iface);\r
-static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface);\r
-\r
-/* IROTData prototype function */\r
-static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,BYTE* pbData,ULONG cbMax,ULONG* pcbData);\r
-\r
-/* Local function used by CompositeMoniker implementation */\r
-HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest);\r
-HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* iface);\r
-\r
-/********************************************************************************/\r
-/* IEnumMoniker prototype functions */\r
-\r
-/* IUnknown prototype functions */\r
-static HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject);\r
-static ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface);\r
-static ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface);\r
-\r
-/* IEnumMoniker prototype functions */\r
-static HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt,IMoniker** rgelt,ULONG* pceltFetched);\r
-static HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt);\r
-static HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface);\r
-static HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum);\r
-\r
-HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the CompositeMonikerImpl class which includes */\r
-/* IPersist, IPersistStream and IMoniker functions. */\r
-\r
-static IMonikerVtbl VT_CompositeMonikerImpl =\r
-{\r
- CompositeMonikerImpl_QueryInterface,\r
- CompositeMonikerImpl_AddRef,\r
- CompositeMonikerImpl_Release,\r
- CompositeMonikerImpl_GetClassID,\r
- CompositeMonikerImpl_IsDirty,\r
- CompositeMonikerImpl_Load,\r
- CompositeMonikerImpl_Save,\r
- CompositeMonikerImpl_GetSizeMax,\r
- CompositeMonikerImpl_BindToObject,\r
- CompositeMonikerImpl_BindToStorage,\r
- CompositeMonikerImpl_Reduce,\r
- CompositeMonikerImpl_ComposeWith,\r
- CompositeMonikerImpl_Enum,\r
- CompositeMonikerImpl_IsEqual,\r
- CompositeMonikerImpl_Hash,\r
- CompositeMonikerImpl_IsRunning,\r
- CompositeMonikerImpl_GetTimeOfLastChange,\r
- CompositeMonikerImpl_Inverse,\r
- CompositeMonikerImpl_CommonPrefixWith,\r
- CompositeMonikerImpl_RelativePathTo,\r
- CompositeMonikerImpl_GetDisplayName,\r
- CompositeMonikerImpl_ParseDisplayName,\r
- CompositeMonikerImpl_IsSystemMoniker\r
-};\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the IROTData class. */\r
-static IROTDataVtbl VT_ROTDataImpl =\r
-{\r
- CompositeMonikerROTDataImpl_QueryInterface,\r
- CompositeMonikerROTDataImpl_AddRef,\r
- CompositeMonikerROTDataImpl_Release,\r
- CompositeMonikerROTDataImpl_GetComparaisonData\r
-};\r
-\r
-/********************************************************************************/\r
-/* Virtual function table for the IROTData class */\r
-static IEnumMonikerVtbl VT_EnumMonikerImpl =\r
-{\r
- EnumMonikerImpl_QueryInterface,\r
- EnumMonikerImpl_AddRef,\r
- EnumMonikerImpl_Release,\r
- EnumMonikerImpl_Next,\r
- EnumMonikerImpl_Skip,\r
- EnumMonikerImpl_Reset,\r
- EnumMonikerImpl_Clone\r
-};\r
+static HRESULT EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,ULONG tabSize,ULONG currentPos,BOOL leftToRigth,IEnumMoniker ** ppmk);\r
\r
/*******************************************************************************\r
* CompositeMoniker_QueryInterface\r
*******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)\r
{\r
CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;\r
\r
return E_NOINTERFACE;\r
\r
/* Query Interface always increases the reference count by one when it is successful */\r
- CompositeMonikerImpl_AddRef(iface);\r
+ IMoniker_AddRef(iface);\r
\r
return S_OK;\r
}\r
/******************************************************************************\r
* CompositeMoniker_AddRef\r
******************************************************************************/\r
-ULONG WINAPI CompositeMonikerImpl_AddRef(IMoniker* iface)\r
+static ULONG WINAPI\r
+CompositeMonikerImpl_AddRef(IMoniker* iface)\r
{\r
CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;\r
\r
/******************************************************************************\r
* CompositeMoniker_Release\r
******************************************************************************/\r
-ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)\r
+static ULONG WINAPI\r
+CompositeMonikerImpl_Release(IMoniker* iface)\r
{\r
CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;\r
ULONG i;\r
for (i=0;i<This->tabLastIndex;i++)\r
IMoniker_Release(This->tabMoniker[i]);\r
\r
- CompositeMonikerImpl_Destroy(This);\r
+ HeapFree(GetProcessHeap(),0,This->tabMoniker);\r
+ HeapFree(GetProcessHeap(),0,This);\r
}\r
return ref;\r
}\r
/******************************************************************************\r
* CompositeMoniker_GetClassID\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_GetClassID(IMoniker* iface,CLSID *pClassID)\r
{\r
TRACE("(%p,%p),stub!\n",iface,pClassID);\r
\r
/******************************************************************************\r
* CompositeMoniker_IsDirty\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_IsDirty(IMoniker* iface)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_IsDirty(IMoniker* iface)\r
{\r
/* Note that the OLE-provided implementations of the IPersistStream::IsDirty\r
method in the OLE-provided moniker interfaces always return S_FALSE because\r
/******************************************************************************\r
* CompositeMoniker_Load\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)\r
{\r
HRESULT res;\r
DWORD constant;\r
/******************************************************************************\r
* CompositeMoniker_Save\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)\r
{\r
HRESULT res;\r
IEnumMoniker *enumMk;\r
/******************************************************************************\r
* CompositeMoniker_GetSizeMax\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_GetSizeMax(IMoniker* iface,ULARGE_INTEGER* pcbSize)\r
{\r
IEnumMoniker *enumMk;\r
IMoniker *pmk;\r
return S_OK;\r
}\r
\r
-/******************************************************************************\r
- * Composite-Moniker_Construct (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,LPMONIKER pmkFirst, LPMONIKER pmkRest)\r
-{\r
- DWORD mkSys;\r
- IEnumMoniker *enumMoniker;\r
- IMoniker *tempMk;\r
- HRESULT res;\r
-\r
- TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);\r
-\r
- /* Initialize the virtual function table. */\r
- This->lpvtbl1 = &VT_CompositeMonikerImpl;\r
- This->lpvtbl2 = &VT_ROTDataImpl;\r
- This->ref = 0;\r
-\r
- This->tabSize=BLOCK_TAB_SIZE;\r
- This->tabLastIndex=0;\r
-\r
- This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));\r
- if (This->tabMoniker==NULL)\r
- return E_OUTOFMEMORY;\r
-\r
- IMoniker_IsSystemMoniker(pmkFirst,&mkSys);\r
-\r
- /* put the first moniker contents in the beginning of the table */\r
- if (mkSys!=MKSYS_GENERICCOMPOSITE){\r
-\r
- This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;\r
- IMoniker_AddRef(pmkFirst);\r
- }\r
- else{\r
-\r
- IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);\r
-\r
- while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){\r
-\r
-\r
- if (++This->tabLastIndex==This->tabSize){\r
-\r
- This->tabSize+=BLOCK_TAB_SIZE;\r
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));\r
-\r
- if (This->tabMoniker==NULL)\r
- return E_OUTOFMEMORY;\r
- }\r
- }\r
-\r
- IEnumMoniker_Release(enumMoniker);\r
- }\r
-\r
- /* put the rest moniker contents after the first one and make simplification if needed */\r
-\r
- IMoniker_IsSystemMoniker(pmkRest,&mkSys);\r
-\r
- if (mkSys!=MKSYS_GENERICCOMPOSITE){\r
-\r
- /* add a simple moniker to the moniker table */\r
-\r
- res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);\r
-\r
- if (res==MK_E_NEEDGENERIC){\r
-\r
- /* there's no simplification in this case */\r
- This->tabMoniker[This->tabLastIndex]=pmkRest;\r
-\r
- This->tabLastIndex++;\r
-\r
- IMoniker_AddRef(pmkRest);\r
- }\r
- else if (tempMk==NULL){\r
-\r
- /* we have an antimoniker after a simple moniker so we can make a simplification in this case */\r
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
-\r
- This->tabLastIndex--;\r
- }\r
- else if (SUCCEEDED(res)){\r
-\r
- /* the non-generic composition was successful so we can make a simplification in this case */\r
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
-\r
- This->tabMoniker[This->tabLastIndex-1]=tempMk;\r
- } else\r
- return res;\r
-\r
- /* resize tabMoniker if needed */\r
- if (This->tabLastIndex==This->tabSize){\r
-\r
- This->tabSize+=BLOCK_TAB_SIZE;\r
-\r
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));\r
-\r
- if (This->tabMoniker==NULL)\r
- return E_OUTOFMEMORY;\r
- }\r
- }\r
- else{\r
-\r
- /* add a composite moniker to the moniker table (do the same thing\r
- * for each moniker within the composite moniker as a simple moniker\r
- * (see above for how to add a simple moniker case) )\r
- */\r
- IMoniker_Enum(pmkRest,TRUE,&enumMoniker);\r
-\r
- while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){\r
-\r
- res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);\r
-\r
- if (res==MK_E_NEEDGENERIC){\r
-\r
- This->tabLastIndex++;\r
- }\r
- else if (tempMk==NULL){\r
-\r
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
- IMoniker_Release(This->tabMoniker[This->tabLastIndex]);\r
- This->tabLastIndex--;\r
- }\r
- else{\r
-\r
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
-\r
- This->tabMoniker[This->tabLastIndex-1]=tempMk;\r
- }\r
-\r
- if (This->tabLastIndex==This->tabSize){\r
-\r
- This->tabSize+=BLOCK_TAB_SIZE;\r
-\r
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));\r
-\r
- if (This->tabMoniker==NULL)\r
- return E_OUTOFMEMORY;\r
- }\r
- }\r
-\r
- IEnumMoniker_Release(enumMoniker);\r
- }\r
-\r
- return S_OK;\r
-}\r
-\r
-/******************************************************************************\r
- * CompositeMoniker_Destroy (local function)\r
- *******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Destroy(CompositeMonikerImpl* This)\r
-{\r
- TRACE("(%p)\n",This);\r
-\r
- HeapFree(GetProcessHeap(),0,This->tabMoniker);\r
-\r
- HeapFree(GetProcessHeap(),0,This);\r
-\r
- return S_OK;\r
-}\r
-\r
/******************************************************************************\r
* CompositeMoniker_BindToObject\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_BindToObject(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvResult)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_BindToObject(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)\r
{\r
HRESULT res;\r
IRunningObjectTable *prot;\r
/******************************************************************************\r
* CompositeMoniker_BindToStorage\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_BindToStorage(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- REFIID riid,\r
- VOID** ppvResult)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_BindToStorage(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult)\r
{\r
HRESULT res;\r
IMoniker *tempMk,*antiMk,*mostRigthMk;\r
/******************************************************************************\r
* CompositeMoniker_Reduce\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Reduce(IMoniker* iface,\r
- IBindCtx* pbc,\r
- DWORD dwReduceHowFar,\r
- IMoniker** ppmkToLeft,\r
- IMoniker** ppmkReduced)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,\r
+ IMoniker** ppmkToLeft, IMoniker** ppmkReduced)\r
{\r
HRESULT res;\r
IMoniker *tempMk,*antiMk,*mostRigthMk,*leftReducedComposedMk,*mostRigthReducedMk;\r
/******************************************************************************\r
* CompositeMoniker_ComposeWith\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_ComposeWith(IMoniker* iface,\r
- IMoniker* pmkRight,\r
- BOOL fOnlyIfNotGeneric,\r
- IMoniker** ppmkComposite)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,\r
+ BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)\r
{\r
TRACE("(%p,%p,%d,%p)\n",iface,pmkRight,fOnlyIfNotGeneric,ppmkComposite);\r
\r
/******************************************************************************\r
* CompositeMoniker_Enum\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)\r
{\r
CompositeMonikerImpl *This = (CompositeMonikerImpl *)iface;\r
\r
/******************************************************************************\r
* CompositeMoniker_IsEqual\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)\r
{\r
IEnumMoniker *enumMoniker1,*enumMoniker2;\r
IMoniker *tempMk1,*tempMk2;\r
/******************************************************************************\r
* CompositeMoniker_Hash\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)\r
{\r
FIXME("(),stub!\n");\r
\r
/******************************************************************************\r
* CompositeMoniker_IsRunning\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_IsRunning(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- IMoniker* pmkNewlyRunning)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_IsRunning(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning)\r
{\r
IRunningObjectTable* rot;\r
HRESULT res;\r
/******************************************************************************\r
* CompositeMoniker_GetTimeOfLastChange\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- FILETIME* pCompositeTime)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, FILETIME* pCompositeTime)\r
{\r
IRunningObjectTable* rot;\r
HRESULT res;\r
/******************************************************************************\r
* CompositeMoniker_Inverse\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_Inverse(IMoniker* iface,IMoniker** ppmk)\r
{\r
HRESULT res;\r
IMoniker *tempMk,*antiMk,*mostRigthMk,*tempInvMk,*mostRigthInvMk;\r
/******************************************************************************\r
* CompositeMoniker_CommonPrefixWith\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,\r
+ IMoniker** ppmkPrefix)\r
{\r
DWORD mkSys;\r
HRESULT res1,res2;\r
return MK_E_NOPREFIX;\r
}\r
}\r
+\r
/***************************************************************************************************\r
* GetAfterCommonPrefix (local function)\r
* This function returns a moniker that consist of the remainder when the common prefix is removed\r
***************************************************************************************************/\r
-VOID WINAPI GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)\r
+static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)\r
{\r
IMoniker *tempMk,*tempMk1,*tempMk2;\r
IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;\r
}\r
}\r
}\r
+\r
/******************************************************************************\r
* CompositeMoniker_RelativePathTo\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther, IMoniker** ppmkRelPath)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,\r
+ IMoniker** ppmkRelPath)\r
{\r
HRESULT res;\r
IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;\r
/******************************************************************************\r
* CompositeMoniker_GetDisplayName\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR *ppszDisplayName)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)\r
{\r
ULONG lengthStr=1;\r
IEnumMoniker *enumMoniker;\r
/******************************************************************************\r
* CompositeMoniker_ParseDisplayName\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_ParseDisplayName(IMoniker* iface,\r
- IBindCtx* pbc,\r
- IMoniker* pmkToLeft,\r
- LPOLESTR pszDisplayName,\r
- ULONG* pchEaten,\r
- IMoniker** ppmkOut)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,\r
+ IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,\r
+ IMoniker** ppmkOut)\r
{\r
IEnumMoniker *enumMoniker;\r
IMoniker *tempMk,*mostRigthMk,*antiMk;\r
/******************************************************************************\r
* CompositeMoniker_IsSystemMoniker\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)\r
+static HRESULT WINAPI\r
+CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)\r
{\r
TRACE("(%p,%p)\n",iface,pwdMksys);\r
\r
/*******************************************************************************\r
* CompositeMonikerIROTData_QueryInterface\r
*******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)\r
+static HRESULT WINAPI\r
+CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,\r
+ VOID** ppvObject)\r
{\r
\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
/***********************************************************************\r
* CompositeMonikerIROTData_AddRef\r
*/\r
-ULONG WINAPI CompositeMonikerROTDataImpl_AddRef(IROTData *iface)\r
+static ULONG WINAPI\r
+CompositeMonikerROTDataImpl_AddRef(IROTData *iface)\r
{\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
\r
TRACE("(%p)\n",iface);\r
\r
- return CompositeMonikerImpl_AddRef(This);\r
+ return IMoniker_AddRef(This);\r
}\r
\r
/***********************************************************************\r
* CompositeMonikerIROTData_Release\r
*/\r
-ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)\r
+static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)\r
{\r
ICOM_THIS_From_IROTData(IMoniker, iface);\r
\r
TRACE("(%p)\n",iface);\r
\r
- return CompositeMonikerImpl_Release(This);\r
+ return IMoniker_Release(This);\r
}\r
\r
/******************************************************************************\r
* CompositeMonikerIROTData_GetComparaisonData\r
******************************************************************************/\r
-HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,\r
- BYTE* pbData,\r
- ULONG cbMax,\r
- ULONG* pcbData)\r
+static HRESULT WINAPI\r
+CompositeMonikerROTDataImpl_GetComparaisonData(IROTData* iface,\r
+ BYTE* pbData, ULONG cbMax, ULONG* pcbData)\r
{\r
FIXME("(),stub!\n");\r
return E_NOTIMPL;\r
/******************************************************************************\r
* EnumMonikerImpl_QueryInterface\r
******************************************************************************/\r
-HRESULT WINAPI EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)\r
+static HRESULT WINAPI\r
+EnumMonikerImpl_QueryInterface(IEnumMoniker* iface,REFIID riid,void** ppvObject)\r
{\r
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
\r
return E_NOINTERFACE;\r
\r
/* Query Interface always increases the reference count by one when it is successful */\r
- EnumMonikerImpl_AddRef(iface);\r
+ IEnumMoniker_AddRef(iface);\r
\r
return S_OK;\r
}\r
/******************************************************************************\r
* EnumMonikerImpl_AddRef\r
******************************************************************************/\r
-ULONG WINAPI EnumMonikerImpl_AddRef(IEnumMoniker* iface)\r
+static ULONG WINAPI\r
+EnumMonikerImpl_AddRef(IEnumMoniker* iface)\r
{\r
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
\r
/******************************************************************************\r
* EnumMonikerImpl_Release\r
******************************************************************************/\r
-ULONG WINAPI EnumMonikerImpl_Release(IEnumMoniker* iface)\r
+static ULONG WINAPI\r
+EnumMonikerImpl_Release(IEnumMoniker* iface)\r
{\r
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
ULONG i;\r
/******************************************************************************\r
* EnumMonikerImpl_Next\r
******************************************************************************/\r
-HRESULT WINAPI EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt, ULONG* pceltFethed){\r
-\r
+static HRESULT WINAPI\r
+EnumMonikerImpl_Next(IEnumMoniker* iface,ULONG celt, IMoniker** rgelt,\r
+ ULONG* pceltFethed)\r
+{\r
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
ULONG i;\r
\r
/******************************************************************************\r
* EnumMonikerImpl_Skip\r
******************************************************************************/\r
-HRESULT WINAPI EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt){\r
-\r
+static HRESULT WINAPI\r
+EnumMonikerImpl_Skip(IEnumMoniker* iface,ULONG celt)\r
+{\r
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
\r
if ((This->currentPos+celt) >= This->tabSize)\r
/******************************************************************************\r
* EnumMonikerImpl_Reset\r
******************************************************************************/\r
-HRESULT WINAPI EnumMonikerImpl_Reset(IEnumMoniker* iface){\r
+static HRESULT WINAPI\r
+EnumMonikerImpl_Reset(IEnumMoniker* iface)\r
+{\r
\r
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
\r
/******************************************************************************\r
* EnumMonikerImpl_Clone\r
******************************************************************************/\r
-HRESULT WINAPI EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum){\r
-\r
+static HRESULT WINAPI\r
+EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)\r
+{\r
EnumMonikerImpl *This = (EnumMonikerImpl *)iface;\r
\r
return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);\r
}\r
\r
+/********************************************************************************/\r
+/* Virtual function table for the IROTData class */\r
+static IEnumMonikerVtbl VT_EnumMonikerImpl =\r
+{\r
+ EnumMonikerImpl_QueryInterface,\r
+ EnumMonikerImpl_AddRef,\r
+ EnumMonikerImpl_Release,\r
+ EnumMonikerImpl_Next,\r
+ EnumMonikerImpl_Skip,\r
+ EnumMonikerImpl_Reset,\r
+ EnumMonikerImpl_Clone\r
+};\r
+\r
/******************************************************************************\r
* EnumMonikerImpl_CreateEnumMoniker\r
******************************************************************************/\r
-HRESULT WINAPI EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker,\r
- ULONG tabSize,\r
- ULONG currentPos,\r
- BOOL leftToRigth,\r
- IEnumMoniker ** ppmk)\r
+static HRESULT\r
+EnumMonikerImpl_CreateEnumMoniker(IMoniker** tabMoniker, ULONG tabSize,\r
+ ULONG currentPos, BOOL leftToRigth, IEnumMoniker ** ppmk)\r
{\r
EnumMonikerImpl* newEnumMoniker;\r
int i;\r
\r
-\r
if (currentPos > tabSize)\r
return E_INVALIDARG;\r
\r
return S_OK;\r
}\r
\r
+/********************************************************************************/\r
+/* Virtual function table for the CompositeMonikerImpl class which includes */\r
+/* IPersist, IPersistStream and IMoniker functions. */\r
+\r
+static IMonikerVtbl VT_CompositeMonikerImpl =\r
+{\r
+ CompositeMonikerImpl_QueryInterface,\r
+ CompositeMonikerImpl_AddRef,\r
+ CompositeMonikerImpl_Release,\r
+ CompositeMonikerImpl_GetClassID,\r
+ CompositeMonikerImpl_IsDirty,\r
+ CompositeMonikerImpl_Load,\r
+ CompositeMonikerImpl_Save,\r
+ CompositeMonikerImpl_GetSizeMax,\r
+ CompositeMonikerImpl_BindToObject,\r
+ CompositeMonikerImpl_BindToStorage,\r
+ CompositeMonikerImpl_Reduce,\r
+ CompositeMonikerImpl_ComposeWith,\r
+ CompositeMonikerImpl_Enum,\r
+ CompositeMonikerImpl_IsEqual,\r
+ CompositeMonikerImpl_Hash,\r
+ CompositeMonikerImpl_IsRunning,\r
+ CompositeMonikerImpl_GetTimeOfLastChange,\r
+ CompositeMonikerImpl_Inverse,\r
+ CompositeMonikerImpl_CommonPrefixWith,\r
+ CompositeMonikerImpl_RelativePathTo,\r
+ CompositeMonikerImpl_GetDisplayName,\r
+ CompositeMonikerImpl_ParseDisplayName,\r
+ CompositeMonikerImpl_IsSystemMoniker\r
+};\r
+\r
+/********************************************************************************/\r
+/* Virtual function table for the IROTData class. */\r
+static IROTDataVtbl VT_ROTDataImpl =\r
+{\r
+ CompositeMonikerROTDataImpl_QueryInterface,\r
+ CompositeMonikerROTDataImpl_AddRef,\r
+ CompositeMonikerROTDataImpl_Release,\r
+ CompositeMonikerROTDataImpl_GetComparaisonData\r
+};\r
+\r
+/******************************************************************************\r
+ * Composite-Moniker_Construct (local function)\r
+ *******************************************************************************/\r
+static HRESULT\r
+CompositeMonikerImpl_Construct(CompositeMonikerImpl* This,\r
+ LPMONIKER pmkFirst, LPMONIKER pmkRest)\r
+{\r
+ DWORD mkSys;\r
+ IEnumMoniker *enumMoniker;\r
+ IMoniker *tempMk;\r
+ HRESULT res;\r
+\r
+ TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);\r
+\r
+ /* Initialize the virtual function table. */\r
+ This->lpvtbl1 = &VT_CompositeMonikerImpl;\r
+ This->lpvtbl2 = &VT_ROTDataImpl;\r
+ This->ref = 0;\r
+\r
+ This->tabSize=BLOCK_TAB_SIZE;\r
+ This->tabLastIndex=0;\r
+\r
+ This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(IMoniker));\r
+ if (This->tabMoniker==NULL)\r
+ return E_OUTOFMEMORY;\r
+\r
+ IMoniker_IsSystemMoniker(pmkFirst,&mkSys);\r
+\r
+ /* put the first moniker contents in the beginning of the table */\r
+ if (mkSys!=MKSYS_GENERICCOMPOSITE){\r
+\r
+ This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;\r
+ IMoniker_AddRef(pmkFirst);\r
+ }\r
+ else{\r
+\r
+ IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);\r
+\r
+ while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){\r
+\r
+\r
+ if (++This->tabLastIndex==This->tabSize){\r
+\r
+ This->tabSize+=BLOCK_TAB_SIZE;\r
+ This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));\r
+\r
+ if (This->tabMoniker==NULL)\r
+ return E_OUTOFMEMORY;\r
+ }\r
+ }\r
+\r
+ IEnumMoniker_Release(enumMoniker);\r
+ }\r
+\r
+ /* put the rest moniker contents after the first one and make simplification if needed */\r
+\r
+ IMoniker_IsSystemMoniker(pmkRest,&mkSys);\r
+\r
+ if (mkSys!=MKSYS_GENERICCOMPOSITE){\r
+\r
+ /* add a simple moniker to the moniker table */\r
+\r
+ res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);\r
+\r
+ if (res==MK_E_NEEDGENERIC){\r
+\r
+ /* there's no simplification in this case */\r
+ This->tabMoniker[This->tabLastIndex]=pmkRest;\r
+\r
+ This->tabLastIndex++;\r
+\r
+ IMoniker_AddRef(pmkRest);\r
+ }\r
+ else if (tempMk==NULL){\r
+\r
+ /* we have an antimoniker after a simple moniker so we can make a simplification in this case */\r
+ IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
+\r
+ This->tabLastIndex--;\r
+ }\r
+ else if (SUCCEEDED(res)){\r
+\r
+ /* the non-generic composition was successful so we can make a simplification in this case */\r
+ IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
+\r
+ This->tabMoniker[This->tabLastIndex-1]=tempMk;\r
+ } else\r
+ return res;\r
+\r
+ /* resize tabMoniker if needed */\r
+ if (This->tabLastIndex==This->tabSize){\r
+\r
+ This->tabSize+=BLOCK_TAB_SIZE;\r
+\r
+ This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));\r
+\r
+ if (This->tabMoniker==NULL)\r
+ return E_OUTOFMEMORY;\r
+ }\r
+ }\r
+ else{\r
+\r
+ /* add a composite moniker to the moniker table (do the same thing\r
+ * for each moniker within the composite moniker as a simple moniker\r
+ * (see above for how to add a simple moniker case) )\r
+ */\r
+ IMoniker_Enum(pmkRest,TRUE,&enumMoniker);\r
+\r
+ while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){\r
+\r
+ res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);\r
+\r
+ if (res==MK_E_NEEDGENERIC){\r
+\r
+ This->tabLastIndex++;\r
+ }\r
+ else if (tempMk==NULL){\r
+\r
+ IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
+ IMoniker_Release(This->tabMoniker[This->tabLastIndex]);\r
+ This->tabLastIndex--;\r
+ }\r
+ else{\r
+\r
+ IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);\r
+\r
+ This->tabMoniker[This->tabLastIndex-1]=tempMk;\r
+ }\r
+\r
+ if (This->tabLastIndex==This->tabSize){\r
+\r
+ This->tabSize+=BLOCK_TAB_SIZE;\r
+\r
+ This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));\r
+\r
+ if (This->tabMoniker==NULL)\r
+ return E_OUTOFMEMORY;\r
+ }\r
+ }\r
+\r
+ IEnumMoniker_Release(enumMoniker);\r
+ }\r
+\r
+ return S_OK;\r
+}\r
+\r
/******************************************************************************\r
* CreateGenericComposite [OLE32.@]\r
******************************************************************************/\r
-HRESULT WINAPI CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest, LPMONIKER* ppmkComposite)\r
+HRESULT WINAPI\r
+CreateGenericComposite(LPMONIKER pmkFirst, LPMONIKER pmkRest,\r
+ LPMONIKER* ppmkComposite)\r
{\r
CompositeMonikerImpl* newCompositeMoniker = 0;\r
HRESULT hr = S_OK;\r
hr = IMoniker_QueryInterface(newCompositeMoniker->tabMoniker[0],&IID_IMoniker,(void**)ppmkComposite);\r
else\r
\r
- hr = CompositeMonikerImpl_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);\r
+ hr = IMoniker_QueryInterface((IMoniker*)newCompositeMoniker,&IID_IMoniker,(void**)ppmkComposite);\r
\r
return hr;\r
}\r
/******************************************************************************\r
* MonikerCommonPrefixWith [OLE32.@]\r
******************************************************************************/\r
-HRESULT WINAPI MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)\r
+HRESULT WINAPI\r
+MonikerCommonPrefixWith(IMoniker* pmkThis,IMoniker* pmkOther,IMoniker** ppmkCommon)\r
{\r
FIXME("(),stub!\n");\r
return E_NOTIMPL;\r
*/\r
static DataCache* DataCache_Construct(REFCLSID clsid,\r
LPUNKNOWN pUnkOuter);\r
-static void DataCache_Destroy(DataCache* ptrToDestroy);\r
-static HRESULT DataCache_ReadPresentationData(DataCache* this,\r
- DWORD drawAspect,\r
- PresentationDataHeader* header);\r
static HRESULT DataCache_OpenPresStream(DataCache *this,\r
DWORD drawAspect,\r
IStream **pStm);\r
-static HMETAFILE DataCache_ReadPresMetafile(DataCache* this,\r
- DWORD drawAspect);\r
-static void DataCache_FireOnViewChange(DataCache* this,\r
- DWORD aspect,\r
- LONG lindex);\r
-\r
-/*\r
- * Prototypes for the methods of the DataCache class\r
- * that implement non delegating IUnknown methods.\r
- */\r
-static HRESULT WINAPI DataCache_NDIUnknown_QueryInterface(\r
- IUnknown* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-static ULONG WINAPI DataCache_NDIUnknown_AddRef(\r
- IUnknown* iface);\r
-static ULONG WINAPI DataCache_NDIUnknown_Release(\r
- IUnknown* iface);\r
-\r
-/*\r
- * Prototypes for the methods of the DataCache class\r
- * that implement IDataObject methods.\r
- */\r
-static HRESULT WINAPI DataCache_IDataObject_QueryInterface(\r
- IDataObject* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-static ULONG WINAPI DataCache_IDataObject_AddRef(\r
- IDataObject* iface);\r
-static ULONG WINAPI DataCache_IDataObject_Release(\r
- IDataObject* iface);\r
-static HRESULT WINAPI DataCache_GetData(\r
- IDataObject* iface,\r
- LPFORMATETC pformatetcIn,\r
- STGMEDIUM* pmedium);\r
-static HRESULT WINAPI DataCache_GetDataHere(\r
- IDataObject* iface,\r
- LPFORMATETC pformatetc,\r
- STGMEDIUM* pmedium);\r
-static HRESULT WINAPI DataCache_QueryGetData(\r
- IDataObject* iface,\r
- LPFORMATETC pformatetc);\r
-static HRESULT WINAPI DataCache_GetCanonicalFormatEtc(\r
- IDataObject* iface,\r
- LPFORMATETC pformatectIn,\r
- LPFORMATETC pformatetcOut);\r
-static HRESULT WINAPI DataCache_IDataObject_SetData(\r
- IDataObject* iface,\r
- LPFORMATETC pformatetc,\r
- STGMEDIUM* pmedium,\r
- BOOL fRelease);\r
-static HRESULT WINAPI DataCache_EnumFormatEtc(\r
- IDataObject* iface,\r
- DWORD dwDirection,\r
- IEnumFORMATETC** ppenumFormatEtc);\r
-static HRESULT WINAPI DataCache_DAdvise(\r
- IDataObject* iface,\r
- FORMATETC* pformatetc,\r
- DWORD advf,\r
- IAdviseSink* pAdvSink,\r
- DWORD* pdwConnection);\r
-static HRESULT WINAPI DataCache_DUnadvise(\r
- IDataObject* iface,\r
- DWORD dwConnection);\r
-static HRESULT WINAPI DataCache_EnumDAdvise(\r
- IDataObject* iface,\r
- IEnumSTATDATA** ppenumAdvise);\r
-\r
-/*\r
- * Prototypes for the methods of the DataCache class\r
- * that implement IPersistStorage methods.\r
- */\r
-static HRESULT WINAPI DataCache_IPersistStorage_QueryInterface(\r
- IPersistStorage* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-static ULONG WINAPI DataCache_IPersistStorage_AddRef(\r
- IPersistStorage* iface);\r
-static ULONG WINAPI DataCache_IPersistStorage_Release(\r
- IPersistStorage* iface);\r
-static HRESULT WINAPI DataCache_GetClassID(\r
- IPersistStorage* iface,\r
- CLSID* pClassID);\r
-static HRESULT WINAPI DataCache_IsDirty(\r
- IPersistStorage* iface);\r
-static HRESULT WINAPI DataCache_InitNew(\r
- IPersistStorage* iface,\r
- IStorage* pStg);\r
-static HRESULT WINAPI DataCache_Load(\r
- IPersistStorage* iface,\r
- IStorage* pStg);\r
-static HRESULT WINAPI DataCache_Save(\r
- IPersistStorage* iface,\r
- IStorage* pStg,\r
- BOOL fSameAsLoad);\r
-static HRESULT WINAPI DataCache_SaveCompleted(\r
- IPersistStorage* iface,\r
- IStorage* pStgNew);\r
-static HRESULT WINAPI DataCache_HandsOffStorage(\r
- IPersistStorage* iface);\r
-\r
-/*\r
- * Prototypes for the methods of the DataCache class\r
- * that implement IViewObject2 methods.\r
- */\r
-static HRESULT WINAPI DataCache_IViewObject2_QueryInterface(\r
- IViewObject2* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-static ULONG WINAPI DataCache_IViewObject2_AddRef(\r
- IViewObject2* iface);\r
-static ULONG WINAPI DataCache_IViewObject2_Release(\r
- IViewObject2* iface);\r
-static HRESULT WINAPI DataCache_Draw(\r
- IViewObject2* iface,\r
- DWORD dwDrawAspect,\r
- LONG lindex,\r
- void* pvAspect,\r
- DVTARGETDEVICE* ptd,\r
- HDC hdcTargetDev,\r
- HDC hdcDraw,\r
- LPCRECTL lprcBounds,\r
- LPCRECTL lprcWBounds,\r
- BOOL (CALLBACK *pfnContinue)(ULONG_PTR dwContinue),\r
- ULONG_PTR dwContinue);\r
-static HRESULT WINAPI DataCache_GetColorSet(\r
- IViewObject2* iface,\r
- DWORD dwDrawAspect,\r
- LONG lindex,\r
- void* pvAspect,\r
- DVTARGETDEVICE* ptd,\r
- HDC hicTargetDevice,\r
- LOGPALETTE** ppColorSet);\r
-static HRESULT WINAPI DataCache_Freeze(\r
- IViewObject2* iface,\r
- DWORD dwDrawAspect,\r
- LONG lindex,\r
- void* pvAspect,\r
- DWORD* pdwFreeze);\r
-static HRESULT WINAPI DataCache_Unfreeze(\r
- IViewObject2* iface,\r
- DWORD dwFreeze);\r
-static HRESULT WINAPI DataCache_SetAdvise(\r
- IViewObject2* iface,\r
- DWORD aspects,\r
- DWORD advf,\r
- IAdviseSink* pAdvSink);\r
-static HRESULT WINAPI DataCache_GetAdvise(\r
- IViewObject2* iface,\r
- DWORD* pAspects,\r
- DWORD* pAdvf,\r
- IAdviseSink** ppAdvSink);\r
-static HRESULT WINAPI DataCache_GetExtent(\r
- IViewObject2* iface,\r
- DWORD dwDrawAspect,\r
- LONG lindex,\r
- DVTARGETDEVICE* ptd,\r
- LPSIZEL lpsizel);\r
-\r
-/*\r
- * Prototypes for the methods of the DataCache class\r
- * that implement IOleCache2 methods.\r
- */\r
-static HRESULT WINAPI DataCache_IOleCache2_QueryInterface(\r
- IOleCache2* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-static ULONG WINAPI DataCache_IOleCache2_AddRef(\r
- IOleCache2* iface);\r
-static ULONG WINAPI DataCache_IOleCache2_Release(\r
- IOleCache2* iface);\r
-static HRESULT WINAPI DataCache_Cache(\r
- IOleCache2* iface,\r
- FORMATETC* pformatetc,\r
- DWORD advf,\r
- DWORD* pdwConnection);\r
-static HRESULT WINAPI DataCache_Uncache(\r
- IOleCache2* iface,\r
- DWORD dwConnection);\r
-static HRESULT WINAPI DataCache_EnumCache(\r
- IOleCache2* iface,\r
- IEnumSTATDATA** ppenumSTATDATA);\r
-static HRESULT WINAPI DataCache_InitCache(\r
- IOleCache2* iface,\r
- IDataObject* pDataObject);\r
-static HRESULT WINAPI DataCache_IOleCache2_SetData(\r
- IOleCache2* iface,\r
- FORMATETC* pformatetc,\r
- STGMEDIUM* pmedium,\r
- BOOL fRelease);\r
-static HRESULT WINAPI DataCache_UpdateCache(\r
- IOleCache2* iface,\r
- LPDATAOBJECT pDataObject,\r
- DWORD grfUpdf,\r
- LPVOID pReserved);\r
-static HRESULT WINAPI DataCache_DiscardCache(\r
- IOleCache2* iface,\r
- DWORD dwDiscardOptions);\r
-\r
-/*\r
- * Prototypes for the methods of the DataCache class\r
- * that implement IOleCacheControl methods.\r
- */\r
-static HRESULT WINAPI DataCache_IOleCacheControl_QueryInterface(\r
- IOleCacheControl* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-static ULONG WINAPI DataCache_IOleCacheControl_AddRef(\r
- IOleCacheControl* iface);\r
-static ULONG WINAPI DataCache_IOleCacheControl_Release(\r
- IOleCacheControl* iface);\r
-static HRESULT WINAPI DataCache_OnRun(\r
- IOleCacheControl* iface,\r
- LPDATAOBJECT pDataObject);\r
-static HRESULT WINAPI DataCache_OnStop(\r
- IOleCacheControl* iface);\r
-\r
-/*\r
- * Virtual function tables for the DataCache class.\r
- */\r
-static IUnknownVtbl DataCache_NDIUnknown_VTable =\r
-{\r
- DataCache_NDIUnknown_QueryInterface,\r
- DataCache_NDIUnknown_AddRef,\r
- DataCache_NDIUnknown_Release\r
-};\r
-\r
-static IDataObjectVtbl DataCache_IDataObject_VTable =\r
-{\r
- DataCache_IDataObject_QueryInterface,\r
- DataCache_IDataObject_AddRef,\r
- DataCache_IDataObject_Release,\r
- DataCache_GetData,\r
- DataCache_GetDataHere,\r
- DataCache_QueryGetData,\r
- DataCache_GetCanonicalFormatEtc,\r
- DataCache_IDataObject_SetData,\r
- DataCache_EnumFormatEtc,\r
- DataCache_DAdvise,\r
- DataCache_DUnadvise,\r
- DataCache_EnumDAdvise\r
-};\r
-\r
-static IPersistStorageVtbl DataCache_IPersistStorage_VTable =\r
-{\r
- DataCache_IPersistStorage_QueryInterface,\r
- DataCache_IPersistStorage_AddRef,\r
- DataCache_IPersistStorage_Release,\r
- DataCache_GetClassID,\r
- DataCache_IsDirty,\r
- DataCache_InitNew,\r
- DataCache_Load,\r
- DataCache_Save,\r
- DataCache_SaveCompleted,\r
- DataCache_HandsOffStorage\r
-};\r
-\r
-static IViewObject2Vtbl DataCache_IViewObject2_VTable =\r
-{\r
- DataCache_IViewObject2_QueryInterface,\r
- DataCache_IViewObject2_AddRef,\r
- DataCache_IViewObject2_Release,\r
- DataCache_Draw,\r
- DataCache_GetColorSet,\r
- DataCache_Freeze,\r
- DataCache_Unfreeze,\r
- DataCache_SetAdvise,\r
- DataCache_GetAdvise,\r
- DataCache_GetExtent\r
-};\r
-\r
-static IOleCache2Vtbl DataCache_IOleCache2_VTable =\r
-{\r
- DataCache_IOleCache2_QueryInterface,\r
- DataCache_IOleCache2_AddRef,\r
- DataCache_IOleCache2_Release,\r
- DataCache_Cache,\r
- DataCache_Uncache,\r
- DataCache_EnumCache,\r
- DataCache_InitCache,\r
- DataCache_IOleCache2_SetData,\r
- DataCache_UpdateCache,\r
- DataCache_DiscardCache\r
-};\r
-\r
-static IOleCacheControlVtbl DataCache_IOleCacheControl_VTable =\r
-{\r
- DataCache_IOleCacheControl_QueryInterface,\r
- DataCache_IOleCacheControl_AddRef,\r
- DataCache_IOleCacheControl_Release,\r
- DataCache_OnRun,\r
- DataCache_OnStop\r
-};\r
-\r
-/******************************************************************************\r
- * CreateDataCache [OLE32.@]\r
- */\r
-HRESULT WINAPI CreateDataCache(\r
- LPUNKNOWN pUnkOuter,\r
- REFCLSID rclsid,\r
- REFIID riid,\r
- LPVOID* ppvObj)\r
-{\r
- DataCache* newCache = NULL;\r
- HRESULT hr = S_OK;\r
-\r
- TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);\r
-\r
- /*\r
- * Sanity check\r
- */\r
- if (ppvObj==0)\r
- return E_POINTER;\r
-\r
- *ppvObj = 0;\r
-\r
- /*\r
- * If this cache is constructed for aggregation, make sure\r
- * the caller is requesting the IUnknown interface.\r
- * This is necessary because it's the only time the non-delegating\r
- * IUnknown pointer can be returned to the outside.\r
- */\r
- if ( (pUnkOuter!=NULL) &&\r
- (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )\r
- return CLASS_E_NOAGGREGATION;\r
-\r
- /*\r
- * Try to construct a new instance of the class.\r
- */\r
- newCache = DataCache_Construct(rclsid,\r
- pUnkOuter);\r
-\r
- if (newCache == 0)\r
- return E_OUTOFMEMORY;\r
-\r
- /*\r
- * Make sure it supports the interface required by the caller.\r
- */\r
- hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);\r
-\r
- /*\r
- * Release the reference obtained in the constructor. If\r
- * the QueryInterface was unsuccessful, it will free the class.\r
- */\r
- IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));\r
-\r
- return hr;\r
-}\r
-\r
-/*********************************************************\r
- * Method implementation for DataCache class.\r
- */\r
-static DataCache* DataCache_Construct(\r
- REFCLSID clsid,\r
- LPUNKNOWN pUnkOuter)\r
-{\r
- DataCache* newObject = 0;\r
-\r
- /*\r
- * Allocate space for the object.\r
- */\r
- newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));\r
-\r
- if (newObject==0)\r
- return newObject;\r
-\r
- /*\r
- * Initialize the virtual function table.\r
- */\r
- newObject->lpvtbl1 = &DataCache_IDataObject_VTable;\r
- newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;\r
- newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;\r
- newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;\r
- newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;\r
- newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;\r
-\r
- /*\r
- * Start with one reference count. The caller of this function\r
- * must release the interface pointer when it is done.\r
- */\r
- newObject->ref = 1;\r
-\r
- /*\r
- * Initialize the outer unknown\r
- * We don't keep a reference on the outer unknown since, the way\r
- * aggregation works, our lifetime is at least as large as it's\r
- * lifetime.\r
- */\r
- if (pUnkOuter==NULL)\r
- pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);\r
-\r
- newObject->outerUnknown = pUnkOuter;\r
-\r
- /*\r
- * Initialize the other members of the structure.\r
- */\r
- newObject->presentationStorage = NULL;\r
- newObject->sinkAspects = 0;\r
- newObject->sinkAdviseFlag = 0;\r
- newObject->sinkInterface = 0;\r
-\r
- return newObject;\r
-}\r
\r
static void DataCache_Destroy(\r
DataCache* ptrToDestroy)\r
{\r
TRACE("(%p, %p)\n", iface, pStg);\r
\r
- return DataCache_Load(iface, pStg);\r
+ return IPersistStorage_Load(iface, pStg);\r
}\r
\r
/************************************************************************\r
* First, make sure we get our hands off any storage we have.\r
*/\r
\r
- DataCache_HandsOffStorage(iface);\r
+ IPersistStorage_HandsOffStorage(iface);\r
\r
/*\r
* Then, attach to the new storage.\r
FIXME("stub\n");\r
return E_NOTIMPL;\r
}\r
+\r
+/*\r
+ * Virtual function tables for the DataCache class.\r
+ */\r
+static IUnknownVtbl DataCache_NDIUnknown_VTable =\r
+{\r
+ DataCache_NDIUnknown_QueryInterface,\r
+ DataCache_NDIUnknown_AddRef,\r
+ DataCache_NDIUnknown_Release\r
+};\r
+\r
+static IDataObjectVtbl DataCache_IDataObject_VTable =\r
+{\r
+ DataCache_IDataObject_QueryInterface,\r
+ DataCache_IDataObject_AddRef,\r
+ DataCache_IDataObject_Release,\r
+ DataCache_GetData,\r
+ DataCache_GetDataHere,\r
+ DataCache_QueryGetData,\r
+ DataCache_GetCanonicalFormatEtc,\r
+ DataCache_IDataObject_SetData,\r
+ DataCache_EnumFormatEtc,\r
+ DataCache_DAdvise,\r
+ DataCache_DUnadvise,\r
+ DataCache_EnumDAdvise\r
+};\r
+\r
+static IPersistStorageVtbl DataCache_IPersistStorage_VTable =\r
+{\r
+ DataCache_IPersistStorage_QueryInterface,\r
+ DataCache_IPersistStorage_AddRef,\r
+ DataCache_IPersistStorage_Release,\r
+ DataCache_GetClassID,\r
+ DataCache_IsDirty,\r
+ DataCache_InitNew,\r
+ DataCache_Load,\r
+ DataCache_Save,\r
+ DataCache_SaveCompleted,\r
+ DataCache_HandsOffStorage\r
+};\r
+\r
+static IViewObject2Vtbl DataCache_IViewObject2_VTable =\r
+{\r
+ DataCache_IViewObject2_QueryInterface,\r
+ DataCache_IViewObject2_AddRef,\r
+ DataCache_IViewObject2_Release,\r
+ DataCache_Draw,\r
+ DataCache_GetColorSet,\r
+ DataCache_Freeze,\r
+ DataCache_Unfreeze,\r
+ DataCache_SetAdvise,\r
+ DataCache_GetAdvise,\r
+ DataCache_GetExtent\r
+};\r
+\r
+static IOleCache2Vtbl DataCache_IOleCache2_VTable =\r
+{\r
+ DataCache_IOleCache2_QueryInterface,\r
+ DataCache_IOleCache2_AddRef,\r
+ DataCache_IOleCache2_Release,\r
+ DataCache_Cache,\r
+ DataCache_Uncache,\r
+ DataCache_EnumCache,\r
+ DataCache_InitCache,\r
+ DataCache_IOleCache2_SetData,\r
+ DataCache_UpdateCache,\r
+ DataCache_DiscardCache\r
+};\r
+\r
+static IOleCacheControlVtbl DataCache_IOleCacheControl_VTable =\r
+{\r
+ DataCache_IOleCacheControl_QueryInterface,\r
+ DataCache_IOleCacheControl_AddRef,\r
+ DataCache_IOleCacheControl_Release,\r
+ DataCache_OnRun,\r
+ DataCache_OnStop\r
+};\r
+\r
+/******************************************************************************\r
+ * CreateDataCache [OLE32.@]\r
+ */\r
+HRESULT WINAPI CreateDataCache(\r
+ LPUNKNOWN pUnkOuter,\r
+ REFCLSID rclsid,\r
+ REFIID riid,\r
+ LPVOID* ppvObj)\r
+{\r
+ DataCache* newCache = NULL;\r
+ HRESULT hr = S_OK;\r
+\r
+ TRACE("(%s, %p, %s, %p)\n", debugstr_guid(rclsid), pUnkOuter, debugstr_guid(riid), ppvObj);\r
+\r
+ /*\r
+ * Sanity check\r
+ */\r
+ if (ppvObj==0)\r
+ return E_POINTER;\r
+\r
+ *ppvObj = 0;\r
+\r
+ /*\r
+ * If this cache is constructed for aggregation, make sure\r
+ * the caller is requesting the IUnknown interface.\r
+ * This is necessary because it's the only time the non-delegating\r
+ * IUnknown pointer can be returned to the outside.\r
+ */\r
+ if ( (pUnkOuter!=NULL) &&\r
+ (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) != 0) )\r
+ return CLASS_E_NOAGGREGATION;\r
+\r
+ /*\r
+ * Try to construct a new instance of the class.\r
+ */\r
+ newCache = DataCache_Construct(rclsid,\r
+ pUnkOuter);\r
+\r
+ if (newCache == 0)\r
+ return E_OUTOFMEMORY;\r
+\r
+ /*\r
+ * Make sure it supports the interface required by the caller.\r
+ */\r
+ hr = IUnknown_QueryInterface((IUnknown*)&(newCache->lpvtbl2), riid, ppvObj);\r
+\r
+ /*\r
+ * Release the reference obtained in the constructor. If\r
+ * the QueryInterface was unsuccessful, it will free the class.\r
+ */\r
+ IUnknown_Release((IUnknown*)&(newCache->lpvtbl2));\r
+\r
+ return hr;\r
+}\r
+\r
+/*********************************************************\r
+ * Method implementation for DataCache class.\r
+ */\r
+static DataCache* DataCache_Construct(\r
+ REFCLSID clsid,\r
+ LPUNKNOWN pUnkOuter)\r
+{\r
+ DataCache* newObject = 0;\r
+\r
+ /*\r
+ * Allocate space for the object.\r
+ */\r
+ newObject = HeapAlloc(GetProcessHeap(), 0, sizeof(DataCache));\r
+\r
+ if (newObject==0)\r
+ return newObject;\r
+\r
+ /*\r
+ * Initialize the virtual function table.\r
+ */\r
+ newObject->lpvtbl1 = &DataCache_IDataObject_VTable;\r
+ newObject->lpvtbl2 = &DataCache_NDIUnknown_VTable;\r
+ newObject->lpvtbl3 = &DataCache_IPersistStorage_VTable;\r
+ newObject->lpvtbl4 = &DataCache_IViewObject2_VTable;\r
+ newObject->lpvtbl5 = &DataCache_IOleCache2_VTable;\r
+ newObject->lpvtbl6 = &DataCache_IOleCacheControl_VTable;\r
+\r
+ /*\r
+ * Start with one reference count. The caller of this function\r
+ * must release the interface pointer when it is done.\r
+ */\r
+ newObject->ref = 1;\r
+\r
+ /*\r
+ * Initialize the outer unknown\r
+ * We don't keep a reference on the outer unknown since, the way\r
+ * aggregation works, our lifetime is at least as large as it's\r
+ * lifetime.\r
+ */\r
+ if (pUnkOuter==NULL)\r
+ pUnkOuter = (IUnknown*)&(newObject->lpvtbl2);\r
+\r
+ newObject->outerUnknown = pUnkOuter;\r
+\r
+ /*\r
+ * Initialize the other members of the structure.\r
+ */\r
+ newObject->presentationStorage = NULL;\r
+ newObject->sinkAspects = 0;\r
+ newObject->sinkAdviseFlag = 0;\r
+ newObject->sinkInterface = 0;\r
+\r
+ return newObject;\r
+}\r
--- /dev/null
+/* Simple dictionary implementation using a linked list.
+ * FIXME: a skip list would be faster.
+ *
+ * Copyright 2005 Juan Lang
+ *
+ * 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
+ */
+#include <assert.h>
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+#include "dictionary.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(storage);
+
+struct dictionary_entry
+{
+ void *key;
+ void *value;
+ struct dictionary_entry *next;
+};
+
+struct dictionary
+{
+ comparefunc comp;
+ destroyfunc destroy;
+ void *extra;
+ struct dictionary_entry *head;
+ UINT num_entries;
+};
+
+struct dictionary *dictionary_create(comparefunc c, destroyfunc d, void *extra)
+{
+ struct dictionary *ret;
+
+ TRACE("(%p, %p, %p)\n", c, d, extra);
+ if (!c)
+ return NULL;
+ ret = HeapAlloc(GetProcessHeap(), 0, sizeof(struct dictionary));
+ if (ret)
+ {
+ ret->comp = c;
+ ret->destroy = d;
+ ret->extra = extra;
+ ret->head = NULL;
+ ret->num_entries = 0;
+ }
+ TRACE("returning %p\n", ret);
+ return ret;
+}
+
+void dictionary_destroy(struct dictionary *d)
+{
+ TRACE("(%p)\n", d);
+ if (d)
+ {
+ struct dictionary_entry *p;
+
+ for (p = d->head; p; )
+ {
+ struct dictionary_entry *next = p->next;
+
+ if (d->destroy)
+ d->destroy(p->key, p->value, d->extra);
+ HeapFree(GetProcessHeap(), 0, p);
+ p = next;
+ }
+ HeapFree(GetProcessHeap(), 0, d);
+ }
+}
+
+UINT dictionary_num_entries(struct dictionary *d)
+{
+ return d ? d->num_entries : 0;
+}
+
+/* Returns the address of the pointer to the node containing k. (It returns
+ * the address of either h->head or the address of the next member of the
+ * prior node. It's useful when you want to delete.)
+ * Assumes h and prev are not NULL.
+ */
+static struct dictionary_entry **dictionary_find_internal(struct dictionary *d,
+ const void *k)
+{
+ struct dictionary_entry **ret = NULL;
+ struct dictionary_entry *p;
+
+ assert(d);
+ /* special case for head containing the desired element */
+ if (d->head && d->comp(k, d->head->key, d->extra) == 0)
+ ret = &d->head;
+ for (p = d->head; !ret && p && p->next; p = p->next)
+ {
+ if (d->comp(k, p->next->key, d->extra) == 0)
+ ret = &p->next;
+ }
+ return ret;
+}
+
+void dictionary_insert(struct dictionary *d, const void *k, const void *v)
+{
+ struct dictionary_entry **prior;
+
+ TRACE("(%p, %p, %p)\n", d, k, v);
+ if (!d)
+ return;
+ if ((prior = dictionary_find_internal(d, k)))
+ {
+ if (d->destroy)
+ d->destroy((*prior)->key, (*prior)->value, d->extra);
+ (*prior)->key = (void *)k;
+ (*prior)->value = (void *)v;
+ }
+ else
+ {
+ struct dictionary_entry *elem = (struct dictionary_entry *)
+ HeapAlloc(GetProcessHeap(), 0, sizeof(struct dictionary_entry));
+
+ if (!elem)
+ return;
+ elem->key = (void *)k;
+ elem->value = (void *)v;
+ elem->next = d->head;
+ d->head = elem;
+ d->num_entries++;
+ }
+}
+
+BOOL dictionary_find(struct dictionary *d, const void *k, void **value)
+{
+ struct dictionary_entry **prior;
+ BOOL ret = FALSE;
+
+ TRACE("(%p, %p, %p)\n", d, k, value);
+ if (!d)
+ return FALSE;
+ if (!value)
+ return FALSE;
+ if ((prior = dictionary_find_internal(d, k)))
+ {
+ *value = (*prior)->value;
+ ret = TRUE;
+ }
+ TRACE("returning %d (%p)\n", ret, *value);
+ return ret;
+}
+
+void dictionary_remove(struct dictionary *d, const void *k)
+{
+ struct dictionary_entry **prior, *temp;
+
+ TRACE("(%p, %p)\n", d, k);
+ if (!d)
+ return;
+ if ((prior = dictionary_find_internal(d, k)))
+ {
+ temp = *prior;
+ if (d->destroy)
+ d->destroy((*prior)->key, (*prior)->value, d->extra);
+ *prior = (*prior)->next;
+ HeapFree(GetProcessHeap(), 0, temp);
+ d->num_entries--;
+ }
+}
+
+void dictionary_enumerate(struct dictionary *d, enumeratefunc e, void *closure)
+{
+ struct dictionary_entry *p;
+
+ TRACE("(%p, %p, %p)\n", d, e, closure);
+ if (!d)
+ return;
+ if (!e)
+ return;
+ for (p = d->head; p; p = p->next)
+ if (!e(p->key, p->value, d->extra, closure))
+ break;
+}
--- /dev/null
+/* Simple dictionary
+ *
+ * Copyright 2005 Juan Lang
+ *
+ * This is a pretty basic dictionary, or map if you prefer. It's not
+ * thread-safe.
+ *
+ * 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
+ */
+#ifndef __DICTIONARY_H__
+#define __DICTIONARY_H__
+
+#include <stdarg.h>
+#include "windef.h"
+#include "winbase.h"
+
+struct dictionary;
+
+/* Returns whether key a is less than, equal to, or greater than key b, in
+ * the same way (a - b) would for integers or strcmp(a, b) would for ANSI
+ * strings.
+ */
+typedef int (*comparefunc)(const void *a, const void *b, void *extra);
+
+/* Called for every element removed from the dictionary. See
+ * dictionary_destroy, dictionary_insert, and dictionary_remove.
+ */
+typedef void (*destroyfunc)(void *k, void *v, void *extra);
+
+/* Called for each element in the dictionary. Return FALSE if you don't want
+ * to enumerate any more.
+ */
+typedef BOOL (*enumeratefunc)(const void *k, const void *v, void *extra,
+ void *closure);
+
+/* Constructs a dictionary, using c as a comparison function for keys.
+ * If d is not NULL, it will be called whenever an item is about to be removed
+ * from the table, for example when dictionary_remove is called for a key, or
+ * when dictionary_destroy is called.
+ * extra is passed to c (and d, if it's provided).
+ * Assumes c is not NULL.
+ */
+struct dictionary *dictionary_create(comparefunc c, destroyfunc d, void *extra);
+
+/* Assumes d is not NULL. */
+void dictionary_destroy(struct dictionary *d);
+
+/* Returns how many entries have been stored in the dictionary. If two values
+ * with the same key are inserted, only one is counted.
+ */
+UINT dictionary_num_entries(struct dictionary *d);
+
+/* Sets an element with key k and value v to the dictionary. If a value
+ * already exists with key k, its value is replaced, and the destroyfunc (if
+ * set) is called for the previous item.
+ * Assumes k and v can be bitwise-copied.
+ * Both k and v are allowed to be NULL, in case you want to use integer
+ * values for either the key or the value.
+ * Assumes d is not NULL.
+ */
+void dictionary_insert(struct dictionary *d, const void *k, const void *v);
+
+/* If a value with key k has been inserted into the dictionary, *v is set
+ * to its associated value. Returns FALSE if the key is not found, and TRUE
+ * if it is. *v is undefined if it returns FALSE. (It is not set to NULL,
+ * because this dictionary doesn't prevent you from using NULL as a value
+ * value; see dictionary_insert.)
+ * Assumes d and v are not NULL.
+ */
+BOOL dictionary_find(struct dictionary *d, const void *k, void **v);
+
+/* Removes the element with key k from the dictionary. Calls the destroyfunc
+ * for the dictionary with the element if found (so you may destroy it if it's
+ * dynamically allocated.)
+ * Assumes d is not NULL.
+ */
+void dictionary_remove(struct dictionary *d, const void *k);
+
+void dictionary_enumerate(struct dictionary *d, enumeratefunc e, void *closure);
+
+#endif /* ndef __DICTIONARY_H__ */
* buffer for the character count and an extra character at the\r
* end for the '\0'.\r
*/\r
- newBuffer = (DWORD*)HeapAlloc(GetProcessHeap(),\r
- 0,\r
+ newBuffer = HeapAlloc(GetProcessHeap(), 0,\r
bufferSize + sizeof(WCHAR) + sizeof(DWORD));\r
\r
/*\r
static ISupportErrorInfoVtbl ISupportErrorInfoImpl_VTable;\r
\r
/*\r
- converts a objectpointer to This\r
+ converts an object pointer to This\r
*/\r
#define _IErrorInfo_Offset ((int)(&(((ErrorInfoImpl*)0)->lpvtei)))\r
#define _ICOM_THIS_From_IErrorInfo(class, name) class* This = (class*)(((char*)name)-_IErrorInfo_Offset)\r
#define _ICOM_THIS_From_ISupportErrorInfo(class, name) class* This = (class*)(((char*)name)-_ISupportErrorInfo_Offset)\r
\r
/*\r
- converts This to a objectpointer\r
+ converts This to an object pointer\r
*/\r
#define _IErrorInfo_(This) (IErrorInfo*)&(This->lpvtei)\r
#define _ICreateErrorInfo_(This) (ICreateErrorInfo*)&(This->lpvtcei)\r
\r
TRACE ("(%p %p)\n", punkOuter, ppunkMarshal);\r
\r
- ftm = (FTMarshalImpl *) HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));\r
+ ftm = HeapAlloc (GetProcessHeap (), 0, sizeof (FTMarshalImpl));\r
if (!ftm)\r
return E_OUTOFMEMORY;\r
\r
*/\r
struct HGLOBALStreamImpl\r
{\r
- IStreamVtbl *lpVtbl; /* Needs to be the first item in the stuct\r
- * since we want to cast this in a IStream pointer */\r
+ IStreamVtbl *lpVtbl; /* Needs to be the first item in the struct\r
+ * since we want to cast this in an IStream pointer */\r
\r
/*\r
* Reference count\r
{\r
LPVOID *NewSpyedBlocks;\r
\r
- if (!Malloc32.SpyedBlocks) NewSpyedBlocks = LocalAlloc(GMEM_ZEROINIT, NewLength * sizeof(PVOID));\r
- else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), GMEM_ZEROINIT);\r
+ if (!Malloc32.SpyedBlocks) NewSpyedBlocks = LocalAlloc(LMEM_ZEROINIT, NewLength * sizeof(PVOID));\r
+ else NewSpyedBlocks = LocalReAlloc(Malloc32.SpyedBlocks, NewLength * sizeof(PVOID), LMEM_ZEROINIT);\r
if (NewSpyedBlocks) {\r
Malloc32.SpyedBlocks = NewSpyedBlocks;\r
Malloc32.SpyedBlockTableLength = NewLength;\r
}\r
\r
/* creates a new stub manager */\r
-HRESULT register_ifstub(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags)\r
+HRESULT marshal_object(APARTMENT *apt, STDOBJREF *stdobjref, REFIID riid, IUnknown *obj, MSHLFLAGS mshlflags)\r
{\r
struct stub_manager *manager;\r
struct ifstub *ifstub;\r
IPSFactoryBuffer *psfb;\r
HRESULT hr;\r
\r
+ hr = apartment_getoxid(apt, &stdobjref->oxid);\r
+ if (hr != S_OK)\r
+ return hr;\r
+\r
hr = get_facbuf_for_iid(riid, &psfb);\r
if (hr != S_OK)\r
{\r
else\r
stdobjref->flags = SORF_NULL;\r
\r
- stdobjref->oxid = apt->oxid;\r
-\r
/* FIXME: what happens if we register an interface twice with different\r
* marshaling flags? */\r
if ((manager = get_stub_manager_from_object(apt, obj)))\r
\r
manager = new_stub_manager(apt, obj, mshlflags);\r
if (!manager)\r
+ {\r
+ IRpcStubBuffer_Release(stub);\r
return E_OUTOFMEMORY;\r
+ }\r
}\r
stdobjref->oid = manager->oid;\r
\r
static HRESULT ifproxy_get_public_ref(struct ifproxy * This)\r
{\r
HRESULT hr = S_OK;\r
- /* FIXME: as this call could possibly be going over the network, we\r
- * are going to spend a long time in this CS. We might want to replace\r
- * this with a mutex */\r
- EnterCriticalSection(&This->parent->cs);\r
+\r
+ if (WAIT_OBJECT_0 != WaitForSingleObject(This->parent->remoting_mutex, INFINITE))\r
+ {\r
+ ERR("Wait failed for ifproxy %p\n", This);\r
+ return E_UNEXPECTED;\r
+ }\r
+\r
if (This->refs == 0)\r
{\r
IRemUnknown *remunk = NULL;\r
ERR("IRemUnknown_RemAddRef returned with 0x%08lx, hrref = 0x%08lx\n", hr, hrref);\r
}\r
}\r
- LeaveCriticalSection(&This->parent->cs);\r
+ ReleaseMutex(This->parent->remoting_mutex);\r
\r
return hr;\r
}\r
{\r
HRESULT hr = S_OK;\r
\r
- /* FIXME: as this call could possibly be going over the network, we\r
- * are going to spend a long time in this CS. We might want to replace\r
- * this with a mutex */\r
- EnterCriticalSection(&This->parent->cs);\r
+ if (WAIT_OBJECT_0 != WaitForSingleObject(This->parent->remoting_mutex, INFINITE))\r
+ {\r
+ ERR("Wait failed for ifproxy %p\n", This);\r
+ return E_UNEXPECTED;\r
+ }\r
+\r
if (This->refs > 0)\r
{\r
IRemUnknown *remunk = NULL;\r
ERR("IRemUnknown_RemRelease failed with error 0x%08lx\n", hr);\r
}\r
}\r
- LeaveCriticalSection(&This->parent->cs);\r
+ ReleaseMutex(This->parent->remoting_mutex);\r
\r
return hr;\r
}\r
struct proxy_manager * This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));\r
if (!This) return E_OUTOFMEMORY;\r
\r
+ This->remoting_mutex = CreateMutexW(NULL, FALSE, NULL);\r
+ if (!This->remoting_mutex)\r
+ {\r
+ HeapFree(GetProcessHeap(), 0, This);\r
+ return HRESULT_FROM_WIN32(GetLastError());\r
+ }\r
+\r
This->lpVtbl = &ClientIdentity_Vtbl;\r
\r
list_init(&This->entry);\r
list_init(&This->interfaces);\r
\r
InitializeCriticalSection(&This->cs);\r
+ DEBUG_SET_CRITSEC_NAME(&This->cs, "proxy_manager");\r
\r
/* the apartment the object was unmarshaled into */\r
This->parent = apt;\r
\r
/* the DCOM draft specification states that the SORF_NOPING flag is\r
* proxy manager specific, not ifproxy specific, so this implies that we\r
- * should store the STDOBJREF flags in the proxy manager. */\r
+ * should store the STDOBJREF flags here in the proxy manager. */\r
This->sorflags = sorflags;\r
\r
/* we create the IRemUnknown proxy on demand */\r
\r
if (This->remunk) IRemUnknown_Release(This->remunk);\r
\r
+ DEBUG_CLEAR_CRITSEC_NAME(&This->cs);\r
DeleteCriticalSection(&This->cs);\r
\r
+ CloseHandle(This->remoting_mutex);\r
+\r
HeapFree(GetProcessHeap(), 0, This);\r
}\r
\r
return found;\r
}\r
\r
-HRESULT MARSHAL_Disconnect_Proxies(APARTMENT *apt)\r
+HRESULT apartment_disconnectproxies(struct apartment *apt)\r
{\r
struct list * cursor;\r
\r
- EnterCriticalSection(&apt->cs);\r
LIST_FOR_EACH(cursor, &apt->proxies)\r
{\r
struct proxy_manager * proxy = LIST_ENTRY(cursor, struct proxy_manager, entry);\r
proxy_manager_disconnect(proxy);\r
}\r
- LeaveCriticalSection(&apt->cs);\r
\r
return S_OK;\r
}\r
return E_NOINTERFACE;\r
}\r
\r
- hres = register_ifstub(apt, &stdobjref, riid, pUnk, mshlflags);\r
+ hres = marshal_object(apt, &stdobjref, riid, pUnk, mshlflags);\r
\r
IUnknown_Release(pUnk);\r
\r
HRESULT hres;\r
APARTMENT *apt = COM_CurrentApt();\r
APARTMENT *stub_apt;\r
+ OXID oxid;\r
\r
TRACE("(...,%s,....)\n",debugstr_guid(riid));\r
\r
/* read STDOBJREF from wire */\r
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);\r
if (hres) return hres;\r
- \r
+\r
+ hres = apartment_getoxid(apt, &oxid);\r
+ if (hres) return hres;\r
+\r
/* check if we're marshalling back to ourselves */\r
- if ((apt->oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid)))\r
+ if ((oxid == stdobjref.oxid) && (stubmgr = get_stub_manager(apt, stdobjref.oid)))\r
{\r
TRACE("Unmarshalling object marshalled in same apartment for iid %s, "\r
"returning original object %p\n", debugstr_guid(riid), stubmgr->object);\r
* ignore table marshaling and normal marshaling rules regarding number of\r
* unmarshals, etc, but if you abuse these rules then your proxy could end\r
* up returning RPC_E_DISCONNECTED. */\r
- if ((stub_apt = COM_ApartmentFromOXID(stdobjref.oxid, TRUE)))\r
+ if ((stub_apt = apartment_findfromoxid(stdobjref.oxid, TRUE)))\r
{\r
if ((stubmgr = get_stub_manager(stub_apt, stdobjref.oid)))\r
{\r
hres = CO_E_OBJNOTCONNECTED;\r
}\r
\r
- COM_ApartmentRelease(stub_apt);\r
+ apartment_release(stub_apt);\r
}\r
else\r
TRACE("Treating unmarshal from OXID %s as inter-process\n",\r
hres = IStream_Read(pStm, &stdobjref, sizeof(stdobjref), &res);\r
if (hres) return hres;\r
\r
- if (!(apt = COM_ApartmentFromOXID(stdobjref.oxid, TRUE)))\r
+ if (!(apt = apartment_findfromoxid(stdobjref.oxid, TRUE)))\r
{\r
WARN("Could not map OXID %s to apartment object\n",\r
wine_dbgstr_longlong(stdobjref.oxid));\r
stub_manager_release_marshal_data(stubmgr, stdobjref.cPublicRefs);\r
\r
stub_manager_int_release(stubmgr);\r
- COM_ApartmentRelease(apt);\r
+ apartment_release(apt);\r
\r
return S_OK;\r
}\r
struct HGLOBALLockBytesImpl\r
{\r
/*\r
- * Needs to be the first item in the stuct\r
+ * Needs to be the first item in the struct\r
* since we want to cast this in an ILockBytes pointer\r
*/\r
ILockBytesVtbl *lpVtbl;\r
struct HGLOBALLockBytesImpl16\r
{\r
/*\r
- * Needs to be the first item in the stuct\r
+ * Needs to be the first item in the struct\r
* since we want to cast this in an ILockBytes pointer\r
*/\r
ILockBytes16Vtbl *lpVtbl;\r
\r
} RunningObjectTableImpl;\r
\r
-RunningObjectTableImpl* runningObjectTableInstance=0;\r
+static RunningObjectTableImpl* runningObjectTableInstance = NULL;\r
\r
/* IRunningObjectTable prototype functions : */\r
/* IUnknown functions*/\r
/***********************************************************************\r
* RunningObjectTable_Initialize\r
*/\r
-HRESULT WINAPI RunningObjectTableImpl_Destroy()\r
+HRESULT WINAPI RunningObjectTableImpl_Destroy(void)\r
{\r
TRACE("()\n");\r
\r
\r
/* free the ROT structure memory */\r
HeapFree(GetProcessHeap(),0,runningObjectTableInstance);\r
+ runningObjectTableInstance = NULL;\r
\r
return S_OK;\r
}\r
/*\r
* OLE2 library\r
*\r
- * Copyright 1995 Martin von Loewis\r
- * Copyright 1999 Francis Beaudet\r
- * Copyright 1999 Noel Borthwick\r
+ * Copyright 1995 Martin von Loewis\r
+ * Copyright 1999 Francis Beaudet\r
+ * Copyright 1999 Noel Borthwick\r
+ * Copyright 1999, 2000 Marcus Meissner\r
*\r
* This library is free software; you can redistribute it and/or\r
* modify it under the terms of the GNU Lesser General Public\r
/******************************************************************************\r
* These are the prototypes of the OLE Clipboard initialization methods (in clipboard.c)\r
*/\r
-void OLEClipbrd_UnInitialize(void);\r
-void OLEClipbrd_Initialize(void);\r
+extern void OLEClipbrd_UnInitialize(void);\r
+extern void OLEClipbrd_Initialize(void);\r
\r
/******************************************************************************\r
* These are the prototypes of the utility methods used for OLE Drag n Drop\r
CoTaskMemFree(pClipDataArray[i].pClipData);\r
}\r
\r
+/***********************************************************************\r
+ * PropSysAllocString [OLE32.@]\r
+ * NOTES:\r
+ * Basically a copy of SysAllocStringLen.\r
+ */\r
+BSTR WINAPI PropSysAllocString(LPCOLESTR str)\r
+{\r
+ DWORD bufferSize;\r
+ DWORD* newBuffer;\r
+ WCHAR* stringBuffer;\r
+ int len;\r
+\r
+ if (!str) return 0;\r
+\r
+ len = lstrlenW(str);\r
+ /*\r
+ * Find the length of the buffer passed-in in bytes.\r
+ */\r
+ bufferSize = len * sizeof (WCHAR);\r
+\r
+ /*\r
+ * Allocate a new buffer to hold the string.\r
+ * don't forget to keep an empty spot at the beginning of the\r
+ * buffer for the character count and an extra character at the\r
+ * end for the NULL.\r
+ */\r
+ newBuffer = HeapAlloc(GetProcessHeap(), 0,\r
+ bufferSize + sizeof(WCHAR) + sizeof(DWORD));\r
+\r
+ /*\r
+ * If the memory allocation failed, return a null pointer.\r
+ */\r
+ if (newBuffer==0)\r
+ return 0;\r
+\r
+ /*\r
+ * Copy the length of the string in the placeholder.\r
+ */\r
+ *newBuffer = bufferSize;\r
+\r
+ /*\r
+ * Skip the byte count.\r
+ */\r
+ newBuffer++;\r
+\r
+ /*\r
+ * Copy the information in the buffer.\r
+ * Since it is valid to pass a NULL pointer here, we'll initialize the\r
+ * buffer to nul if it is the case.\r
+ */\r
+ if (str != 0)\r
+ memcpy(newBuffer, str, bufferSize);\r
+ else\r
+ memset(newBuffer, 0, bufferSize);\r
+\r
+ /*\r
+ * Make sure that there is a nul character at the end of the\r
+ * string.\r
+ */\r
+ stringBuffer = (WCHAR*)newBuffer;\r
+ stringBuffer[len] = L'\0';\r
+\r
+ return (LPWSTR)stringBuffer;\r
+}\r
+\r
+/***********************************************************************\r
+ * PropSysFreeString [OLE32.@]\r
+ * NOTES\r
+ * Copy of SysFreeString.\r
+ */\r
+void WINAPI PropSysFreeString(LPOLESTR str)\r
+{\r
+ DWORD* bufferPointer;\r
+\r
+ /* NULL is a valid parameter */\r
+ if(!str) return;\r
+\r
+ /*\r
+ * We have to be careful when we free a BSTR pointer, it points to\r
+ * the beginning of the string but it skips the byte count contained\r
+ * before the string.\r
+ */\r
+ bufferPointer = (DWORD*)str;\r
+\r
+ bufferPointer--;\r
+\r
+ /*\r
+ * Free the memory from its "real" origin.\r
+ */\r
+ HeapFree(GetProcessHeap(), 0, bufferPointer);\r
+}\r
+\r
/******************************************************************************\r
* Check if a PROPVARIANT's type is valid.\r
*/\r
break;\r
case VT_BSTR:\r
if (pvar->u.bstrVal)\r
- {\r
- FIXME("Need to load OLEAUT32 for SysFreeString\n");\r
- /* SysFreeString(pvar->u.bstrVal); */\r
- }\r
+ PropSysFreeString(pvar->u.bstrVal);\r
break;\r
case VT_CF:\r
if (pvar->u.pclipdata)\r
}\r
break;\r
case VT_BSTR:\r
- FIXME("Need to copy BSTR\n");\r
+ pvarDest->u.bstrVal = PropSysAllocString(pvarSrc->u.bstrVal);\r
break;\r
case VT_CF:\r
if (pvarSrc->u.pclipdata)\r
LPCOLESTR16 lpszSourceFile,\r
UINT16 iIconIndex\r
) {\r
- METAFILEPICT16 *mf;\r
- HGLOBAL16 hmf;\r
+ METAFILEPICT16 *mf16;\r
+ HGLOBAL16 hmf16;\r
+ HMETAFILE hmf;\r
+ INT mfSize;\r
HDC hdc;\r
\r
- FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n\n\n", hIcon, lpszLabel, lpszSourceFile, iIconIndex);\r
-\r
if (!hIcon) {\r
if (lpszSourceFile) {\r
HINSTANCE16 hInstance = LoadLibrary16(lpszSourceFile);\r
return 0;\r
}\r
\r
- hdc = CreateMetaFileA(NULL);\r
+ FIXME("(%04x, '%s', '%s', %d): incorrect metrics, please try to correct them !\n", \r
+ hIcon, lpszLabel, lpszSourceFile, iIconIndex);\r
+\r
+ hdc = CreateMetaFileW(NULL);\r
DrawIcon(hdc, 0, 0, HICON_32(hIcon)); /* FIXME */\r
TextOutA(hdc, 0, 0, lpszLabel, 1); /* FIXME */\r
- hmf = GlobalAlloc16(0, sizeof(METAFILEPICT16));\r
- mf = (METAFILEPICT16 *)GlobalLock16(hmf);\r
- mf->mm = MM_ANISOTROPIC;\r
- mf->xExt = 20; /* FIXME: bogus */\r
- mf->yExt = 20; /* dito */\r
- mf->hMF = CloseMetaFile16(HDC_16(hdc));\r
- return hmf;\r
+ hmf = CloseMetaFile(hdc);\r
+\r
+ hmf16 = GlobalAlloc16(0, sizeof(METAFILEPICT16));\r
+ mf16 = (METAFILEPICT16 *)GlobalLock16(hmf16);\r
+ mf16->mm = MM_ANISOTROPIC;\r
+ mf16->xExt = 20; /* FIXME: bogus */\r
+ mf16->yExt = 20; /* dito */\r
+ mfSize = GetMetaFileBitsEx(hmf, 0, 0);\r
+ mf16->hMF = GlobalAlloc16(GMEM_MOVEABLE, mfSize);\r
+ if(mf16->hMF)\r
+ {\r
+ GetMetaFileBitsEx(hmf, mfSize, GlobalLock16(mf16->hMF));\r
+ GlobalUnlock16(mf16->hMF);\r
+ }\r
+ return hmf16;\r
}\r
\r
\r
if (!size) return NULL;\r
bm.bmBits = HeapAlloc(GetProcessHeap(), 0, size);\r
if (!bm.bmBits) return NULL;\r
- if (!GetBitmapBits(hSrc, size, bm.bmBits))\r
- return NULL;\r
- hDst = CreateBitmapIndirect(&bm);\r
+ if (GetBitmapBits(hSrc, size, bm.bmBits))\r
+ hDst = CreateBitmapIndirect(&bm);\r
HeapFree(GetProcessHeap(), 0, bm.bmBits);\r
break;\r
}\r
@ stdcall -private DllUnregisterServer()\r
@ stdcall DoDragDrop(ptr ptr long ptr)\r
@ stub EnableHookObject\r
+@ stdcall FmtIdToPropStgName(ptr wstr)\r
@ stdcall FreePropVariantArray(long ptr)\r
@ stdcall GetClassFile(wstr ptr)\r
@ stdcall GetConvertStg(ptr)\r
@ stdcall OleUninitialize()\r
@ stub OpenOrCreateStream\r
@ stdcall ProgIDFromCLSID(ptr ptr)\r
-@ stub PropSysAllocString\r
-@ stub PropSysFreeString\r
+@ stdcall PropStgNameToFmtId(wstr ptr)\r
+@ stdcall PropSysAllocString(wstr)\r
+@ stdcall PropSysFreeString(wstr)\r
@ stdcall PropVariantClear(ptr)\r
@ stdcall PropVariantCopy(ptr ptr)\r
@ stdcall ReadClassStg(ptr ptr)\r
OleAdviseHolderImpl* lpoah;\r
DWORD index;\r
\r
- lpoah= (OleAdviseHolderImpl*)HeapAlloc(GetProcessHeap(),\r
- 0,\r
- sizeof(OleAdviseHolderImpl));\r
+ lpoah = HeapAlloc(GetProcessHeap(), 0, sizeof(OleAdviseHolderImpl));\r
\r
lpoah->lpVtbl = &oahvt;\r
lpoah->ref = 1;\r
{\r
DataAdviseHolder* newHolder;\r
\r
- newHolder = (DataAdviseHolder*)HeapAlloc(GetProcessHeap(),\r
- 0,\r
- sizeof(DataAdviseHolder));\r
+ newHolder = HeapAlloc(GetProcessHeap(), 0, sizeof(DataAdviseHolder));\r
\r
newHolder->lpVtbl = &DataAdviseHolderImpl_VTable;\r
newHolder->ref = 1;\r
TRACE("->CreateInstance(%s)\n",debugstr_guid(&iid));\r
hres = IUnknown_QueryInterface(This->pUnkServer,&IID_IClassFactory,(LPVOID*)&classfac);\r
if (hres) {\r
- FIXME("Ole server does not provide a IClassFactory?\n");\r
+ FIXME("Ole server does not provide an IClassFactory?\n");\r
return hres;\r
}\r
hres = IClassFactory_CreateInstance(classfac,NULL,&iid,(LPVOID*)&ppv);\r
/*\r
- * (Local) RPC Stuff\r
+ * RPC Manager\r
*\r
* Copyright 2001 Ove Kåven, TransGaming Technologies\r
* Copyright 2002 Marcus Meissner\r
RPC_BINDING_HANDLE bind; /* handle to the remote server */\r
} ClientRpcChannelBuffer;\r
\r
+struct dispatch_params\r
+{\r
+ RPCOLEMESSAGE *msg; /* message */\r
+ IRpcStubBuffer *stub; /* stub buffer, if applicable */\r
+ IRpcChannelBuffer *chan; /* server channel buffer, if applicable */\r
+ HANDLE handle; /* handle that will become signaled when call finishes */\r
+ RPC_STATUS status; /* status (out) */\r
+};\r
+\r
static HRESULT WINAPI RpcChannelBuffer_QueryInterface(LPRPCCHANNELBUFFER iface, REFIID riid, LPVOID *ppv)\r
{\r
*ppv = NULL;\r
RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg;\r
RPC_STATUS status;\r
\r
- TRACE("(%p)->(%p,%p)\n", This, olemsg, riid);\r
+ TRACE("(%p)->(%p,%s)\n", This, olemsg, debugstr_guid(riid));\r
\r
status = I_RpcGetBuffer(msg);\r
\r
RPC_CLIENT_INTERFACE *cif;\r
RPC_STATUS status;\r
\r
- TRACE("(%p)->(%p,%p)\n", This, olemsg, riid);\r
+ TRACE("(%p)->(%p,%s)\n", This, olemsg, debugstr_guid(riid));\r
\r
cif = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RPC_CLIENT_INTERFACE));\r
if (!cif)\r
return HRESULT_FROM_WIN32(status);\r
}\r
\r
-struct rpc_sendreceive_params\r
-{\r
- RPC_MESSAGE *msg;\r
- RPC_STATUS status;\r
-};\r
-\r
/* this thread runs an outgoing RPC */\r
static DWORD WINAPI rpc_sendreceive_thread(LPVOID param)\r
{\r
- struct rpc_sendreceive_params *data = (struct rpc_sendreceive_params *) param;\r
+ struct dispatch_params *data = (struct dispatch_params *) param;\r
\r
- TRACE("starting up\n");\r
-\r
/* FIXME: trap and rethrow RPC exceptions in app thread */\r
- data->status = I_RpcSendReceive(data->msg);\r
+ data->status = I_RpcSendReceive((RPC_MESSAGE *)data->msg);\r
\r
TRACE("completed with status 0x%lx\n", data->status);\r
\r
\r
static HRESULT WINAPI RpcChannelBuffer_SendReceive(LPRPCCHANNELBUFFER iface, RPCOLEMESSAGE *olemsg, ULONG *pstatus)\r
{\r
- RPC_MESSAGE *msg = (RPC_MESSAGE *)olemsg;\r
HRESULT hr = S_OK;\r
- HANDLE thread;\r
- struct rpc_sendreceive_params *params;\r
- DWORD tid, res;\r
RPC_STATUS status;\r
+ DWORD index;\r
+ struct dispatch_params *params;\r
+ DWORD tid;\r
\r
- TRACE("(%p)\n", msg);\r
+ TRACE("(%p) iMethod=%ld\n", olemsg, olemsg->iMethod);\r
\r
- params = HeapAlloc(GetProcessHeap(), 0, sizeof(*params));\r
+ params = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*params));\r
if (!params) return E_OUTOFMEMORY;\r
\r
- params->msg = msg;\r
+ params->msg = olemsg;\r
+ params->status = RPC_S_OK;\r
\r
/* we use a separate thread here because we need to be able to\r
* pump the message loop in the application thread: if we do not,\r
* and re-enter this STA from an incoming server thread will\r
* deadlock. InstallShield is an example of that.\r
*/\r
- \r
- thread = CreateThread(NULL, 0, rpc_sendreceive_thread, params, 0, &tid);\r
- if (!thread)\r
+ params->handle = CreateThread(NULL, 0, rpc_sendreceive_thread, params, 0, &tid);\r
+ if (!params->handle)\r
{\r
ERR("Could not create RpcSendReceive thread, error %lx\n", GetLastError());\r
- return E_UNEXPECTED;\r
- }\r
-\r
- while (TRUE)\r
- {\r
- TRACE("waiting for rpc completion or window message\n");\r
- res = MsgWaitForMultipleObjectsEx(1, &thread, INFINITE, QS_ALLINPUT, 0);\r
- \r
- if (res == WAIT_OBJECT_0 + 1) /* messages available */\r
- {\r
- MSG message;\r
- while (PeekMessageW(&message, NULL, 0, 0, PM_REMOVE))\r
- {\r
- /* FIXME: filter the messages here */\r
- if (message.message == DM_EXECUTERPC)\r
- TRACE("received DM_EXECUTRPC dispatch request, re-entering ...\n");\r
- else\r
- TRACE("received message whilst waiting for RPC: 0x%x\n", message.message);\r
- TranslateMessage(&message);\r
- DispatchMessageW(&message);\r
- }\r
- }\r
- else if (res == WAIT_OBJECT_0) \r
- {\r
- break; /* RPC is completed */\r
- }\r
- else\r
- {\r
- ERR("Unexpected wait termination: %ld, %ld\n", res, GetLastError());\r
- hr = E_UNEXPECTED;\r
- break;\r
- }\r
+ hr = E_UNEXPECTED;\r
}\r
\r
- CloseHandle(thread);\r
+ if (hr == S_OK)\r
+ hr = CoWaitForMultipleHandles(0, INFINITE, 1, ¶ms->handle, &index);\r
+ CloseHandle(params->handle);\r
\r
status = params->status;\r
HeapFree(GetProcessHeap(), 0, params);\r
params = NULL;\r
+\r
if (hr) return hr;\r
\r
if (pstatus) *pstatus = status;\r
if (status == RPC_S_OK)\r
hr = S_OK;\r
else if (status == RPC_S_CALL_FAILED)\r
- hr = *(HRESULT *)msg->Buffer;\r
+ hr = *(HRESULT *)olemsg->Buffer;\r
else\r
hr = HRESULT_FROM_WIN32(status);\r
\r
}\r
\r
\r
-HRESULT RPC_ExecuteCall(RPCOLEMESSAGE *msg, IRpcStubBuffer *stub)\r
+HRESULT RPC_ExecuteCall(struct dispatch_params *params)\r
{\r
- /* FIXME: pass server channel buffer, but don't create it every time */\r
- return IRpcStubBuffer_Invoke(stub, msg, NULL);\r
+ HRESULT hr = IRpcStubBuffer_Invoke(params->stub, params->msg, params->chan);\r
+ IRpcStubBuffer_Release(params->stub);\r
+ if (params->handle) SetEvent(params->handle);\r
+ return hr;\r
}\r
\r
static void __RPC_STUB dispatch_rpc(RPC_MESSAGE *msg)\r
{\r
+ struct dispatch_params *params;\r
IRpcStubBuffer *stub;\r
APARTMENT *apt;\r
IPID ipid;\r
\r
RpcBindingInqObject(msg->Handle, &ipid);\r
\r
+ TRACE("ipid = %s, iMethod = %d\n", debugstr_guid(&ipid), msg->ProcNum);\r
+\r
+ params = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*params));\r
+ if (!params) return RpcRaiseException(E_OUTOFMEMORY);\r
+\r
stub = ipid_to_apt_and_stubbuffer(&ipid, &apt);\r
if (!apt || !stub)\r
{\r
- if (apt) COM_ApartmentRelease(apt);\r
+ if (apt) apartment_release(apt);\r
/* ipid_to_apt_and_stubbuffer will already have logged the error */\r
return RpcRaiseException(RPC_E_DISCONNECTED);\r
}\r
\r
+ params->msg = (RPCOLEMESSAGE *)msg;\r
+ params->stub = stub;\r
+ params->chan = NULL; /* FIXME: pass server channel */\r
+ params->status = RPC_S_OK;\r
+\r
/* Note: this is the important difference between STAs and MTAs - we\r
* always execute RPCs to STAs in the thread that originally created the\r
* apartment (i.e. the one that pumps messages to the window) */\r
if (apt->model & COINIT_APARTMENTTHREADED)\r
- SendMessageW(apt->win, DM_EXECUTERPC, (WPARAM)msg, (LPARAM)stub);\r
+ {\r
+ params->handle = CreateEventW(NULL, FALSE, FALSE, NULL);\r
+\r
+ TRACE("Calling apartment thread 0x%08lx...\n", apt->tid);\r
+\r
+ PostMessageW(apt->win, DM_EXECUTERPC, 0, (LPARAM)params);\r
+ WaitForSingleObject(params->handle, INFINITE);\r
+ CloseHandle(params->handle);\r
+ }\r
else\r
- RPC_ExecuteCall((RPCOLEMESSAGE *)msg, stub);\r
+ RPC_ExecuteCall(params);\r
+\r
+ HeapFree(GetProcessHeap(), 0, params);\r
\r
- COM_ApartmentRelease(apt);\r
- IRpcStubBuffer_Release(stub);\r
+ apartment_release(apt);\r
}\r
\r
/* stub registration */\r
{\r
LPBIGBLOCKFILE This;\r
\r
- This = (LPBIGBLOCKFILE)HeapAlloc(GetProcessHeap(), 0, sizeof(BigBlockFile));\r
+ This = HeapAlloc(GetProcessHeap(), 0, sizeof(BigBlockFile));\r
\r
if (This == NULL)\r
return NULL;\r
* Copyright 1999 Sylvain St-Germain
* Copyright 1999 Thuy Nguyen
* Copyright 2005 Mike McCormack
+ * Copyright 2005 Juan Lang
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* 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
+ *
+ * There's a decent overview of property set storage here:
+ * http://msdn.microsoft.com/archive/en-us/dnarolegen/html/msdn_propset.asp
+ * It's a little bit out of date, and more definitive references are given
+ * below, but it gives the best "big picture" that I've found.
+ *
+ * TODO: There's a lot missing in here. Biggies:
+ * - There are all sorts of restricions I don't honor, like maximum property
+ * set byte size, maximum property name length
+ * - Certain bogus files could result in reading past the end of a buffer.
+ * - This will probably fail on big-endian machines, especially reading and
+ * writing strings.
+ * - Mac-generated files won't be read correctly, even if they're little
+ * endian, because I disregard whether the generator was a Mac. This means
+ * strings will probably be munged (as I don't understand Mac scripts.)
+ * - Not all PROPVARIANT types are supported.
+ * There are lots more unimplemented features, see FIXMEs below.
*/
#include <assert.h>
#include "winuser.h"
#include "wine/unicode.h"
#include "wine/debug.h"
-
+#include "dictionary.h"
#include "storage32.h"
WINE_DEFAULT_DEBUG_CHANNEL(storage);
#define _ICOM_THIS_From_IPropertySetStorage(class, name) \
class* This = (class*)(((char*)name)-_IPropertySetStorage_Offset)
+/* These are documented in MSDN, e.g.
+ * http://msdn.microsoft.com/library/en-us/stg/stg/property_set_header.asp
+ * http://msdn.microsoft.com/library/library/en-us/stg/stg/section.asp
+ * but they don't seem to be in any header file.
+ */
+#define PROPSETHDR_BYTEORDER_MAGIC 0xfffe
+#define PROPSETHDR_OSVER_KIND_WIN16 0
+#define PROPSETHDR_OSVER_KIND_MAC 1
+#define PROPSETHDR_OSVER_KIND_WIN32 2
+
+#define CP_UNICODE 1200
+
+/* The format version (and what it implies) is described here:
+ * http://msdn.microsoft.com/library/en-us/stg/stg/format_version.asp
+ */
+typedef struct tagPROPERTYSETHEADER
+{
+ WORD wByteOrder; /* always 0xfffe */
+ WORD wFormat; /* can be zero or one */
+ DWORD dwOSVer; /* OS version of originating system */
+ CLSID clsid; /* application CLSID */
+ DWORD reserved; /* always 1 */
+} PROPERTYSETHEADER;
+
+typedef struct tagFORMATIDOFFSET
+{
+ FMTID fmtid;
+ DWORD dwOffset; /* from beginning of stream */
+} FORMATIDOFFSET;
+
+typedef struct tagPROPERTYSECTIONHEADER
+{
+ DWORD cbSection;
+ DWORD cProperties;
+} PROPERTYSECTIONHEADER;
+
+typedef struct tagPROPERTYIDOFFSET
+{
+ DWORD propid;
+ DWORD dwOffset; /* from beginning of section */
+} PROPERTYIDOFFSET;
+
+struct tagPropertyStorage_impl;
+
+/* Initializes the property storage from the stream (and undoes any uncommitted
+ * changes in the process.) Returns an error if there is an error reading or
+ * if the stream format doesn't match what's expected.
+ */
+static HRESULT PropertyStorage_ReadFromStream(struct tagPropertyStorage_impl *);
+
+static HRESULT PropertyStorage_WriteToStream(struct tagPropertyStorage_impl *);
+
+/* Creates the dictionaries used by the property storage. If successful, all
+ * the dictionaries have been created. If failed, none has been. (This makes
+ * it a bit easier to deal with destroying them.)
+ */
+static HRESULT PropertyStorage_CreateDictionaries(
+ struct tagPropertyStorage_impl *);
+
+static void PropertyStorage_DestroyDictionaries(
+ struct tagPropertyStorage_impl *);
+
static IPropertyStorageVtbl IPropertyStorage_Vtbl;
/***********************************************************************
{
IPropertyStorageVtbl *vtbl;
DWORD ref;
+ CRITICAL_SECTION cs;
IStream *stm;
+ BOOL dirty;
+ FMTID fmtid;
+ CLSID clsid;
+ DWORD originatorOS;
+ DWORD grfFlags;
+ DWORD grfMode;
+ UINT codePage;
+ LCID locale;
+ PROPID highestProp;
+ struct dictionary *name_to_propid;
+ struct dictionary *propid_to_name;
+ struct dictionary *propid_to_prop;
} PropertyStorage_impl;
/************************************************************************
if (ref == 0)
{
TRACE("Destroying %p\n", This);
+ if (This->dirty)
+ IPropertyStorage_Commit(iface, STGC_DEFAULT);
IStream_Release(This->stm);
+ DeleteCriticalSection(&This->cs);
+ PropertyStorage_DestroyDictionaries(This);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
+static PROPVARIANT *PropertyStorage_FindProperty(PropertyStorage_impl *This,
+ DWORD propid)
+{
+ PROPVARIANT *ret = NULL;
+
+ assert(This);
+ dictionary_find(This->propid_to_prop, (void *)propid, (void **)&ret);
+ TRACE("returning %p\n", ret);
+ return ret;
+}
+
+/* Returns NULL if name is NULL. */
+static PROPVARIANT *PropertyStorage_FindPropertyByName(
+ PropertyStorage_impl *This, LPCWSTR name)
+{
+ PROPVARIANT *ret = NULL;
+ PROPID propid;
+
+ assert(This);
+ if (!name)
+ return NULL;
+ if (dictionary_find(This->name_to_propid, name, (void **)&propid))
+ ret = PropertyStorage_FindProperty(This, (PROPID)propid);
+ TRACE("returning %p\n", ret);
+ return ret;
+}
+
+static LPWSTR PropertyStorage_FindPropertyNameById(PropertyStorage_impl *This,
+ DWORD propid)
+{
+ LPWSTR ret = NULL;
+
+ assert(This);
+ dictionary_find(This->propid_to_name, (void *)propid, (void **)&ret);
+ TRACE("returning %p\n", ret);
+ return ret;
+}
+
/************************************************************************
* IPropertyStorage_fnReadMultiple (IPropertyStorage)
*/
const PROPSPEC rgpspec[],
PROPVARIANT rgpropvar[])
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ HRESULT hr = S_FALSE;
+ ULONG i;
+
+ TRACE("(%p, %ld, %p, %p)\n", iface, cpspec, rgpspec, rgpropvar);
+ if (!This)
+ return E_INVALIDARG;
+ if (cpspec && (!rgpspec || !rgpropvar))
+ return E_INVALIDARG;
+ EnterCriticalSection(&This->cs);
+ for (i = 0; i < cpspec; i++)
+ {
+ PropVariantInit(&rgpropvar[i]);
+ if (rgpspec[i].ulKind == PRSPEC_LPWSTR)
+ {
+ PROPVARIANT *prop = PropertyStorage_FindPropertyByName(This,
+ rgpspec[i].u.lpwstr);
+
+ if (prop)
+ PropVariantCopy(&rgpropvar[i], prop);
+ }
+ else
+ {
+ PROPVARIANT *prop = PropertyStorage_FindProperty(This,
+ rgpspec[i].u.propid);
+
+ if (prop)
+ PropVariantCopy(&rgpropvar[i], prop);
+ }
+ }
+ LeaveCriticalSection(&This->cs);
+ return hr;
+}
+
+static HRESULT PropertyStorage_StorePropWithId(PropertyStorage_impl *This,
+ PROPID propid, const PROPVARIANT *propvar)
+{
+ HRESULT hr = S_OK;
+ PROPVARIANT *prop = PropertyStorage_FindProperty(This, propid);
+
+ assert(This);
+ assert(propvar);
+ TRACE("Setting 0x%08lx to type %d\n", propid, propvar->vt);
+ if (prop)
+ {
+ PropVariantClear(prop);
+ PropVariantCopy(prop, propvar);
+ }
+ else
+ {
+ prop = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+ sizeof(PROPVARIANT));
+ if (prop)
+ {
+ PropVariantCopy(prop, propvar);
+ dictionary_insert(This->propid_to_prop, (void *)propid, prop);
+ if (propid > This->highestProp)
+ This->highestProp = propid;
+ }
+ else
+ hr = STG_E_INSUFFICIENTMEMORY;
+ }
+ return hr;
}
/************************************************************************
const PROPVARIANT rgpropvar[],
PROPID propidNameFirst)
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ HRESULT hr = S_OK;
+ ULONG i;
+
+ TRACE("(%p, %ld, %p, %p)\n", iface, cpspec, rgpspec, rgpropvar);
+ if (!This)
+ return E_INVALIDARG;
+ if (cpspec && (!rgpspec || !rgpropvar))
+ return E_INVALIDARG;
+ if (!(This->grfMode & STGM_READWRITE))
+ return STG_E_ACCESSDENIED;
+ EnterCriticalSection(&This->cs);
+ This->dirty = TRUE;
+ This->originatorOS = (DWORD)MAKELONG(LOWORD(GetVersion()),
+ PROPSETHDR_OSVER_KIND_WIN32) ;
+ for (i = 0; i < cpspec; i++)
+ {
+ if (rgpspec[i].ulKind == PRSPEC_LPWSTR)
+ {
+ PROPVARIANT *prop = PropertyStorage_FindPropertyByName(This,
+ rgpspec[i].u.lpwstr);
+
+ if (prop)
+ PropVariantCopy(prop, &rgpropvar[i]);
+ else
+ {
+ /* Note that I don't do the special cases here that I do below,
+ * because naming the special PIDs isn't supported.
+ */
+ if (propidNameFirst < PID_FIRST_USABLE ||
+ propidNameFirst >= PID_MIN_READONLY)
+ hr = STG_E_INVALIDPARAMETER;
+ else
+ {
+ PROPID nextId = max(propidNameFirst, This->highestProp + 1);
+ size_t len = strlenW(rgpspec[i].u.lpwstr) + 1;
+ LPWSTR name = HeapAlloc(GetProcessHeap(), 0,
+ len * sizeof(WCHAR));
+
+ strcpyW(name, rgpspec[i].u.lpwstr);
+ TRACE("Adding prop name %s, propid %ld\n", debugstr_w(name),
+ nextId);
+ dictionary_insert(This->name_to_propid, name,
+ (void *)nextId);
+ dictionary_insert(This->propid_to_name, (void *)nextId,
+ name);
+ hr = PropertyStorage_StorePropWithId(This, nextId,
+ &rgpropvar[i]);
+ }
+ }
+ }
+ else
+ {
+ switch (rgpspec[i].u.propid)
+ {
+ case PID_DICTIONARY:
+ /* Can't set the dictionary */
+ hr = STG_E_INVALIDPARAMETER;
+ break;
+ case PID_CODEPAGE:
+ /* Can only set the code page if nothing else has been set */
+ if (dictionary_num_entries(This->propid_to_prop) == 0 &&
+ rgpropvar[i].vt == VT_I2)
+ This->codePage = rgpropvar[i].u.iVal;
+ else
+ hr = STG_E_INVALIDPARAMETER;
+ break;
+ case PID_LOCALE:
+ /* Can only set the locale if nothing else has been set */
+ if (dictionary_num_entries(This->propid_to_prop) == 0 &&
+ rgpropvar[i].vt == VT_I4)
+ This->locale = rgpropvar[i].u.lVal;
+ else
+ hr = STG_E_INVALIDPARAMETER;
+ break;
+ case PID_ILLEGAL:
+ /* silently ignore like MSDN says */
+ break;
+ default:
+ if (rgpspec[i].u.propid >= PID_MIN_READONLY)
+ hr = STG_E_INVALIDPARAMETER;
+ else
+ hr = PropertyStorage_StorePropWithId(This,
+ rgpspec[i].u.propid, &rgpropvar[i]);
+ }
+ }
+ }
+ if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
+ IPropertyStorage_Commit(iface, STGC_DEFAULT);
+ LeaveCriticalSection(&This->cs);
+ return hr;
}
/************************************************************************
ULONG cpspec,
const PROPSPEC rgpspec[])
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ ULONG i;
+ HRESULT hr;
+
+ TRACE("(%p, %ld, %p)\n", iface, cpspec, rgpspec);
+ if (!This)
+ return E_INVALIDARG;
+ if (cpspec && !rgpspec)
+ return E_INVALIDARG;
+ if (!(This->grfMode & STGM_READWRITE))
+ return STG_E_ACCESSDENIED;
+ hr = S_OK;
+ EnterCriticalSection(&This->cs);
+ This->dirty = TRUE;
+ for (i = 0; i < cpspec; i++)
+ {
+ if (rgpspec[i].ulKind == PRSPEC_LPWSTR)
+ {
+ PROPID propid;
+
+ if (dictionary_find(This->name_to_propid,
+ (void *)rgpspec[i].u.lpwstr, (void **)&propid))
+ dictionary_remove(This->propid_to_prop, (void *)propid);
+ }
+ else
+ {
+ if (rgpspec[i].u.propid >= PID_FIRST_USABLE &&
+ rgpspec[i].u.propid < PID_MIN_READONLY)
+ dictionary_remove(This->propid_to_prop,
+ (void *)rgpspec[i].u.propid);
+ else
+ hr = STG_E_INVALIDPARAMETER;
+ }
+ }
+ if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
+ IPropertyStorage_Commit(iface, STGC_DEFAULT);
+ LeaveCriticalSection(&This->cs);
+ return hr;
}
/************************************************************************
const PROPID rgpropid[],
LPOLESTR rglpwstrName[])
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ ULONG i;
+ HRESULT hr = S_FALSE;
+
+ TRACE("(%p, %ld, %p, %p)\n", iface, cpropid, rgpropid, rglpwstrName);
+ if (!This)
+ return E_INVALIDARG;
+ if (cpropid && (!rgpropid || !rglpwstrName))
+ return E_INVALIDARG;
+ EnterCriticalSection(&This->cs);
+ for (i = 0; i < cpropid && SUCCEEDED(hr); i++)
+ {
+ LPWSTR name = PropertyStorage_FindPropertyNameById(This, rgpropid[i]);
+
+ if (name)
+ {
+ size_t len = lstrlenW(name);
+
+ hr = S_OK;
+ rglpwstrName[i] = CoTaskMemAlloc((len + 1) * sizeof(WCHAR));
+ if (rglpwstrName)
+ memcpy(rglpwstrName, name, (len + 1) * sizeof(WCHAR));
+ else
+ hr = STG_E_INSUFFICIENTMEMORY;
+ }
+ else
+ rglpwstrName[i] = NULL;
+ }
+ LeaveCriticalSection(&This->cs);
+ return hr;
}
/************************************************************************
const PROPID rgpropid[],
const LPOLESTR rglpwstrName[])
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ ULONG i;
+ HRESULT hr;
+
+ TRACE("(%p, %ld, %p, %p)\n", iface, cpropid, rgpropid, rglpwstrName);
+ if (!This)
+ return E_INVALIDARG;
+ if (cpropid && (!rgpropid || !rglpwstrName))
+ return E_INVALIDARG;
+ if (!(This->grfMode & STGM_READWRITE))
+ return STG_E_ACCESSDENIED;
+ hr = S_OK;
+ EnterCriticalSection(&This->cs);
+ This->dirty = TRUE;
+ for (i = 0; i < cpropid; i++)
+ {
+ if (rgpropid[i] != PID_ILLEGAL)
+ {
+ size_t len = lstrlenW(rglpwstrName[i]) + 1;
+ LPWSTR name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+
+ strcpyW(name, rglpwstrName[i]);
+ dictionary_insert(This->name_to_propid, name, (void *)rgpropid[i]);
+ dictionary_insert(This->propid_to_name, (void *)rgpropid[i], name);
+ }
+ }
+ if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
+ IPropertyStorage_Commit(iface, STGC_DEFAULT);
+ LeaveCriticalSection(&This->cs);
+ return hr;
}
/************************************************************************
ULONG cpropid,
const PROPID rgpropid[])
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ ULONG i;
+ HRESULT hr;
+
+ TRACE("(%p, %ld, %p)\n", iface, cpropid, rgpropid);
+ if (!This)
+ return E_INVALIDARG;
+ if (cpropid && !rgpropid)
+ return E_INVALIDARG;
+ if (!(This->grfMode & STGM_READWRITE))
+ return STG_E_ACCESSDENIED;
+ hr = S_OK;
+ EnterCriticalSection(&This->cs);
+ This->dirty = TRUE;
+ for (i = 0; i < cpropid; i++)
+ {
+ LPWSTR name = NULL;
+
+ if (dictionary_find(This->propid_to_name, (void *)rgpropid[i],
+ (void **)&name))
+ {
+ dictionary_remove(This->propid_to_name, (void *)rgpropid[i]);
+ dictionary_remove(This->name_to_propid, name);
+ }
+ }
+ if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
+ IPropertyStorage_Commit(iface, STGC_DEFAULT);
+ LeaveCriticalSection(&This->cs);
+ return hr;
}
/************************************************************************
IPropertyStorage* iface,
DWORD grfCommitFlags)
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ HRESULT hr;
+
+ TRACE("(%p, 0x%08lx)\n", iface, grfCommitFlags);
+ if (!This)
+ return E_INVALIDARG;
+ if (!(This->grfMode & STGM_READWRITE))
+ return STG_E_ACCESSDENIED;
+ EnterCriticalSection(&This->cs);
+ if (This->dirty)
+ hr = PropertyStorage_WriteToStream(This);
+ else
+ hr = S_OK;
+ LeaveCriticalSection(&This->cs);
+ return hr;
}
/************************************************************************
static HRESULT WINAPI IPropertyStorage_fnRevert(
IPropertyStorage* iface)
{
- FIXME("\n");
- return E_NOTIMPL;
+ HRESULT hr;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+
+ TRACE("%p\n", iface);
+ if (!This)
+ return E_INVALIDARG;
+
+ EnterCriticalSection(&This->cs);
+ if (This->dirty)
+ {
+ PropertyStorage_DestroyDictionaries(This);
+ hr = PropertyStorage_CreateDictionaries(This);
+ if (SUCCEEDED(hr))
+ hr = PropertyStorage_ReadFromStream(This);
+ }
+ else
+ hr = S_OK;
+ LeaveCriticalSection(&This->cs);
+ return hr;
}
/************************************************************************
IPropertyStorage* iface,
REFCLSID clsid)
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+
+ TRACE("%p, %s\n", iface, debugstr_guid(clsid));
+ if (!This || !clsid)
+ return E_INVALIDARG;
+ if (!(This->grfMode & STGM_READWRITE))
+ return STG_E_ACCESSDENIED;
+ memcpy(&This->clsid, clsid, sizeof(This->clsid));
+ This->dirty = TRUE;
+ if (This->grfFlags & PROPSETFLAG_UNBUFFERED)
+ IPropertyStorage_Commit(iface, STGC_DEFAULT);
+ return S_OK;
}
/************************************************************************
IPropertyStorage* iface,
STATPROPSETSTG* statpsstg)
{
- FIXME("\n");
- return E_NOTIMPL;
+ PropertyStorage_impl *This = (PropertyStorage_impl *)iface;
+ STATSTG stat;
+ HRESULT hr;
+
+ TRACE("%p, %p\n", iface, statpsstg);
+ if (!This || !statpsstg)
+ return E_INVALIDARG;
+
+ hr = IStream_Stat(This->stm, &stat, STATFLAG_NONAME);
+ if (SUCCEEDED(hr))
+ {
+ memcpy(&statpsstg->fmtid, &This->fmtid, sizeof(statpsstg->fmtid));
+ memcpy(&statpsstg->clsid, &This->clsid, sizeof(statpsstg->clsid));
+ statpsstg->grfFlags = This->grfFlags;
+ memcpy(&statpsstg->mtime, &stat.mtime, sizeof(statpsstg->mtime));
+ memcpy(&statpsstg->ctime, &stat.ctime, sizeof(statpsstg->ctime));
+ memcpy(&statpsstg->atime, &stat.atime, sizeof(statpsstg->atime));
+ statpsstg->dwOSVersion = This->originatorOS;
+ }
+ return hr;
}
-/***********************************************************************
- * PropertyStorage_Contruct
+static int PropertyStorage_PropNameCompare(const void *a, const void *b,
+ void *extra)
+{
+ PropertyStorage_impl *This = (PropertyStorage_impl *)extra;
+
+ TRACE("(%s, %s)\n", debugstr_w(a), debugstr_w(b));
+ /* FIXME: this assumes property names are always Unicode, but they
+ * might be ANSI, depending on whether This->grfFlags & PROPSETFLAG_ANSI
+ * is true.
+ */
+ if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
+ return strcmpW((LPCWSTR)a, (LPCWSTR)b);
+ else
+ return strcmpiW((LPCWSTR)a, (LPCWSTR)b);
+}
+
+static void PropertyStorage_PropNameDestroy(void *k, void *d, void *extra)
+{
+ HeapFree(GetProcessHeap(), 0, k);
+}
+
+static int PropertyStorage_PropCompare(const void *a, const void *b,
+ void *extra)
+{
+ TRACE("(%ld, %ld)\n", (PROPID)a, (PROPID)b);
+ return (PROPID)a - (PROPID)b;
+}
+
+static void PropertyStorage_PropertyDestroy(void *k, void *d, void *extra)
+{
+ PropVariantClear((PROPVARIANT *)d);
+ HeapFree(GetProcessHeap(), 0, d);
+}
+
+/* Reads the dictionary from the memory buffer beginning at ptr. Interprets
+ * the entries according to the values of This->codePage and This->locale.
+ * FIXME: there isn't any checking whether the read property extends past the
+ * end of the buffer.
+ * FIXME: this always stores dictionary entries as Unicode, but it should store
+ * them as ANSI if (This->grfFlags & PROPSETFLAG_ANSI) is true.
*/
-static HRESULT PropertyStorage_Contruct(IStream *stm, IPropertyStorage** pps)
+static HRESULT PropertyStorage_ReadDictionary(PropertyStorage_impl *This,
+ BYTE *ptr)
{
- PropertyStorage_impl *ps;
+ DWORD numEntries, i;
+ HRESULT hr = S_OK;
- ps = HeapAlloc(GetProcessHeap(), 0, sizeof *ps);
- if (!ps)
- return E_OUTOFMEMORY;
+ assert(This);
+ assert(This->name_to_propid);
+ assert(This->propid_to_name);
+
+ StorageUtl_ReadDWord(ptr, 0, &numEntries);
+ TRACE("Reading %ld entries:\n", numEntries);
+ ptr += sizeof(DWORD);
+ for (i = 0; SUCCEEDED(hr) && i < numEntries; i++)
+ {
+ PROPID propid;
+ DWORD cbEntry;
+ LPWSTR name = NULL;
+
+ StorageUtl_ReadDWord(ptr, 0, &propid);
+ ptr += sizeof(PROPID);
+ StorageUtl_ReadDWord(ptr, 0, &cbEntry);
+ ptr += sizeof(DWORD);
+ /* FIXME: if host is big-endian, this'll suck to convert */
+ TRACE("Reading entry with ID 0x%08lx, %ld bytes\n", propid, cbEntry);
+ if (This->codePage != CP_UNICODE)
+ {
+ int len = MultiByteToWideChar(This->codePage, 0, ptr, cbEntry,
+ NULL, 0);
+
+ if (!len)
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ else
+ {
+ name = HeapAlloc(GetProcessHeap(), 0,
+ len * sizeof(WCHAR));
+ if (name)
+ MultiByteToWideChar(This->codePage, 0, ptr, cbEntry, name,
+ len);
+ else
+ hr = STG_E_INSUFFICIENTMEMORY;
+ }
+ }
+ else
+ {
+ name = HeapAlloc(GetProcessHeap(), 0, cbEntry);
+ if (name)
+ lstrcpyW(name, (LPWSTR)ptr);
+ else
+ hr = STG_E_INSUFFICIENTMEMORY;
+ /* Unicode entries are padded to DWORD boundaries */
+ if (cbEntry % sizeof(DWORD))
+ ptr += sizeof(DWORD) - (cbEntry % sizeof(DWORD));
+ }
+ if (name)
+ {
+ dictionary_insert(This->name_to_propid, name, (void *)propid);
+ dictionary_insert(This->propid_to_name, (void *)propid, name);
+ TRACE("Property %s maps to id %ld\n", debugstr_w(name), propid);
+ }
+ ptr += sizeof(DWORD) + cbEntry;
+ }
+ return hr;
+}
- ps->vtbl = &IPropertyStorage_Vtbl;
- ps->ref = 1;
- ps->stm = stm;
+/* FIXME: there isn't any checking whether the read property extends past the
+ * end of the buffer.
+ */
+static HRESULT PropertyStorage_ReadProperty(PROPVARIANT *prop, const BYTE *data)
+{
+ HRESULT hr = S_OK;
- *pps = (IPropertyStorage*)ps;
+ assert(prop);
+ assert(data);
+ StorageUtl_ReadDWord(data, 0, (DWORD *)&prop->vt);
+ data += sizeof(DWORD);
+ switch (prop->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ break;
+ case VT_I1:
+ prop->u.cVal = *(const char *)data;
+ TRACE("Read char 0x%x ('%c')\n", prop->u.cVal, prop->u.cVal);
+ break;
+ case VT_UI1:
+ prop->u.bVal = *(const UCHAR *)data;
+ TRACE("Read byte 0x%x\n", prop->u.bVal);
+ break;
+ case VT_I2:
+ StorageUtl_ReadWord(data, 0, &prop->u.iVal);
+ TRACE("Read short %d\n", prop->u.iVal);
+ break;
+ case VT_UI2:
+ StorageUtl_ReadWord(data, 0, &prop->u.uiVal);
+ TRACE("Read ushort %d\n", prop->u.uiVal);
+ break;
+ case VT_I4:
+ StorageUtl_ReadDWord(data, 0, &prop->u.lVal);
+ TRACE("Read long %ld\n", prop->u.lVal);
+ break;
+ case VT_UI4:
+ StorageUtl_ReadDWord(data, 0, &prop->u.ulVal);
+ TRACE("Read ulong %ld\n", prop->u.ulVal);
+ break;
+ case VT_LPSTR:
+ {
+ DWORD count;
+
+ StorageUtl_ReadDWord(data, 0, &count);
+ prop->u.pszVal = CoTaskMemAlloc(count);
+ if (prop->u.pszVal)
+ {
+ /* FIXME: if the host is big-endian, this'll suck */
+ memcpy(prop->u.pszVal, data + sizeof(DWORD), count);
+ /* FIXME: so far so good, but this may be Unicode or DBCS depending
+ * on This->codePage.
+ */
+ TRACE("Read string value %s\n", debugstr_a(prop->u.pszVal));
+ }
+ else
+ hr = STG_E_INSUFFICIENTMEMORY;
+ break;
+ }
+ case VT_LPWSTR:
+ {
+ DWORD count;
+
+ StorageUtl_ReadDWord(data, 0, &count);
+ prop->u.pwszVal = CoTaskMemAlloc(count * sizeof(WCHAR));
+ if (prop->u.pwszVal)
+ {
+ /* FIXME: if the host is big-endian, gotta swap every char */
+ memcpy(prop->u.pwszVal, data + sizeof(DWORD),
+ count * sizeof(WCHAR));
+ TRACE("Read string value %s\n", debugstr_w(prop->u.pwszVal));
+ }
+ else
+ hr = STG_E_INSUFFICIENTMEMORY;
+ break;
+ }
+ case VT_FILETIME:
+ /* FIXME: endianness */
+ memcpy(&prop->u.filetime, data, sizeof(FILETIME));
+ break;
+ default:
+ FIXME("unsupported type %d\n", prop->vt);
+ hr = STG_E_INVALIDPARAMETER;
+ }
+ return hr;
+}
- TRACE("PropertyStorage %p constructed\n", ps);
+static HRESULT PropertyStorage_ReadHeaderFromStream(IStream *stm,
+ PROPERTYSETHEADER *hdr)
+{
+ BYTE buf[sizeof(PROPERTYSETHEADER)];
+ ULONG count = 0;
+ HRESULT hr;
+
+ assert(stm);
+ assert(hdr);
+ hr = IStream_Read(stm, buf, sizeof(buf), &count);
+ if (SUCCEEDED(hr))
+ {
+ if (count != sizeof(buf))
+ {
+ WARN("read %ld, expected %d\n", count, sizeof(buf));
+ hr = STG_E_INVALIDHEADER;
+ }
+ else
+ {
+ StorageUtl_ReadWord(buf, offsetof(PROPERTYSETHEADER, wByteOrder),
+ &hdr->wByteOrder);
+ StorageUtl_ReadWord(buf, offsetof(PROPERTYSETHEADER, wFormat),
+ &hdr->wFormat);
+ StorageUtl_ReadDWord(buf, offsetof(PROPERTYSETHEADER, dwOSVer),
+ &hdr->dwOSVer);
+ StorageUtl_ReadGUID(buf, offsetof(PROPERTYSETHEADER, clsid),
+ &hdr->clsid);
+ StorageUtl_ReadDWord(buf, offsetof(PROPERTYSETHEADER, reserved),
+ &hdr->reserved);
+ }
+ }
+ TRACE("returning 0x%08lx\n", hr);
+ return hr;
+}
- return S_OK;
+static HRESULT PropertyStorage_ReadFmtIdOffsetFromStream(IStream *stm,
+ FORMATIDOFFSET *fmt)
+{
+ BYTE buf[sizeof(FORMATIDOFFSET)];
+ ULONG count = 0;
+ HRESULT hr;
+
+ assert(stm);
+ assert(fmt);
+ hr = IStream_Read(stm, buf, sizeof(buf), &count);
+ if (SUCCEEDED(hr))
+ {
+ if (count != sizeof(buf))
+ {
+ WARN("read %ld, expected %d\n", count, sizeof(buf));
+ hr = STG_E_INVALIDHEADER;
+ }
+ else
+ {
+ StorageUtl_ReadGUID(buf, offsetof(FORMATIDOFFSET, fmtid),
+ &fmt->fmtid);
+ StorageUtl_ReadDWord(buf, offsetof(FORMATIDOFFSET, dwOffset),
+ &fmt->dwOffset);
+ }
+ }
+ TRACE("returning 0x%08lx\n", hr);
+ return hr;
+}
+
+static HRESULT PropertyStorage_ReadSectionHeaderFromStream(IStream *stm,
+ PROPERTYSECTIONHEADER *hdr)
+{
+ BYTE buf[sizeof(PROPERTYSECTIONHEADER)];
+ ULONG count = 0;
+ HRESULT hr;
+
+ assert(stm);
+ assert(hdr);
+ hr = IStream_Read(stm, buf, sizeof(buf), &count);
+ if (SUCCEEDED(hr))
+ {
+ if (count != sizeof(buf))
+ {
+ WARN("read %ld, expected %d\n", count, sizeof(buf));
+ hr = STG_E_INVALIDHEADER;
+ }
+ else
+ {
+ StorageUtl_ReadDWord(buf, offsetof(PROPERTYSECTIONHEADER,
+ cbSection), &hdr->cbSection);
+ StorageUtl_ReadDWord(buf, offsetof(PROPERTYSECTIONHEADER,
+ cProperties), &hdr->cProperties);
+ }
+ }
+ TRACE("returning 0x%08lx\n", hr);
+ return hr;
+}
+
+static HRESULT PropertyStorage_ReadFromStream(PropertyStorage_impl *This)
+{
+ PROPERTYSETHEADER hdr;
+ FORMATIDOFFSET fmtOffset;
+ PROPERTYSECTIONHEADER sectionHdr;
+ LARGE_INTEGER seek;
+ ULONG i;
+ STATSTG stat;
+ HRESULT hr;
+ BYTE *buf = NULL;
+ ULONG count = 0;
+ DWORD dictOffset = 0;
+
+ assert(This);
+ This->dirty = FALSE;
+ This->highestProp = 0;
+ hr = IStream_Stat(This->stm, &stat, STATFLAG_NONAME);
+ if (FAILED(hr))
+ goto end;
+ if (stat.cbSize.u.HighPart)
+ {
+ WARN("stream too big\n");
+ /* maximum size varies, but it can't be this big */
+ hr = STG_E_INVALIDHEADER;
+ goto end;
+ }
+ if (stat.cbSize.u.LowPart == 0)
+ {
+ /* empty stream is okay */
+ hr = S_OK;
+ goto end;
+ }
+ else if (stat.cbSize.u.LowPart < sizeof(PROPERTYSETHEADER) +
+ sizeof(FORMATIDOFFSET))
+ {
+ WARN("stream too small\n");
+ hr = STG_E_INVALIDHEADER;
+ goto end;
+ }
+ seek.QuadPart = 0;
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ hr = PropertyStorage_ReadHeaderFromStream(This->stm, &hdr);
+ /* I've only seen reserved == 1, but the article says I shouldn't disallow
+ * higher values.
+ */
+ if (hdr.wByteOrder != PROPSETHDR_BYTEORDER_MAGIC || hdr.reserved < 1)
+ {
+ WARN("bad magic in prop set header\n");
+ hr = STG_E_INVALIDHEADER;
+ goto end;
+ }
+ if (hdr.wFormat != 0 && hdr.wFormat != 1)
+ {
+ WARN("bad format version %d\n", hdr.wFormat);
+ hr = STG_E_INVALIDHEADER;
+ goto end;
+ }
+ memcpy(&This->clsid, &hdr.clsid, sizeof(This->clsid));
+ This->originatorOS = hdr.dwOSVer;
+ if (PROPSETHDR_OSVER_KIND(hdr.dwOSVer) == PROPSETHDR_OSVER_KIND_MAC)
+ WARN("File comes from a Mac, strings will probably be screwed up\n");
+ hr = PropertyStorage_ReadFmtIdOffsetFromStream(This->stm, &fmtOffset);
+ if (FAILED(hr))
+ goto end;
+ if (fmtOffset.dwOffset > stat.cbSize.u.LowPart)
+ {
+ WARN("invalid offset %ld (stream length is %ld)\n", fmtOffset.dwOffset,
+ stat.cbSize.u.LowPart);
+ hr = STG_E_INVALIDHEADER;
+ goto end;
+ }
+ /* wackiness alert: if the format ID is FMTID_DocSummaryInformation, there
+ * follow not one, but two sections. The first is the standard properties
+ * for the document summary information, and the second is user-defined
+ * properties. This is the only case in which multiple sections are
+ * allowed.
+ * Reading the second stream isn't implemented yet.
+ */
+ hr = PropertyStorage_ReadSectionHeaderFromStream(This->stm, §ionHdr);
+ if (FAILED(hr))
+ goto end;
+ /* The section size includes the section header, so check it */
+ if (sectionHdr.cbSection < sizeof(PROPERTYSECTIONHEADER))
+ {
+ WARN("section header too small, got %ld, expected at least %d\n",
+ sectionHdr.cbSection, sizeof(PROPERTYSECTIONHEADER));
+ hr = STG_E_INVALIDHEADER;
+ goto end;
+ }
+ buf = HeapAlloc(GetProcessHeap(), 0, sectionHdr.cbSection -
+ sizeof(PROPERTYSECTIONHEADER));
+ if (!buf)
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
+ hr = IStream_Read(This->stm, buf, sectionHdr.cbSection -
+ sizeof(PROPERTYSECTIONHEADER), &count);
+ if (FAILED(hr))
+ goto end;
+ TRACE("Reading %ld properties:\n", sectionHdr.cProperties);
+ for (i = 0; SUCCEEDED(hr) && i < sectionHdr.cProperties; i++)
+ {
+ PROPERTYIDOFFSET *idOffset = (PROPERTYIDOFFSET *)(buf +
+ i * sizeof(PROPERTYIDOFFSET));
+
+ if (idOffset->dwOffset < sizeof(PROPERTYSECTIONHEADER) ||
+ idOffset->dwOffset >= sectionHdr.cbSection - sizeof(DWORD))
+ hr = STG_E_INVALIDPOINTER;
+ else
+ {
+ if (idOffset->propid >= PID_FIRST_USABLE &&
+ idOffset->propid < PID_MIN_READONLY && idOffset->propid >
+ This->highestProp)
+ This->highestProp = idOffset->propid;
+ if (idOffset->propid == PID_DICTIONARY)
+ {
+ /* Don't read the dictionary yet, its entries depend on the
+ * code page. Just store the offset so we know to read it
+ * later.
+ */
+ dictOffset = idOffset->dwOffset;
+ TRACE("Dictionary offset is %ld\n", dictOffset);
+ }
+ else
+ {
+ PROPVARIANT prop;
+
+ if (SUCCEEDED(PropertyStorage_ReadProperty(&prop,
+ buf + idOffset->dwOffset - sizeof(PROPERTYSECTIONHEADER))))
+ {
+ TRACE("Read property with ID 0x%08lx, type %d\n",
+ idOffset->propid, prop.vt);
+ switch(idOffset->propid)
+ {
+ case PID_CODEPAGE:
+ if (prop.vt == VT_I2)
+ This->codePage = (UINT)prop.u.iVal;
+ break;
+ case PID_LOCALE:
+ if (prop.vt == VT_I4)
+ This->locale = (LCID)prop.u.lVal;
+ break;
+ case PID_BEHAVIOR:
+ if (prop.vt == VT_I4 && prop.u.lVal)
+ This->grfFlags |= PROPSETFLAG_CASE_SENSITIVE;
+ break;
+ default:
+ hr = PropertyStorage_StorePropWithId(This,
+ idOffset->propid, &prop);
+ }
+ }
+ }
+ }
+ }
+ if (!This->codePage)
+ {
+ /* default to Unicode unless told not to, as specified here:
+ * http://msdn.microsoft.com/library/en-us/stg/stg/names_in_istorage.asp
+ */
+ if (This->grfFlags & PROPSETFLAG_ANSI)
+ This->codePage = GetACP();
+ else
+ This->codePage = CP_UNICODE;
+ }
+ if (!This->locale)
+ This->locale = LOCALE_SYSTEM_DEFAULT;
+ TRACE("Code page is %d, locale is %ld\n", This->codePage, This->locale);
+ if (dictOffset)
+ hr = PropertyStorage_ReadDictionary(This,
+ buf + dictOffset - sizeof(PROPERTYSECTIONHEADER));
+
+end:
+ HeapFree(GetProcessHeap(), 0, buf);
+ if (FAILED(hr))
+ {
+ dictionary_destroy(This->name_to_propid);
+ This->name_to_propid = NULL;
+ dictionary_destroy(This->propid_to_name);
+ This->propid_to_name = NULL;
+ dictionary_destroy(This->propid_to_prop);
+ This->propid_to_prop = NULL;
+ }
+ return hr;
+}
+
+static void PropertyStorage_MakeHeader(PropertyStorage_impl *This,
+ PROPERTYSETHEADER *hdr)
+{
+ assert(This);
+ assert(hdr);
+ StorageUtl_WriteWord((BYTE *)&hdr->wByteOrder, 0,
+ PROPSETHDR_BYTEORDER_MAGIC);
+ /* FIXME: should be able to write format 0 property sets too, depending
+ * on whether I have too long string names or if case-sensitivity is set.
+ * For now always write format 1.
+ */
+ StorageUtl_WriteWord((BYTE *)&hdr->wFormat, 0, 1);
+ StorageUtl_WriteDWord((BYTE *)&hdr->dwOSVer, 0, This->originatorOS);
+ StorageUtl_WriteGUID((BYTE *)&hdr->clsid, 0, &This->clsid);
+ StorageUtl_WriteDWord((BYTE *)&hdr->reserved, 0, 1);
+}
+
+static void PropertyStorage_MakeFmtIdOffset(PropertyStorage_impl *This,
+ FORMATIDOFFSET *fmtOffset)
+{
+ assert(This);
+ assert(fmtOffset);
+ StorageUtl_WriteGUID((BYTE *)fmtOffset, 0, &This->fmtid);
+ StorageUtl_WriteDWord((BYTE *)fmtOffset, offsetof(FORMATIDOFFSET, dwOffset),
+ sizeof(PROPERTYSETHEADER) + sizeof(FORMATIDOFFSET));
+}
+
+static void PropertyStorage_MakeSectionHdr(DWORD cbSection, DWORD numProps,
+ PROPERTYSECTIONHEADER *hdr)
+{
+ assert(hdr);
+ StorageUtl_WriteDWord((BYTE *)hdr, 0, cbSection);
+ StorageUtl_WriteDWord((BYTE *)hdr,
+ offsetof(PROPERTYSECTIONHEADER, cProperties), numProps);
+}
+
+static void PropertyStorage_MakePropertyIdOffset(DWORD propid, DWORD dwOffset,
+ PROPERTYIDOFFSET *propIdOffset)
+{
+ assert(propIdOffset);
+ StorageUtl_WriteDWord((BYTE *)propIdOffset, 0, propid);
+ StorageUtl_WriteDWord((BYTE *)propIdOffset,
+ offsetof(PROPERTYIDOFFSET, dwOffset), dwOffset);
+}
+
+struct DictionaryClosure
+{
+ HRESULT hr;
+ DWORD bytesWritten;
+};
+
+static BOOL PropertyStorage_DictionaryWriter(const void *key,
+ const void *value, void *extra, void *closure)
+{
+ PropertyStorage_impl *This = (PropertyStorage_impl *)extra;
+ struct DictionaryClosure *c = (struct DictionaryClosure *)closure;
+ DWORD propid;
+ ULONG count;
+
+ assert(key);
+ assert(This);
+ assert(closure);
+ StorageUtl_WriteDWord((LPBYTE)&propid, 0, (DWORD)value);
+ c->hr = IStream_Write(This->stm, &propid, sizeof(propid), &count);
+ if (FAILED(c->hr))
+ goto end;
+ c->bytesWritten += sizeof(DWORD);
+ if (This->codePage == CP_UNICODE)
+ {
+ DWORD keyLen, pad = 0;
+
+ StorageUtl_WriteDWord((LPBYTE)&keyLen, 0,
+ (lstrlenW((LPWSTR)key) + 1) * sizeof(WCHAR));
+ c->hr = IStream_Write(This->stm, &keyLen, sizeof(keyLen), &count);
+ if (FAILED(c->hr))
+ goto end;
+ c->bytesWritten += sizeof(DWORD);
+ /* FIXME: endian-convert every char (yuck) */
+ c->hr = IStream_Write(This->stm, key, keyLen, &count);
+ if (FAILED(c->hr))
+ goto end;
+ c->bytesWritten += keyLen;
+ if (keyLen % sizeof(DWORD))
+ {
+ c->hr = IStream_Write(This->stm, &pad,
+ sizeof(DWORD) - keyLen % sizeof(DWORD), &count);
+ if (FAILED(c->hr))
+ goto end;
+ c->bytesWritten += sizeof(DWORD) - keyLen % sizeof(DWORD);
+ }
+ }
+ else
+ {
+ int len = WideCharToMultiByte(This->codePage, 0, (LPWSTR)key, -1, NULL,
+ 0, NULL, NULL);
+ LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, len);
+ DWORD dwLen;
+
+ if (!buf)
+ {
+ c->hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
+ /* FIXME: endian-convert multibyte chars? Ick! */
+ WideCharToMultiByte(This->codePage, 0, (LPWSTR)key, -1, buf, len,
+ NULL, NULL);
+ StorageUtl_WriteDWord((LPBYTE)&dwLen, 0, len);
+ c->hr = IStream_Write(This->stm, &dwLen, sizeof(dwLen), &count);
+ if (FAILED(c->hr))
+ {
+ HeapFree(GetProcessHeap(), 0, buf);
+ goto end;
+ }
+ c->bytesWritten += sizeof(DWORD);
+ c->hr = IStream_Write(This->stm, buf, len, &count);
+ if (FAILED(c->hr))
+ {
+ HeapFree(GetProcessHeap(), 0, buf);
+ goto end;
+ }
+ c->bytesWritten += len;
+ HeapFree(GetProcessHeap(), 0, buf);
+ }
+end:
+ return SUCCEEDED(c->hr);
+}
+
+#define SECTIONHEADER_OFFSET sizeof(PROPERTYSETHEADER) + sizeof(FORMATIDOFFSET)
+
+/* Writes the dictionary to the stream. Assumes without checking that the
+ * dictionary isn't empty.
+ */
+static HRESULT PropertyStorage_WriteDictionaryToStream(
+ PropertyStorage_impl *This, DWORD *sectionOffset)
+{
+ HRESULT hr;
+ LARGE_INTEGER seek;
+ PROPERTYIDOFFSET propIdOffset;
+ ULONG count;
+ DWORD dwTemp;
+ struct DictionaryClosure closure;
+
+ assert(This);
+ assert(sectionOffset);
+
+ /* The dictionary's always the first property written, so seek to its
+ * spot.
+ */
+ seek.QuadPart = SECTIONHEADER_OFFSET + sizeof(PROPERTYSECTIONHEADER);
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ PropertyStorage_MakePropertyIdOffset(PID_DICTIONARY, *sectionOffset,
+ &propIdOffset);
+ hr = IStream_Write(This->stm, &propIdOffset, sizeof(propIdOffset), &count);
+ if (FAILED(hr))
+ goto end;
+
+ seek.QuadPart = SECTIONHEADER_OFFSET + *sectionOffset;
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0,
+ dictionary_num_entries(This->name_to_propid));
+ hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
+ if (FAILED(hr))
+ goto end;
+ *sectionOffset += sizeof(dwTemp);
+
+ closure.hr = S_OK;
+ closure.bytesWritten = 0;
+ dictionary_enumerate(This->name_to_propid, PropertyStorage_DictionaryWriter,
+ &closure);
+ hr = closure.hr;
+ if (FAILED(hr))
+ goto end;
+ *sectionOffset += closure.bytesWritten;
+ if (closure.bytesWritten % sizeof(DWORD))
+ {
+ TRACE("adding %ld bytes of padding\n", sizeof(DWORD) -
+ closure.bytesWritten % sizeof(DWORD));
+ *sectionOffset += sizeof(DWORD) - closure.bytesWritten % sizeof(DWORD);
+ }
+
+end:
+ return hr;
}
+static HRESULT PropertyStorage_WritePropertyToStream(PropertyStorage_impl *This,
+ DWORD propNum, DWORD propid, PROPVARIANT *var, DWORD *sectionOffset)
+{
+ HRESULT hr;
+ LARGE_INTEGER seek;
+ PROPERTYIDOFFSET propIdOffset;
+ ULONG count;
+ DWORD dwType, bytesWritten;
+
+ assert(This);
+ assert(var);
+ assert(sectionOffset);
+
+ TRACE("%p, %ld, 0x%08lx, (%d), (%ld)\n", This, propNum, propid, var->vt,
+ *sectionOffset);
+
+ seek.QuadPart = SECTIONHEADER_OFFSET + sizeof(PROPERTYSECTIONHEADER) +
+ propNum * sizeof(PROPERTYIDOFFSET);
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ PropertyStorage_MakePropertyIdOffset(propid, *sectionOffset, &propIdOffset);
+ hr = IStream_Write(This->stm, &propIdOffset, sizeof(propIdOffset), &count);
+ if (FAILED(hr))
+ goto end;
+
+ seek.QuadPart = SECTIONHEADER_OFFSET + *sectionOffset;
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ StorageUtl_WriteDWord((LPBYTE)&dwType, 0, var->vt);
+ hr = IStream_Write(This->stm, &dwType, sizeof(dwType), &count);
+ if (FAILED(hr))
+ goto end;
+ *sectionOffset += sizeof(dwType);
+
+ switch (var->vt)
+ {
+ case VT_EMPTY:
+ case VT_NULL:
+ bytesWritten = 0;
+ break;
+ case VT_I1:
+ case VT_UI1:
+ hr = IStream_Write(This->stm, &var->u.cVal, sizeof(var->u.cVal),
+ &count);
+ bytesWritten = count;
+ break;
+ case VT_I2:
+ case VT_UI2:
+ {
+ WORD wTemp;
+
+ StorageUtl_WriteWord((LPBYTE)&wTemp, 0, var->u.iVal);
+ hr = IStream_Write(This->stm, &wTemp, sizeof(wTemp), &count);
+ bytesWritten = count;
+ break;
+ }
+ case VT_I4:
+ case VT_UI4:
+ {
+ DWORD dwTemp;
+
+ StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, var->u.lVal);
+ hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
+ bytesWritten = count;
+ break;
+ }
+ case VT_LPSTR:
+ {
+ DWORD len, dwTemp;
+
+ if (This->codePage == CP_UNICODE)
+ len = (lstrlenW(var->u.pwszVal) + 1) * sizeof(WCHAR);
+ else
+ len = lstrlenA(var->u.pszVal) + 1;
+ StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, len);
+ hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
+ if (FAILED(hr))
+ goto end;
+ hr = IStream_Write(This->stm, var->u.pszVal, len, &count);
+ bytesWritten = count + sizeof(DWORD);
+ break;
+ }
+ case VT_LPWSTR:
+ {
+ DWORD len = lstrlenW(var->u.pwszVal) + 1, dwTemp;
+
+ StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, len);
+ hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
+ if (FAILED(hr))
+ goto end;
+ hr = IStream_Write(This->stm, var->u.pwszVal, len * sizeof(WCHAR),
+ &count);
+ bytesWritten = count + sizeof(DWORD);
+ break;
+ }
+ default:
+ FIXME("unsupported type: %d\n", var->vt);
+ return STG_E_INVALIDPARAMETER;
+ }
+
+ if (SUCCEEDED(hr))
+ {
+ *sectionOffset += bytesWritten;
+ if (bytesWritten % sizeof(DWORD))
+ {
+ TRACE("adding %ld bytes of padding\n", sizeof(DWORD) -
+ bytesWritten % sizeof(DWORD));
+ *sectionOffset += sizeof(DWORD) - bytesWritten % sizeof(DWORD);
+ }
+ }
+
+end:
+ return hr;
+}
+
+struct PropertyClosure
+{
+ HRESULT hr;
+ DWORD propNum;
+ DWORD *sectionOffset;
+};
+
+static BOOL PropertyStorage_PropertiesWriter(const void *key, const void *value,
+ void *extra, void *closure)
+{
+ PropertyStorage_impl *This = (PropertyStorage_impl *)extra;
+ struct PropertyClosure *c = (struct PropertyClosure *)closure;
+
+ assert(key);
+ assert(value);
+ assert(extra);
+ assert(closure);
+ c->hr = PropertyStorage_WritePropertyToStream(This,
+ c->propNum++, (DWORD)key, (PROPVARIANT *)value, c->sectionOffset);
+ return SUCCEEDED(c->hr);
+}
+
+static HRESULT PropertyStorage_WritePropertiesToStream(
+ PropertyStorage_impl *This, DWORD startingPropNum, DWORD *sectionOffset)
+{
+ struct PropertyClosure closure;
+
+ assert(This);
+ assert(sectionOffset);
+ closure.hr = S_OK;
+ closure.propNum = startingPropNum;
+ closure.sectionOffset = sectionOffset;
+ dictionary_enumerate(This->propid_to_prop, PropertyStorage_PropertiesWriter,
+ &closure);
+ return closure.hr;
+}
+
+static HRESULT PropertyStorage_WriteHeadersToStream(PropertyStorage_impl *This)
+{
+ HRESULT hr;
+ ULONG count = 0;
+ LARGE_INTEGER seek = { {0} };
+ PROPERTYSETHEADER hdr;
+ FORMATIDOFFSET fmtOffset;
+
+ assert(This);
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ PropertyStorage_MakeHeader(This, &hdr);
+ hr = IStream_Write(This->stm, &hdr, sizeof(hdr), &count);
+ if (FAILED(hr))
+ goto end;
+ if (count != sizeof(hdr))
+ {
+ hr = STG_E_WRITEFAULT;
+ goto end;
+ }
+
+ PropertyStorage_MakeFmtIdOffset(This, &fmtOffset);
+ hr = IStream_Write(This->stm, &fmtOffset, sizeof(fmtOffset), &count);
+ if (FAILED(hr))
+ goto end;
+ if (count != sizeof(fmtOffset))
+ {
+ hr = STG_E_WRITEFAULT;
+ goto end;
+ }
+ hr = S_OK;
+
+end:
+ return hr;
+}
+
+static HRESULT PropertyStorage_WriteToStream(PropertyStorage_impl *This)
+{
+ PROPERTYSECTIONHEADER sectionHdr;
+ HRESULT hr;
+ ULONG count;
+ LARGE_INTEGER seek;
+ DWORD numProps, prop, sectionOffset, dwTemp;
+ PROPVARIANT var;
+
+ assert(This);
+
+ PropertyStorage_WriteHeadersToStream(This);
+
+ /* Count properties. Always at least one property, the code page */
+ numProps = 1;
+ if (dictionary_num_entries(This->name_to_propid))
+ numProps++;
+ if (This->locale != LOCALE_SYSTEM_DEFAULT)
+ numProps++;
+ if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
+ numProps++;
+ numProps += dictionary_num_entries(This->propid_to_prop);
+
+ /* Write section header with 0 bytes right now, I'll adjust it after
+ * writing properties.
+ */
+ PropertyStorage_MakeSectionHdr(0, numProps, §ionHdr);
+ seek.QuadPart = SECTIONHEADER_OFFSET;
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ hr = IStream_Write(This->stm, §ionHdr, sizeof(sectionHdr), &count);
+ if (FAILED(hr))
+ goto end;
+
+ prop = 0;
+ sectionOffset = sizeof(PROPERTYSECTIONHEADER) +
+ numProps * sizeof(PROPERTYIDOFFSET);
+
+ if (dictionary_num_entries(This->name_to_propid))
+ {
+ prop++;
+ hr = PropertyStorage_WriteDictionaryToStream(This, §ionOffset);
+ if (FAILED(hr))
+ goto end;
+ }
+
+ PropVariantInit(&var);
+
+ var.vt = VT_I2;
+ var.u.iVal = This->codePage;
+ hr = PropertyStorage_WritePropertyToStream(This, prop++, PID_CODEPAGE,
+ &var, §ionOffset);
+ if (FAILED(hr))
+ goto end;
+
+ if (This->locale != LOCALE_SYSTEM_DEFAULT)
+ {
+ var.vt = VT_I4;
+ var.u.lVal = This->locale;
+ hr = PropertyStorage_WritePropertyToStream(This, prop++, PID_LOCALE,
+ &var, §ionOffset);
+ if (FAILED(hr))
+ goto end;
+ }
+
+ if (This->grfFlags & PROPSETFLAG_CASE_SENSITIVE)
+ {
+ var.vt = VT_I4;
+ var.u.lVal = 1;
+ hr = PropertyStorage_WritePropertyToStream(This, prop++, PID_BEHAVIOR,
+ &var, §ionOffset);
+ if (FAILED(hr))
+ goto end;
+ }
+
+ hr = PropertyStorage_WritePropertiesToStream(This, prop, §ionOffset);
+ if (FAILED(hr))
+ goto end;
+
+ /* Now write the byte count of the section */
+ seek.QuadPart = SECTIONHEADER_OFFSET;
+ hr = IStream_Seek(This->stm, seek, STREAM_SEEK_SET, NULL);
+ if (FAILED(hr))
+ goto end;
+ StorageUtl_WriteDWord((LPBYTE)&dwTemp, 0, sectionOffset);
+ hr = IStream_Write(This->stm, &dwTemp, sizeof(dwTemp), &count);
+
+end:
+ return hr;
+}
/***********************************************************************
- * Implementation of IPropertySetStorage
+ * PropertyStorage_Construct
*/
+static void PropertyStorage_DestroyDictionaries(PropertyStorage_impl *This)
+{
+ assert(This);
+ dictionary_destroy(This->name_to_propid);
+ This->name_to_propid = NULL;
+ dictionary_destroy(This->propid_to_name);
+ This->propid_to_name = NULL;
+ dictionary_destroy(This->propid_to_prop);
+ This->propid_to_prop = NULL;
+}
-static LPCWSTR format_id_to_name(REFFMTID rfmtid)
+static HRESULT PropertyStorage_CreateDictionaries(PropertyStorage_impl *This)
{
- static const WCHAR szSummaryInfo[] = { 5,'S','u','m','m','a','r','y',
- 'I','n','f','o','r','m','a','t','i','o','n',0 };
+ HRESULT hr = S_OK;
- if (IsEqualGUID(&FMTID_SummaryInformation, rfmtid))
- return szSummaryInfo;
- ERR("Unknown format id %s\n", debugstr_guid(rfmtid));
- return NULL;
+ assert(This);
+ This->name_to_propid = dictionary_create(
+ PropertyStorage_PropNameCompare, PropertyStorage_PropNameDestroy,
+ This);
+ if (!This->name_to_propid)
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
+ This->propid_to_name = dictionary_create(PropertyStorage_PropCompare,
+ NULL, This);
+ if (!This->propid_to_name)
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
+ This->propid_to_prop = dictionary_create(PropertyStorage_PropCompare,
+ PropertyStorage_PropertyDestroy, This);
+ if (!This->propid_to_prop)
+ {
+ hr = STG_E_INSUFFICIENTMEMORY;
+ goto end;
+ }
+end:
+ if (FAILED(hr))
+ PropertyStorage_DestroyDictionaries(This);
+ return hr;
+}
+
+static HRESULT PropertyStorage_BaseConstruct(IStream *stm,
+ REFFMTID rfmtid, DWORD grfMode, PropertyStorage_impl **pps)
+{
+ HRESULT hr = S_OK;
+
+ assert(pps);
+ assert(rfmtid);
+ *pps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof **pps);
+ if (!pps)
+ return E_OUTOFMEMORY;
+
+ (*pps)->vtbl = &IPropertyStorage_Vtbl;
+ (*pps)->ref = 1;
+ InitializeCriticalSection(&(*pps)->cs);
+ (*pps)->stm = stm;
+ memcpy(&(*pps)->fmtid, rfmtid, sizeof((*pps)->fmtid));
+ (*pps)->grfMode = grfMode;
+
+ hr = PropertyStorage_CreateDictionaries(*pps);
+
+ return hr;
}
+static HRESULT PropertyStorage_ConstructFromStream(IStream *stm,
+ REFFMTID rfmtid, DWORD grfMode, IPropertyStorage** pps)
+{
+ PropertyStorage_impl *ps;
+ HRESULT hr;
+
+ assert(pps);
+ hr = PropertyStorage_BaseConstruct(stm, rfmtid, grfMode, &ps);
+ if (SUCCEEDED(hr))
+ {
+ hr = PropertyStorage_ReadFromStream(ps);
+ if (SUCCEEDED(hr))
+ {
+ *pps = (IPropertyStorage *)ps;
+ TRACE("PropertyStorage %p constructed\n", ps);
+ hr = S_OK;
+ }
+ else
+ {
+ PropertyStorage_DestroyDictionaries(ps);
+ HeapFree(GetProcessHeap(), 0, ps);
+ }
+ }
+ return hr;
+}
+
+static HRESULT PropertyStorage_ConstructEmpty(IStream *stm,
+ REFFMTID rfmtid, DWORD grfFlags, DWORD grfMode, IPropertyStorage** pps)
+{
+ PropertyStorage_impl *ps;
+ HRESULT hr;
+
+ assert(pps);
+ hr = PropertyStorage_BaseConstruct(stm, rfmtid, grfMode, &ps);
+ if (SUCCEEDED(hr))
+ {
+ ps->grfFlags = grfFlags;
+ /* default to Unicode unless told not to, as specified here:
+ * http://msdn.microsoft.com/library/en-us/stg/stg/names_in_istorage.asp
+ */
+ if (ps->grfFlags & PROPSETFLAG_ANSI)
+ ps->codePage = GetACP();
+ else
+ ps->codePage = CP_UNICODE;
+ ps->locale = LOCALE_SYSTEM_DEFAULT;
+ TRACE("Code page is %d, locale is %ld\n", ps->codePage, ps->locale);
+ *pps = (IPropertyStorage *)ps;
+ TRACE("PropertyStorage %p constructed\n", ps);
+ hr = S_OK;
+ }
+ return hr;
+}
+
+
+/***********************************************************************
+ * Implementation of IPropertySetStorage
+ */
+
/************************************************************************
* IPropertySetStorage_fnQueryInterface (IUnknown)
*
void** ppvObject)
{
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
- return StorageBaseImpl_QueryInterface( (IStorage*)This, riid, ppvObject );
+ return IStorage_QueryInterface( (IStorage*)This, riid, ppvObject );
}
/************************************************************************
IPropertySetStorage *ppstg)
{
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
- return StorageBaseImpl_AddRef( (IStorage*)This );
+ return IStorage_AddRef( (IStorage*)This );
}
/************************************************************************
IPropertySetStorage *ppstg)
{
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
- return StorageBaseImpl_Release( (IStorage*)This );
+ return IStorage_Release( (IStorage*)This );
}
/************************************************************************
IPropertyStorage** ppprstg)
{
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
- LPCWSTR name = NULL;
+ WCHAR name[CCH_MAX_PROPSTG_NAME];
IStream *stm = NULL;
HRESULT r;
- TRACE("%p %s %08lx %p\n", This, debugstr_guid(rfmtid), grfMode, ppprstg);
+ TRACE("%p %s %08lx %08lx %p\n", This, debugstr_guid(rfmtid), grfFlags,
+ grfMode, ppprstg);
/* be picky */
if (grfMode != (STGM_CREATE|STGM_READWRITE|STGM_SHARE_EXCLUSIVE))
- return STG_E_INVALIDFLAG;
+ {
+ r = STG_E_INVALIDFLAG;
+ goto end;
+ }
if (!rfmtid)
- return E_INVALIDARG;
+ {
+ r = E_INVALIDARG;
+ goto end;
+ }
- name = format_id_to_name(rfmtid);
- if (!name)
- return STG_E_FILENOTFOUND;
+ /* FIXME: if (grfFlags & PROPSETFLAG_NONSIMPLE), we need to create a
+ * storage, not a stream. For now, disallow it.
+ */
+ if (grfFlags & PROPSETFLAG_NONSIMPLE)
+ {
+ FIXME("PROPSETFLAG_NONSIMPLE not supported\n");
+ r = STG_E_INVALIDFLAG;
+ goto end;
+ }
+
+ r = FmtIdToPropStgName(rfmtid, name);
+ if (FAILED(r))
+ goto end;
r = IStorage_CreateStream( (IStorage*)This, name, grfMode, 0, 0, &stm );
if (FAILED(r))
- return r;
+ goto end;
+
+ r = PropertyStorage_ConstructEmpty(stm, rfmtid, grfFlags, grfMode, ppprstg);
- return PropertyStorage_Contruct(stm, ppprstg);
+end:
+ TRACE("returning 0x%08lx\n", r);
+ return r;
}
/************************************************************************
{
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
IStream *stm = NULL;
- LPCWSTR name = NULL;
+ WCHAR name[CCH_MAX_PROPSTG_NAME];
HRESULT r;
TRACE("%p %s %08lx %p\n", This, debugstr_guid(rfmtid), grfMode, ppprstg);
/* be picky */
if (grfMode != (STGM_READWRITE|STGM_SHARE_EXCLUSIVE) &&
grfMode != (STGM_READ|STGM_SHARE_EXCLUSIVE))
- return STG_E_INVALIDFLAG;
+ {
+ r = STG_E_INVALIDFLAG;
+ goto end;
+ }
if (!rfmtid)
- return E_INVALIDARG;
+ {
+ r = E_INVALIDARG;
+ goto end;
+ }
- name = format_id_to_name(rfmtid);
- if (!name)
- return STG_E_FILENOTFOUND;
+ r = FmtIdToPropStgName(rfmtid, name);
+ if (FAILED(r))
+ goto end;
r = IStorage_OpenStream((IStorage*) This, name, 0, grfMode, 0, &stm );
if (FAILED(r))
- return r;
+ goto end;
- return PropertyStorage_Contruct(stm, ppprstg);
+ r = PropertyStorage_ConstructFromStream(stm, rfmtid, grfMode, ppprstg);
+
+end:
+ TRACE("returning 0x%08lx\n", r);
+ return r;
}
/************************************************************************
{
_ICOM_THIS_From_IPropertySetStorage(StorageImpl, ppstg);
IStorage *stg = NULL;
- LPCWSTR name = NULL;
+ WCHAR name[CCH_MAX_PROPSTG_NAME];
+ HRESULT r;
TRACE("%p %s\n", This, debugstr_guid(rfmtid));
if (!rfmtid)
return E_INVALIDARG;
- name = format_id_to_name(rfmtid);
- if (!name)
- return STG_E_FILENOTFOUND;
+ r = FmtIdToPropStgName(rfmtid, name);
+ if (FAILED(r))
+ return r;
stg = (IStorage*) This;
return IStorage_DestroyElement(stg, name);
IPropertyStorage_fnSetClass,
IPropertyStorage_fnStat,
};
+
+/***********************************************************************
+ * Format ID <-> name conversion
+ */
+static const WCHAR szSummaryInfo[] = { 5,'S','u','m','m','a','r','y',
+ 'I','n','f','o','r','m','a','t','i','o','n',0 };
+static const WCHAR szDocSummaryInfo[] = { 5,'D','o','c','u','m','e','n','t',
+ 'S','u','m','m','a','r','y','I','n','f','o','r','m','a','t','i','o','n',0 };
+
+#define BITS_PER_BYTE 8
+#define CHARMASK 0x1f
+#define BITS_IN_CHARMASK 5
+#define NUM_ALPHA_CHARS 26
+
+/***********************************************************************
+ * FmtIdToPropStgName [ole32.@]
+ * Returns the storage name of the format ID rfmtid.
+ * PARAMS
+ * rfmtid [I] Format ID for which to return a storage name
+ * str [O] Storage name associated with rfmtid.
+ *
+ * RETURNS
+ * E_INVALIDARG if rfmtid or str i NULL, S_OK otherwise.
+ *
+ * NOTES
+ * str must be at least CCH_MAX_PROPSTG_NAME characters in length.
+ * Based on the algorithm described here:
+ * http://msdn.microsoft.com/library/en-us/stg/stg/names_in_istorage.asp
+ */
+HRESULT WINAPI FmtIdToPropStgName(const FMTID *rfmtid, LPOLESTR str)
+{
+ static const char fmtMap[] = "abcdefghijklmnopqrstuvwxyz012345";
+
+ TRACE("%s, %p\n", debugstr_guid(rfmtid), str);
+
+ if (!rfmtid) return E_INVALIDARG;
+ if (!str) return E_INVALIDARG;
+
+ if (IsEqualGUID(&FMTID_SummaryInformation, rfmtid))
+ lstrcpyW(str, szSummaryInfo);
+ else if (IsEqualGUID(&FMTID_DocSummaryInformation, rfmtid))
+ lstrcpyW(str, szDocSummaryInfo);
+ else if (IsEqualGUID(&FMTID_UserDefinedProperties, rfmtid))
+ lstrcpyW(str, szDocSummaryInfo);
+ else
+ {
+ BYTE *fmtptr;
+ WCHAR *pstr = str;
+ ULONG bitsRemaining = BITS_PER_BYTE;
+
+ *pstr++ = 5;
+ for (fmtptr = (BYTE *)rfmtid; fmtptr < (BYTE *)rfmtid + sizeof(FMTID); )
+ {
+ ULONG i = *fmtptr >> (BITS_PER_BYTE - bitsRemaining);
+
+ if (bitsRemaining >= BITS_IN_CHARMASK)
+ {
+ *pstr = (WCHAR)(fmtMap[i & CHARMASK]);
+ if (bitsRemaining == BITS_PER_BYTE && *pstr >= 'a' &&
+ *pstr <= 'z')
+ *pstr += 'A' - 'a';
+ pstr++;
+ bitsRemaining -= BITS_IN_CHARMASK;
+ if (bitsRemaining == 0)
+ {
+ fmtptr++;
+ bitsRemaining = BITS_PER_BYTE;
+ }
+ }
+ else
+ {
+ if (++fmtptr < (BYTE *)rfmtid + sizeof(FMTID))
+ i |= *fmtptr << bitsRemaining;
+ *pstr++ = (WCHAR)(fmtMap[i & CHARMASK]);
+ bitsRemaining += BITS_PER_BYTE - BITS_IN_CHARMASK;
+ }
+ }
+ *pstr = 0;
+ }
+ TRACE("returning %s\n", debugstr_w(str));
+ return S_OK;
+}
+
+/***********************************************************************
+ * PropStgNameToFmtId [ole32.@]
+ * Returns the format ID corresponding to the given name.
+ * PARAMS
+ * str [I] Storage name to convert to a format ID.
+ * rfmtid [O] Format ID corresponding to str.
+ *
+ * RETURNS
+ * E_INVALIDARG if rfmtid or str is NULL or if str can't be converted to
+ * a format ID, S_OK otherwise.
+ *
+ * NOTES
+ * Based on the algorithm described here:
+ * http://msdn.microsoft.com/library/en-us/stg/stg/names_in_istorage.asp
+ */
+HRESULT WINAPI PropStgNameToFmtId(const LPOLESTR str, FMTID *rfmtid)
+{
+ HRESULT hr = E_INVALIDARG;
+
+ TRACE("%s, %p\n", debugstr_w(str), rfmtid);
+
+ if (!rfmtid) return E_INVALIDARG;
+ if (!str) return E_INVALIDARG;
+
+ if (!lstrcmpiW(str, szDocSummaryInfo))
+ {
+ memcpy(rfmtid, &FMTID_DocSummaryInformation, sizeof(*rfmtid));
+ hr = S_OK;
+ }
+ else if (!lstrcmpiW(str, szSummaryInfo))
+ {
+ memcpy(rfmtid, &FMTID_SummaryInformation, sizeof(*rfmtid));
+ hr = S_OK;
+ }
+ else
+ {
+ ULONG bits;
+ BYTE *fmtptr = (BYTE *)rfmtid - 1;
+ const WCHAR *pstr = str;
+
+ memset(rfmtid, 0, sizeof(*rfmtid));
+ for (bits = 0; bits < sizeof(FMTID) * BITS_PER_BYTE;
+ bits += BITS_IN_CHARMASK)
+ {
+ ULONG bitsUsed = bits % BITS_PER_BYTE, bitsStored;
+ WCHAR wc;
+
+ if (bitsUsed == 0)
+ fmtptr++;
+ wc = *++pstr - 'A';
+ if (wc > NUM_ALPHA_CHARS)
+ {
+ wc += 'A' - 'a';
+ if (wc > NUM_ALPHA_CHARS)
+ {
+ wc += 'a' - '0' + NUM_ALPHA_CHARS;
+ if (wc > CHARMASK)
+ {
+ WARN("invalid character (%d)\n", *pstr);
+ goto end;
+ }
+ }
+ }
+ *fmtptr |= wc << bitsUsed;
+ bitsStored = min(BITS_PER_BYTE - bitsUsed, BITS_IN_CHARMASK);
+ if (bitsStored < BITS_IN_CHARMASK)
+ {
+ wc >>= BITS_PER_BYTE - bitsUsed;
+ if (bits + bitsStored == sizeof(FMTID) * BITS_PER_BYTE)
+ {
+ if (wc != 0)
+ {
+ WARN("extra bits\n");
+ goto end;
+ }
+ break;
+ }
+ fmtptr++;
+ *fmtptr |= (BYTE)wc;
+ }
+ }
+ hr = S_OK;
+ }
+end:
+ return hr;
+}
WINE_DEFAULT_DEBUG_CHANNEL(storage);\r
\r
\r
-/*\r
- * Virtual function table for the StgStreamImpl class.\r
- */\r
-static IStreamVtbl StgStreamImpl_Vtbl =\r
-{\r
- StgStreamImpl_QueryInterface,\r
- StgStreamImpl_AddRef,\r
- StgStreamImpl_Release,\r
- StgStreamImpl_Read,\r
- StgStreamImpl_Write,\r
- StgStreamImpl_Seek,\r
- StgStreamImpl_SetSize,\r
- StgStreamImpl_CopyTo,\r
- StgStreamImpl_Commit,\r
- StgStreamImpl_Revert,\r
- StgStreamImpl_LockRegion,\r
- StgStreamImpl_UnlockRegion,\r
- StgStreamImpl_Stat,\r
- StgStreamImpl_Clone\r
-};\r
-\r
-/******************************************************************************\r
-** StgStreamImpl implementation\r
-*/\r
-\r
-/***\r
- * This is the constructor for the StgStreamImpl class.\r
- *\r
- * Params:\r
- * parentStorage - Pointer to the storage that contains the stream to open\r
- * ownerProperty - Index of the property that points to this stream.\r
- */\r
-StgStreamImpl* StgStreamImpl_Construct(\r
- StorageBaseImpl* parentStorage,\r
- DWORD grfMode,\r
- ULONG ownerProperty)\r
-{\r
- StgStreamImpl* newStream;\r
-\r
- newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(StgStreamImpl));\r
-\r
- if (newStream!=0)\r
- {\r
- /*\r
- * Set-up the virtual function table and reference count.\r
- */\r
- newStream->lpVtbl = &StgStreamImpl_Vtbl;\r
- newStream->ref = 0;\r
-\r
- /*\r
- * We want to nail-down the reference to the storage in case the\r
- * stream out-lives the storage in the client application.\r
- */\r
- newStream->parentStorage = parentStorage;\r
- IStorage_AddRef((IStorage*)newStream->parentStorage);\r
-\r
- newStream->grfMode = grfMode;\r
- newStream->ownerProperty = ownerProperty;\r
-\r
- /*\r
- * Start the stream at the beginning.\r
- */\r
- newStream->currentPosition.u.HighPart = 0;\r
- newStream->currentPosition.u.LowPart = 0;\r
-\r
- /*\r
- * Initialize the rest of the data.\r
- */\r
- newStream->streamSize.u.HighPart = 0;\r
- newStream->streamSize.u.LowPart = 0;\r
- newStream->bigBlockChain = 0;\r
- newStream->smallBlockChain = 0;\r
-\r
- /*\r
- * Read the size from the property and determine if the blocks forming\r
- * this stream are large or small.\r
- */\r
- StgStreamImpl_OpenBlockChain(newStream);\r
- }\r
-\r
- return newStream;\r
-}\r
-\r
/***\r
* This is the destructor of the StgStreamImpl class.\r
*\r
* class. The pointer passed-in to this function will be freed and will not\r
* be valid anymore.\r
*/\r
-void StgStreamImpl_Destroy(StgStreamImpl* This)\r
+static void StgStreamImpl_Destroy(StgStreamImpl* This)\r
{\r
TRACE("(%p)\n", This);\r
\r
* This implements the IUnknown method QueryInterface for this\r
* class\r
*/\r
-HRESULT WINAPI StgStreamImpl_QueryInterface(\r
+static HRESULT WINAPI StgStreamImpl_QueryInterface(\r
IStream* iface,\r
REFIID riid, /* [in] */\r
void** ppvObject) /* [iid_is][out] */\r
/*\r
* Compare the riid with the interface IDs implemented by this object.\r
*/\r
- if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)\r
- {\r
- *ppvObject = (IStream*)This;\r
- }\r
- else if (memcmp(&IID_IStream, riid, sizeof(IID_IStream)) == 0)\r
+ if (IsEqualGUID(&IID_IUnknown, riid)||\r
+ IsEqualGUID(&IID_IStream, riid))\r
{\r
*ppvObject = (IStream*)This;\r
}\r
* Query Interface always increases the reference count by one when it is\r
* successful\r
*/\r
- StgStreamImpl_AddRef(iface);\r
+ IStream_AddRef(iface);\r
\r
return S_OK;\r
}\r
* This implements the IUnknown method AddRef for this\r
* class\r
*/\r
-ULONG WINAPI StgStreamImpl_AddRef(\r
+static ULONG WINAPI StgStreamImpl_AddRef(\r
IStream* iface)\r
{\r
StgStreamImpl* const This=(StgStreamImpl*)iface;\r
* This implements the IUnknown method Release for this\r
* class\r
*/\r
-ULONG WINAPI StgStreamImpl_Release(\r
+static ULONG WINAPI StgStreamImpl_Release(\r
IStream* iface)\r
{\r
StgStreamImpl* const This=(StgStreamImpl*)iface;\r
* that describes the stream.\r
* If the stream's size is null, no chain is opened.\r
*/\r
-void StgStreamImpl_OpenBlockChain(\r
+static void StgStreamImpl_OpenBlockChain(\r
StgStreamImpl* This)\r
{\r
StgProperty curProperty;\r
*\r
* See the documentation of ISequentialStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_Read(\r
+static HRESULT WINAPI StgStreamImpl_Read(\r
IStream* iface,\r
void* pv, /* [length_is][size_is][out] */\r
ULONG cb, /* [in] */\r
*\r
* See the documentation of ISequentialStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_Write(\r
+static HRESULT WINAPI StgStreamImpl_Write(\r
IStream* iface,\r
const void* pv, /* [size_is][in] */\r
ULONG cb, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_Seek(\r
+static HRESULT WINAPI StgStreamImpl_Seek(\r
IStream* iface,\r
LARGE_INTEGER dlibMove, /* [in] */\r
DWORD dwOrigin, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_SetSize(\r
+static HRESULT WINAPI StgStreamImpl_SetSize(\r
IStream* iface,\r
ULARGE_INTEGER libNewSize) /* [in] */\r
{\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_CopyTo(\r
+static HRESULT WINAPI StgStreamImpl_CopyTo(\r
IStream* iface,\r
IStream* pstm, /* [unique][in] */\r
ULARGE_INTEGER cb, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_Commit(\r
+static HRESULT WINAPI StgStreamImpl_Commit(\r
IStream* iface,\r
DWORD grfCommitFlags) /* [in] */\r
{\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_Revert(\r
+static HRESULT WINAPI StgStreamImpl_Revert(\r
IStream* iface)\r
{\r
return S_OK;\r
}\r
\r
-HRESULT WINAPI StgStreamImpl_LockRegion(\r
+static HRESULT WINAPI StgStreamImpl_LockRegion(\r
IStream* iface,\r
ULARGE_INTEGER libOffset, /* [in] */\r
ULARGE_INTEGER cb, /* [in] */\r
return E_NOTIMPL;\r
}\r
\r
-HRESULT WINAPI StgStreamImpl_UnlockRegion(\r
+static HRESULT WINAPI StgStreamImpl_UnlockRegion(\r
IStream* iface,\r
ULARGE_INTEGER libOffset, /* [in] */\r
ULARGE_INTEGER cb, /* [in] */\r
*\r
* See the documentation of IStream for more info.\r
*/\r
-HRESULT WINAPI StgStreamImpl_Stat(\r
+static HRESULT WINAPI StgStreamImpl_Stat(\r
IStream* iface,\r
STATSTG* pstatstg, /* [out] */\r
DWORD grfStatFlag) /* [in] */\r
* should be basically as simple as creating a new stream with the same\r
* parent etc and positioning its seek cursor.\r
*/\r
-HRESULT WINAPI StgStreamImpl_Clone(\r
+static HRESULT WINAPI StgStreamImpl_Clone(\r
IStream* iface,\r
IStream** ppstm) /* [out] */\r
{\r
\r
return S_OK;\r
}\r
+\r
+/*\r
+ * Virtual function table for the StgStreamImpl class.\r
+ */\r
+static IStreamVtbl StgStreamImpl_Vtbl =\r
+{\r
+ StgStreamImpl_QueryInterface,\r
+ StgStreamImpl_AddRef,\r
+ StgStreamImpl_Release,\r
+ StgStreamImpl_Read,\r
+ StgStreamImpl_Write,\r
+ StgStreamImpl_Seek,\r
+ StgStreamImpl_SetSize,\r
+ StgStreamImpl_CopyTo,\r
+ StgStreamImpl_Commit,\r
+ StgStreamImpl_Revert,\r
+ StgStreamImpl_LockRegion,\r
+ StgStreamImpl_UnlockRegion,\r
+ StgStreamImpl_Stat,\r
+ StgStreamImpl_Clone\r
+};\r
+\r
+/******************************************************************************\r
+** StgStreamImpl implementation\r
+*/\r
+\r
+/***\r
+ * This is the constructor for the StgStreamImpl class.\r
+ *\r
+ * Params:\r
+ * parentStorage - Pointer to the storage that contains the stream to open\r
+ * ownerProperty - Index of the property that points to this stream.\r
+ */\r
+StgStreamImpl* StgStreamImpl_Construct(\r
+ StorageBaseImpl* parentStorage,\r
+ DWORD grfMode,\r
+ ULONG ownerProperty)\r
+{\r
+ StgStreamImpl* newStream;\r
+\r
+ newStream = HeapAlloc(GetProcessHeap(), 0, sizeof(StgStreamImpl));\r
+\r
+ if (newStream!=0)\r
+ {\r
+ /*\r
+ * Set-up the virtual function table and reference count.\r
+ */\r
+ newStream->lpVtbl = &StgStreamImpl_Vtbl;\r
+ newStream->ref = 0;\r
+\r
+ /*\r
+ * We want to nail-down the reference to the storage in case the\r
+ * stream out-lives the storage in the client application.\r
+ */\r
+ newStream->parentStorage = parentStorage;\r
+ IStorage_AddRef((IStorage*)newStream->parentStorage);\r
+\r
+ newStream->grfMode = grfMode;\r
+ newStream->ownerProperty = ownerProperty;\r
+\r
+ /*\r
+ * Start the stream at the beginning.\r
+ */\r
+ newStream->currentPosition.u.HighPart = 0;\r
+ newStream->currentPosition.u.LowPart = 0;\r
+\r
+ /*\r
+ * Initialize the rest of the data.\r
+ */\r
+ newStream->streamSize.u.HighPart = 0;\r
+ newStream->streamSize.u.LowPart = 0;\r
+ newStream->bigBlockChain = 0;\r
+ newStream->smallBlockChain = 0;\r
+\r
+ /*\r
+ * Read the size from the property and determine if the blocks forming\r
+ * this stream are large or small.\r
+ */\r
+ StgStreamImpl_OpenBlockChain(newStream);\r
+ }\r
+\r
+ return newStream;\r
+}\r
static DWORD GetAccessModeFromSTGM(DWORD stgm);\r
static DWORD GetCreationModeFromSTGM(DWORD stgm);\r
\r
-/*\r
- * Virtual function table for the IStorage32Impl class.\r
- */\r
-static IStorageVtbl Storage32Impl_Vtbl =\r
-{\r
- StorageBaseImpl_QueryInterface,\r
- StorageBaseImpl_AddRef,\r
- StorageBaseImpl_Release,\r
- StorageBaseImpl_CreateStream,\r
- StorageBaseImpl_OpenStream,\r
- StorageImpl_CreateStorage,\r
- StorageBaseImpl_OpenStorage,\r
- StorageImpl_CopyTo,\r
- StorageImpl_MoveElementTo,\r
- StorageImpl_Commit,\r
- StorageImpl_Revert,\r
- StorageBaseImpl_EnumElements,\r
- StorageImpl_DestroyElement,\r
- StorageBaseImpl_RenameElement,\r
- StorageImpl_SetElementTimes,\r
- StorageBaseImpl_SetClass,\r
- StorageImpl_SetStateBits,\r
- StorageImpl_Stat\r
-};\r
-\r
-/*\r
- * Virtual function table for the Storage32InternalImpl class.\r
- */\r
-static IStorageVtbl Storage32InternalImpl_Vtbl =\r
- {\r
- StorageBaseImpl_QueryInterface,\r
- StorageBaseImpl_AddRef,\r
- StorageBaseImpl_Release,\r
- StorageBaseImpl_CreateStream,\r
- StorageBaseImpl_OpenStream,\r
- StorageImpl_CreateStorage,\r
- StorageBaseImpl_OpenStorage,\r
- StorageImpl_CopyTo,\r
- StorageImpl_MoveElementTo,\r
- StorageInternalImpl_Commit,\r
- StorageInternalImpl_Revert,\r
- StorageBaseImpl_EnumElements,\r
- StorageImpl_DestroyElement,\r
- StorageBaseImpl_RenameElement,\r
- StorageImpl_SetElementTimes,\r
- StorageBaseImpl_SetClass,\r
- StorageImpl_SetStateBits,\r
- StorageBaseImpl_Stat\r
-};\r
-\r
-/*\r
- * Virtual function table for the IEnumSTATSTGImpl class.\r
- */\r
-static IEnumSTATSTGVtbl IEnumSTATSTGImpl_Vtbl =\r
-{\r
- IEnumSTATSTGImpl_QueryInterface,\r
- IEnumSTATSTGImpl_AddRef,\r
- IEnumSTATSTGImpl_Release,\r
- IEnumSTATSTGImpl_Next,\r
- IEnumSTATSTGImpl_Skip,\r
- IEnumSTATSTGImpl_Reset,\r
- IEnumSTATSTGImpl_Clone\r
-};\r
-\r
extern IPropertySetStorageVtbl IPropertySetStorage_Vtbl;\r
\r
\r
* Query Interface always increases the reference count by one when it is\r
* successful\r
*/\r
- StorageBaseImpl_AddRef(iface);\r
+ IStorage_AddRef(iface);\r
\r
return S_OK;\r
}\r
* Since we are returning a pointer to the interface, we have to\r
* nail down the reference.\r
*/\r
- StgStreamImpl_AddRef(*ppstm);\r
+ IStream_AddRef(*ppstm);\r
\r
res = S_OK;\r
goto end;\r
* Don't forget to nail down a reference to the new object before\r
* returning it.\r
*/\r
- IEnumSTATSTGImpl_AddRef(*ppenum);\r
+ IEnumSTATSTG_AddRef(*ppenum);\r
\r
return S_OK;\r
}\r
return STG_E_FILEALREADYEXISTS;\r
}\r
\r
- IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)propertyEnumeration);\r
+ IEnumSTATSTG_Reset((IEnumSTATSTG*)propertyEnumeration);\r
\r
/*\r
* Search the enumeration for the old property name\r
* Invoke Destroy to get rid of the ole property and automatically redo\r
* the linking of it's previous and next members...\r
*/\r
- StorageImpl_DestroyElement((IStorage*)This->ancestorStorage, pwcsOldName);\r
+ IStorage_DestroyElement((IStorage*)This->ancestorStorage, pwcsOldName);\r
\r
}\r
else\r
* Since we are returning a pointer to the interface, we have to nail down\r
* the reference.\r
*/\r
- StgStreamImpl_AddRef(*ppstm);\r
+ IStream_AddRef(*ppstm);\r
}\r
else\r
{\r
return E_NOTIMPL;\r
}\r
\r
+/*\r
+ * Virtual function table for the IStorage32Impl class.\r
+ */\r
+static IStorageVtbl Storage32Impl_Vtbl =\r
+{\r
+ StorageBaseImpl_QueryInterface,\r
+ StorageBaseImpl_AddRef,\r
+ StorageBaseImpl_Release,\r
+ StorageBaseImpl_CreateStream,\r
+ StorageBaseImpl_OpenStream,\r
+ StorageImpl_CreateStorage,\r
+ StorageBaseImpl_OpenStorage,\r
+ StorageImpl_CopyTo,\r
+ StorageImpl_MoveElementTo,\r
+ StorageImpl_Commit,\r
+ StorageImpl_Revert,\r
+ StorageBaseImpl_EnumElements,\r
+ StorageImpl_DestroyElement,\r
+ StorageBaseImpl_RenameElement,\r
+ StorageImpl_SetElementTimes,\r
+ StorageBaseImpl_SetClass,\r
+ StorageImpl_SetStateBits,\r
+ StorageImpl_Stat\r
+};\r
+\r
HRESULT StorageImpl_Construct(\r
StorageImpl* This,\r
HANDLE hFile,\r
cbTotalRead = 0;\r
cbTotalWritten = 0;\r
\r
- buffer = (BYTE *) HeapAlloc(GetProcessHeap(),0,DEF_SMALL_BLOCK_SIZE);\r
+ buffer = HeapAlloc(GetProcessHeap(),0,DEF_SMALL_BLOCK_SIZE);\r
do\r
{\r
successRead = SmallBlockChainStream_ReadAt(*ppsbChain,\r
return bigBlockChain;\r
}\r
\r
-/******************************************************************************\r
-** Storage32InternalImpl implementation\r
-*/\r
-\r
-StorageInternalImpl* StorageInternalImpl_Construct(\r
- StorageImpl* ancestorStorage,\r
- ULONG rootPropertyIndex)\r
-{\r
- StorageInternalImpl* newStorage;\r
-\r
- /*\r
- * Allocate space for the new storage object\r
- */\r
- newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageInternalImpl));\r
-\r
- if (newStorage!=0)\r
- {\r
- memset(newStorage, 0, sizeof(StorageInternalImpl));\r
-\r
- /*\r
- * Initialize the virtual function table.\r
- */\r
- newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl;\r
- newStorage->base.v_destructor = &StorageInternalImpl_Destroy;\r
-\r
- /*\r
- * Keep the ancestor storage pointer and nail a reference to it.\r
- */\r
- newStorage->base.ancestorStorage = ancestorStorage;\r
- StorageBaseImpl_AddRef((IStorage*)(newStorage->base.ancestorStorage));\r
-\r
- /*\r
- * Keep the index of the root property set for this storage,\r
- */\r
- newStorage->base.rootPropertySetIndex = rootPropertyIndex;\r
-\r
- return newStorage;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
void StorageInternalImpl_Destroy( StorageBaseImpl *iface)\r
{\r
StorageInternalImpl* This = (StorageInternalImpl*) iface;\r
return S_OK;\r
}\r
\r
-/******************************************************************************\r
-** IEnumSTATSTGImpl implementation\r
-*/\r
-\r
-IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(\r
- StorageImpl* parentStorage,\r
- ULONG firstPropertyNode)\r
-{\r
- IEnumSTATSTGImpl* newEnumeration;\r
-\r
- newEnumeration = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumSTATSTGImpl));\r
-\r
- if (newEnumeration!=0)\r
- {\r
- /*\r
- * Set-up the virtual function table and reference count.\r
- */\r
- newEnumeration->lpVtbl = &IEnumSTATSTGImpl_Vtbl;\r
- newEnumeration->ref = 0;\r
-\r
- /*\r
- * We want to nail-down the reference to the storage in case the\r
- * enumeration out-lives the storage in the client application.\r
- */\r
- newEnumeration->parentStorage = parentStorage;\r
- IStorage_AddRef((IStorage*)newEnumeration->parentStorage);\r
-\r
- newEnumeration->firstPropertyNode = firstPropertyNode;\r
-\r
- /*\r
- * Initialize the search stack\r
- */\r
- newEnumeration->stackSize = 0;\r
- newEnumeration->stackMaxSize = ENUMSTATSGT_SIZE_INCREMENT;\r
- newEnumeration->stackToVisit =\r
- HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG)*ENUMSTATSGT_SIZE_INCREMENT);\r
-\r
- /*\r
- * Make sure the current node of the iterator is the first one.\r
- */\r
- IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)newEnumeration);\r
- }\r
-\r
- return newEnumeration;\r
-}\r
-\r
void IEnumSTATSTGImpl_Destroy(IEnumSTATSTGImpl* This)\r
{\r
IStorage_Release((IStorage*)This->parentStorage);\r
/*\r
* Compare the riid with the interface IDs implemented by this object.\r
*/\r
- if (memcmp(&IID_IUnknown, riid, sizeof(IID_IUnknown)) == 0)\r
- {\r
- *ppvObject = (IEnumSTATSTG*)This;\r
- }\r
- else if (memcmp(&IID_IStorage, riid, sizeof(IID_IEnumSTATSTG)) == 0)\r
+ if (IsEqualGUID(&IID_IUnknown, riid) ||\r
+ IsEqualGUID(&IID_IStorage, riid))\r
{\r
*ppvObject = (IEnumSTATSTG*)This;\r
+ IEnumSTATSTG_AddRef((IEnumSTATSTG*)This);\r
+ return S_OK;\r
}\r
\r
- /*\r
- * Check that we obtained an interface.\r
- */\r
- if ((*ppvObject)==0)\r
- return E_NOINTERFACE;\r
-\r
- /*\r
- * Query Interface always increases the reference count by one when it is\r
- * successful\r
- */\r
- IEnumSTATSTGImpl_AddRef((IEnumSTATSTG*)This);\r
-\r
- return S_OK;\r
+ return E_NOINTERFACE;\r
}\r
\r
ULONG WINAPI IEnumSTATSTGImpl_AddRef(\r
return topNode;\r
}\r
\r
+/*\r
+ * Virtual function table for the IEnumSTATSTGImpl class.\r
+ */\r
+static IEnumSTATSTGVtbl IEnumSTATSTGImpl_Vtbl =\r
+{\r
+ IEnumSTATSTGImpl_QueryInterface,\r
+ IEnumSTATSTGImpl_AddRef,\r
+ IEnumSTATSTGImpl_Release,\r
+ IEnumSTATSTGImpl_Next,\r
+ IEnumSTATSTGImpl_Skip,\r
+ IEnumSTATSTGImpl_Reset,\r
+ IEnumSTATSTGImpl_Clone\r
+};\r
+\r
+/******************************************************************************\r
+** IEnumSTATSTGImpl implementation\r
+*/\r
+\r
+IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(\r
+ StorageImpl* parentStorage,\r
+ ULONG firstPropertyNode)\r
+{\r
+ IEnumSTATSTGImpl* newEnumeration;\r
+\r
+ newEnumeration = HeapAlloc(GetProcessHeap(), 0, sizeof(IEnumSTATSTGImpl));\r
+\r
+ if (newEnumeration!=0)\r
+ {\r
+ /*\r
+ * Set-up the virtual function table and reference count.\r
+ */\r
+ newEnumeration->lpVtbl = &IEnumSTATSTGImpl_Vtbl;\r
+ newEnumeration->ref = 0;\r
+\r
+ /*\r
+ * We want to nail-down the reference to the storage in case the\r
+ * enumeration out-lives the storage in the client application.\r
+ */\r
+ newEnumeration->parentStorage = parentStorage;\r
+ IStorage_AddRef((IStorage*)newEnumeration->parentStorage);\r
+\r
+ newEnumeration->firstPropertyNode = firstPropertyNode;\r
+\r
+ /*\r
+ * Initialize the search stack\r
+ */\r
+ newEnumeration->stackSize = 0;\r
+ newEnumeration->stackMaxSize = ENUMSTATSGT_SIZE_INCREMENT;\r
+ newEnumeration->stackToVisit =\r
+ HeapAlloc(GetProcessHeap(), 0, sizeof(ULONG)*ENUMSTATSGT_SIZE_INCREMENT);\r
+\r
+ /*\r
+ * Make sure the current node of the iterator is the first one.\r
+ */\r
+ IEnumSTATSTGImpl_Reset((IEnumSTATSTG*)newEnumeration);\r
+ }\r
+\r
+ return newEnumeration;\r
+}\r
+\r
+/*\r
+ * Virtual function table for the Storage32InternalImpl class.\r
+ */\r
+static IStorageVtbl Storage32InternalImpl_Vtbl =\r
+{\r
+ StorageBaseImpl_QueryInterface,\r
+ StorageBaseImpl_AddRef,\r
+ StorageBaseImpl_Release,\r
+ StorageBaseImpl_CreateStream,\r
+ StorageBaseImpl_OpenStream,\r
+ StorageImpl_CreateStorage,\r
+ StorageBaseImpl_OpenStorage,\r
+ StorageImpl_CopyTo,\r
+ StorageImpl_MoveElementTo,\r
+ StorageInternalImpl_Commit,\r
+ StorageInternalImpl_Revert,\r
+ StorageBaseImpl_EnumElements,\r
+ StorageImpl_DestroyElement,\r
+ StorageBaseImpl_RenameElement,\r
+ StorageImpl_SetElementTimes,\r
+ StorageBaseImpl_SetClass,\r
+ StorageImpl_SetStateBits,\r
+ StorageBaseImpl_Stat\r
+};\r
+\r
+/******************************************************************************\r
+** Storage32InternalImpl implementation\r
+*/\r
+\r
+StorageInternalImpl* StorageInternalImpl_Construct(\r
+ StorageImpl* ancestorStorage,\r
+ ULONG rootPropertyIndex)\r
+{\r
+ StorageInternalImpl* newStorage;\r
+\r
+ /*\r
+ * Allocate space for the new storage object\r
+ */\r
+ newStorage = HeapAlloc(GetProcessHeap(), 0, sizeof(StorageInternalImpl));\r
+\r
+ if (newStorage!=0)\r
+ {\r
+ memset(newStorage, 0, sizeof(StorageInternalImpl));\r
+\r
+ /*\r
+ * Initialize the virtual function table.\r
+ */\r
+ newStorage->base.lpVtbl = &Storage32InternalImpl_Vtbl;\r
+ newStorage->base.v_destructor = &StorageInternalImpl_Destroy;\r
+\r
+ /*\r
+ * Keep the ancestor storage pointer and nail a reference to it.\r
+ */\r
+ newStorage->base.ancestorStorage = ancestorStorage;\r
+ StorageBaseImpl_AddRef((IStorage*)(newStorage->base.ancestorStorage));\r
+\r
+ /*\r
+ * Keep the index of the root property set for this storage,\r
+ */\r
+ newStorage->base.rootPropertySetIndex = rootPropertyIndex;\r
+\r
+ return newStorage;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
/******************************************************************************\r
** StorageUtl implementation\r
+* FIXME: these should read and write in little-endian order on all\r
+* architectures, but right now just assume the host is little-endian.\r
*/\r
\r
-void StorageUtl_ReadWord(void* buffer, ULONG offset, WORD* value)\r
+void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value)\r
{\r
- memcpy(value, (BYTE*)buffer+offset, sizeof(WORD));\r
+ memcpy(value, buffer+offset, sizeof(WORD));\r
}\r
\r
-void StorageUtl_WriteWord(void* buffer, ULONG offset, WORD value)\r
+void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value)\r
{\r
- memcpy((BYTE*)buffer+offset, &value, sizeof(WORD));\r
+ memcpy(buffer+offset, &value, sizeof(WORD));\r
}\r
\r
-void StorageUtl_ReadDWord(void* buffer, ULONG offset, DWORD* value)\r
+void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value)\r
{\r
- memcpy(value, (BYTE*)buffer+offset, sizeof(DWORD));\r
+ memcpy(value, buffer+offset, sizeof(DWORD));\r
}\r
\r
-void StorageUtl_WriteDWord(void* buffer, ULONG offset, DWORD value)\r
+void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value)\r
{\r
- memcpy((BYTE*)buffer+offset, &value, sizeof(DWORD));\r
+ memcpy(buffer+offset, &value, sizeof(DWORD));\r
}\r
\r
-void StorageUtl_ReadGUID(void* buffer, ULONG offset, GUID* value)\r
+void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value)\r
{\r
StorageUtl_ReadDWord(buffer, offset, &(value->Data1));\r
StorageUtl_ReadWord(buffer, offset+4, &(value->Data2));\r
StorageUtl_ReadWord(buffer, offset+6, &(value->Data3));\r
\r
- memcpy(value->Data4, (BYTE*)buffer+offset+8, sizeof(value->Data4));\r
+ memcpy(value->Data4, buffer+offset+8, sizeof(value->Data4));\r
}\r
\r
-void StorageUtl_WriteGUID(void* buffer, ULONG offset, GUID* value)\r
+void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value)\r
{\r
StorageUtl_WriteDWord(buffer, offset, value->Data1);\r
StorageUtl_WriteWord(buffer, offset+4, value->Data2);\r
StorageUtl_WriteWord(buffer, offset+6, value->Data3);\r
\r
- memcpy((BYTE*)buffer+offset+8, value->Data4, sizeof(value->Data4));\r
+ memcpy(buffer+offset+8, value->Data4, sizeof(value->Data4));\r
}\r
\r
void StorageUtl_CopyPropertyToSTATSTG(\r
\r
if (success)\r
{\r
- StorageUtl_ReadDWord(&buffer, 0, nextBlockInChain);\r
+ StorageUtl_ReadDWord((BYTE *)&buffer, 0, nextBlockInChain);\r
return S_OK;\r
}\r
\r
offsetOfBlockInDepot.u.HighPart = 0;\r
offsetOfBlockInDepot.u.LowPart = blockIndex * sizeof(ULONG);\r
\r
- StorageUtl_WriteDWord(&buffer, 0, nextBlock);\r
+ StorageUtl_WriteDWord((BYTE *)&buffer, 0, nextBlock);\r
\r
/*\r
* Read those bytes in the buffer from the small block file.\r
*/\r
if (success)\r
{\r
- StorageUtl_ReadDWord(&buffer, 0, &nextBlockIndex);\r
+ StorageUtl_ReadDWord((BYTE *)&buffer, 0, &nextBlockIndex);\r
\r
if (nextBlockIndex != BLOCK_UNUSED)\r
blockIndex++;\r
WCHAR tempPath[MAX_PATH];\r
static const WCHAR prefix[] = { 'S', 'T', 'O', 0 };\r
\r
- if (STGM_SHARE_MODE(grfMode) == STGM_SHARE_EXCLUSIVE)\r
+ if (STGM_SHARE_MODE(grfMode) != STGM_SHARE_EXCLUSIVE)\r
goto end;\r
\r
memset(tempPath, 0, sizeof(tempPath));\r
goto end;\r
}\r
\r
+ /* shared reading requires transacted mode */\r
+ if( STGM_SHARE_MODE(grfMode) == STGM_SHARE_DENY_WRITE &&\r
+ STGM_ACCESS_MODE(grfMode) == STGM_READWRITE &&\r
+ !(grfMode&STGM_TRANSACTED) )\r
+ {\r
+ hr = STG_E_INVALIDFLAG;\r
+ goto end;\r
+ }\r
+\r
/*\r
* Interpret the STGM value grfMode\r
*/\r
goto end;\r
}\r
\r
+ /*\r
+ * Refuse to open the file if it's too small to be a structured storage file\r
+ * FIXME: verify the file when reading instead of here\r
+ */\r
length = GetFileSize(hFile, NULL);\r
+ if (length < 0x100)\r
+ {\r
+ CloseHandle(hFile);\r
+ hr = STG_E_FILEALREADYEXISTS;\r
+ goto end;\r
+ }\r
\r
/*\r
* Allocate and initialize the new IStorage32object.\r
NULL,\r
grfMode,\r
TRUE,\r
- !length );\r
+ FALSE );\r
\r
if (FAILED(hr))\r
{\r
/*\r
* STGM_NOSCRATCH requires STGM_TRANSACTED\r
*/\r
- if ( (stgm & STGM_NOSCRATCH) && (stgm & STGM_TRANSACTED) )\r
+ if ( (stgm & STGM_NOSCRATCH) && !(stgm & STGM_TRANSACTED) )\r
return E_FAIL;\r
\r
/*\r
{\r
if(pData->dwOleObjFileNameLength < 1) /* there is no file name exist */\r
pData->dwOleObjFileNameLength = sizeof(pData->dwOleObjFileNameLength);\r
- pData->pstrOleObjFileName = (CHAR *)HeapAlloc(GetProcessHeap(), 0, pData->dwOleObjFileNameLength);\r
+ pData->pstrOleObjFileName = HeapAlloc(GetProcessHeap(), 0, pData->dwOleObjFileNameLength);\r
if(pData->pstrOleObjFileName)\r
{\r
dwSize = pOleStream->lpstbl->Get(pOleStream, (void *)(pData->pstrOleObjFileName),pData->dwOleObjFileNameLength);\r
{\r
if(pData->dwDataLength > 0)\r
{\r
- pData->pData = (BYTE *)HeapAlloc(GetProcessHeap(),0,pData->dwDataLength);\r
+ pData->pData = HeapAlloc(GetProcessHeap(),0,pData->dwDataLength);\r
\r
/* Get Data (ex. IStorage, Metafile, or BMP) */\r
if(pData->pData)\r
if(hFile != INVALID_HANDLE_VALUE)\r
{\r
nDataLength = GetFileSize(hFile, NULL);\r
- *pData = (BYTE *) HeapAlloc(GetProcessHeap(),0,nDataLength);\r
+ *pData = HeapAlloc(GetProcessHeap(),0,nDataLength);\r
ReadFile(hFile, *pData, nDataLength, &nDataLength, 0);\r
CloseHandle(hFile);\r
}\r
return r;\r
}\r
\r
-/* enumerate HKEY_CLASSES_ROOT\\CLSID looking for a CLSID whose name matches */\r
-static HRESULT CLSIDFromUserType(LPCWSTR lpszUserType, CLSID *clsid)\r
-{\r
- LONG r, i, len;\r
- ULONG count;\r
- WCHAR szKey[0x40];\r
- HKEY hkey, hkeyclsid;\r
- LPWSTR buffer = NULL;\r
- BOOL found = FALSE;\r
- static const WCHAR szclsid[] = { 'C','L','S','I','D',0 };\r
-\r
- TRACE("Finding CLSID for %s\n", debugstr_w(lpszUserType));\r
-\r
- r = RegOpenKeyW( HKEY_CLASSES_ROOT, szclsid, &hkeyclsid );\r
- if( r )\r
- return E_INVALIDARG;\r
-\r
- len = lstrlenW( lpszUserType ) + 1;\r
- buffer = CoTaskMemAlloc( len * sizeof (WCHAR) );\r
- if( !buffer )\r
- goto end;\r
-\r
- for(i=0; !found; i++ )\r
- {\r
- r = RegEnumKeyW( hkeyclsid, i, szKey, sizeof(szKey)/sizeof(WCHAR));\r
- if( r != ERROR_SUCCESS )\r
- break;\r
- hkey = 0;\r
- r = RegOpenKeyW( hkeyclsid, szKey, &hkey );\r
- if( r != ERROR_SUCCESS )\r
- break;\r
- count = len * sizeof (WCHAR);\r
- r = RegQueryValueW( hkey, NULL, buffer, &count );\r
- found = ( r == ERROR_SUCCESS ) &&\r
- ( count == len*sizeof(WCHAR) ) && \r
- !lstrcmpW( buffer, lpszUserType ) ;\r
- RegCloseKey( hkey );\r
- }\r
-\r
-end:\r
- if( buffer )\r
- CoTaskMemFree( buffer );\r
- RegCloseKey( hkeyclsid );\r
-\r
- if ( !found )\r
- return E_INVALIDARG;\r
-\r
- TRACE("clsid is %s\n", debugstr_w( szKey ) );\r
-\r
- r = CLSIDFromString( szKey, clsid );\r
-\r
- return r;\r
-}\r
-\r
-\r
/***********************************************************************\r
* WriteFmtUserTypeStg (OLE32.@)\r
*/\r
{\r
HRESULT r;\r
WCHAR szwClipName[0x40];\r
- WCHAR szCLSIDName[OLESTREAM_MAX_STR_LEN];\r
- CLSID clsid;\r
- LPWSTR wstrProgID;\r
+ CLSID clsid = CLSID_NULL;\r
+ LPWSTR wstrProgID = NULL;\r
DWORD n;\r
- LPMALLOC allocator = NULL;\r
\r
TRACE("(%p,%x,%s)\n",pstg,cf,debugstr_w(lpszUserType));\r
\r
- r = CoGetMalloc(0, &allocator);\r
- if( FAILED( r) )\r
- return E_OUTOFMEMORY;\r
-\r
/* get the clipboard format name */\r
n = GetClipboardFormatNameW( cf, szwClipName, sizeof(szwClipName) );\r
szwClipName[n]=0;\r
\r
TRACE("Clipboard name is %s\n", debugstr_w(szwClipName));\r
\r
- /* Get the CLSID */\r
- szCLSIDName[0]=0;\r
- r = CLSIDFromUserType(lpszUserType, &clsid);\r
- if( FAILED( r ) )\r
- return r;\r
+ /* FIXME: There's room to save a CLSID and its ProgID, but\r
+ the CLSID is not looked up in the registry and in all the\r
+ tests I wrote it was CLSID_NULL. Where does it come from?\r
+ */\r
\r
- TRACE("CLSID is %s\n",debugstr_guid(&clsid));\r
-\r
- /* get the real program ID */\r
- r = ProgIDFromCLSID( &clsid, &wstrProgID);\r
- if( FAILED( r ) )\r
- return r;\r
+ /* get the real program ID. This may fail, but that's fine */\r
+ ProgIDFromCLSID(&clsid, &wstrProgID);\r
\r
TRACE("progid is %s\n",debugstr_w(wstrProgID));\r
\r
- /* if we have a good string, write the stream */\r
- if( wstrProgID )\r
- r = STORAGE_WriteCompObj( pstg, &clsid, \r
- lpszUserType, szwClipName, wstrProgID );\r
- else\r
- r = E_OUTOFMEMORY;\r
+ r = STORAGE_WriteCompObj( pstg, &clsid, \r
+ lpszUserType, szwClipName, wstrProgID );\r
\r
- IMalloc_Free( allocator, wstrProgID);\r
+ CoTaskMemFree(wstrProgID);\r
\r
return r;\r
}\r
IStream_Read(pStream, &(pOleStreamData->dwDataLength), sizeof(pOleStreamData->dwDataLength), NULL);\r
if(pOleStreamData->dwDataLength > 0)\r
{\r
- pOleStreamData->pData = (LPSTR) HeapAlloc(GetProcessHeap(),0,pOleStreamData->dwDataLength);\r
+ pOleStreamData->pData = HeapAlloc(GetProcessHeap(),0,pOleStreamData->dwDataLength);\r
IStream_Read(pStream, pOleStreamData->pData, pOleStreamData->dwDataLength, NULL);\r
}\r
IStream_Release(pStream);\r
MetaFilePict.hMF = 0;\r
\r
/* Get Metafile Data */\r
- pOleStreamData[1].pData = (BYTE *) HeapAlloc(GetProcessHeap(),0,pOleStreamData[1].dwDataLength);\r
+ pOleStreamData[1].pData = HeapAlloc(GetProcessHeap(),0,pOleStreamData[1].dwDataLength);\r
memcpy(pOleStreamData[1].pData, &MetaFilePict, sizeof(MetaFilePict));\r
IStream_Read(pStream, &(pOleStreamData[1].pData[sizeof(MetaFilePict)]), pOleStreamData[1].dwDataLength-sizeof(METAFILEPICT16), NULL);\r
}\r
};\r
\r
\r
-/*\r
- * Prototypes for the methods of the Storage32BaseImpl class.\r
- */\r
-HRESULT WINAPI StorageBaseImpl_QueryInterface(\r
- IStorage* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-\r
-ULONG WINAPI StorageBaseImpl_AddRef(\r
- IStorage* iface);\r
-\r
-ULONG WINAPI StorageBaseImpl_Release(\r
- IStorage* iface);\r
-\r
-HRESULT WINAPI StorageBaseImpl_OpenStream(\r
- IStorage* iface,\r
- const OLECHAR* pwcsName, /* [string][in] */\r
- void* reserved1, /* [unique][in] */\r
- DWORD grfMode, /* [in] */\r
- DWORD reserved2, /* [in] */\r
- IStream** ppstm); /* [out] */\r
-\r
-HRESULT WINAPI StorageBaseImpl_OpenStorage(\r
- IStorage* iface,\r
- const OLECHAR* pwcsName, /* [string][unique][in] */\r
- IStorage* pstgPriority, /* [unique][in] */\r
- DWORD grfMode, /* [in] */\r
- SNB snbExclude, /* [unique][in] */\r
- DWORD reserved, /* [in] */\r
- IStorage** ppstg); /* [out] */\r
-\r
-HRESULT WINAPI StorageBaseImpl_EnumElements(\r
- IStorage* iface,\r
- DWORD reserved1, /* [in] */\r
- void* reserved2, /* [size_is][unique][in] */\r
- DWORD reserved3, /* [in] */\r
- IEnumSTATSTG** ppenum); /* [out] */\r
-\r
-HRESULT WINAPI StorageBaseImpl_Stat(\r
- IStorage* iface,\r
- STATSTG* pstatstg, /* [out] */\r
- DWORD grfStatFlag); /* [in] */\r
-\r
-HRESULT WINAPI StorageBaseImpl_RenameElement(\r
- IStorage* iface,\r
- const OLECHAR* pwcsOldName, /* [string][in] */\r
- const OLECHAR* pwcsNewName); /* [string][in] */\r
-\r
-HRESULT WINAPI StorageBaseImpl_CreateStream(\r
- IStorage* iface,\r
- const OLECHAR* pwcsName, /* [string][in] */\r
- DWORD grfMode, /* [in] */\r
- DWORD reserved1, /* [in] */\r
- DWORD reserved2, /* [in] */\r
- IStream** ppstm); /* [out] */\r
-\r
-HRESULT WINAPI StorageBaseImpl_SetClass(\r
- IStorage* iface,\r
- REFCLSID clsid); /* [in] */\r
-\r
/****************************************************************************\r
* Storage32Impl definitions.\r
*\r
BigBlockFile* bigBlockFile;\r
};\r
\r
-/*\r
- * Method declaration for the Storage32Impl class\r
- */\r
-\r
-HRESULT WINAPI StorageImpl_CreateStorage(\r
- IStorage* iface,\r
- const OLECHAR* pwcsName, /* [string][in] */\r
- DWORD grfMode, /* [in] */\r
- DWORD dwStgFmt, /* [in] */\r
- DWORD reserved2, /* [in] */\r
- IStorage** ppstg); /* [out] */\r
-\r
-HRESULT WINAPI StorageImpl_CopyTo(\r
- IStorage* iface,\r
- DWORD ciidExclude, /* [in] */\r
- const IID* rgiidExclude, /* [size_is][unique][in] */\r
- SNB snbExclude, /* [unique][in] */\r
- IStorage* pstgDest); /* [unique][in] */\r
-\r
-HRESULT WINAPI StorageImpl_MoveElementTo(\r
- IStorage* iface,\r
- const OLECHAR* pwcsName, /* [string][in] */\r
- IStorage* pstgDest, /* [unique][in] */\r
- const OLECHAR* pwcsNewName, /* [string][in] */\r
- DWORD grfFlags); /* [in] */\r
-\r
-HRESULT WINAPI StorageImpl_Commit(\r
- IStorage* iface,\r
- DWORD grfCommitFlags); /* [in] */\r
-\r
-HRESULT WINAPI StorageImpl_Revert(\r
- IStorage* iface);\r
-\r
-HRESULT WINAPI StorageImpl_DestroyElement(\r
- IStorage* iface,\r
- const OLECHAR* pwcsName); /* [string][in] */\r
-\r
-HRESULT WINAPI StorageImpl_SetElementTimes(\r
- IStorage* iface,\r
- const OLECHAR* pwcsName, /* [string][in] */\r
- const FILETIME* pctime, /* [in] */\r
- const FILETIME* patime, /* [in] */\r
- const FILETIME* pmtime); /* [in] */\r
-\r
-HRESULT WINAPI StorageImpl_SetStateBits(\r
- IStorage* iface,\r
- DWORD grfStateBits, /* [in] */\r
- DWORD grfMask); /* [in] */\r
-\r
-HRESULT WINAPI StorageImpl_Stat(IStorage* iface,\r
- STATSTG* pstatstg, /* [out] */\r
- DWORD grfStatFlag); /* [in] */\r
-\r
void StorageImpl_Destroy(\r
StorageBaseImpl* This);\r
\r
struct IEnumSTATSTGImpl\r
{\r
IEnumSTATSTGVtbl *lpVtbl; /* Needs to be the first item in the struct\r
- * since we want to cast this in a IEnumSTATSTG pointer */\r
+ * since we want to cast this in an IEnumSTATSTG pointer */\r
\r
ULONG ref; /* Reference count */\r
StorageImpl* parentStorage; /* Reference to the parent storage */\r
#define ENUMSTATSGT_SIZE_INCREMENT 10\r
};\r
\r
-/*\r
- * Method definitions for the IEnumSTATSTGImpl class.\r
- */\r
-HRESULT WINAPI IEnumSTATSTGImpl_QueryInterface(\r
- IEnumSTATSTG* iface,\r
- REFIID riid,\r
- void** ppvObject);\r
-\r
-ULONG WINAPI IEnumSTATSTGImpl_AddRef(\r
- IEnumSTATSTG* iface);\r
-\r
-ULONG WINAPI IEnumSTATSTGImpl_Release(\r
- IEnumSTATSTG* iface);\r
-\r
-HRESULT WINAPI IEnumSTATSTGImpl_Next(\r
- IEnumSTATSTG* iface,\r
- ULONG celt,\r
- STATSTG* rgelt,\r
- ULONG* pceltFetched);\r
-\r
-HRESULT WINAPI IEnumSTATSTGImpl_Skip(\r
- IEnumSTATSTG* iface,\r
- ULONG celt);\r
-\r
-HRESULT WINAPI IEnumSTATSTGImpl_Reset(\r
- IEnumSTATSTG* iface);\r
-\r
-HRESULT WINAPI IEnumSTATSTGImpl_Clone(\r
- IEnumSTATSTG* iface,\r
- IEnumSTATSTG** ppenum);\r
-\r
IEnumSTATSTGImpl* IEnumSTATSTGImpl_Construct(\r
StorageImpl* This,\r
ULONG firstPropertyNode);\r
struct StgStreamImpl\r
{\r
IStreamVtbl *lpVtbl; /* Needs to be the first item in the struct\r
- * since we want to cast this in a IStream pointer */\r
+ * since we want to cast this to an IStream pointer */\r
\r
/*\r
* Reference count\r
DWORD grfMode,\r
ULONG ownerProperty);\r
\r
-void StgStreamImpl_Destroy(\r
- StgStreamImpl* This);\r
-\r
-void StgStreamImpl_OpenBlockChain(\r
- StgStreamImpl* This);\r
-\r
-HRESULT WINAPI StgStreamImpl_QueryInterface(\r
- IStream* iface,\r
- REFIID riid, /* [in] */\r
- void** ppvObject); /* [iid_is][out] */\r
-\r
-ULONG WINAPI StgStreamImpl_AddRef(\r
- IStream* iface);\r
-\r
-ULONG WINAPI StgStreamImpl_Release(\r
- IStream* iface);\r
-\r
-HRESULT WINAPI StgStreamImpl_Read(\r
- IStream* iface,\r
- void* pv, /* [length_is][size_is][out] */\r
- ULONG cb, /* [in] */\r
- ULONG* pcbRead); /* [out] */\r
-\r
-HRESULT WINAPI StgStreamImpl_Write(\r
- IStream* iface,\r
- const void* pv, /* [size_is][in] */\r
- ULONG cb, /* [in] */\r
- ULONG* pcbWritten); /* [out] */\r
-\r
-HRESULT WINAPI StgStreamImpl_Seek(\r
- IStream* iface,\r
- LARGE_INTEGER dlibMove, /* [in] */\r
- DWORD dwOrigin, /* [in] */\r
- ULARGE_INTEGER* plibNewPosition); /* [out] */\r
-\r
-HRESULT WINAPI StgStreamImpl_SetSize(\r
- IStream* iface,\r
- ULARGE_INTEGER libNewSize); /* [in] */\r
-\r
-HRESULT WINAPI StgStreamImpl_CopyTo(\r
- IStream* iface,\r
- IStream* pstm, /* [unique][in] */\r
- ULARGE_INTEGER cb, /* [in] */\r
- ULARGE_INTEGER* pcbRead, /* [out] */\r
- ULARGE_INTEGER* pcbWritten); /* [out] */\r
-\r
-HRESULT WINAPI StgStreamImpl_Commit(\r
- IStream* iface,\r
- DWORD grfCommitFlags); /* [in] */\r
-\r
-HRESULT WINAPI StgStreamImpl_Revert(\r
- IStream* iface);\r
-\r
-HRESULT WINAPI StgStreamImpl_LockRegion(\r
- IStream* iface,\r
- ULARGE_INTEGER libOffset, /* [in] */\r
- ULARGE_INTEGER cb, /* [in] */\r
- DWORD dwLockType); /* [in] */\r
-\r
-HRESULT WINAPI StgStreamImpl_UnlockRegion(\r
- IStream* iface,\r
- ULARGE_INTEGER libOffset, /* [in] */\r
- ULARGE_INTEGER cb, /* [in] */\r
- DWORD dwLockType); /* [in] */\r
-\r
-HRESULT WINAPI StgStreamImpl_Stat(\r
- IStream* iface,\r
- STATSTG* pstatstg, /* [out] */\r
- DWORD grfStatFlag); /* [in] */\r
-\r
-HRESULT WINAPI StgStreamImpl_Clone(\r
- IStream* iface,\r
- IStream** ppstm); /* [out] */\r
-\r
\r
/********************************************************************************\r
* The StorageUtl_ functions are miscelaneous utility functions. Most of which are\r
* abstractions used to read values from file buffers without having to worry\r
* about bit order\r
*/\r
-void StorageUtl_ReadWord(void* buffer, ULONG offset, WORD* value);\r
-void StorageUtl_WriteWord(void* buffer, ULONG offset, WORD value);\r
-void StorageUtl_ReadDWord(void* buffer, ULONG offset, DWORD* value);\r
-void StorageUtl_WriteDWord(void* buffer, ULONG offset, DWORD value);\r
-void StorageUtl_ReadGUID(void* buffer, ULONG offset, GUID* value);\r
-void StorageUtl_WriteGUID(void* buffer, ULONG offset, GUID* value);\r
+void StorageUtl_ReadWord(const BYTE* buffer, ULONG offset, WORD* value);\r
+void StorageUtl_WriteWord(BYTE* buffer, ULONG offset, WORD value);\r
+void StorageUtl_ReadDWord(const BYTE* buffer, ULONG offset, DWORD* value);\r
+void StorageUtl_WriteDWord(BYTE* buffer, ULONG offset, DWORD value);\r
+void StorageUtl_ReadGUID(const BYTE* buffer, ULONG offset, GUID* value);\r
+void StorageUtl_WriteGUID(BYTE* buffer, ULONG offset, const GUID* value);\r
void StorageUtl_CopyPropertyToSTATSTG(STATSTG* destination,\r
StgProperty* source,\r
int statFlags);\r
if (!sm) return NULL;\r
\r
list_init(&sm->ifstubs);\r
+\r
InitializeCriticalSection(&sm->lock);\r
+ DEBUG_SET_CRITSEC_NAME(&sm->lock, "stub_manager");\r
+\r
IUnknown_AddRef(object);\r
sm->object = object;\r
sm->apt = apt;\r
\r
IUnknown_Release(m->object);\r
\r
+ DEBUG_CLEAR_CRITSEC_NAME(&m->lock);\r
DeleteCriticalSection(&m->lock);\r
\r
HeapFree(GetProcessHeap(), 0, m);\r
\r
/* removes the apartment reference to an object, destroying it when no other\r
* threads have a reference to it */\r
-void apartment_disconnect_object(APARTMENT *apt, void *object)\r
+void apartment_disconnectobject(struct apartment *apt, void *object)\r
{\r
int found = FALSE;\r
struct stub_manager *stubmgr;\r
{\r
/* FIXME: hack for IRemUnknown */\r
if (ipid->Data2 == 0xffff)\r
- *stub_apt = COM_ApartmentFromOXID(*(OXID *)ipid->Data4, TRUE);\r
+ *stub_apt = apartment_findfromoxid(*(OXID *)ipid->Data4, TRUE);\r
else\r
- *stub_apt = COM_ApartmentFromTID(ipid->Data2);\r
+ *stub_apt = apartment_findfromtid(ipid->Data2);\r
if (!*stub_apt)\r
{\r
ERR("Couldn't find apartment corresponding to TID 0x%04x\n", ipid->Data2);\r
*stubmgr_ret = get_stub_manager_from_ipid(*stub_apt, ipid);\r
if (!*stubmgr_ret)\r
{\r
- COM_ApartmentRelease(*stub_apt);\r
+ apartment_release(*stub_apt);\r
*stub_apt = NULL;\r
return RPC_E_INVALID_OBJECT;\r
}\r
\r
for (i = 0; i < cIids; i++)\r
{\r
- HRESULT hrobj = register_ifstub(apt, &(*ppQIResults)[i].std, &iids[i],\r
- stubmgr->object, MSHLFLAGS_NORMAL);\r
+ HRESULT hrobj = marshal_object(apt, &(*ppQIResults)[i].std, &iids[i],\r
+ stubmgr->object, MSHLFLAGS_NORMAL);\r
if (hrobj == S_OK)\r
successful_qis++;\r
(*ppQIResults)[i].hResult = hrobj;\r
}\r
\r
stub_manager_int_release(stubmgr);\r
- COM_ApartmentRelease(apt);\r
+ apartment_release(apt);\r
\r
if (successful_qis == cIids)\r
return S_OK; /* we got all requested interfaces */\r
FIXME("Adding %ld refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);\r
\r
stub_manager_int_release(stubmgr);\r
- COM_ApartmentRelease(apt);\r
+ apartment_release(apt);\r
}\r
\r
return hr;\r
FIXME("Releasing %ld refs securely not implemented\n", InterfaceRefs[i].cPrivateRefs);\r
\r
stub_manager_int_release(stubmgr);\r
- COM_ApartmentRelease(apt);\r
+ apartment_release(apt);\r
}\r
\r
return hr;\r
{\r
STDOBJREF stdobjref; /* dummy - not used */\r
/* register it with the stub manager */\r
- hr = register_ifstub(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHLFLAGS_NORMAL);\r
+ hr = marshal_object(apt, &stdobjref, &IID_IRemUnknown, (IUnknown *)pRemUnknown, MSHLFLAGS_NORMAL);\r
/* release our reference to the object as the stub manager will manage the life cycle for us */\r
IRemUnknown_Release(pRemUnknown);\r
if (hr == S_OK)\r
COINIT_DISABLE_OLE1DDE = 0x4,
COINIT_SPEED_OVER_MEMORY = 0x8
} COINIT;
+typedef enum tagCOWAIT_FLAGS
+{
+ COWAIT_WAITALL = 0x01,
+ COWAIT_ALERTABLE = 0x02
+} COWAIT_FLAGS;
typedef enum tagSTDMSHLFLAGS {
SMEXF_SERVER = 0x01,
SMEXF_HANDLER = 0x02
WINOLEAPI CoSuspendClassObjects(void);
WINOLEAPI CoGetPSClsid(REFIID,CLSID*);
WINOLEAPI CoRegisterPSClsid(REFIID,REFCLSID);
+WINOLEAPI CoWaitForMultipleHandles(DWORD dwFlags,DWORD dwTimeout,ULONG cHandles,const HANDLE* pHandles,LPDWORD lpdwindex);
#pragma pack(pop)
#endif
FILETIME mtime;
FILETIME ctime;
FILETIME atime;
+ DWORD dwOSVersion;
} STATPROPSETSTG;
typedef enum tagEXTCONN {
EXTCONN_STRONG=1,
STDMETHOD(ReadPropertyNames)(THIS_ ULONG,PROPID const*,LPWSTR*) PURE;
STDMETHOD(WritePropertyNames)(THIS_ ULONG,PROPID const*,LPWSTR const*) PURE;
STDMETHOD(DeletePropertyNames)(THIS_ ULONG,PROPID const*) PURE;
- STDMETHOD(SetClass)(THIS_ REFCLSID) PURE;
STDMETHOD(Commit)(THIS_ DWORD) PURE;
STDMETHOD(Revert)(THIS) PURE;
STDMETHOD(Enum)(THIS_ IEnumSTATPROPSTG**) PURE;
- STDMETHOD(Stat)(THIS_ STATPROPSTG*) PURE;
STDMETHOD(SetTimes)(THIS_ FILETIME const*,FILETIME const*,FILETIME const*) PURE;
+ STDMETHOD(SetClass)(THIS_ REFCLSID) PURE;
+ STDMETHOD(Stat)(THIS_ STATPROPSETSTG*) PURE;
};
#undef INTERFACE
#include <objidl.h>
+#define PRSPEC_LPWSTR (0)
+#define PRSPEC_PROPID (1)
+
+#define PID_DICTIONARY 0x00000000
+#define PID_CODEPAGE 0x00000001
+#define PID_FIRST_USABLE 0x00000002
+#define PID_FIRST_NAME_DEFAULT 0x00000fff
+#define PID_LOCALE 0x80000000
+#define PID_MODIFY_TIME 0x80000001
+#define PID_SECURITY 0x80000002
+#define PID_BEHAVIOR 0x80000003
+#define PID_ILLEGAL 0xffffffff
+#define PID_MIN_READONLY 0x80000000
+#define PID_MAX_READONLY 0xbfffffff
+
+#define PROPSETFLAG_DEFAULT 0
+#define PROPSETFLAG_NONSIMPLE 1
+#define PROPSETFLAG_ANSI 2
+#define PROPSETFLAG_UNBUFFERED 4
+#define PROPSETFLAG_CASE_SENSITIVE 8
+
+#define CCH_MAX_PROPSTG_NAME 31
+
+/* Macros for dwOSVersion member of STATPROPSETSTG */
+#define PROPSETHDR_OSVER_KIND(dwOSVer) HIWORD((dwOSVer))
+#define PROPSETHDR_OSVER_MAJOR(dwOSVer) LOBYTE(LOWORD((dwOSVer)))
+#define PROPSETHDR_OSVER_MINOR(dwOSVer) HIBYTE(LOWORD((dwOSVer)))
+#define PROPSETHDR_OSVERSION_UNKNOWN 0xffffffff
+
HRESULT WINAPI FreePropVariantArray(ULONG cVariants, PROPVARIANT *rgvars);
+HRESULT WINAPI PropVariantClear(PROPVARIANT*);
+HRESULT WINAPI PropVariantCopy(PROPVARIANT*,const PROPVARIANT*);
+
+#define _PROPVARIANT_INIT_DEFINED_
+#define PropVariantInit(p) memset((p), 0, sizeof(PROPVARIANT))
+
+HRESULT WINAPI FmtIdToPropStgName(const FMTID *, LPOLESTR);
#endif
#define RPC_E_WRONG_THREAD ((HRESULT)0x8001010EL)
#define RPC_E_THREAD_NOT_INIT ((HRESULT)0x8001010FL)
#define RPC_E_INVALID_OBJECT ((HRESULT)0x80010114L)
+#define RPC_S_CALLPENDING ((HRESULT)0x80010115L)
#define RPC_E_INVALID_OBJREF ((HRESULT)0x8001011DL)
#define RPC_E_UNEXPECTED ((HRESULT)0x8001FFFFL)