ole32: Fix return codes returned by IBindCtx::RegisterObjectBound and IBindCtx::Revok...
[wine/hacks.git] / dlls / ole32 / tests / moniker.c
blobaa7c30f74ed52c700d280bbe749ca4bff587f098
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 "comcat.h"
33 #include "wine/test.h"
35 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
36 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
37 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
38 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
40 #define CHECK_EXPECTED_METHOD(method_name) \
41 do { \
42 trace("%s\n", method_name); \
43 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
44 if (*expected_method_list) \
45 { \
46 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
47 *expected_method_list, method_name); \
48 expected_method_list++; \
49 } \
50 } while(0)
52 static char const * const *expected_method_list;
53 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
54 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
56 static const CLSID CLSID_WineTest =
57 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
58 0x9474ba1a,
59 0x258b,
60 0x490b,
61 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
64 static const CLSID CLSID_TestMoniker =
65 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
66 0xb306bfbc,
67 0x496e,
68 0x4f53,
69 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
72 static LONG cLocks;
74 static void LockModule(void)
76 InterlockedIncrement(&cLocks);
79 static void UnlockModule(void)
81 InterlockedDecrement(&cLocks);
84 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
85 LPCLASSFACTORY iface,
86 REFIID riid,
87 LPVOID *ppvObj)
89 if (ppvObj == NULL) return E_POINTER;
91 if (IsEqualGUID(riid, &IID_IUnknown) ||
92 IsEqualGUID(riid, &IID_IClassFactory))
94 *ppvObj = (LPVOID)iface;
95 IClassFactory_AddRef(iface);
96 return S_OK;
99 *ppvObj = NULL;
100 return E_NOINTERFACE;
103 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
105 LockModule();
106 return 2; /* non-heap-based object */
109 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
111 UnlockModule();
112 return 1; /* non-heap-based object */
115 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
116 LPCLASSFACTORY iface,
117 LPUNKNOWN pUnkOuter,
118 REFIID riid,
119 LPVOID *ppvObj)
121 return E_NOTIMPL;
124 static HRESULT WINAPI Test_IClassFactory_LockServer(
125 LPCLASSFACTORY iface,
126 BOOL fLock)
128 return S_OK;
131 static const IClassFactoryVtbl TestClassFactory_Vtbl =
133 Test_IClassFactory_QueryInterface,
134 Test_IClassFactory_AddRef,
135 Test_IClassFactory_Release,
136 Test_IClassFactory_CreateInstance,
137 Test_IClassFactory_LockServer
140 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
142 typedef struct
144 const IUnknownVtbl *lpVtbl;
145 ULONG refs;
146 } HeapUnknown;
148 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
150 if (IsEqualIID(riid, &IID_IUnknown))
152 IUnknown_AddRef(iface);
153 *ppv = (LPVOID)iface;
154 return S_OK;
156 *ppv = NULL;
157 return E_NOINTERFACE;
160 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
162 HeapUnknown *This = (HeapUnknown *)iface;
163 return InterlockedIncrement((LONG*)&This->refs);
166 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
168 HeapUnknown *This = (HeapUnknown *)iface;
169 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
170 if (!refs) HeapFree(GetProcessHeap(), 0, This);
171 return refs;
174 static const IUnknownVtbl HeapUnknown_Vtbl =
176 HeapUnknown_QueryInterface,
177 HeapUnknown_AddRef,
178 HeapUnknown_Release
181 static HRESULT WINAPI
182 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
184 if (!ppvObject)
185 return E_INVALIDARG;
187 *ppvObject = 0;
189 if (IsEqualIID(&IID_IUnknown, riid) ||
190 IsEqualIID(&IID_IPersist, riid) ||
191 IsEqualIID(&IID_IPersistStream,riid) ||
192 IsEqualIID(&IID_IMoniker, riid))
193 *ppvObject = iface;
194 if (IsEqualIID(&IID_IROTData, riid))
195 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
197 if ((*ppvObject)==0)
198 return E_NOINTERFACE;
200 IMoniker_AddRef(iface);
202 return S_OK;
205 static ULONG WINAPI
206 Moniker_AddRef(IMoniker* iface)
208 return 2;
211 static ULONG WINAPI
212 Moniker_Release(IMoniker* iface)
214 return 1;
217 static HRESULT WINAPI
218 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
220 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
222 *pClassID = CLSID_TestMoniker;
224 return S_OK;
227 static HRESULT WINAPI
228 Moniker_IsDirty(IMoniker* iface)
230 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
232 return S_FALSE;
235 static HRESULT WINAPI
236 Moniker_Load(IMoniker* iface, IStream* pStm)
238 CHECK_EXPECTED_METHOD("Moniker_Load");
239 return E_NOTIMPL;
242 static HRESULT WINAPI
243 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
245 CHECK_EXPECTED_METHOD("Moniker_Save");
246 return E_NOTIMPL;
249 static HRESULT WINAPI
250 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
252 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
253 return E_NOTIMPL;
256 static HRESULT WINAPI
257 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
258 REFIID riid, VOID** ppvResult)
260 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
261 return E_NOTIMPL;
264 static HRESULT WINAPI
265 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
266 REFIID riid, VOID** ppvObject)
268 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
269 return E_NOTIMPL;
272 static HRESULT WINAPI
273 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
274 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
276 CHECK_EXPECTED_METHOD("Moniker_Reduce");
278 if (ppmkReduced==NULL)
279 return E_POINTER;
281 IMoniker_AddRef(iface);
283 *ppmkReduced=iface;
285 return MK_S_REDUCED_TO_SELF;
288 static HRESULT WINAPI
289 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
290 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
292 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
293 return E_NOTIMPL;
296 static HRESULT WINAPI
297 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
299 CHECK_EXPECTED_METHOD("Moniker_Enum");
301 if (ppenumMoniker == NULL)
302 return E_POINTER;
304 *ppenumMoniker = NULL;
306 return S_OK;
309 static HRESULT WINAPI
310 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
312 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
313 return E_NOTIMPL;
316 static HRESULT WINAPI
317 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
319 CHECK_EXPECTED_METHOD("Moniker_Hash");
320 return E_NOTIMPL;
323 static HRESULT WINAPI
324 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
325 IMoniker* pmkNewlyRunning)
327 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
328 return E_NOTIMPL;
331 static HRESULT WINAPI
332 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
333 IMoniker* pmkToLeft, FILETIME* pFileTime)
335 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
336 return E_NOTIMPL;
339 static HRESULT WINAPI
340 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
342 CHECK_EXPECTED_METHOD("Moniker_Inverse");
343 return E_NOTIMPL;
346 static HRESULT WINAPI
347 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
349 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
350 return E_NOTIMPL;
353 static HRESULT WINAPI
354 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
356 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
357 return E_NOTIMPL;
360 static HRESULT WINAPI
361 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
362 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
364 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
365 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
366 *ppszDisplayName = (LPOLESTR)CoTaskMemAlloc(sizeof(wszDisplayName));
367 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
368 return S_OK;
371 static HRESULT WINAPI
372 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
373 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
375 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
376 return E_NOTIMPL;
379 static HRESULT WINAPI
380 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
382 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
384 if (!pwdMksys)
385 return E_POINTER;
387 (*pwdMksys)=MKSYS_NONE;
389 return S_FALSE;
392 static const IMonikerVtbl MonikerNoROTDataVtbl =
394 MonikerNoROTData_QueryInterface,
395 Moniker_AddRef,
396 Moniker_Release,
397 Moniker_GetClassID,
398 Moniker_IsDirty,
399 Moniker_Load,
400 Moniker_Save,
401 Moniker_GetSizeMax,
402 Moniker_BindToObject,
403 Moniker_BindToStorage,
404 Moniker_Reduce,
405 Moniker_ComposeWith,
406 Moniker_Enum,
407 Moniker_IsEqual,
408 Moniker_Hash,
409 Moniker_IsRunning,
410 Moniker_GetTimeOfLastChange,
411 Moniker_Inverse,
412 Moniker_CommonPrefixWith,
413 Moniker_RelativePathTo,
414 Moniker_GetDisplayName,
415 Moniker_ParseDisplayName,
416 Moniker_IsSystemMoniker
419 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
421 static IMoniker Moniker;
423 static HRESULT WINAPI
424 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
426 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
429 static ULONG WINAPI
430 ROTData_AddRef(IROTData *iface)
432 return 2;
435 static ULONG WINAPI
436 ROTData_Release(IROTData* iface)
438 return 1;
441 static HRESULT WINAPI
442 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
443 ULONG cbMax, ULONG* pcbData)
445 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
447 *pcbData = 1;
448 if (cbMax < *pcbData)
449 return E_OUTOFMEMORY;
451 *pbData = 0xde;
453 return S_OK;
456 static IROTDataVtbl ROTDataVtbl =
458 ROTData_QueryInterface,
459 ROTData_AddRef,
460 ROTData_Release,
461 ROTData_GetComparisonData
464 static IROTData ROTData = { &ROTDataVtbl };
466 static HRESULT WINAPI
467 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
469 if (!ppvObject)
470 return E_INVALIDARG;
472 *ppvObject = 0;
474 if (IsEqualIID(&IID_IUnknown, riid) ||
475 IsEqualIID(&IID_IPersist, riid) ||
476 IsEqualIID(&IID_IPersistStream,riid) ||
477 IsEqualIID(&IID_IMoniker, riid))
478 *ppvObject = iface;
479 if (IsEqualIID(&IID_IROTData, riid))
481 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
482 *ppvObject = &ROTData;
485 if ((*ppvObject)==0)
486 return E_NOINTERFACE;
488 IMoniker_AddRef(iface);
490 return S_OK;
493 static const IMonikerVtbl MonikerVtbl =
495 Moniker_QueryInterface,
496 Moniker_AddRef,
497 Moniker_Release,
498 Moniker_GetClassID,
499 Moniker_IsDirty,
500 Moniker_Load,
501 Moniker_Save,
502 Moniker_GetSizeMax,
503 Moniker_BindToObject,
504 Moniker_BindToStorage,
505 Moniker_Reduce,
506 Moniker_ComposeWith,
507 Moniker_Enum,
508 Moniker_IsEqual,
509 Moniker_Hash,
510 Moniker_IsRunning,
511 Moniker_GetTimeOfLastChange,
512 Moniker_Inverse,
513 Moniker_CommonPrefixWith,
514 Moniker_RelativePathTo,
515 Moniker_GetDisplayName,
516 Moniker_ParseDisplayName,
517 Moniker_IsSystemMoniker
520 static IMoniker Moniker = { &MonikerVtbl };
522 static void test_ROT(void)
524 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
525 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
526 '2','0','4','6','E','5','8','6','C','9','2','5',0};
527 HRESULT hr;
528 IMoniker *pMoniker = NULL;
529 IRunningObjectTable *pROT = NULL;
530 DWORD dwCookie;
531 static const char *methods_register_no_ROTData[] =
533 "Moniker_Reduce",
534 "Moniker_GetTimeOfLastChange",
535 "Moniker_QueryInterface(IID_IROTData)",
536 "Moniker_GetDisplayName",
537 "Moniker_GetClassID",
538 NULL
540 static const char *methods_register[] =
542 "Moniker_Reduce",
543 "Moniker_GetTimeOfLastChange",
544 "Moniker_QueryInterface(IID_IROTData)",
545 "ROTData_GetComparisonData",
546 NULL
548 static const char *methods_isrunning_no_ROTData[] =
550 "Moniker_Reduce",
551 "Moniker_QueryInterface(IID_IROTData)",
552 "Moniker_GetDisplayName",
553 "Moniker_GetClassID",
554 NULL
556 static const char *methods_isrunning[] =
558 "Moniker_Reduce",
559 "Moniker_QueryInterface(IID_IROTData)",
560 "ROTData_GetComparisonData",
561 NULL
564 cLocks = 0;
566 hr = GetRunningObjectTable(0, &pROT);
567 ok_ole_success(hr, GetRunningObjectTable);
569 expected_method_list = methods_register_no_ROTData;
570 /* try with our own moniker that doesn't support IROTData */
571 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
572 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
573 todo_wine { /* only fails because of lack of IMoniker marshaling */
574 ok_ole_success(hr, IRunningObjectTable_Register);
576 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
578 todo_wine { /* only fails because of lack of IMoniker marshaling */
579 ok_more_than_one_lock();
582 expected_method_list = methods_isrunning_no_ROTData;
583 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
584 todo_wine { /* only fails because of lack of IMoniker marshaling */
585 ok_ole_success(hr, IRunningObjectTable_IsRunning);
587 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
589 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
590 todo_wine { /* only fails because of lack of IMoniker marshaling */
591 ok_ole_success(hr, IRunningObjectTable_Revoke);
594 ok_no_locks();
596 expected_method_list = methods_register;
597 /* try with our own moniker */
598 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
599 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
600 todo_wine { /* only fails because of lack of IMoniker marshaling */
601 ok_ole_success(hr, IRunningObjectTable_Register);
603 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
605 todo_wine { /* only fails because of lack of IMoniker marshaling */
606 ok_more_than_one_lock();
609 expected_method_list = methods_isrunning;
610 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
611 todo_wine { /* only fails because of lack of IMoniker marshaling */
612 ok_ole_success(hr, IRunningObjectTable_IsRunning);
614 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
616 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
617 todo_wine { /* only fails because of lack of IMoniker marshaling */
618 ok_ole_success(hr, IRunningObjectTable_Revoke);
621 ok_no_locks();
623 hr = CreateFileMoniker(wszFileName, &pMoniker);
624 ok_ole_success(hr, CreateClassMoniker);
626 /* test flags: 0 */
627 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
628 pMoniker, &dwCookie);
629 ok_ole_success(hr, IRunningObjectTable_Register);
631 ok_more_than_one_lock();
633 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
634 ok_ole_success(hr, IRunningObjectTable_Revoke);
636 ok_no_locks();
638 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
639 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
640 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
641 ok_ole_success(hr, IRunningObjectTable_Register);
643 ok_more_than_one_lock();
645 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
646 ok_ole_success(hr, IRunningObjectTable_Revoke);
648 ok_no_locks();
650 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
651 /* only succeeds when process is started by SCM and has LocalService
652 * or RunAs AppId values */
653 hr = IRunningObjectTable_Register(pROT,
654 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
655 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
656 todo_wine {
657 ok(hr == CO_E_WRONG_SERVER_IDENTITY, "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
660 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
661 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
662 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
664 IMoniker_Release(pMoniker);
666 IRunningObjectTable_Release(pROT);
669 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
671 IMoniker * spMoniker;
672 int monCnt=0, matchCnt=0;
674 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
676 HRESULT hr;
677 WCHAR * szDisplayn;
678 monCnt++;
679 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
680 if (SUCCEEDED(hr))
682 if (!lstrcmpW(szDisplayn, wszFileName1) || !lstrcmpW(szDisplayn, wszFileName2))
683 matchCnt++;
684 CoTaskMemFree(szDisplayn);
687 trace("Total number of monikers is %i\n", monCnt);
688 return matchCnt;
691 static void test_MkParseDisplayName(void)
693 IBindCtx * pbc = NULL;
694 HRESULT hr;
695 IMoniker * pmk = NULL;
696 IMoniker * pmk1 = NULL;
697 IMoniker * pmk2 = NULL;
698 ULONG eaten;
699 int matchCnt;
700 IUnknown * object = NULL;
702 IUnknown *lpEM1;
704 IEnumMoniker *spEM1 = NULL;
705 IEnumMoniker *spEM2 = NULL;
706 IEnumMoniker *spEM3 = NULL;
708 DWORD pdwReg1=0;
709 DWORD grflags=0;
710 DWORD pdwReg2=0;
711 IRunningObjectTable * pprot=NULL;
713 /* CLSID of My Computer */
714 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
715 '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};
717 hr = CreateBindCtx(0, &pbc);
718 ok_ole_success(hr, CreateBindCtx);
720 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
721 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
723 if (object)
725 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
726 ok_ole_success(hr, IMoniker_BindToObject);
728 IUnknown_Release(object);
730 IBindCtx_Release(pbc);
732 /* Test the EnumMoniker interface */
733 hr = CreateBindCtx(0, &pbc);
734 ok_ole_success(hr, CreateBindCtx);
736 hr = CreateFileMoniker(wszFileName1, &pmk1);
737 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
738 hr = CreateFileMoniker(wszFileName2, &pmk2);
739 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
740 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
741 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
743 /* Check EnumMoniker before registering */
744 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
745 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
746 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
747 /* Register a couple of Monikers and check is ok */
748 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
749 hr = MK_E_NOOBJECT;
751 matchCnt = count_moniker_matches(pbc, spEM1);
752 trace("Number of matches is %i\n", matchCnt);
754 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
755 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
756 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
757 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
759 trace("IROT::Register\n");
760 grflags=0;
761 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
762 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
763 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
764 pprot, grflags, lpEM1, pmk2, pdwReg2);
766 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
767 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
769 matchCnt = count_moniker_matches(pbc, spEM2);
770 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
772 trace("IEnumMoniker::Clone\n");
773 IEnumMoniker_Clone(spEM2, &spEM3);
775 matchCnt = count_moniker_matches(pbc, spEM3);
776 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
777 trace("IEnumMoniker::Reset\n");
778 IEnumMoniker_Reset(spEM3);
780 matchCnt = count_moniker_matches(pbc, spEM3);
781 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
783 IRunningObjectTable_Revoke(pprot,pdwReg1);
784 IRunningObjectTable_Revoke(pprot,pdwReg2);
785 IEnumMoniker_Release(spEM1);
786 IEnumMoniker_Release(spEM1);
787 IEnumMoniker_Release(spEM2);
788 IEnumMoniker_Release(spEM3);
789 IMoniker_Release(pmk1);
790 IMoniker_Release(pmk2);
791 IRunningObjectTable_Release(pprot);
793 IBindCtx_Release(pbc);
796 static const LARGE_INTEGER llZero;
798 static const BYTE expected_class_moniker_marshal_data[] =
800 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
801 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
802 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
803 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
804 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
805 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
806 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
807 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
808 0x00,0x00,0x00,0x00,
811 static const BYTE expected_class_moniker_saved_data[] =
813 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
814 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
815 0x00,0x00,0x00,0x00,
818 static const BYTE expected_class_moniker_comparison_data[] =
820 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
821 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
822 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
823 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
826 static const WCHAR expected_class_moniker_display_name[] =
828 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
829 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
830 '0','0','0','0','4','6',':',0
833 static const BYTE expected_item_moniker_comparison_data[] =
835 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
836 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
837 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
838 0x54,0x00,0x00,0x00,
841 static const BYTE expected_item_moniker_saved_data[] =
843 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
844 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
847 static const BYTE expected_item_moniker_marshal_data[] =
849 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
850 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
851 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
852 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
853 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
854 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
855 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
856 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
859 static const BYTE expected_anti_moniker_marshal_data[] =
861 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
862 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
863 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
864 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
865 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
866 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
867 0x01,0x00,0x00,0x00,
870 static const BYTE expected_anti_moniker_saved_data[] =
872 0x01,0x00,0x00,0x00,
875 static const BYTE expected_anti_moniker_comparison_data[] =
877 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
878 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
879 0x01,0x00,0x00,0x00,
882 static const BYTE expected_gc_moniker_marshal_data[] =
884 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
885 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
886 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
887 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
888 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
889 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
890 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
891 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
892 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
893 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
894 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
895 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
896 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
897 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
898 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
899 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
900 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
901 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
902 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
903 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
904 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
905 0x00,0x57,0x69,0x6e,0x65,0x00,
908 static const BYTE expected_gc_moniker_saved_data[] =
910 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
911 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
912 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
913 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
914 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
915 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
916 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
917 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
918 0x65,0x00,
921 static const BYTE expected_gc_moniker_comparison_data[] =
923 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
924 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
925 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
926 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
927 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
928 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
929 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
930 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
931 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
934 static void test_moniker(
935 const char *testname, IMoniker *moniker,
936 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
937 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
938 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
939 LPCWSTR expected_display_name)
941 IStream * stream;
942 IROTData * rotdata;
943 HRESULT hr;
944 HGLOBAL hglobal;
945 LPBYTE moniker_data;
946 DWORD moniker_size;
947 DWORD i;
948 BOOL same = TRUE;
949 BYTE buffer[128];
950 IMoniker * moniker_proxy;
951 LPOLESTR display_name;
952 IBindCtx *bindctx;
954 hr = IMoniker_IsDirty(moniker);
955 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
957 /* Display Name */
959 hr = CreateBindCtx(0, &bindctx);
960 ok_ole_success(hr, CreateBindCtx);
962 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
963 ok_ole_success(hr, IMoniker_GetDisplayName);
964 ok(!lstrcmpW(display_name, expected_display_name), "display name wasn't what was expected\n");
966 CoTaskMemFree(display_name);
967 IBindCtx_Release(bindctx);
969 hr = IMoniker_IsDirty(moniker);
970 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
972 /* IROTData::GetComparisonData test */
974 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
975 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
977 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
978 ok_ole_success(hr, IROTData_GetComparisonData);
980 if (hr != S_OK) moniker_size = 0;
982 /* first check we have the right amount of data */
983 ok(moniker_size == sizeof_expected_moniker_comparison_data,
984 "%s: Size of comparison data differs (expected %d, actual %d)\n",
985 testname, sizeof_expected_moniker_comparison_data, moniker_size);
987 /* then do a byte-by-byte comparison */
988 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
990 if (expected_moniker_comparison_data[i] != buffer[i])
992 same = FALSE;
993 break;
997 ok(same, "%s: Comparison data differs\n", testname);
998 if (!same)
1000 for (i = 0; i < moniker_size; i++)
1002 if (i % 8 == 0) printf(" ");
1003 printf("0x%02x,", buffer[i]);
1004 if (i % 8 == 7) printf("\n");
1006 printf("\n");
1009 IROTData_Release(rotdata);
1011 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1013 /* Saving */
1015 hr = IMoniker_Save(moniker, stream, TRUE);
1016 ok_ole_success(hr, IMoniker_Save);
1018 hr = GetHGlobalFromStream(stream, &hglobal);
1019 ok_ole_success(hr, GetHGlobalFromStream);
1021 moniker_size = GlobalSize(hglobal);
1023 moniker_data = GlobalLock(hglobal);
1025 /* first check we have the right amount of data */
1026 ok(moniker_size == sizeof_expected_moniker_saved_data,
1027 "%s: Size of saved data differs (expected %d, actual %d)\n",
1028 testname, sizeof_expected_moniker_saved_data, moniker_size);
1030 /* then do a byte-by-byte comparison */
1031 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
1033 if (expected_moniker_saved_data[i] != moniker_data[i])
1035 same = FALSE;
1036 break;
1040 ok(same, "%s: Saved data differs\n", testname);
1041 if (!same)
1043 for (i = 0; i < moniker_size; i++)
1045 if (i % 8 == 0) printf(" ");
1046 printf("0x%02x,", moniker_data[i]);
1047 if (i % 8 == 7) printf("\n");
1049 printf("\n");
1052 GlobalUnlock(hglobal);
1054 IStream_Release(stream);
1056 /* Marshaling tests */
1058 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1059 ok_ole_success(hr, CreateStreamOnHGlobal);
1061 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1062 ok_ole_success(hr, CoMarshalInterface);
1064 hr = GetHGlobalFromStream(stream, &hglobal);
1065 ok_ole_success(hr, GetHGlobalFromStream);
1067 moniker_size = GlobalSize(hglobal);
1069 moniker_data = GlobalLock(hglobal);
1071 /* first check we have the right amount of data */
1072 ok(moniker_size == sizeof_expected_moniker_marshal_data,
1073 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1074 testname, sizeof_expected_moniker_marshal_data, moniker_size);
1076 /* then do a byte-by-byte comparison */
1077 if (expected_moniker_marshal_data)
1079 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1081 if (expected_moniker_marshal_data[i] != moniker_data[i])
1083 same = FALSE;
1084 break;
1089 ok(same, "%s: Marshaled data differs\n", testname);
1090 if (!same)
1092 for (i = 0; i < moniker_size; i++)
1094 if (i % 8 == 0) printf(" ");
1095 printf("0x%02x,", moniker_data[i]);
1096 if (i % 8 == 7) printf("\n");
1098 printf("\n");
1101 GlobalUnlock(hglobal);
1103 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1104 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1105 ok_ole_success(hr, CoUnmarshalInterface);
1107 IStream_Release(stream);
1108 IMoniker_Release(moniker_proxy);
1111 static void test_class_moniker(void)
1113 HRESULT hr;
1114 IMoniker *moniker;
1115 DWORD moniker_type;
1116 DWORD hash;
1117 IBindCtx *bindctx;
1118 IMoniker *inverse;
1119 IUnknown *unknown;
1120 FILETIME filetime;
1122 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1123 ok_ole_success(hr, CreateClassMoniker);
1124 if (!moniker) return;
1126 test_moniker("class moniker", moniker,
1127 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1128 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1129 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1130 expected_class_moniker_display_name);
1132 /* Hashing */
1134 hr = IMoniker_Hash(moniker, &hash);
1135 ok_ole_success(hr, IMoniker_Hash);
1137 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1138 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1139 hash);
1141 /* IsSystemMoniker test */
1143 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1144 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1146 ok(moniker_type == MKSYS_CLASSMONIKER,
1147 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1148 moniker_type);
1150 hr = CreateBindCtx(0, &bindctx);
1151 ok_ole_success(hr, CreateBindCtx);
1153 /* IsRunning test */
1154 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1155 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1157 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1158 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1160 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1161 ok_ole_success(hr, IMoniker_BindToStorage);
1162 IUnknown_Release(unknown);
1164 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1165 ok_ole_success(hr, IMoniker_BindToStorage);
1166 IUnknown_Release(unknown);
1168 IBindCtx_Release(bindctx);
1170 hr = IMoniker_Inverse(moniker, &inverse);
1171 ok_ole_success(hr, IMoniker_Inverse);
1172 IMoniker_Release(inverse);
1174 IMoniker_Release(moniker);
1177 static void test_file_moniker(WCHAR* path)
1179 IStream *stream;
1180 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1181 HRESULT hr;
1183 hr = CreateFileMoniker(path, &moniker1);
1184 ok_ole_success(hr, CreateFileMoniker);
1186 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1188 /* Marshal */
1189 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1190 ok_ole_success(hr, CoMarshalInterface);
1192 /* Rewind */
1193 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1194 ok_ole_success(hr, IStream_Seek);
1196 /* Unmarshal */
1197 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1198 ok_ole_success(hr, CoUnmarshalInterface);
1200 hr = IMoniker_IsEqual(moniker1, moniker2);
1201 ok_ole_success(hr, IsEqual);
1203 IStream_Release(stream);
1204 if (moniker1)
1205 IMoniker_Release(moniker1);
1206 if (moniker2)
1207 IMoniker_Release(moniker2);
1210 static void test_file_monikers(void)
1212 static WCHAR wszFile[][30] = {
1213 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1214 {'\\', '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},
1215 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1216 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1217 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1218 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1219 * U+0100 .. = Latin extended-A
1221 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1224 int i;
1226 trace("ACP is %u\n", GetACP());
1228 for (i = 0; i < COUNTOF(wszFile); ++i)
1230 int j ;
1231 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1233 wszFile[i][j] = 0;
1234 test_file_moniker(wszFile[i]);
1239 static void test_item_moniker(void)
1241 HRESULT hr;
1242 IMoniker *moniker;
1243 DWORD moniker_type;
1244 DWORD hash;
1245 IBindCtx *bindctx;
1246 IMoniker *inverse;
1247 IUnknown *unknown;
1248 static const WCHAR wszDelimeter[] = {'!',0};
1249 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1250 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1252 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1253 ok_ole_success(hr, CreateItemMoniker);
1255 test_moniker("item moniker", moniker,
1256 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1257 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1258 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1259 expected_display_name);
1261 /* Hashing */
1263 hr = IMoniker_Hash(moniker, &hash);
1264 ok_ole_success(hr, IMoniker_Hash);
1266 ok(hash == 0x73c,
1267 "Hash value != 0x73c, instead was 0x%08x\n",
1268 hash);
1270 /* IsSystemMoniker test */
1272 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1273 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1275 ok(moniker_type == MKSYS_ITEMMONIKER,
1276 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1277 moniker_type);
1279 hr = CreateBindCtx(0, &bindctx);
1280 ok_ole_success(hr, CreateBindCtx);
1282 /* IsRunning test */
1283 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1284 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1286 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1287 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1289 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1290 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1292 IBindCtx_Release(bindctx);
1294 hr = IMoniker_Inverse(moniker, &inverse);
1295 ok_ole_success(hr, IMoniker_Inverse);
1296 IMoniker_Release(inverse);
1298 IMoniker_Release(moniker);
1301 static void test_anti_moniker(void)
1303 HRESULT hr;
1304 IMoniker *moniker;
1305 DWORD moniker_type;
1306 DWORD hash;
1307 IBindCtx *bindctx;
1308 FILETIME filetime;
1309 IMoniker *inverse;
1310 IUnknown *unknown;
1311 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1313 hr = CreateAntiMoniker(&moniker);
1314 ok_ole_success(hr, CreateAntiMoniker);
1315 if (!moniker) return;
1317 test_moniker("anti moniker", moniker,
1318 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1319 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1320 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1321 expected_display_name);
1323 /* Hashing */
1324 hr = IMoniker_Hash(moniker, &hash);
1325 ok_ole_success(hr, IMoniker_Hash);
1326 ok(hash == 0x80000001,
1327 "Hash value != 0x80000001, instead was 0x%08x\n",
1328 hash);
1330 /* IsSystemMoniker test */
1331 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1332 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1333 ok(moniker_type == MKSYS_ANTIMONIKER,
1334 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1335 moniker_type);
1337 hr = IMoniker_Inverse(moniker, &inverse);
1338 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1339 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1341 hr = CreateBindCtx(0, &bindctx);
1342 ok_ole_success(hr, CreateBindCtx);
1344 /* IsRunning test */
1345 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1346 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1348 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1349 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1351 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1352 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1354 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1355 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1357 IBindCtx_Release(bindctx);
1359 IMoniker_Release(moniker);
1362 static void test_generic_composite_moniker(void)
1364 HRESULT hr;
1365 IMoniker *moniker;
1366 IMoniker *moniker1;
1367 IMoniker *moniker2;
1368 DWORD moniker_type;
1369 DWORD hash;
1370 IBindCtx *bindctx;
1371 FILETIME filetime;
1372 IMoniker *inverse;
1373 IUnknown *unknown;
1374 static const WCHAR wszDelimeter1[] = {'!',0};
1375 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1376 static const WCHAR wszDelimeter2[] = {'#',0};
1377 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1378 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1380 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1381 ok_ole_success(hr, CreateItemMoniker);
1382 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1383 ok_ole_success(hr, CreateItemMoniker);
1384 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1385 ok_ole_success(hr, CreateGenericComposite);
1387 test_moniker("generic composite moniker", moniker,
1388 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1389 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1390 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1391 expected_display_name);
1393 /* Hashing */
1395 hr = IMoniker_Hash(moniker, &hash);
1396 ok_ole_success(hr, IMoniker_Hash);
1398 ok(hash == 0xd87,
1399 "Hash value != 0xd87, instead was 0x%08x\n",
1400 hash);
1402 /* IsSystemMoniker test */
1404 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1405 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1407 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1408 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1409 moniker_type);
1411 hr = CreateBindCtx(0, &bindctx);
1412 ok_ole_success(hr, CreateBindCtx);
1414 /* IsRunning test */
1415 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1416 todo_wine
1417 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1419 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1420 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1422 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1423 todo_wine
1424 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1426 todo_wine
1427 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1428 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1430 IBindCtx_Release(bindctx);
1432 hr = IMoniker_Inverse(moniker, &inverse);
1433 ok_ole_success(hr, IMoniker_Inverse);
1434 IMoniker_Release(inverse);
1436 IMoniker_Release(moniker);
1439 static void test_bind_context(void)
1441 HRESULT hr;
1442 IBindCtx *pBindCtx;
1443 IEnumString *pEnumString;
1444 BIND_OPTS2 bind_opts;
1445 HeapUnknown *unknown;
1446 HeapUnknown *unknown2;
1447 IUnknown *param_obj;
1448 ULONG refs;
1449 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1450 static const WCHAR wszNonExistant[] = {'N','o','n','E','x','i','s','t','a','n','t',0};
1452 hr = CreateBindCtx(0, NULL);
1453 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1455 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1456 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1458 hr = CreateBindCtx(0, &pBindCtx);
1459 ok_ole_success(hr, "CreateBindCtx");
1461 bind_opts.cbStruct = -1;
1462 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1463 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1464 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1466 bind_opts.cbStruct = sizeof(BIND_OPTS);
1467 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1468 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1469 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1471 bind_opts.cbStruct = sizeof(bind_opts);
1472 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1473 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1474 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1475 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1476 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1477 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1478 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1479 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1480 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1481 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1482 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1484 bind_opts.cbStruct = -1;
1485 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1486 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1488 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1489 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1491 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1492 unknown->lpVtbl = &HeapUnknown_Vtbl;
1493 unknown->refs = 1;
1494 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1495 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1497 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1498 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1499 IUnknown_Release(param_obj);
1501 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistant, &param_obj);
1502 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with non-existing key should have failed with E_FAIL instead of 0x%08x\n", hr);
1503 ok(param_obj == NULL, "IBindCtx_GetObjectParam with non-existing key should have set output parameter to NULL instead of %p\n", param_obj);
1505 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistant);
1506 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with non-existing key should have failed with E_FAIL instead of 0x%08x\n", hr);
1508 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1509 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1510 ok(!pEnumString, "pEnumString should be NULL\n");
1512 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1513 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1515 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1516 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1518 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1519 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1520 unknown2->refs = 1;
1521 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1522 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1524 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1525 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1527 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1528 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1530 IBindCtx_Release(pBindCtx);
1532 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1533 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1535 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1536 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1539 START_TEST(moniker)
1541 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1543 test_ROT();
1544 test_MkParseDisplayName();
1545 test_class_moniker();
1546 test_file_monikers();
1547 test_item_moniker();
1548 test_anti_moniker();
1549 test_generic_composite_moniker();
1551 /* FIXME: test moniker creation funcs and parsing other moniker formats */
1553 test_bind_context();
1555 CoUninitialize();