push 5b1efc32b5a8acb1d5b5e60584746392dd0c436e
[wine/hacks.git] / dlls / ole32 / tests / moniker.c
blob7cc5f78c2dbcb60e716ce35b76b7b94f26e31483
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 "initguid.h"
32 #include "comcat.h"
33 #include "olectl.h"
35 #include "wine/test.h"
37 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
38 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
39 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
40 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
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_WineTest =
59 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
60 0x9474ba1a,
61 0x258b,
62 0x490b,
63 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
66 static const CLSID CLSID_TestMoniker =
67 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
68 0xb306bfbc,
69 0x496e,
70 0x4f53,
71 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
74 static LONG cLocks;
76 static void LockModule(void)
78 InterlockedIncrement(&cLocks);
81 static void UnlockModule(void)
83 InterlockedDecrement(&cLocks);
86 static SIZE_T round_global_size(SIZE_T size)
88 static SIZE_T global_size_alignment = -1;
89 if (global_size_alignment == -1)
91 void *p = GlobalAlloc(GMEM_FIXED, 1);
92 global_size_alignment = GlobalSize(p);
93 GlobalFree(p);
96 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
99 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
100 LPCLASSFACTORY iface,
101 REFIID riid,
102 LPVOID *ppvObj)
104 if (ppvObj == NULL) return E_POINTER;
106 if (IsEqualGUID(riid, &IID_IUnknown) ||
107 IsEqualGUID(riid, &IID_IClassFactory))
109 *ppvObj = iface;
110 IClassFactory_AddRef(iface);
111 return S_OK;
114 *ppvObj = NULL;
115 return E_NOINTERFACE;
118 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
120 LockModule();
121 return 2; /* non-heap-based object */
124 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
126 UnlockModule();
127 return 1; /* non-heap-based object */
130 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
131 LPCLASSFACTORY iface,
132 LPUNKNOWN pUnkOuter,
133 REFIID riid,
134 LPVOID *ppvObj)
136 return E_NOTIMPL;
139 static HRESULT WINAPI Test_IClassFactory_LockServer(
140 LPCLASSFACTORY iface,
141 BOOL fLock)
143 return S_OK;
146 static const IClassFactoryVtbl TestClassFactory_Vtbl =
148 Test_IClassFactory_QueryInterface,
149 Test_IClassFactory_AddRef,
150 Test_IClassFactory_Release,
151 Test_IClassFactory_CreateInstance,
152 Test_IClassFactory_LockServer
155 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
157 typedef struct
159 const IUnknownVtbl *lpVtbl;
160 ULONG refs;
161 } HeapUnknown;
163 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
165 if (IsEqualIID(riid, &IID_IUnknown))
167 IUnknown_AddRef(iface);
168 *ppv = iface;
169 return S_OK;
171 *ppv = NULL;
172 return E_NOINTERFACE;
175 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
177 HeapUnknown *This = (HeapUnknown *)iface;
178 return InterlockedIncrement((LONG*)&This->refs);
181 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
183 HeapUnknown *This = (HeapUnknown *)iface;
184 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
185 if (!refs) HeapFree(GetProcessHeap(), 0, This);
186 return refs;
189 static const IUnknownVtbl HeapUnknown_Vtbl =
191 HeapUnknown_QueryInterface,
192 HeapUnknown_AddRef,
193 HeapUnknown_Release
196 static HRESULT WINAPI
197 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
199 if (!ppvObject)
200 return E_INVALIDARG;
202 *ppvObject = 0;
204 if (IsEqualIID(&IID_IUnknown, riid) ||
205 IsEqualIID(&IID_IPersist, riid) ||
206 IsEqualIID(&IID_IPersistStream,riid) ||
207 IsEqualIID(&IID_IMoniker, riid))
208 *ppvObject = iface;
209 if (IsEqualIID(&IID_IROTData, riid))
210 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
212 if ((*ppvObject)==0)
213 return E_NOINTERFACE;
215 IMoniker_AddRef(iface);
217 return S_OK;
220 static ULONG WINAPI
221 Moniker_AddRef(IMoniker* iface)
223 return 2;
226 static ULONG WINAPI
227 Moniker_Release(IMoniker* iface)
229 return 1;
232 static HRESULT WINAPI
233 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
235 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
237 *pClassID = CLSID_TestMoniker;
239 return S_OK;
242 static HRESULT WINAPI
243 Moniker_IsDirty(IMoniker* iface)
245 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
247 return S_FALSE;
250 static HRESULT WINAPI
251 Moniker_Load(IMoniker* iface, IStream* pStm)
253 CHECK_EXPECTED_METHOD("Moniker_Load");
254 return E_NOTIMPL;
257 static HRESULT WINAPI
258 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
260 CHECK_EXPECTED_METHOD("Moniker_Save");
261 return E_NOTIMPL;
264 static HRESULT WINAPI
265 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
267 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
268 return E_NOTIMPL;
271 static HRESULT WINAPI
272 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
273 REFIID riid, VOID** ppvResult)
275 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
276 return E_NOTIMPL;
279 static HRESULT WINAPI
280 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
281 REFIID riid, VOID** ppvObject)
283 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
284 return E_NOTIMPL;
287 static HRESULT WINAPI
288 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
289 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
291 CHECK_EXPECTED_METHOD("Moniker_Reduce");
293 if (ppmkReduced==NULL)
294 return E_POINTER;
296 IMoniker_AddRef(iface);
298 *ppmkReduced=iface;
300 return MK_S_REDUCED_TO_SELF;
303 static HRESULT WINAPI
304 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
305 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
307 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
308 return E_NOTIMPL;
311 static HRESULT WINAPI
312 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
314 CHECK_EXPECTED_METHOD("Moniker_Enum");
316 if (ppenumMoniker == NULL)
317 return E_POINTER;
319 *ppenumMoniker = NULL;
321 return S_OK;
324 static HRESULT WINAPI
325 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
327 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
328 return E_NOTIMPL;
331 static HRESULT WINAPI
332 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
334 CHECK_EXPECTED_METHOD("Moniker_Hash");
335 return E_NOTIMPL;
338 static HRESULT WINAPI
339 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
340 IMoniker* pmkNewlyRunning)
342 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
343 return E_NOTIMPL;
346 static HRESULT WINAPI
347 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
348 IMoniker* pmkToLeft, FILETIME* pFileTime)
350 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
351 return E_NOTIMPL;
354 static HRESULT WINAPI
355 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
357 CHECK_EXPECTED_METHOD("Moniker_Inverse");
358 return E_NOTIMPL;
361 static HRESULT WINAPI
362 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
364 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
365 return E_NOTIMPL;
368 static HRESULT WINAPI
369 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
371 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
372 return E_NOTIMPL;
375 static HRESULT WINAPI
376 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
377 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
379 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
380 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
381 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
382 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
383 return S_OK;
386 static HRESULT WINAPI
387 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
388 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
390 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
391 return E_NOTIMPL;
394 static HRESULT WINAPI
395 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
397 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
399 if (!pwdMksys)
400 return E_POINTER;
402 (*pwdMksys)=MKSYS_NONE;
404 return S_FALSE;
407 static const IMonikerVtbl MonikerNoROTDataVtbl =
409 MonikerNoROTData_QueryInterface,
410 Moniker_AddRef,
411 Moniker_Release,
412 Moniker_GetClassID,
413 Moniker_IsDirty,
414 Moniker_Load,
415 Moniker_Save,
416 Moniker_GetSizeMax,
417 Moniker_BindToObject,
418 Moniker_BindToStorage,
419 Moniker_Reduce,
420 Moniker_ComposeWith,
421 Moniker_Enum,
422 Moniker_IsEqual,
423 Moniker_Hash,
424 Moniker_IsRunning,
425 Moniker_GetTimeOfLastChange,
426 Moniker_Inverse,
427 Moniker_CommonPrefixWith,
428 Moniker_RelativePathTo,
429 Moniker_GetDisplayName,
430 Moniker_ParseDisplayName,
431 Moniker_IsSystemMoniker
434 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
436 static IMoniker Moniker;
438 static HRESULT WINAPI
439 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
441 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
444 static ULONG WINAPI
445 ROTData_AddRef(IROTData *iface)
447 return 2;
450 static ULONG WINAPI
451 ROTData_Release(IROTData* iface)
453 return 1;
456 static HRESULT WINAPI
457 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
458 ULONG cbMax, ULONG* pcbData)
460 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
462 *pcbData = 1;
463 if (cbMax < *pcbData)
464 return E_OUTOFMEMORY;
466 *pbData = 0xde;
468 return S_OK;
471 static IROTDataVtbl ROTDataVtbl =
473 ROTData_QueryInterface,
474 ROTData_AddRef,
475 ROTData_Release,
476 ROTData_GetComparisonData
479 static IROTData ROTData = { &ROTDataVtbl };
481 static HRESULT WINAPI
482 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
484 if (!ppvObject)
485 return E_INVALIDARG;
487 *ppvObject = 0;
489 if (IsEqualIID(&IID_IUnknown, riid) ||
490 IsEqualIID(&IID_IPersist, riid) ||
491 IsEqualIID(&IID_IPersistStream,riid) ||
492 IsEqualIID(&IID_IMoniker, riid))
493 *ppvObject = iface;
494 if (IsEqualIID(&IID_IROTData, riid))
496 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
497 *ppvObject = &ROTData;
500 if ((*ppvObject)==0)
501 return E_NOINTERFACE;
503 IMoniker_AddRef(iface);
505 return S_OK;
508 static const IMonikerVtbl MonikerVtbl =
510 Moniker_QueryInterface,
511 Moniker_AddRef,
512 Moniker_Release,
513 Moniker_GetClassID,
514 Moniker_IsDirty,
515 Moniker_Load,
516 Moniker_Save,
517 Moniker_GetSizeMax,
518 Moniker_BindToObject,
519 Moniker_BindToStorage,
520 Moniker_Reduce,
521 Moniker_ComposeWith,
522 Moniker_Enum,
523 Moniker_IsEqual,
524 Moniker_Hash,
525 Moniker_IsRunning,
526 Moniker_GetTimeOfLastChange,
527 Moniker_Inverse,
528 Moniker_CommonPrefixWith,
529 Moniker_RelativePathTo,
530 Moniker_GetDisplayName,
531 Moniker_ParseDisplayName,
532 Moniker_IsSystemMoniker
535 static IMoniker Moniker = { &MonikerVtbl };
537 static void test_ROT(void)
539 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
540 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
541 '2','0','4','6','E','5','8','6','C','9','2','5',0};
542 HRESULT hr;
543 IMoniker *pMoniker = NULL;
544 IRunningObjectTable *pROT = NULL;
545 DWORD dwCookie;
546 static const char *methods_register_no_ROTData[] =
548 "Moniker_Reduce",
549 "Moniker_GetTimeOfLastChange",
550 "Moniker_QueryInterface(IID_IROTData)",
551 "Moniker_GetDisplayName",
552 "Moniker_GetClassID",
553 NULL
555 static const char *methods_register[] =
557 "Moniker_Reduce",
558 "Moniker_GetTimeOfLastChange",
559 "Moniker_QueryInterface(IID_IROTData)",
560 "ROTData_GetComparisonData",
561 NULL
563 static const char *methods_isrunning_no_ROTData[] =
565 "Moniker_Reduce",
566 "Moniker_QueryInterface(IID_IROTData)",
567 "Moniker_GetDisplayName",
568 "Moniker_GetClassID",
569 NULL
571 static const char *methods_isrunning[] =
573 "Moniker_Reduce",
574 "Moniker_QueryInterface(IID_IROTData)",
575 "ROTData_GetComparisonData",
576 NULL
579 cLocks = 0;
581 hr = GetRunningObjectTable(0, &pROT);
582 ok_ole_success(hr, GetRunningObjectTable);
584 expected_method_list = methods_register_no_ROTData;
585 /* try with our own moniker that doesn't support IROTData */
586 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
587 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
588 ok_ole_success(hr, IRunningObjectTable_Register);
589 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
591 ok_more_than_one_lock();
593 expected_method_list = methods_isrunning_no_ROTData;
594 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
595 ok_ole_success(hr, IRunningObjectTable_IsRunning);
596 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
598 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
599 ok_ole_success(hr, IRunningObjectTable_Revoke);
601 ok_no_locks();
603 expected_method_list = methods_register;
604 /* try with our own moniker */
605 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
606 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
607 ok_ole_success(hr, IRunningObjectTable_Register);
608 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
610 ok_more_than_one_lock();
612 expected_method_list = methods_isrunning;
613 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
614 ok_ole_success(hr, IRunningObjectTable_IsRunning);
615 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
617 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
618 ok_ole_success(hr, IRunningObjectTable_Revoke);
620 ok_no_locks();
622 hr = CreateFileMoniker(wszFileName, &pMoniker);
623 ok_ole_success(hr, CreateClassMoniker);
625 /* test flags: 0 */
626 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
627 pMoniker, &dwCookie);
628 ok_ole_success(hr, IRunningObjectTable_Register);
630 ok_more_than_one_lock();
632 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
633 ok_ole_success(hr, IRunningObjectTable_Revoke);
635 ok_no_locks();
637 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
638 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
639 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
640 ok_ole_success(hr, IRunningObjectTable_Register);
642 ok_more_than_one_lock();
644 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
645 ok_ole_success(hr, IRunningObjectTable_Revoke);
647 ok_no_locks();
649 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
650 /* only succeeds when process is started by SCM and has LocalService
651 * or RunAs AppId values */
652 hr = IRunningObjectTable_Register(pROT,
653 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
654 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
655 todo_wine {
656 ok(hr == CO_E_WRONG_SERVER_IDENTITY ||
657 broken(hr == S_OK) /* Win9x */,
658 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
660 if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie);
662 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
663 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
664 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
666 IMoniker_Release(pMoniker);
668 IRunningObjectTable_Release(pROT);
671 static void test_ROT_multiple_entries(void)
673 HRESULT hr;
674 IMoniker *pMoniker = NULL;
675 IRunningObjectTable *pROT = NULL;
676 DWORD dwCookie1, dwCookie2;
677 IUnknown *pObject = NULL;
678 static const WCHAR moniker_path[] =
679 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
681 hr = GetRunningObjectTable(0, &pROT);
682 ok_ole_success(hr, GetRunningObjectTable);
684 hr = CreateFileMoniker(moniker_path, &pMoniker);
685 ok_ole_success(hr, CreateFileMoniker);
687 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
688 ok_ole_success(hr, IRunningObjectTable_Register);
690 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
691 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
693 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
695 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
696 ok_ole_success(hr, IRunningObjectTable_GetObject);
697 IUnknown_Release(pObject);
699 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
700 ok_ole_success(hr, IRunningObjectTable_Revoke);
702 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
703 ok_ole_success(hr, IRunningObjectTable_GetObject);
704 IUnknown_Release(pObject);
706 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
707 ok_ole_success(hr, IRunningObjectTable_Revoke);
709 IMoniker_Release(pMoniker);
711 IRunningObjectTable_Release(pROT);
714 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
716 if (IsEqualIID(riid, &IID_IUnknown) ||
717 IsEqualIID(riid, &IID_IParseDisplayName))
719 *ppv = iface;
720 IUnknown_AddRef(iface);
721 return S_OK;
723 *ppv = NULL;
724 return E_NOINTERFACE;
727 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
729 return 2;
732 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
734 return 1;
737 static LPCWSTR expected_display_name;
739 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
740 IBindCtx *pbc,
741 LPOLESTR pszDisplayName,
742 ULONG *pchEaten,
743 IMoniker **ppmkOut)
745 char display_nameA[256];
746 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
747 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
748 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
749 *pchEaten = lstrlenW(pszDisplayName);
750 return CreateAntiMoniker(ppmkOut);
753 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
755 ParseDisplayName_QueryInterface,
756 ParseDisplayName_AddRef,
757 ParseDisplayName_Release,
758 ParseDisplayName_ParseDisplayName
761 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
763 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
765 IMoniker * spMoniker;
766 int monCnt=0, matchCnt=0;
768 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
770 HRESULT hr;
771 WCHAR * szDisplayn;
772 monCnt++;
773 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
774 if (SUCCEEDED(hr))
776 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
777 matchCnt++;
778 CoTaskMemFree(szDisplayn);
781 trace("Total number of monikers is %i\n", monCnt);
782 return matchCnt;
785 static void test_MkParseDisplayName(void)
787 IBindCtx * pbc = NULL;
788 HRESULT hr;
789 IMoniker * pmk = NULL;
790 IMoniker * pmk1 = NULL;
791 IMoniker * pmk2 = NULL;
792 ULONG eaten;
793 int matchCnt;
794 IUnknown * object = NULL;
796 IUnknown *lpEM1;
798 IEnumMoniker *spEM1 = NULL;
799 IEnumMoniker *spEM2 = NULL;
800 IEnumMoniker *spEM3 = NULL;
802 DWORD pdwReg1=0;
803 DWORD grflags=0;
804 DWORD pdwReg2=0;
805 DWORD moniker_type;
806 IRunningObjectTable * pprot=NULL;
808 /* CLSID of My Computer */
809 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
810 '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};
811 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
812 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
813 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
814 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
815 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
816 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
817 char szDisplayNameFile[256];
818 WCHAR wszDisplayNameFile[256];
820 hr = CreateBindCtx(0, &pbc);
821 ok_ole_success(hr, CreateBindCtx);
823 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
824 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
825 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
827 /* no special handling of "clsid:" without the string form of the clsid
828 * following */
829 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
830 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
831 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
833 /* shows clsid has higher precedence than a running object */
834 hr = CreateFileMoniker(wszDisplayName, &pmk);
835 ok_ole_success(hr, CreateFileMoniker);
836 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
837 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
838 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
839 ok_ole_success(hr, IRunningObjectTable_Register);
840 IMoniker_Release(pmk);
841 pmk = NULL;
842 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
843 ok_ole_success(hr, MkParseDisplayName);
844 if (pmk)
846 IMoniker_IsSystemMoniker(pmk, &moniker_type);
847 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
848 IMoniker_Release(pmk);
850 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
851 ok_ole_success(hr, IRunningObjectTable_Revoke);
852 IRunningObjectTable_Release(pprot);
854 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
855 ok_ole_success(hr, CreateFileMoniker);
856 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
857 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
858 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
859 ok_ole_success(hr, IRunningObjectTable_Register);
860 IMoniker_Release(pmk);
861 pmk = NULL;
862 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
863 ok_ole_success(hr, MkParseDisplayName);
864 if (pmk)
866 IMoniker_IsSystemMoniker(pmk, &moniker_type);
867 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
868 IMoniker_Release(pmk);
870 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
871 ok_ole_success(hr, IRunningObjectTable_Revoke);
872 IRunningObjectTable_Release(pprot);
874 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
875 ok_ole_success(hr, CoRegisterClassObject);
877 expected_display_name = wszDisplayNameProgId1;
878 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
879 ok_ole_success(hr, MkParseDisplayName);
880 if (pmk)
882 IMoniker_IsSystemMoniker(pmk, &moniker_type);
883 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
884 IMoniker_Release(pmk);
887 expected_display_name = wszDisplayNameProgId2;
888 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
889 ok_ole_success(hr, MkParseDisplayName);
890 if (pmk)
892 IMoniker_IsSystemMoniker(pmk, &moniker_type);
893 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
894 IMoniker_Release(pmk);
897 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
898 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
899 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
901 hr = CoRevokeClassObject(pdwReg1);
902 ok_ole_success(hr, CoRevokeClassObject);
904 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
905 strcat(szDisplayNameFile, "\\kernel32.dll");
906 MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
907 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
908 ok_ole_success(hr, MkParseDisplayName);
909 if (pmk)
911 IMoniker_IsSystemMoniker(pmk, &moniker_type);
912 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
913 IMoniker_Release(pmk);
916 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
917 ok_ole_success(hr, MkParseDisplayName);
919 if (pmk)
921 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
922 ok_ole_success(hr, IMoniker_BindToObject);
924 if (SUCCEEDED(hr))
925 IUnknown_Release(object);
926 IMoniker_Release(pmk);
928 IBindCtx_Release(pbc);
930 /* Test the EnumMoniker interface */
931 hr = CreateBindCtx(0, &pbc);
932 ok_ole_success(hr, CreateBindCtx);
934 hr = CreateFileMoniker(wszFileName1, &pmk1);
935 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
936 hr = CreateFileMoniker(wszFileName2, &pmk2);
937 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
938 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
939 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
941 /* Check EnumMoniker before registering */
942 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
943 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
944 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
945 /* Register a couple of Monikers and check is ok */
946 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
947 hr = MK_E_NOOBJECT;
949 matchCnt = count_moniker_matches(pbc, spEM1);
950 trace("Number of matches is %i\n", matchCnt);
952 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
953 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
954 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
955 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
957 trace("IROT::Register\n");
958 grflags=0;
959 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
960 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
961 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
962 pprot, grflags, lpEM1, pmk2, pdwReg2);
964 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
965 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
967 matchCnt = count_moniker_matches(pbc, spEM2);
968 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
970 trace("IEnumMoniker::Clone\n");
971 IEnumMoniker_Clone(spEM2, &spEM3);
973 matchCnt = count_moniker_matches(pbc, spEM3);
974 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
975 trace("IEnumMoniker::Reset\n");
976 IEnumMoniker_Reset(spEM3);
978 matchCnt = count_moniker_matches(pbc, spEM3);
979 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
981 IRunningObjectTable_Revoke(pprot,pdwReg1);
982 IRunningObjectTable_Revoke(pprot,pdwReg2);
983 IUnknown_Release(lpEM1);
984 IEnumMoniker_Release(spEM1);
985 IEnumMoniker_Release(spEM2);
986 IEnumMoniker_Release(spEM3);
987 IMoniker_Release(pmk1);
988 IMoniker_Release(pmk2);
989 IRunningObjectTable_Release(pprot);
991 IBindCtx_Release(pbc);
994 static const LARGE_INTEGER llZero;
996 static const BYTE expected_class_moniker_marshal_data[] =
998 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
999 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1000 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1001 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1002 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1003 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1004 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1005 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1006 0x00,0x00,0x00,0x00,
1009 static const BYTE expected_class_moniker_saved_data[] =
1011 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1012 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1013 0x00,0x00,0x00,0x00,
1016 static const BYTE expected_class_moniker_comparison_data[] =
1018 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1019 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1020 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1021 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1024 static const WCHAR expected_class_moniker_display_name[] =
1026 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1027 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1028 '0','0','0','0','4','6',':',0
1031 static const BYTE expected_item_moniker_comparison_data[] =
1033 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1034 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1035 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1036 0x54,0x00,0x00,0x00,
1039 static const BYTE expected_item_moniker_saved_data[] =
1041 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1042 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1045 static const BYTE expected_item_moniker_marshal_data[] =
1047 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1048 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1049 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1050 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1051 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1052 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1053 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1054 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1057 static const BYTE expected_anti_moniker_marshal_data[] =
1059 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1060 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1061 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1062 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1063 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1064 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1065 0x01,0x00,0x00,0x00,
1068 static const BYTE expected_anti_moniker_saved_data[] =
1070 0x01,0x00,0x00,0x00,
1073 static const BYTE expected_anti_moniker_comparison_data[] =
1075 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1076 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1077 0x01,0x00,0x00,0x00,
1080 static const BYTE expected_gc_moniker_marshal_data[] =
1082 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1083 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1084 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1085 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1086 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1087 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1088 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1089 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1090 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1091 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1092 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1093 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1094 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1095 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1096 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1097 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1098 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1099 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1100 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1101 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1102 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1103 0x00,0x57,0x69,0x6e,0x65,0x00,
1106 static const BYTE expected_gc_moniker_saved_data[] =
1108 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1109 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1110 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1111 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1112 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1113 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1114 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1115 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1116 0x65,0x00,
1119 static const BYTE expected_gc_moniker_comparison_data[] =
1121 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1122 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1123 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1124 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1125 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1126 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1127 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1128 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1129 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1132 static void test_moniker(
1133 const char *testname, IMoniker *moniker,
1134 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1135 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1136 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1137 LPCWSTR expected_display_name)
1139 IStream * stream;
1140 IROTData * rotdata;
1141 HRESULT hr;
1142 HGLOBAL hglobal;
1143 LPBYTE moniker_data;
1144 DWORD moniker_size;
1145 DWORD i;
1146 BOOL same;
1147 BYTE buffer[128];
1148 IMoniker * moniker_proxy;
1149 LPOLESTR display_name;
1150 IBindCtx *bindctx;
1152 hr = IMoniker_IsDirty(moniker);
1153 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1155 /* Display Name */
1157 hr = CreateBindCtx(0, &bindctx);
1158 ok_ole_success(hr, CreateBindCtx);
1160 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1161 ok_ole_success(hr, IMoniker_GetDisplayName);
1162 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1164 CoTaskMemFree(display_name);
1165 IBindCtx_Release(bindctx);
1167 hr = IMoniker_IsDirty(moniker);
1168 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1170 /* IROTData::GetComparisonData test */
1172 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1173 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1175 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1176 ok_ole_success(hr, IROTData_GetComparisonData);
1178 if (hr != S_OK) moniker_size = 0;
1180 /* first check we have the right amount of data */
1181 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1182 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1183 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1185 /* then do a byte-by-byte comparison */
1186 same = TRUE;
1187 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1189 if (expected_moniker_comparison_data[i] != buffer[i])
1191 same = FALSE;
1192 break;
1196 ok(same, "%s: Comparison data differs\n", testname);
1197 if (!same)
1199 for (i = 0; i < moniker_size; i++)
1201 if (i % 8 == 0) printf(" ");
1202 printf("0x%02x,", buffer[i]);
1203 if (i % 8 == 7) printf("\n");
1205 printf("\n");
1208 IROTData_Release(rotdata);
1210 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1212 /* Saving */
1214 hr = IMoniker_Save(moniker, stream, TRUE);
1215 ok_ole_success(hr, IMoniker_Save);
1217 hr = GetHGlobalFromStream(stream, &hglobal);
1218 ok_ole_success(hr, GetHGlobalFromStream);
1220 moniker_size = GlobalSize(hglobal);
1222 moniker_data = GlobalLock(hglobal);
1224 /* first check we have the right amount of data */
1225 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1226 "%s: Size of saved data differs (expected %d, actual %d)\n",
1227 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1229 /* then do a byte-by-byte comparison */
1230 same = TRUE;
1231 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1233 if (expected_moniker_saved_data[i] != moniker_data[i])
1235 same = FALSE;
1236 break;
1240 ok(same, "%s: Saved data differs\n", testname);
1241 if (!same)
1243 for (i = 0; i < moniker_size; i++)
1245 if (i % 8 == 0) printf(" ");
1246 printf("0x%02x,", moniker_data[i]);
1247 if (i % 8 == 7) printf("\n");
1249 printf("\n");
1252 GlobalUnlock(hglobal);
1254 IStream_Release(stream);
1256 /* Marshaling tests */
1258 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1259 ok_ole_success(hr, CreateStreamOnHGlobal);
1261 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1262 ok_ole_success(hr, CoMarshalInterface);
1264 hr = GetHGlobalFromStream(stream, &hglobal);
1265 ok_ole_success(hr, GetHGlobalFromStream);
1267 moniker_size = GlobalSize(hglobal);
1269 moniker_data = GlobalLock(hglobal);
1271 /* first check we have the right amount of data */
1272 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1273 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1274 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1276 /* then do a byte-by-byte comparison */
1277 same = TRUE;
1278 if (expected_moniker_marshal_data)
1280 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1282 if (expected_moniker_marshal_data[i] != moniker_data[i])
1284 same = FALSE;
1285 break;
1290 ok(same, "%s: Marshaled data differs\n", testname);
1291 if (!same)
1293 for (i = 0; i < moniker_size; i++)
1295 if (i % 8 == 0) printf(" ");
1296 printf("0x%02x,", moniker_data[i]);
1297 if (i % 8 == 7) printf("\n");
1299 printf("\n");
1302 GlobalUnlock(hglobal);
1304 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1305 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1306 ok_ole_success(hr, CoUnmarshalInterface);
1308 IStream_Release(stream);
1309 IMoniker_Release(moniker_proxy);
1312 static void test_class_moniker(void)
1314 HRESULT hr;
1315 IMoniker *moniker;
1316 DWORD moniker_type;
1317 DWORD hash;
1318 IBindCtx *bindctx;
1319 IMoniker *inverse;
1320 IUnknown *unknown;
1321 FILETIME filetime;
1323 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1324 ok_ole_success(hr, CreateClassMoniker);
1325 if (!moniker) return;
1327 test_moniker("class moniker", moniker,
1328 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1329 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1330 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1331 expected_class_moniker_display_name);
1333 /* Hashing */
1335 hr = IMoniker_Hash(moniker, &hash);
1336 ok_ole_success(hr, IMoniker_Hash);
1338 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1339 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1340 hash);
1342 /* IsSystemMoniker test */
1344 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1345 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1347 ok(moniker_type == MKSYS_CLASSMONIKER,
1348 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1349 moniker_type);
1351 hr = CreateBindCtx(0, &bindctx);
1352 ok_ole_success(hr, CreateBindCtx);
1354 /* IsRunning test */
1355 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1356 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1358 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1359 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1361 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1362 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1364 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1365 ok_ole_success(hr, IMoniker_BindToObject);
1366 IUnknown_Release(unknown);
1368 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1369 ok_ole_success(hr, IMoniker_BindToStorage);
1370 IUnknown_Release(unknown);
1372 IBindCtx_Release(bindctx);
1374 hr = IMoniker_Inverse(moniker, &inverse);
1375 ok_ole_success(hr, IMoniker_Inverse);
1376 IMoniker_Release(inverse);
1378 IMoniker_Release(moniker);
1381 static void test_file_moniker(WCHAR* path)
1383 IStream *stream;
1384 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1385 HRESULT hr;
1387 hr = CreateFileMoniker(path, &moniker1);
1388 ok_ole_success(hr, CreateFileMoniker);
1390 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1392 /* Marshal */
1393 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1394 ok_ole_success(hr, CoMarshalInterface);
1396 /* Rewind */
1397 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1398 ok_ole_success(hr, IStream_Seek);
1400 /* Unmarshal */
1401 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1402 ok_ole_success(hr, CoUnmarshalInterface);
1404 hr = IMoniker_IsEqual(moniker1, moniker2);
1405 ok_ole_success(hr, IsEqual);
1407 IStream_Release(stream);
1408 if (moniker1)
1409 IMoniker_Release(moniker1);
1410 if (moniker2)
1411 IMoniker_Release(moniker2);
1414 static void test_file_monikers(void)
1416 static WCHAR wszFile[][30] = {
1417 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1418 {'\\', '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},
1419 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1420 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1421 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1422 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1423 * U+0100 .. = Latin extended-A
1425 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1428 int i;
1430 trace("ACP is %u\n", GetACP());
1432 for (i = 0; i < COUNTOF(wszFile); ++i)
1434 int j ;
1435 if (i == 2)
1437 BOOL used;
1438 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1439 if (used)
1441 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1442 continue;
1445 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1447 wszFile[i][j] = 0;
1448 test_file_moniker(wszFile[i]);
1453 static void test_item_moniker(void)
1455 HRESULT hr;
1456 IMoniker *moniker;
1457 DWORD moniker_type;
1458 DWORD hash;
1459 IBindCtx *bindctx;
1460 IMoniker *inverse;
1461 IUnknown *unknown;
1462 static const WCHAR wszDelimeter[] = {'!',0};
1463 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1464 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1466 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1467 ok_ole_success(hr, CreateItemMoniker);
1469 test_moniker("item moniker", moniker,
1470 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1471 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1472 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1473 expected_display_name);
1475 /* Hashing */
1477 hr = IMoniker_Hash(moniker, &hash);
1478 ok_ole_success(hr, IMoniker_Hash);
1480 ok(hash == 0x73c,
1481 "Hash value != 0x73c, instead was 0x%08x\n",
1482 hash);
1484 /* IsSystemMoniker test */
1486 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1487 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1489 ok(moniker_type == MKSYS_ITEMMONIKER,
1490 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1491 moniker_type);
1493 hr = CreateBindCtx(0, &bindctx);
1494 ok_ole_success(hr, CreateBindCtx);
1496 /* IsRunning test */
1497 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1498 todo_wine
1499 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1501 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1502 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1504 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1505 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1507 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1508 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1510 IBindCtx_Release(bindctx);
1512 hr = IMoniker_Inverse(moniker, &inverse);
1513 ok_ole_success(hr, IMoniker_Inverse);
1514 IMoniker_Release(inverse);
1516 IMoniker_Release(moniker);
1519 static void test_anti_moniker(void)
1521 HRESULT hr;
1522 IMoniker *moniker;
1523 DWORD moniker_type;
1524 DWORD hash;
1525 IBindCtx *bindctx;
1526 FILETIME filetime;
1527 IMoniker *inverse;
1528 IUnknown *unknown;
1529 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1531 hr = CreateAntiMoniker(&moniker);
1532 ok_ole_success(hr, CreateAntiMoniker);
1533 if (!moniker) return;
1535 test_moniker("anti moniker", moniker,
1536 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1537 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1538 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1539 expected_display_name);
1541 /* Hashing */
1542 hr = IMoniker_Hash(moniker, &hash);
1543 ok_ole_success(hr, IMoniker_Hash);
1544 ok(hash == 0x80000001,
1545 "Hash value != 0x80000001, instead was 0x%08x\n",
1546 hash);
1548 /* IsSystemMoniker test */
1549 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1550 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1551 ok(moniker_type == MKSYS_ANTIMONIKER,
1552 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1553 moniker_type);
1555 hr = IMoniker_Inverse(moniker, &inverse);
1556 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1557 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1559 hr = CreateBindCtx(0, &bindctx);
1560 ok_ole_success(hr, CreateBindCtx);
1562 /* IsRunning test */
1563 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1564 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1566 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1567 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1569 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1570 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1572 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1573 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1575 IBindCtx_Release(bindctx);
1577 IMoniker_Release(moniker);
1580 static void test_generic_composite_moniker(void)
1582 HRESULT hr;
1583 IMoniker *moniker;
1584 IMoniker *moniker1;
1585 IMoniker *moniker2;
1586 DWORD moniker_type;
1587 DWORD hash;
1588 IBindCtx *bindctx;
1589 FILETIME filetime;
1590 IMoniker *inverse;
1591 IUnknown *unknown;
1592 static const WCHAR wszDelimeter1[] = {'!',0};
1593 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1594 static const WCHAR wszDelimeter2[] = {'#',0};
1595 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1596 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1598 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1599 ok_ole_success(hr, CreateItemMoniker);
1600 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1601 ok_ole_success(hr, CreateItemMoniker);
1602 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1603 ok_ole_success(hr, CreateGenericComposite);
1605 test_moniker("generic composite moniker", moniker,
1606 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1607 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1608 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1609 expected_display_name);
1611 /* Hashing */
1613 hr = IMoniker_Hash(moniker, &hash);
1614 ok_ole_success(hr, IMoniker_Hash);
1616 ok(hash == 0xd87,
1617 "Hash value != 0xd87, instead was 0x%08x\n",
1618 hash);
1620 /* IsSystemMoniker test */
1622 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1623 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1625 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1626 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1627 moniker_type);
1629 hr = CreateBindCtx(0, &bindctx);
1630 ok_ole_success(hr, CreateBindCtx);
1632 /* IsRunning test */
1633 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1634 todo_wine
1635 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1637 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1638 todo_wine
1639 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1641 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1642 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1644 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1645 todo_wine
1646 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1648 todo_wine
1649 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1650 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1652 IBindCtx_Release(bindctx);
1654 hr = IMoniker_Inverse(moniker, &inverse);
1655 ok_ole_success(hr, IMoniker_Inverse);
1656 IMoniker_Release(inverse);
1658 IMoniker_Release(moniker);
1661 static void test_pointer_moniker(void)
1663 HRESULT hr;
1664 IMoniker *moniker;
1665 DWORD moniker_type;
1666 DWORD hash;
1667 IBindCtx *bindctx;
1668 FILETIME filetime;
1669 IMoniker *inverse;
1670 IUnknown *unknown;
1671 IStream *stream;
1672 IROTData *rotdata;
1673 LPOLESTR display_name;
1675 cLocks = 0;
1677 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1678 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1680 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1681 ok_ole_success(hr, CreatePointerMoniker);
1682 if (!moniker) return;
1684 ok_more_than_one_lock();
1686 /* Display Name */
1688 hr = CreateBindCtx(0, &bindctx);
1689 ok_ole_success(hr, CreateBindCtx);
1691 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1692 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1694 IBindCtx_Release(bindctx);
1696 hr = IMoniker_IsDirty(moniker);
1697 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1699 /* IROTData::GetComparisonData test */
1701 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1702 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1704 /* Saving */
1706 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1707 ok_ole_success(hr, CreateStreamOnHGlobal);
1709 hr = IMoniker_Save(moniker, stream, TRUE);
1710 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1712 IStream_Release(stream);
1714 /* Hashing */
1715 hr = IMoniker_Hash(moniker, &hash);
1716 ok_ole_success(hr, IMoniker_Hash);
1717 ok(hash == (DWORD)&Test_ClassFactory,
1718 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1719 (DWORD)&Test_ClassFactory, hash);
1721 /* IsSystemMoniker test */
1722 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1723 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1724 ok(moniker_type == MKSYS_POINTERMONIKER,
1725 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1726 moniker_type);
1728 hr = IMoniker_Inverse(moniker, &inverse);
1729 ok_ole_success(hr, IMoniker_Inverse);
1730 IMoniker_Release(inverse);
1732 hr = CreateBindCtx(0, &bindctx);
1733 ok_ole_success(hr, CreateBindCtx);
1735 /* IsRunning test */
1736 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1737 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1739 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1740 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1742 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1743 ok_ole_success(hr, IMoniker_BindToObject);
1744 IUnknown_Release(unknown);
1746 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1747 ok_ole_success(hr, IMoniker_BindToStorage);
1748 IUnknown_Release(unknown);
1750 IMoniker_Release(moniker);
1752 ok_no_locks();
1754 hr = CreatePointerMoniker(NULL, &moniker);
1755 ok_ole_success(hr, CreatePointerMoniker);
1757 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1758 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1760 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1761 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1763 IBindCtx_Release(bindctx);
1765 IMoniker_Release(moniker);
1768 static void test_bind_context(void)
1770 HRESULT hr;
1771 IBindCtx *pBindCtx;
1772 IEnumString *pEnumString;
1773 BIND_OPTS2 bind_opts;
1774 HeapUnknown *unknown;
1775 HeapUnknown *unknown2;
1776 IUnknown *param_obj;
1777 ULONG refs;
1778 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1779 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1781 hr = CreateBindCtx(0, NULL);
1782 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1784 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1785 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1787 hr = CreateBindCtx(0, &pBindCtx);
1788 ok_ole_success(hr, "CreateBindCtx");
1790 bind_opts.cbStruct = -1;
1791 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1792 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1793 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1794 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1795 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1797 bind_opts.cbStruct = sizeof(BIND_OPTS);
1798 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1799 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1800 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1802 bind_opts.cbStruct = sizeof(bind_opts);
1803 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1804 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1805 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1806 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1807 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1808 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1809 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1810 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1811 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1812 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1813 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1815 bind_opts.cbStruct = -1;
1816 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1817 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1819 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1820 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1822 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1823 unknown->lpVtbl = &HeapUnknown_Vtbl;
1824 unknown->refs = 1;
1825 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1826 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1828 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1829 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1830 IUnknown_Release(param_obj);
1832 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1833 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1834 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1836 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1837 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1839 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1840 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1841 ok(!pEnumString, "pEnumString should be NULL\n");
1843 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1844 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1846 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1847 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1849 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1850 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1851 unknown2->refs = 1;
1852 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1853 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1855 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1856 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1858 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1859 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1861 IBindCtx_Release(pBindCtx);
1863 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1864 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1866 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1867 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1870 static void test_save_load_filemoniker(void)
1872 IMoniker* pMk;
1873 IStream* pStm;
1874 HRESULT hr;
1875 ULARGE_INTEGER size;
1876 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
1877 DWORD some_val = 0xFEDCBA98;
1878 int i;
1880 /* see FileMonikerImpl_Save docs */
1881 zero_pos.QuadPart = 0;
1882 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
1883 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
1885 /* create the stream we're going to write to */
1886 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
1887 ok_ole_success(hr, "CreateStreamOnHGlobal");
1889 size.u.LowPart = 128;
1890 hr = IStream_SetSize(pStm, size);
1891 ok_ole_success(hr, "IStream_SetSize");
1893 /* create and save a moniker */
1894 hr = CreateFileMoniker(wszFileName1, &pMk);
1895 ok_ole_success(hr, "CreateFileMoniker");
1897 hr = IMoniker_Save(pMk, pStm, TRUE);
1898 ok_ole_success(hr, "IMoniker_Save");
1900 hr = IMoniker_Release(pMk);
1901 ok_ole_success(hr, "IMoniker_Release");
1903 /* overwrite the constants with various values */
1904 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1905 ok_ole_success(hr, "IStream_Seek");
1906 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1907 ok_ole_success(hr, "IStream_Write");
1909 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
1910 ok_ole_success(hr, "IStream_Seek");
1911 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1912 ok_ole_success(hr, "IStream_Write");
1914 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
1915 ok_ole_success(hr, "IStream_Seek");
1916 for(i = 0; i < 5; ++i){
1917 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
1918 ok_ole_success(hr, "IStream_Write");
1921 /* go back to the start of the stream */
1922 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1923 ok_ole_success(hr, "IStream_Seek");
1925 /* create a new moniker and load into it */
1926 hr = CreateFileMoniker(wszFileName1, &pMk);
1927 ok_ole_success(hr, "CreateFileMoniker");
1929 hr = IMoniker_Load(pMk, pStm);
1930 ok_ole_success(hr, "IMoniker_Load");
1932 hr = IMoniker_Release(pMk);
1933 ok_ole_success(hr, "IMoniker_Release");
1935 hr = IStream_Release(pStm);
1936 ok_ole_success(hr, "IStream_Release");
1939 START_TEST(moniker)
1941 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1943 test_ROT();
1944 test_ROT_multiple_entries();
1945 test_MkParseDisplayName();
1946 test_class_moniker();
1947 test_file_monikers();
1948 test_item_moniker();
1949 test_anti_moniker();
1950 test_generic_composite_moniker();
1951 test_pointer_moniker();
1952 test_save_load_filemoniker();
1954 /* FIXME: test moniker creation funcs and parsing other moniker formats */
1956 test_bind_context();
1958 CoUninitialize();