ole32/tests: Use the available ARRAY_SIZE() macro.
[wine.git] / dlls / ole32 / tests / moniker.c
blob7302ab0f21bfbdd3db1374b9b68928058a2d0401
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 "initguid.h"
33 #include "comcat.h"
34 #include "olectl.h"
36 #include "wine/test.h"
38 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
42 #define CHECK_EXPECTED_METHOD(method_name) \
43 do { \
44 trace("%s\n", method_name); \
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 static LONG cLocks;
68 static void LockModule(void)
70 InterlockedIncrement(&cLocks);
73 static void UnlockModule(void)
75 InterlockedDecrement(&cLocks);
78 static SIZE_T round_global_size(SIZE_T size)
80 static SIZE_T global_size_alignment = -1;
81 if (global_size_alignment == -1)
83 void *p = GlobalAlloc(GMEM_FIXED, 1);
84 global_size_alignment = GlobalSize(p);
85 GlobalFree(p);
88 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
91 static DWORD external_connections;
93 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
95 ok(0, "unexpected call\n");
96 *ppv = NULL;
97 return E_NOINTERFACE;
100 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
102 return 2;
105 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
107 return 1;
110 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
112 trace("add connection\n");
114 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
115 ok(!reserved, "reserved = %x\n", reserved);
116 return ++external_connections;
119 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
120 DWORD reserved, BOOL fLastReleaseCloses)
122 trace("release connection\n");
124 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
125 ok(!reserved, "reserved = %x\n", reserved);
127 return --external_connections;
130 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
131 ExternalConnection_QueryInterface,
132 ExternalConnection_AddRef,
133 ExternalConnection_Release,
134 ExternalConnection_AddConnection,
135 ExternalConnection_ReleaseConnection
138 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
140 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
141 LPCLASSFACTORY iface,
142 REFIID riid,
143 LPVOID *ppvObj)
145 if (ppvObj == NULL) return E_POINTER;
147 if (IsEqualGUID(riid, &IID_IUnknown) ||
148 IsEqualGUID(riid, &IID_IClassFactory))
150 *ppvObj = iface;
151 IClassFactory_AddRef(iface);
152 return S_OK;
155 if(IsEqualGUID(riid, &IID_IExternalConnection)) {
156 *ppvObj = &ExternalConnection;
157 return S_OK;
160 *ppvObj = NULL;
161 return E_NOINTERFACE;
164 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
166 LockModule();
167 return 2; /* non-heap-based object */
170 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
172 UnlockModule();
173 return 1; /* non-heap-based object */
176 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
177 LPCLASSFACTORY iface,
178 LPUNKNOWN pUnkOuter,
179 REFIID riid,
180 LPVOID *ppvObj)
182 return E_NOTIMPL;
185 static HRESULT WINAPI Test_IClassFactory_LockServer(
186 LPCLASSFACTORY iface,
187 BOOL fLock)
189 return S_OK;
192 static const IClassFactoryVtbl TestClassFactory_Vtbl =
194 Test_IClassFactory_QueryInterface,
195 Test_IClassFactory_AddRef,
196 Test_IClassFactory_Release,
197 Test_IClassFactory_CreateInstance,
198 Test_IClassFactory_LockServer
201 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
203 typedef struct
205 IUnknown IUnknown_iface;
206 ULONG refs;
207 } HeapUnknown;
209 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
211 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
214 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
216 if (IsEqualIID(riid, &IID_IUnknown))
218 IUnknown_AddRef(iface);
219 *ppv = iface;
220 return S_OK;
222 *ppv = NULL;
223 return E_NOINTERFACE;
226 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
228 HeapUnknown *This = impl_from_IUnknown(iface);
229 return InterlockedIncrement((LONG*)&This->refs);
232 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
234 HeapUnknown *This = impl_from_IUnknown(iface);
235 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
236 if (!refs) HeapFree(GetProcessHeap(), 0, This);
237 return refs;
240 static const IUnknownVtbl HeapUnknown_Vtbl =
242 HeapUnknown_QueryInterface,
243 HeapUnknown_AddRef,
244 HeapUnknown_Release
247 static HRESULT WINAPI
248 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
250 if (!ppvObject)
251 return E_INVALIDARG;
253 *ppvObject = 0;
255 if (IsEqualIID(&IID_IUnknown, riid) ||
256 IsEqualIID(&IID_IPersist, riid) ||
257 IsEqualIID(&IID_IPersistStream,riid) ||
258 IsEqualIID(&IID_IMoniker, riid))
259 *ppvObject = iface;
260 if (IsEqualIID(&IID_IROTData, riid))
261 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
263 if ((*ppvObject)==0)
264 return E_NOINTERFACE;
266 IMoniker_AddRef(iface);
268 return S_OK;
271 static ULONG WINAPI
272 Moniker_AddRef(IMoniker* iface)
274 return 2;
277 static ULONG WINAPI
278 Moniker_Release(IMoniker* iface)
280 return 1;
283 static HRESULT WINAPI
284 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
286 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
288 *pClassID = CLSID_TestMoniker;
290 return S_OK;
293 static HRESULT WINAPI
294 Moniker_IsDirty(IMoniker* iface)
296 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
298 return S_FALSE;
301 static HRESULT WINAPI
302 Moniker_Load(IMoniker* iface, IStream* pStm)
304 CHECK_EXPECTED_METHOD("Moniker_Load");
305 return E_NOTIMPL;
308 static HRESULT WINAPI
309 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
311 CHECK_EXPECTED_METHOD("Moniker_Save");
312 return E_NOTIMPL;
315 static HRESULT WINAPI
316 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
318 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
319 return E_NOTIMPL;
322 static HRESULT WINAPI
323 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
324 REFIID riid, VOID** ppvResult)
326 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
327 return E_NOTIMPL;
330 static HRESULT WINAPI
331 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
332 REFIID riid, VOID** ppvObject)
334 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
335 return E_NOTIMPL;
338 static HRESULT WINAPI
339 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
340 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
342 CHECK_EXPECTED_METHOD("Moniker_Reduce");
344 if (ppmkReduced==NULL)
345 return E_POINTER;
347 IMoniker_AddRef(iface);
349 *ppmkReduced=iface;
351 return MK_S_REDUCED_TO_SELF;
354 static HRESULT WINAPI
355 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
356 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
358 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
359 return E_NOTIMPL;
362 static HRESULT WINAPI
363 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
365 CHECK_EXPECTED_METHOD("Moniker_Enum");
367 if (ppenumMoniker == NULL)
368 return E_POINTER;
370 *ppenumMoniker = NULL;
372 return S_OK;
375 static HRESULT WINAPI
376 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
378 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
379 return E_NOTIMPL;
382 static HRESULT WINAPI
383 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
385 CHECK_EXPECTED_METHOD("Moniker_Hash");
386 return E_NOTIMPL;
389 static HRESULT WINAPI
390 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
391 IMoniker* pmkNewlyRunning)
393 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
394 return E_NOTIMPL;
397 static HRESULT WINAPI
398 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
399 IMoniker* pmkToLeft, FILETIME* pFileTime)
401 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
402 return E_NOTIMPL;
405 static HRESULT WINAPI
406 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
408 CHECK_EXPECTED_METHOD("Moniker_Inverse");
409 return E_NOTIMPL;
412 static HRESULT WINAPI
413 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
415 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
416 return E_NOTIMPL;
419 static HRESULT WINAPI
420 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
422 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
423 return E_NOTIMPL;
426 static HRESULT WINAPI
427 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
428 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
430 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
431 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
432 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
433 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
434 return S_OK;
437 static HRESULT WINAPI
438 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
439 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
441 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
442 return E_NOTIMPL;
445 static HRESULT WINAPI
446 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
448 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
450 if (!pwdMksys)
451 return E_POINTER;
453 (*pwdMksys)=MKSYS_NONE;
455 return S_FALSE;
458 static const IMonikerVtbl MonikerNoROTDataVtbl =
460 MonikerNoROTData_QueryInterface,
461 Moniker_AddRef,
462 Moniker_Release,
463 Moniker_GetClassID,
464 Moniker_IsDirty,
465 Moniker_Load,
466 Moniker_Save,
467 Moniker_GetSizeMax,
468 Moniker_BindToObject,
469 Moniker_BindToStorage,
470 Moniker_Reduce,
471 Moniker_ComposeWith,
472 Moniker_Enum,
473 Moniker_IsEqual,
474 Moniker_Hash,
475 Moniker_IsRunning,
476 Moniker_GetTimeOfLastChange,
477 Moniker_Inverse,
478 Moniker_CommonPrefixWith,
479 Moniker_RelativePathTo,
480 Moniker_GetDisplayName,
481 Moniker_ParseDisplayName,
482 Moniker_IsSystemMoniker
485 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
487 static IMoniker Moniker;
489 static HRESULT WINAPI
490 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
492 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
495 static ULONG WINAPI
496 ROTData_AddRef(IROTData *iface)
498 return 2;
501 static ULONG WINAPI
502 ROTData_Release(IROTData* iface)
504 return 1;
507 static HRESULT WINAPI
508 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
509 ULONG cbMax, ULONG* pcbData)
511 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
513 *pcbData = 1;
514 if (cbMax < *pcbData)
515 return E_OUTOFMEMORY;
517 *pbData = 0xde;
519 return S_OK;
522 static IROTDataVtbl ROTDataVtbl =
524 ROTData_QueryInterface,
525 ROTData_AddRef,
526 ROTData_Release,
527 ROTData_GetComparisonData
530 static IROTData ROTData = { &ROTDataVtbl };
532 static HRESULT WINAPI
533 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
535 if (!ppvObject)
536 return E_INVALIDARG;
538 *ppvObject = 0;
540 if (IsEqualIID(&IID_IUnknown, riid) ||
541 IsEqualIID(&IID_IPersist, riid) ||
542 IsEqualIID(&IID_IPersistStream,riid) ||
543 IsEqualIID(&IID_IMoniker, riid))
544 *ppvObject = iface;
545 if (IsEqualIID(&IID_IROTData, riid))
547 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
548 *ppvObject = &ROTData;
551 if ((*ppvObject)==0)
552 return E_NOINTERFACE;
554 IMoniker_AddRef(iface);
556 return S_OK;
559 static const IMonikerVtbl MonikerVtbl =
561 Moniker_QueryInterface,
562 Moniker_AddRef,
563 Moniker_Release,
564 Moniker_GetClassID,
565 Moniker_IsDirty,
566 Moniker_Load,
567 Moniker_Save,
568 Moniker_GetSizeMax,
569 Moniker_BindToObject,
570 Moniker_BindToStorage,
571 Moniker_Reduce,
572 Moniker_ComposeWith,
573 Moniker_Enum,
574 Moniker_IsEqual,
575 Moniker_Hash,
576 Moniker_IsRunning,
577 Moniker_GetTimeOfLastChange,
578 Moniker_Inverse,
579 Moniker_CommonPrefixWith,
580 Moniker_RelativePathTo,
581 Moniker_GetDisplayName,
582 Moniker_ParseDisplayName,
583 Moniker_IsSystemMoniker
586 static IMoniker Moniker = { &MonikerVtbl };
588 static void test_ROT(void)
590 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
591 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
592 '2','0','4','6','E','5','8','6','C','9','2','5',0};
593 HRESULT hr;
594 IMoniker *pMoniker = NULL;
595 IRunningObjectTable *pROT = NULL;
596 DWORD dwCookie;
597 static const char *methods_register_no_ROTData[] =
599 "Moniker_Reduce",
600 "Moniker_GetTimeOfLastChange",
601 "Moniker_QueryInterface(IID_IROTData)",
602 "Moniker_GetDisplayName",
603 "Moniker_GetClassID",
604 NULL
606 static const char *methods_register[] =
608 "Moniker_Reduce",
609 "Moniker_GetTimeOfLastChange",
610 "Moniker_QueryInterface(IID_IROTData)",
611 "ROTData_GetComparisonData",
612 NULL
614 static const char *methods_isrunning_no_ROTData[] =
616 "Moniker_Reduce",
617 "Moniker_QueryInterface(IID_IROTData)",
618 "Moniker_GetDisplayName",
619 "Moniker_GetClassID",
620 NULL
622 static const char *methods_isrunning[] =
624 "Moniker_Reduce",
625 "Moniker_QueryInterface(IID_IROTData)",
626 "ROTData_GetComparisonData",
627 NULL
630 cLocks = 0;
632 hr = GetRunningObjectTable(0, &pROT);
633 ok_ole_success(hr, GetRunningObjectTable);
635 expected_method_list = methods_register_no_ROTData;
636 external_connections = 0;
637 /* try with our own moniker that doesn't support IROTData */
638 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
639 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
640 ok_ole_success(hr, IRunningObjectTable_Register);
641 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
642 ok(external_connections == 1, "external_connections = %d\n", external_connections);
644 ok_more_than_one_lock();
646 expected_method_list = methods_isrunning_no_ROTData;
647 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
648 ok_ole_success(hr, IRunningObjectTable_IsRunning);
649 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
651 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
652 ok_ole_success(hr, IRunningObjectTable_Revoke);
653 ok(external_connections == 0, "external_connections = %d\n", external_connections);
655 ok_no_locks();
657 expected_method_list = methods_register;
658 /* try with our own moniker */
659 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
660 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
661 ok_ole_success(hr, IRunningObjectTable_Register);
662 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
664 ok_more_than_one_lock();
666 expected_method_list = methods_isrunning;
667 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
668 ok_ole_success(hr, IRunningObjectTable_IsRunning);
669 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
671 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
672 ok_ole_success(hr, IRunningObjectTable_Revoke);
674 ok_no_locks();
676 hr = CreateFileMoniker(wszFileName, &pMoniker);
677 ok_ole_success(hr, CreateClassMoniker);
679 /* test flags: 0 */
680 external_connections = 0;
681 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
682 pMoniker, &dwCookie);
683 ok_ole_success(hr, IRunningObjectTable_Register);
684 ok(external_connections == 0, "external_connections = %d\n", external_connections);
686 ok_more_than_one_lock();
688 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
689 ok_ole_success(hr, IRunningObjectTable_Revoke);
691 ok_no_locks();
693 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
694 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
695 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
696 ok_ole_success(hr, IRunningObjectTable_Register);
698 ok_more_than_one_lock();
700 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
701 ok_ole_success(hr, IRunningObjectTable_Revoke);
703 ok_no_locks();
705 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
706 /* only succeeds when process is started by SCM and has LocalService
707 * or RunAs AppId values */
708 hr = IRunningObjectTable_Register(pROT,
709 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
710 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
711 todo_wine {
712 ok(hr == CO_E_WRONG_SERVER_IDENTITY ||
713 broken(hr == S_OK) /* Win9x */,
714 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
716 if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie);
718 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
719 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
720 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
722 IMoniker_Release(pMoniker);
724 IRunningObjectTable_Release(pROT);
727 static void test_ROT_multiple_entries(void)
729 HRESULT hr;
730 IMoniker *pMoniker = NULL;
731 IRunningObjectTable *pROT = NULL;
732 DWORD dwCookie1, dwCookie2;
733 IUnknown *pObject = NULL;
734 static const WCHAR moniker_path[] =
735 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
737 hr = GetRunningObjectTable(0, &pROT);
738 ok_ole_success(hr, GetRunningObjectTable);
740 hr = CreateFileMoniker(moniker_path, &pMoniker);
741 ok_ole_success(hr, CreateFileMoniker);
743 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
744 ok_ole_success(hr, IRunningObjectTable_Register);
746 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
747 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
749 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
751 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
752 ok_ole_success(hr, IRunningObjectTable_GetObject);
753 IUnknown_Release(pObject);
755 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
756 ok_ole_success(hr, IRunningObjectTable_Revoke);
758 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
759 ok_ole_success(hr, IRunningObjectTable_GetObject);
760 IUnknown_Release(pObject);
762 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
763 ok_ole_success(hr, IRunningObjectTable_Revoke);
765 IMoniker_Release(pMoniker);
767 IRunningObjectTable_Release(pROT);
770 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
772 if (IsEqualIID(riid, &IID_IUnknown) ||
773 IsEqualIID(riid, &IID_IParseDisplayName))
775 *ppv = iface;
776 IParseDisplayName_AddRef(iface);
777 return S_OK;
779 *ppv = NULL;
780 return E_NOINTERFACE;
783 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
785 return 2;
788 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
790 return 1;
793 static LPCWSTR expected_display_name;
795 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
796 IBindCtx *pbc,
797 LPOLESTR pszDisplayName,
798 ULONG *pchEaten,
799 IMoniker **ppmkOut)
801 char display_nameA[256];
802 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
803 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
804 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
805 *pchEaten = lstrlenW(pszDisplayName);
806 return CreateAntiMoniker(ppmkOut);
809 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
811 ParseDisplayName_QueryInterface,
812 ParseDisplayName_AddRef,
813 ParseDisplayName_Release,
814 ParseDisplayName_ParseDisplayName
817 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
819 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
821 IMoniker * spMoniker;
822 int monCnt=0, matchCnt=0;
824 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
826 HRESULT hr;
827 WCHAR * szDisplayn;
828 monCnt++;
829 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
830 if (SUCCEEDED(hr))
832 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
833 matchCnt++;
834 CoTaskMemFree(szDisplayn);
837 trace("Total number of monikers is %i\n", monCnt);
838 return matchCnt;
841 static void test_MkParseDisplayName(void)
843 IBindCtx * pbc = NULL;
844 HRESULT hr;
845 IMoniker * pmk = NULL;
846 IMoniker * pmk1 = NULL;
847 IMoniker * pmk2 = NULL;
848 ULONG eaten;
849 int matchCnt;
850 IUnknown * object = NULL;
852 IUnknown *lpEM1;
854 IEnumMoniker *spEM1 = NULL;
855 IEnumMoniker *spEM2 = NULL;
856 IEnumMoniker *spEM3 = NULL;
858 DWORD pdwReg1=0;
859 DWORD grflags=0;
860 DWORD pdwReg2=0;
861 DWORD moniker_type;
862 IRunningObjectTable * pprot=NULL;
864 /* CLSID of My Computer */
865 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
866 '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};
867 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
868 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
869 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
870 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
871 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
872 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
873 static const WCHAR wszEmpty[] = {0};
874 char szDisplayNameFile[256];
875 WCHAR wszDisplayNameFile[256];
876 int i, len;
878 const struct
880 LPBC *ppbc;
881 LPCOLESTR szDisplayName;
882 LPDWORD pchEaten;
883 LPMONIKER *ppmk;
884 } invalid_parameters[] =
886 {NULL, NULL, NULL, NULL},
887 {NULL, NULL, NULL, &pmk},
888 {NULL, NULL, &eaten, NULL},
889 {NULL, NULL, &eaten, &pmk},
890 {NULL, wszEmpty, NULL, NULL},
891 {NULL, wszEmpty, NULL, &pmk},
892 {NULL, wszEmpty, &eaten, NULL},
893 {NULL, wszEmpty, &eaten, &pmk},
894 {&pbc, NULL, NULL, NULL},
895 {&pbc, NULL, NULL, &pmk},
896 {&pbc, NULL, &eaten, NULL},
897 {&pbc, NULL, &eaten, &pmk},
898 {&pbc, wszEmpty, NULL, NULL},
899 {&pbc, wszEmpty, NULL, &pmk},
900 {&pbc, wszEmpty, &eaten, NULL},
901 {&pbc, wszEmpty, &eaten, &pmk},
904 hr = CreateBindCtx(0, &pbc);
905 ok_ole_success(hr, CreateBindCtx);
907 for (i = 0; i < ARRAY_SIZE(invalid_parameters); i++)
909 eaten = 0xdeadbeef;
910 pmk = (IMoniker *)0xdeadbeef;
911 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
912 invalid_parameters[i].szDisplayName,
913 invalid_parameters[i].pchEaten,
914 invalid_parameters[i].ppmk);
915 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
916 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
917 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
920 eaten = 0xdeadbeef;
921 pmk = (IMoniker *)0xdeadbeef;
922 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
923 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
924 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
925 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
926 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
928 /* no special handling of "clsid:" without the string form of the clsid
929 * following */
930 eaten = 0xdeadbeef;
931 pmk = (IMoniker *)0xdeadbeef;
932 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
933 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
934 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
935 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
936 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
938 /* shows clsid has higher precedence than a running object */
939 hr = CreateFileMoniker(wszDisplayName, &pmk);
940 ok_ole_success(hr, CreateFileMoniker);
941 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
942 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
943 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
944 ok_ole_success(hr, IRunningObjectTable_Register);
945 IMoniker_Release(pmk);
946 pmk = NULL;
947 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
948 ok_ole_success(hr, MkParseDisplayName);
949 ok(eaten == ARRAY_SIZE(wszDisplayName) - 1,
950 "Processed character count should have been 43 instead of %u\n", eaten);
951 if (pmk)
953 IMoniker_IsSystemMoniker(pmk, &moniker_type);
954 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
955 IMoniker_Release(pmk);
957 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
958 ok_ole_success(hr, IRunningObjectTable_Revoke);
959 IRunningObjectTable_Release(pprot);
961 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
962 ok_ole_success(hr, CreateFileMoniker);
963 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
964 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
965 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
966 ok_ole_success(hr, IRunningObjectTable_Register);
967 IMoniker_Release(pmk);
968 pmk = NULL;
969 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
970 ok_ole_success(hr, MkParseDisplayName);
971 ok(eaten == ARRAY_SIZE(wszDisplayNameRunning) - 1,
972 "Processed character count should have been 15 instead of %u\n", eaten);
973 if (pmk)
975 IMoniker_IsSystemMoniker(pmk, &moniker_type);
976 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
977 IMoniker_Release(pmk);
979 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
980 ok_ole_success(hr, IRunningObjectTable_Revoke);
981 IRunningObjectTable_Release(pprot);
983 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
984 ok_ole_success(hr, CoRegisterClassObject);
986 expected_display_name = wszDisplayNameProgId1;
987 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
988 ok_ole_success(hr, MkParseDisplayName);
989 ok(eaten == ARRAY_SIZE(wszDisplayNameProgId1) - 1,
990 "Processed character count should have been 8 instead of %u\n", eaten);
991 if (pmk)
993 IMoniker_IsSystemMoniker(pmk, &moniker_type);
994 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
995 IMoniker_Release(pmk);
998 expected_display_name = wszDisplayNameProgId2;
999 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
1000 ok_ole_success(hr, MkParseDisplayName);
1001 ok(eaten == ARRAY_SIZE(wszDisplayNameProgId2) - 1,
1002 "Processed character count should have been 8 instead of %u\n", eaten);
1003 if (pmk)
1005 IMoniker_IsSystemMoniker(pmk, &moniker_type);
1006 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
1007 IMoniker_Release(pmk);
1010 eaten = 0xdeadbeef;
1011 pmk = (IMoniker *)0xdeadbeef;
1012 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
1013 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
1014 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
1015 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1016 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1018 hr = CoRevokeClassObject(pdwReg1);
1019 ok_ole_success(hr, CoRevokeClassObject);
1021 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
1022 strcat(szDisplayNameFile, "\\kernel32.dll");
1023 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile,
1024 ARRAY_SIZE(wszDisplayNameFile));
1025 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
1026 ok_ole_success(hr, MkParseDisplayName);
1027 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
1028 if (pmk)
1030 IMoniker_IsSystemMoniker(pmk, &moniker_type);
1031 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
1032 IMoniker_Release(pmk);
1035 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
1036 ok_ole_success(hr, MkParseDisplayName);
1037 ok(eaten == ARRAY_SIZE(wszDisplayName) - 1,
1038 "Processed character count should have been 43 instead of %u\n", eaten);
1040 if (pmk)
1042 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
1043 ok_ole_success(hr, IMoniker_BindToObject);
1045 if (SUCCEEDED(hr))
1046 IUnknown_Release(object);
1047 IMoniker_Release(pmk);
1049 IBindCtx_Release(pbc);
1051 /* Test the EnumMoniker interface */
1052 hr = CreateBindCtx(0, &pbc);
1053 ok_ole_success(hr, CreateBindCtx);
1055 hr = CreateFileMoniker(wszFileName1, &pmk1);
1056 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1057 hr = CreateFileMoniker(wszFileName2, &pmk2);
1058 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1059 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1060 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
1062 /* Check EnumMoniker before registering */
1063 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1064 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1065 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
1066 /* Register a couple of Monikers and check is ok */
1067 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
1069 matchCnt = count_moniker_matches(pbc, spEM1);
1070 trace("Number of matches is %i\n", matchCnt);
1072 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1073 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1074 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
1075 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
1077 trace("IROT::Register\n");
1078 grflags=0;
1079 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1080 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1081 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
1082 pprot, grflags, lpEM1, pmk2, pdwReg2);
1084 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1085 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1087 matchCnt = count_moniker_matches(pbc, spEM2);
1088 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1090 trace("IEnumMoniker::Clone\n");
1091 IEnumMoniker_Clone(spEM2, &spEM3);
1093 matchCnt = count_moniker_matches(pbc, spEM3);
1094 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1095 trace("IEnumMoniker::Reset\n");
1096 IEnumMoniker_Reset(spEM3);
1098 matchCnt = count_moniker_matches(pbc, spEM3);
1099 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1101 IRunningObjectTable_Revoke(pprot,pdwReg1);
1102 IRunningObjectTable_Revoke(pprot,pdwReg2);
1103 IUnknown_Release(lpEM1);
1104 IEnumMoniker_Release(spEM1);
1105 IEnumMoniker_Release(spEM2);
1106 IEnumMoniker_Release(spEM3);
1107 IMoniker_Release(pmk1);
1108 IMoniker_Release(pmk2);
1109 IRunningObjectTable_Release(pprot);
1111 IBindCtx_Release(pbc);
1114 static const LARGE_INTEGER llZero;
1116 static const BYTE expected_class_moniker_marshal_data[] =
1118 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1119 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1120 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1121 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1122 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1123 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1124 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1125 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1126 0x00,0x00,0x00,0x00,
1129 static const BYTE expected_class_moniker_saved_data[] =
1131 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1132 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1133 0x00,0x00,0x00,0x00,
1136 static const BYTE expected_class_moniker_comparison_data[] =
1138 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1139 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1140 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1141 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1144 static const WCHAR expected_class_moniker_display_name[] =
1146 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1147 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1148 '0','0','0','0','4','6',':',0
1151 static const BYTE expected_item_moniker_comparison_data[] =
1153 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1154 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1155 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1156 0x54,0x00,0x00,0x00,
1159 static const BYTE expected_item_moniker_saved_data[] =
1161 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1162 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1165 static const BYTE expected_item_moniker_marshal_data[] =
1167 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1168 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1169 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1170 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1171 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1172 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1173 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1174 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1177 static const BYTE expected_anti_moniker_marshal_data[] =
1179 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1180 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1181 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1182 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1183 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1184 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1185 0x01,0x00,0x00,0x00,
1188 static const BYTE expected_anti_moniker_saved_data[] =
1190 0x01,0x00,0x00,0x00,
1193 static const BYTE expected_anti_moniker_comparison_data[] =
1195 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1196 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1197 0x01,0x00,0x00,0x00,
1200 static const BYTE expected_gc_moniker_marshal_data[] =
1202 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1203 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1204 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1205 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1206 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1207 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1208 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1209 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1210 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1211 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1212 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1213 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1214 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1215 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1216 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1217 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1218 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1219 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1220 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1221 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1222 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1223 0x00,0x57,0x69,0x6e,0x65,0x00,
1226 static const BYTE expected_gc_moniker_saved_data[] =
1228 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1229 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1230 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1231 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1232 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1233 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1234 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1235 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1236 0x65,0x00,
1239 static const BYTE expected_gc_moniker_comparison_data[] =
1241 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1242 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1243 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1244 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1245 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1246 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1247 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1248 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1249 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1252 static void test_moniker(
1253 const char *testname, IMoniker *moniker,
1254 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1255 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1256 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1257 LPCWSTR expected_display_name)
1259 IStream * stream;
1260 IROTData * rotdata;
1261 HRESULT hr;
1262 HGLOBAL hglobal;
1263 LPBYTE moniker_data;
1264 DWORD moniker_size;
1265 DWORD i;
1266 BOOL same;
1267 BYTE buffer[128];
1268 IMoniker * moniker_proxy;
1269 LPOLESTR display_name;
1270 IBindCtx *bindctx;
1272 hr = IMoniker_IsDirty(moniker);
1273 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1275 /* Display Name */
1277 hr = CreateBindCtx(0, &bindctx);
1278 ok_ole_success(hr, CreateBindCtx);
1280 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1281 ok_ole_success(hr, IMoniker_GetDisplayName);
1282 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1284 CoTaskMemFree(display_name);
1285 IBindCtx_Release(bindctx);
1287 hr = IMoniker_IsDirty(moniker);
1288 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1290 /* IROTData::GetComparisonData test */
1292 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1293 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1295 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1296 ok_ole_success(hr, IROTData_GetComparisonData);
1298 if (hr != S_OK) moniker_size = 0;
1300 /* first check we have the right amount of data */
1301 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1302 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1303 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1305 /* then do a byte-by-byte comparison */
1306 same = TRUE;
1307 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1309 if (expected_moniker_comparison_data[i] != buffer[i])
1311 same = FALSE;
1312 break;
1316 ok(same, "%s: Comparison data differs\n", testname);
1317 if (!same)
1319 for (i = 0; i < moniker_size; i++)
1321 if (i % 8 == 0) printf(" ");
1322 printf("0x%02x,", buffer[i]);
1323 if (i % 8 == 7) printf("\n");
1325 printf("\n");
1328 IROTData_Release(rotdata);
1330 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1331 ok_ole_success(hr, CreateStreamOnHGlobal);
1333 /* Saving */
1335 hr = IMoniker_Save(moniker, stream, TRUE);
1336 ok_ole_success(hr, IMoniker_Save);
1338 hr = GetHGlobalFromStream(stream, &hglobal);
1339 ok_ole_success(hr, GetHGlobalFromStream);
1341 moniker_size = GlobalSize(hglobal);
1343 moniker_data = GlobalLock(hglobal);
1345 /* first check we have the right amount of data */
1346 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1347 "%s: Size of saved data differs (expected %d, actual %d)\n",
1348 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1350 /* then do a byte-by-byte comparison */
1351 same = TRUE;
1352 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1354 if (expected_moniker_saved_data[i] != moniker_data[i])
1356 same = FALSE;
1357 break;
1361 ok(same, "%s: Saved data differs\n", testname);
1362 if (!same)
1364 for (i = 0; i < moniker_size; i++)
1366 if (i % 8 == 0) printf(" ");
1367 printf("0x%02x,", moniker_data[i]);
1368 if (i % 8 == 7) printf("\n");
1370 printf("\n");
1373 GlobalUnlock(hglobal);
1375 IStream_Release(stream);
1377 /* Marshaling tests */
1379 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1380 ok_ole_success(hr, CreateStreamOnHGlobal);
1382 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1383 ok_ole_success(hr, CoMarshalInterface);
1385 hr = GetHGlobalFromStream(stream, &hglobal);
1386 ok_ole_success(hr, GetHGlobalFromStream);
1388 moniker_size = GlobalSize(hglobal);
1390 moniker_data = GlobalLock(hglobal);
1392 /* first check we have the right amount of data */
1393 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1394 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1395 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1397 /* then do a byte-by-byte comparison */
1398 same = TRUE;
1399 if (expected_moniker_marshal_data)
1401 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1403 if (expected_moniker_marshal_data[i] != moniker_data[i])
1405 same = FALSE;
1406 break;
1411 ok(same, "%s: Marshaled data differs\n", testname);
1412 if (!same)
1414 for (i = 0; i < moniker_size; i++)
1416 if (i % 8 == 0) printf(" ");
1417 printf("0x%02x,", moniker_data[i]);
1418 if (i % 8 == 7) printf("\n");
1420 printf("\n");
1423 GlobalUnlock(hglobal);
1425 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1426 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1427 ok_ole_success(hr, CoUnmarshalInterface);
1429 IStream_Release(stream);
1430 IMoniker_Release(moniker_proxy);
1433 static void test_class_moniker(void)
1435 HRESULT hr;
1436 IMoniker *moniker;
1437 DWORD moniker_type;
1438 DWORD hash;
1439 IBindCtx *bindctx;
1440 IMoniker *inverse;
1441 IUnknown *unknown;
1442 FILETIME filetime;
1444 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1445 ok_ole_success(hr, CreateClassMoniker);
1446 if (!moniker) return;
1448 test_moniker("class moniker", moniker,
1449 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1450 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1451 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1452 expected_class_moniker_display_name);
1454 /* Hashing */
1456 hr = IMoniker_Hash(moniker, &hash);
1457 ok_ole_success(hr, IMoniker_Hash);
1459 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1460 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1461 hash);
1463 /* IsSystemMoniker test */
1465 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1466 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1468 ok(moniker_type == MKSYS_CLASSMONIKER,
1469 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1470 moniker_type);
1472 hr = CreateBindCtx(0, &bindctx);
1473 ok_ole_success(hr, CreateBindCtx);
1475 /* IsRunning test */
1476 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1477 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1479 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1480 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1482 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1483 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1485 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1486 ok_ole_success(hr, IMoniker_BindToObject);
1487 IUnknown_Release(unknown);
1489 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1490 ok_ole_success(hr, IMoniker_BindToStorage);
1491 IUnknown_Release(unknown);
1493 IBindCtx_Release(bindctx);
1495 hr = IMoniker_Inverse(moniker, &inverse);
1496 ok_ole_success(hr, IMoniker_Inverse);
1497 IMoniker_Release(inverse);
1499 IMoniker_Release(moniker);
1502 static void test_file_moniker(WCHAR* path)
1504 IStream *stream;
1505 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1506 HRESULT hr;
1508 hr = CreateFileMoniker(path, &moniker1);
1509 ok_ole_success(hr, CreateFileMoniker);
1511 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1512 ok_ole_success(hr, CreateStreamOnHGlobal);
1514 /* Marshal */
1515 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1516 ok_ole_success(hr, CoMarshalInterface);
1518 /* Rewind */
1519 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1520 ok_ole_success(hr, IStream_Seek);
1522 /* Unmarshal */
1523 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1524 ok_ole_success(hr, CoUnmarshalInterface);
1526 hr = IMoniker_IsEqual(moniker1, moniker2);
1527 ok_ole_success(hr, IsEqual);
1529 IStream_Release(stream);
1530 if (moniker1)
1531 IMoniker_Release(moniker1);
1532 if (moniker2)
1533 IMoniker_Release(moniker2);
1536 static void test_file_monikers(void)
1538 static WCHAR wszFile[][30] = {
1539 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1540 {'\\', '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},
1541 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1542 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1543 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1544 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1545 * U+0100 .. = Latin extended-A
1547 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1550 int i;
1552 trace("ACP is %u\n", GetACP());
1554 for (i = 0; i < ARRAY_SIZE(wszFile); ++i)
1556 int j ;
1557 if (i == 2)
1559 BOOL used;
1560 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1561 if (used)
1563 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1564 continue;
1567 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1569 wszFile[i][j] = 0;
1570 test_file_moniker(wszFile[i]);
1575 static void test_item_moniker(void)
1577 HRESULT hr;
1578 IMoniker *moniker;
1579 DWORD moniker_type;
1580 DWORD hash;
1581 IBindCtx *bindctx;
1582 IMoniker *inverse;
1583 IUnknown *unknown;
1584 static const WCHAR wszDelimiter[] = {'!',0};
1585 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1586 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1588 hr = CreateItemMoniker(wszDelimiter, wszObjectName, &moniker);
1589 ok_ole_success(hr, CreateItemMoniker);
1591 test_moniker("item moniker", moniker,
1592 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1593 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1594 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1595 expected_display_name);
1597 /* Hashing */
1599 hr = IMoniker_Hash(moniker, &hash);
1600 ok_ole_success(hr, IMoniker_Hash);
1602 ok(hash == 0x73c,
1603 "Hash value != 0x73c, instead was 0x%08x\n",
1604 hash);
1606 /* IsSystemMoniker test */
1608 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1609 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1611 ok(moniker_type == MKSYS_ITEMMONIKER,
1612 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1613 moniker_type);
1615 hr = CreateBindCtx(0, &bindctx);
1616 ok_ole_success(hr, CreateBindCtx);
1618 /* IsRunning test */
1619 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1620 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1622 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1623 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1625 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1626 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1628 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1629 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1631 IBindCtx_Release(bindctx);
1633 hr = IMoniker_Inverse(moniker, &inverse);
1634 ok_ole_success(hr, IMoniker_Inverse);
1635 IMoniker_Release(inverse);
1637 IMoniker_Release(moniker);
1640 static void test_anti_moniker(void)
1642 HRESULT hr;
1643 IMoniker *moniker;
1644 DWORD moniker_type;
1645 DWORD hash;
1646 IBindCtx *bindctx;
1647 FILETIME filetime;
1648 IMoniker *inverse;
1649 IUnknown *unknown;
1650 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1652 hr = CreateAntiMoniker(&moniker);
1653 ok_ole_success(hr, CreateAntiMoniker);
1654 if (!moniker) return;
1656 test_moniker("anti moniker", moniker,
1657 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1658 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1659 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1660 expected_display_name);
1662 /* Hashing */
1663 hr = IMoniker_Hash(moniker, &hash);
1664 ok_ole_success(hr, IMoniker_Hash);
1665 ok(hash == 0x80000001,
1666 "Hash value != 0x80000001, instead was 0x%08x\n",
1667 hash);
1669 /* IsSystemMoniker test */
1670 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1671 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1672 ok(moniker_type == MKSYS_ANTIMONIKER,
1673 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1674 moniker_type);
1676 hr = IMoniker_Inverse(moniker, &inverse);
1677 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1678 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1680 hr = CreateBindCtx(0, &bindctx);
1681 ok_ole_success(hr, CreateBindCtx);
1683 /* IsRunning test */
1684 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1685 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1687 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1688 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1690 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1691 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1693 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1694 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1696 IBindCtx_Release(bindctx);
1698 IMoniker_Release(moniker);
1701 static void test_generic_composite_moniker(void)
1703 HRESULT hr;
1704 IMoniker *moniker;
1705 IMoniker *moniker1;
1706 IMoniker *moniker2;
1707 DWORD moniker_type;
1708 DWORD hash;
1709 IBindCtx *bindctx;
1710 FILETIME filetime;
1711 IMoniker *inverse;
1712 IUnknown *unknown;
1713 static const WCHAR wszDelimiter1[] = {'!',0};
1714 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1715 static const WCHAR wszDelimiter2[] = {'#',0};
1716 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1717 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1719 hr = CreateItemMoniker(wszDelimiter1, wszObjectName1, &moniker1);
1720 ok_ole_success(hr, CreateItemMoniker);
1721 hr = CreateItemMoniker(wszDelimiter2, wszObjectName2, &moniker2);
1722 ok_ole_success(hr, CreateItemMoniker);
1723 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1724 ok_ole_success(hr, CreateGenericComposite);
1726 test_moniker("generic composite moniker", moniker,
1727 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1728 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1729 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1730 expected_display_name);
1732 /* Hashing */
1734 hr = IMoniker_Hash(moniker, &hash);
1735 ok_ole_success(hr, IMoniker_Hash);
1737 ok(hash == 0xd87,
1738 "Hash value != 0xd87, instead was 0x%08x\n",
1739 hash);
1741 /* IsSystemMoniker test */
1743 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1744 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1746 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1747 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1748 moniker_type);
1750 hr = CreateBindCtx(0, &bindctx);
1751 ok_ole_success(hr, CreateBindCtx);
1753 /* IsRunning test */
1754 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1755 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1757 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1758 todo_wine
1759 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1761 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1762 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1764 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1765 todo_wine
1766 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1768 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1769 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1771 IBindCtx_Release(bindctx);
1773 hr = IMoniker_Inverse(moniker, &inverse);
1774 ok_ole_success(hr, IMoniker_Inverse);
1775 IMoniker_Release(inverse);
1777 IMoniker_Release(moniker);
1780 static void test_pointer_moniker(void)
1782 HRESULT hr;
1783 IMoniker *moniker;
1784 DWORD moniker_type;
1785 DWORD hash;
1786 IBindCtx *bindctx;
1787 FILETIME filetime;
1788 IMoniker *inverse;
1789 IUnknown *unknown;
1790 IStream *stream;
1791 IROTData *rotdata;
1792 LPOLESTR display_name;
1794 cLocks = 0;
1796 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1797 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1799 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1800 ok_ole_success(hr, CreatePointerMoniker);
1801 if (!moniker) return;
1803 ok_more_than_one_lock();
1805 /* Display Name */
1807 hr = CreateBindCtx(0, &bindctx);
1808 ok_ole_success(hr, CreateBindCtx);
1810 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1811 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1813 IBindCtx_Release(bindctx);
1815 hr = IMoniker_IsDirty(moniker);
1816 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1818 /* IROTData::GetComparisonData test */
1820 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1821 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1823 /* Saving */
1825 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1826 ok_ole_success(hr, CreateStreamOnHGlobal);
1828 hr = IMoniker_Save(moniker, stream, TRUE);
1829 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1831 IStream_Release(stream);
1833 /* Hashing */
1834 hr = IMoniker_Hash(moniker, &hash);
1835 ok_ole_success(hr, IMoniker_Hash);
1836 ok(hash == PtrToUlong(&Test_ClassFactory),
1837 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1838 PtrToUlong(&Test_ClassFactory), hash);
1840 /* IsSystemMoniker test */
1841 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1842 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1843 ok(moniker_type == MKSYS_POINTERMONIKER,
1844 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1845 moniker_type);
1847 hr = IMoniker_Inverse(moniker, &inverse);
1848 ok_ole_success(hr, IMoniker_Inverse);
1849 IMoniker_Release(inverse);
1851 hr = CreateBindCtx(0, &bindctx);
1852 ok_ole_success(hr, CreateBindCtx);
1854 /* IsRunning test */
1855 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1856 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1858 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1859 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1861 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1862 ok_ole_success(hr, IMoniker_BindToObject);
1863 IUnknown_Release(unknown);
1865 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1866 ok_ole_success(hr, IMoniker_BindToStorage);
1867 IUnknown_Release(unknown);
1869 IMoniker_Release(moniker);
1871 ok_no_locks();
1873 hr = CreatePointerMoniker(NULL, &moniker);
1874 ok_ole_success(hr, CreatePointerMoniker);
1876 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1877 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1879 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1880 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1882 IBindCtx_Release(bindctx);
1884 IMoniker_Release(moniker);
1887 static void test_bind_context(void)
1889 HRESULT hr;
1890 IBindCtx *pBindCtx;
1891 IEnumString *pEnumString;
1892 BIND_OPTS2 bind_opts;
1893 HeapUnknown *unknown;
1894 HeapUnknown *unknown2;
1895 IUnknown *param_obj;
1896 ULONG refs;
1897 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1898 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1900 hr = CreateBindCtx(0, NULL);
1901 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1903 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1904 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1906 hr = CreateBindCtx(0, &pBindCtx);
1907 ok_ole_success(hr, "CreateBindCtx");
1909 bind_opts.cbStruct = -1;
1910 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1911 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1912 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1913 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1914 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1916 bind_opts.cbStruct = sizeof(BIND_OPTS);
1917 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1918 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1919 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1921 bind_opts.cbStruct = sizeof(bind_opts);
1922 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1923 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1924 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1925 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1926 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1927 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1928 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1929 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1930 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1931 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1932 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1934 bind_opts.cbStruct = -1;
1935 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1936 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1938 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1939 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1941 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1942 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1943 unknown->refs = 1;
1944 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface);
1945 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1947 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1948 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1949 IUnknown_Release(param_obj);
1951 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1952 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1953 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1955 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1956 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1958 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1959 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1960 ok(!pEnumString, "pEnumString should be NULL\n");
1962 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1963 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1965 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1966 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1968 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1969 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1970 unknown2->refs = 1;
1971 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1972 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1974 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1975 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1977 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1978 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1980 IBindCtx_Release(pBindCtx);
1982 refs = IUnknown_Release(&unknown->IUnknown_iface);
1983 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1985 refs = IUnknown_Release(&unknown2->IUnknown_iface);
1986 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1989 static void test_save_load_filemoniker(void)
1991 IMoniker* pMk;
1992 IStream* pStm;
1993 HRESULT hr;
1994 ULARGE_INTEGER size;
1995 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
1996 DWORD some_val = 0xFEDCBA98;
1997 int i;
1999 /* see FileMonikerImpl_Save docs */
2000 zero_pos.QuadPart = 0;
2001 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
2002 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
2004 /* create the stream we're going to write to */
2005 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
2006 ok_ole_success(hr, "CreateStreamOnHGlobal");
2008 size.u.LowPart = 128;
2009 hr = IStream_SetSize(pStm, size);
2010 ok_ole_success(hr, "IStream_SetSize");
2012 /* create and save a moniker */
2013 hr = CreateFileMoniker(wszFileName1, &pMk);
2014 ok_ole_success(hr, "CreateFileMoniker");
2016 hr = IMoniker_Save(pMk, pStm, TRUE);
2017 ok_ole_success(hr, "IMoniker_Save");
2018 IMoniker_Release(pMk);
2020 /* overwrite the constants with various values */
2021 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
2022 ok_ole_success(hr, "IStream_Seek");
2023 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
2024 ok_ole_success(hr, "IStream_Write");
2026 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
2027 ok_ole_success(hr, "IStream_Seek");
2028 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
2029 ok_ole_success(hr, "IStream_Write");
2031 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
2032 ok_ole_success(hr, "IStream_Seek");
2033 for(i = 0; i < 5; ++i){
2034 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
2035 ok_ole_success(hr, "IStream_Write");
2038 /* go back to the start of the stream */
2039 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
2040 ok_ole_success(hr, "IStream_Seek");
2042 /* create a new moniker and load into it */
2043 hr = CreateFileMoniker(wszFileName1, &pMk);
2044 ok_ole_success(hr, "CreateFileMoniker");
2046 hr = IMoniker_Load(pMk, pStm);
2047 ok_ole_success(hr, "IMoniker_Load");
2049 IMoniker_Release(pMk);
2050 IStream_Release(pStm);
2053 START_TEST(moniker)
2055 if (!GetProcAddress(GetModuleHandleA("ole32.dll"), "CoRegisterSurrogateEx")) {
2056 win_skip("skipping test on win9x\n");
2057 return;
2060 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2062 test_ROT();
2063 test_ROT_multiple_entries();
2064 test_MkParseDisplayName();
2065 test_class_moniker();
2066 test_file_monikers();
2067 test_item_moniker();
2068 test_anti_moniker();
2069 test_generic_composite_moniker();
2070 test_pointer_moniker();
2071 test_save_load_filemoniker();
2073 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2075 test_bind_context();
2077 CoUninitialize();