From 292774d95c294fa76cfe3959c94e57ec15cbb320 Mon Sep 17 00:00:00 2001 From: Nikolay Sivov Date: Wed, 29 Jan 2020 16:57:01 +0300 Subject: [PATCH] ole32/tests: Add some ComposeWith() tests with antimoniker at the right side. Signed-off-by: Nikolay Sivov Signed-off-by: Alexandre Julliard --- 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 0e6f2677c50..f5f69870bfa 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); }