ole32: Fix a use-after-free of the file moniker in the running object table tests.
[wine.git] / dlls / ole32 / tests / moniker.c
blobf603f724c852b9948bd6d879fbc792bfd01568f7
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 static HRESULT WINAPI
143 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
145 if (!ppvObject)
146 return E_INVALIDARG;
148 *ppvObject = 0;
150 if (IsEqualIID(&IID_IUnknown, riid) ||
151 IsEqualIID(&IID_IPersist, riid) ||
152 IsEqualIID(&IID_IPersistStream,riid) ||
153 IsEqualIID(&IID_IMoniker, riid))
154 *ppvObject = iface;
155 if (IsEqualIID(&IID_IROTData, riid))
156 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
158 if ((*ppvObject)==0)
159 return E_NOINTERFACE;
161 IMoniker_AddRef(iface);
163 return S_OK;
166 static ULONG WINAPI
167 Moniker_AddRef(IMoniker* iface)
169 return 2;
172 static ULONG WINAPI
173 Moniker_Release(IMoniker* iface)
175 return 1;
178 static HRESULT WINAPI
179 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
181 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
183 *pClassID = CLSID_TestMoniker;
185 return S_OK;
188 static HRESULT WINAPI
189 Moniker_IsDirty(IMoniker* iface)
191 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
193 return S_FALSE;
196 static HRESULT WINAPI
197 Moniker_Load(IMoniker* iface, IStream* pStm)
199 CHECK_EXPECTED_METHOD("Moniker_Load");
200 return E_NOTIMPL;
203 static HRESULT WINAPI
204 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
206 CHECK_EXPECTED_METHOD("Moniker_Save");
207 return E_NOTIMPL;
210 static HRESULT WINAPI
211 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
213 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
214 return E_NOTIMPL;
217 static HRESULT WINAPI
218 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
219 REFIID riid, VOID** ppvResult)
221 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
222 return E_NOTIMPL;
225 static HRESULT WINAPI
226 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
227 REFIID riid, VOID** ppvObject)
229 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
230 return E_NOTIMPL;
233 static HRESULT WINAPI
234 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
235 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
237 CHECK_EXPECTED_METHOD("Moniker_Reduce");
239 if (ppmkReduced==NULL)
240 return E_POINTER;
242 IMoniker_AddRef(iface);
244 *ppmkReduced=iface;
246 return MK_S_REDUCED_TO_SELF;
249 static HRESULT WINAPI
250 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
251 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
253 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
254 return E_NOTIMPL;
257 static HRESULT WINAPI
258 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
260 CHECK_EXPECTED_METHOD("Moniker_Enum");
262 if (ppenumMoniker == NULL)
263 return E_POINTER;
265 *ppenumMoniker = NULL;
267 return S_OK;
270 static HRESULT WINAPI
271 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
273 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
274 return E_NOTIMPL;
277 static HRESULT WINAPI
278 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
280 CHECK_EXPECTED_METHOD("Moniker_Hash");
281 return E_NOTIMPL;
284 static HRESULT WINAPI
285 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
286 IMoniker* pmkNewlyRunning)
288 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
289 return E_NOTIMPL;
292 static HRESULT WINAPI
293 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
294 IMoniker* pmkToLeft, FILETIME* pFileTime)
296 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
297 return E_NOTIMPL;
300 static HRESULT WINAPI
301 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
303 CHECK_EXPECTED_METHOD("Moniker_Inverse");
304 return E_NOTIMPL;
307 static HRESULT WINAPI
308 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
310 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
311 return E_NOTIMPL;
314 static HRESULT WINAPI
315 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
317 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
318 return E_NOTIMPL;
321 static HRESULT WINAPI
322 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
323 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
325 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
326 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
327 *ppszDisplayName = (LPOLESTR)CoTaskMemAlloc(sizeof(wszDisplayName));
328 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
329 return S_OK;
332 static HRESULT WINAPI
333 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
334 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
336 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
337 return E_NOTIMPL;
340 static HRESULT WINAPI
341 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
343 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
345 if (!pwdMksys)
346 return E_POINTER;
348 (*pwdMksys)=MKSYS_NONE;
350 return S_FALSE;
353 static const IMonikerVtbl MonikerNoROTDataVtbl =
355 MonikerNoROTData_QueryInterface,
356 Moniker_AddRef,
357 Moniker_Release,
358 Moniker_GetClassID,
359 Moniker_IsDirty,
360 Moniker_Load,
361 Moniker_Save,
362 Moniker_GetSizeMax,
363 Moniker_BindToObject,
364 Moniker_BindToStorage,
365 Moniker_Reduce,
366 Moniker_ComposeWith,
367 Moniker_Enum,
368 Moniker_IsEqual,
369 Moniker_Hash,
370 Moniker_IsRunning,
371 Moniker_GetTimeOfLastChange,
372 Moniker_Inverse,
373 Moniker_CommonPrefixWith,
374 Moniker_RelativePathTo,
375 Moniker_GetDisplayName,
376 Moniker_ParseDisplayName,
377 Moniker_IsSystemMoniker
380 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
382 static IMoniker Moniker;
384 static HRESULT WINAPI
385 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
387 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
390 static ULONG WINAPI
391 ROTData_AddRef(IROTData *iface)
393 return 2;
396 static ULONG WINAPI
397 ROTData_Release(IROTData* iface)
399 return 1;
402 static HRESULT WINAPI
403 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
404 ULONG cbMax, ULONG* pcbData)
406 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
408 *pcbData = 1;
409 if (cbMax < *pcbData)
410 return E_OUTOFMEMORY;
412 *pbData = 0xde;
414 return S_OK;
417 static IROTDataVtbl ROTDataVtbl =
419 ROTData_QueryInterface,
420 ROTData_AddRef,
421 ROTData_Release,
422 ROTData_GetComparisonData
425 static IROTData ROTData = { &ROTDataVtbl };
427 static HRESULT WINAPI
428 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
430 if (!ppvObject)
431 return E_INVALIDARG;
433 *ppvObject = 0;
435 if (IsEqualIID(&IID_IUnknown, riid) ||
436 IsEqualIID(&IID_IPersist, riid) ||
437 IsEqualIID(&IID_IPersistStream,riid) ||
438 IsEqualIID(&IID_IMoniker, riid))
439 *ppvObject = iface;
440 if (IsEqualIID(&IID_IROTData, riid))
442 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
443 *ppvObject = &ROTData;
446 if ((*ppvObject)==0)
447 return E_NOINTERFACE;
449 IMoniker_AddRef(iface);
451 return S_OK;
454 static const IMonikerVtbl MonikerVtbl =
456 Moniker_QueryInterface,
457 Moniker_AddRef,
458 Moniker_Release,
459 Moniker_GetClassID,
460 Moniker_IsDirty,
461 Moniker_Load,
462 Moniker_Save,
463 Moniker_GetSizeMax,
464 Moniker_BindToObject,
465 Moniker_BindToStorage,
466 Moniker_Reduce,
467 Moniker_ComposeWith,
468 Moniker_Enum,
469 Moniker_IsEqual,
470 Moniker_Hash,
471 Moniker_IsRunning,
472 Moniker_GetTimeOfLastChange,
473 Moniker_Inverse,
474 Moniker_CommonPrefixWith,
475 Moniker_RelativePathTo,
476 Moniker_GetDisplayName,
477 Moniker_ParseDisplayName,
478 Moniker_IsSystemMoniker
481 static IMoniker Moniker = { &MonikerVtbl };
483 static void test_ROT(void)
485 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
486 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
487 '2','0','4','6','E','5','8','6','C','9','2','5',0};
488 HRESULT hr;
489 IMoniker *pMoniker = NULL;
490 IRunningObjectTable *pROT = NULL;
491 DWORD dwCookie;
492 static const char *methods_register_no_ROTData[] =
494 "Moniker_Reduce",
495 "Moniker_GetTimeOfLastChange",
496 "Moniker_QueryInterface(IID_IROTData)",
497 "Moniker_GetDisplayName",
498 "Moniker_GetClassID",
499 NULL
501 static const char *methods_register[] =
503 "Moniker_Reduce",
504 "Moniker_GetTimeOfLastChange",
505 "Moniker_QueryInterface(IID_IROTData)",
506 "ROTData_GetComparisonData",
507 NULL
509 static const char *methods_isrunning_no_ROTData[] =
511 "Moniker_Reduce",
512 "Moniker_QueryInterface(IID_IROTData)",
513 "Moniker_GetDisplayName",
514 "Moniker_GetClassID",
515 NULL
517 static const char *methods_isrunning[] =
519 "Moniker_Reduce",
520 "Moniker_QueryInterface(IID_IROTData)",
521 "ROTData_GetComparisonData",
522 NULL
525 cLocks = 0;
527 hr = GetRunningObjectTable(0, &pROT);
528 ok_ole_success(hr, GetRunningObjectTable);
530 expected_method_list = methods_register_no_ROTData;
531 /* try with our own moniker that doesn't support IROTData */
532 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
533 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
534 todo_wine { /* only fails because of lack of IMoniker marshaling */
535 ok_ole_success(hr, IRunningObjectTable_Register);
537 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
539 todo_wine { /* only fails because of lack of IMoniker marshaling */
540 ok_more_than_one_lock();
543 expected_method_list = methods_isrunning_no_ROTData;
544 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
545 todo_wine { /* only fails because of lack of IMoniker marshaling */
546 ok_ole_success(hr, IRunningObjectTable_IsRunning);
548 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
550 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
551 todo_wine { /* only fails because of lack of IMoniker marshaling */
552 ok_ole_success(hr, IRunningObjectTable_Revoke);
555 ok_no_locks();
557 expected_method_list = methods_register;
558 /* try with our own moniker */
559 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
560 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
561 todo_wine { /* only fails because of lack of IMoniker marshaling */
562 ok_ole_success(hr, IRunningObjectTable_Register);
564 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
566 todo_wine { /* only fails because of lack of IMoniker marshaling */
567 ok_more_than_one_lock();
570 expected_method_list = methods_isrunning;
571 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
572 todo_wine { /* only fails because of lack of IMoniker marshaling */
573 ok_ole_success(hr, IRunningObjectTable_IsRunning);
575 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
577 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
578 todo_wine { /* only fails because of lack of IMoniker marshaling */
579 ok_ole_success(hr, IRunningObjectTable_Revoke);
582 ok_no_locks();
584 hr = CreateFileMoniker(wszFileName, &pMoniker);
585 ok_ole_success(hr, CreateClassMoniker);
587 /* test flags: 0 */
588 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
589 pMoniker, &dwCookie);
590 ok_ole_success(hr, IRunningObjectTable_Register);
592 ok_more_than_one_lock();
594 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
595 ok_ole_success(hr, IRunningObjectTable_Revoke);
597 ok_no_locks();
599 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
600 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
601 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
602 ok_ole_success(hr, IRunningObjectTable_Register);
604 ok_more_than_one_lock();
606 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
607 ok_ole_success(hr, IRunningObjectTable_Revoke);
609 ok_no_locks();
611 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
612 /* only succeeds when process is started by SCM and has LocalService
613 * or RunAs AppId values */
614 hr = IRunningObjectTable_Register(pROT,
615 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
616 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
617 todo_wine {
618 ok(hr == CO_E_WRONG_SERVER_IDENTITY, "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
621 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
622 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
623 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
625 IMoniker_Release(pMoniker);
627 IRunningObjectTable_Release(pROT);
630 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
632 IMoniker * spMoniker;
633 int monCnt=0, matchCnt=0;
635 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
637 HRESULT hr;
638 WCHAR * szDisplayn;
639 monCnt++;
640 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
641 if (SUCCEEDED(hr))
643 if (!lstrcmpW(szDisplayn, wszFileName1) || !lstrcmpW(szDisplayn, wszFileName2))
644 matchCnt++;
645 CoTaskMemFree(szDisplayn);
648 trace("Total number of monikers is %i\n", monCnt);
649 return matchCnt;
652 static void test_MkParseDisplayName(void)
654 IBindCtx * pbc = NULL;
655 HRESULT hr;
656 IMoniker * pmk = NULL;
657 IMoniker * pmk1 = NULL;
658 IMoniker * pmk2 = NULL;
659 ULONG eaten;
660 int matchCnt;
661 IUnknown * object = NULL;
663 IUnknown *lpEM1;
665 IEnumMoniker *spEM1 = NULL;
666 IEnumMoniker *spEM2 = NULL;
667 IEnumMoniker *spEM3 = NULL;
669 DWORD pdwReg1=0;
670 DWORD grflags=0;
671 DWORD pdwReg2=0;
672 IRunningObjectTable * pprot=NULL;
674 /* CLSID of My Computer */
675 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
676 '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};
678 hr = CreateBindCtx(0, &pbc);
679 ok_ole_success(hr, CreateBindCtx);
681 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
682 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
684 if (object)
686 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
687 ok_ole_success(hr, IMoniker_BindToObject);
689 IUnknown_Release(object);
691 IBindCtx_Release(pbc);
693 /* Test the EnumMoniker interface */
694 hr = CreateBindCtx(0, &pbc);
695 ok_ole_success(hr, CreateBindCtx);
697 hr = CreateFileMoniker(wszFileName1, &pmk1);
698 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
699 hr = CreateFileMoniker(wszFileName2, &pmk2);
700 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
701 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
702 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
704 /* Check EnumMoniker before registering */
705 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
706 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
707 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
708 /* Register a couple of Monikers and check is ok */
709 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
710 hr = MK_E_NOOBJECT;
712 matchCnt = count_moniker_matches(pbc, spEM1);
713 trace("Number of matches is %i\n", matchCnt);
715 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
716 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
717 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
718 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
720 trace("IROT::Register\n");
721 grflags=0;
722 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
723 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
724 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
725 pprot, grflags, lpEM1, pmk2, pdwReg2);
727 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
728 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
730 matchCnt = count_moniker_matches(pbc, spEM2);
731 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
733 trace("IEnumMoniker::Clone\n");
734 IEnumMoniker_Clone(spEM2, &spEM3);
736 matchCnt = count_moniker_matches(pbc, spEM3);
737 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
738 trace("IEnumMoniker::Reset\n");
739 IEnumMoniker_Reset(spEM3);
741 matchCnt = count_moniker_matches(pbc, spEM3);
742 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
744 IRunningObjectTable_Revoke(pprot,pdwReg1);
745 IRunningObjectTable_Revoke(pprot,pdwReg2);
746 IEnumMoniker_Release(spEM1);
747 IEnumMoniker_Release(spEM1);
748 IEnumMoniker_Release(spEM2);
749 IEnumMoniker_Release(spEM3);
750 IMoniker_Release(pmk1);
751 IMoniker_Release(pmk2);
752 IRunningObjectTable_Release(pprot);
754 IBindCtx_Release(pbc);
757 static const LARGE_INTEGER llZero;
759 static const BYTE expected_class_moniker_marshal_data[] =
761 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
762 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
763 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
764 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
765 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
766 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
767 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
768 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
769 0x00,0x00,0x00,0x00,
772 static const BYTE expected_class_moniker_saved_data[] =
774 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
775 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
776 0x00,0x00,0x00,0x00,
779 static const BYTE expected_class_moniker_comparison_data[] =
781 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
782 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
783 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
784 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
787 static const WCHAR expected_class_moniker_display_name[] =
789 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
790 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
791 '0','0','0','0','4','6',':',0
794 static const BYTE expected_item_moniker_comparison_data[] =
796 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
797 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
798 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
799 0x54,0x00,0x00,0x00,
802 static const BYTE expected_item_moniker_saved_data[] =
804 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
805 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
808 static const BYTE expected_item_moniker_marshal_data[] =
810 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
811 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
812 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
813 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
814 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
815 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
816 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
817 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
820 static const BYTE expected_anti_moniker_marshal_data[] =
822 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
823 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
824 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
825 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
826 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
827 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
828 0x01,0x00,0x00,0x00,
831 static const BYTE expected_anti_moniker_saved_data[] =
833 0x01,0x00,0x00,0x00,
836 static const BYTE expected_anti_moniker_comparison_data[] =
838 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
839 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
840 0x01,0x00,0x00,0x00,
843 static const BYTE expected_gc_moniker_marshal_data[] =
845 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
846 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
847 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
848 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
849 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
850 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
851 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
852 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
853 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
854 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
855 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
856 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
857 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
858 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
859 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
860 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
861 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
862 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
863 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
864 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
865 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
866 0x00,0x57,0x69,0x6e,0x65,0x00,
869 static const BYTE expected_gc_moniker_saved_data[] =
871 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
872 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
873 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
874 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
875 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
876 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
877 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
878 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
879 0x65,0x00,
882 static const BYTE expected_gc_moniker_comparison_data[] =
884 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
885 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
886 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
887 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
888 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
889 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
890 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
891 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
892 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
895 static void test_moniker(
896 const char *testname, IMoniker *moniker,
897 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
898 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
899 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
900 LPCWSTR expected_display_name)
902 IStream * stream;
903 IROTData * rotdata;
904 HRESULT hr;
905 HGLOBAL hglobal;
906 LPBYTE moniker_data;
907 DWORD moniker_size;
908 DWORD i;
909 BOOL same = TRUE;
910 BYTE buffer[128];
911 IMoniker * moniker_proxy;
912 LPOLESTR display_name;
913 IBindCtx *bindctx;
915 hr = IMoniker_IsDirty(moniker);
916 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
918 /* Display Name */
920 hr = CreateBindCtx(0, &bindctx);
921 ok_ole_success(hr, CreateBindCtx);
923 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
924 ok_ole_success(hr, IMoniker_GetDisplayName);
925 ok(!lstrcmpW(display_name, expected_display_name), "display name wasn't what was expected\n");
927 CoTaskMemFree(display_name);
928 IBindCtx_Release(bindctx);
930 hr = IMoniker_IsDirty(moniker);
931 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
933 /* IROTData::GetComparisonData test */
935 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
936 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
938 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
939 ok_ole_success(hr, IROTData_GetComparisonData);
941 if (hr != S_OK) moniker_size = 0;
943 /* first check we have the right amount of data */
944 ok(moniker_size == sizeof_expected_moniker_comparison_data,
945 "%s: Size of comparison data differs (expected %d, actual %d)\n",
946 testname, sizeof_expected_moniker_comparison_data, moniker_size);
948 /* then do a byte-by-byte comparison */
949 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
951 if (expected_moniker_comparison_data[i] != buffer[i])
953 same = FALSE;
954 break;
958 ok(same, "%s: Comparison data differs\n", testname);
959 if (!same)
961 for (i = 0; i < moniker_size; i++)
963 if (i % 8 == 0) printf(" ");
964 printf("0x%02x,", buffer[i]);
965 if (i % 8 == 7) printf("\n");
967 printf("\n");
970 IROTData_Release(rotdata);
972 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
974 /* Saving */
976 hr = IMoniker_Save(moniker, stream, TRUE);
977 ok_ole_success(hr, IMoniker_Save);
979 hr = GetHGlobalFromStream(stream, &hglobal);
980 ok_ole_success(hr, GetHGlobalFromStream);
982 moniker_size = GlobalSize(hglobal);
984 moniker_data = GlobalLock(hglobal);
986 /* first check we have the right amount of data */
987 ok(moniker_size == sizeof_expected_moniker_saved_data,
988 "%s: Size of saved data differs (expected %d, actual %d)\n",
989 testname, sizeof_expected_moniker_saved_data, moniker_size);
991 /* then do a byte-by-byte comparison */
992 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
994 if (expected_moniker_saved_data[i] != moniker_data[i])
996 same = FALSE;
997 break;
1001 ok(same, "%s: Saved data differs\n", testname);
1002 if (!same)
1004 for (i = 0; i < moniker_size; i++)
1006 if (i % 8 == 0) printf(" ");
1007 printf("0x%02x,", moniker_data[i]);
1008 if (i % 8 == 7) printf("\n");
1010 printf("\n");
1013 GlobalUnlock(hglobal);
1015 IStream_Release(stream);
1017 /* Marshaling tests */
1019 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1020 ok_ole_success(hr, CreateStreamOnHGlobal);
1022 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1023 ok_ole_success(hr, CoMarshalInterface);
1025 hr = GetHGlobalFromStream(stream, &hglobal);
1026 ok_ole_success(hr, GetHGlobalFromStream);
1028 moniker_size = GlobalSize(hglobal);
1030 moniker_data = GlobalLock(hglobal);
1032 /* first check we have the right amount of data */
1033 ok(moniker_size == sizeof_expected_moniker_marshal_data,
1034 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1035 testname, sizeof_expected_moniker_marshal_data, moniker_size);
1037 /* then do a byte-by-byte comparison */
1038 if (expected_moniker_marshal_data)
1040 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1042 if (expected_moniker_marshal_data[i] != moniker_data[i])
1044 same = FALSE;
1045 break;
1050 ok(same, "%s: Marshaled data differs\n", testname);
1051 if (!same)
1053 for (i = 0; i < moniker_size; i++)
1055 if (i % 8 == 0) printf(" ");
1056 printf("0x%02x,", moniker_data[i]);
1057 if (i % 8 == 7) printf("\n");
1059 printf("\n");
1062 GlobalUnlock(hglobal);
1064 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1065 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1066 ok_ole_success(hr, CoUnmarshalInterface);
1068 IStream_Release(stream);
1069 IMoniker_Release(moniker_proxy);
1072 static void test_class_moniker(void)
1074 HRESULT hr;
1075 IMoniker *moniker;
1076 DWORD moniker_type;
1077 DWORD hash;
1078 IBindCtx *bindctx;
1079 IMoniker *inverse;
1080 IUnknown *unknown;
1081 FILETIME filetime;
1083 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1084 ok_ole_success(hr, CreateClassMoniker);
1085 if (!moniker) return;
1087 test_moniker("class moniker", moniker,
1088 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1089 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1090 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1091 expected_class_moniker_display_name);
1093 /* Hashing */
1095 hr = IMoniker_Hash(moniker, &hash);
1096 ok_ole_success(hr, IMoniker_Hash);
1098 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1099 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1100 hash);
1102 /* IsSystemMoniker test */
1104 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1105 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1107 ok(moniker_type == MKSYS_CLASSMONIKER,
1108 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1109 moniker_type);
1111 hr = CreateBindCtx(0, &bindctx);
1112 ok_ole_success(hr, CreateBindCtx);
1114 /* IsRunning test */
1115 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1116 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1118 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1119 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1121 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1122 ok_ole_success(hr, IMoniker_BindToStorage);
1123 IUnknown_Release(unknown);
1125 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1126 ok_ole_success(hr, IMoniker_BindToStorage);
1127 IUnknown_Release(unknown);
1129 IBindCtx_Release(bindctx);
1131 hr = IMoniker_Inverse(moniker, &inverse);
1132 ok_ole_success(hr, IMoniker_Inverse);
1133 IMoniker_Release(inverse);
1135 IMoniker_Release(moniker);
1138 static void test_file_moniker(WCHAR* path)
1140 IStream *stream;
1141 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1142 HRESULT hr;
1144 hr = CreateFileMoniker(path, &moniker1);
1145 ok_ole_success(hr, CreateFileMoniker);
1147 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1149 /* Marshal */
1150 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1151 ok_ole_success(hr, CoMarshalInterface);
1153 /* Rewind */
1154 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1155 ok_ole_success(hr, IStream_Seek);
1157 /* Unmarshal */
1158 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1159 ok_ole_success(hr, CoUnmarshalInterface);
1161 hr = IMoniker_IsEqual(moniker1, moniker2);
1162 ok_ole_success(hr, IsEqual);
1164 IStream_Release(stream);
1165 if (moniker1)
1166 IMoniker_Release(moniker1);
1167 if (moniker2)
1168 IMoniker_Release(moniker2);
1171 static void test_file_monikers(void)
1173 static WCHAR wszFile[][30] = {
1174 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1175 {'\\', '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},
1176 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1177 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1178 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1179 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1180 * U+0100 .. = Latin extended-A
1182 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1185 int i;
1187 trace("ACP is %u\n", GetACP());
1189 for (i = 0; i < COUNTOF(wszFile); ++i)
1191 int j ;
1192 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1194 wszFile[i][j] = 0;
1195 test_file_moniker(wszFile[i]);
1200 static void test_item_moniker(void)
1202 HRESULT hr;
1203 IMoniker *moniker;
1204 DWORD moniker_type;
1205 DWORD hash;
1206 IBindCtx *bindctx;
1207 IMoniker *inverse;
1208 IUnknown *unknown;
1209 static const WCHAR wszDelimeter[] = {'!',0};
1210 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1211 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1213 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1214 ok_ole_success(hr, CreateItemMoniker);
1216 test_moniker("item moniker", moniker,
1217 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1218 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1219 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1220 expected_display_name);
1222 /* Hashing */
1224 hr = IMoniker_Hash(moniker, &hash);
1225 ok_ole_success(hr, IMoniker_Hash);
1227 ok(hash == 0x73c,
1228 "Hash value != 0x73c, instead was 0x%08x\n",
1229 hash);
1231 /* IsSystemMoniker test */
1233 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1234 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1236 ok(moniker_type == MKSYS_ITEMMONIKER,
1237 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1238 moniker_type);
1240 hr = CreateBindCtx(0, &bindctx);
1241 ok_ole_success(hr, CreateBindCtx);
1243 /* IsRunning test */
1244 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1245 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1247 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1248 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1250 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1251 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1253 IBindCtx_Release(bindctx);
1255 hr = IMoniker_Inverse(moniker, &inverse);
1256 ok_ole_success(hr, IMoniker_Inverse);
1257 IMoniker_Release(inverse);
1259 IMoniker_Release(moniker);
1262 static void test_anti_moniker(void)
1264 HRESULT hr;
1265 IMoniker *moniker;
1266 DWORD moniker_type;
1267 DWORD hash;
1268 IBindCtx *bindctx;
1269 FILETIME filetime;
1270 IMoniker *inverse;
1271 IUnknown *unknown;
1272 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1274 hr = CreateAntiMoniker(&moniker);
1275 ok_ole_success(hr, CreateAntiMoniker);
1276 if (!moniker) return;
1278 test_moniker("anti moniker", moniker,
1279 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1280 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1281 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1282 expected_display_name);
1284 /* Hashing */
1285 hr = IMoniker_Hash(moniker, &hash);
1286 ok_ole_success(hr, IMoniker_Hash);
1287 ok(hash == 0x80000001,
1288 "Hash value != 0x80000001, instead was 0x%08x\n",
1289 hash);
1291 /* IsSystemMoniker test */
1292 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1293 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1294 ok(moniker_type == MKSYS_ANTIMONIKER,
1295 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1296 moniker_type);
1298 hr = IMoniker_Inverse(moniker, &inverse);
1299 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1300 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1302 hr = CreateBindCtx(0, &bindctx);
1303 ok_ole_success(hr, CreateBindCtx);
1305 /* IsRunning test */
1306 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1307 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1309 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1310 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1312 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1313 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1315 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1316 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1318 IBindCtx_Release(bindctx);
1320 IMoniker_Release(moniker);
1323 static void test_generic_composite_moniker(void)
1325 HRESULT hr;
1326 IMoniker *moniker;
1327 IMoniker *moniker1;
1328 IMoniker *moniker2;
1329 DWORD moniker_type;
1330 DWORD hash;
1331 IBindCtx *bindctx;
1332 FILETIME filetime;
1333 IMoniker *inverse;
1334 IUnknown *unknown;
1335 static const WCHAR wszDelimeter1[] = {'!',0};
1336 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1337 static const WCHAR wszDelimeter2[] = {'#',0};
1338 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1339 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1341 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1342 ok_ole_success(hr, CreateItemMoniker);
1343 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1344 ok_ole_success(hr, CreateItemMoniker);
1345 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1346 ok_ole_success(hr, CreateGenericComposite);
1348 test_moniker("generic composite moniker", moniker,
1349 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1350 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1351 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1352 expected_display_name);
1354 /* Hashing */
1356 hr = IMoniker_Hash(moniker, &hash);
1357 ok_ole_success(hr, IMoniker_Hash);
1359 ok(hash == 0xd87,
1360 "Hash value != 0xd87, instead was 0x%08x\n",
1361 hash);
1363 /* IsSystemMoniker test */
1365 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1366 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1368 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1369 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1370 moniker_type);
1372 hr = CreateBindCtx(0, &bindctx);
1373 ok_ole_success(hr, CreateBindCtx);
1375 /* IsRunning test */
1376 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1377 todo_wine
1378 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1380 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1381 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1383 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1384 todo_wine
1385 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1387 todo_wine
1388 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1389 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1391 IBindCtx_Release(bindctx);
1393 hr = IMoniker_Inverse(moniker, &inverse);
1394 ok_ole_success(hr, IMoniker_Inverse);
1395 IMoniker_Release(inverse);
1397 IMoniker_Release(moniker);
1400 START_TEST(moniker)
1402 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1404 test_ROT();
1405 test_MkParseDisplayName();
1406 test_class_moniker();
1407 test_file_monikers();
1408 test_item_moniker();
1409 test_anti_moniker();
1410 test_generic_composite_moniker();
1412 /* FIXME: test moniker creation funcs and parsing other moniker formats */
1414 CoUninitialize();