mfplat: Implement GetScanline0AndPitch() for d3d11 buffers.
[wine/zf.git] / dlls / ole32 / tests / moniker.c
blob6be75f75c2872eba47bde65f90a2fafc64071452
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_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
40 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
41 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
43 #define CHECK_EXPECTED_METHOD(method_name) \
44 do { \
45 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
46 if (*expected_method_list) \
47 { \
48 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
49 *expected_method_list, method_name); \
50 expected_method_list++; \
51 } \
52 } while(0)
54 static char const * const *expected_method_list;
55 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
56 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
58 static const CLSID CLSID_TestMoniker =
59 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
60 0xb306bfbc,
61 0x496e,
62 0x4f53,
63 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
66 DEFINE_OLEGUID(CLSID_FileMoniker, 0x303, 0, 0);
67 DEFINE_OLEGUID(CLSID_ItemMoniker, 0x304, 0, 0);
68 DEFINE_OLEGUID(CLSID_AntiMoniker, 0x305, 0, 0);
69 DEFINE_OLEGUID(CLSID_CompositeMoniker, 0x309, 0, 0);
70 DEFINE_OLEGUID(CLSID_ClassMoniker, 0x31a, 0, 0);
71 DEFINE_OLEGUID(CLSID_PointerMoniker, 0x306, 0, 0);
73 #define EXPECT_REF(obj,ref) _expect_ref((IUnknown *)obj, ref, __LINE__)
74 static void _expect_ref(IUnknown* obj, ULONG ref, int line)
76 ULONG refcount;
77 IUnknown_AddRef(obj);
78 refcount = IUnknown_Release(obj);
79 ok_(__FILE__, line)(refcount == ref, "Unexpected got %u.\n", refcount);
82 #define TEST_MONIKER_TYPE_TODO(m,t) _test_moniker_type(m, t, TRUE, __LINE__)
83 #define TEST_MONIKER_TYPE(m,t) _test_moniker_type(m, t, FALSE, __LINE__)
84 static void _test_moniker_type(IMoniker *moniker, DWORD type, BOOL todo, int line)
86 DWORD type2;
87 HRESULT hr;
89 hr = IMoniker_IsSystemMoniker(moniker, &type2);
90 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#x.\n", hr);
91 todo_wine_if(todo)
92 ok_(__FILE__, line)(type2 == type, "Unexpected moniker type %d.\n", type2);
95 #define TEST_DISPLAY_NAME(m,name) _test_moniker_name(m, name, __LINE__)
96 static void _test_moniker_name(IMoniker *moniker, const WCHAR *name, int line)
98 WCHAR *display_name;
99 IBindCtx *pbc;
100 HRESULT hr;
102 hr = CreateBindCtx(0, &pbc);
103 ok_(__FILE__, line)(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
105 hr = IMoniker_GetDisplayName(moniker, pbc, NULL, &display_name);
106 ok_(__FILE__, line)(hr == S_OK, "Failed to get display name, hr %#x.\n", hr);
107 ok_(__FILE__, line)(!lstrcmpW(display_name, name), "Unexpected display name %s.\n", wine_dbgstr_w(display_name));
109 CoTaskMemFree(display_name);
110 IBindCtx_Release(pbc);
113 static IMoniker *create_antimoniker(DWORD level)
115 LARGE_INTEGER pos;
116 IMoniker *moniker;
117 IStream *stream;
118 HRESULT hr;
120 hr = CreateAntiMoniker(&moniker);
121 ok(hr == S_OK, "Failed to create antimoniker, hr %#x.\n", hr);
123 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
124 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
126 hr = IStream_Write(stream, &level, sizeof(level), NULL);
127 ok(hr == S_OK, "Failed to write contents, hr %#x.\n", hr);
129 pos.QuadPart = 0;
130 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
131 ok(hr == S_OK, "Failed to rewind, hr %#x.\n", hr);
133 hr = IMoniker_Load(moniker, stream);
134 ok(hr == S_OK, "Failed to load, hr %#x.\n", hr);
136 IStream_Release(stream);
138 return moniker;
141 static LONG cLocks;
143 static void LockModule(void)
145 InterlockedIncrement(&cLocks);
148 static void UnlockModule(void)
150 InterlockedDecrement(&cLocks);
153 static SIZE_T round_global_size(SIZE_T size)
155 static SIZE_T global_size_alignment = -1;
156 if (global_size_alignment == -1)
158 void *p = GlobalAlloc(GMEM_FIXED, 1);
159 global_size_alignment = GlobalSize(p);
160 GlobalFree(p);
163 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
166 static DWORD external_connections;
168 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
170 ok(0, "unexpected call\n");
171 *ppv = NULL;
172 return E_NOINTERFACE;
175 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
177 return 2;
180 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
182 return 1;
185 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
187 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
188 ok(!reserved, "reserved = %x\n", reserved);
189 return ++external_connections;
192 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
193 DWORD reserved, BOOL fLastReleaseCloses)
195 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
196 ok(!reserved, "reserved = %x\n", reserved);
198 return --external_connections;
201 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
202 ExternalConnection_QueryInterface,
203 ExternalConnection_AddRef,
204 ExternalConnection_Release,
205 ExternalConnection_AddConnection,
206 ExternalConnection_ReleaseConnection
209 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
211 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
212 LPCLASSFACTORY iface,
213 REFIID riid,
214 LPVOID *ppvObj)
216 if (ppvObj == NULL) return E_POINTER;
218 if (IsEqualGUID(riid, &IID_IUnknown) ||
219 IsEqualGUID(riid, &IID_IClassFactory))
221 *ppvObj = iface;
222 IClassFactory_AddRef(iface);
223 return S_OK;
226 if(IsEqualGUID(riid, &IID_IExternalConnection)) {
227 *ppvObj = &ExternalConnection;
228 return S_OK;
231 *ppvObj = NULL;
232 return E_NOINTERFACE;
235 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
237 LockModule();
238 return 2; /* non-heap-based object */
241 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
243 UnlockModule();
244 return 1; /* non-heap-based object */
247 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
248 LPCLASSFACTORY iface,
249 LPUNKNOWN pUnkOuter,
250 REFIID riid,
251 LPVOID *ppvObj)
253 return E_NOTIMPL;
256 static HRESULT WINAPI Test_IClassFactory_LockServer(
257 LPCLASSFACTORY iface,
258 BOOL fLock)
260 return S_OK;
263 static const IClassFactoryVtbl TestClassFactory_Vtbl =
265 Test_IClassFactory_QueryInterface,
266 Test_IClassFactory_AddRef,
267 Test_IClassFactory_Release,
268 Test_IClassFactory_CreateInstance,
269 Test_IClassFactory_LockServer
272 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
274 typedef struct
276 IUnknown IUnknown_iface;
277 ULONG refs;
278 } HeapUnknown;
280 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
282 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
285 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
287 if (IsEqualIID(riid, &IID_IUnknown))
289 IUnknown_AddRef(iface);
290 *ppv = iface;
291 return S_OK;
293 *ppv = NULL;
294 return E_NOINTERFACE;
297 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
299 HeapUnknown *This = impl_from_IUnknown(iface);
300 return InterlockedIncrement((LONG*)&This->refs);
303 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
305 HeapUnknown *This = impl_from_IUnknown(iface);
306 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
307 if (!refs) HeapFree(GetProcessHeap(), 0, This);
308 return refs;
311 static const IUnknownVtbl HeapUnknown_Vtbl =
313 HeapUnknown_QueryInterface,
314 HeapUnknown_AddRef,
315 HeapUnknown_Release
318 struct test_moniker
320 IMoniker IMoniker_iface;
321 IROTData IROTData_iface;
322 IOleItemContainer IOleItemContainer_iface;
323 IParseDisplayName IParseDisplayName_iface;
324 LONG refcount;
326 BOOL no_IROTData;
329 static struct test_moniker *impl_from_IMoniker(IMoniker *iface)
331 return CONTAINING_RECORD(iface, struct test_moniker, IMoniker_iface);
334 static struct test_moniker *impl_from_IROTData(IROTData *iface)
336 return CONTAINING_RECORD(iface, struct test_moniker, IROTData_iface);
339 static struct test_moniker *impl_from_IOleItemContainer(IOleItemContainer *iface)
341 return CONTAINING_RECORD(iface, struct test_moniker, IOleItemContainer_iface);
344 static struct test_moniker *impl_from_IParseDisplayName(IParseDisplayName *iface)
346 return CONTAINING_RECORD(iface, struct test_moniker, IParseDisplayName_iface);
349 static HRESULT WINAPI test_moniker_parse_QueryInterface(IParseDisplayName *iface, REFIID riid, void **obj)
351 if (IsEqualIID(riid, &IID_IUnknown) ||
352 IsEqualIID(riid, &IID_IParseDisplayName))
354 *obj = iface;
355 IParseDisplayName_AddRef(iface);
356 return S_OK;
359 *obj = NULL;
360 return E_NOINTERFACE;
363 static ULONG WINAPI test_moniker_parse_AddRef(IParseDisplayName *iface)
365 struct test_moniker *moniker = impl_from_IParseDisplayName(iface);
366 return IMoniker_AddRef(&moniker->IMoniker_iface);
369 static ULONG WINAPI test_moniker_parse_Release(IParseDisplayName *iface)
371 struct test_moniker *moniker = impl_from_IParseDisplayName(iface);
372 return IMoniker_Release(&moniker->IMoniker_iface);
375 static HRESULT WINAPI test_moniker_parse_ParseDisplayName(IParseDisplayName *iface,
376 IBindCtx *pbc, LPOLESTR displayname, ULONG *eaten, IMoniker **out)
378 return E_NOTIMPL;
381 static const IParseDisplayNameVtbl test_moniker_parse_vtbl =
383 test_moniker_parse_QueryInterface,
384 test_moniker_parse_AddRef,
385 test_moniker_parse_Release,
386 test_moniker_parse_ParseDisplayName,
389 static HRESULT WINAPI test_item_container_QueryInterface(IOleItemContainer *iface, REFIID riid, void **obj)
391 if (IsEqualIID(riid, &IID_IOleItemContainer) ||
392 IsEqualIID(riid, &IID_IOleContainer) ||
393 IsEqualIID(riid, &IID_IParseDisplayName) ||
394 IsEqualIID(riid, &IID_IUnknown))
396 *obj = iface;
397 IOleItemContainer_AddRef(iface);
398 return S_OK;
401 *obj = NULL;
402 return E_NOINTERFACE;
405 static ULONG WINAPI test_item_container_AddRef(IOleItemContainer *iface)
407 struct test_moniker *moniker = impl_from_IOleItemContainer(iface);
408 return IMoniker_AddRef(&moniker->IMoniker_iface);
411 static ULONG WINAPI test_item_container_Release(IOleItemContainer *iface)
413 struct test_moniker *moniker = impl_from_IOleItemContainer(iface);
414 return IMoniker_Release(&moniker->IMoniker_iface);
417 static HRESULT WINAPI test_item_container_ParseDisplayName(IOleItemContainer *iface,
418 IBindCtx *pbc, LPOLESTR displayname, ULONG *eaten, IMoniker **out)
420 return E_NOTIMPL;
423 static HRESULT WINAPI test_item_container_EnumObjects(IOleItemContainer *iface, DWORD flags,
424 IEnumUnknown **ppenum)
426 return E_NOTIMPL;
429 static HRESULT WINAPI test_item_container_LockContainer(IOleItemContainer *iface, BOOL lock)
431 return S_OK;
434 static HRESULT WINAPI test_item_container_GetObject(IOleItemContainer *iface, LPOLESTR item,
435 DWORD bind_speed, IBindCtx *pbc, REFIID riid, void **obj)
437 struct test_moniker *moniker = impl_from_IOleItemContainer(iface);
439 if (IsEqualIID(riid, &IID_IParseDisplayName))
441 *obj = &moniker->IParseDisplayName_iface;
442 IOleItemContainer_AddRef(iface);
445 return 0x8bee0000 | bind_speed;
448 static HRESULT WINAPI test_item_container_GetObjectStorage(IOleItemContainer *iface, LPOLESTR item,
449 IBindCtx *pbc, REFIID riid, void **obj)
451 return 0x8bee0001;
454 static HRESULT WINAPI test_item_container_IsRunning(IOleItemContainer *iface, LPOLESTR item)
456 ok(0, "Unexpected call.\n");
457 return E_NOTIMPL;
460 static const IOleItemContainerVtbl test_item_container_vtbl =
462 test_item_container_QueryInterface,
463 test_item_container_AddRef,
464 test_item_container_Release,
465 test_item_container_ParseDisplayName,
466 test_item_container_EnumObjects,
467 test_item_container_LockContainer,
468 test_item_container_GetObject,
469 test_item_container_GetObjectStorage,
470 test_item_container_IsRunning,
473 static HRESULT WINAPI
474 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
476 struct test_moniker *moniker = impl_from_IMoniker(iface);
478 if (!ppvObject)
479 return E_INVALIDARG;
481 *ppvObject = 0;
483 if (IsEqualIID(&IID_IUnknown, riid) ||
484 IsEqualIID(&IID_IPersist, riid) ||
485 IsEqualIID(&IID_IPersistStream,riid) ||
486 IsEqualIID(&IID_IMoniker, riid))
487 *ppvObject = iface;
488 if (IsEqualIID(&IID_IROTData, riid))
490 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
491 if (!moniker->no_IROTData)
492 *ppvObject = &moniker->IROTData_iface;
495 if ((*ppvObject)==0)
496 return E_NOINTERFACE;
498 IMoniker_AddRef(iface);
500 return S_OK;
503 static ULONG WINAPI
504 Moniker_AddRef(IMoniker* iface)
506 struct test_moniker *moniker = impl_from_IMoniker(iface);
507 return InterlockedIncrement(&moniker->refcount);
510 static ULONG WINAPI
511 Moniker_Release(IMoniker* iface)
513 struct test_moniker *moniker = impl_from_IMoniker(iface);
514 ULONG refcount = InterlockedDecrement(&moniker->refcount);
516 if (!refcount)
517 heap_free(moniker);
519 return refcount;
522 static HRESULT WINAPI
523 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
525 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
527 *pClassID = CLSID_TestMoniker;
529 return S_OK;
532 static HRESULT WINAPI
533 Moniker_IsDirty(IMoniker* iface)
535 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
537 return S_FALSE;
540 static HRESULT WINAPI
541 Moniker_Load(IMoniker* iface, IStream* pStm)
543 CHECK_EXPECTED_METHOD("Moniker_Load");
544 return E_NOTIMPL;
547 static HRESULT WINAPI
548 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
550 CHECK_EXPECTED_METHOD("Moniker_Save");
551 return E_NOTIMPL;
554 static HRESULT WINAPI
555 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
557 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
558 return E_NOTIMPL;
561 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft, REFIID riid,
562 void **obj)
564 struct test_moniker *moniker = impl_from_IMoniker(iface);
566 if (IsEqualIID(riid, &IID_IOleItemContainer))
568 *obj = &moniker->IOleItemContainer_iface;
569 IMoniker_AddRef(iface);
570 return S_OK;
573 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
574 return E_NOTIMPL;
577 static HRESULT WINAPI
578 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
579 REFIID riid, VOID** ppvObject)
581 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
582 return E_NOTIMPL;
585 static HRESULT WINAPI
586 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
587 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
589 CHECK_EXPECTED_METHOD("Moniker_Reduce");
591 if (ppmkReduced==NULL)
592 return E_POINTER;
594 IMoniker_AddRef(iface);
596 *ppmkReduced=iface;
598 return MK_S_REDUCED_TO_SELF;
601 static HRESULT WINAPI
602 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
603 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
605 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
606 return E_NOTIMPL;
609 static HRESULT WINAPI
610 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
612 CHECK_EXPECTED_METHOD("Moniker_Enum");
614 if (ppenumMoniker == NULL)
615 return E_POINTER;
617 *ppenumMoniker = NULL;
619 return S_OK;
622 static HRESULT WINAPI
623 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
625 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
626 return E_NOTIMPL;
629 static HRESULT WINAPI
630 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
632 CHECK_EXPECTED_METHOD("Moniker_Hash");
633 return E_NOTIMPL;
636 static HRESULT WINAPI
637 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
638 IMoniker* pmkNewlyRunning)
640 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
641 return 0x8beef000;
644 static HRESULT WINAPI
645 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
646 IMoniker* pmkToLeft, FILETIME* pFileTime)
648 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
649 return E_NOTIMPL;
652 static HRESULT WINAPI
653 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
655 CHECK_EXPECTED_METHOD("Moniker_Inverse");
656 return E_NOTIMPL;
659 static HRESULT WINAPI
660 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
662 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
663 return E_NOTIMPL;
666 static HRESULT WINAPI
667 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
669 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
670 return E_NOTIMPL;
673 static HRESULT WINAPI
674 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
675 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
677 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
678 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
679 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
680 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
681 return S_OK;
684 static HRESULT WINAPI
685 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
686 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
688 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
689 return E_NOTIMPL;
692 static HRESULT WINAPI
693 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
695 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
697 if (!pwdMksys)
698 return E_POINTER;
700 (*pwdMksys)=MKSYS_NONE;
702 return S_FALSE;
705 static HRESULT WINAPI
706 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
708 struct test_moniker *moniker = impl_from_IROTData(iface);
709 return IMoniker_QueryInterface(&moniker->IMoniker_iface, riid, ppvObject);
712 static ULONG WINAPI
713 ROTData_AddRef(IROTData *iface)
715 struct test_moniker *moniker = impl_from_IROTData(iface);
716 return IMoniker_AddRef(&moniker->IMoniker_iface);
719 static ULONG WINAPI
720 ROTData_Release(IROTData* iface)
722 struct test_moniker *moniker = impl_from_IROTData(iface);
723 return IMoniker_Release(&moniker->IMoniker_iface);
726 static HRESULT WINAPI
727 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
728 ULONG cbMax, ULONG* pcbData)
730 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
732 *pcbData = 1;
733 if (cbMax < *pcbData)
734 return E_OUTOFMEMORY;
736 *pbData = 0xde;
738 return S_OK;
741 static IROTDataVtbl ROTDataVtbl =
743 ROTData_QueryInterface,
744 ROTData_AddRef,
745 ROTData_Release,
746 ROTData_GetComparisonData
749 static const IMonikerVtbl MonikerVtbl =
751 Moniker_QueryInterface,
752 Moniker_AddRef,
753 Moniker_Release,
754 Moniker_GetClassID,
755 Moniker_IsDirty,
756 Moniker_Load,
757 Moniker_Save,
758 Moniker_GetSizeMax,
759 Moniker_BindToObject,
760 Moniker_BindToStorage,
761 Moniker_Reduce,
762 Moniker_ComposeWith,
763 Moniker_Enum,
764 Moniker_IsEqual,
765 Moniker_Hash,
766 Moniker_IsRunning,
767 Moniker_GetTimeOfLastChange,
768 Moniker_Inverse,
769 Moniker_CommonPrefixWith,
770 Moniker_RelativePathTo,
771 Moniker_GetDisplayName,
772 Moniker_ParseDisplayName,
773 Moniker_IsSystemMoniker
776 static struct test_moniker *create_test_moniker(void)
778 struct test_moniker *obj;
780 obj = heap_alloc_zero(sizeof(*obj));
781 obj->IMoniker_iface.lpVtbl = &MonikerVtbl;
782 obj->IROTData_iface.lpVtbl = &ROTDataVtbl;
783 obj->IOleItemContainer_iface.lpVtbl = &test_item_container_vtbl;
784 obj->IParseDisplayName_iface.lpVtbl = &test_moniker_parse_vtbl;
785 obj->refcount = 1;
787 return obj;
790 static void test_ROT(void)
792 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
793 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
794 '2','0','4','6','E','5','8','6','C','9','2','5',0};
795 HRESULT hr;
796 IMoniker *pMoniker = NULL;
797 struct test_moniker *test_moniker;
798 IRunningObjectTable *pROT = NULL;
799 DWORD dwCookie;
800 static const char *methods_register_no_ROTData[] =
802 "Moniker_Reduce",
803 "Moniker_GetTimeOfLastChange",
804 "Moniker_QueryInterface(IID_IROTData)",
805 "Moniker_GetDisplayName",
806 "Moniker_GetClassID",
807 NULL
809 static const char *methods_register[] =
811 "Moniker_Reduce",
812 "Moniker_GetTimeOfLastChange",
813 "Moniker_QueryInterface(IID_IROTData)",
814 "ROTData_GetComparisonData",
815 NULL
817 static const char *methods_isrunning_no_ROTData[] =
819 "Moniker_Reduce",
820 "Moniker_QueryInterface(IID_IROTData)",
821 "Moniker_GetDisplayName",
822 "Moniker_GetClassID",
823 NULL
825 static const char *methods_isrunning[] =
827 "Moniker_Reduce",
828 "Moniker_QueryInterface(IID_IROTData)",
829 "ROTData_GetComparisonData",
830 NULL
833 cLocks = 0;
835 hr = GetRunningObjectTable(0, &pROT);
836 ok_ole_success(hr, GetRunningObjectTable);
838 test_moniker = create_test_moniker();
839 test_moniker->no_IROTData = TRUE;
841 expected_method_list = methods_register_no_ROTData;
842 external_connections = 0;
843 /* try with our own moniker that doesn't support IROTData */
844 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE, (IUnknown *)&Test_ClassFactory,
845 &test_moniker->IMoniker_iface, &dwCookie);
846 ok(hr == S_OK, "Failed to register interface, hr %#x.\n", hr);
847 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
848 ok(external_connections == 1, "external_connections = %d\n", external_connections);
850 ok_more_than_one_lock();
852 expected_method_list = methods_isrunning_no_ROTData;
853 hr = IRunningObjectTable_IsRunning(pROT, &test_moniker->IMoniker_iface);
854 ok_ole_success(hr, IRunningObjectTable_IsRunning);
855 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
857 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
858 ok_ole_success(hr, IRunningObjectTable_Revoke);
859 ok(external_connections == 0, "external_connections = %d\n", external_connections);
861 ok_no_locks();
863 expected_method_list = methods_register;
864 /* try with our own moniker */
865 test_moniker->no_IROTData = FALSE;
866 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
867 (IUnknown *)&Test_ClassFactory, &test_moniker->IMoniker_iface, &dwCookie);
868 ok_ole_success(hr, IRunningObjectTable_Register);
869 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
871 ok_more_than_one_lock();
873 expected_method_list = methods_isrunning;
874 hr = IRunningObjectTable_IsRunning(pROT, &test_moniker->IMoniker_iface);
875 ok_ole_success(hr, IRunningObjectTable_IsRunning);
876 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
878 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
879 ok_ole_success(hr, IRunningObjectTable_Revoke);
881 ok_no_locks();
883 hr = CreateFileMoniker(wszFileName, &pMoniker);
884 ok_ole_success(hr, CreateClassMoniker);
886 /* test flags: 0 */
887 external_connections = 0;
888 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
889 pMoniker, &dwCookie);
890 ok_ole_success(hr, IRunningObjectTable_Register);
891 ok(external_connections == 0, "external_connections = %d\n", external_connections);
893 ok_more_than_one_lock();
895 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
896 ok_ole_success(hr, IRunningObjectTable_Revoke);
898 ok_no_locks();
900 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
901 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
902 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
903 ok_ole_success(hr, IRunningObjectTable_Register);
905 ok_more_than_one_lock();
907 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
908 ok_ole_success(hr, IRunningObjectTable_Revoke);
910 ok_no_locks();
912 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
913 /* only succeeds when process is started by SCM and has LocalService
914 * or RunAs AppId values */
915 hr = IRunningObjectTable_Register(pROT,
916 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
917 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
918 todo_wine {
919 ok(hr == CO_E_WRONG_SERVER_IDENTITY, "Unexpected hr %#x.\n", hr);
922 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
923 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
924 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
926 IMoniker_Release(pMoniker);
927 IMoniker_Release(&test_moniker->IMoniker_iface);
929 IRunningObjectTable_Release(pROT);
932 static void test_ROT_multiple_entries(void)
934 HRESULT hr;
935 IMoniker *pMoniker = NULL;
936 IRunningObjectTable *pROT = NULL;
937 DWORD dwCookie1, dwCookie2;
938 IUnknown *pObject = NULL;
939 static const WCHAR moniker_path[] =
940 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
942 hr = GetRunningObjectTable(0, &pROT);
943 ok_ole_success(hr, GetRunningObjectTable);
945 hr = CreateFileMoniker(moniker_path, &pMoniker);
946 ok_ole_success(hr, CreateFileMoniker);
948 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
949 ok_ole_success(hr, IRunningObjectTable_Register);
951 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
952 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
954 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
956 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
957 ok_ole_success(hr, IRunningObjectTable_GetObject);
958 IUnknown_Release(pObject);
960 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
961 ok_ole_success(hr, IRunningObjectTable_Revoke);
963 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
964 ok_ole_success(hr, IRunningObjectTable_GetObject);
965 IUnknown_Release(pObject);
967 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
968 ok_ole_success(hr, IRunningObjectTable_Revoke);
970 IMoniker_Release(pMoniker);
972 IRunningObjectTable_Release(pROT);
975 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
977 if (IsEqualIID(riid, &IID_IUnknown) ||
978 IsEqualIID(riid, &IID_IParseDisplayName))
980 *ppv = iface;
981 IParseDisplayName_AddRef(iface);
982 return S_OK;
984 *ppv = NULL;
985 return E_NOINTERFACE;
988 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
990 return 2;
993 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
995 return 1;
998 static LPCWSTR expected_display_name;
1000 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
1001 IBindCtx *pbc,
1002 LPOLESTR pszDisplayName,
1003 ULONG *pchEaten,
1004 IMoniker **ppmkOut)
1006 char display_nameA[256];
1007 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
1008 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
1009 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
1010 *pchEaten = lstrlenW(pszDisplayName);
1011 return CreateAntiMoniker(ppmkOut);
1014 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
1016 ParseDisplayName_QueryInterface,
1017 ParseDisplayName_AddRef,
1018 ParseDisplayName_Release,
1019 ParseDisplayName_ParseDisplayName
1022 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
1024 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
1026 IMoniker * spMoniker;
1027 int monCnt=0, matchCnt=0;
1029 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
1031 HRESULT hr;
1032 WCHAR * szDisplayn;
1033 monCnt++;
1034 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
1035 if (SUCCEEDED(hr))
1037 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
1038 matchCnt++;
1039 CoTaskMemFree(szDisplayn);
1042 return matchCnt;
1045 static void test_MkParseDisplayName(void)
1047 IBindCtx * pbc = NULL;
1048 HRESULT hr;
1049 IMoniker * pmk = NULL;
1050 IMoniker * pmk1 = NULL;
1051 IMoniker * pmk2 = NULL;
1052 ULONG eaten;
1053 int matchCnt;
1054 IUnknown * object = NULL;
1056 IUnknown *lpEM1;
1058 IEnumMoniker *spEM1 = NULL;
1059 IEnumMoniker *spEM2 = NULL;
1060 IEnumMoniker *spEM3 = NULL;
1062 DWORD pdwReg1=0;
1063 DWORD grflags=0;
1064 DWORD pdwReg2=0;
1065 IRunningObjectTable * pprot=NULL;
1067 /* CLSID of My Computer */
1068 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
1069 '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};
1070 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
1071 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
1072 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
1073 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
1074 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
1075 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
1076 static const WCHAR wszEmpty[] = {0};
1077 char szDisplayNameFile[256];
1078 WCHAR wszDisplayNameFile[256];
1079 int i, len;
1081 const struct
1083 LPBC *ppbc;
1084 LPCOLESTR szDisplayName;
1085 LPDWORD pchEaten;
1086 LPMONIKER *ppmk;
1087 } invalid_parameters[] =
1089 {NULL, NULL, NULL, NULL},
1090 {NULL, NULL, NULL, &pmk},
1091 {NULL, NULL, &eaten, NULL},
1092 {NULL, NULL, &eaten, &pmk},
1093 {NULL, wszEmpty, NULL, NULL},
1094 {NULL, wszEmpty, NULL, &pmk},
1095 {NULL, wszEmpty, &eaten, NULL},
1096 {NULL, wszEmpty, &eaten, &pmk},
1097 {&pbc, NULL, NULL, NULL},
1098 {&pbc, NULL, NULL, &pmk},
1099 {&pbc, NULL, &eaten, NULL},
1100 {&pbc, NULL, &eaten, &pmk},
1101 {&pbc, wszEmpty, NULL, NULL},
1102 {&pbc, wszEmpty, NULL, &pmk},
1103 {&pbc, wszEmpty, &eaten, NULL},
1104 {&pbc, wszEmpty, &eaten, &pmk},
1107 hr = CreateBindCtx(0, &pbc);
1108 ok_ole_success(hr, CreateBindCtx);
1110 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++)
1112 eaten = 0xdeadbeef;
1113 pmk = (IMoniker *)0xdeadbeef;
1114 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
1115 invalid_parameters[i].szDisplayName,
1116 invalid_parameters[i].pchEaten,
1117 invalid_parameters[i].ppmk);
1118 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
1119 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
1120 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
1123 eaten = 0xdeadbeef;
1124 pmk = (IMoniker *)0xdeadbeef;
1125 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
1126 todo_wine
1127 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
1128 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1129 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1131 /* no special handling of "clsid:" without the string form of the clsid
1132 * following */
1133 eaten = 0xdeadbeef;
1134 pmk = (IMoniker *)0xdeadbeef;
1135 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
1136 todo_wine
1137 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
1138 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1139 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1141 /* shows clsid has higher precedence than a running object */
1142 hr = CreateFileMoniker(wszDisplayName, &pmk);
1143 ok_ole_success(hr, CreateFileMoniker);
1144 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1145 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
1146 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
1147 ok_ole_success(hr, IRunningObjectTable_Register);
1148 IMoniker_Release(pmk);
1149 pmk = NULL;
1150 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
1151 ok_ole_success(hr, MkParseDisplayName);
1152 ok(eaten == ARRAY_SIZE(wszDisplayName) - 1,
1153 "Processed character count should have been 43 instead of %u\n", eaten);
1154 if (pmk)
1156 TEST_MONIKER_TYPE(pmk, MKSYS_CLASSMONIKER);
1157 IMoniker_Release(pmk);
1159 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
1160 ok_ole_success(hr, IRunningObjectTable_Revoke);
1161 IRunningObjectTable_Release(pprot);
1163 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
1164 ok_ole_success(hr, CreateFileMoniker);
1165 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1166 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
1167 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
1168 ok_ole_success(hr, IRunningObjectTable_Register);
1169 IMoniker_Release(pmk);
1170 pmk = NULL;
1171 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
1172 ok_ole_success(hr, MkParseDisplayName);
1173 ok(eaten == ARRAY_SIZE(wszDisplayNameRunning) - 1,
1174 "Processed character count should have been 15 instead of %u\n", eaten);
1175 if (pmk)
1177 TEST_MONIKER_TYPE(pmk, MKSYS_FILEMONIKER);
1178 IMoniker_Release(pmk);
1180 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
1181 ok_ole_success(hr, IRunningObjectTable_Revoke);
1182 IRunningObjectTable_Release(pprot);
1184 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
1185 ok_ole_success(hr, CoRegisterClassObject);
1187 expected_display_name = wszDisplayNameProgId1;
1188 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
1189 ok_ole_success(hr, MkParseDisplayName);
1190 ok(eaten == ARRAY_SIZE(wszDisplayNameProgId1) - 1,
1191 "Processed character count should have been 8 instead of %u\n", eaten);
1192 if (pmk)
1194 TEST_MONIKER_TYPE(pmk, MKSYS_ANTIMONIKER);
1195 IMoniker_Release(pmk);
1198 expected_display_name = wszDisplayNameProgId2;
1199 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
1200 ok_ole_success(hr, MkParseDisplayName);
1201 ok(eaten == ARRAY_SIZE(wszDisplayNameProgId2) - 1,
1202 "Processed character count should have been 8 instead of %u\n", eaten);
1203 if (pmk)
1205 TEST_MONIKER_TYPE(pmk, MKSYS_ANTIMONIKER);
1206 IMoniker_Release(pmk);
1209 eaten = 0xdeadbeef;
1210 pmk = (IMoniker *)0xdeadbeef;
1211 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
1212 todo_wine
1213 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
1214 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1215 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1217 hr = CoRevokeClassObject(pdwReg1);
1218 ok_ole_success(hr, CoRevokeClassObject);
1220 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
1221 strcat(szDisplayNameFile, "\\kernel32.dll");
1222 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile,
1223 ARRAY_SIZE(wszDisplayNameFile));
1224 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
1225 ok_ole_success(hr, MkParseDisplayName);
1226 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
1227 if (pmk)
1229 TEST_MONIKER_TYPE(pmk, MKSYS_FILEMONIKER);
1230 IMoniker_Release(pmk);
1233 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
1234 ok_ole_success(hr, MkParseDisplayName);
1235 ok(eaten == ARRAY_SIZE(wszDisplayName) - 1,
1236 "Processed character count should have been 43 instead of %u\n", eaten);
1238 if (pmk)
1240 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
1241 ok_ole_success(hr, IMoniker_BindToObject);
1243 if (SUCCEEDED(hr))
1244 IUnknown_Release(object);
1245 IMoniker_Release(pmk);
1247 IBindCtx_Release(pbc);
1249 /* Test the EnumMoniker interface */
1250 hr = CreateBindCtx(0, &pbc);
1251 ok_ole_success(hr, CreateBindCtx);
1253 hr = CreateFileMoniker(wszFileName1, &pmk1);
1254 ok(hr == S_OK, "Failed to create file moniker, hr %#x.\n", hr);
1255 hr = CreateFileMoniker(wszFileName2, &pmk2);
1256 ok(hr == S_OK, "Failed to create file moniker, hr %#x.\n", hr);
1257 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1258 ok(hr == S_OK, "Failed to get ROT, hr %#x.\n", hr);
1260 /* Check EnumMoniker before registering */
1261 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1262 ok(hr == S_OK, "Failed to get enum object, hr %#x.\n", hr);
1263 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void *)&lpEM1);
1264 /* Register a couple of Monikers and check is ok */
1265 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
1267 matchCnt = count_moniker_matches(pbc, spEM1);
1269 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1270 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1271 ok(hr == S_OK, "Failed to register object, hr %#x.\n", hr);
1273 grflags=0;
1274 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1275 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1276 ok(hr == S_OK, "Failed to register object, hr %#x.\n", hr);
1278 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1279 ok(hr == S_OK, "Failed to get enum object, hr %#x.\n", hr);
1281 matchCnt = count_moniker_matches(pbc, spEM2);
1282 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1284 IEnumMoniker_Clone(spEM2, &spEM3);
1286 matchCnt = count_moniker_matches(pbc, spEM3);
1287 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1288 IEnumMoniker_Reset(spEM3);
1290 matchCnt = count_moniker_matches(pbc, spEM3);
1291 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1293 hr = IRunningObjectTable_Revoke(pprot,pdwReg1);
1294 ok(hr == S_OK, "Failed to revoke, hr %#x.\n", hr);
1295 hr = IRunningObjectTable_Revoke(pprot,pdwReg2);
1296 ok(hr == S_OK, "Failed to revoke, hr %#x.\n", hr);
1297 IUnknown_Release(lpEM1);
1298 IEnumMoniker_Release(spEM1);
1299 IEnumMoniker_Release(spEM2);
1300 IEnumMoniker_Release(spEM3);
1301 IMoniker_Release(pmk1);
1302 IMoniker_Release(pmk2);
1303 IRunningObjectTable_Release(pprot);
1305 IBindCtx_Release(pbc);
1308 static const LARGE_INTEGER llZero;
1310 static const BYTE expected_class_moniker_marshal_data[] =
1312 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1313 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1314 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1315 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1316 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1317 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1318 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1319 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1320 0x00,0x00,0x00,0x00,
1323 static const BYTE expected_class_moniker_saved_data[] =
1325 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1326 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1327 0x00,0x00,0x00,0x00,
1330 static const BYTE expected_class_moniker_comparison_data[] =
1332 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1333 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1334 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1335 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1338 static const WCHAR expected_class_moniker_display_name[] =
1340 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1341 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1342 '0','0','0','0','4','6',':',0
1345 static const BYTE expected_item_moniker_comparison_data[] =
1347 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1348 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1349 '!',0x00, 'T',0x00, 'E',0x00, 'S',0x00,
1350 'T',0x00,0x00,0x00,
1353 static const BYTE expected_item_moniker_comparison_data2[] =
1355 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1356 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1357 'T',0x00, 'E',0x00, 'S',0x00, 'T',0x00,
1358 0x00,0x00,
1361 static const BYTE expected_item_moniker_comparison_data4[] =
1363 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1364 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1365 '&',0x00, '&',0x00, 'T',0x00, 'E',0x00,
1366 'S',0x00, 'T',0x00,0x00,0x00,
1369 static const BYTE expected_item_moniker_comparison_data5[] =
1371 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1372 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1373 'A',0x00, 'B',0x00, 'T',0x00, 'E',0x00,
1374 'S',0x00, 'T',0x00,0x00,0x00,
1377 static const BYTE expected_item_moniker_comparison_data6[] =
1379 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1380 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1381 0x00,0x00,
1384 static const BYTE expected_item_moniker_saved_data[] =
1386 0x02,0x00,0x00,0x00, '!',0x00,0x05,0x00,
1387 0x00,0x00, 'T', 'e', 's', 't',0x00,
1390 static const BYTE expected_item_moniker_saved_data2[] =
1392 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
1393 'T', 'e', 's', 't',0x00,
1396 static const BYTE expected_item_moniker_saved_data3[] =
1398 0x01,0x00,0x00,0x00,0x00,0x05,0x00,0x00,
1399 0x00,'T', 'e', 's', 't',0x00,
1402 static const BYTE expected_item_moniker_saved_data4[] =
1404 0x03,0x00,0x00,0x00, '&', '&',0x00,0x05,
1405 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1408 static const BYTE expected_item_moniker_saved_data5[] =
1410 0x03,0x00,0x00,0x00, 'a', 'b',0x00,0x05,
1411 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1414 static const BYTE expected_item_moniker_saved_data6[] =
1416 0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
1417 0x00,0x00,
1420 static const BYTE expected_item_moniker_marshal_data[] =
1422 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1423 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1424 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1425 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1426 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1427 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1428 0x02,0x00,0x00,0x00, '!',0x00,0x05,0x00,
1429 0x00,0x00, 'T', 'e', 's', 't',0x00,
1432 static const BYTE expected_item_moniker_marshal_data2[] =
1434 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1435 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1436 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1437 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1438 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1439 0x00,0x00,0x00,0x00,0x2e,0x00,0x00,0x00,
1440 0x00,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
1441 'T', 'e', 's', 't',0x00,
1444 static const BYTE expected_item_moniker_marshal_data3[] =
1446 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1447 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1448 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1449 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1450 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1451 0x00,0x00,0x00,0x00,0x32,0x00,0x00,0x00,
1452 0x01,0x00,0x00,0x00,0x00,0x05,0x00,0x00,
1453 0x00, 'T', 'e', 's', 't',0x00,
1456 static const BYTE expected_item_moniker_marshal_data4[] =
1458 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1459 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1460 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1461 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1462 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1463 0x00,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,
1464 0x03,0x00,0x00,0x00, '&', '&',0x00,0x05,
1465 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1468 static const BYTE expected_item_moniker_marshal_data5[] =
1470 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1471 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1472 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1473 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1474 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1475 0x00,0x00,0x00,0x00,0x3a,0x00,0x00,0x00,
1476 0x03,0x00,0x00,0x00, 'a', 'b',0x00,0x05,
1477 0x00,0x00,0x00, 'T', 'e', 's', 't',0x00,
1480 static const BYTE expected_item_moniker_marshal_data6[] =
1482 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1483 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1484 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1485 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1486 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1487 0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,
1488 0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,
1489 0x00,0x00,
1492 static const BYTE expected_anti_moniker_marshal_data[] =
1494 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1495 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1496 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1497 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1498 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1499 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1500 0x01,0x00,0x00,0x00,
1503 static const BYTE expected_anti_moniker_marshal_data2[] =
1505 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1506 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1507 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1508 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1509 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1510 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1511 0x02,0x00,0x00,0x00,
1514 static const BYTE expected_anti_moniker_saved_data[] =
1516 0x01,0x00,0x00,0x00,
1519 static const BYTE expected_anti_moniker_saved_data2[] =
1521 0x02,0x00,0x00,0x00,
1524 static const BYTE expected_anti_moniker_comparison_data[] =
1526 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1527 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1528 0x01,0x00,0x00,0x00,
1531 static const BYTE expected_anti_moniker_comparison_data2[] =
1533 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1534 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1535 0x02,0x00,0x00,0x00,
1538 static const BYTE expected_gc_moniker_marshal_data[] =
1540 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1541 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1542 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1543 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1544 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1545 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1546 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1547 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1548 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1549 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1550 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1551 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1552 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1553 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1554 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1555 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1556 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1557 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1558 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1559 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1560 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1561 0x00,0x57,0x69,0x6e,0x65,0x00,
1564 static const BYTE expected_gc_moniker_saved_data[] =
1566 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1567 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1568 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1569 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1570 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1571 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1572 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1573 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1574 0x65,0x00,
1577 static const BYTE expected_gc_moniker_comparison_data[] =
1579 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1580 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1581 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1582 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1583 '!',0x00, 'T',0x00, 'E',0x00, 'S',0x00,
1584 'T',0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1585 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1586 0x00,0x00,0x00,0x46, '#',0x00, 'W',0x00,
1587 'I',0x00, 'N',0x00, 'E',0x00,0x00,0x00,
1590 static void test_moniker(
1591 const char *testname, IMoniker *moniker,
1592 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1593 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1594 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1595 int expected_max_size, LPCWSTR expected_display_name)
1597 ULARGE_INTEGER max_size;
1598 IStream * stream;
1599 IROTData * rotdata;
1600 HRESULT hr;
1601 HGLOBAL hglobal;
1602 LPBYTE moniker_data;
1603 DWORD moniker_size;
1604 DWORD i, moniker_type;
1605 BOOL same;
1606 BYTE buffer[128];
1607 IMoniker * moniker_proxy;
1609 hr = IMoniker_IsDirty(moniker);
1610 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1612 /* Display Name */
1613 TEST_DISPLAY_NAME(moniker, expected_display_name);
1615 hr = IMoniker_IsDirty(moniker);
1616 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1618 /* IROTData::GetComparisonData test */
1620 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1621 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1623 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1624 ok_ole_success(hr, IROTData_GetComparisonData);
1626 if (hr != S_OK) moniker_size = 0;
1628 /* first check we have the right amount of data */
1629 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1630 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1631 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1633 /* then do a byte-by-byte comparison */
1634 same = TRUE;
1635 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1637 if (expected_moniker_comparison_data[i] != buffer[i])
1639 same = FALSE;
1640 break;
1644 ok(same, "%s: Comparison data differs\n", testname);
1645 if (!same)
1647 for (i = 0; i < moniker_size; i++)
1649 if (i % 8 == 0) printf(" ");
1650 printf("0x%02x,", buffer[i]);
1651 if (i % 8 == 7) printf("\n");
1653 printf("\n");
1656 IROTData_Release(rotdata);
1658 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1659 ok_ole_success(hr, CreateStreamOnHGlobal);
1661 /* Saving */
1662 moniker_type = 0;
1663 IMoniker_IsSystemMoniker(moniker, &moniker_type);
1665 hr = IMoniker_GetSizeMax(moniker, &max_size);
1666 ok(hr == S_OK, "Failed to get max size, hr %#x.\n", hr);
1667 todo_wine_if(moniker_type == MKSYS_GENERICCOMPOSITE)
1668 ok(expected_max_size == max_size.u.LowPart, "%s: unexpected max size %u.\n", testname, max_size.u.LowPart);
1670 hr = IMoniker_Save(moniker, stream, TRUE);
1671 ok_ole_success(hr, IMoniker_Save);
1673 hr = GetHGlobalFromStream(stream, &hglobal);
1674 ok_ole_success(hr, GetHGlobalFromStream);
1676 moniker_size = GlobalSize(hglobal);
1678 moniker_data = GlobalLock(hglobal);
1680 /* first check we have the right amount of data */
1681 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1682 "%s: Size of saved data differs (expected %d, actual %d)\n",
1683 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1685 /* then do a byte-by-byte comparison */
1686 same = TRUE;
1687 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1689 if (expected_moniker_saved_data[i] != moniker_data[i])
1691 same = FALSE;
1692 break;
1696 ok(same, "%s: Saved data differs\n", testname);
1697 if (!same)
1699 for (i = 0; i < moniker_size; i++)
1701 if (i % 8 == 0) printf(" ");
1702 printf("0x%02x,", moniker_data[i]);
1703 if (i % 8 == 7) printf("\n");
1705 printf("\n");
1708 GlobalUnlock(hglobal);
1710 IStream_Release(stream);
1712 /* Marshaling tests */
1714 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1715 ok_ole_success(hr, CreateStreamOnHGlobal);
1717 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1718 ok_ole_success(hr, CoMarshalInterface);
1720 hr = GetHGlobalFromStream(stream, &hglobal);
1721 ok_ole_success(hr, GetHGlobalFromStream);
1723 moniker_size = GlobalSize(hglobal);
1725 moniker_data = GlobalLock(hglobal);
1727 /* first check we have the right amount of data */
1728 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1729 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1730 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1732 /* then do a byte-by-byte comparison */
1733 same = TRUE;
1734 if (expected_moniker_marshal_data)
1736 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1738 if (expected_moniker_marshal_data[i] != moniker_data[i])
1740 same = FALSE;
1741 break;
1746 ok(same, "%s: Marshaled data differs\n", testname);
1747 if (!same)
1749 for (i = 0; i < moniker_size; i++)
1751 if (i % 8 == 0) printf(" ");
1752 printf("0x%02x,", moniker_data[i]);
1753 if (i % 8 == 7) printf("\n");
1755 printf("\n");
1758 GlobalUnlock(hglobal);
1760 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1761 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1762 ok_ole_success(hr, CoUnmarshalInterface);
1764 IStream_Release(stream);
1765 IMoniker_Release(moniker_proxy);
1768 static void test_class_moniker(void)
1770 IMoniker *moniker, *moniker2, *inverse, *reduced, *anti;
1771 IEnumMoniker *enummoniker;
1772 HRESULT hr;
1773 DWORD hash;
1774 IBindCtx *bindctx;
1775 IUnknown *unknown;
1776 FILETIME filetime;
1778 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1779 ok_ole_success(hr, CreateClassMoniker);
1781 hr = IMoniker_QueryInterface(moniker, &CLSID_ClassMoniker, (void **)&unknown);
1782 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1783 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
1784 IUnknown_Release(unknown);
1786 test_moniker("class moniker", moniker,
1787 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1788 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1789 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1790 sizeof(expected_class_moniker_saved_data), expected_class_moniker_display_name);
1792 /* Hashing */
1794 hr = IMoniker_Hash(moniker, &hash);
1795 ok_ole_success(hr, IMoniker_Hash);
1797 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1798 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1799 hash);
1801 /* IsSystemMoniker test */
1802 TEST_MONIKER_TYPE(moniker, MKSYS_CLASSMONIKER);
1804 hr = CreateBindCtx(0, &bindctx);
1805 ok_ole_success(hr, CreateBindCtx);
1807 /* IsRunning test */
1808 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1809 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1811 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1812 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1814 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1815 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1817 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1818 ok_ole_success(hr, IMoniker_BindToObject);
1819 IUnknown_Release(unknown);
1821 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1822 ok_ole_success(hr, IMoniker_BindToStorage);
1823 IUnknown_Release(unknown);
1825 hr = IMoniker_Inverse(moniker, &inverse);
1826 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
1827 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
1828 IMoniker_Release(inverse);
1830 /* Reduce() */
1831 hr = IMoniker_Reduce(moniker, NULL, MKRREDUCE_ALL, NULL, &reduced);
1832 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
1833 ok(reduced == moniker, "Unexpected moniker.\n");
1834 IMoniker_Release(reduced);
1836 /* Enum() */
1837 enummoniker = (void *)0xdeadbeef;
1838 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
1839 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1840 ok(!enummoniker, "Unexpected pointer.\n");
1842 enummoniker = (void *)0xdeadbeef;
1843 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
1844 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1845 ok(!enummoniker, "Unexpected pointer.\n");
1847 hr = IMoniker_Enum(moniker, FALSE, NULL);
1848 todo_wine
1849 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1851 IBindCtx_Release(bindctx);
1853 /* ComposeWith() */
1855 /* C + A -> () */
1856 anti = create_antimoniker(1);
1857 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
1858 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
1859 ok(!moniker2, "Unexpected pointer.\n");
1860 IMoniker_Release(anti);
1862 /* C + A2 -> A */
1863 anti = create_antimoniker(2);
1864 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
1865 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
1866 ok(!moniker2, "Unexpected pointer.\n");
1867 IMoniker_Release(anti);
1869 IMoniker_Release(moniker);
1872 static void test_file_moniker(WCHAR* path)
1874 IMoniker *moniker1 = NULL, *moniker2 = NULL, *inverse, *reduced, *anti;
1875 IEnumMoniker *enummoniker;
1876 IBindCtx *bind_ctx;
1877 IStream *stream;
1878 IUnknown *unk;
1879 DWORD hash;
1880 HRESULT hr;
1882 hr = CreateFileMoniker(path, &moniker1);
1883 ok_ole_success(hr, CreateFileMoniker);
1885 hr = IMoniker_QueryInterface(moniker1, &CLSID_FileMoniker, (void **)&unk);
1886 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1887 ok(unk == (IUnknown *)moniker1, "Unexpected interface.\n");
1888 IUnknown_Release(unk);
1890 hr = IMoniker_Inverse(moniker1, &inverse);
1891 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
1892 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
1893 IMoniker_Release(inverse);
1895 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1896 ok_ole_success(hr, CreateStreamOnHGlobal);
1898 /* Marshal */
1899 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1900 ok_ole_success(hr, CoMarshalInterface);
1902 /* Rewind */
1903 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1904 ok_ole_success(hr, IStream_Seek);
1906 /* Unmarshal */
1907 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1908 ok_ole_success(hr, CoUnmarshalInterface);
1910 hr = IMoniker_IsEqual(moniker1, moniker2);
1911 ok_ole_success(hr, IsEqual);
1913 /* Reduce() */
1914 hr = CreateBindCtx(0, &bind_ctx);
1915 ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
1917 hr = IMoniker_Reduce(moniker1, NULL, MKRREDUCE_ALL, NULL, &reduced);
1918 todo_wine
1919 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1921 hr = IMoniker_Reduce(moniker1, bind_ctx, MKRREDUCE_ALL, NULL, &reduced);
1922 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
1923 ok(reduced == moniker1, "Unexpected moniker.\n");
1924 IMoniker_Release(reduced);
1926 /* Enum() */
1927 enummoniker = (void *)0xdeadbeef;
1928 hr = IMoniker_Enum(moniker1, TRUE, &enummoniker);
1929 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1930 ok(!enummoniker, "Unexpected pointer.\n");
1932 enummoniker = (void *)0xdeadbeef;
1933 hr = IMoniker_Enum(moniker1, FALSE, &enummoniker);
1934 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
1935 ok(!enummoniker, "Unexpected pointer.\n");
1937 hr = IMoniker_Enum(moniker1, FALSE, NULL);
1938 todo_wine
1939 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
1941 IBindCtx_Release(bind_ctx);
1943 IStream_Release(stream);
1944 IMoniker_Release(moniker2);
1946 /* ComposeWith() */
1948 /* F + A -> () */
1949 anti = create_antimoniker(1);
1950 hr = IMoniker_ComposeWith(moniker1, anti, TRUE, &moniker2);
1951 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
1952 ok(!moniker2, "Unexpected pointer.\n");
1953 IMoniker_Release(anti);
1955 /* I + A2 -> (A) */
1956 anti = create_antimoniker(2);
1957 hr = IMoniker_ComposeWith(moniker1, anti, TRUE, &moniker2);
1958 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
1959 TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER);
1960 hr = IMoniker_Hash(moniker2, &hash);
1961 ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr);
1962 ok(hash == 0x80000001, "Unexpected hash.\n");
1963 IMoniker_Release(moniker2);
1965 IMoniker_Release(anti);
1967 IMoniker_Release(moniker1);
1970 static void test_file_monikers(void)
1972 static WCHAR wszFile[][30] = {
1973 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1974 {'\\', '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},
1975 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1976 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1977 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1978 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1979 * U+0100 .. = Latin extended-A
1981 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1984 int i;
1986 trace("ACP is %u\n", GetACP());
1988 for (i = 0; i < ARRAY_SIZE(wszFile); ++i)
1990 int j ;
1991 if (i == 2)
1993 BOOL used;
1994 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1995 if (used)
1997 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1998 continue;
2001 for (j = lstrlenW(wszFile[i]); j > 0; --j)
2003 wszFile[i][j] = 0;
2004 test_file_moniker(wszFile[i]);
2009 static void test_item_moniker(void)
2011 static const char item_moniker_unicode_delim_stream[] =
2013 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, '!',
2014 0x00, 0x02, 0x00, 0x00, 0x00, 'A', 0x00,
2016 static const char item_moniker_unicode_item_stream[] =
2018 0x02, 0x00, 0x00, 0x00, '!', 0x00, 0x05, 0x00,
2019 0x00, 0x00, 0xff, 0xff, 0x00, 'B', 0x00,
2021 static const char item_moniker_unicode_delim_item_stream[] =
2023 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, '!',
2024 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
2025 0x00, 'C', 0x00,
2027 static struct
2029 const char *data;
2030 int data_len;
2031 const WCHAR *display_name;
2033 item_moniker_data[] =
2035 { item_moniker_unicode_delim_stream, sizeof(item_moniker_unicode_delim_stream), L"!A" },
2036 { item_moniker_unicode_item_stream, sizeof(item_moniker_unicode_item_stream), L"!B" },
2037 { item_moniker_unicode_delim_item_stream, sizeof(item_moniker_unicode_delim_item_stream), L"!C" },
2039 static const struct
2041 const WCHAR *delim1;
2042 const WCHAR *item1;
2043 const WCHAR *delim2;
2044 const WCHAR *item2;
2045 HRESULT hr;
2046 } isequal_tests[] =
2048 { L"!", L"Item1", L"!", L"ITEM1", S_OK },
2049 { NULL, L"Item1", L"!", L"ITEM1", S_OK },
2050 { L"", L"Item1", L"!", L"ITEM1", S_OK },
2051 { L"&", L"Item1", L"!", L"ITEM1", S_OK },
2052 {L"&&", L"Item1", L"&", L"&Item1", S_FALSE },
2053 { NULL, L"Item1", NULL, L"Item2", S_FALSE },
2054 { NULL, L"Item1", NULL, L"ITEM1", S_OK },
2056 static const struct
2058 const WCHAR *delim;
2059 const WCHAR *item;
2060 DWORD hash;
2061 } hash_tests[] =
2063 { L"!", L"Test", 0x73c },
2064 { L"%", L"Test", 0x73c },
2065 { L"%", L"TEST", 0x73c },
2066 { L"%", L"T", 0x54 },
2067 { L"%", L"A", 0x41 },
2068 { L"%", L"a", 0x41 },
2070 static const char *methods_isrunning[] =
2072 "Moniker_IsRunning",
2073 NULL
2075 IMoniker *moniker, *moniker2, *reduced, *anti, *inverse;
2076 DWORD i, hash, eaten, cookie;
2077 HRESULT hr;
2078 IBindCtx *bindctx;
2079 IUnknown *unknown;
2080 static const WCHAR wszDelimiter[] = {'!',0};
2081 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
2082 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
2083 struct test_moniker *container_moniker;
2084 WCHAR displayname[16] = L"display name";
2085 IEnumMoniker *enummoniker;
2086 IRunningObjectTable *rot;
2087 BIND_OPTS bind_opts;
2088 LARGE_INTEGER pos;
2089 IStream *stream;
2091 hr = CreateItemMoniker(NULL, wszObjectName, &moniker);
2092 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2094 hr = IMoniker_QueryInterface(moniker, &CLSID_ItemMoniker, (void **)&unknown);
2095 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2096 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
2097 IUnknown_Release(unknown);
2099 test_moniker("item moniker 2", moniker,
2100 expected_item_moniker_marshal_data2, sizeof(expected_item_moniker_marshal_data2),
2101 expected_item_moniker_saved_data2, sizeof(expected_item_moniker_saved_data2),
2102 expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2),
2103 46, L"Test");
2105 IMoniker_Release(moniker);
2107 hr = CreateItemMoniker(L"", wszObjectName, &moniker);
2108 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2110 test_moniker("item moniker 3", moniker,
2111 expected_item_moniker_marshal_data3, sizeof(expected_item_moniker_marshal_data3),
2112 expected_item_moniker_saved_data3, sizeof(expected_item_moniker_saved_data3),
2113 expected_item_moniker_comparison_data2, sizeof(expected_item_moniker_comparison_data2),
2114 50, L"Test");
2116 IMoniker_Release(moniker);
2118 hr = CreateItemMoniker(L"&&", wszObjectName, &moniker);
2119 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2121 test_moniker("item moniker 4", moniker,
2122 expected_item_moniker_marshal_data4, sizeof(expected_item_moniker_marshal_data4),
2123 expected_item_moniker_saved_data4, sizeof(expected_item_moniker_saved_data4),
2124 expected_item_moniker_comparison_data4, sizeof(expected_item_moniker_comparison_data4),
2125 58, L"&&Test");
2127 IMoniker_Release(moniker);
2129 hr = CreateItemMoniker(L"ab", wszObjectName, &moniker);
2130 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2132 test_moniker("item moniker 5", moniker,
2133 expected_item_moniker_marshal_data5, sizeof(expected_item_moniker_marshal_data5),
2134 expected_item_moniker_saved_data5, sizeof(expected_item_moniker_saved_data5),
2135 expected_item_moniker_comparison_data5, sizeof(expected_item_moniker_comparison_data5),
2136 58, L"abTest");
2138 /* Serialize and load back. */
2139 hr = CreateItemMoniker(NULL, L"object", &moniker2);
2140 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2142 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2143 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
2145 hr = CreateBindCtx(0, &bindctx);
2146 ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
2148 for (i = 0; i < ARRAY_SIZE(item_moniker_data); ++i)
2150 pos.QuadPart = 0;
2151 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2152 ok(hr == S_OK, "Failed to seek stream, hr %#x.\n", hr);
2154 hr = IStream_Write(stream, item_moniker_data[i].data, item_moniker_data[i].data_len, NULL);
2155 ok(hr == S_OK, "Failed to write stream contents, hr %#x.\n", hr);
2157 pos.QuadPart = 0;
2158 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2159 ok(hr == S_OK, "Failed to seek stream, hr %#x.\n", hr);
2161 hr = IMoniker_Load(moniker2, stream);
2162 ok(hr == S_OK, "Failed to load moniker, hr %#x.\n", hr);
2164 TEST_DISPLAY_NAME(moniker2, item_moniker_data[i].display_name);
2167 IStream_Release(stream);
2169 IMoniker_Release(moniker2);
2170 IMoniker_Release(moniker);
2172 /* Hashing */
2174 for (i = 0; i < ARRAY_SIZE(hash_tests); ++i)
2176 hr = CreateItemMoniker(hash_tests[i].delim, hash_tests[i].item, &moniker);
2177 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2179 hr = IMoniker_Hash(moniker, &hash);
2180 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2181 ok(hash == hash_tests[i].hash, "%d: unexpected hash value %#x.\n", i, hash);
2183 IMoniker_Release(moniker);
2186 hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker);
2187 ok_ole_success(hr, CreateItemMoniker);
2189 test_moniker("item moniker 1", moniker,
2190 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
2191 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
2192 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
2193 54, expected_display_name);
2195 /* IsSystemMoniker test */
2196 TEST_MONIKER_TYPE(moniker, MKSYS_ITEMMONIKER);
2198 container_moniker = create_test_moniker();
2200 /* IsRunning test */
2201 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
2202 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
2204 hr = IMoniker_IsRunning(moniker, NULL, &container_moniker->IMoniker_iface, NULL);
2205 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2207 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2208 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
2210 hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker2);
2211 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2212 hr = IMoniker_IsRunning(moniker, bindctx, NULL, moniker2);
2213 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2214 IMoniker_Release(moniker2);
2216 /* Different moniker as newly running. */
2217 hr = CreateItemMoniker(wszDelimiter, L"Item123", &moniker2);
2218 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2220 hr = IMoniker_IsRunning(moniker, bindctx, NULL, moniker2);
2221 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2223 hr = IBindCtx_GetRunningObjectTable(bindctx, &rot);
2224 ok(hr == S_OK, "Failed to get ROT, hr %#x.\n", hr);
2226 hr = IRunningObjectTable_Register(rot, ROTFLAGS_REGISTRATIONKEEPSALIVE, (IUnknown *)moniker, moniker, &cookie);
2227 ok(hr == S_OK, "Failed to register, hr %#x.\n", hr);
2229 hr = IRunningObjectTable_IsRunning(rot, moniker);
2230 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2232 hr = IMoniker_IsRunning(moniker, bindctx, NULL, moniker2);
2233 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2235 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2236 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2238 hr = IRunningObjectTable_Revoke(rot, cookie);
2239 ok(hr == S_OK, "Failed to revoke registration, hr %#x.\n", hr);
2241 IRunningObjectTable_Release(rot);
2243 expected_method_list = methods_isrunning;
2244 hr = IMoniker_IsRunning(moniker, bindctx, &container_moniker->IMoniker_iface, NULL);
2245 ok(hr == 0x8beef000, "Unexpected hr %#x.\n", hr);
2247 expected_method_list = methods_isrunning;
2248 hr = IMoniker_IsRunning(moniker, bindctx, &container_moniker->IMoniker_iface, moniker2);
2249 ok(hr == 0x8beef000, "Unexpected hr %#x.\n", hr);
2251 IMoniker_Release(moniker2);
2253 /* BindToObject() */
2254 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2255 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
2257 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2258 ok(hr == (0x8bee0000 | BINDSPEED_INDEFINITE), "Unexpected hr %#x.\n", hr);
2260 bind_opts.cbStruct = sizeof(bind_opts);
2261 hr = IBindCtx_GetBindOptions(bindctx, &bind_opts);
2262 ok(hr == S_OK, "Failed to get bind options, hr %#x.\n", hr);
2264 bind_opts.dwTickCountDeadline = 1;
2265 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2266 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2267 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2268 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2270 bind_opts.dwTickCountDeadline = 2499;
2271 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2272 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2273 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2274 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2276 bind_opts.dwTickCountDeadline = 2500;
2277 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2278 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2279 hr = IMoniker_BindToObject(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2280 ok(hr == (0x8bee0000 | BINDSPEED_MODERATE), "Unexpected hr %#x.\n", hr);
2282 /* BindToStorage() */
2283 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2284 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2286 hr = IMoniker_BindToStorage(moniker, bindctx, &container_moniker->IMoniker_iface, &IID_IUnknown, (void **)&unknown);
2287 ok(hr == 0x8bee0001, "Unexpected hr %#x.\n", hr);
2289 /* ParseDisplayName() */
2290 hr = IMoniker_ParseDisplayName(moniker, bindctx, NULL, displayname, &eaten, &moniker2);
2291 ok(hr == MK_E_SYNTAX, "Unexpected hr %#x.\n", hr);
2293 bind_opts.dwTickCountDeadline = 0;
2294 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2295 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2296 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2297 ok(hr == (0x8bee0000 | BINDSPEED_INDEFINITE), "Unexpected hr %#x.\n", hr);
2299 bind_opts.dwTickCountDeadline = 1;
2300 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2301 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2302 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2303 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2305 bind_opts.dwTickCountDeadline = 2499;
2306 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2307 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2308 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2309 ok(hr == (0x8bee0000 | BINDSPEED_IMMEDIATE), "Unexpected hr %#x.\n", hr);
2311 bind_opts.dwTickCountDeadline = 2500;
2312 hr = IBindCtx_SetBindOptions(bindctx, &bind_opts);
2313 ok(hr == S_OK, "Failed to set bind options, hr %#x.\n", hr);
2314 hr = IMoniker_ParseDisplayName(moniker, bindctx, &container_moniker->IMoniker_iface, displayname, &eaten, &moniker2);
2315 ok(hr == (0x8bee0000 | BINDSPEED_MODERATE), "Unexpected hr %#x.\n", hr);
2317 IMoniker_Release(&container_moniker->IMoniker_iface);
2319 IBindCtx_Release(bindctx);
2321 hr = IMoniker_Inverse(moniker, &inverse);
2322 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
2323 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
2324 IMoniker_Release(inverse);
2326 /* Reduce() */
2327 hr = IMoniker_Reduce(moniker, NULL, MKRREDUCE_ALL, NULL, &reduced);
2328 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
2329 ok(reduced == moniker, "Unexpected moniker.\n");
2330 IMoniker_Release(reduced);
2332 /* Enum() */
2333 enummoniker = (void *)0xdeadbeef;
2334 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
2335 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2336 ok(!enummoniker, "Unexpected pointer.\n");
2338 enummoniker = (void *)0xdeadbeef;
2339 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
2340 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2341 ok(!enummoniker, "Unexpected pointer.\n");
2343 hr = IMoniker_Enum(moniker, FALSE, NULL);
2344 todo_wine
2345 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2347 hr = IMoniker_IsEqual(moniker, NULL);
2348 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2350 IMoniker_Release(moniker);
2352 /* IsEqual */
2353 for (i = 0; i < ARRAY_SIZE(isequal_tests); ++i)
2355 hr = CreateItemMoniker(isequal_tests[i].delim1, isequal_tests[i].item1, &moniker);
2356 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2358 hr = CreateItemMoniker(isequal_tests[i].delim2, isequal_tests[i].item2, &moniker2);
2359 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2361 hr = IMoniker_IsEqual(moniker, moniker2);
2362 ok(hr == isequal_tests[i].hr, "%d: unexpected result %#x.\n", i, hr);
2364 hr = IMoniker_IsEqual(moniker2, moniker);
2365 ok(hr == isequal_tests[i].hr, "%d: unexpected result %#x.\n", i, hr);
2367 IMoniker_Release(moniker);
2368 IMoniker_Release(moniker2);
2371 /* Default instance. */
2372 hr = CoCreateInstance(&CLSID_ItemMoniker, NULL, CLSCTX_SERVER, &IID_IMoniker, (void **)&moniker);
2373 ok(hr == S_OK, "Failed to create item moniker, hr %#x.\n", hr);
2375 test_moniker("item moniker 6", moniker,
2376 expected_item_moniker_marshal_data6, sizeof(expected_item_moniker_marshal_data6),
2377 expected_item_moniker_saved_data6, sizeof(expected_item_moniker_saved_data6),
2378 expected_item_moniker_comparison_data6, sizeof(expected_item_moniker_comparison_data6),
2379 34, L"");
2381 hr = CoCreateInstance(&CLSID_ItemMoniker, (IUnknown *)moniker, CLSCTX_SERVER, &IID_IMoniker, (void **)&moniker2);
2382 ok(FAILED(hr), "Unexpected hr %#x.\n", hr);
2384 IMoniker_Release(moniker);
2386 /* ComposeWith() */
2387 hr = CreateItemMoniker(L"!", L"Item", &moniker);
2388 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2390 /* I + A -> () */
2391 anti = create_antimoniker(1);
2392 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
2393 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2394 ok(!moniker2, "Unexpected pointer.\n");
2395 IMoniker_Release(anti);
2397 /* I + A2 -> (A) */
2398 anti = create_antimoniker(2);
2399 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
2400 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2401 TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER);
2402 hr = IMoniker_Hash(moniker2, &hash);
2403 ok(hr == S_OK, "Failed to get hash, hr %#x.\n", hr);
2404 ok(hash == 0x80000001, "Unexpected hash.\n");
2405 IMoniker_Release(moniker2);
2407 IMoniker_Release(anti);
2409 IMoniker_Release(moniker);
2412 static void stream_write_dword(IStream *stream, DWORD value)
2414 LARGE_INTEGER pos;
2415 HRESULT hr;
2417 pos.QuadPart = 0;
2418 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2419 ok(hr == S_OK, "Failed to seek, hr %#x.\n", hr);
2421 hr = IStream_Write(stream, &value, sizeof(value), NULL);
2422 ok(hr == S_OK, "Stream write failed, hr %#x.\n", hr);
2424 hr = IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2425 ok(hr == S_OK, "Failed to seek, hr %#x.\n", hr);
2428 static void test_anti_moniker(void)
2430 IMoniker *moniker, *moniker2, *moniker3, *inverse, *reduced;
2431 HRESULT hr;
2432 DWORD hash;
2433 IBindCtx *bindctx;
2434 FILETIME filetime;
2435 IUnknown *unknown;
2436 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
2437 IEnumMoniker *enummoniker;
2438 IStream *stream;
2440 hr = CreateAntiMoniker(&moniker);
2441 ok_ole_success(hr, CreateAntiMoniker);
2443 hr = IMoniker_QueryInterface(moniker, &CLSID_AntiMoniker, (void **)&unknown);
2444 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2445 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
2446 IUnknown_Release(unknown);
2448 test_moniker("anti moniker", moniker,
2449 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
2450 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
2451 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
2452 20, expected_display_name);
2454 /* Hashing */
2455 hr = IMoniker_Hash(moniker, &hash);
2456 ok_ole_success(hr, IMoniker_Hash);
2457 ok(hash == 0x80000001,
2458 "Hash value != 0x80000001, instead was 0x%08x\n",
2459 hash);
2461 /* IsSystemMoniker test */
2462 TEST_MONIKER_TYPE(moniker, MKSYS_ANTIMONIKER);
2464 hr = IMoniker_Inverse(moniker, &inverse);
2465 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
2466 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
2468 hr = CreateBindCtx(0, &bindctx);
2469 ok_ole_success(hr, CreateBindCtx);
2471 /* IsRunning test */
2472 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2473 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
2475 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
2476 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
2478 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2479 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
2481 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2482 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
2484 /* ComposeWith */
2485 hr = CreateAntiMoniker(&moniker2);
2486 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2488 moniker3 = moniker;
2489 hr = IMoniker_ComposeWith(moniker, moniker2, TRUE, &moniker3);
2490 ok(hr == MK_E_NEEDGENERIC, "Unexpected hr %#x.\n", hr);
2491 ok(!moniker3, "Unexpected interface.\n");
2493 hr = IMoniker_ComposeWith(moniker, moniker2, FALSE, &moniker3);
2494 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
2495 TEST_MONIKER_TYPE(moniker3, MKSYS_GENERICCOMPOSITE);
2496 IMoniker_Release(moniker3);
2498 IMoniker_Release(moniker2);
2500 /* Load with composed number > 1. */
2501 hr = CreateAntiMoniker(&moniker2);
2502 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2504 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2505 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
2507 stream_write_dword(stream, 2);
2509 hr = IMoniker_Load(moniker, stream);
2510 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2512 test_moniker("anti moniker 2", moniker,
2513 expected_anti_moniker_marshal_data2, sizeof(expected_anti_moniker_marshal_data2),
2514 expected_anti_moniker_saved_data2, sizeof(expected_anti_moniker_saved_data2),
2515 expected_anti_moniker_comparison_data2, sizeof(expected_anti_moniker_comparison_data2),
2516 20, L"\\..\\..");
2518 hr = IMoniker_IsEqual(moniker, moniker2);
2519 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2521 hr = IMoniker_IsEqual(moniker2, moniker);
2522 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2524 hr = IMoniker_Hash(moniker, &hash);
2525 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2526 ok(hash == 0x80000002, "Unexpected hash value %#x.\n", hash);
2528 /* Display name reflects anti combination. */
2529 TEST_DISPLAY_NAME(moniker, L"\\..\\..");
2531 /* Limit is at 0xfffff. */
2532 stream_write_dword(stream, 0xfffff);
2534 hr = IMoniker_Load(moniker, stream);
2535 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2537 hr = IMoniker_Hash(moniker, &hash);
2538 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2539 ok(hash == 0x800fffff, "Unexpected hash value %#x.\n", hash);
2541 stream_write_dword(stream, 0xfffff + 1);
2543 hr = IMoniker_Load(moniker, stream);
2544 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2546 hr = IMoniker_Hash(moniker, &hash);
2547 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2548 ok(hash == 0x800fffff, "Unexpected hash value %#x.\n", hash);
2550 /* Zero combining counter is also valid. */
2551 stream_write_dword(stream, 0);
2553 hr = IMoniker_Load(moniker, stream);
2554 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2556 hr = IMoniker_IsEqual(moniker, moniker2);
2557 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2559 hr = IMoniker_IsEqual(moniker2, moniker);
2560 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2562 hr = IMoniker_Hash(moniker, &hash);
2563 ok(hr == S_OK, "Failed to get hash value, hr %#x.\n", hr);
2564 ok(hash == 0x80000000, "Unexpected hash value %#x.\n", hash);
2566 TEST_DISPLAY_NAME(moniker, L"");
2568 /* Back to initial value. */
2569 stream_write_dword(stream, 1);
2571 hr = IMoniker_Load(moniker, stream);
2572 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2574 hr = IMoniker_IsEqual(moniker, moniker2);
2575 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2577 hr = IMoniker_IsEqual(moniker2, moniker);
2578 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2580 hr = IMoniker_IsEqual(moniker, NULL);
2581 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2583 /* Reduce() */
2584 hr = IMoniker_Reduce(moniker, NULL, MKRREDUCE_ALL, NULL, &reduced);
2585 ok(hr == MK_S_REDUCED_TO_SELF, "Unexpected hr %#x.\n", hr);
2586 ok(reduced == moniker, "Unexpected moniker.\n");
2587 IMoniker_Release(reduced);
2589 /* Enum() */
2590 enummoniker = (void *)0xdeadbeef;
2591 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
2592 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2593 ok(!enummoniker, "Unexpected pointer.\n");
2595 enummoniker = (void *)0xdeadbeef;
2596 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
2597 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2598 ok(!enummoniker, "Unexpected pointer.\n");
2600 hr = IMoniker_Enum(moniker, FALSE, NULL);
2601 todo_wine
2602 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2604 /* CommonPrefixWith() */
2605 stream_write_dword(stream, 0);
2607 hr = IMoniker_Load(moniker, stream);
2608 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2610 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2611 ok(hr == MK_S_ME, "Unexpected hr %#x.\n", hr);
2612 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2613 IMoniker_Release(moniker3);
2615 hr = IMoniker_CommonPrefixWith(moniker2, moniker, &moniker3);
2616 ok(hr == MK_S_HIM, "Unexpected hr %#x.\n", hr);
2617 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2618 IMoniker_Release(moniker3);
2620 stream_write_dword(stream, 10);
2622 hr = IMoniker_Load(moniker, stream);
2623 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2625 stream_write_dword(stream, 5);
2627 hr = IMoniker_Load(moniker2, stream);
2628 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2630 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2631 ok(hr == MK_S_HIM, "Unexpected hr %#x.\n", hr);
2632 ok(moniker3 == moniker2, "Unexpected prefix moniker.\n");
2633 IMoniker_Release(moniker3);
2635 hr = IMoniker_CommonPrefixWith(moniker2, moniker, &moniker3);
2636 ok(hr == MK_S_ME, "Unexpected hr %#x.\n", hr);
2637 ok(moniker3 == moniker2, "Unexpected prefix moniker.\n");
2638 IMoniker_Release(moniker3);
2640 /* Now same length, 0 or 2 */
2641 stream_write_dword(stream, 0);
2642 hr = IMoniker_Load(moniker, stream);
2643 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2645 stream_write_dword(stream, 0);
2646 hr = IMoniker_Load(moniker2, stream);
2647 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2649 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2650 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
2651 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2652 IMoniker_Release(moniker3);
2654 stream_write_dword(stream, 2);
2655 hr = IMoniker_Load(moniker, stream);
2656 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2658 stream_write_dword(stream, 2);
2659 hr = IMoniker_Load(moniker2, stream);
2660 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2662 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &moniker3);
2663 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
2664 ok(moniker3 == moniker, "Unexpected prefix moniker.\n");
2665 IMoniker_Release(moniker3);
2667 IStream_Release(stream);
2668 IBindCtx_Release(bindctx);
2669 IMoniker_Release(moniker);
2670 IMoniker_Release(moniker2);
2673 static void test_generic_composite_moniker(void)
2675 IMoniker *moniker, *inverse, *inverse2, *moniker1, *moniker2, *moniker3, *moniker4;
2676 IEnumMoniker *enummoniker;
2677 HRESULT hr;
2678 DWORD hash;
2679 IBindCtx *bindctx;
2680 FILETIME filetime;
2681 IUnknown *unknown;
2683 hr = CreateBindCtx(0, &bindctx);
2684 ok(hr == S_OK, "Failed to create bind context, hr %#x.\n", hr);
2686 hr = CreateItemMoniker(L"!", L"Test", &moniker1);
2687 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2688 hr = CreateItemMoniker(L"#", L"Wine", &moniker2);
2689 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2690 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2691 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
2693 /* Compose with itself. */
2694 EXPECT_REF(moniker1, 2);
2695 hr = CreateGenericComposite(moniker1, moniker1, &moniker);
2696 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2697 EXPECT_REF(moniker1, 4);
2698 TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
2699 IMoniker_Release(moniker);
2701 /* (I) + (A) -> () */
2702 hr = IMoniker_Inverse(moniker1, &inverse);
2703 ok(hr == S_OK, "Failed to invert, hr %#x.\n", hr);
2704 hr = CreateGenericComposite(moniker1, inverse, &moniker);
2705 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2706 todo_wine
2707 ok(!moniker, "Unexpected pointer.\n");
2708 if (moniker)
2709 IMoniker_Release(moniker);
2711 /* (I1,I2) + (A,A) -> (I1,I2+A,A) -> (I1,A) -> () */
2712 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2713 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2714 hr = CreateGenericComposite(inverse, inverse, &moniker3);
2715 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2716 TEST_MONIKER_TYPE(moniker3, MKSYS_GENERICCOMPOSITE);
2718 hr = CreateGenericComposite(moniker, moniker3, &moniker4);
2719 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2720 todo_wine
2721 ok(!moniker4, "Unexpected pointer.\n");
2722 if (moniker4)
2723 IMoniker_Release(moniker4);
2725 IMoniker_Release(moniker);
2726 IMoniker_Release(moniker3);
2728 /* (I1,I2) + (A2,A) -> (I1,I2+A2,A) -> (I1,A,A) -> (I1+A,A) -> (A) */
2729 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2730 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2731 ok(!!moniker, "Unexpected pointer.\n");
2732 inverse2 = create_antimoniker(2);
2733 hr = CreateGenericComposite(inverse2, inverse, &moniker3);
2734 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2735 ok(!!moniker3, "Unexpected pointer.\n");
2736 IMoniker_Release(inverse2);
2738 hr = CreateGenericComposite(moniker, moniker3, &moniker4);
2739 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2740 TEST_MONIKER_TYPE_TODO(moniker4, MKSYS_ANTIMONIKER);
2741 IMoniker_Release(moniker4);
2742 IMoniker_Release(moniker);
2743 IMoniker_Release(moniker3);
2745 /* (I1,I2) + (A,I2) -> (I1,I2+A,I2) -> (I1,I2) */
2746 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
2747 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2748 ok(!!moniker, "Unexpected pointer.\n");
2750 hr = CreateGenericComposite(inverse, moniker2, &moniker3);
2751 ok(hr == S_OK, "Failed to create composite, hr %#x.\n", hr);
2752 ok(!!moniker3, "Unexpected pointer.\n");
2754 hr = CreateGenericComposite(moniker, moniker3, &moniker4);
2755 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2756 TEST_MONIKER_TYPE(moniker4, MKSYS_GENERICCOMPOSITE);
2758 TEST_DISPLAY_NAME(moniker4, L"!Test#Wine");
2760 IMoniker_Release(moniker4);
2761 IMoniker_Release(moniker3);
2763 IMoniker_Release(inverse);
2765 /* Generic composite is special, as it does not addref in this case. */
2766 hr = IMoniker_QueryInterface(moniker, &CLSID_CompositeMoniker, (void **)&unknown);
2767 todo_wine
2768 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2769 if (SUCCEEDED(hr))
2770 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
2772 test_moniker("generic composite moniker", moniker,
2773 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
2774 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
2775 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
2776 160, L"!Test#Wine");
2778 /* Hashing */
2780 hr = IMoniker_Hash(moniker, &hash);
2781 ok_ole_success(hr, IMoniker_Hash);
2783 ok(hash == 0xd87,
2784 "Hash value != 0xd87, instead was 0x%08x\n",
2785 hash);
2787 /* IsSystemMoniker test */
2788 TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
2790 hr = CreateBindCtx(0, &bindctx);
2791 ok_ole_success(hr, CreateBindCtx);
2793 /* IsRunning test */
2794 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
2795 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
2797 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2798 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
2800 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
2801 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
2803 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2804 todo_wine
2805 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
2807 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2808 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
2810 IBindCtx_Release(bindctx);
2812 hr = IMoniker_Inverse(moniker, &inverse);
2813 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
2814 TEST_MONIKER_TYPE(inverse, MKSYS_GENERICCOMPOSITE);
2815 IMoniker_Release(inverse);
2817 /* Enum() */
2818 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
2819 ok(hr == S_OK, "Failed to get enumerator, hr %#x.\n", hr);
2820 IEnumMoniker_Release(enummoniker);
2822 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
2823 ok(hr == S_OK, "Failed to get enumerator, hr %#x.\n", hr);
2824 IEnumMoniker_Release(enummoniker);
2826 hr = IMoniker_Enum(moniker, FALSE, NULL);
2827 todo_wine
2828 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2830 IMoniker_Release(moniker);
2833 static void test_pointer_moniker(void)
2835 IMoniker *moniker, *moniker2, *prefix, *inverse, *anti;
2836 IEnumMoniker *enummoniker;
2837 DWORD hash, size;
2838 HRESULT hr;
2839 IBindCtx *bindctx;
2840 FILETIME filetime;
2841 IUnknown *unknown;
2842 IStream *stream;
2843 IROTData *rotdata;
2844 LPOLESTR display_name;
2845 IMarshal *marshal;
2846 LARGE_INTEGER pos;
2847 CLSID clsid;
2849 cLocks = 0;
2851 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
2852 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
2854 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
2855 ok_ole_success(hr, CreatePointerMoniker);
2857 hr = IMoniker_QueryInterface(moniker, &IID_IMoniker, NULL);
2858 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2860 hr = IMoniker_QueryInterface(moniker, &CLSID_PointerMoniker, (void **)&unknown);
2861 ok(unknown == (IUnknown *)moniker, "Unexpected interface.\n");
2862 IUnknown_Release(unknown);
2864 hr = IMoniker_QueryInterface(moniker, &IID_IMarshal, (void **)&marshal);
2865 ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
2867 hr = IMarshal_GetUnmarshalClass(marshal, NULL, NULL, 0, NULL, 0, &clsid);
2868 ok(hr == S_OK, "Failed to get class, hr %#x.\n", hr);
2869 ok(IsEqualGUID(&clsid, &CLSID_PointerMoniker), "Unexpected class.\n");
2871 hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IMoniker, NULL, CLSCTX_INPROC, NULL, 0, &size);
2872 ok(hr == S_OK, "Failed to get marshal size, hr %#x.\n", hr);
2873 ok(size > 0, "Unexpected size %d.\n", size);
2875 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2876 ok(hr == S_OK, "Failed to create a stream, hr %#x.\n", hr);
2878 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2879 ok(hr == S_OK, "Failed to marshal moniker, hr %#x.\n", hr);
2881 pos.QuadPart = 0;
2882 IStream_Seek(stream, pos, STREAM_SEEK_SET, NULL);
2883 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker2);
2884 ok(hr == S_OK, "Failed to unmarshal, hr %#x.\n", hr);
2885 hr = IMoniker_IsEqual(moniker, moniker2);
2886 ok(hr == S_OK, "Expected equal moniker, hr %#x.\n", hr);
2887 IMoniker_Release(moniker2);
2889 IStream_Release(stream);
2891 IMarshal_Release(marshal);
2893 ok_more_than_one_lock();
2895 /* Display Name */
2897 hr = CreateBindCtx(0, &bindctx);
2898 ok_ole_success(hr, CreateBindCtx);
2900 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
2901 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
2903 IBindCtx_Release(bindctx);
2905 hr = IMoniker_IsDirty(moniker);
2906 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
2908 /* IROTData::GetComparisonData test */
2910 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
2911 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2913 /* Saving */
2915 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
2916 ok_ole_success(hr, CreateStreamOnHGlobal);
2918 hr = IMoniker_Save(moniker, stream, TRUE);
2919 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
2921 IStream_Release(stream);
2923 /* Hashing */
2924 hr = IMoniker_Hash(moniker, &hash);
2925 ok_ole_success(hr, IMoniker_Hash);
2926 ok(hash == PtrToUlong(&Test_ClassFactory),
2927 "Hash value should have been 0x%08x, instead of 0x%08x\n",
2928 PtrToUlong(&Test_ClassFactory), hash);
2930 /* IsSystemMoniker test */
2931 TEST_MONIKER_TYPE(moniker, MKSYS_POINTERMONIKER);
2933 hr = IMoniker_Inverse(moniker, &inverse);
2934 ok(hr == S_OK, "Failed to get inverse, hr %#x.\n", hr);
2935 TEST_MONIKER_TYPE(inverse, MKSYS_ANTIMONIKER);
2936 IMoniker_Release(inverse);
2938 hr = CreateBindCtx(0, &bindctx);
2939 ok_ole_success(hr, CreateBindCtx);
2941 /* IsRunning test */
2942 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
2943 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
2945 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
2946 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
2948 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2949 ok_ole_success(hr, IMoniker_BindToObject);
2950 IUnknown_Release(unknown);
2952 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2953 ok_ole_success(hr, IMoniker_BindToStorage);
2954 IUnknown_Release(unknown);
2956 IMoniker_Release(moniker);
2958 todo_wine
2959 ok(cLocks == 0, "Number of locks should be 0, but actually is %d.\n", cLocks);
2961 hr = CreatePointerMoniker(NULL, &moniker);
2962 ok_ole_success(hr, CreatePointerMoniker);
2964 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2965 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
2967 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
2968 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
2970 IBindCtx_Release(bindctx);
2972 /* Enum() */
2973 hr = IMoniker_Enum(moniker, TRUE, &enummoniker);
2974 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
2976 hr = IMoniker_Enum(moniker, FALSE, &enummoniker);
2977 ok(hr == E_NOTIMPL, "Unexpected hr %#x.\n", hr);
2979 IMoniker_Release(moniker);
2981 /* CommonPrefixWith() */
2982 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
2983 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2985 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker2);
2986 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
2988 hr = IMoniker_IsEqual(moniker, NULL);
2989 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2991 hr = IMoniker_IsEqual(moniker, moniker2);
2992 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
2994 hr = IMoniker_CommonPrefixWith(moniker, moniker2, NULL);
2995 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
2997 hr = IMoniker_CommonPrefixWith(moniker, NULL, &prefix);
2998 ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr);
3000 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
3001 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
3002 ok(prefix == moniker, "Unexpected pointer.\n");
3003 IMoniker_Release(prefix);
3005 IMoniker_Release(moniker2);
3007 hr = CreatePointerMoniker((IUnknown *)moniker, &moniker2);
3008 ok(hr == S_OK, "Failed to create moniker, hr %#x.\n", hr);
3010 hr = IMoniker_IsEqual(moniker, moniker2);
3011 ok(hr == S_FALSE, "Unexpected hr %#x.\n", hr);
3013 hr = IMoniker_CommonPrefixWith(moniker, moniker2, &prefix);
3014 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3016 IMoniker_Release(moniker2);
3018 /* ComposeWith() */
3020 /* P + A -> () */
3021 anti = create_antimoniker(1);
3022 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
3023 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
3024 ok(!moniker2, "Unexpected pointer.\n");
3025 IMoniker_Release(anti);
3027 /* P + A2 -> A */
3028 anti = create_antimoniker(2);
3029 hr = IMoniker_ComposeWith(moniker, anti, TRUE, &moniker2);
3030 ok(hr == S_OK, "Failed to compose, hr %#x.\n", hr);
3031 TEST_MONIKER_TYPE(moniker2, MKSYS_ANTIMONIKER);
3032 IMoniker_Release(moniker2);
3034 IMoniker_Release(anti);
3036 IMoniker_Release(moniker);
3039 static void test_bind_context(void)
3041 HRESULT hr;
3042 IBindCtx *pBindCtx;
3043 IEnumString *pEnumString;
3044 BIND_OPTS3 bind_opts;
3045 HeapUnknown *unknown;
3046 HeapUnknown *unknown2;
3047 IUnknown *param_obj;
3048 ULONG refs;
3049 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
3050 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
3052 hr = CreateBindCtx(0, NULL);
3053 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3055 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
3056 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3058 hr = CreateBindCtx(0, &pBindCtx);
3059 ok_ole_success(hr, "CreateBindCtx");
3061 bind_opts.cbStruct = -1;
3062 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3063 ok_ole_success(hr, "IBindCtx_GetBindOptions");
3064 ok(bind_opts.cbStruct == sizeof(BIND_OPTS3) || broken(bind_opts.cbStruct == sizeof(BIND_OPTS2)) /* XP */,
3065 "Unexpected bind_opts.cbStruct %d.\n", bind_opts.cbStruct);
3067 bind_opts.cbStruct = sizeof(BIND_OPTS);
3068 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3069 ok_ole_success(hr, "IBindCtx_GetBindOptions");
3070 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
3072 memset(&bind_opts, 0xfe, sizeof(bind_opts));
3073 bind_opts.cbStruct = sizeof(bind_opts);
3074 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3075 ok_ole_success(hr, "IBindCtx_GetBindOptions");
3076 ok(bind_opts.cbStruct == sizeof(bind_opts) || bind_opts.cbStruct == sizeof(BIND_OPTS2) /* XP */,
3077 "Unexpected bind_opts.cbStruct %d.\n", bind_opts.cbStruct);
3078 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
3079 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
3080 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
3081 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
3082 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
3083 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
3084 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
3085 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
3086 if (bind_opts.cbStruct >= sizeof(BIND_OPTS3))
3087 ok(bind_opts.hwnd == NULL, "Unexpected bind_opts.hwnd %p.\n", bind_opts.hwnd);
3089 bind_opts.cbStruct = -1;
3090 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
3091 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3093 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
3094 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3096 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
3097 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
3098 unknown->refs = 1;
3099 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface);
3100 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
3102 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
3103 ok_ole_success(hr, "IBindCtx_GetObjectParam");
3104 IUnknown_Release(param_obj);
3106 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
3107 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
3108 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
3110 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
3111 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
3113 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
3114 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
3115 ok(!pEnumString, "pEnumString should be NULL\n");
3117 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
3118 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
3120 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
3121 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
3123 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
3124 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
3125 unknown2->refs = 1;
3126 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface);
3127 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
3129 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
3130 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
3132 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
3133 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
3135 IBindCtx_Release(pBindCtx);
3137 refs = IUnknown_Release(&unknown->IUnknown_iface);
3138 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
3140 refs = IUnknown_Release(&unknown2->IUnknown_iface);
3141 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
3144 static void test_save_load_filemoniker(void)
3146 IMoniker* pMk;
3147 IStream* pStm;
3148 HRESULT hr;
3149 ULARGE_INTEGER size;
3150 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
3151 DWORD some_val = 0xFEDCBA98;
3152 int i;
3154 /* see FileMonikerImpl_Save docs */
3155 zero_pos.QuadPart = 0;
3156 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
3157 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
3159 /* create the stream we're going to write to */
3160 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
3161 ok_ole_success(hr, "CreateStreamOnHGlobal");
3163 size.u.LowPart = 128;
3164 hr = IStream_SetSize(pStm, size);
3165 ok_ole_success(hr, "IStream_SetSize");
3167 /* create and save a moniker */
3168 hr = CreateFileMoniker(wszFileName1, &pMk);
3169 ok_ole_success(hr, "CreateFileMoniker");
3171 hr = IMoniker_Save(pMk, pStm, TRUE);
3172 ok_ole_success(hr, "IMoniker_Save");
3173 IMoniker_Release(pMk);
3175 /* overwrite the constants with various values */
3176 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
3177 ok_ole_success(hr, "IStream_Seek");
3178 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
3179 ok_ole_success(hr, "IStream_Write");
3181 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
3182 ok_ole_success(hr, "IStream_Seek");
3183 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
3184 ok_ole_success(hr, "IStream_Write");
3186 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
3187 ok_ole_success(hr, "IStream_Seek");
3188 for(i = 0; i < 5; ++i){
3189 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
3190 ok_ole_success(hr, "IStream_Write");
3193 /* go back to the start of the stream */
3194 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
3195 ok_ole_success(hr, "IStream_Seek");
3197 /* create a new moniker and load into it */
3198 hr = CreateFileMoniker(wszFileName1, &pMk);
3199 ok_ole_success(hr, "CreateFileMoniker");
3201 hr = IMoniker_Load(pMk, pStm);
3202 ok_ole_success(hr, "IMoniker_Load");
3204 IMoniker_Release(pMk);
3205 IStream_Release(pStm);
3208 static void test_MonikerCommonPrefixWith(void)
3210 IMoniker *moniker, *item, *file1, *file2, *composite, *composite2;
3211 HRESULT hr;
3213 moniker = (void *)0xdeadbeef;
3214 hr = MonikerCommonPrefixWith(NULL, NULL, &moniker);
3215 todo_wine {
3216 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3217 ok(!moniker, "Unexpected pointer.\n");
3219 if (hr == E_NOTIMPL)
3220 return;
3222 hr = CreateItemMoniker(L"!", L"Item", &item);
3223 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3225 hr = MonikerCommonPrefixWith(item, NULL, &moniker);
3226 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3228 hr = MonikerCommonPrefixWith(NULL, item, &moniker);
3229 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3231 hr = MonikerCommonPrefixWith(item, item, &moniker);
3232 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3234 hr = CreateFileMoniker(L"C:\\test.txt", &file1);
3235 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3237 hr = MonikerCommonPrefixWith(file1, NULL, &moniker);
3238 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3240 hr = MonikerCommonPrefixWith(NULL, file1, &moniker);
3241 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3243 /* F x F */
3244 hr = MonikerCommonPrefixWith(file1, file1, &moniker);
3245 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3247 hr = CreateFileMoniker(L"C:\\a\\test.txt", &file2);
3248 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3250 /* F1 x F2 */
3251 hr = MonikerCommonPrefixWith(file1, file2, &moniker);
3252 ok(hr == MK_E_NOPREFIX, "Unexpected hr %#x.\n", hr);
3254 hr = CreateGenericComposite(file1, item, &composite);
3255 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3257 hr = CreateGenericComposite(file2, item, &composite2);
3258 ok(hr == S_OK, "Failed to create a moniker, hr %#x.\n", hr);
3260 /* F x (F,I) -> F */
3261 hr = MonikerCommonPrefixWith(file1, composite, &moniker);
3262 ok(hr == MK_S_ME, "Unexpected hr %#x.\n", hr);
3263 ok(moniker == file1, "Unexpected pointer.\n");
3264 IMoniker_Release(moniker);
3266 /* F1 x (F2,I) -> F */
3267 hr = MonikerCommonPrefixWith(file1, composite2, &moniker);
3268 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3269 TEST_MONIKER_TYPE(moniker, MKSYS_FILEMONIKER);
3270 TEST_DISPLAY_NAME(moniker, L"C:\\");
3271 IMoniker_Release(moniker);
3273 /* (F2,I) x F1 -> F */
3274 hr = MonikerCommonPrefixWith(composite2, file1, &moniker);
3275 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3276 TEST_MONIKER_TYPE(moniker, MKSYS_FILEMONIKER);
3277 TEST_DISPLAY_NAME(moniker, L"C:\\");
3278 IMoniker_Release(moniker);
3280 /* (F,I) x (F) -> F */
3281 hr = MonikerCommonPrefixWith(composite, file1, &moniker);
3282 ok(hr == MK_S_HIM, "Unexpected hr %#x.\n", hr);
3283 ok(moniker == file1, "Unexpected pointer.\n");
3284 IMoniker_Release(moniker);
3286 /* (F,I) x (F,I) -> (F,I) */
3287 hr = MonikerCommonPrefixWith(composite, composite, &moniker);
3288 ok(hr == MK_S_US, "Unexpected hr %#x.\n", hr);
3289 TEST_MONIKER_TYPE(moniker, MKSYS_GENERICCOMPOSITE);
3290 TEST_DISPLAY_NAME(moniker, L"C:\\test.txt!Item");
3291 ok(moniker != composite, "Unexpected pointer.\n");
3292 IMoniker_Release(moniker);
3294 /* (F1,I) x (F2,I) -> () */
3295 hr = MonikerCommonPrefixWith(composite, composite2, &moniker);
3296 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3297 ok(!moniker, "Unexpected pointer %p.\n", moniker);
3299 IMoniker_Release(composite2);
3300 IMoniker_Release(composite);
3301 IMoniker_Release(file2);
3302 IMoniker_Release(file1);
3303 IMoniker_Release(item);
3306 START_TEST(moniker)
3308 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3310 test_ROT();
3311 test_ROT_multiple_entries();
3312 test_MkParseDisplayName();
3313 test_class_moniker();
3314 test_file_monikers();
3315 test_item_moniker();
3316 test_anti_moniker();
3317 test_generic_composite_moniker();
3318 test_pointer_moniker();
3319 test_save_load_filemoniker();
3320 test_MonikerCommonPrefixWith();
3322 /* FIXME: test moniker creation funcs and parsing other moniker formats */
3324 test_bind_context();
3326 CoUninitialize();