[PATCH 2/2] ole32/composite: Store components as a pair of top level monikers.
Nikolay Sivov
nsivov at codeweavers.com
Tue Sep 21 07:05:08 CDT 2021
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
Storing left,right pair makes it easy to implement hierarchical marshalling
and comparison data correctly - composite marshaling is always concerned
about two monikers, that would recursively be marshaled down to non-composite
types. It also makes it possible to have better initial simplification results
that preserve original moniker structure after applying all non-generic compositions.
dlls/ole32/compositemoniker.c | 966 +++++++++++++++++-----------------
dlls/ole32/tests/moniker.c | 48 +-
2 files changed, 517 insertions(+), 497 deletions(-)
diff --git a/dlls/ole32/compositemoniker.c b/dlls/ole32/compositemoniker.c
index 38a2e2a4892..7abbd51090f 100644
--- a/dlls/ole32/compositemoniker.c
+++ b/dlls/ole32/compositemoniker.c
@@ -28,23 +28,24 @@
#include "winbase.h"
#include "winuser.h"
#include "winerror.h"
-#include "wine/debug.h"
#include "ole2.h"
#include "moniker.h"
-WINE_DEFAULT_DEBUG_CHANNEL(ole);
+#include "wine/debug.h"
+#include "wine/heap.h"
-#define BLOCK_TAB_SIZE 5 /* represent the first size table and its increment block size */
+WINE_DEFAULT_DEBUG_CHANNEL(ole);
-/* CompositeMoniker data structure */
-typedef struct CompositeMonikerImpl{
+typedef struct CompositeMonikerImpl
+{
IMoniker IMoniker_iface;
IROTData IROTData_iface;
IMarshal IMarshal_iface;
LONG ref;
- IMoniker** tabMoniker; /* dynamic table containing all components (monikers) of this composite moniker */
- ULONG tabSize; /* size of tabMoniker */
- ULONG tabLastIndex; /* first free index in tabMoniker */
+
+ IMoniker *left;
+ IMoniker *right;
+ unsigned int comp_count;
} CompositeMonikerImpl;
static inline CompositeMonikerImpl *impl_from_IMoniker(IMoniker *iface)
@@ -52,6 +53,15 @@ static inline CompositeMonikerImpl *impl_from_IMoniker(IMoniker *iface)
return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMoniker_iface);
}
+static const IMonikerVtbl VT_CompositeMonikerImpl;
+
+static CompositeMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface)
+{
+ if (iface->lpVtbl != &VT_CompositeMonikerImpl)
+ return NULL;
+ return CONTAINING_RECORD(iface, CompositeMonikerImpl, IMoniker_iface);
+}
+
static inline CompositeMonikerImpl *impl_from_IROTData(IROTData *iface)
{
return CONTAINING_RECORD(iface, CompositeMonikerImpl, IROTData_iface);
@@ -130,39 +140,21 @@ CompositeMonikerImpl_AddRef(IMoniker* iface)
return InterlockedIncrement(&This->ref);
}
-static void CompositeMonikerImpl_ReleaseMonikersInTable(CompositeMonikerImpl *This)
+static ULONG WINAPI CompositeMonikerImpl_Release(IMoniker* iface)
{
- ULONG i;
-
- for (i = 0; i < This->tabLastIndex; i++)
- IMoniker_Release(This->tabMoniker[i]);
-
- This->tabLastIndex = 0;
-}
-
-/******************************************************************************
- * CompositeMoniker_Release
- ******************************************************************************/
-static ULONG WINAPI
-CompositeMonikerImpl_Release(IMoniker* iface)
-{
- CompositeMonikerImpl *This = impl_from_IMoniker(iface);
- ULONG ref;
+ CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
+ ULONG refcount = InterlockedDecrement(&moniker->ref);
- TRACE("(%p)\n",This);
-
- ref = InterlockedDecrement(&This->ref);
-
- /* destroy the object if there are no more references to it */
- if (ref == 0){
-
- /* release all the components before destroying this object */
- CompositeMonikerImpl_ReleaseMonikersInTable(This);
+ TRACE("%p, refcount %u\n", iface, refcount);
- HeapFree(GetProcessHeap(),0,This->tabMoniker);
- HeapFree(GetProcessHeap(),0,This);
+ if (!refcount)
+ {
+ if (moniker->left) IMoniker_Release(moniker->left);
+ if (moniker->right) IMoniker_Release(moniker->right);
+ heap_free(moniker);
}
- return ref;
+
+ return refcount;
}
/******************************************************************************
@@ -196,94 +188,92 @@ CompositeMonikerImpl_IsDirty(IMoniker* iface)
return S_FALSE;
}
-/******************************************************************************
- * CompositeMoniker_Load
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_Load(IMoniker* iface,IStream* pStm)
+static HRESULT WINAPI CompositeMonikerImpl_Load(IMoniker *iface, IStream *stream)
{
- CompositeMonikerImpl *This = impl_from_IMoniker(iface);
- HRESULT res;
- DWORD moniker_count;
- DWORD i;
+ CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
+ IMoniker *last, *m, *c;
+ DWORD i, count;
+ HRESULT hr;
- TRACE("(%p,%p)\n",iface,pStm);
+ TRACE("%p, %p\n", iface, stream);
- /* this function call OleLoadFromStream function for each moniker within this object */
+ if (moniker->comp_count)
+ return E_UNEXPECTED;
- res=IStream_Read(pStm,&moniker_count,sizeof(DWORD),NULL);
- if (res != S_OK)
+ hr = IStream_Read(stream, &count, sizeof(DWORD), NULL);
+ if (hr != S_OK)
{
- ERR("couldn't reading moniker count from stream\n");
- return E_FAIL;
+ WARN("Failed to read component count, hr %#x.\n", hr);
+ return hr;
}
- CompositeMonikerImpl_ReleaseMonikersInTable(This);
+ if (count < 2)
+ {
+ WARN("Unexpected component count %u.\n", count);
+ return E_UNEXPECTED;
+ }
+
+ if (FAILED(hr = OleLoadFromStream(stream, &IID_IMoniker, (void **)&last)))
+ return hr;
- for (i = 0; i < moniker_count; i++)
+ for (i = 1; i < count - 1; ++i)
{
- res=OleLoadFromStream(pStm,&IID_IMoniker,(void**)&This->tabMoniker[This->tabLastIndex]);
- if (FAILED(res))
+ if (FAILED(hr = OleLoadFromStream(stream, &IID_IMoniker, (void **)&m)))
{
- ERR("couldn't load moniker from stream, res = 0x%08x\n", res);
- break;
+ WARN("Failed to initialize component %u, hr %#x.\n", i, hr);
+ IMoniker_Release(last);
+ return hr;
}
+ hr = CreateGenericComposite(last, m, &c);
+ IMoniker_Release(last);
+ IMoniker_Release(m);
+ if (FAILED(hr)) return hr;
+ last = c;
+ }
- /* resize the table if needed */
- if (++This->tabLastIndex==This->tabSize){
-
- This->tabSize+=BLOCK_TAB_SIZE;
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0]));
-
- if (This->tabMoniker==NULL)
- return E_OUTOFMEMORY;
- }
+ if (FAILED(hr = OleLoadFromStream(stream, &IID_IMoniker, (void **)&m)))
+ {
+ IMoniker_Release(last);
+ return hr;
}
- return res;
+ moniker->left = last;
+ moniker->right = m;
+ moniker->comp_count = count;
+
+ return hr;
}
-/******************************************************************************
- * CompositeMoniker_Save
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_Save(IMoniker* iface,IStream* pStm,BOOL fClearDirty)
+static HRESULT composite_save_components(IMoniker *moniker, IStream *stream)
{
- CompositeMonikerImpl *This = impl_from_IMoniker(iface);
- HRESULT res;
- IEnumMoniker *enumMk;
- IMoniker *pmk;
- DWORD moniker_count = This->tabLastIndex;
-
- TRACE("(%p,%p,%d)\n",iface,pStm,fClearDirty);
-
- /* This function calls OleSaveToStream function for each moniker within
- * this object.
- * When I tested this function in windows, I usually found this constant
- * at the beginning of the stream. I don't known why (there's no
- * indication in the specification) !
- */
- res=IStream_Write(pStm,&moniker_count,sizeof(moniker_count),NULL);
- if (FAILED(res)) return res;
-
- IMoniker_Enum(iface,TRUE,&enumMk);
+ CompositeMonikerImpl *comp_moniker;
+ HRESULT hr;
- while(IEnumMoniker_Next(enumMk,1,&pmk,NULL)==S_OK){
+ if ((comp_moniker = unsafe_impl_from_IMoniker(moniker)))
+ {
+ if (SUCCEEDED(hr = composite_save_components(comp_moniker->left, stream)))
+ hr = composite_save_components(comp_moniker->right, stream);
+ }
+ else
+ hr = OleSaveToStream((IPersistStream *)moniker, stream);
- res=OleSaveToStream((IPersistStream*)pmk,pStm);
+ return hr;
+}
- IMoniker_Release(pmk);
+static HRESULT WINAPI CompositeMonikerImpl_Save(IMoniker *iface, IStream *stream, BOOL clear_dirty)
+{
+ CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
+ HRESULT hr;
- if (FAILED(res)){
+ TRACE("%p, %p, %d\n", iface, stream, clear_dirty);
- IEnumMoniker_Release(enumMk);
- return res;
- }
- }
+ if (!moniker->comp_count)
+ return E_UNEXPECTED;
- IEnumMoniker_Release(enumMk);
+ hr = IStream_Write(stream, &moniker->comp_count, sizeof(moniker->comp_count), NULL);
+ if (FAILED(hr)) return hr;
- return S_OK;
+ return composite_save_components(iface, stream);
}
/******************************************************************************
@@ -517,20 +507,44 @@ CompositeMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
return CreateGenericComposite(iface,pmkRight,ppmkComposite);
}
-/******************************************************************************
- * CompositeMoniker_Enum
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
+static void composite_get_components(IMoniker *moniker, IMoniker **components, unsigned int *index)
{
- CompositeMonikerImpl *This = impl_from_IMoniker(iface);
+ CompositeMonikerImpl *comp_moniker;
- TRACE("(%p,%d,%p)\n",iface,fForward,ppenumMoniker);
+ if ((comp_moniker = unsafe_impl_from_IMoniker(moniker)))
+ {
+ composite_get_components(comp_moniker->left, components, index);
+ composite_get_components(comp_moniker->right, components, index);
+ }
+ else
+ {
+ components[*index] = moniker;
+ (*index)++;
+ }
+}
- if (ppenumMoniker == NULL)
+static HRESULT WINAPI CompositeMonikerImpl_Enum(IMoniker *iface, BOOL forward, IEnumMoniker **ppenumMoniker)
+{
+ CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
+ IMoniker **monikers;
+ unsigned int index;
+ HRESULT hr;
+
+ TRACE("%p, %d, %p\n", iface, forward, ppenumMoniker);
+
+ if (!ppenumMoniker)
return E_POINTER;
- return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabLastIndex,0,fForward,ppenumMoniker);
+ if (!(monikers = heap_alloc(moniker->comp_count * sizeof(*monikers))))
+ return E_OUTOFMEMORY;
+
+ index = 0;
+ composite_get_components(iface, monikers, &index);
+
+ hr = EnumMonikerImpl_CreateEnumMoniker(monikers, moniker->comp_count, 0, forward, ppenumMoniker);
+ heap_free(monikers);
+
+ return hr;
}
/******************************************************************************
@@ -584,40 +598,29 @@ CompositeMonikerImpl_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
return res;
}
-/******************************************************************************
- * CompositeMoniker_Hash
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_Hash(IMoniker* iface,DWORD* pdwHash)
+
+static HRESULT WINAPI CompositeMonikerImpl_Hash(IMoniker *iface, DWORD *hash)
{
- IEnumMoniker *enumMoniker;
- IMoniker *tempMk;
- HRESULT res;
- DWORD tempHash;
+ CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
+ DWORD left_hash, right_hash;
+ HRESULT hr;
- TRACE("(%p,%p)\n",iface,pdwHash);
+ TRACE("%p, %p\n", iface, hash);
- if (pdwHash==NULL)
+ if (!hash)
return E_POINTER;
- res = IMoniker_Enum(iface,TRUE,&enumMoniker);
- if(FAILED(res))
- return res;
+ if (!moniker->comp_count)
+ return E_UNEXPECTED;
- *pdwHash = 0;
+ *hash = 0;
- while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
- res = IMoniker_Hash(tempMk, &tempHash);
- if(FAILED(res))
- break;
- *pdwHash = *pdwHash ^ tempHash;
-
- IMoniker_Release(tempMk);
- }
+ if (FAILED(hr = IMoniker_Hash(moniker->left, &left_hash))) return hr;
+ if (FAILED(hr = IMoniker_Hash(moniker->right, &right_hash))) return hr;
- IEnumMoniker_Release(enumMoniker);
+ *hash = left_hash ^ right_hash;
- return res;
+ return hr;
}
/******************************************************************************
@@ -1096,53 +1099,35 @@ CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
return S_OK;
}
-/******************************************************************************
- * CompositeMoniker_GetDisplayName
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
- IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
+static HRESULT WINAPI CompositeMonikerImpl_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
+ IMoniker *pmkToLeft, LPOLESTR *displayname)
{
- ULONG lengthStr=1;
- IEnumMoniker *enumMoniker;
- IMoniker* tempMk;
- LPOLESTR tempStr;
+ CompositeMonikerImpl *moniker = impl_from_IMoniker(iface);
+ WCHAR *left_name = NULL, *right_name = NULL;
- TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
+ TRACE("%p, %p, %p, %p\n", iface, pbc, pmkToLeft, displayname);
- if (ppszDisplayName==NULL)
+ if (!displayname)
return E_POINTER;
- *ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
-
- if (*ppszDisplayName==NULL)
- return E_OUTOFMEMORY;
-
- /* This method returns the concatenation of the display names returned by each component moniker of */
- /* the composite */
-
- **ppszDisplayName=0;
-
- IMoniker_Enum(iface,TRUE,&enumMoniker);
-
- while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
-
- IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
-
- lengthStr+=lstrlenW(tempStr);
-
- *ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
-
- if (*ppszDisplayName==NULL)
- return E_OUTOFMEMORY;
+ if (!moniker->comp_count)
+ return E_INVALIDARG;
- lstrcatW(*ppszDisplayName,tempStr);
+ IMoniker_GetDisplayName(moniker->left, pbc, NULL, &left_name);
+ IMoniker_GetDisplayName(moniker->right, pbc, NULL, &right_name);
- CoTaskMemFree(tempStr);
- IMoniker_Release(tempMk);
+ if (!(*displayname = CoTaskMemAlloc((lstrlenW(left_name) + lstrlenW(right_name) + 1) * sizeof(WCHAR))))
+ {
+ CoTaskMemFree(left_name);
+ CoTaskMemFree(right_name);
+ return E_OUTOFMEMORY;
}
- IEnumMoniker_Release(enumMoniker);
+ lstrcpyW(*displayname, left_name);
+ lstrcatW(*displayname, right_name);
+
+ CoTaskMemFree(left_name);
+ CoTaskMemFree(right_name);
return S_OK;
}
@@ -1228,94 +1213,77 @@ static ULONG WINAPI CompositeMonikerROTDataImpl_Release(IROTData* iface)
return IMoniker_Release(&This->IMoniker_iface);
}
-/******************************************************************************
- * CompositeMonikerIROTData_GetComparisonData
- ******************************************************************************/
-static HRESULT WINAPI
-CompositeMonikerROTDataImpl_GetComparisonData(IROTData* iface,
- BYTE* pbData, ULONG cbMax, ULONG* pcbData)
+static HRESULT composite_get_moniker_comparison_data(IMoniker *moniker,
+ BYTE *data, ULONG max_len, ULONG *ret_len)
{
- CompositeMonikerImpl *This = impl_from_IROTData(iface);
- IEnumMoniker *pEnumMk;
- IMoniker *pmk;
+ IROTData *rot_data;
HRESULT hr;
- TRACE("(%p, %u, %p)\n", pbData, cbMax, pcbData);
-
- *pcbData = sizeof(CLSID);
-
- hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk);
- if (FAILED(hr)) return hr;
-
- while(IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
+ if (FAILED(hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rot_data)))
{
- IROTData *pROTData;
- hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
- if (FAILED(hr))
- ERR("moniker doesn't support IROTData interface\n");
+ WARN("Failed to get IROTData for component moniker, hr %#x.\n", hr);
+ return hr;
+ }
- if (SUCCEEDED(hr))
- {
- ULONG cbData;
- hr = IROTData_GetComparisonData(pROTData, NULL, 0, &cbData);
- IROTData_Release(pROTData);
- if (SUCCEEDED(hr) || (hr == E_OUTOFMEMORY))
- {
- *pcbData += cbData;
- hr = S_OK;
- }
- else
- ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
- }
+ hr = IROTData_GetComparisonData(rot_data, data, max_len, ret_len);
+ IROTData_Release(rot_data);
- IMoniker_Release(pmk);
+ return hr;
+}
- if (FAILED(hr))
- {
- IEnumMoniker_Release(pEnumMk);
- return hr;
- }
- }
- if (cbMax < *pcbData)
- return E_OUTOFMEMORY;
+static HRESULT WINAPI CompositeMonikerROTDataImpl_GetComparisonData(IROTData *iface,
+ BYTE *data, ULONG max_len, ULONG *ret_len)
+{
+ CompositeMonikerImpl *moniker = impl_from_IROTData(iface);
+ HRESULT hr;
+ ULONG len;
+
+ TRACE("%p, %p, %u, %p\n", iface, data, max_len, ret_len);
- IEnumMoniker_Reset(pEnumMk);
+ if (!moniker->comp_count)
+ return E_UNEXPECTED;
- memcpy(pbData, &CLSID_CompositeMoniker, sizeof(CLSID));
- pbData += sizeof(CLSID);
- cbMax -= sizeof(CLSID);
+ /* Get required size first */
+ *ret_len = sizeof(CLSID);
- while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
+ len = 0;
+ hr = composite_get_moniker_comparison_data(moniker->left, NULL, 0, &len);
+ if (SUCCEEDED(hr) || hr == E_OUTOFMEMORY)
+ *ret_len += len;
+ else
{
- IROTData *pROTData;
- hr = IMoniker_QueryInterface(pmk, &IID_IROTData, (void **)&pROTData);
- if (FAILED(hr))
- ERR("moniker doesn't support IROTData interface\n");
+ WARN("Failed to get comparison data length for left component, hr %#x.\n", hr);
+ return hr;
+ }
- if (SUCCEEDED(hr))
- {
- ULONG cbData;
- hr = IROTData_GetComparisonData(pROTData, pbData, cbMax, &cbData);
- IROTData_Release(pROTData);
- if (SUCCEEDED(hr))
- {
- pbData += cbData;
- cbMax -= cbData;
- }
- else
- ERR("IROTData_GetComparisonData failed with error 0x%08x\n", hr);
- }
+ len = 0;
+ hr = composite_get_moniker_comparison_data(moniker->right, NULL, 0, &len);
+ if (SUCCEEDED(hr) || hr == E_OUTOFMEMORY)
+ *ret_len += len;
+ else
+ {
+ WARN("Failed to get comparison data length for right component, hr %#x.\n", hr);
+ return hr;
+ }
- IMoniker_Release(pmk);
+ if (max_len < *ret_len)
+ return E_OUTOFMEMORY;
- if (FAILED(hr))
- {
- IEnumMoniker_Release(pEnumMk);
- return hr;
- }
+ memcpy(data, &CLSID_CompositeMoniker, sizeof(CLSID));
+ data += sizeof(CLSID);
+ max_len -= sizeof(CLSID);
+ if (FAILED(hr = composite_get_moniker_comparison_data(moniker->left, data, max_len, &len)))
+ {
+ WARN("Failed to get comparison data for left component, hr %#x.\n", hr);
+ return hr;
+ }
+ data += len;
+ max_len -= len;
+ if (FAILED(hr = composite_get_moniker_comparison_data(moniker->right, data, max_len, &len)))
+ {
+ WARN("Failed to get comparison data for right component, hr %#x.\n", hr);
+ return hr;
}
-
- IEnumMoniker_Release(pEnumMk);
return S_OK;
}
@@ -1363,118 +1331,91 @@ static HRESULT WINAPI CompositeMonikerMarshalImpl_GetMarshalSizeMax(
IMarshal *iface, REFIID riid, void *pv, DWORD dwDestContext,
void* pvDestContext, DWORD mshlflags, DWORD* pSize)
{
- CompositeMonikerImpl *This = impl_from_IMarshal(iface);
- IEnumMoniker *pEnumMk;
- IMoniker *pmk;
+ CompositeMonikerImpl *moniker = impl_from_IMarshal(iface);
HRESULT hr;
- ULARGE_INTEGER size;
+ ULONG size;
TRACE("(%s, %p, %x, %p, %x, %p)\n", debugstr_guid(riid), pv,
dwDestContext, pvDestContext, mshlflags, pSize);
- *pSize = 0x10; /* to match native */
-
- hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk);
- if (FAILED(hr)) return hr;
+ if (!moniker->comp_count)
+ return E_UNEXPECTED;
- hr = IMoniker_GetSizeMax(&This->IMoniker_iface, &size);
+ *pSize = 0x10; /* to match native */
- while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
+ if (FAILED(hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)moniker->left, dwDestContext,
+ pvDestContext, mshlflags)))
{
- ULONG size;
-
- hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
- if (SUCCEEDED(hr))
- *pSize += size;
-
- IMoniker_Release(pmk);
-
- if (FAILED(hr))
- {
- IEnumMoniker_Release(pEnumMk);
- return hr;
- }
+ return hr;
}
+ *pSize += size;
- IEnumMoniker_Release(pEnumMk);
+ if (FAILED(hr = CoGetMarshalSizeMax(&size, &IID_IMoniker, (IUnknown *)moniker->right, dwDestContext,
+ pvDestContext, mshlflags)))
+ {
+ return hr;
+ }
+ *pSize += size;
- return S_OK;
+ return hr;
}
-static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(IMarshal *iface, IStream *pStm,
- REFIID riid, void* pv, DWORD dwDestContext,
- void* pvDestContext, DWORD mshlflags)
+static HRESULT WINAPI CompositeMonikerMarshalImpl_MarshalInterface(IMarshal *iface, IStream *stream,
+ REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD flags)
{
- CompositeMonikerImpl *This = impl_from_IMarshal(iface);
- IEnumMoniker *pEnumMk;
- IMoniker *pmk;
+ CompositeMonikerImpl *moniker = impl_from_IMarshal(iface);
HRESULT hr;
- ULONG i = 0;
- TRACE("(%p, %s, %p, %x, %p, %x)\n", pStm, debugstr_guid(riid), pv,
- dwDestContext, pvDestContext, mshlflags);
+ TRACE("%p, %p, %s, %p, %x, %p, %#x\n", iface, stream, debugstr_guid(riid), pv, dwDestContext, pvDestContext, flags);
- hr = IMoniker_Enum(&This->IMoniker_iface, TRUE, &pEnumMk);
- if (FAILED(hr)) return hr;
+ if (!moniker->comp_count)
+ return E_UNEXPECTED;
- while (IEnumMoniker_Next(pEnumMk, 1, &pmk, NULL) == S_OK)
+ if (FAILED(hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker->left, dwDestContext, pvDestContext, flags)))
{
- hr = CoMarshalInterface(pStm, &IID_IMoniker, (IUnknown *)pmk, dwDestContext, pvDestContext, mshlflags);
-
- IMoniker_Release(pmk);
-
- if (FAILED(hr))
- {
- IEnumMoniker_Release(pEnumMk);
- return hr;
- }
- i++;
+ WARN("Failed to marshal left component, hr %#x.\n", hr);
+ return hr;
}
- if (i != 2)
- FIXME("moniker count of %d not supported\n", i);
-
- IEnumMoniker_Release(pEnumMk);
+ if (FAILED(hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker->right, dwDestContext, pvDestContext, flags)))
+ WARN("Failed to marshal right component, hr %#x.\n", hr);
- return S_OK;
+ return hr;
}
-static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *pStm,
- REFIID riid, void **ppv)
+static HRESULT WINAPI CompositeMonikerMarshalImpl_UnmarshalInterface(IMarshal *iface, IStream *stream,
+ REFIID riid, void **ppv)
{
- CompositeMonikerImpl *This = impl_from_IMarshal(iface);
+ CompositeMonikerImpl *moniker = impl_from_IMarshal(iface);
HRESULT hr;
- TRACE("(%p, %s, %p)\n", pStm, debugstr_guid(riid), ppv);
-
- CompositeMonikerImpl_ReleaseMonikersInTable(This);
+ TRACE("%p, %p, %s, %p\n", iface, stream, debugstr_guid(riid), ppv);
- /* resize the table if needed */
- if (This->tabLastIndex + 2 > This->tabSize)
+ if (moniker->left)
{
- This->tabSize += max(BLOCK_TAB_SIZE, 2);
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0]));
+ IMoniker_Release(moniker->left);
+ moniker->left = NULL;
+ }
- if (This->tabMoniker==NULL)
- return E_OUTOFMEMORY;
+ if (moniker->right)
+ {
+ IMoniker_Release(moniker->right);
+ moniker->right = NULL;
}
- hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
- if (FAILED(hr))
+ if (FAILED(hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker->left)))
{
- ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
+ WARN("Failed to unmarshal left moniker, hr %#x.\n", hr);
return hr;
}
- This->tabLastIndex++;
- hr = CoUnmarshalInterface(pStm, &IID_IMoniker, (void**)&This->tabMoniker[This->tabLastIndex]);
- if (FAILED(hr))
+
+ if (FAILED(hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker->right)))
{
- ERR("couldn't unmarshal moniker, hr = 0x%08x\n", hr);
+ WARN("Failed to unmarshal right moniker, hr %#x.\n", hr);
return hr;
}
- This->tabLastIndex++;
- return IMoniker_QueryInterface(&This->IMoniker_iface, riid, ppv);
+ return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv);
}
static HRESULT WINAPI CompositeMonikerMarshalImpl_ReleaseMarshalData(IMarshal *iface, IStream *pStm)
@@ -1630,8 +1571,6 @@ EnumMonikerImpl_Clone(IEnumMoniker* iface,IEnumMoniker** ppenum)
return EnumMonikerImpl_CreateEnumMoniker(This->tabMoniker,This->tabSize,This->currentPos,TRUE,ppenum);
}
-/********************************************************************************/
-/* Virtual function table for the IROTData class */
static const IEnumMonikerVtbl VT_EnumMonikerImpl =
{
EnumMonikerImpl_QueryInterface,
@@ -1747,196 +1686,256 @@ static const IMarshalVtbl VT_MarshalImpl =
CompositeMonikerMarshalImpl_DisconnectObject
};
-/******************************************************************************
- * Composite-Moniker_Construct (local function)
- *******************************************************************************/
-static HRESULT
-CompositeMonikerImpl_Construct(IMoniker **ppMoniker, IMoniker *pmkFirst, IMoniker *pmkRest)
+struct comp_node
{
- DWORD mkSys;
- IEnumMoniker *enumMoniker;
- IMoniker *tempMk;
- HRESULT res;
- CompositeMonikerImpl *This;
- int i;
+ IMoniker *moniker;
+ struct comp_node *parent;
+ struct comp_node *left;
+ struct comp_node *right;
+};
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
+static HRESULT moniker_get_tree_representation(IMoniker *moniker, struct comp_node *parent,
+ struct comp_node **ret)
+{
+ CompositeMonikerImpl *comp_moniker;
+ struct comp_node *node;
- if (!This)
+ if (!(node = heap_alloc_zero(sizeof(*node))))
return E_OUTOFMEMORY;
+ node->parent = parent;
- TRACE("(%p,%p,%p)\n",This,pmkFirst,pmkRest);
-
- /* Initialize the virtual function table. */
- This->IMoniker_iface.lpVtbl = &VT_CompositeMonikerImpl;
- This->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
- This->IMarshal_iface.lpVtbl = &VT_MarshalImpl;
- This->ref = 1;
-
- This->tabSize=BLOCK_TAB_SIZE;
- This->tabLastIndex=0;
-
- This->tabMoniker=HeapAlloc(GetProcessHeap(),0,This->tabSize*sizeof(This->tabMoniker[0]));
- if (This->tabMoniker==NULL) {
- HeapFree(GetProcessHeap(), 0, This);
- return E_OUTOFMEMORY;
- }
-
- if (!pmkFirst && !pmkRest)
+ if ((comp_moniker = unsafe_impl_from_IMoniker(moniker)))
{
- *ppMoniker = &This->IMoniker_iface;
- return S_OK;
+ moniker_get_tree_representation(comp_moniker->left, node, &node->left);
+ moniker_get_tree_representation(comp_moniker->right, node, &node->right);
}
-
- IMoniker_IsSystemMoniker(pmkFirst,&mkSys);
-
- /* put the first moniker contents in the beginning of the table */
- if (mkSys!=MKSYS_GENERICCOMPOSITE){
-
- This->tabMoniker[(This->tabLastIndex)++]=pmkFirst;
- IMoniker_AddRef(pmkFirst);
+ else
+ {
+ node->moniker = moniker;
+ IMoniker_AddRef(node->moniker);
}
- else{
- IMoniker_Enum(pmkFirst,TRUE,&enumMoniker);
+ *ret = node;
- while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
+ return S_OK;
+}
+static struct comp_node *moniker_tree_get_rightmost(struct comp_node *root)
+{
+ if (!root->left && !root->right) return root->moniker ? root : NULL;
+ while (root->right) root = root->right;
+ return root;
+}
- if (++This->tabLastIndex==This->tabSize){
- IMoniker **tab_moniker = This->tabMoniker;
+static struct comp_node *moniker_tree_get_leftmost(struct comp_node *root)
+{
+ if (!root->left && !root->right) return root->moniker ? root : NULL;
+ while (root->left) root = root->left;
+ return root;
+}
- This->tabSize+=BLOCK_TAB_SIZE;
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0]));
+static void moniker_tree_node_release(struct comp_node *node)
+{
+ if (node->moniker)
+ IMoniker_Release(node->moniker);
+ heap_free(node);
+}
- if (This->tabMoniker==NULL){
- for (i = 0; i < This->tabLastIndex; i++)
- IMoniker_Release(tab_moniker[i]);
- HeapFree(GetProcessHeap(), 0, tab_moniker);
- HeapFree(GetProcessHeap(), 0, This);
- return E_OUTOFMEMORY;
- }
- }
- }
+static void moniker_tree_release(struct comp_node *node)
+{
+ if (node->left)
+ moniker_tree_node_release(node->left);
+ if (node->right)
+ moniker_tree_node_release(node->right);
+ moniker_tree_node_release(node);
+}
- IEnumMoniker_Release(enumMoniker);
+static void moniker_tree_replace_node(struct comp_node *node, struct comp_node *replace_with)
+{
+ if (node->parent)
+ {
+ if (node->parent->left == node) node->parent->left = replace_with;
+ else node->parent->right = replace_with;
+ replace_with->parent = node->parent;
}
+ else if (replace_with->moniker)
+ {
+ /* Replacing root with non-composite */
+ node->moniker = replace_with->moniker;
+ IMoniker_AddRef(node->moniker);
+ node->left = node->right = NULL;
+ moniker_tree_node_release(replace_with);
+ }
+ else
+ {
+ /* Attaching composite branches to the root */
+ node->left = replace_with->left;
+ node->right = replace_with->right;
+ moniker_tree_node_release(replace_with);
+ }
+}
- /* put the rest moniker contents after the first one and make simplification if needed */
-
- IMoniker_IsSystemMoniker(pmkRest,&mkSys);
-
- if (mkSys!=MKSYS_GENERICCOMPOSITE){
+static void moniker_tree_discard(struct comp_node *node, BOOL left)
+{
+ if (node->parent)
+ {
+ moniker_tree_replace_node(node->parent, left ? node->parent->left : node->parent->right);
+ moniker_tree_node_release(node);
+ }
+ else
+ {
+ IMoniker_Release(node->moniker);
+ node->moniker = NULL;
+ }
+}
- /* add a simple moniker to the moniker table */
+static HRESULT moniker_create_from_tree(const struct comp_node *root, unsigned int *count, IMoniker **moniker)
+{
+ IMoniker *left_moniker, *right_moniker;
+ HRESULT hr;
- res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],pmkRest,TRUE,&tempMk);
+ *moniker = NULL;
- if (res==MK_E_NEEDGENERIC){
+ /* Non-composite node */
+ if (!root->left && !root->right)
+ {
+ (*count)++;
+ *moniker = root->moniker;
+ if (*moniker) IMoniker_AddRef(*moniker);
+ return S_OK;
+ }
- /* there's no simplification in this case */
- This->tabMoniker[This->tabLastIndex]=pmkRest;
+ if (FAILED(hr = moniker_create_from_tree(root->left, count, &left_moniker))) return hr;
+ if (FAILED(hr = moniker_create_from_tree(root->right, count, &right_moniker)))
+ {
+ IMoniker_Release(left_moniker);
+ return hr;
+ }
- This->tabLastIndex++;
+ hr = CreateGenericComposite(left_moniker, right_moniker, moniker);
+ IMoniker_Release(left_moniker);
+ IMoniker_Release(right_moniker);
+ return hr;
+}
- IMoniker_AddRef(pmkRest);
- }
- else if (tempMk==NULL){
+static void moniker_get_tree_comp_count(const struct comp_node *root, unsigned int *count)
+{
+ if (!root->left && !root->right)
+ {
+ (*count)++;
+ return;
+ }
- /* we have an antimoniker after a simple moniker so we can make a simplification in this case */
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
+ moniker_get_tree_comp_count(root->left, count);
+ moniker_get_tree_comp_count(root->right, count);
+}
- This->tabLastIndex--;
- }
- else if (SUCCEEDED(res)){
+static HRESULT moniker_simplify_composition(IMoniker *left, IMoniker *right,
+ unsigned int *count, IMoniker **new_left, IMoniker **new_right)
+{
+ struct comp_node *left_tree, *right_tree;
+ unsigned int modified = 0;
+ HRESULT hr = S_OK;
+ IMoniker *c;
- /* the non-generic composition was successful so we can make a simplification in this case */
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
+ *count = 0;
- This->tabMoniker[This->tabLastIndex-1]=tempMk;
- } else{
- for (i = 0; i < This->tabLastIndex; i++)
- IMoniker_Release(This->tabMoniker[i]);
- HeapFree(GetProcessHeap(), 0, This->tabMoniker);
- HeapFree(GetProcessHeap(), 0, This);
- return res;
- }
+ moniker_get_tree_representation(left, NULL, &left_tree);
+ moniker_get_tree_representation(right, NULL, &right_tree);
- /* resize tabMoniker if needed */
- if (This->tabLastIndex==This->tabSize){
- IMoniker **tab_moniker = This->tabMoniker;
+ /* Simplify by composing trees together, in a non-generic way. */
+ for (;;)
+ {
+ struct comp_node *l, *r;
- This->tabSize+=BLOCK_TAB_SIZE;
+ if (!(l = moniker_tree_get_rightmost(left_tree))) break;
+ if (!(r = moniker_tree_get_leftmost(right_tree))) break;
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(IMoniker));
+ c = NULL;
+ if (FAILED(IMoniker_ComposeWith(l->moniker, r->moniker, TRUE, &c))) break;
+ modified++;
- if (This->tabMoniker==NULL){
- for (i = 0; i < This->tabLastIndex; i++)
- IMoniker_Release(tab_moniker[i]);
- HeapFree(GetProcessHeap(), 0, tab_moniker);
- HeapFree(GetProcessHeap(), 0, This);
- return E_OUTOFMEMORY;
- }
+ if (c)
+ {
+ /* Replace with composed moniker on the left side */
+ IMoniker_Release(l->moniker);
+ l->moniker = c;
}
+ else
+ moniker_tree_discard(l, TRUE);
+ moniker_tree_discard(r, FALSE);
}
- else{
-
- /* add a composite moniker to the moniker table (do the same thing
- * for each moniker within the composite moniker as a simple moniker
- * (see above for how to add a simple moniker case) )
- */
- IMoniker_Enum(pmkRest,TRUE,&enumMoniker);
-
- while(IEnumMoniker_Next(enumMoniker,1,&This->tabMoniker[This->tabLastIndex],NULL)==S_OK){
- res=IMoniker_ComposeWith(This->tabMoniker[This->tabLastIndex-1],This->tabMoniker[This->tabLastIndex],TRUE,&tempMk);
+ if (!modified)
+ {
+ *new_left = left;
+ IMoniker_AddRef(*new_left);
+ *new_right = right;
+ IMoniker_AddRef(*new_right);
- if (res==MK_E_NEEDGENERIC){
+ moniker_get_tree_comp_count(left_tree, count);
+ moniker_get_tree_comp_count(right_tree, count);
+ }
+ else
+ {
+ hr = moniker_create_from_tree(left_tree, count, new_left);
+ if (SUCCEEDED(hr))
+ hr = moniker_create_from_tree(right_tree, count, new_right);
+ }
- This->tabLastIndex++;
- }
- else if (tempMk==NULL){
+ moniker_tree_release(left_tree);
+ moniker_tree_release(right_tree);
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
- IMoniker_Release(This->tabMoniker[This->tabLastIndex]);
- This->tabLastIndex--;
- }
- else{
+ if (FAILED(hr))
+ {
+ if (*new_left) IMoniker_Release(*new_left);
+ if (*new_right) IMoniker_Release(*new_right);
+ *new_left = *new_right = NULL;
+ }
- IMoniker_Release(This->tabMoniker[This->tabLastIndex-1]);
+ return hr;
+}
- This->tabMoniker[This->tabLastIndex-1]=tempMk;
- }
+static HRESULT create_composite(IMoniker *left, IMoniker *right, IMoniker **moniker)
+{
+ IMoniker *new_left, *new_right;
+ CompositeMonikerImpl *object;
+ HRESULT hr;
- if (This->tabLastIndex==This->tabSize){
- IMoniker **tab_moniker = This->tabMoniker;
+ *moniker = NULL;
- This->tabSize+=BLOCK_TAB_SIZE;
+ if (!(object = heap_alloc_zero(sizeof(*object))))
+ return E_OUTOFMEMORY;
- This->tabMoniker=HeapReAlloc(GetProcessHeap(),0,This->tabMoniker,This->tabSize*sizeof(This->tabMoniker[0]));
+ object->IMoniker_iface.lpVtbl = &VT_CompositeMonikerImpl;
+ object->IROTData_iface.lpVtbl = &VT_ROTDataImpl;
+ object->IMarshal_iface.lpVtbl = &VT_MarshalImpl;
+ object->ref = 1;
- if (This->tabMoniker==NULL){
- for (i = 0; i < This->tabLastIndex; i++)
- IMoniker_Release(tab_moniker[i]);
- HeapFree(GetProcessHeap(), 0, tab_moniker);
- HeapFree(GetProcessHeap(), 0, This);
- return E_OUTOFMEMORY;
- }
- }
- }
+ /* Uninitialized moniker created by object activation */
+ if (!left && !right)
+ {
+ *moniker = &object->IMoniker_iface;
+ return S_OK;
+ }
- IEnumMoniker_Release(enumMoniker);
+ if (FAILED(hr = moniker_simplify_composition(left, right, &object->comp_count, &new_left, &new_right)))
+ {
+ IMoniker_Release(&object->IMoniker_iface);
+ return hr;
}
- /* only one moniker, then just return it */
- if (This->tabLastIndex == 1)
+ if (!new_left || !new_right)
{
- *ppMoniker = This->tabMoniker[0];
- IMoniker_AddRef(*ppMoniker);
- IMoniker_Release(&This->IMoniker_iface);
+ *moniker = new_left ? new_left : new_right;
+ IMoniker_Release(&object->IMoniker_iface);
+ return S_OK;
}
- else
- *ppMoniker = &This->IMoniker_iface;
+
+ object->left = new_left;
+ object->right = new_right;
+
+ *moniker = &object->IMoniker_iface;
return S_OK;
}
@@ -1944,42 +1943,29 @@ CompositeMonikerImpl_Construct(IMoniker **ppMoniker, IMoniker *pmkFirst, IMonike
/******************************************************************************
* CreateGenericComposite [OLE32.@]
******************************************************************************/
-HRESULT WINAPI
-CreateGenericComposite(IMoniker *pmkFirst, IMoniker *pmkRest, IMoniker **ppmkComposite)
+HRESULT WINAPI CreateGenericComposite(IMoniker *left, IMoniker *right, IMoniker **composite)
{
- IMoniker* moniker = 0;
- HRESULT hr = S_OK;
+ TRACE("%p, %p, %p\n", left, right, composite);
- TRACE("(%p,%p,%p)\n",pmkFirst,pmkRest,ppmkComposite);
-
- if (ppmkComposite==NULL)
+ if (!composite)
return E_POINTER;
- *ppmkComposite=0;
-
- if (pmkFirst==NULL && pmkRest!=NULL){
-
- *ppmkComposite=pmkRest;
- IMoniker_AddRef(pmkRest);
+ if (!left && right)
+ {
+ *composite = right;
+ IMoniker_AddRef(*composite);
return S_OK;
}
- else if (pmkFirst!=NULL && pmkRest==NULL){
- *ppmkComposite=pmkFirst;
- IMoniker_AddRef(pmkFirst);
+ else if (left && !right)
+ {
+ *composite = left;
+ IMoniker_AddRef(*composite);
return S_OK;
}
- else if (pmkFirst==NULL && pmkRest==NULL)
+ else if (!left && !right)
return S_OK;
- hr = CompositeMonikerImpl_Construct(&moniker,pmkFirst,pmkRest);
-
- if (FAILED(hr))
- return hr;
-
- hr = IMoniker_QueryInterface(moniker,&IID_IMoniker,(void**)ppmkComposite);
- IMoniker_Release(moniker);
-
- return hr;
+ return create_composite(left, right, composite);
}
/******************************************************************************
@@ -2005,7 +1991,7 @@ HRESULT WINAPI CompositeMoniker_CreateInstance(IClassFactory *iface,
if (pUnk)
return CLASS_E_NOAGGREGATION;
- hr = CompositeMonikerImpl_Construct(&pMoniker, NULL, NULL);
+ hr = create_composite(NULL, NULL, &pMoniker);
if (SUCCEEDED(hr))
{
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c
index d65535a0584..ef1d3869b63 100644
--- a/dlls/ole32/tests/moniker.c
+++ b/dlls/ole32/tests/moniker.c
@@ -2912,6 +2912,11 @@ static void test_generic_composite_moniker(void)
IBindCtx *bindctx;
FILETIME filetime;
IUnknown *unknown;
+ IROTData *rotdata;
+ IMarshal *marshal;
+ IStream *stream;
+ WCHAR *str;
+ ULONG len;
hr = CreateBindCtx(0, &bindctx);
ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
@@ -2936,10 +2941,7 @@ static void test_generic_composite_moniker(void)
ok(hr == S_OK, "Failed to invert, hr %#x.\n", hr);
hr = CreateGenericComposite(moniker1, inverse, &moniker);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-todo_wine
ok(!moniker, "Unexpected pointer.\n");
- if (moniker)
- IMoniker_Release(moniker);
/* (I1,I2) + (A,A) -> (I1,I2+A,A) -> (I1,A) -> () */
hr = CreateGenericComposite(moniker1, moniker2, &moniker);
@@ -2950,10 +2952,7 @@ todo_wine
hr = CreateGenericComposite(moniker, moniker3, &moniker4);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
-todo_wine
ok(!moniker4, "Unexpected pointer.\n");
- if (moniker4)
- IMoniker_Release(moniker4);
IMoniker_Release(moniker);
IMoniker_Release(moniker3);
@@ -2970,7 +2969,7 @@ todo_wine
hr = CreateGenericComposite(moniker, moniker3, &moniker4);
ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
- TEST_MONIKER_TYPE_TODO(moniker4, MKSYS_ANTIMONIKER);
+ TEST_MONIKER_TYPE(moniker4, MKSYS_ANTIMONIKER);
IMoniker_Release(moniker4);
IMoniker_Release(moniker);
IMoniker_Release(moniker3);
@@ -3083,6 +3082,41 @@ todo_wine
IMoniker_Release(moniker);
+ /* Uninitialized composite */
+ hr = CoCreateInstance(&CLSID_CompositeMoniker, NULL, CLSCTX_SERVER, &IID_IMoniker, (void **)&moniker);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+
+ hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+ ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
+ /* Exact error is E_OUTOFMEMORY */
+ hr = IMoniker_Save(moniker, stream, TRUE);
+ ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ IStream_Release(stream);
+
+ hash = 0xdeadbeef;
+ hr = IMoniker_Hash(moniker, &hash);
+ ok(hr == E_UNEXPECTED, "Unexpected hr %#x.\n", hr);
+ ok(hash == 0xdeadbeef, "Unexpected hash %#x.\n", hash);
+
+ hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &str);
+ ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
+
+ hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IROTData_GetComparisonData(rotdata, NULL, 0, &len);
+ ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ IROTData_Release(rotdata);
+
+ hr = IMoniker_QueryInterface(moniker, &IID_IMarshal, (void **)&marshal);
+ ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
+ hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &len);
+ ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ hr = IMarshal_MarshalInterface(marshal, stream, &IID_IMoniker, NULL, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+ ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
+ IMarshal_Release(marshal);
+
+ IMoniker_Release(moniker);
+
IBindCtx_Release(bindctx);
}
--
2.33.0
More information about the wine-devel
mailing list