Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/pointermoniker.c | 129 ++++++++++++++++++++++++++++++++++-- dlls/ole32/tests/moniker.c | 38 ++++++++++- 2 files changed, 160 insertions(+), 7 deletions(-)
diff --git a/dlls/ole32/pointermoniker.c b/dlls/ole32/pointermoniker.c index c1a0e2ae1c..2cb0600336 100644 --- a/dlls/ole32/pointermoniker.c +++ b/dlls/ole32/pointermoniker.c @@ -37,13 +37,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole);
/* PointerMoniker data structure */ -typedef struct PointerMonikerImpl{ - +typedef struct PointerMonikerImpl +{ IMoniker IMoniker_iface; + IMarshal IMarshal_iface;
LONG ref; /* reference counter for this object */
- IUnknown *pObject; /* custom marshaler */ + IUnknown *pObject; } PointerMonikerImpl;
static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface) @@ -51,6 +52,11 @@ static inline PointerMonikerImpl *impl_from_IMoniker(IMoniker *iface) return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface); }
+static PointerMonikerImpl *impl_from_IMarshal(IMarshal *iface) +{ + return CONTAINING_RECORD(iface, PointerMonikerImpl, IMarshal_iface); +} + static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface); static HRESULT WINAPI PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) @@ -70,7 +76,11 @@ PointerMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid) || IsEqualIID(&IID_IMoniker, riid)) + { *ppvObject = iface; + } + else if (IsEqualIID(&IID_IMarshal, riid)) + *ppvObject = &This->IMarshal_iface;
/* Check that we obtained an interface.*/ if ((*ppvObject)==0) @@ -542,6 +552,117 @@ static PointerMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface) return CONTAINING_RECORD(iface, PointerMonikerImpl, IMoniker_iface); }
+static HRESULT WINAPI pointer_moniker_marshal_QueryInterface(IMarshal *iface, REFIID riid, LPVOID *ppv) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), ppv); + + return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv); +} + +static ULONG WINAPI pointer_moniker_marshal_AddRef(IMarshal *iface) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p.\n",iface); + + return IMoniker_AddRef(&moniker->IMoniker_iface); +} + +static ULONG WINAPI pointer_moniker_marshal_Release(IMarshal *iface) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p.\n",iface); + + return IMoniker_Release(&moniker->IMoniker_iface); +} + +static HRESULT WINAPI pointer_moniker_marshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, void *pv, + DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p, %s, %p, %x, %p, %x, %p.\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext, + mshlflags, clsid); + + return IMoniker_GetClassID(&moniker->IMoniker_iface, clsid); +} + +static HRESULT WINAPI pointer_moniker_marshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, void *pv, + DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p, %s, %p, %d, %p, %#x, %p.\n", iface, debugstr_guid(riid), pv, dwDestContext, pvDestContext, + mshlflags, size); + + return CoGetMarshalSizeMax(size, &IID_IUnknown, moniker->pObject, dwDestContext, pvDestContext, mshlflags); +} + +static HRESULT WINAPI pointer_moniker_marshal_MarshalInterface(IMarshal *iface, IStream *stream, REFIID riid, + void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + + TRACE("%p, %s, %p, %x, %p, %x.\n", stream, debugstr_guid(riid), pv, + dwDestContext, pvDestContext, mshlflags); + + return CoMarshalInterface(stream, &IID_IUnknown, moniker->pObject, dwDestContext, + pvDestContext, mshlflags); +} + +static HRESULT WINAPI pointer_moniker_marshal_UnmarshalInterface(IMarshal *iface, IStream *stream, + REFIID riid, void **ppv) +{ + PointerMonikerImpl *moniker = impl_from_IMarshal(iface); + IUnknown *object; + HRESULT hr; + + TRACE("%p, %p, %s, %p.\n", iface, stream, debugstr_guid(riid), ppv); + + hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void **)&object); + if (FAILED(hr)) + { + ERR("Couldn't unmarshal moniker, hr = %#x.\n", hr); + return hr; + } + + if (moniker->pObject) + IUnknown_Release(moniker->pObject); + moniker->pObject = object; + + return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppv); +} + +static HRESULT WINAPI pointer_moniker_marshal_ReleaseMarshalData(IMarshal *iface, IStream *stream) +{ + TRACE("%p, %p.\n", iface, stream); + + return S_OK; +} + +static HRESULT WINAPI pointer_moniker_marshal_DisconnectObject(IMarshal *iface, DWORD reserved) +{ + TRACE("%p, %#x.\n", iface, reserved); + + return S_OK; +} + +static const IMarshalVtbl pointer_moniker_marshal_vtbl = +{ + pointer_moniker_marshal_QueryInterface, + pointer_moniker_marshal_AddRef, + pointer_moniker_marshal_Release, + pointer_moniker_marshal_GetUnmarshalClass, + pointer_moniker_marshal_GetMarshalSizeMax, + pointer_moniker_marshal_MarshalInterface, + pointer_moniker_marshal_UnmarshalInterface, + pointer_moniker_marshal_ReleaseMarshalData, + pointer_moniker_marshal_DisconnectObject +}; + /****************************************************************************** * PointerMoniker_Construct (local function) *******************************************************************************/ @@ -549,8 +670,8 @@ static void PointerMonikerImpl_Construct(PointerMonikerImpl* This, IUnknown *pun { TRACE("(%p)\n",This);
- /* Initialize the virtual function table. */ This->IMoniker_iface.lpVtbl = &VT_PointerMonikerImpl; + This->IMarshal_iface.lpVtbl = &pointer_moniker_marshal_vtbl; This->ref = 1; if (punk) IUnknown_AddRef(punk); diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 231551b244..0e6f2677c5 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -2722,16 +2722,18 @@ todo_wine static void test_pointer_moniker(void) { IMoniker *moniker, *moniker2, *prefix, *inverse; + DWORD moniker_type, hash, size; IEnumMoniker *enummoniker; HRESULT hr; - DWORD moniker_type; - DWORD hash; IBindCtx *bindctx; FILETIME filetime; IUnknown *unknown; IStream *stream; IROTData *rotdata; LPOLESTR display_name; + IMarshal *marshal; + LARGE_INTEGER pos; + CLSID clsid;
cLocks = 0;
@@ -2750,6 +2752,35 @@ todo_wine IUnknown_Release(unknown); }
+ hr = IMoniker_QueryInterface(moniker, &IID_IMarshal, (void **)&marshal); + ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr); + + hr = IMarshal_GetUnmarshalClass(marshal, NULL, NULL, 0, NULL, 0, &clsid); + ok(hr == S_OK, "Failed to get class, hr %#x.\n", hr); + ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "Unexpected class.\n"); + + hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, CLSCTX_INPROC, NULL, 0, &size); + ok(hr == S_OK, "Failed to get marshal size, hr %#x.\n", hr); + ok(size > 0, "Unexpected size %d.\n", size); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr); + + hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); + ok(hr == S_OK, "Failed to marshal moniker, hr %#x.\n", hr); + + pos.QuadPart = 0; + IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker2); + ok(hr == S_OK, "Failed to unmarshal, hr %#x.\n", hr); + hr = IMoniker_IsEqual(moniker, moniker2); + ok(hr == S_OK, "Expected equal moniker, hr %#x.\n", hr); + IMoniker_Release(moniker2); + + IStream_Release(stream); + + IMarshal_Release(marshal); + ok_more_than_one_lock();
/* Display Name */ @@ -2821,7 +2852,8 @@ todo_wine
IMoniker_Release(moniker);
- ok_no_locks(); +todo_wine + ok(cLocks == 0, "Number of locks should be 0, but actually is %d.\n", cLocks);
hr = CreatePointerMoniker(NULL, &moniker); ok_ole_success(hr, CreatePointerMoniker);
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/tests/moniker.c | 329 ++++++++++++++++++++++++++++--------- 1 file changed, 248 insertions(+), 81 deletions(-)
diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 0e6f2677c5..f5f69870bf 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -70,6 +70,56 @@ DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x309, 0, 0); DEFINE_OLEGUID(CLSID_ClassMoniker, 0x31a, 0, 0); DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0);
+#define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__) +static void _expect_ref(IUnknown* obj, ULONG ref, int line) +{ + ULONG refcount; + IUnknown_AddRef(obj); + refcount = IUnknown_Release(obj); + ok_(__FILE__, line)(refcount == ref, "Unexpected got %u.\n", refcount); +} + +#define TEST_MONIKER_TYPE_TODO(m,t) _test_moniker_type(m, t, TRUE, __LINE__) +#define TEST_MONIKER_TYPE(m,t) _test_moniker_type(m, t, FALSE, __LINE__) +static void _test_moniker_type(IMoniker *moniker, DWORD type, BOOL todo, int line) +{ + DWORD type2; + HRESULT hr; + + hr = IMoniker_IsSystemMoniker(moniker, &type2); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#x.\n", hr); +todo_wine_if(todo) + ok_(__FILE__, line)(type2 == type, "Unexpected moniker type %d.\n", type2); +} + +static IMoniker *create_antimoniker(DWORD level) +{ + LARGE_INTEGER pos; + IMoniker *moniker; + IStream *stream; + HRESULT hr; + + hr = CreateAntiMoniker(&moniker); + ok(hr == S_OK, "Failed to create antimoniker, hr %#x.\n", hr); + + hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); + ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr); + + hr = IStream_Write(stream, &level, sizeof(level), NULL); + ok(hr == S_OK, "Failed to write contents, hr %#x.\n", hr); + + pos.QuadPart = 0; + hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL); + ok(hr == S_OK, "Failed to rewind, hr %#x.\n", hr); + + hr = IMoniker_Load(moniker, stream); + ok(hr == S_OK, "Failed to load, hr %#x.\n", hr); + + IStream_Release(stream); + + return moniker; +} + static LONG cLocks;
static void LockModule(void) @@ -994,7 +1044,6 @@ static void test_MkParseDisplayName(void) DWORD pdwReg1=0; DWORD grflags=0; DWORD pdwReg2=0; - DWORD moniker_type; IRunningObjectTable * pprot=NULL;
/* CLSID of My Computer */ @@ -1086,8 +1135,7 @@ todo_wine "Processed character count should have been 43 instead of %u\n", eaten); if (pmk) { - IMoniker_IsSystemMoniker(pmk, &moniker_type); - ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type); + TEST_MONIKER_TYPE(pmk, MKSYS_CLASSMONIKER); IMoniker_Release(pmk); } hr = IRunningObjectTable_Revoke(pprot, pdwReg1); @@ -1108,8 +1156,7 @@ todo_wine "Processed character count should have been 15 instead of %u\n", eaten); if (pmk) { - IMoniker_IsSystemMoniker(pmk, &moniker_type); - ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type); + TEST_MONIKER_TYPE(pmk, MKSYS_FILEMONIKER); IMoniker_Release(pmk); } hr = IRunningObjectTable_Revoke(pprot, pdwReg1); @@ -1126,8 +1173,7 @@ todo_wine "Processed character count should have been 8 instead of %u\n", eaten); if (pmk) { - IMoniker_IsSystemMoniker(pmk, &moniker_type); - ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type); + TEST_MONIKER_TYPE(pmk, MKSYS_ANTIMONIKER); IMoniker_Release(pmk); }
@@ -1138,8 +1184,7 @@ todo_wine "Processed character count should have been 8 instead of %u\n", eaten); if (pmk) { - IMoniker_IsSystemMoniker(pmk, &moniker_type); - ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type); + TEST_MONIKER_TYPE(pmk, MKSYS_ANTIMONIKER); IMoniker_Release(pmk); }
@@ -1163,8 +1208,7 @@ todo_wine ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten); if (pmk) { - IMoniker_IsSystemMoniker(pmk, &moniker_type); - ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type); + TEST_MONIKER_TYPE(pmk, MKSYS_FILEMONIKER); IMoniker_Release(pmk); }
@@ -1717,10 +1761,9 @@ todo_wine_if(moniker_type == MKSYS_GENERICCOMPOSITE)
static void test_class_moniker(void) { - IMoniker *moniker, *inverse, *reduced; + IMoniker *moniker, *moniker2, *inverse, *reduced, *anti; IEnumMoniker *enummoniker; HRESULT hr; - DWORD moniker_type; DWORD hash; IBindCtx *bindctx; IUnknown *unknown; @@ -1754,13 +1797,7 @@ todo_wine hash);
/* IsSystemMoniker test */ - - hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); - ok_ole_success(hr, IMoniker_IsSystemMoniker); - - ok(moniker_type == MKSYS_CLASSMONIKER, - "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n", - moniker_type); + TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
hr = CreateBindCtx(0, &bindctx); ok_ole_success(hr, CreateBindCtx); @@ -1785,9 +1822,7 @@ todo_wine
hr = IMoniker_Inverse(moniker, &inverse); ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr); - hr = IMoniker_IsSystemMoniker(inverse, &moniker_type); - ok(hr == S_OK, "Failed to get moniker type, hr %#x.\n", hr); - ok(moniker_type == MKSYS_ANTIMONIKER, "Unexpected moniker type %d.\n", moniker_type); + TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER); IMoniker_Release(inverse);
/* Reduce() */ @@ -1813,17 +1848,33 @@ todo_wine
IBindCtx_Release(bindctx);
+ /* ComposeWith() */ + + /* C + A -> () */ + anti = create_antimoniker(1); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); + ok(!moniker2, "Unexpected pointer.\n"); + IMoniker_Release(anti); + + /* C + A2 -> A */ + anti = create_antimoniker(2); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); + ok(!moniker2, "Unexpected pointer.\n"); + IMoniker_Release(anti); + IMoniker_Release(moniker); }
static void test_file_moniker(WCHAR* path) { - IMoniker *moniker1 = NULL, *moniker2 = NULL, *inverse, *reduced; + IMoniker *moniker1 = NULL, *moniker2 = NULL, *inverse, *reduced, *anti; IEnumMoniker *enummoniker; - DWORD moniker_type; IBindCtx *bind_ctx; IStream *stream; IUnknown *unk; + DWORD hash; HRESULT hr;
hr = CreateFileMoniker(path, &moniker1); @@ -1840,9 +1891,7 @@ todo_wine
hr = IMoniker_Inverse(moniker1, &inverse); ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr); - hr = IMoniker_IsSystemMoniker(inverse, &moniker_type); - ok(hr == S_OK, "Failed to get moniker type, hr %#x.\n", hr); - ok(moniker_type == MKSYS_ANTIMONIKER, "Unexpected moniker type %d.\n", moniker_type); + TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER); IMoniker_Release(inverse);
hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); @@ -1894,10 +1943,34 @@ todo_wine IBindCtx_Release(bind_ctx);
IStream_Release(stream); - if (moniker1) - IMoniker_Release(moniker1); - if (moniker2) - IMoniker_Release(moniker2); + IMoniker_Release(moniker2); + + /* ComposeWith() */ + + /* F + A -> () */ + anti = create_antimoniker(1); + hr = IMoniker_ComposeWith(moniker1, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); + ok(!moniker2, "Unexpected pointer.\n"); + IMoniker_Release(anti); + + /* I + A2 -> (A) */ + anti = create_antimoniker(2); + hr = IMoniker_ComposeWith(moniker1, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); +todo_wine + ok(!!moniker2, "Unexpected pointer.\n"); +if (moniker2) +{ + TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); + hr = IMoniker_Hash(moniker2, &hash); + ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr); + ok(hash == 0x80000001, "Unexpected hash.\n"); + IMoniker_Release(moniker2); +} + IMoniker_Release(anti); + + IMoniker_Release(moniker1); }
static void test_file_monikers(void) @@ -2005,12 +2078,10 @@ static void test_item_moniker(void) "Moniker_IsRunning", NULL }; - IMoniker *moniker, *moniker2, *reduced; + IMoniker *moniker, *moniker2, *reduced, *anti, *inverse; + DWORD i, hash, eaten, cookie; HRESULT hr; - DWORD moniker_type, i; - DWORD hash, eaten; IBindCtx *bindctx; - IMoniker *inverse; IUnknown *unknown; static const WCHAR wszDelimiter[] = {'!',0}; static const WCHAR wszObjectName[] = {'T','e','s','t',0}; @@ -2023,7 +2094,6 @@ static void test_item_moniker(void) BIND_OPTS bind_opts; LARGE_INTEGER pos; IStream *stream; - DWORD cookie;
hr = CreateItemMoniker(NULL, wszObjectName, &moniker); ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr); @@ -2139,13 +2209,7 @@ todo_wine 54, expected_display_name);
/* IsSystemMoniker test */ - - hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); - ok_ole_success(hr, IMoniker_IsSystemMoniker); - - ok(moniker_type == MKSYS_ITEMMONIKER, - "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n", - moniker_type); + TEST_MONIKER_TYPE(moniker, MKSYS_ITEMMONIKER);
container_moniker = create_test_moniker();
@@ -2272,9 +2336,7 @@ todo_wine
hr = IMoniker_Inverse(moniker, &inverse); ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr); - hr = IMoniker_IsSystemMoniker(inverse, &moniker_type); - ok(hr == S_OK, "Failed to get moniker type, hr %#x.\n", hr); - ok(moniker_type == MKSYS_ANTIMONIKER, "Unexpected moniker type %d.\n", moniker_type); + TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER); IMoniker_Release(inverse);
/* Reduce() */ @@ -2336,6 +2398,35 @@ todo_wine ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
IMoniker_Release(moniker); + + /* ComposeWith() */ + hr = CreateItemMoniker(L"!", L"Item", &moniker); + ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr); + + /* I + A -> () */ + anti = create_antimoniker(1); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); + ok(!moniker2, "Unexpected pointer.\n"); + IMoniker_Release(anti); + + /* I + A2 -> (A) */ + anti = create_antimoniker(2); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); +todo_wine + ok(!!moniker2, "Unexpected pointer.\n"); +if (moniker2) +{ + TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); + hr = IMoniker_Hash(moniker2, &hash); + ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr); + ok(hash == 0x80000001, "Unexpected hash.\n"); + IMoniker_Release(moniker2); +} + IMoniker_Release(anti); + + IMoniker_Release(moniker); }
static void stream_write_dword(IStream *stream, DWORD value) @@ -2358,7 +2449,6 @@ static void test_anti_moniker(void) { IMoniker *moniker, *moniker2, *moniker3, *inverse, *reduced; HRESULT hr; - DWORD moniker_type; DWORD hash; IBindCtx *bindctx; FILETIME filetime; @@ -2394,11 +2484,7 @@ todo_wine hash);
/* IsSystemMoniker test */ - hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); - ok_ole_success(hr, IMoniker_IsSystemMoniker); - ok(moniker_type == MKSYS_ANTIMONIKER, - "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n", - moniker_type); + TEST_MONIKER_TYPE(moniker, MKSYS_ANTIMONIKER);
hr = IMoniker_Inverse(moniker, &inverse); ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr); @@ -2431,9 +2517,7 @@ todo_wine
hr = IMoniker_ComposeWith(moniker, moniker2, FALSE, &moniker3); ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); - hr = IMoniker_IsSystemMoniker(moniker3, &moniker_type); - ok(hr == S_OK, "Failed to get moniker type, hr %#x.\n", hr); - ok(moniker_type == MKSYS_GENERICCOMPOSITE, "Unexpected moniker type %d.\n", moniker_type); + TEST_MONIKER_TYPE(moniker3, MKSYS_GENERICCOMPOSITE); IMoniker_Release(moniker3);
IMoniker_Release(moniker2); @@ -2619,22 +2703,22 @@ todo_wine
static void test_generic_composite_moniker(void) { + IMoniker *moniker, *inverse, *inverse2, *moniker1, *moniker2, *moniker3, *moniker4; IEnumMoniker *enummoniker; HRESULT hr; - IMoniker *moniker; - IMoniker *moniker1; - IMoniker *moniker2; - DWORD moniker_type; DWORD hash; IBindCtx *bindctx; FILETIME filetime; - IMoniker *inverse; IUnknown *unknown; static const WCHAR wszDelimiter1[] = {'!',0}; static const WCHAR wszObjectName1[] = {'T','e','s','t',0}; static const WCHAR wszDelimiter2[] = {'#',0}; static const WCHAR wszObjectName2[] = {'W','i','n','e',0}; static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 }; + WCHAR *name; + + hr = CreateBindCtx(0, &bindctx); + ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
hr = CreateItemMoniker(wszDelimiter1, wszObjectName1, &moniker1); ok_ole_success(hr, CreateItemMoniker); @@ -2643,6 +2727,81 @@ static void test_generic_composite_moniker(void) hr = CreateGenericComposite(moniker1, moniker2, &moniker); ok_ole_success(hr, CreateGenericComposite);
+ /* Compose with itself. */ + EXPECT_REF(moniker1, 2); + hr = CreateGenericComposite(moniker1, moniker1, &moniker); + ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); + EXPECT_REF(moniker1, 4); + TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE); + IMoniker_Release(moniker); + + /* (I) + (A) -> () */ + hr = IMoniker_Inverse(moniker1, &inverse); + 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); + ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); + hr = CreateGenericComposite(inverse, inverse, &moniker3); + ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); + TEST_MONIKER_TYPE(moniker3, MKSYS_GENERICCOMPOSITE); + + 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); + + /* (I1,I2) + (A2,A) -> (I1,I2+A2,A) -> (I1,A,A) -> (I1+A,A) -> (A) */ + hr = CreateGenericComposite(moniker1, moniker2, &moniker); + ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); + ok(!!moniker, "Unexpected pointer.\n"); + inverse2 = create_antimoniker(2); + hr = CreateGenericComposite(inverse2, inverse, &moniker3); + ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); + ok(!!moniker3, "Unexpected pointer.\n"); + IMoniker_Release(inverse2); + + hr = CreateGenericComposite(moniker, moniker3, &moniker4); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE_TODO(moniker4, MKSYS_ANTIMONIKER); + IMoniker_Release(moniker4); + IMoniker_Release(moniker); + IMoniker_Release(moniker3); + + /* (I1,I2) + (A,I2) -> (I1,I2+A,I2) -> (I1,I2) */ + hr = CreateGenericComposite(moniker1, moniker2, &moniker); + ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); + ok(!!moniker, "Unexpected pointer.\n"); + + hr = CreateGenericComposite(inverse, moniker2, &moniker3); + ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr); + ok(!!moniker3, "Unexpected pointer.\n"); + + hr = CreateGenericComposite(moniker, moniker3, &moniker4); + ok(hr == S_OK, "Unexpected hr %#x.\n", hr); + TEST_MONIKER_TYPE(moniker4, MKSYS_GENERICCOMPOSITE); + + hr = IMoniker_GetDisplayName(moniker4, bindctx, NULL, &name); + ok(hr == S_OK, "Failed to get display name, hr %#x.\n", hr); + ok(!lstrcmpW(name, L"!Test#Wine"), "Unexpected name %s.\n", wine_dbgstr_w(name)); + CoTaskMemFree(name); + + IMoniker_Release(moniker4); + IMoniker_Release(moniker3); + + IMoniker_Release(inverse); + /* Generic composite is special, as it does not addref in this case. */ hr = IMoniker_QueryInterface(moniker, &CLSID_CompositeMoniker, (void **)&unknown); todo_wine @@ -2666,13 +2825,7 @@ todo_wine hash);
/* IsSystemMoniker test */ - - hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); - ok_ole_success(hr, IMoniker_IsSystemMoniker); - - ok(moniker_type == MKSYS_GENERICCOMPOSITE, - "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n", - moniker_type); + TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
hr = CreateBindCtx(0, &bindctx); ok_ole_success(hr, CreateBindCtx); @@ -2698,9 +2851,7 @@ todo_wine
hr = IMoniker_Inverse(moniker, &inverse); ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr); - hr = IMoniker_IsSystemMoniker(inverse, &moniker_type); - ok(hr == S_OK, "Failed to get moniker type, hr %#x.\n", hr); - ok(moniker_type == MKSYS_GENERICCOMPOSITE, "Unexpected moniker type %d.\n", moniker_type); + TEST_MONIKER_TYPE(inverse, MKSYS_GENERICCOMPOSITE); IMoniker_Release(inverse);
/* Enum() */ @@ -2721,9 +2872,9 @@ todo_wine
static void test_pointer_moniker(void) { - IMoniker *moniker, *moniker2, *prefix, *inverse; - DWORD moniker_type, hash, size; + IMoniker *moniker, *moniker2, *prefix, *inverse, *anti; IEnumMoniker *enummoniker; + DWORD hash, size; HRESULT hr; IBindCtx *bindctx; FILETIME filetime; @@ -2819,17 +2970,11 @@ todo_wine PtrToUlong(&Test_ClassFactory), hash);
/* IsSystemMoniker test */ - hr = IMoniker_IsSystemMoniker(moniker, &moniker_type); - ok_ole_success(hr, IMoniker_IsSystemMoniker); - ok(moniker_type == MKSYS_POINTERMONIKER, - "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n", - moniker_type); + TEST_MONIKER_TYPE(moniker, MKSYS_POINTERMONIKER);
hr = IMoniker_Inverse(moniker, &inverse); ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr); - hr = IMoniker_IsSystemMoniker(inverse, &moniker_type); - ok(hr == S_OK, "Failed to get moniker type, hr %#x.\n", hr); - ok(moniker_type == MKSYS_ANTIMONIKER, "Unexpected moniker type %d.\n", moniker_type); + TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER); IMoniker_Release(inverse);
hr = CreateBindCtx(0, &bindctx); @@ -2914,6 +3059,28 @@ todo_wine
IMoniker_Release(moniker2);
+ /* ComposeWith() */ + + /* P + A -> () */ + anti = create_antimoniker(1); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); + ok(!moniker2, "Unexpected pointer.\n"); + IMoniker_Release(anti); + + /* P + A2 -> A */ + anti = create_antimoniker(2); + hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); + ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); +todo_wine + ok(!!moniker2, "Unexpected pointer.\n"); +if (moniker2) +{ + TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); + IMoniker_Release(moniker2); +} + IMoniker_Release(anti); + IMoniker_Release(moniker); }
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/antimoniker.c | 77 +++++++++++++++------------------------- 1 file changed, 29 insertions(+), 48 deletions(-)
diff --git a/dlls/ole32/antimoniker.c b/dlls/ole32/antimoniker.c index 5bce4fc5da..93d6ab9d56 100644 --- a/dlls/ole32/antimoniker.c +++ b/dlls/ole32/antimoniker.c @@ -30,6 +30,7 @@ #include "winerror.h" #include "objbase.h" #include "wine/debug.h" +#include "wine/heap.h" #include "moniker.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole); @@ -38,7 +39,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ole); typedef struct AntiMonikerImpl{ IMoniker IMoniker_iface; IROTData IROTData_iface; - LONG ref; + LONG refcount; IUnknown *pMarshal; /* custom marshaler */ DWORD count; } AntiMonikerImpl; @@ -103,37 +104,33 @@ AntiMonikerImpl_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject) /****************************************************************************** * AntiMoniker_AddRef ******************************************************************************/ -static ULONG WINAPI -AntiMonikerImpl_AddRef(IMoniker* iface) +static ULONG WINAPI AntiMonikerImpl_AddRef(IMoniker *iface) { - AntiMonikerImpl *This = impl_from_IMoniker(iface); + AntiMonikerImpl *moniker = impl_from_IMoniker(iface); + ULONG refcount = InterlockedIncrement(&moniker->refcount);
- TRACE("(%p)\n",This); + TRACE("%p, refcount %u.\n", iface, refcount);
- return InterlockedIncrement(&This->ref); + return refcount; }
/****************************************************************************** * AntiMoniker_Release ******************************************************************************/ -static ULONG WINAPI -AntiMonikerImpl_Release(IMoniker* iface) +static ULONG WINAPI AntiMonikerImpl_Release(IMoniker *iface) { - AntiMonikerImpl *This = impl_from_IMoniker(iface); - ULONG ref; - - TRACE("(%p)\n",This); + AntiMonikerImpl *moniker = impl_from_IMoniker(iface); + ULONG refcount = InterlockedDecrement(&moniker->refcount);
- ref = InterlockedDecrement(&This->ref); + TRACE("%p, refcount %u.\n", iface, refcount);
- /* destroy the object if there are no more references to it */ - if (ref == 0) + if (!refcount) { - if (This->pMarshal) IUnknown_Release(This->pMarshal); - HeapFree(GetProcessHeap(),0,This); + if (moniker->pMarshal) IUnknown_Release(moniker->pMarshal); + heap_free(moniker); }
- return ref; + return refcount; }
/****************************************************************************** @@ -610,20 +607,20 @@ static const IROTDataVtbl VT_ROTDataImpl = AntiMonikerROTDataImpl_GetComparisonData };
-/****************************************************************************** - * AntiMoniker_Construct (local function) - *******************************************************************************/ -static HRESULT AntiMonikerImpl_Construct(AntiMonikerImpl* This) +static HRESULT create_anti_moniker(DWORD order, IMoniker **ret) { + AntiMonikerImpl *moniker; + + moniker = heap_alloc_zero(sizeof(*moniker)); + if (!moniker) + return E_OUTOFMEMORY;
- TRACE("(%p)\n",This); + moniker->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl; + moniker->IROTData_iface.lpVtbl = &VT_ROTDataImpl; + moniker->refcount = 1; + moniker->count = order;
- /* Initialize the virtual function table. */ - This->IMoniker_iface.lpVtbl = &VT_AntiMonikerImpl; - This->IROTData_iface.lpVtbl = &VT_ROTDataImpl; - This->ref = 0; - This->pMarshal = NULL; - This->count = 1; + *ret = &moniker->IMoniker_iface;
return S_OK; } @@ -631,27 +628,11 @@ static HRESULT AntiMonikerImpl_Construct(AntiMonikerImpl* This) /****************************************************************************** * CreateAntiMoniker [OLE32.@] ******************************************************************************/ -HRESULT WINAPI CreateAntiMoniker(IMoniker **ppmk) +HRESULT WINAPI CreateAntiMoniker(IMoniker **moniker) { - AntiMonikerImpl* newAntiMoniker; - HRESULT hr; - - TRACE("(%p)\n",ppmk); - - newAntiMoniker = HeapAlloc(GetProcessHeap(), 0, sizeof(AntiMonikerImpl)); - - if (newAntiMoniker == 0) - return STG_E_INSUFFICIENTMEMORY; - - hr = AntiMonikerImpl_Construct(newAntiMoniker); - if (FAILED(hr)) - { - HeapFree(GetProcessHeap(),0,newAntiMoniker); - return hr; - } + TRACE("%p.\n", moniker);
- return AntiMonikerImpl_QueryInterface(&newAntiMoniker->IMoniker_iface, &IID_IMoniker, - (void**)ppmk); + return create_anti_moniker(1, moniker); }
HRESULT WINAPI AntiMoniker_CreateInstance(IClassFactory *iface,
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/antimoniker.c | 17 ++++++++++++++++- dlls/ole32/moniker.h | 2 ++ dlls/ole32/pointermoniker.c | 15 ++++++++------- dlls/ole32/tests/moniker.c | 6 +----- 4 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/dlls/ole32/antimoniker.c b/dlls/ole32/antimoniker.c index 93d6ab9d56..6efd4ae853 100644 --- a/dlls/ole32/antimoniker.c +++ b/dlls/ole32/antimoniker.c @@ -56,6 +56,21 @@ static inline AntiMonikerImpl *impl_from_IROTData(IROTData *iface)
static AntiMonikerImpl *unsafe_impl_from_IMoniker(IMoniker *iface);
+BOOL is_anti_moniker(IMoniker *iface, DWORD *order) +{ + AntiMonikerImpl *moniker = unsafe_impl_from_IMoniker(iface); + + if (!moniker) + { + *order = 0; + return FALSE; + } + + *order = moniker->count; + + return TRUE; +} + /******************************************************************************* * AntiMoniker_QueryInterface *******************************************************************************/ @@ -607,7 +622,7 @@ static const IROTDataVtbl VT_ROTDataImpl = AntiMonikerROTDataImpl_GetComparisonData };
-static HRESULT create_anti_moniker(DWORD order, IMoniker **ret) +HRESULT create_anti_moniker(DWORD order, IMoniker **ret) { AntiMonikerImpl *moniker;
diff --git a/dlls/ole32/moniker.h b/dlls/ole32/moniker.h index eaeed54a4e..995e0459e5 100644 --- a/dlls/ole32/moniker.h +++ b/dlls/ole32/moniker.h @@ -48,5 +48,7 @@ HRESULT ClassMoniker_CreateFromDisplayName(LPBC pbc, LPCOLESTR szDisplayName,
HRESULT MonikerMarshal_Create(IMoniker *inner, IUnknown **outer) DECLSPEC_HIDDEN;
+BOOL is_anti_moniker(IMoniker *iface, DWORD *order) DECLSPEC_HIDDEN; +HRESULT create_anti_moniker(DWORD order, IMoniker **ret) DECLSPEC_HIDDEN;
#endif /* __WINE_MONIKER_H__ */ diff --git a/dlls/ole32/pointermoniker.c b/dlls/ole32/pointermoniker.c index 2cb0600336..a16a56a098 100644 --- a/dlls/ole32/pointermoniker.c +++ b/dlls/ole32/pointermoniker.c @@ -262,7 +262,7 @@ PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight, {
HRESULT res=S_OK; - DWORD mkSys,mkSys2; + DWORD mkSys,mkSys2, order; IEnumMoniker* penumMk=0; IMoniker *pmostLeftMk=0; IMoniker* tempMkComposite=0; @@ -274,15 +274,15 @@ PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
*ppmkComposite=0;
- IMoniker_IsSystemMoniker(pmkRight,&mkSys); - - /* If pmkRight is an anti-moniker, the returned moniker is NULL */ - if(mkSys==MKSYS_ANTIMONIKER) - return res; - + if (is_anti_moniker(pmkRight, &order)) + { + return order > 1 ? create_anti_moniker(order - 1, ppmkComposite) : S_OK; + } else + { /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ + IMoniker_IsSystemMoniker(pmkRight,&mkSys);
if(mkSys==MKSYS_GENERICCOMPOSITE){
@@ -326,6 +326,7 @@ PointerMonikerImpl_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
else return MK_E_NEEDGENERIC; + } }
/****************************************************************************** diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index f5f69870bf..61aa0b4a96 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -3072,13 +3072,9 @@ todo_wine anti = create_antimoniker(2); hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); -todo_wine - ok(!!moniker2, "Unexpected pointer.\n"); -if (moniker2) -{ TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); IMoniker_Release(moniker2); -} + IMoniker_Release(anti);
IMoniker_Release(moniker);
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=64075
Your paranoid android.
=== debian10 (32 bit Chinese:China report) ===
ole32: clipboard.c:1051: Test failed: OleIsCurrentClipboard returned 0 clipboard.c:1119: Test failed: 1 WM_DRAWCLIPBOARD received
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/ole32/itemmoniker.c | 14 ++++++-------- dlls/ole32/tests/moniker.c | 6 +----- 2 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/dlls/ole32/itemmoniker.c b/dlls/ole32/itemmoniker.c index 19876aa363..78b23ae633 100644 --- a/dlls/ole32/itemmoniker.c +++ b/dlls/ole32/itemmoniker.c @@ -518,7 +518,7 @@ static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface, IMoniker** ppmkComposite) { HRESULT res=S_OK; - DWORD mkSys,mkSys2; + DWORD mkSys,mkSys2, order; IEnumMoniker* penumMk=0; IMoniker *pmostLeftMk=0; IMoniker* tempMkComposite=0; @@ -530,16 +530,14 @@ static HRESULT WINAPI ItemMonikerImpl_ComposeWith(IMoniker* iface,
*ppmkComposite=0;
- IMoniker_IsSystemMoniker(pmkRight,&mkSys); - - /* If pmkRight is an anti-moniker, the returned moniker is NULL */ - if(mkSys==MKSYS_ANTIMONIKER) - return res; - + if (is_anti_moniker(pmkRight, &order)) + { + return order > 1 ? create_anti_moniker(order - 1, ppmkComposite) : S_OK; + } else /* if pmkRight is a composite whose leftmost component is an anti-moniker, */ /* the returned moniker is the composite after the leftmost anti-moniker is removed. */ - + IMoniker_IsSystemMoniker(pmkRight,&mkSys); if(mkSys==MKSYS_GENERICCOMPOSITE){
res=IMoniker_Enum(pmkRight,TRUE,&penumMk); diff --git a/dlls/ole32/tests/moniker.c b/dlls/ole32/tests/moniker.c index 61aa0b4a96..ea1e5b1933 100644 --- a/dlls/ole32/tests/moniker.c +++ b/dlls/ole32/tests/moniker.c @@ -2414,16 +2414,12 @@ todo_wine anti = create_antimoniker(2); hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2); ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr); -todo_wine - ok(!!moniker2, "Unexpected pointer.\n"); -if (moniker2) -{ TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER); hr = IMoniker_Hash(moniker2, &hash); ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr); ok(hash == 0x80000001, "Unexpected hash.\n"); IMoniker_Release(moniker2); -} + IMoniker_Release(anti);
IMoniker_Release(moniker);