ole32/tests: Add a test for IBindCtx::GetRunningObjectTable().
[wine.git] / dlls / ole32 / tests / moniker.c
blobdf4b5c7bc881ff9e6391d46d6273500587b4a187
1 /*
2 * Moniker Tests
4 * Copyright 2004 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define _WIN32_DCOM
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "ocidl.h"
32 #include "comcat.h"
33 #include "olectl.h"
34 #include "initguid.h"
36 #include "wine/test.h"
37 #include "wine/heap.h"
39 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
41 #define CHECK_EXPECTED_METHOD(method_name) \
42 do { \
43 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
44 if (*expected_method_list) \
45 { \
46 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
47 *expected_method_list, method_name); \
48 expected_method_list++; \
49 } \
50 } while(0)
52 static char const * const *expected_method_list;
53 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
54 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
56 static const CLSID CLSID_TestMoniker =
57 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
58 0xb306bfbc,
59 0x496e,
60 0x4f53,
61 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
64 DEFINE_OLEGUID(CLSID_FileMoniker, 0x303, 0, 0);
65 DEFINE_OLEGUID(CLSID_ItemMoniker, 0x304, 0, 0);
66 DEFINE_OLEGUID(CLSID_AntiMoniker, 0x305, 0, 0);
67 DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x309, 0, 0);
68 DEFINE_OLEGUID(CLSID_ClassMoniker, 0x31a, 0, 0);
69 DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0);
71 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
72 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
74 ULONG refcount;
75 IUnknown_AddRef(obj);
76 refcount = IUnknown_Release(obj);
77 ok_(__FILE__, line)(refcount == ref, "Unexpected got %u.\n", refcount);
80 #define TEST_MONIKER_TYPE_TODO(m,t) _test_moniker_type(m, t, TRUE, __LINE__)
81 #define TEST_MONIKER_TYPE(m,t) _test_moniker_type(m, t, FALSE, __LINE__)
82 static void _test_moniker_type(IMoniker *moniker, DWORD type, BOOL todo, int line)
84 DWORD type2;
85 HRESULT hr;
87 hr = IMoniker_IsSystemMoniker(moniker, &type2);
88 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#x.\n", hr);
89 todo_wine_if(todo)
90 ok_(__FILE__, line)(type2 == type, "Unexpected moniker type %d.\n", type2);
93 #define TEST_DISPLAY_NAME(m,name) _test_moniker_name(m, name, __LINE__)
94 static void _test_moniker_name(IMoniker *moniker, const WCHAR *name, int line)
96 WCHAR *display_name;
97 IBindCtx *pbc;
98 HRESULT hr;
100 hr = CreateBindCtx(0, &pbc);
101 ok_(__FILE__, line)(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
103 hr = IMoniker_GetDisplayName(moniker, pbc, NULL, &display_name);
104 ok_(__FILE__, line)(hr == S_OK, "Failed to get display name, hr %#x.\n", hr);
105 ok_(__FILE__, line)(!lstrcmpW(display_name, name), "Unexpected display name %s.\n", wine_dbgstr_w(display_name));
107 CoTaskMemFree(display_name);
108 IBindCtx_Release(pbc);
111 static IMoniker *create_antimoniker(DWORD level)
113 LARGE_INTEGER pos;
114 IMoniker *moniker;
115 IStream *stream;
116 HRESULT hr;
118 hr = CreateAntiMoniker(&moniker);
119 ok(hr == S_OK, "Failed to create antimoniker, hr %#x.\n", hr);
121 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
122 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
124 hr = IStream_Write(stream, &level, sizeof(level), NULL);
125 ok(hr == S_OK, "Failed to write contents, hr %#x.\n", hr);
127 pos.QuadPart = 0;
128 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
129 ok(hr == S_OK, "Failed to rewind, hr %#x.\n", hr);
131 hr = IMoniker_Load(moniker, stream);
132 ok(hr == S_OK, "Failed to load, hr %#x.\n", hr);
134 IStream_Release(stream);
136 return moniker;
139 static SIZE_T round_global_size(SIZE_T size)
141 static SIZE_T global_size_alignment = -1;
142 if (global_size_alignment == -1)
144 void *p = GlobalAlloc(GMEM_FIXED, 1);
145 global_size_alignment = GlobalSize(p);
146 GlobalFree(p);
149 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
152 struct test_factory
154 IClassFactory IClassFactory_iface;
155 IExternalConnection IExternalConnection_iface;
156 LONG refcount;
157 unsigned int external_connections;
160 static struct test_factory *impl_from_IClassFactory(IClassFactory *iface)
162 return CONTAINING_RECORD(iface, struct test_factory, IClassFactory_iface);
165 static struct test_factory *impl_from_IExternalConnection(IExternalConnection *iface)
167 return CONTAINING_RECORD(iface, struct test_factory, IExternalConnection_iface);
170 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
172 ok(0, "unexpected call\n");
173 *ppv = NULL;
174 return E_NOINTERFACE;
177 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
179 struct test_factory *factory = impl_from_IExternalConnection(iface);
180 return IClassFactory_AddRef(&factory->IClassFactory_iface);
183 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
185 struct test_factory *factory = impl_from_IExternalConnection(iface);
186 return IClassFactory_Release(&factory->IClassFactory_iface);
189 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
191 struct test_factory *factory = impl_from_IExternalConnection(iface);
192 ok(extconn == EXTCONN_STRONG, "Unexpected connection type %d\n", extconn);
193 ok(!reserved, "reserved = %x\n", reserved);
194 return ++factory->external_connections;
197 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
198 DWORD reserved, BOOL fLastReleaseCloses)
200 struct test_factory *factory = impl_from_IExternalConnection(iface);
201 ok(extconn == EXTCONN_STRONG, "Unexpected connection type %d\n", extconn);
202 ok(!reserved, "reserved = %x\n", reserved);
203 return --factory->external_connections;
206 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
207 ExternalConnection_QueryInterface,
208 ExternalConnection_AddRef,
209 ExternalConnection_Release,
210 ExternalConnection_AddConnection,
211 ExternalConnection_ReleaseConnection
214 static HRESULT WINAPI test_factory_QueryInterface(IClassFactory *iface, REFIID riid, void **obj)
216 struct test_factory *factory = impl_from_IClassFactory(iface);
218 if (!obj) return E_POINTER;
220 if (IsEqualGUID(riid, &IID_IUnknown) ||
221 IsEqualGUID(riid, &IID_IClassFactory))
223 *obj = iface;
225 else if (IsEqualGUID(riid, &IID_IExternalConnection))
227 *obj = &factory->IExternalConnection_iface;
229 else
231 *obj = NULL;
232 return E_NOINTERFACE;
235 IUnknown_AddRef((IUnknown *)*obj);
236 return S_OK;
239 static ULONG WINAPI test_factory_AddRef(IClassFactory *iface)
241 struct test_factory *factory = impl_from_IClassFactory(iface);
242 return InterlockedIncrement(&factory->refcount);
245 static ULONG WINAPI test_factory_Release(IClassFactory *iface)
247 struct test_factory *factory = impl_from_IClassFactory(iface);
248 return InterlockedDecrement(&factory->refcount);
251 static HRESULT WINAPI test_factory_CreateInstance(IClassFactory *iface, IUnknown *outer,
252 REFIID riid, void **obj)
254 return E_NOTIMPL;
257 static HRESULT WINAPI test_factory_LockServer(IClassFactory *iface, BOOL lock)
259 return S_OK;
262 static const IClassFactoryVtbl test_factory_vtbl =
264 test_factory_QueryInterface,
265 test_factory_AddRef,
266 test_factory_Release,
267 test_factory_CreateInstance,
268 test_factory_LockServer
271 static void test_factory_init(struct test_factory *factory)
273 factory->IClassFactory_iface.lpVtbl = &test_factory_vtbl;
274 factory->IExternalConnection_iface.lpVtbl = &ExternalConnectionVtbl;
275 factory->refcount = 1;
276 factory->external_connections = 0;
279 typedef struct
281 IUnknown IUnknown_iface;
282 ULONG refs;
283 } HeapUnknown;
285 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
287 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
290 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
292 if (IsEqualIID(riid, &IID_IUnknown))
294 IUnknown_AddRef(iface);
295 *ppv = iface;
296 return S_OK;
298 *ppv = NULL;
299 return E_NOINTERFACE;
302 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
304 HeapUnknown *This = impl_from_IUnknown(iface);
305 return InterlockedIncrement((LONG*)&This->refs);
308 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
310 HeapUnknown *This = impl_from_IUnknown(iface);
311 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
312 if (!refs) HeapFree(GetProcessHeap(), 0, This);
313 return refs;
316 static const IUnknownVtbl HeapUnknown_Vtbl =
318 HeapUnknown_QueryInterface,
319 HeapUnknown_AddRef,
320 HeapUnknown_Release
323 struct test_moniker
325 IMoniker IMoniker_iface;
326 IROTData IROTData_iface;
327 IOleItemContainer IOleItemContainer_iface;
328 IParseDisplayName IParseDisplayName_iface;
329 LONG refcount;
331 BOOL no_IROTData;
334 static struct test_moniker *impl_from_IMoniker(IMoniker *iface)
336 return CONTAINING_RECORD(iface, struct test_moniker, IMoniker_iface);
339 static struct test_moniker *impl_from_IROTData(IROTData *iface)
341 return CONTAINING_RECORD(iface, struct test_moniker, IROTData_iface);
344 static struct test_moniker *impl_from_IOleItemContainer(IOleItemContainer *iface)
346 return CONTAINING_RECORD(iface, struct test_moniker, IOleItemContainer_iface);
349 static struct test_moniker *impl_from_IParseDisplayName(IParseDisplayName *iface)
351 return CONTAINING_RECORD(iface, struct test_moniker, IParseDisplayName_iface);
354 static HRESULT WINAPI test_moniker_parse_QueryInterface(IParseDisplayName *iface, REFIID riid, void **obj)
356 if (IsEqualIID(riid, &IID_IUnknown) ||
357 IsEqualIID(riid, &IID_IParseDisplayName))
359 *obj = iface;
360 IParseDisplayName_AddRef(iface);
361 return S_OK;
364 *obj = NULL;
365 return E_NOINTERFACE;
368 static ULONG WINAPI test_moniker_parse_AddRef(IParseDisplayName *iface)
370 struct test_moniker *moniker = impl_from_IParseDisplayName(iface);
371 return IMoniker_AddRef(&moniker->IMoniker_iface);
374 static ULONG WINAPI test_moniker_parse_Release(IParseDisplayName *iface)
376 struct test_moniker *moniker = impl_from_IParseDisplayName(iface);
377 return IMoniker_Release(&moniker->IMoniker_iface);
380 static HRESULT WINAPI test_moniker_parse_ParseDisplayName(IParseDisplayName *iface,
381 IBindCtx *pbc, LPOLESTR displayname, ULONG *eaten, IMoniker **out)
383 return E_NOTIMPL;
386 static const IParseDisplayNameVtbl test_moniker_parse_vtbl =
388 test_moniker_parse_QueryInterface,
389 test_moniker_parse_AddRef,
390 test_moniker_parse_Release,
391 test_moniker_parse_ParseDisplayName,
394 static HRESULT WINAPI test_item_container_QueryInterface(IOleItemContainer *iface, REFIID riid, void **obj)
396 if (IsEqualIID(riid, &IID_IOleItemContainer) ||
397 IsEqualIID(riid, &IID_IOleContainer) ||
398 IsEqualIID(riid, &IID_IParseDisplayName) ||
399 IsEqualIID(riid, &IID_IUnknown))
401 *obj = iface;
402 IOleItemContainer_AddRef(iface);
403 return S_OK;
406 *obj = NULL;
407 return E_NOINTERFACE;
410 static ULONG WINAPI test_item_container_AddRef(IOleItemContainer *iface)
412 struct test_moniker *moniker = impl_from_IOleItemContainer(iface);
413 return IMoniker_AddRef(&moniker->IMoniker_iface);
416 static ULONG WINAPI test_item_container_Release(IOleItemContainer *iface)
418 struct test_moniker *moniker = impl_from_IOleItemContainer(iface);
419 return IMoniker_Release(&moniker->IMoniker_iface);
422 static HRESULT WINAPI test_item_container_ParseDisplayName(IOleItemContainer *iface,
423 IBindCtx *pbc, LPOLESTR displayname, ULONG *eaten, IMoniker **out)
425 return E_NOTIMPL;
428 static HRESULT WINAPI test_item_container_EnumObjects(IOleItemContainer *iface, DWORD flags,
429 IEnumUnknown **ppenum)
431 return E_NOTIMPL;
434 static HRESULT WINAPI test_item_container_LockContainer(IOleItemContainer *iface, BOOL lock)
436 return S_OK;
439 static HRESULT WINAPI test_item_container_GetObject(IOleItemContainer *iface, LPOLESTR item,
440 DWORD bind_speed, IBindCtx *pbc, REFIID riid, void **obj)
442 struct test_moniker *moniker = impl_from_IOleItemContainer(iface);
444 if (IsEqualIID(riid, &IID_IParseDisplayName))
446 *obj = &moniker->IParseDisplayName_iface;
447 IOleItemContainer_AddRef(iface);
450 return 0x8bee0000 | bind_speed;
453 static HRESULT WINAPI test_item_container_GetObjectStorage(IOleItemContainer *iface, LPOLESTR item,
454 IBindCtx *pbc, REFIID riid, void **obj)
456 return 0x8bee0001;
459 static HRESULT WINAPI test_item_container_IsRunning(IOleItemContainer *iface, LPOLESTR item)
461 ok(0, "Unexpected call.\n");
462 return E_NOTIMPL;
465 static const IOleItemContainerVtbl test_item_container_vtbl =
467 test_item_container_QueryInterface,
468 test_item_container_AddRef,
469 test_item_container_Release,
470 test_item_container_ParseDisplayName,
471 test_item_container_EnumObjects,
472 test_item_container_LockContainer,
473 test_item_container_GetObject,
474 test_item_container_GetObjectStorage,
475 test_item_container_IsRunning,
478 static HRESULT WINAPI
479 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
481 struct test_moniker *moniker = impl_from_IMoniker(iface);
483 if (!ppvObject)
484 return E_INVALIDARG;
486 *ppvObject = 0;
488 if (IsEqualIID(&IID_IUnknown, riid) ||
489 IsEqualIID(&IID_IPersist, riid) ||
490 IsEqualIID(&IID_IPersistStream,riid) ||
491 IsEqualIID(&IID_IMoniker, riid))
492 *ppvObject = iface;
493 if (IsEqualIID(&IID_IROTData, riid))
495 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
496 if (!moniker->no_IROTData)
497 *ppvObject = &moniker->IROTData_iface;
500 if ((*ppvObject)==0)
501 return E_NOINTERFACE;
503 IMoniker_AddRef(iface);
505 return S_OK;
508 static ULONG WINAPI
509 Moniker_AddRef(IMoniker* iface)
511 struct test_moniker *moniker = impl_from_IMoniker(iface);
512 return InterlockedIncrement(&moniker->refcount);
515 static ULONG WINAPI
516 Moniker_Release(IMoniker* iface)
518 struct test_moniker *moniker = impl_from_IMoniker(iface);
519 ULONG refcount = InterlockedDecrement(&moniker->refcount);
521 if (!refcount)
522 heap_free(moniker);
524 return refcount;
527 static HRESULT WINAPI
528 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
530 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
532 *pClassID = CLSID_TestMoniker;
534 return S_OK;
537 static HRESULT WINAPI
538 Moniker_IsDirty(IMoniker* iface)
540 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
542 return S_FALSE;
545 static HRESULT WINAPI
546 Moniker_Load(IMoniker* iface, IStream* pStm)
548 CHECK_EXPECTED_METHOD("Moniker_Load");
549 return E_NOTIMPL;
552 static HRESULT WINAPI
553 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
555 CHECK_EXPECTED_METHOD("Moniker_Save");
556 return E_NOTIMPL;
559 static HRESULT WINAPI
560 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
562 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
563 return E_NOTIMPL;
566 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid,
567 void **obj)
569 struct test_moniker *moniker = impl_from_IMoniker(iface);
571 if (IsEqualIID(riid, &IID_IOleItemContainer))
573 *obj = &moniker->IOleItemContainer_iface;
574 IMoniker_AddRef(iface);
575 return S_OK;
578 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
579 return E_NOTIMPL;
582 static HRESULT WINAPI
583 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
584 REFIID riid, VOID** ppvObject)
586 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
587 return E_NOTIMPL;
590 static HRESULT WINAPI
591 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
592 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
594 CHECK_EXPECTED_METHOD("Moniker_Reduce");
596 if (ppmkReduced==NULL)
597 return E_POINTER;
599 IMoniker_AddRef(iface);
601 *ppmkReduced=iface;
603 return MK_S_REDUCED_TO_SELF;
606 static HRESULT WINAPI
607 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
608 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
610 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
611 return E_NOTIMPL;
614 static HRESULT WINAPI
615 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
617 CHECK_EXPECTED_METHOD("Moniker_Enum");
619 if (ppenumMoniker == NULL)
620 return E_POINTER;
622 *ppenumMoniker = NULL;
624 return S_OK;
627 static HRESULT WINAPI
628 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
630 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
631 return E_NOTIMPL;
634 static HRESULT WINAPI
635 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
637 CHECK_EXPECTED_METHOD("Moniker_Hash");
638 return E_NOTIMPL;
641 static HRESULT WINAPI
642 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
643 IMoniker* pmkNewlyRunning)
645 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
646 return 0x8beef000;
649 static HRESULT WINAPI
650 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
651 IMoniker* pmkToLeft, FILETIME* pFileTime)
653 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
654 return E_NOTIMPL;
657 static HRESULT WINAPI
658 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
660 CHECK_EXPECTED_METHOD("Moniker_Inverse");
661 return E_NOTIMPL;
664 static HRESULT WINAPI
665 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
667 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
668 return E_NOTIMPL;
671 static HRESULT WINAPI
672 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
674 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
675 return E_NOTIMPL;
678 static HRESULT WINAPI
679 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
680 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
682 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
683 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
684 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
685 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
686 return S_OK;
689 static HRESULT WINAPI
690 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
691 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
693 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
694 return E_NOTIMPL;
697 static HRESULT WINAPI
698 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
700 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
702 if (!pwdMksys)
703 return E_POINTER;
705 (*pwdMksys)=MKSYS_NONE;
707 return S_FALSE;
710 static HRESULT WINAPI
711 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
713 struct test_moniker *moniker = impl_from_IROTData(iface);
714 return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppvObject);
717 static ULONG WINAPI
718 ROTData_AddRef(IROTData *iface)
720 struct test_moniker *moniker = impl_from_IROTData(iface);
721 return IMoniker_AddRef(&moniker->IMoniker_iface);
724 static ULONG WINAPI
725 ROTData_Release(IROTData* iface)
727 struct test_moniker *moniker = impl_from_IROTData(iface);
728 return IMoniker_Release(&moniker->IMoniker_iface);
731 static HRESULT WINAPI
732 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
733 ULONG cbMax, ULONG* pcbData)
735 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
737 *pcbData = 1;
738 if (cbMax < *pcbData)
739 return E_OUTOFMEMORY;
741 *pbData = 0xde;
743 return S_OK;
746 static IROTDataVtbl ROTDataVtbl =
748 ROTData_QueryInterface,
749 ROTData_AddRef,
750 ROTData_Release,
751 ROTData_GetComparisonData
754 static const IMonikerVtbl MonikerVtbl =
756 Moniker_QueryInterface,
757 Moniker_AddRef,
758 Moniker_Release,
759 Moniker_GetClassID,
760 Moniker_IsDirty,
761 Moniker_Load,
762 Moniker_Save,
763 Moniker_GetSizeMax,
764 Moniker_BindToObject,
765 Moniker_BindToStorage,
766 Moniker_Reduce,
767 Moniker_ComposeWith,
768 Moniker_Enum,
769 Moniker_IsEqual,
770 Moniker_Hash,
771 Moniker_IsRunning,
772 Moniker_GetTimeOfLastChange,
773 Moniker_Inverse,
774 Moniker_CommonPrefixWith,
775 Moniker_RelativePathTo,
776 Moniker_GetDisplayName,
777 Moniker_ParseDisplayName,
778 Moniker_IsSystemMoniker
781 static struct test_moniker *create_test_moniker(void)
783 struct test_moniker *obj;
785 obj = heap_alloc_zero(sizeof(*obj));
786 obj->IMoniker_iface.lpVtbl = &MonikerVtbl;
787 obj->IROTData_iface.lpVtbl = &ROTDataVtbl;
788 obj->IOleItemContainer_iface.lpVtbl = &test_item_container_vtbl;
789 obj->IParseDisplayName_iface.lpVtbl = &test_moniker_parse_vtbl;
790 obj->refcount = 1;
792 return obj;
795 static void test_ROT(void)
797 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
798 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
799 '2','0','4','6','E','5','8','6','C','9','2','5',0};
800 HRESULT hr;
801 IMoniker *pMoniker = NULL;
802 struct test_moniker *test_moniker;
803 IRunningObjectTable *pROT = NULL;
804 struct test_factory factory;
805 DWORD dwCookie;
806 static const char *methods_register_no_ROTData[] =
808 "Moniker_Reduce",
809 "Moniker_GetTimeOfLastChange",
810 "Moniker_QueryInterface(IID_IROTData)",
811 "Moniker_GetDisplayName",
812 "Moniker_GetClassID",
813 NULL
815 static const char *methods_register[] =
817 "Moniker_Reduce",
818 "Moniker_GetTimeOfLastChange",
819 "Moniker_QueryInterface(IID_IROTData)",
820 "ROTData_GetComparisonData",
821 NULL
823 static const char *methods_isrunning_no_ROTData[] =
825 "Moniker_Reduce",
826 "Moniker_QueryInterface(IID_IROTData)",
827 "Moniker_GetDisplayName",
828 "Moniker_GetClassID",
829 NULL
831 static const char *methods_isrunning[] =
833 "Moniker_Reduce",
834 "Moniker_QueryInterface(IID_IROTData)",
835 "ROTData_GetComparisonData",
836 NULL
839 test_factory_init(&factory);
841 hr = GetRunningObjectTable(0, &pROT);
842 ok_ole_success(hr, GetRunningObjectTable);
844 test_moniker = create_test_moniker();
845 test_moniker->no_IROTData = TRUE;
847 expected_method_list = methods_register_no_ROTData;
848 /* try with our own moniker that doesn't support IROTData */
849 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE, (IUnknown *)&factory.IClassFactory_iface,
850 &test_moniker->IMoniker_iface, &dwCookie);
851 ok(hr == S_OK, "Failed to register interface, hr %#x.\n", hr);
852 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
853 ok(factory.external_connections == 1, "external_connections = %d\n", factory.external_connections);
854 ok(factory.refcount > 1, "Unexpected factory refcount %u.\n", factory.refcount);
856 expected_method_list = methods_isrunning_no_ROTData;
857 hr = IRunningObjectTable_IsRunning(pROT, &test_moniker->IMoniker_iface);
858 ok_ole_success(hr, IRunningObjectTable_IsRunning);
859 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
861 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
862 ok_ole_success(hr, IRunningObjectTable_Revoke);
863 ok(!factory.external_connections, "external_connections = %d\n", factory.external_connections);
864 ok(factory.refcount == 1, "Unexpected factory refcount %u.\n", factory.refcount);
866 expected_method_list = methods_register;
867 /* try with our own moniker */
868 test_moniker->no_IROTData = FALSE;
869 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE, (IUnknown *)&factory.IClassFactory_iface,
870 &test_moniker->IMoniker_iface, &dwCookie);
871 ok_ole_success(hr, IRunningObjectTable_Register);
872 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
873 ok(factory.refcount > 1, "Unexpected factory refcount %u.\n", factory.refcount);
875 expected_method_list = methods_isrunning;
876 hr = IRunningObjectTable_IsRunning(pROT, &test_moniker->IMoniker_iface);
877 ok_ole_success(hr, IRunningObjectTable_IsRunning);
878 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
880 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
881 ok_ole_success(hr, IRunningObjectTable_Revoke);
882 ok(factory.refcount == 1, "Unexpected factory refcount %u.\n", factory.refcount);
884 hr = CreateFileMoniker(wszFileName, &pMoniker);
885 ok_ole_success(hr, CreateClassMoniker);
887 /* test flags: 0 */
888 factory.external_connections = 0;
889 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&factory.IClassFactory_iface, pMoniker, &dwCookie);
890 ok_ole_success(hr, IRunningObjectTable_Register);
891 ok(!factory.external_connections, "external_connections = %d\n", factory.external_connections);
892 ok(factory.refcount > 1, "Unexpected factory refcount %u.\n", factory.refcount);
894 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
895 ok_ole_success(hr, IRunningObjectTable_Revoke);
896 ok(factory.refcount == 1, "Unexpected factory refcount %u.\n", factory.refcount);
898 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
899 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE, (IUnknown *)&factory.IClassFactory_iface,
900 pMoniker, &dwCookie);
901 ok_ole_success(hr, IRunningObjectTable_Register);
902 ok(factory.refcount > 1, "Unexpected factory refcount %u.\n", factory.refcount);
904 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
905 ok_ole_success(hr, IRunningObjectTable_Revoke);
906 ok(factory.refcount == 1, "Unexpected factory refcount %u.\n", factory.refcount);
908 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
909 /* only succeeds when process is started by SCM and has LocalService
910 * or RunAs AppId values */
911 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE | ROTFLAGS_ALLOWANYCLIENT,
912 (IUnknown *)&factory.IClassFactory_iface, pMoniker, &dwCookie);
913 todo_wine {
914 ok(hr == CO_E_WRONG_SERVER_IDENTITY, "Unexpected hr %#x.\n", hr);
916 if (SUCCEEDED(hr))
918 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
919 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
922 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef, (IUnknown *)&factory.IClassFactory_iface, pMoniker, &dwCookie);
923 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
925 IMoniker_Release(pMoniker);
926 IMoniker_Release(&test_moniker->IMoniker_iface);
928 IRunningObjectTable_Release(pROT);
931 static void test_ROT_multiple_entries(void)
933 HRESULT hr;
934 IMoniker *pMoniker = NULL;
935 IRunningObjectTable *pROT = NULL;
936 DWORD dwCookie1, dwCookie2;
937 IUnknown *pObject = NULL;
938 static const WCHAR moniker_path[] =
939 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
940 struct test_factory factory;
942 test_factory_init(&factory);
944 hr = GetRunningObjectTable(0, &pROT);
945 ok_ole_success(hr, GetRunningObjectTable);
947 hr = CreateFileMoniker(moniker_path, &pMoniker);
948 ok_ole_success(hr, CreateFileMoniker);
950 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&factory.IClassFactory_iface, pMoniker, &dwCookie1);
951 ok_ole_success(hr, IRunningObjectTable_Register);
953 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&factory.IClassFactory_iface, pMoniker, &dwCookie2);
954 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
956 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
958 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
959 ok_ole_success(hr, IRunningObjectTable_GetObject);
960 IUnknown_Release(pObject);
962 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
963 ok_ole_success(hr, IRunningObjectTable_Revoke);
965 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
966 ok_ole_success(hr, IRunningObjectTable_GetObject);
967 IUnknown_Release(pObject);
969 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
970 ok_ole_success(hr, IRunningObjectTable_Revoke);
972 IMoniker_Release(pMoniker);
974 IRunningObjectTable_Release(pROT);
977 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
979 if (IsEqualIID(riid, &IID_IUnknown) ||
980 IsEqualIID(riid, &IID_IParseDisplayName))
982 *ppv = iface;
983 IParseDisplayName_AddRef(iface);
984 return S_OK;
986 *ppv = NULL;
987 return E_NOINTERFACE;
990 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
992 return 2;
995 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
997 return 1;
1000 static LPCWSTR expected_display_name;
1002 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
1003 IBindCtx *pbc,
1004 LPOLESTR pszDisplayName,
1005 ULONG *pchEaten,
1006 IMoniker **ppmkOut)
1008 char display_nameA[256];
1009 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
1010 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
1011 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
1012 *pchEaten = lstrlenW(pszDisplayName);
1013 return CreateAntiMoniker(ppmkOut);
1016 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
1018 ParseDisplayName_QueryInterface,
1019 ParseDisplayName_AddRef,
1020 ParseDisplayName_Release,
1021 ParseDisplayName_ParseDisplayName
1024 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
1026 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
1028 IMoniker * spMoniker;
1029 int monCnt=0, matchCnt=0;
1031 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
1033 HRESULT hr;
1034 WCHAR * szDisplayn;
1035 monCnt++;
1036 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
1037 if (SUCCEEDED(hr))
1039 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
1040 matchCnt++;
1041 CoTaskMemFree(szDisplayn);
1044 return matchCnt;
1047 static void test_MkParseDisplayName(void)
1049 IBindCtx * pbc = NULL;
1050 HRESULT hr;
1051 IMoniker * pmk = NULL;
1052 IMoniker * pmk1 = NULL;
1053 IMoniker * pmk2 = NULL;
1054 ULONG eaten;
1055 int matchCnt;
1056 IUnknown * object = NULL;
1058 IUnknown *lpEM1;
1060 IEnumMoniker *spEM1 = NULL;
1061 IEnumMoniker *spEM2 = NULL;
1062 IEnumMoniker *spEM3 = NULL;
1064 DWORD pdwReg1=0;
1065 DWORD grflags=0;
1066 DWORD pdwReg2=0;
1067 IRunningObjectTable * pprot=NULL;
1069 /* CLSID of My Computer */
1070 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
1071 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
1072 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
1073 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
1074 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
1075 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
1076 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
1077 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
1078 static const WCHAR wszEmpty[] = {0};
1079 char szDisplayNameFile[256];
1080 WCHAR wszDisplayNameFile[256];
1081 int i, len;
1083 const struct
1085 LPBC *ppbc;
1086 LPCOLESTR szDisplayName;
1087 LPDWORD pchEaten;
1088 LPMONIKER *ppmk;
1089 } invalid_parameters[] =
1091 {NULL, NULL, NULL, NULL},
1092 {NULL, NULL, NULL, &pmk},
1093 {NULL, NULL, &eaten, NULL},
1094 {NULL, NULL, &eaten, &pmk},
1095 {NULL, wszEmpty, NULL, NULL},
1096 {NULL, wszEmpty, NULL, &pmk},
1097 {NULL, wszEmpty, &eaten, NULL},
1098 {NULL, wszEmpty, &eaten, &pmk},
1099 {&pbc, NULL, NULL, NULL},
1100 {&pbc, NULL, NULL, &pmk},
1101 {&pbc, NULL, &eaten, NULL},
1102 {&pbc, NULL, &eaten, &pmk},
1103 {&pbc, wszEmpty, NULL, NULL},
1104 {&pbc, wszEmpty, NULL, &pmk},
1105 {&pbc, wszEmpty, &eaten, NULL},
1106 {&pbc, wszEmpty, &eaten, &pmk},
1108 struct test_factory factory;
1110 test_factory_init(&factory);
1112 hr = CreateBindCtx(0, &pbc);
1113 ok_ole_success(hr, CreateBindCtx);
1115 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++)
1117 eaten = 0xdeadbeef;
1118 pmk = (IMoniker *)0xdeadbeef;
1119 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
1120 invalid_parameters[i].szDisplayName,
1121 invalid_parameters[i].pchEaten,
1122 invalid_parameters[i].ppmk);
1123 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
1124 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
1125 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
1128 eaten = 0xdeadbeef;
1129 pmk = (IMoniker *)0xdeadbeef;
1130 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
1131 todo_wine
1132 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
1133 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1134 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1136 /* no special handling of "clsid:" without the string form of the clsid
1137 * following */
1138 eaten = 0xdeadbeef;
1139 pmk = (IMoniker *)0xdeadbeef;
1140 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
1141 todo_wine
1142 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
1143 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1144 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1146 /* shows clsid has higher precedence than a running object */
1147 hr = CreateFileMoniker(wszDisplayName, &pmk);
1148 ok_ole_success(hr, CreateFileMoniker);
1149 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1150 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
1151 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&factory.IClassFactory_iface, pmk, &pdwReg1);
1152 ok_ole_success(hr, IRunningObjectTable_Register);
1153 IMoniker_Release(pmk);
1154 pmk = NULL;
1155 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
1156 ok_ole_success(hr, MkParseDisplayName);
1157 ok(eaten == ARRAY_SIZE(wszDisplayName) - 1,
1158 "Processed character count should have been 43 instead of %u\n", eaten);
1159 if (pmk)
1161 TEST_MONIKER_TYPE(pmk, MKSYS_CLASSMONIKER);
1162 IMoniker_Release(pmk);
1164 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
1165 ok_ole_success(hr, IRunningObjectTable_Revoke);
1166 IRunningObjectTable_Release(pprot);
1168 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
1169 ok_ole_success(hr, CreateFileMoniker);
1170 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1171 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
1172 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&factory.IClassFactory_iface, pmk, &pdwReg1);
1173 ok_ole_success(hr, IRunningObjectTable_Register);
1174 IMoniker_Release(pmk);
1175 pmk = NULL;
1176 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
1177 ok_ole_success(hr, MkParseDisplayName);
1178 ok(eaten == ARRAY_SIZE(wszDisplayNameRunning) - 1,
1179 "Processed character count should have been 15 instead of %u\n", eaten);
1180 if (pmk)
1182 TEST_MONIKER_TYPE(pmk, MKSYS_FILEMONIKER);
1183 IMoniker_Release(pmk);
1185 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
1186 ok_ole_success(hr, IRunningObjectTable_Revoke);
1187 IRunningObjectTable_Release(pprot);
1189 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
1190 ok_ole_success(hr, CoRegisterClassObject);
1192 expected_display_name = wszDisplayNameProgId1;
1193 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
1194 ok_ole_success(hr, MkParseDisplayName);
1195 ok(eaten == ARRAY_SIZE(wszDisplayNameProgId1) - 1,
1196 "Processed character count should have been 8 instead of %u\n", eaten);
1197 if (pmk)
1199 TEST_MONIKER_TYPE(pmk, MKSYS_ANTIMONIKER);
1200 IMoniker_Release(pmk);
1203 expected_display_name = wszDisplayNameProgId2;
1204 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
1205 ok_ole_success(hr, MkParseDisplayName);
1206 ok(eaten == ARRAY_SIZE(wszDisplayNameProgId2) - 1,
1207 "Processed character count should have been 8 instead of %u\n", eaten);
1208 if (pmk)
1210 TEST_MONIKER_TYPE(pmk, MKSYS_ANTIMONIKER);
1211 IMoniker_Release(pmk);
1214 eaten = 0xdeadbeef;
1215 pmk = (IMoniker *)0xdeadbeef;
1216 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
1217 todo_wine
1218 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
1219 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1220 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1222 hr = CoRevokeClassObject(pdwReg1);
1223 ok_ole_success(hr, CoRevokeClassObject);
1225 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
1226 strcat(szDisplayNameFile, "\\kernel32.dll");
1227 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile,
1228 ARRAY_SIZE(wszDisplayNameFile));
1229 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
1230 ok_ole_success(hr, MkParseDisplayName);
1231 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
1232 if (pmk)
1234 TEST_MONIKER_TYPE(pmk, MKSYS_FILEMONIKER);
1235 IMoniker_Release(pmk);
1238 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
1239 ok_ole_success(hr, MkParseDisplayName);
1240 ok(eaten == ARRAY_SIZE(wszDisplayName) - 1,
1241 "Processed character count should have been 43 instead of %u\n", eaten);
1243 if (pmk)
1245 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
1246 ok_ole_success(hr, IMoniker_BindToObject);
1248 if (SUCCEEDED(hr))
1249 IUnknown_Release(object);
1250 IMoniker_Release(pmk);
1252 IBindCtx_Release(pbc);
1254 /* Test the EnumMoniker interface */
1255 hr = CreateBindCtx(0, &pbc);
1256 ok_ole_success(hr, CreateBindCtx);
1258 hr = CreateFileMoniker(wszFileName1, &pmk1);
1259 ok(hr == S_OK, "Failed to create file moniker, hr %#x.\n", hr);
1260 hr = CreateFileMoniker(wszFileName2, &pmk2);
1261 ok(hr == S_OK, "Failed to create file moniker, hr %#x.\n", hr);
1262 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1263 ok(hr == S_OK, "Failed to get ROT, hr %#x.\n", hr);
1265 /* Check EnumMoniker before registering */
1266 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1267 ok(hr == S_OK, "Failed to get enum object, hr %#x.\n", hr);
1268 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void *)&lpEM1);
1269 /* Register a couple of Monikers and check is ok */
1270 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
1272 matchCnt = count_moniker_matches(pbc, spEM1);
1274 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1275 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1276 ok(hr == S_OK, "Failed to register object, hr %#x.\n", hr);
1278 grflags=0;
1279 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1280 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1281 ok(hr == S_OK, "Failed to register object, hr %#x.\n", hr);
1283 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1284 ok(hr == S_OK, "Failed to get enum object, hr %#x.\n", hr);
1286 matchCnt = count_moniker_matches(pbc, spEM2);
1287 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1289 IEnumMoniker_Clone(spEM2, &spEM3);
1291 matchCnt = count_moniker_matches(pbc, spEM3);
1292 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1293 IEnumMoniker_Reset(spEM3);
1295 matchCnt = count_moniker_matches(pbc, spEM3);
1296 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1298 hr = IRunningObjectTable_Revoke(pprot,pdwReg1);
1299 ok(hr == S_OK, "Failed to revoke, hr %#x.\n", hr);
1300 hr = IRunningObjectTable_Revoke(pprot,pdwReg2);
1301 ok(hr == S_OK, "Failed to revoke, hr %#x.\n", hr);
1302 IUnknown_Release(lpEM1);
1303 IEnumMoniker_Release(spEM1);
1304 IEnumMoniker_Release(spEM2);
1305 IEnumMoniker_Release(spEM3);
1306 IMoniker_Release(pmk1);
1307 IMoniker_Release(pmk2);
1308 IRunningObjectTable_Release(pprot);
1310 IBindCtx_Release(pbc);
1313 static const LARGE_INTEGER llZero;
1315 static const BYTE expected_class_moniker_marshal_data[] =
1317 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1318 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1319 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1320 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1321 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1322 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1323 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1324 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1325 0x00,0x00,0x00,0x00,
1328 static const BYTE expected_class_moniker_saved_data[] =
1330 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1331 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1332 0x00,0x00,0x00,0x00,
1335 static const BYTE expected_class_moniker_comparison_data[] =
1337 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1338 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1339 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1340 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1343 static const WCHAR expected_class_moniker_display_name[] =
1345 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1346 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1347 '0','0','0','0','4','6',':',0
1350 static const BYTE expected_item_moniker_comparison_data[] =
1352 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1353 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1354 '!',0x00, 'T',0x00, 'E',0x00, 'S',0x00,
1355 'T',0x00,0x00,0x00,
1358 static const BYTE expected_item_moniker_comparison_data2[] =
1360 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1361 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1362 'T',0x00, 'E',0x00, 'S',0x00, 'T',0x00,
1363 0x00,0x00,
1366 static const BYTE expected_item_moniker_comparison_data4[] =
1368 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1369 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1370 '&',0x00, '&',0x00, 'T',0x00, 'E',0x00,
1371 'S',0x00, 'T',0x00,0x00,0x00,
1374 static const BYTE expected_item_moniker_comparison_data5[] =
1376 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1377 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1378 'A',0x00, 'B',0x00, 'T',0x00, 'E',0x00,
1379 'S',0x00, 'T',0x00,0x00,0x00,
1382 static const BYTE expected_item_moniker_comparison_data6[] =
1384 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1385 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1386 0x00,0x00,
1389 static const BYTE expected_item_moniker_saved_data[] =
1391 0x02,0x00,0x00,0x00, '!',0x00,0x05,0x00,
1392 0x00,0x00, 'T', 'e', 's', 't',0x00,
1395 static const BYTE expected_item_moniker_saved_data2[] =
1397 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
1398 'T', 'e', 's', 't',0x00,
1401 static const BYTE expected_item_moniker_saved_data3[] =
1403 0x01,0x00,0x00,0x00,0x00,0x05,0x00,0x00,
1404 0x00,'T', 'e', 's', 't',0x00,
1407 static const BYTE expected_item_moniker_saved_data4[] =
1409 0x03,0x00,0x00,0x00, '&', '&',0x00,0x05,
1410 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1413 static const BYTE expected_item_moniker_saved_data5[] =
1415 0x03,0x00,0x00,0x00, 'a', 'b',0x00,0x05,
1416 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1419 static const BYTE expected_item_moniker_saved_data6[] =
1421 0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
1422 0x00,0x00,
1425 static const BYTE expected_item_moniker_marshal_data[] =
1427 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1428 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1429 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1430 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1431 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1432 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1433 0x02,0x00,0x00,0x00, '!',0x00,0x05,0x00,
1434 0x00,0x00, 'T', 'e', 's', 't',0x00,
1437 static const BYTE expected_item_moniker_marshal_data2[] =
1439 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1440 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1441 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1442 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1443 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1444 0x00,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,
1445 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
1446 'T', 'e', 's', 't',0x00,
1449 static const BYTE expected_item_moniker_marshal_data3[] =
1451 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1452 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1453 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1454 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1455 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1456 0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x00,
1457 0x01,0x00,0x00,0x00,0x00,0x05,0x00,0x00,
1458 0x00, 'T', 'e', 's', 't',0x00,
1461 static const BYTE expected_item_moniker_marshal_data4[] =
1463 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1464 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1465 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1466 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1467 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1468 0x00,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,
1469 0x03,0x00,0x00,0x00, '&', '&',0x00,0x05,
1470 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1473 static const BYTE expected_item_moniker_marshal_data5[] =
1475 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1476 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1477 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1478 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1479 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1480 0x00,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,
1481 0x03,0x00,0x00,0x00, 'a', 'b',0x00,0x05,
1482 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1485 static const BYTE expected_item_moniker_marshal_data6[] =
1487 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1488 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1489 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1490 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1491 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1492 0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,
1493 0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
1494 0x00,0x00,
1497 static const BYTE expected_anti_moniker_marshal_data[] =
1499 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1500 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1501 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1502 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1503 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1504 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1505 0x01,0x00,0x00,0x00,
1508 static const BYTE expected_anti_moniker_marshal_data2[] =
1510 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1511 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1512 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1513 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1514 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1515 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1516 0x02,0x00,0x00,0x00,
1519 static const BYTE expected_anti_moniker_saved_data[] =
1521 0x01,0x00,0x00,0x00,
1524 static const BYTE expected_anti_moniker_saved_data2[] =
1526 0x02,0x00,0x00,0x00,
1529 static const BYTE expected_anti_moniker_comparison_data[] =
1531 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1532 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1533 0x01,0x00,0x00,0x00,
1536 static const BYTE expected_anti_moniker_comparison_data2[] =
1538 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1539 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1540 0x02,0x00,0x00,0x00,
1543 static const BYTE expected_gc_moniker_marshal_data[] =
1545 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1546 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1547 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1548 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1549 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1550 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1551 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1552 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1553 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1554 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1555 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1556 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1557 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1558 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1559 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1560 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1561 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1562 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1563 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1564 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1565 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1566 0x00,0x57,0x69,0x6e,0x65,0x00,
1569 static const BYTE expected_gc_moniker_saved_data[] =
1571 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1572 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1573 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1574 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1575 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1576 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1577 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1578 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1579 0x65,0x00,
1582 static const BYTE expected_gc_moniker_comparison_data[] =
1584 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1585 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1586 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1587 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1588 '!',0x00, 'T',0x00, 'E',0x00, 'S',0x00,
1589 'T',0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1590 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1591 0x00,0x00,0x00,0x46, '#',0x00, 'W',0x00,
1592 'I',0x00, 'N',0x00, 'E',0x00,0x00,0x00,
1595 static void test_moniker(
1596 const char *testname, IMoniker *moniker,
1597 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1598 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1599 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1600 int expected_max_size, LPCWSTR expected_display_name)
1602 ULARGE_INTEGER max_size;
1603 IStream * stream;
1604 IROTData * rotdata;
1605 HRESULT hr;
1606 HGLOBAL hglobal;
1607 LPBYTE moniker_data;
1608 DWORD moniker_size;
1609 DWORD i, moniker_type;
1610 BOOL same;
1611 BYTE buffer[128];
1612 IMoniker * moniker_proxy;
1614 hr = IMoniker_IsDirty(moniker);
1615 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1617 /* Display Name */
1618 TEST_DISPLAY_NAME(moniker, expected_display_name);
1620 hr = IMoniker_IsDirty(moniker);
1621 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1623 /* IROTData::GetComparisonData test */
1625 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1626 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1628 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1629 ok_ole_success(hr, IROTData_GetComparisonData);
1631 if (hr != S_OK) moniker_size = 0;
1633 /* first check we have the right amount of data */
1634 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1635 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1636 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1638 /* then do a byte-by-byte comparison */
1639 same = TRUE;
1640 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1642 if (expected_moniker_comparison_data[i] != buffer[i])
1644 same = FALSE;
1645 break;
1649 ok(same, "%s: Comparison data differs\n", testname);
1650 if (!same)
1652 for (i = 0; i < moniker_size; i++)
1654 if (i % 8 == 0) printf(" ");
1655 printf("0x%02x,", buffer[i]);
1656 if (i % 8 == 7) printf("\n");
1658 printf("\n");
1661 IROTData_Release(rotdata);
1663 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1664 ok_ole_success(hr, CreateStreamOnHGlobal);
1666 /* Saving */
1667 moniker_type = 0;
1668 IMoniker_IsSystemMoniker(moniker, &moniker_type);
1670 hr = IMoniker_GetSizeMax(moniker, &max_size);
1671 ok(hr == S_OK, "Failed to get max size, hr %#x.\n", hr);
1672 todo_wine_if(moniker_type == MKSYS_GENERICCOMPOSITE)
1673 ok(expected_max_size == max_size.u.LowPart, "%s: unexpected max size %u.\n", testname, max_size.u.LowPart);
1675 hr = IMoniker_Save(moniker, stream, TRUE);
1676 ok_ole_success(hr, IMoniker_Save);
1678 hr = GetHGlobalFromStream(stream, &hglobal);
1679 ok_ole_success(hr, GetHGlobalFromStream);
1681 moniker_size = GlobalSize(hglobal);
1683 moniker_data = GlobalLock(hglobal);
1685 /* first check we have the right amount of data */
1686 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1687 "%s: Size of saved data differs (expected %d, actual %d)\n",
1688 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1690 /* then do a byte-by-byte comparison */
1691 same = TRUE;
1692 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1694 if (expected_moniker_saved_data[i] != moniker_data[i])
1696 same = FALSE;
1697 break;
1701 ok(same, "%s: Saved data differs\n", testname);
1702 if (!same)
1704 for (i = 0; i < moniker_size; i++)
1706 if (i % 8 == 0) printf(" ");
1707 printf("0x%02x,", moniker_data[i]);
1708 if (i % 8 == 7) printf("\n");
1710 printf("\n");
1713 GlobalUnlock(hglobal);
1715 IStream_Release(stream);
1717 /* Marshaling tests */
1719 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1720 ok_ole_success(hr, CreateStreamOnHGlobal);
1722 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1723 ok_ole_success(hr, CoMarshalInterface);
1725 hr = GetHGlobalFromStream(stream, &hglobal);
1726 ok_ole_success(hr, GetHGlobalFromStream);
1728 moniker_size = GlobalSize(hglobal);
1730 moniker_data = GlobalLock(hglobal);
1732 /* first check we have the right amount of data */
1733 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1734 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1735 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1737 /* then do a byte-by-byte comparison */
1738 same = TRUE;
1739 if (expected_moniker_marshal_data)
1741 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1743 if (expected_moniker_marshal_data[i] != moniker_data[i])
1745 same = FALSE;
1746 break;
1751 ok(same, "%s: Marshaled data differs\n", testname);
1752 if (!same)
1754 for (i = 0; i < moniker_size; i++)
1756 if (i % 8 == 0) printf(" ");
1757 printf("0x%02x,", moniker_data[i]);
1758 if (i % 8 == 7) printf("\n");
1760 printf("\n");
1763 GlobalUnlock(hglobal);
1765 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1766 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1767 ok_ole_success(hr, CoUnmarshalInterface);
1769 IStream_Release(stream);
1770 IMoniker_Release(moniker_proxy);
1773 static void test_class_moniker(void)
1775 static const struct parse_test
1777 const WCHAR *name;
1778 ULONG eaten;
1779 HRESULT hr;
1781 tests[] =
1783 { L"clsid:11111111-0000-0000-2222-444444444444;extra data:", 54 },
1784 { L"clsid:11111111-0000-0000-2222-444444444444extra data", 52 },
1785 { L"clsid:11111111-0000-0000-2222-444444444444:", 43 },
1786 { L"clsid:11111111-0000-0000-2222-444444444444", 42 },
1787 { L"clsid:{11111111-0000-0000-2222-444444444444}", 44 },
1788 { L"clsid:{11111111-0000-0000-2222-444444444444", 0, MK_E_SYNTAX },
1789 { L"clsid:11111111-0000-0000-2222-444444444444}", 43 },
1791 IMoniker *moniker, *moniker2, *inverse, *reduced, *anti;
1792 IEnumMoniker *enummoniker;
1793 ULONG length, eaten;
1794 ULARGE_INTEGER size;
1795 LARGE_INTEGER pos;
1796 IROTData *rotdata;
1797 HRESULT hr;
1798 DWORD hash;
1799 IBindCtx *bindctx;
1800 IUnknown *unknown;
1801 FILETIME filetime;
1802 IStream *stream;
1803 BYTE buffer[100];
1804 HGLOBAL hglobal;
1805 unsigned int i;
1806 DWORD *data;
1808 hr = CreateBindCtx(0, &bindctx);
1809 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1811 for (i = 0; i < ARRAY_SIZE(tests); ++i)
1813 eaten = 0xdeadbeef;
1814 hr = MkParseDisplayName(bindctx, tests[i].name, &eaten, &moniker);
1815 todo_wine_if(i == 5)
1816 ok(hr == tests[i].hr, "%u: unexpected hr %#x.\n", i, hr);
1817 ok(eaten == tests[i].eaten, "%u: unexpected eaten length %u, expected %u.\n", i, eaten, tests[i].eaten);
1818 if (SUCCEEDED(hr))
1820 TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
1821 IMoniker_Release(moniker);
1825 /* Extended syntax, handled by class moniker directly, only CLSID is meaningful for equality. */
1826 hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;extra data:", &eaten, &moniker);
1827 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1828 ok(eaten == 54, "Unexpected length %u.\n", eaten);
1830 hr = MkParseDisplayName(bindctx, L"clsid:11111111-0000-0000-2222-444444444444;different extra data:", &eaten, &moniker2);
1831 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1833 TEST_DISPLAY_NAME(moniker, L"clsid:11111111-0000-0000-2222-444444444444;extra data:");
1834 TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
1835 hr = IMoniker_GetSizeMax(moniker, &size);
1836 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1837 ok(size.LowPart == 44, "Unexpected size %u.\n", size.LowPart);
1839 TEST_MONIKER_TYPE(moniker2, MKSYS_CLASSMONIKER);
1841 hr = IMoniker_IsEqual(moniker, moniker2);
1842 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1844 hr = IMoniker_IsEqual(moniker2, moniker);
1845 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1847 IMoniker_Release(moniker2);
1848 IMoniker_Release(moniker);
1850 /* From persistent state */
1851 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1852 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1854 hr = CreateClassMoniker(&GUID_NULL, &moniker);
1855 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1857 hr = IMoniker_GetSizeMax(moniker, &size);
1858 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1859 ok(size.QuadPart == 20, "Unexpected size %u.\n", size.LowPart);
1861 hr = IStream_Write(stream, &CLSID_StdComponentCategoriesMgr, sizeof(CLSID), NULL);
1862 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1863 length = 5 * sizeof(WCHAR);
1864 hr = IStream_Write(stream, &length, sizeof(length), NULL);
1865 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1866 hr = IStream_Write(stream, L"data", length, NULL);
1867 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1868 pos.QuadPart = 0;
1869 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
1870 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1872 hr = IMoniker_Load(moniker, stream);
1873 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1875 hr = IMoniker_GetSizeMax(moniker, &size);
1876 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1877 ok(size.QuadPart == 30, "Unexpected size %u.\n", size.LowPart);
1878 TEST_DISPLAY_NAME(moniker, L"clsid:0002E005-0000-0000-C000-000000000046data:");
1879 IStream_Release(stream);
1881 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1882 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1884 hr = GetHGlobalFromStream(stream, &hglobal);
1885 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1887 hr = IMoniker_Save(moniker, stream, FALSE);
1888 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1890 length = GlobalSize(hglobal);
1891 data = GlobalLock(hglobal);
1892 ok(length == 30, "Unexpected stream size %u.\n", length);
1893 ok(IsEqualGUID((CLSID *)data, &CLSID_StdComponentCategoriesMgr), "Unexpected clsid.\n");
1894 data += sizeof(CLSID) / sizeof(*data);
1895 ok(*data == 10, "Unexpected data length %u.\n", *data);
1896 data++;
1897 ok(!lstrcmpW((WCHAR *)data, L"data"), "Unexpected data.\n");
1899 IStream_Release(stream);
1901 /* Extra data does not affect comparison */
1902 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1903 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1904 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &length);
1905 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1906 ok(length == sizeof(expected_class_moniker_comparison_data), "Unexpected comparison data length %u.\n", length);
1907 ok(!memcmp(buffer, expected_class_moniker_comparison_data, length), "Unexpected data.\n");
1908 IROTData_Release(rotdata);
1910 IMoniker_Release(moniker);
1912 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1913 ok_ole_success(hr, CreateClassMoniker);
1915 hr = IMoniker_GetSizeMax(moniker, &size);
1916 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1917 ok(size.LowPart == 20, "Unexpected size %u.\n", size.LowPart);
1919 hr = IMoniker_QueryInterface(moniker, &CLSID_ClassMoniker, (void **)&unknown);
1920 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1921 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
1922 IUnknown_Release(unknown);
1924 test_moniker("class moniker", moniker,
1925 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1926 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1927 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1928 sizeof(expected_class_moniker_saved_data), expected_class_moniker_display_name);
1930 /* Hashing */
1932 hr = IMoniker_Hash(moniker, &hash);
1933 ok_ole_success(hr, IMoniker_Hash);
1935 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1936 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1937 hash);
1939 /* IsSystemMoniker test */
1940 TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
1942 /* IsRunning test */
1943 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1944 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1946 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1947 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1949 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1950 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1952 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1953 ok_ole_success(hr, IMoniker_BindToObject);
1954 IUnknown_Release(unknown);
1956 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1957 ok_ole_success(hr, IMoniker_BindToStorage);
1958 IUnknown_Release(unknown);
1960 hr = IMoniker_Inverse(moniker, &inverse);
1961 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
1962 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
1963 IMoniker_Release(inverse);
1965 /* Reduce() */
1966 hr = IMoniker_Reduce(moniker, NULL, MKRREDUCE_ALL, NULL, &reduced);
1967 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
1968 ok(reduced == moniker, "Unexpected moniker.\n");
1969 IMoniker_Release(reduced);
1971 /* Enum() */
1972 enummoniker = (void *)0xdeadbeef;
1973 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
1974 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1975 ok(!enummoniker, "Unexpected pointer.\n");
1977 enummoniker = (void *)0xdeadbeef;
1978 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
1979 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1980 ok(!enummoniker, "Unexpected pointer.\n");
1982 hr = IMoniker_Enum(moniker, FALSE, NULL);
1983 todo_wine
1984 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1986 IBindCtx_Release(bindctx);
1988 /* ComposeWith() */
1990 /* C + A -> () */
1991 anti = create_antimoniker(1);
1992 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
1993 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
1994 ok(!moniker2, "Unexpected pointer.\n");
1995 IMoniker_Release(anti);
1997 /* C + A2 -> A */
1998 anti = create_antimoniker(2);
1999 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
2000 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2001 ok(!moniker2, "Unexpected pointer.\n");
2002 IMoniker_Release(anti);
2004 IMoniker_Release(moniker);
2007 static void test_file_moniker(WCHAR* path)
2009 IMoniker *moniker1 = NULL, *moniker2 = NULL, *inverse, *reduced, *anti;
2010 IEnumMoniker *enummoniker;
2011 IBindCtx *bind_ctx;
2012 IStream *stream;
2013 IUnknown *unk;
2014 DWORD hash;
2015 HRESULT hr;
2017 hr = CreateFileMoniker(path, &moniker1);
2018 ok_ole_success(hr, CreateFileMoniker);
2020 hr = IMoniker_QueryInterface(moniker1, &CLSID_FileMoniker, (void **)&unk);
2021 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2022 ok(unk == (IUnknown *)moniker1, "Unexpected interface.\n");
2023 IUnknown_Release(unk);
2025 hr = IMoniker_Inverse(moniker1, &inverse);
2026 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
2027 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
2028 IMoniker_Release(inverse);
2030 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2031 ok_ole_success(hr, CreateStreamOnHGlobal);
2033 /* Marshal */
2034 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2035 ok_ole_success(hr, CoMarshalInterface);
2037 /* Rewind */
2038 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
2039 ok_ole_success(hr, IStream_Seek);
2041 /* Unmarshal */
2042 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
2043 ok_ole_success(hr, CoUnmarshalInterface);
2045 hr = IMoniker_IsEqual(moniker1, moniker2);
2046 ok_ole_success(hr, IsEqual);
2048 /* Reduce() */
2049 hr = CreateBindCtx(0, &bind_ctx);
2050 ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
2052 hr = IMoniker_Reduce(moniker1, NULL, MKRREDUCE_ALL, NULL, &reduced);
2053 todo_wine
2054 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2056 hr = IMoniker_Reduce(moniker1, bind_ctx, MKRREDUCE_ALL, NULL, &reduced);
2057 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
2058 ok(reduced == moniker1, "Unexpected moniker.\n");
2059 IMoniker_Release(reduced);
2061 /* Enum() */
2062 enummoniker = (void *)0xdeadbeef;
2063 hr = IMoniker_Enum(moniker1, TRUE, &enummoniker);
2064 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2065 ok(!enummoniker, "Unexpected pointer.\n");
2067 enummoniker = (void *)0xdeadbeef;
2068 hr = IMoniker_Enum(moniker1, FALSE, &enummoniker);
2069 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2070 ok(!enummoniker, "Unexpected pointer.\n");
2072 hr = IMoniker_Enum(moniker1, FALSE, NULL);
2073 todo_wine
2074 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2076 IBindCtx_Release(bind_ctx);
2078 IStream_Release(stream);
2079 IMoniker_Release(moniker2);
2081 /* ComposeWith() */
2083 /* F + A -> () */
2084 anti = create_antimoniker(1);
2085 hr = IMoniker_ComposeWith(moniker1, anti, TRUE, &moniker2);
2086 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2087 ok(!moniker2, "Unexpected pointer.\n");
2088 IMoniker_Release(anti);
2090 /* I + A2 -> (A) */
2091 anti = create_antimoniker(2);
2092 hr = IMoniker_ComposeWith(moniker1, anti, TRUE, &moniker2);
2093 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2094 TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER);
2095 hr = IMoniker_Hash(moniker2, &hash);
2096 ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr);
2097 ok(hash == 0x80000001, "Unexpected hash.\n");
2098 IMoniker_Release(moniker2);
2100 IMoniker_Release(anti);
2102 IMoniker_Release(moniker1);
2105 static void test_file_monikers(void)
2107 static WCHAR wszFile[][30] = {
2108 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
2109 {'\\', 'a','b','c','d','e','f','g','\\','h','i','j','k','l','\\','m','n','o','p','q','r','s','t','u','.','m','n','o',0},
2110 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
2111 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
2112 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
2113 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
2114 * U+0100 .. = Latin extended-A
2116 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
2118 WCHAR filename[MAX_PATH], path[MAX_PATH];
2119 IMoniker *moniker, *moniker2;
2120 BIND_OPTS bind_opts;
2121 IStorage *storage;
2122 IBindCtx *bindctx;
2123 STATSTG statstg;
2124 HRESULT hr;
2125 int i;
2127 trace("ACP is %u\n", GetACP());
2129 for (i = 0; i < ARRAY_SIZE(wszFile); ++i)
2131 int j ;
2132 if (i == 2)
2134 BOOL used;
2135 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
2136 if (used)
2138 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
2139 continue;
2142 for (j = lstrlenW(wszFile[i]); j > 0; --j)
2144 wszFile[i][j] = 0;
2145 test_file_moniker(wszFile[i]);
2149 /* BindToStorage() */
2150 GetTempPathW(MAX_PATH, path);
2151 GetTempFileNameW(path, L"stg", 1, filename);
2153 hr = StgCreateStorageEx(filename, STGM_SHARE_EXCLUSIVE | STGM_READWRITE, STGFMT_STORAGE,
2154 0, NULL, NULL, &IID_IStorage, (void **)&storage);
2155 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2156 IStorage_Release(storage);
2158 hr = CreateFileMoniker(filename, &moniker);
2159 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2161 hr = IMoniker_BindToStorage(moniker, NULL, NULL, &IID_IStorage, (void **)&storage);
2162 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2164 hr = CreateBindCtx(0, &bindctx);
2165 ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
2167 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IStorage, (void **)&storage);
2168 ok(hr == STG_E_INVALIDFLAG, "Unexpected hr %#x.\n", hr);
2170 bind_opts.cbStruct = sizeof(bind_opts);
2171 bind_opts.grfMode = STGM_READWRITE | STGM_SHARE_DENY_WRITE;
2172 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2173 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2175 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IStorage, (void **)&storage);
2176 ok(hr == STG_E_INVALIDFLAG, "Unexpected hr %#x.\n", hr);
2178 bind_opts.grfMode = STGM_READ | STGM_SHARE_DENY_WRITE;
2179 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2180 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2182 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IStorage, (void **)&storage);
2183 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2185 memset(&statstg, 0, sizeof(statstg));
2186 hr = IStorage_Stat(storage, &statstg, STATFLAG_NONAME);
2187 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2188 ok(statstg.grfMode == (STGM_READ | STGM_SHARE_DENY_WRITE), "Unexpected mode %#x.\n", statstg.grfMode);
2190 IStorage_Release(storage);
2191 IBindCtx_Release(bindctx);
2192 IMoniker_Release(moniker);
2194 DeleteFileW(filename);
2196 /* IsEqual() */
2197 hr = CreateFileMoniker(L"test.bmp", &moniker);
2198 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2200 hr = CreateFileMoniker(L"TEST.bmp", &moniker2);
2201 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2203 hr = IMoniker_IsEqual(moniker, moniker2);
2204 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2206 hr = IMoniker_IsEqual(moniker, NULL);
2207 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2209 IMoniker_Release(moniker2);
2210 IMoniker_Release(moniker);
2213 static void test_item_moniker(void)
2215 static const char item_moniker_unicode_delim_stream[] =
2217 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, '!',
2218 0x00, 0x02, 0x00, 0x00, 0x00, 'A', 0x00,
2220 static const char item_moniker_unicode_item_stream[] =
2222 0x02, 0x00, 0x00, 0x00, '!', 0x00, 0x05, 0x00,
2223 0x00, 0x00, 0xff, 0xff, 0x00, 'B', 0x00,
2225 static const char item_moniker_unicode_delim_item_stream[] =
2227 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, '!',
2228 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
2229 0x00, 'C', 0x00,
2231 static struct
2233 const char *data;
2234 int data_len;
2235 const WCHAR *display_name;
2237 item_moniker_data[] =
2239 { item_moniker_unicode_delim_stream, sizeof(item_moniker_unicode_delim_stream), L"!A" },
2240 { item_moniker_unicode_item_stream, sizeof(item_moniker_unicode_item_stream), L"!B" },
2241 { item_moniker_unicode_delim_item_stream, sizeof(item_moniker_unicode_delim_item_stream), L"!C" },
2243 static const struct
2245 const WCHAR *delim1;
2246 const WCHAR *item1;
2247 const WCHAR *delim2;
2248 const WCHAR *item2;
2249 HRESULT hr;
2250 } isequal_tests[] =
2252 { L"!", L"Item1", L"!", L"ITEM1", S_OK },
2253 { NULL, L"Item1", L"!", L"ITEM1", S_OK },
2254 { L"", L"Item1", L"!", L"ITEM1", S_OK },
2255 { L"&", L"Item1", L"!", L"ITEM1", S_OK },
2256 {L"&&", L"Item1", L"&", L"&Item1", S_FALSE },
2257 { NULL, L"Item1", NULL, L"Item2", S_FALSE },
2258 { NULL, L"Item1", NULL, L"ITEM1", S_OK },
2260 static const struct
2262 const WCHAR *delim;
2263 const WCHAR *item;
2264 DWORD hash;
2265 } hash_tests[] =
2267 { L"!", L"Test", 0x73c },
2268 { L"%", L"Test", 0x73c },
2269 { L"%", L"TEST", 0x73c },
2270 { L"%", L"T", 0x54 },
2271 { L"%", L"A", 0x41 },
2272 { L"%", L"a", 0x41 },
2274 static const char *methods_isrunning[] =
2276 "Moniker_IsRunning",
2277 NULL
2279 IMoniker *moniker, *moniker2, *reduced, *anti, *inverse;
2280 DWORD i, hash, eaten, cookie;
2281 HRESULT hr;
2282 IBindCtx *bindctx;
2283 IUnknown *unknown;
2284 static const WCHAR wszDelimiter[] = {'!',0};
2285 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
2286 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
2287 struct test_moniker *container_moniker;
2288 WCHAR displayname[16] = L"display name";
2289 IEnumMoniker *enummoniker;
2290 IRunningObjectTable *rot;
2291 BIND_OPTS bind_opts;
2292 LARGE_INTEGER pos;
2293 IStream *stream;
2295 hr = CreateItemMoniker(NULL, wszObjectName, &moniker);
2296 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2298 hr = IMoniker_QueryInterface(moniker, &CLSID_ItemMoniker, (void **)&unknown);
2299 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2300 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
2301 IUnknown_Release(unknown);
2303 test_moniker("item moniker 2", moniker,
2304 expected_item_moniker_marshal_data2, sizeof(expected_item_moniker_marshal_data2),
2305 expected_item_moniker_saved_data2, sizeof(expected_item_moniker_saved_data2),
2306 expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2),
2307 46, L"Test");
2309 IMoniker_Release(moniker);
2311 hr = CreateItemMoniker(L"", wszObjectName, &moniker);
2312 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2314 test_moniker("item moniker 3", moniker,
2315 expected_item_moniker_marshal_data3, sizeof(expected_item_moniker_marshal_data3),
2316 expected_item_moniker_saved_data3, sizeof(expected_item_moniker_saved_data3),
2317 expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2),
2318 50, L"Test");
2320 IMoniker_Release(moniker);
2322 hr = CreateItemMoniker(L"&&", wszObjectName, &moniker);
2323 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2325 test_moniker("item moniker 4", moniker,
2326 expected_item_moniker_marshal_data4, sizeof(expected_item_moniker_marshal_data4),
2327 expected_item_moniker_saved_data4, sizeof(expected_item_moniker_saved_data4),
2328 expected_item_moniker_comparison_data4, sizeof(expected_item_moniker_comparison_data4),
2329 58, L"&&Test");
2331 IMoniker_Release(moniker);
2333 hr = CreateItemMoniker(L"ab", wszObjectName, &moniker);
2334 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2336 test_moniker("item moniker 5", moniker,
2337 expected_item_moniker_marshal_data5, sizeof(expected_item_moniker_marshal_data5),
2338 expected_item_moniker_saved_data5, sizeof(expected_item_moniker_saved_data5),
2339 expected_item_moniker_comparison_data5, sizeof(expected_item_moniker_comparison_data5),
2340 58, L"abTest");
2342 /* Serialize and load back. */
2343 hr = CreateItemMoniker(NULL, L"object", &moniker2);
2344 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2346 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2347 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
2349 hr = CreateBindCtx(0, &bindctx);
2350 ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
2352 for (i = 0; i < ARRAY_SIZE(item_moniker_data); ++i)
2354 pos.QuadPart = 0;
2355 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2356 ok(hr == S_OK, "Failed to seek stream, hr %#x.\n", hr);
2358 hr = IStream_Write(stream, item_moniker_data[i].data, item_moniker_data[i].data_len, NULL);
2359 ok(hr == S_OK, "Failed to write stream contents, hr %#x.\n", hr);
2361 pos.QuadPart = 0;
2362 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2363 ok(hr == S_OK, "Failed to seek stream, hr %#x.\n", hr);
2365 hr = IMoniker_Load(moniker2, stream);
2366 ok(hr == S_OK, "Failed to load moniker, hr %#x.\n", hr);
2368 TEST_DISPLAY_NAME(moniker2, item_moniker_data[i].display_name);
2371 IStream_Release(stream);
2373 IMoniker_Release(moniker2);
2374 IMoniker_Release(moniker);
2376 /* Hashing */
2378 for (i = 0; i < ARRAY_SIZE(hash_tests); ++i)
2380 hr = CreateItemMoniker(hash_tests[i].delim, hash_tests[i].item, &moniker);
2381 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2383 hr = IMoniker_Hash(moniker, &hash);
2384 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2385 ok(hash == hash_tests[i].hash, "%d: unexpected hash value %#x.\n", i, hash);
2387 IMoniker_Release(moniker);
2390 hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker);
2391 ok_ole_success(hr, CreateItemMoniker);
2393 test_moniker("item moniker 1", moniker,
2394 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
2395 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
2396 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
2397 54, expected_display_name);
2399 /* IsSystemMoniker test */
2400 TEST_MONIKER_TYPE(moniker, MKSYS_ITEMMONIKER);
2402 container_moniker = create_test_moniker();
2404 /* IsRunning test */
2405 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
2406 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
2408 hr = IMoniker_IsRunning(moniker, NULL, &container_moniker->IMoniker_iface, NULL);
2409 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2411 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2412 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
2414 hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker2);
2415 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2416 hr = IMoniker_IsRunning(moniker, bindctx, NULL, moniker2);
2417 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2418 IMoniker_Release(moniker2);
2420 /* Different moniker as newly running. */
2421 hr = CreateItemMoniker(wszDelimiter, L"Item123", &moniker2);
2422 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2424 hr = IMoniker_IsRunning(moniker, bindctx, NULL, moniker2);
2425 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2427 hr = IBindCtx_GetRunningObjectTable(bindctx, &rot);
2428 ok(hr == S_OK, "Failed to get ROT, hr %#x.\n", hr);
2430 hr = IRunningObjectTable_Register(rot, ROTFLAGS_REGISTRATIONKEEPSALIVE, (IUnknown *)moniker, moniker, &cookie);
2431 ok(hr == S_OK, "Failed to register, hr %#x.\n", hr);
2433 hr = IRunningObjectTable_IsRunning(rot, moniker);
2434 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2436 hr = IMoniker_IsRunning(moniker, bindctx, NULL, moniker2);
2437 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2439 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2440 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2442 hr = IRunningObjectTable_Revoke(rot, cookie);
2443 ok(hr == S_OK, "Failed to revoke registration, hr %#x.\n", hr);
2445 IRunningObjectTable_Release(rot);
2447 expected_method_list = methods_isrunning;
2448 hr = IMoniker_IsRunning(moniker, bindctx, &container_moniker->IMoniker_iface, NULL);
2449 ok(hr == 0x8beef000, "Unexpected hr %#x.\n", hr);
2451 expected_method_list = methods_isrunning;
2452 hr = IMoniker_IsRunning(moniker, bindctx, &container_moniker->IMoniker_iface, moniker2);
2453 ok(hr == 0x8beef000, "Unexpected hr %#x.\n", hr);
2455 IMoniker_Release(moniker2);
2457 /* BindToObject() */
2458 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2459 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
2461 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2462 ok(hr == (0x8bee0000 | BINDSPEED_INDEFINITE), "Unexpected hr %#x.\n", hr);
2464 bind_opts.cbStruct = sizeof(bind_opts);
2465 hr = IBindCtx_GetBindOptions(bindctx, &bind_opts);
2466 ok(hr == S_OK, "Failed to get bind options, hr %#x.\n", hr);
2468 bind_opts.dwTickCountDeadline = 1;
2469 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2470 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2471 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2472 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2474 bind_opts.dwTickCountDeadline = 2499;
2475 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2476 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2477 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2478 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2480 bind_opts.dwTickCountDeadline = 2500;
2481 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2482 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2483 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2484 ok(hr == (0x8bee0000 | BINDSPEED_MODERATE), "Unexpected hr %#x.\n", hr);
2486 /* BindToStorage() */
2487 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2488 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2490 hr = IMoniker_BindToStorage(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2491 ok(hr == 0x8bee0001, "Unexpected hr %#x.\n", hr);
2493 /* ParseDisplayName() */
2494 hr = IMoniker_ParseDisplayName(moniker, bindctx, NULL, displayname, &eaten, &moniker2);
2495 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
2497 bind_opts.dwTickCountDeadline = 0;
2498 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2499 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2500 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2501 ok(hr == (0x8bee0000 | BINDSPEED_INDEFINITE), "Unexpected hr %#x.\n", hr);
2503 bind_opts.dwTickCountDeadline = 1;
2504 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2505 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2506 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2507 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2509 bind_opts.dwTickCountDeadline = 2499;
2510 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2511 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2512 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2513 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2515 bind_opts.dwTickCountDeadline = 2500;
2516 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2517 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2518 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2519 ok(hr == (0x8bee0000 | BINDSPEED_MODERATE), "Unexpected hr %#x.\n", hr);
2521 IMoniker_Release(&container_moniker->IMoniker_iface);
2523 IBindCtx_Release(bindctx);
2525 hr = IMoniker_Inverse(moniker, &inverse);
2526 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
2527 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
2528 IMoniker_Release(inverse);
2530 /* Reduce() */
2531 hr = IMoniker_Reduce(moniker, NULL, MKRREDUCE_ALL, NULL, &reduced);
2532 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
2533 ok(reduced == moniker, "Unexpected moniker.\n");
2534 IMoniker_Release(reduced);
2536 /* Enum() */
2537 enummoniker = (void *)0xdeadbeef;
2538 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
2539 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2540 ok(!enummoniker, "Unexpected pointer.\n");
2542 enummoniker = (void *)0xdeadbeef;
2543 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
2544 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2545 ok(!enummoniker, "Unexpected pointer.\n");
2547 hr = IMoniker_Enum(moniker, FALSE, NULL);
2548 todo_wine
2549 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2551 hr = IMoniker_IsEqual(moniker, NULL);
2552 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2554 IMoniker_Release(moniker);
2556 /* IsEqual */
2557 for (i = 0; i < ARRAY_SIZE(isequal_tests); ++i)
2559 hr = CreateItemMoniker(isequal_tests[i].delim1, isequal_tests[i].item1, &moniker);
2560 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2562 hr = CreateItemMoniker(isequal_tests[i].delim2, isequal_tests[i].item2, &moniker2);
2563 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2565 hr = IMoniker_IsEqual(moniker, moniker2);
2566 ok(hr == isequal_tests[i].hr, "%d: unexpected result %#x.\n", i, hr);
2568 hr = IMoniker_IsEqual(moniker2, moniker);
2569 ok(hr == isequal_tests[i].hr, "%d: unexpected result %#x.\n", i, hr);
2571 IMoniker_Release(moniker);
2572 IMoniker_Release(moniker2);
2575 /* Default instance. */
2576 hr = CoCreateInstance(&CLSID_ItemMoniker, NULL, CLSCTX_SERVER, &IID_IMoniker, (void **)&moniker);
2577 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2579 test_moniker("item moniker 6", moniker,
2580 expected_item_moniker_marshal_data6, sizeof(expected_item_moniker_marshal_data6),
2581 expected_item_moniker_saved_data6, sizeof(expected_item_moniker_saved_data6),
2582 expected_item_moniker_comparison_data6, sizeof(expected_item_moniker_comparison_data6),
2583 34, L"");
2585 hr = CoCreateInstance(&CLSID_ItemMoniker, (IUnknown *)moniker, CLSCTX_SERVER, &IID_IMoniker, (void **)&moniker2);
2586 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
2588 IMoniker_Release(moniker);
2590 /* ComposeWith() */
2591 hr = CreateItemMoniker(L"!", L"Item", &moniker);
2592 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2594 /* I + A -> () */
2595 anti = create_antimoniker(1);
2596 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
2597 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2598 ok(!moniker2, "Unexpected pointer.\n");
2599 IMoniker_Release(anti);
2601 /* I + A2 -> (A) */
2602 anti = create_antimoniker(2);
2603 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
2604 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2605 TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER);
2606 hr = IMoniker_Hash(moniker2, &hash);
2607 ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr);
2608 ok(hash == 0x80000001, "Unexpected hash.\n");
2609 IMoniker_Release(moniker2);
2611 IMoniker_Release(anti);
2613 IMoniker_Release(moniker);
2616 static void stream_write_dword(IStream *stream, DWORD value)
2618 LARGE_INTEGER pos;
2619 HRESULT hr;
2621 pos.QuadPart = 0;
2622 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2623 ok(hr == S_OK, "Failed to seek, hr %#x.\n", hr);
2625 hr = IStream_Write(stream, &value, sizeof(value), NULL);
2626 ok(hr == S_OK, "Stream write failed, hr %#x.\n", hr);
2628 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2629 ok(hr == S_OK, "Failed to seek, hr %#x.\n", hr);
2632 static void test_anti_moniker(void)
2634 IMoniker *moniker, *moniker2, *moniker3, *inverse, *reduced;
2635 HRESULT hr;
2636 DWORD hash;
2637 IBindCtx *bindctx;
2638 FILETIME filetime;
2639 IUnknown *unknown;
2640 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
2641 IEnumMoniker *enummoniker;
2642 IStream *stream;
2644 hr = CreateAntiMoniker(&moniker);
2645 ok_ole_success(hr, CreateAntiMoniker);
2647 hr = IMoniker_QueryInterface(moniker, &CLSID_AntiMoniker, (void **)&unknown);
2648 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2649 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
2650 IUnknown_Release(unknown);
2652 test_moniker("anti moniker", moniker,
2653 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
2654 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
2655 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
2656 20, expected_display_name);
2658 /* Hashing */
2659 hr = IMoniker_Hash(moniker, &hash);
2660 ok_ole_success(hr, IMoniker_Hash);
2661 ok(hash == 0x80000001,
2662 "Hash value != 0x80000001, instead was 0x%08x\n",
2663 hash);
2665 /* IsSystemMoniker test */
2666 TEST_MONIKER_TYPE(moniker, MKSYS_ANTIMONIKER);
2668 hr = IMoniker_Inverse(moniker, &inverse);
2669 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
2670 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
2672 hr = CreateBindCtx(0, &bindctx);
2673 ok_ole_success(hr, CreateBindCtx);
2675 /* IsRunning test */
2676 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2677 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
2679 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
2680 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
2682 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2683 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
2685 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2686 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
2688 /* ComposeWith */
2689 hr = CreateAntiMoniker(&moniker2);
2690 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2692 moniker3 = moniker;
2693 hr = IMoniker_ComposeWith(moniker, moniker2, TRUE, &moniker3);
2694 ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr);
2695 ok(!moniker3, "Unexpected interface.\n");
2697 hr = IMoniker_ComposeWith(moniker, moniker2, FALSE, &moniker3);
2698 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2699 TEST_MONIKER_TYPE(moniker3, MKSYS_GENERICCOMPOSITE);
2700 IMoniker_Release(moniker3);
2702 IMoniker_Release(moniker2);
2704 /* Load with composed number > 1. */
2705 hr = CreateAntiMoniker(&moniker2);
2706 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2708 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2709 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
2711 stream_write_dword(stream, 2);
2713 hr = IMoniker_Load(moniker, stream);
2714 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2716 test_moniker("anti moniker 2", moniker,
2717 expected_anti_moniker_marshal_data2, sizeof(expected_anti_moniker_marshal_data2),
2718 expected_anti_moniker_saved_data2, sizeof(expected_anti_moniker_saved_data2),
2719 expected_anti_moniker_comparison_data2, sizeof(expected_anti_moniker_comparison_data2),
2720 20, L"\\..\\..");
2722 hr = IMoniker_IsEqual(moniker, moniker2);
2723 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2725 hr = IMoniker_IsEqual(moniker2, moniker);
2726 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2728 hr = IMoniker_Hash(moniker, &hash);
2729 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2730 ok(hash == 0x80000002, "Unexpected hash value %#x.\n", hash);
2732 /* Display name reflects anti combination. */
2733 TEST_DISPLAY_NAME(moniker, L"\\..\\..");
2735 /* Limit is at 0xfffff. */
2736 stream_write_dword(stream, 0xfffff);
2738 hr = IMoniker_Load(moniker, stream);
2739 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2741 hr = IMoniker_Hash(moniker, &hash);
2742 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2743 ok(hash == 0x800fffff, "Unexpected hash value %#x.\n", hash);
2745 stream_write_dword(stream, 0xfffff + 1);
2747 hr = IMoniker_Load(moniker, stream);
2748 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2750 hr = IMoniker_Hash(moniker, &hash);
2751 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2752 ok(hash == 0x800fffff, "Unexpected hash value %#x.\n", hash);
2754 /* Zero combining counter is also valid. */
2755 stream_write_dword(stream, 0);
2757 hr = IMoniker_Load(moniker, stream);
2758 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2760 hr = IMoniker_IsEqual(moniker, moniker2);
2761 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2763 hr = IMoniker_IsEqual(moniker2, moniker);
2764 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2766 hr = IMoniker_Hash(moniker, &hash);
2767 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2768 ok(hash == 0x80000000, "Unexpected hash value %#x.\n", hash);
2770 TEST_DISPLAY_NAME(moniker, L"");
2772 /* Back to initial value. */
2773 stream_write_dword(stream, 1);
2775 hr = IMoniker_Load(moniker, stream);
2776 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2778 hr = IMoniker_IsEqual(moniker, moniker2);
2779 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2781 hr = IMoniker_IsEqual(moniker2, moniker);
2782 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2784 hr = IMoniker_IsEqual(moniker, NULL);
2785 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2787 /* Reduce() */
2788 hr = IMoniker_Reduce(moniker, NULL, MKRREDUCE_ALL, NULL, &reduced);
2789 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
2790 ok(reduced == moniker, "Unexpected moniker.\n");
2791 IMoniker_Release(reduced);
2793 /* Enum() */
2794 enummoniker = (void *)0xdeadbeef;
2795 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
2796 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2797 ok(!enummoniker, "Unexpected pointer.\n");
2799 enummoniker = (void *)0xdeadbeef;
2800 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
2801 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2802 ok(!enummoniker, "Unexpected pointer.\n");
2804 hr = IMoniker_Enum(moniker, FALSE, NULL);
2805 todo_wine
2806 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2808 /* CommonPrefixWith() */
2809 stream_write_dword(stream, 0);
2811 hr = IMoniker_Load(moniker, stream);
2812 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2814 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2815 ok(hr == MK_S_ME, "Unexpected hr %#x.\n", hr);
2816 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2817 IMoniker_Release(moniker3);
2819 hr = IMoniker_CommonPrefixWith(moniker2, moniker, &moniker3);
2820 ok(hr == MK_S_HIM, "Unexpected hr %#x.\n", hr);
2821 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2822 IMoniker_Release(moniker3);
2824 stream_write_dword(stream, 10);
2826 hr = IMoniker_Load(moniker, stream);
2827 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2829 stream_write_dword(stream, 5);
2831 hr = IMoniker_Load(moniker2, stream);
2832 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2834 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2835 ok(hr == MK_S_HIM, "Unexpected hr %#x.\n", hr);
2836 ok(moniker3 == moniker2, "Unexpected prefix moniker.\n");
2837 IMoniker_Release(moniker3);
2839 hr = IMoniker_CommonPrefixWith(moniker2, moniker, &moniker3);
2840 ok(hr == MK_S_ME, "Unexpected hr %#x.\n", hr);
2841 ok(moniker3 == moniker2, "Unexpected prefix moniker.\n");
2842 IMoniker_Release(moniker3);
2844 /* Now same length, 0 or 2 */
2845 stream_write_dword(stream, 0);
2846 hr = IMoniker_Load(moniker, stream);
2847 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2849 stream_write_dword(stream, 0);
2850 hr = IMoniker_Load(moniker2, stream);
2851 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2853 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2854 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
2855 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2856 IMoniker_Release(moniker3);
2858 stream_write_dword(stream, 2);
2859 hr = IMoniker_Load(moniker, stream);
2860 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2862 stream_write_dword(stream, 2);
2863 hr = IMoniker_Load(moniker2, stream);
2864 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2866 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2867 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
2868 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2869 IMoniker_Release(moniker3);
2871 IStream_Release(stream);
2872 IBindCtx_Release(bindctx);
2873 IMoniker_Release(moniker);
2874 IMoniker_Release(moniker2);
2877 static void test_generic_composite_moniker(void)
2879 IMoniker *moniker, *inverse, *inverse2, *moniker1, *moniker2, *moniker3, *moniker4;
2880 IEnumMoniker *enummoniker;
2881 HRESULT hr;
2882 DWORD hash;
2883 IBindCtx *bindctx;
2884 FILETIME filetime;
2885 IUnknown *unknown;
2887 hr = CreateBindCtx(0, &bindctx);
2888 ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
2890 hr = CreateItemMoniker(L"!", L"Test", &moniker1);
2891 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2892 hr = CreateItemMoniker(L"#", L"Wine", &moniker2);
2893 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2894 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2895 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2897 /* Compose with itself. */
2898 EXPECT_REF(moniker1, 2);
2899 hr = CreateGenericComposite(moniker1, moniker1, &moniker);
2900 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2901 EXPECT_REF(moniker1, 4);
2902 TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
2903 IMoniker_Release(moniker);
2905 /* (I) + (A) -> () */
2906 hr = IMoniker_Inverse(moniker1, &inverse);
2907 ok(hr == S_OK, "Failed to invert, hr %#x.\n", hr);
2908 hr = CreateGenericComposite(moniker1, inverse, &moniker);
2909 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2910 todo_wine
2911 ok(!moniker, "Unexpected pointer.\n");
2912 if (moniker)
2913 IMoniker_Release(moniker);
2915 /* (I1,I2) + (A,A) -> (I1,I2+A,A) -> (I1,A) -> () */
2916 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2917 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2918 hr = CreateGenericComposite(inverse, inverse, &moniker3);
2919 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2920 TEST_MONIKER_TYPE(moniker3, MKSYS_GENERICCOMPOSITE);
2922 hr = CreateGenericComposite(moniker, moniker3, &moniker4);
2923 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2924 todo_wine
2925 ok(!moniker4, "Unexpected pointer.\n");
2926 if (moniker4)
2927 IMoniker_Release(moniker4);
2929 IMoniker_Release(moniker);
2930 IMoniker_Release(moniker3);
2932 /* (I1,I2) + (A2,A) -> (I1,I2+A2,A) -> (I1,A,A) -> (I1+A,A) -> (A) */
2933 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2934 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2935 ok(!!moniker, "Unexpected pointer.\n");
2936 inverse2 = create_antimoniker(2);
2937 hr = CreateGenericComposite(inverse2, inverse, &moniker3);
2938 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2939 ok(!!moniker3, "Unexpected pointer.\n");
2940 IMoniker_Release(inverse2);
2942 hr = CreateGenericComposite(moniker, moniker3, &moniker4);
2943 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2944 TEST_MONIKER_TYPE_TODO(moniker4, MKSYS_ANTIMONIKER);
2945 IMoniker_Release(moniker4);
2946 IMoniker_Release(moniker);
2947 IMoniker_Release(moniker3);
2949 /* (I1,I2) + (A,I2) -> (I1,I2+A,I2) -> (I1,I2) */
2950 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2951 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2952 ok(!!moniker, "Unexpected pointer.\n");
2954 hr = CreateGenericComposite(inverse, moniker2, &moniker3);
2955 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2956 ok(!!moniker3, "Unexpected pointer.\n");
2958 hr = CreateGenericComposite(moniker, moniker3, &moniker4);
2959 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2960 TEST_MONIKER_TYPE(moniker4, MKSYS_GENERICCOMPOSITE);
2962 TEST_DISPLAY_NAME(moniker4, L"!Test#Wine");
2964 IMoniker_Release(moniker4);
2965 IMoniker_Release(moniker3);
2967 IMoniker_Release(inverse);
2969 /* Generic composite is special, as it does not addref in this case. */
2970 hr = IMoniker_QueryInterface(moniker, &CLSID_CompositeMoniker, (void **)&unknown);
2971 todo_wine
2972 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2973 if (SUCCEEDED(hr))
2974 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
2976 test_moniker("generic composite moniker", moniker,
2977 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
2978 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
2979 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
2980 160, L"!Test#Wine");
2982 /* Hashing */
2984 hr = IMoniker_Hash(moniker, &hash);
2985 ok_ole_success(hr, IMoniker_Hash);
2987 ok(hash == 0xd87,
2988 "Hash value != 0xd87, instead was 0x%08x\n",
2989 hash);
2991 /* IsSystemMoniker test */
2992 TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
2994 hr = CreateBindCtx(0, &bindctx);
2995 ok_ole_success(hr, CreateBindCtx);
2997 /* IsRunning test */
2998 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
2999 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
3001 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
3002 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
3004 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
3005 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
3007 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
3008 todo_wine
3009 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
3011 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
3012 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
3014 IBindCtx_Release(bindctx);
3016 hr = IMoniker_Inverse(moniker, &inverse);
3017 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
3018 TEST_MONIKER_TYPE(inverse, MKSYS_GENERICCOMPOSITE);
3019 IMoniker_Release(inverse);
3021 /* Enum() */
3022 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
3023 ok(hr == S_OK, "Failed to get enumerator, hr %#x.\n", hr);
3024 IEnumMoniker_Release(enummoniker);
3026 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
3027 ok(hr == S_OK, "Failed to get enumerator, hr %#x.\n", hr);
3028 IEnumMoniker_Release(enummoniker);
3030 hr = IMoniker_Enum(moniker, FALSE, NULL);
3031 todo_wine
3032 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3034 IMoniker_Release(moniker);
3037 static void test_pointer_moniker(void)
3039 IMoniker *moniker, *moniker2, *prefix, *inverse, *anti;
3040 struct test_factory factory;
3041 IEnumMoniker *enummoniker;
3042 DWORD hash, size;
3043 HRESULT hr;
3044 IBindCtx *bindctx;
3045 FILETIME filetime;
3046 IUnknown *unknown;
3047 IStream *stream;
3048 IROTData *rotdata;
3049 LPOLESTR display_name;
3050 IMarshal *marshal;
3051 LARGE_INTEGER pos;
3052 CLSID clsid;
3054 test_factory_init(&factory);
3056 hr = CreatePointerMoniker((IUnknown *)&factory.IClassFactory_iface, NULL);
3057 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3059 hr = CreatePointerMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker);
3060 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3062 hr = IMoniker_QueryInterface(moniker, &IID_IMoniker, NULL);
3063 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3065 hr = IMoniker_QueryInterface(moniker, &CLSID_PointerMoniker, (void **)&unknown);
3066 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
3067 IUnknown_Release(unknown);
3069 hr = IMoniker_QueryInterface(moniker, &IID_IMarshal, (void **)&marshal);
3070 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
3072 hr = IMarshal_GetUnmarshalClass(marshal, NULL, NULL, 0, NULL, 0, &clsid);
3073 ok(hr == S_OK, "Failed to get class, hr %#x.\n", hr);
3074 ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "Unexpected class.\n");
3076 hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, CLSCTX_INPROC, NULL, 0, &size);
3077 ok(hr == S_OK, "Failed to get marshal size, hr %#x.\n", hr);
3078 ok(size > 0, "Unexpected size %d.\n", size);
3080 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3081 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
3083 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3084 ok(hr == S_OK, "Failed to marshal moniker, hr %#x.\n", hr);
3086 pos.QuadPart = 0;
3087 IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
3088 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker2);
3089 ok(hr == S_OK, "Failed to unmarshal, hr %#x.\n", hr);
3090 hr = IMoniker_IsEqual(moniker, moniker2);
3091 ok(hr == S_OK, "Expected equal moniker, hr %#x.\n", hr);
3092 IMoniker_Release(moniker2);
3094 IStream_Release(stream);
3096 IMarshal_Release(marshal);
3098 ok(factory.refcount > 1, "Unexpected factory refcount %u.\n", factory.refcount);
3100 /* Display Name */
3102 hr = CreateBindCtx(0, &bindctx);
3103 ok_ole_success(hr, CreateBindCtx);
3105 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
3106 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
3108 IBindCtx_Release(bindctx);
3110 hr = IMoniker_IsDirty(moniker);
3111 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
3113 /* IROTData::GetComparisonData test */
3115 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
3116 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3118 /* Saving */
3120 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
3121 ok_ole_success(hr, CreateStreamOnHGlobal);
3123 hr = IMoniker_Save(moniker, stream, TRUE);
3124 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
3126 IStream_Release(stream);
3128 /* Hashing */
3129 hr = IMoniker_Hash(moniker, &hash);
3130 ok_ole_success(hr, IMoniker_Hash);
3131 ok(hash == PtrToUlong(&factory.IClassFactory_iface), "Unexpected hash value %#x.\n", hash);
3133 /* IsSystemMoniker test */
3134 TEST_MONIKER_TYPE(moniker, MKSYS_POINTERMONIKER);
3136 hr = IMoniker_Inverse(moniker, &inverse);
3137 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
3138 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
3139 IMoniker_Release(inverse);
3141 hr = CreateBindCtx(0, &bindctx);
3142 ok_ole_success(hr, CreateBindCtx);
3144 /* IsRunning test */
3145 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
3146 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
3148 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
3149 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
3151 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
3152 ok_ole_success(hr, IMoniker_BindToObject);
3153 IUnknown_Release(unknown);
3155 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
3156 ok_ole_success(hr, IMoniker_BindToStorage);
3157 IUnknown_Release(unknown);
3159 IMoniker_Release(moniker);
3161 ok(factory.refcount == 1, "Unexpected factory refcount %u.\n", factory.refcount);
3163 hr = CreatePointerMoniker(NULL, &moniker);
3164 ok_ole_success(hr, CreatePointerMoniker);
3166 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
3167 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
3169 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
3170 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
3172 IBindCtx_Release(bindctx);
3174 /* Enum() */
3175 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
3176 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3178 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
3179 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
3181 IMoniker_Release(moniker);
3183 /* CommonPrefixWith() */
3184 hr = CreatePointerMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker);
3185 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
3187 hr = CreatePointerMoniker((IUnknown *)&factory.IClassFactory_iface, &moniker2);
3188 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
3190 hr = IMoniker_IsEqual(moniker, NULL);
3191 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3193 hr = IMoniker_IsEqual(moniker, moniker2);
3194 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3196 hr = IMoniker_CommonPrefixWith(moniker, moniker2, NULL);
3197 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3199 hr = IMoniker_CommonPrefixWith(moniker, NULL, &prefix);
3200 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3202 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
3203 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
3204 ok(prefix == moniker, "Unexpected pointer.\n");
3205 IMoniker_Release(prefix);
3207 IMoniker_Release(moniker2);
3209 hr = CreatePointerMoniker((IUnknown *)moniker, &moniker2);
3210 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
3212 hr = IMoniker_IsEqual(moniker, moniker2);
3213 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
3215 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
3216 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3218 IMoniker_Release(moniker2);
3220 /* ComposeWith() */
3222 /* P + A -> () */
3223 anti = create_antimoniker(1);
3224 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
3225 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
3226 ok(!moniker2, "Unexpected pointer.\n");
3227 IMoniker_Release(anti);
3229 /* P + A2 -> A */
3230 anti = create_antimoniker(2);
3231 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
3232 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
3233 TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER);
3234 IMoniker_Release(moniker2);
3236 IMoniker_Release(anti);
3238 IMoniker_Release(moniker);
3241 static void test_bind_context(void)
3243 IRunningObjectTable *rot, *rot2;
3244 HRESULT hr;
3245 IBindCtx *pBindCtx;
3246 IEnumString *pEnumString;
3247 BIND_OPTS3 bind_opts;
3248 HeapUnknown *unknown;
3249 HeapUnknown *unknown2;
3250 IUnknown *param_obj;
3251 ULONG refs;
3252 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
3253 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
3255 hr = CreateBindCtx(0, NULL);
3256 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3258 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
3259 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3261 hr = CreateBindCtx(0, &pBindCtx);
3262 ok_ole_success(hr, "CreateBindCtx");
3264 hr = IBindCtx_GetRunningObjectTable(pBindCtx, NULL);
3265 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
3267 hr = IBindCtx_GetRunningObjectTable(pBindCtx, &rot);
3268 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3270 hr = GetRunningObjectTable(0, &rot2);
3271 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3272 ok(rot == rot2, "Unexpected ROT instance.\n");
3273 IRunningObjectTable_Release(rot);
3274 IRunningObjectTable_Release(rot2);
3276 bind_opts.cbStruct = -1;
3277 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3278 ok_ole_success(hr, "IBindCtx_GetBindOptions");
3279 ok(bind_opts.cbStruct == sizeof(BIND_OPTS3) || broken(bind_opts.cbStruct == sizeof(BIND_OPTS2)) /* XP */,
3280 "Unexpected bind_opts.cbStruct %d.\n", bind_opts.cbStruct);
3282 bind_opts.cbStruct = sizeof(BIND_OPTS);
3283 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3284 ok_ole_success(hr, "IBindCtx_GetBindOptions");
3285 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
3287 memset(&bind_opts, 0xfe, sizeof(bind_opts));
3288 bind_opts.cbStruct = sizeof(bind_opts);
3289 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3290 ok_ole_success(hr, "IBindCtx_GetBindOptions");
3291 ok(bind_opts.cbStruct == sizeof(bind_opts) || bind_opts.cbStruct == sizeof(BIND_OPTS2) /* XP */,
3292 "Unexpected bind_opts.cbStruct %d.\n", bind_opts.cbStruct);
3293 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
3294 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
3295 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
3296 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
3297 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
3298 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
3299 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
3300 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
3301 if (bind_opts.cbStruct >= sizeof(BIND_OPTS3))
3302 ok(bind_opts.hwnd == NULL, "Unexpected bind_opts.hwnd %p.\n", bind_opts.hwnd);
3304 bind_opts.cbStruct = -1;
3305 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3306 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3308 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
3309 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3311 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
3312 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
3313 unknown->refs = 1;
3314 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface);
3315 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
3317 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
3318 ok_ole_success(hr, "IBindCtx_GetObjectParam");
3319 IUnknown_Release(param_obj);
3321 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
3322 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
3323 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
3325 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
3326 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
3328 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
3329 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
3330 ok(!pEnumString, "pEnumString should be NULL\n");
3332 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
3333 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
3335 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
3336 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
3338 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
3339 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
3340 unknown2->refs = 1;
3341 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface);
3342 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
3344 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
3345 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
3347 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
3348 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
3350 IBindCtx_Release(pBindCtx);
3352 refs = IUnknown_Release(&unknown->IUnknown_iface);
3353 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
3355 refs = IUnknown_Release(&unknown2->IUnknown_iface);
3356 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
3359 static void test_save_load_filemoniker(void)
3361 IMoniker* pMk;
3362 IStream* pStm;
3363 HRESULT hr;
3364 ULARGE_INTEGER size;
3365 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
3366 DWORD some_val = 0xFEDCBA98;
3367 int i;
3369 /* see FileMonikerImpl_Save docs */
3370 zero_pos.QuadPart = 0;
3371 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
3372 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
3374 /* create the stream we're going to write to */
3375 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
3376 ok_ole_success(hr, "CreateStreamOnHGlobal");
3378 size.u.LowPart = 128;
3379 hr = IStream_SetSize(pStm, size);
3380 ok_ole_success(hr, "IStream_SetSize");
3382 /* create and save a moniker */
3383 hr = CreateFileMoniker(wszFileName1, &pMk);
3384 ok_ole_success(hr, "CreateFileMoniker");
3386 hr = IMoniker_Save(pMk, pStm, TRUE);
3387 ok_ole_success(hr, "IMoniker_Save");
3388 IMoniker_Release(pMk);
3390 /* overwrite the constants with various values */
3391 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
3392 ok_ole_success(hr, "IStream_Seek");
3393 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
3394 ok_ole_success(hr, "IStream_Write");
3396 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
3397 ok_ole_success(hr, "IStream_Seek");
3398 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
3399 ok_ole_success(hr, "IStream_Write");
3401 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
3402 ok_ole_success(hr, "IStream_Seek");
3403 for(i = 0; i < 5; ++i){
3404 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
3405 ok_ole_success(hr, "IStream_Write");
3408 /* go back to the start of the stream */
3409 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
3410 ok_ole_success(hr, "IStream_Seek");
3412 /* create a new moniker and load into it */
3413 hr = CreateFileMoniker(wszFileName1, &pMk);
3414 ok_ole_success(hr, "CreateFileMoniker");
3416 hr = IMoniker_Load(pMk, pStm);
3417 ok_ole_success(hr, "IMoniker_Load");
3419 IMoniker_Release(pMk);
3420 IStream_Release(pStm);
3423 static void test_MonikerCommonPrefixWith(void)
3425 IMoniker *moniker, *item, *file1, *file2, *composite, *composite2;
3426 HRESULT hr;
3428 moniker = (void *)0xdeadbeef;
3429 hr = MonikerCommonPrefixWith(NULL, NULL, &moniker);
3430 todo_wine {
3431 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3432 ok(!moniker, "Unexpected pointer.\n");
3434 if (hr == E_NOTIMPL)
3435 return;
3437 hr = CreateItemMoniker(L"!", L"Item", &item);
3438 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3440 hr = MonikerCommonPrefixWith(item, NULL, &moniker);
3441 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3443 hr = MonikerCommonPrefixWith(NULL, item, &moniker);
3444 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3446 hr = MonikerCommonPrefixWith(item, item, &moniker);
3447 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3449 hr = CreateFileMoniker(L"C:\\test.txt", &file1);
3450 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3452 hr = MonikerCommonPrefixWith(file1, NULL, &moniker);
3453 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3455 hr = MonikerCommonPrefixWith(NULL, file1, &moniker);
3456 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3458 /* F x F */
3459 hr = MonikerCommonPrefixWith(file1, file1, &moniker);
3460 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3462 hr = CreateFileMoniker(L"C:\\a\\test.txt", &file2);
3463 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3465 /* F1 x F2 */
3466 hr = MonikerCommonPrefixWith(file1, file2, &moniker);
3467 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3469 hr = CreateGenericComposite(file1, item, &composite);
3470 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3472 hr = CreateGenericComposite(file2, item, &composite2);
3473 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3475 /* F x (F,I) -> F */
3476 hr = MonikerCommonPrefixWith(file1, composite, &moniker);
3477 ok(hr == MK_S_ME, "Unexpected hr %#x.\n", hr);
3478 ok(moniker == file1, "Unexpected pointer.\n");
3479 IMoniker_Release(moniker);
3481 /* F1 x (F2,I) -> F */
3482 hr = MonikerCommonPrefixWith(file1, composite2, &moniker);
3483 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3484 TEST_MONIKER_TYPE(moniker, MKSYS_FILEMONIKER);
3485 TEST_DISPLAY_NAME(moniker, L"C:\\");
3486 IMoniker_Release(moniker);
3488 /* (F2,I) x F1 -> F */
3489 hr = MonikerCommonPrefixWith(composite2, file1, &moniker);
3490 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3491 TEST_MONIKER_TYPE(moniker, MKSYS_FILEMONIKER);
3492 TEST_DISPLAY_NAME(moniker, L"C:\\");
3493 IMoniker_Release(moniker);
3495 /* (F,I) x (F) -> F */
3496 hr = MonikerCommonPrefixWith(composite, file1, &moniker);
3497 ok(hr == MK_S_HIM, "Unexpected hr %#x.\n", hr);
3498 ok(moniker == file1, "Unexpected pointer.\n");
3499 IMoniker_Release(moniker);
3501 /* (F,I) x (F,I) -> (F,I) */
3502 hr = MonikerCommonPrefixWith(composite, composite, &moniker);
3503 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
3504 TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
3505 TEST_DISPLAY_NAME(moniker, L"C:\\test.txt!Item");
3506 ok(moniker != composite, "Unexpected pointer.\n");
3507 IMoniker_Release(moniker);
3509 /* (F1,I) x (F2,I) -> () */
3510 hr = MonikerCommonPrefixWith(composite, composite2, &moniker);
3511 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3512 ok(!moniker, "Unexpected pointer %p.\n", moniker);
3514 IMoniker_Release(composite2);
3515 IMoniker_Release(composite);
3516 IMoniker_Release(file2);
3517 IMoniker_Release(file1);
3518 IMoniker_Release(item);
3521 START_TEST(moniker)
3523 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3525 test_ROT();
3526 test_ROT_multiple_entries();
3527 test_MkParseDisplayName();
3528 test_class_moniker();
3529 test_file_monikers();
3530 test_item_moniker();
3531 test_anti_moniker();
3532 test_generic_composite_moniker();
3533 test_pointer_moniker();
3534 test_save_load_filemoniker();
3535 test_MonikerCommonPrefixWith();
3537 /* FIXME: test moniker creation funcs and parsing other moniker formats */
3539 test_bind_context();
3541 CoUninitialize();