ole32: Keep track of the number of weak references to an object.
[wine.git] / dlls / ole32 / tests / moniker.c
blobaa737c0413e00496fa54c6ac1f5c3e0306647aa0
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"
32 #include "olectl.h"
34 #include "wine/test.h"
36 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
37 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
38 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
39 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
41 #define CHECK_EXPECTED_METHOD(method_name) \
42 do { \
43 trace("%s\n", method_name); \
44 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
45 if (*expected_method_list) \
46 { \
47 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
48 *expected_method_list, method_name); \
49 expected_method_list++; \
50 } \
51 } while(0)
53 static char const * const *expected_method_list;
54 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
55 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
57 static const CLSID CLSID_WineTest =
58 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
59 0x9474ba1a,
60 0x258b,
61 0x490b,
62 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
65 static const CLSID CLSID_TestMoniker =
66 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
67 0xb306bfbc,
68 0x496e,
69 0x4f53,
70 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
73 static LONG cLocks;
75 static void LockModule(void)
77 InterlockedIncrement(&cLocks);
80 static void UnlockModule(void)
82 InterlockedDecrement(&cLocks);
85 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
86 LPCLASSFACTORY iface,
87 REFIID riid,
88 LPVOID *ppvObj)
90 if (ppvObj == NULL) return E_POINTER;
92 if (IsEqualGUID(riid, &IID_IUnknown) ||
93 IsEqualGUID(riid, &IID_IClassFactory))
95 *ppvObj = (LPVOID)iface;
96 IClassFactory_AddRef(iface);
97 return S_OK;
100 *ppvObj = NULL;
101 return E_NOINTERFACE;
104 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
106 LockModule();
107 return 2; /* non-heap-based object */
110 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
112 UnlockModule();
113 return 1; /* non-heap-based object */
116 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
117 LPCLASSFACTORY iface,
118 LPUNKNOWN pUnkOuter,
119 REFIID riid,
120 LPVOID *ppvObj)
122 return E_NOTIMPL;
125 static HRESULT WINAPI Test_IClassFactory_LockServer(
126 LPCLASSFACTORY iface,
127 BOOL fLock)
129 return S_OK;
132 static const IClassFactoryVtbl TestClassFactory_Vtbl =
134 Test_IClassFactory_QueryInterface,
135 Test_IClassFactory_AddRef,
136 Test_IClassFactory_Release,
137 Test_IClassFactory_CreateInstance,
138 Test_IClassFactory_LockServer
141 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
143 typedef struct
145 const IUnknownVtbl *lpVtbl;
146 ULONG refs;
147 } HeapUnknown;
149 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
151 if (IsEqualIID(riid, &IID_IUnknown))
153 IUnknown_AddRef(iface);
154 *ppv = (LPVOID)iface;
155 return S_OK;
157 *ppv = NULL;
158 return E_NOINTERFACE;
161 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
163 HeapUnknown *This = (HeapUnknown *)iface;
164 return InterlockedIncrement((LONG*)&This->refs);
167 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
169 HeapUnknown *This = (HeapUnknown *)iface;
170 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
171 if (!refs) HeapFree(GetProcessHeap(), 0, This);
172 return refs;
175 static const IUnknownVtbl HeapUnknown_Vtbl =
177 HeapUnknown_QueryInterface,
178 HeapUnknown_AddRef,
179 HeapUnknown_Release
182 static HRESULT WINAPI
183 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
185 if (!ppvObject)
186 return E_INVALIDARG;
188 *ppvObject = 0;
190 if (IsEqualIID(&IID_IUnknown, riid) ||
191 IsEqualIID(&IID_IPersist, riid) ||
192 IsEqualIID(&IID_IPersistStream,riid) ||
193 IsEqualIID(&IID_IMoniker, riid))
194 *ppvObject = iface;
195 if (IsEqualIID(&IID_IROTData, riid))
196 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
198 if ((*ppvObject)==0)
199 return E_NOINTERFACE;
201 IMoniker_AddRef(iface);
203 return S_OK;
206 static ULONG WINAPI
207 Moniker_AddRef(IMoniker* iface)
209 return 2;
212 static ULONG WINAPI
213 Moniker_Release(IMoniker* iface)
215 return 1;
218 static HRESULT WINAPI
219 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
221 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
223 *pClassID = CLSID_TestMoniker;
225 return S_OK;
228 static HRESULT WINAPI
229 Moniker_IsDirty(IMoniker* iface)
231 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
233 return S_FALSE;
236 static HRESULT WINAPI
237 Moniker_Load(IMoniker* iface, IStream* pStm)
239 CHECK_EXPECTED_METHOD("Moniker_Load");
240 return E_NOTIMPL;
243 static HRESULT WINAPI
244 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
246 CHECK_EXPECTED_METHOD("Moniker_Save");
247 return E_NOTIMPL;
250 static HRESULT WINAPI
251 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
253 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
254 return E_NOTIMPL;
257 static HRESULT WINAPI
258 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
259 REFIID riid, VOID** ppvResult)
261 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
262 return E_NOTIMPL;
265 static HRESULT WINAPI
266 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
267 REFIID riid, VOID** ppvObject)
269 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
270 return E_NOTIMPL;
273 static HRESULT WINAPI
274 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
275 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
277 CHECK_EXPECTED_METHOD("Moniker_Reduce");
279 if (ppmkReduced==NULL)
280 return E_POINTER;
282 IMoniker_AddRef(iface);
284 *ppmkReduced=iface;
286 return MK_S_REDUCED_TO_SELF;
289 static HRESULT WINAPI
290 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
291 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
293 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
294 return E_NOTIMPL;
297 static HRESULT WINAPI
298 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
300 CHECK_EXPECTED_METHOD("Moniker_Enum");
302 if (ppenumMoniker == NULL)
303 return E_POINTER;
305 *ppenumMoniker = NULL;
307 return S_OK;
310 static HRESULT WINAPI
311 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
313 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
314 return E_NOTIMPL;
317 static HRESULT WINAPI
318 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
320 CHECK_EXPECTED_METHOD("Moniker_Hash");
321 return E_NOTIMPL;
324 static HRESULT WINAPI
325 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
326 IMoniker* pmkNewlyRunning)
328 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
329 return E_NOTIMPL;
332 static HRESULT WINAPI
333 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
334 IMoniker* pmkToLeft, FILETIME* pFileTime)
336 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
337 return E_NOTIMPL;
340 static HRESULT WINAPI
341 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
343 CHECK_EXPECTED_METHOD("Moniker_Inverse");
344 return E_NOTIMPL;
347 static HRESULT WINAPI
348 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
350 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
351 return E_NOTIMPL;
354 static HRESULT WINAPI
355 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
357 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
358 return E_NOTIMPL;
361 static HRESULT WINAPI
362 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
363 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
365 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
366 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
367 *ppszDisplayName = (LPOLESTR)CoTaskMemAlloc(sizeof(wszDisplayName));
368 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
369 return S_OK;
372 static HRESULT WINAPI
373 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
374 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
376 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
377 return E_NOTIMPL;
380 static HRESULT WINAPI
381 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
383 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
385 if (!pwdMksys)
386 return E_POINTER;
388 (*pwdMksys)=MKSYS_NONE;
390 return S_FALSE;
393 static const IMonikerVtbl MonikerNoROTDataVtbl =
395 MonikerNoROTData_QueryInterface,
396 Moniker_AddRef,
397 Moniker_Release,
398 Moniker_GetClassID,
399 Moniker_IsDirty,
400 Moniker_Load,
401 Moniker_Save,
402 Moniker_GetSizeMax,
403 Moniker_BindToObject,
404 Moniker_BindToStorage,
405 Moniker_Reduce,
406 Moniker_ComposeWith,
407 Moniker_Enum,
408 Moniker_IsEqual,
409 Moniker_Hash,
410 Moniker_IsRunning,
411 Moniker_GetTimeOfLastChange,
412 Moniker_Inverse,
413 Moniker_CommonPrefixWith,
414 Moniker_RelativePathTo,
415 Moniker_GetDisplayName,
416 Moniker_ParseDisplayName,
417 Moniker_IsSystemMoniker
420 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
422 static IMoniker Moniker;
424 static HRESULT WINAPI
425 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
427 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
430 static ULONG WINAPI
431 ROTData_AddRef(IROTData *iface)
433 return 2;
436 static ULONG WINAPI
437 ROTData_Release(IROTData* iface)
439 return 1;
442 static HRESULT WINAPI
443 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
444 ULONG cbMax, ULONG* pcbData)
446 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
448 *pcbData = 1;
449 if (cbMax < *pcbData)
450 return E_OUTOFMEMORY;
452 *pbData = 0xde;
454 return S_OK;
457 static IROTDataVtbl ROTDataVtbl =
459 ROTData_QueryInterface,
460 ROTData_AddRef,
461 ROTData_Release,
462 ROTData_GetComparisonData
465 static IROTData ROTData = { &ROTDataVtbl };
467 static HRESULT WINAPI
468 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
470 if (!ppvObject)
471 return E_INVALIDARG;
473 *ppvObject = 0;
475 if (IsEqualIID(&IID_IUnknown, riid) ||
476 IsEqualIID(&IID_IPersist, riid) ||
477 IsEqualIID(&IID_IPersistStream,riid) ||
478 IsEqualIID(&IID_IMoniker, riid))
479 *ppvObject = iface;
480 if (IsEqualIID(&IID_IROTData, riid))
482 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
483 *ppvObject = &ROTData;
486 if ((*ppvObject)==0)
487 return E_NOINTERFACE;
489 IMoniker_AddRef(iface);
491 return S_OK;
494 static const IMonikerVtbl MonikerVtbl =
496 Moniker_QueryInterface,
497 Moniker_AddRef,
498 Moniker_Release,
499 Moniker_GetClassID,
500 Moniker_IsDirty,
501 Moniker_Load,
502 Moniker_Save,
503 Moniker_GetSizeMax,
504 Moniker_BindToObject,
505 Moniker_BindToStorage,
506 Moniker_Reduce,
507 Moniker_ComposeWith,
508 Moniker_Enum,
509 Moniker_IsEqual,
510 Moniker_Hash,
511 Moniker_IsRunning,
512 Moniker_GetTimeOfLastChange,
513 Moniker_Inverse,
514 Moniker_CommonPrefixWith,
515 Moniker_RelativePathTo,
516 Moniker_GetDisplayName,
517 Moniker_ParseDisplayName,
518 Moniker_IsSystemMoniker
521 static IMoniker Moniker = { &MonikerVtbl };
523 static void test_ROT(void)
525 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
526 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
527 '2','0','4','6','E','5','8','6','C','9','2','5',0};
528 HRESULT hr;
529 IMoniker *pMoniker = NULL;
530 IRunningObjectTable *pROT = NULL;
531 DWORD dwCookie;
532 static const char *methods_register_no_ROTData[] =
534 "Moniker_Reduce",
535 "Moniker_GetTimeOfLastChange",
536 "Moniker_QueryInterface(IID_IROTData)",
537 "Moniker_GetDisplayName",
538 "Moniker_GetClassID",
539 NULL
541 static const char *methods_register[] =
543 "Moniker_Reduce",
544 "Moniker_GetTimeOfLastChange",
545 "Moniker_QueryInterface(IID_IROTData)",
546 "ROTData_GetComparisonData",
547 NULL
549 static const char *methods_isrunning_no_ROTData[] =
551 "Moniker_Reduce",
552 "Moniker_QueryInterface(IID_IROTData)",
553 "Moniker_GetDisplayName",
554 "Moniker_GetClassID",
555 NULL
557 static const char *methods_isrunning[] =
559 "Moniker_Reduce",
560 "Moniker_QueryInterface(IID_IROTData)",
561 "ROTData_GetComparisonData",
562 NULL
565 cLocks = 0;
567 hr = GetRunningObjectTable(0, &pROT);
568 ok_ole_success(hr, GetRunningObjectTable);
570 expected_method_list = methods_register_no_ROTData;
571 /* try with our own moniker that doesn't support IROTData */
572 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
573 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
574 todo_wine { /* only fails because of lack of IMoniker marshaling */
575 ok_ole_success(hr, IRunningObjectTable_Register);
577 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
579 todo_wine { /* only fails because of lack of IMoniker marshaling */
580 ok_more_than_one_lock();
583 expected_method_list = methods_isrunning_no_ROTData;
584 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
585 todo_wine { /* only fails because of lack of IMoniker marshaling */
586 ok_ole_success(hr, IRunningObjectTable_IsRunning);
588 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
590 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
591 todo_wine { /* only fails because of lack of IMoniker marshaling */
592 ok_ole_success(hr, IRunningObjectTable_Revoke);
595 ok_no_locks();
597 expected_method_list = methods_register;
598 /* try with our own moniker */
599 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
600 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
601 todo_wine { /* only fails because of lack of IMoniker marshaling */
602 ok_ole_success(hr, IRunningObjectTable_Register);
604 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
606 todo_wine { /* only fails because of lack of IMoniker marshaling */
607 ok_more_than_one_lock();
610 expected_method_list = methods_isrunning;
611 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
612 todo_wine { /* only fails because of lack of IMoniker marshaling */
613 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 todo_wine { /* only fails because of lack of IMoniker marshaling */
619 ok_ole_success(hr, IRunningObjectTable_Revoke);
622 ok_no_locks();
624 hr = CreateFileMoniker(wszFileName, &pMoniker);
625 ok_ole_success(hr, CreateClassMoniker);
627 /* test flags: 0 */
628 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
629 pMoniker, &dwCookie);
630 ok_ole_success(hr, IRunningObjectTable_Register);
632 ok_more_than_one_lock();
634 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
635 ok_ole_success(hr, IRunningObjectTable_Revoke);
637 ok_no_locks();
639 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
640 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
641 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
642 ok_ole_success(hr, IRunningObjectTable_Register);
644 ok_more_than_one_lock();
646 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
647 ok_ole_success(hr, IRunningObjectTable_Revoke);
649 ok_no_locks();
651 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
652 /* only succeeds when process is started by SCM and has LocalService
653 * or RunAs AppId values */
654 hr = IRunningObjectTable_Register(pROT,
655 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
656 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
657 todo_wine {
658 ok(hr == CO_E_WRONG_SERVER_IDENTITY, "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 todo_wine
694 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
696 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
697 ok_ole_success(hr, IRunningObjectTable_GetObject);
698 IUnknown_Release(pObject);
700 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
701 ok_ole_success(hr, IRunningObjectTable_Revoke);
703 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
704 ok_ole_success(hr, IRunningObjectTable_GetObject);
705 IUnknown_Release(pObject);
707 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
708 ok_ole_success(hr, IRunningObjectTable_Revoke);
710 IMoniker_Release(pMoniker);
712 IRunningObjectTable_Release(pROT);
715 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
717 if (IsEqualIID(riid, &IID_IUnknown) ||
718 IsEqualIID(riid, &IID_IParseDisplayName))
720 *ppv = iface;
721 IUnknown_AddRef(iface);
722 return S_OK;
724 *ppv = NULL;
725 return E_NOINTERFACE;
728 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
730 return 2;
733 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
735 return 1;
738 static LPCWSTR expected_display_name;
740 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
741 IBindCtx *pbc,
742 LPOLESTR pszDisplayName,
743 ULONG *pchEaten,
744 IMoniker **ppmkOut)
746 char display_nameA[256];
747 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
748 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
749 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
750 *pchEaten = lstrlenW(pszDisplayName);
751 return CreateAntiMoniker(ppmkOut);
754 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
756 ParseDisplayName_QueryInterface,
757 ParseDisplayName_AddRef,
758 ParseDisplayName_Release,
759 ParseDisplayName_ParseDisplayName
762 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
764 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
766 IMoniker * spMoniker;
767 int monCnt=0, matchCnt=0;
769 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
771 HRESULT hr;
772 WCHAR * szDisplayn;
773 monCnt++;
774 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
775 if (SUCCEEDED(hr))
777 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
778 matchCnt++;
779 CoTaskMemFree(szDisplayn);
782 trace("Total number of monikers is %i\n", monCnt);
783 return matchCnt;
786 static void test_MkParseDisplayName(void)
788 IBindCtx * pbc = NULL;
789 HRESULT hr;
790 IMoniker * pmk = NULL;
791 IMoniker * pmk1 = NULL;
792 IMoniker * pmk2 = NULL;
793 ULONG eaten;
794 int matchCnt;
795 IUnknown * object = NULL;
797 IUnknown *lpEM1;
799 IEnumMoniker *spEM1 = NULL;
800 IEnumMoniker *spEM2 = NULL;
801 IEnumMoniker *spEM3 = NULL;
803 DWORD pdwReg1=0;
804 DWORD grflags=0;
805 DWORD pdwReg2=0;
806 DWORD moniker_type;
807 IRunningObjectTable * pprot=NULL;
809 /* CLSID of My Computer */
810 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
811 '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};
812 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
813 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
814 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
815 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
816 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
817 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
818 char szDisplayNameFile[256];
819 WCHAR wszDisplayNameFile[256];
821 hr = CreateBindCtx(0, &pbc);
822 ok_ole_success(hr, CreateBindCtx);
824 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
825 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
826 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
828 /* no special handling of "clsid:" without the string form of the clsid
829 * following */
830 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
831 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
832 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
834 /* shows clsid has higher precedence than a running object */
835 hr = CreateFileMoniker(wszDisplayName, &pmk);
836 ok_ole_success(hr, CreateFileMoniker);
837 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
838 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
839 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
840 ok_ole_success(hr, IRunningObjectTable_Register);
841 IMoniker_Release(pmk);
842 pmk = NULL;
843 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
844 ok_ole_success(hr, MkParseDisplayName);
845 if (pmk)
847 IMoniker_IsSystemMoniker(pmk, &moniker_type);
848 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
849 IMoniker_Release(pmk);
851 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
852 ok_ole_success(hr, IRunningObjectTable_Revoke);
853 IRunningObjectTable_Release(pprot);
855 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
856 ok_ole_success(hr, CreateFileMoniker);
857 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
858 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
859 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
860 ok_ole_success(hr, IRunningObjectTable_Register);
861 IMoniker_Release(pmk);
862 pmk = NULL;
863 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
864 ok_ole_success(hr, MkParseDisplayName);
865 if (pmk)
867 IMoniker_IsSystemMoniker(pmk, &moniker_type);
868 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
869 IMoniker_Release(pmk);
871 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
872 ok_ole_success(hr, IRunningObjectTable_Revoke);
873 IRunningObjectTable_Release(pprot);
875 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
876 ok_ole_success(hr, CoRegisterClassObject);
878 expected_display_name = wszDisplayNameProgId1;
879 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
880 ok_ole_success(hr, MkParseDisplayName);
881 if (pmk)
883 IMoniker_IsSystemMoniker(pmk, &moniker_type);
884 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
885 IMoniker_Release(pmk);
888 expected_display_name = wszDisplayNameProgId2;
889 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
890 ok_ole_success(hr, MkParseDisplayName);
891 if (pmk)
893 IMoniker_IsSystemMoniker(pmk, &moniker_type);
894 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
895 IMoniker_Release(pmk);
898 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
899 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
900 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
902 hr = CoRevokeClassObject(pdwReg1);
903 ok_ole_success(hr, CoRevokeClassObject);
905 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
906 strcat(szDisplayNameFile, "\\kernel32.dll");
907 MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
908 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
909 ok_ole_success(hr, MkParseDisplayName);
910 if (pmk)
912 IMoniker_IsSystemMoniker(pmk, &moniker_type);
913 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
914 IMoniker_Release(pmk);
917 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
918 ok_ole_success(hr, MkParseDisplayName);
920 if (pmk)
922 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
923 ok_ole_success(hr, IMoniker_BindToObject);
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 = TRUE;
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 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1188 if (expected_moniker_comparison_data[i] != buffer[i])
1190 same = FALSE;
1191 break;
1195 ok(same, "%s: Comparison data differs\n", testname);
1196 if (!same)
1198 for (i = 0; i < moniker_size; i++)
1200 if (i % 8 == 0) printf(" ");
1201 printf("0x%02x,", buffer[i]);
1202 if (i % 8 == 7) printf("\n");
1204 printf("\n");
1207 IROTData_Release(rotdata);
1209 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1211 /* Saving */
1213 hr = IMoniker_Save(moniker, stream, TRUE);
1214 ok_ole_success(hr, IMoniker_Save);
1216 hr = GetHGlobalFromStream(stream, &hglobal);
1217 ok_ole_success(hr, GetHGlobalFromStream);
1219 moniker_size = GlobalSize(hglobal);
1221 moniker_data = GlobalLock(hglobal);
1223 /* first check we have the right amount of data */
1224 ok(moniker_size == sizeof_expected_moniker_saved_data,
1225 "%s: Size of saved data differs (expected %d, actual %d)\n",
1226 testname, sizeof_expected_moniker_saved_data, moniker_size);
1228 /* then do a byte-by-byte comparison */
1229 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
1231 if (expected_moniker_saved_data[i] != moniker_data[i])
1233 same = FALSE;
1234 break;
1238 ok(same, "%s: Saved data differs\n", testname);
1239 if (!same)
1241 for (i = 0; i < moniker_size; i++)
1243 if (i % 8 == 0) printf(" ");
1244 printf("0x%02x,", moniker_data[i]);
1245 if (i % 8 == 7) printf("\n");
1247 printf("\n");
1250 GlobalUnlock(hglobal);
1252 IStream_Release(stream);
1254 /* Marshaling tests */
1256 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1257 ok_ole_success(hr, CreateStreamOnHGlobal);
1259 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1260 ok_ole_success(hr, CoMarshalInterface);
1262 hr = GetHGlobalFromStream(stream, &hglobal);
1263 ok_ole_success(hr, GetHGlobalFromStream);
1265 moniker_size = GlobalSize(hglobal);
1267 moniker_data = GlobalLock(hglobal);
1269 /* first check we have the right amount of data */
1270 ok(moniker_size == sizeof_expected_moniker_marshal_data,
1271 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1272 testname, sizeof_expected_moniker_marshal_data, moniker_size);
1274 /* then do a byte-by-byte comparison */
1275 if (expected_moniker_marshal_data)
1277 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1279 if (expected_moniker_marshal_data[i] != moniker_data[i])
1281 same = FALSE;
1282 break;
1287 ok(same, "%s: Marshaled data differs\n", testname);
1288 if (!same)
1290 for (i = 0; i < moniker_size; i++)
1292 if (i % 8 == 0) printf(" ");
1293 printf("0x%02x,", moniker_data[i]);
1294 if (i % 8 == 7) printf("\n");
1296 printf("\n");
1299 GlobalUnlock(hglobal);
1301 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1302 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1303 ok_ole_success(hr, CoUnmarshalInterface);
1305 IStream_Release(stream);
1306 IMoniker_Release(moniker_proxy);
1309 static void test_class_moniker(void)
1311 HRESULT hr;
1312 IMoniker *moniker;
1313 DWORD moniker_type;
1314 DWORD hash;
1315 IBindCtx *bindctx;
1316 IMoniker *inverse;
1317 IUnknown *unknown;
1318 FILETIME filetime;
1320 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1321 ok_ole_success(hr, CreateClassMoniker);
1322 if (!moniker) return;
1324 test_moniker("class moniker", moniker,
1325 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1326 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1327 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1328 expected_class_moniker_display_name);
1330 /* Hashing */
1332 hr = IMoniker_Hash(moniker, &hash);
1333 ok_ole_success(hr, IMoniker_Hash);
1335 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1336 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1337 hash);
1339 /* IsSystemMoniker test */
1341 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1342 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1344 ok(moniker_type == MKSYS_CLASSMONIKER,
1345 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1346 moniker_type);
1348 hr = CreateBindCtx(0, &bindctx);
1349 ok_ole_success(hr, CreateBindCtx);
1351 /* IsRunning test */
1352 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1353 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1355 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1356 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1358 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1359 ok_ole_success(hr, IMoniker_BindToObject);
1360 IUnknown_Release(unknown);
1362 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1363 ok_ole_success(hr, IMoniker_BindToStorage);
1364 IUnknown_Release(unknown);
1366 IBindCtx_Release(bindctx);
1368 hr = IMoniker_Inverse(moniker, &inverse);
1369 ok_ole_success(hr, IMoniker_Inverse);
1370 IMoniker_Release(inverse);
1372 IMoniker_Release(moniker);
1375 static void test_file_moniker(WCHAR* path)
1377 IStream *stream;
1378 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1379 HRESULT hr;
1381 hr = CreateFileMoniker(path, &moniker1);
1382 ok_ole_success(hr, CreateFileMoniker);
1384 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1386 /* Marshal */
1387 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1388 ok_ole_success(hr, CoMarshalInterface);
1390 /* Rewind */
1391 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1392 ok_ole_success(hr, IStream_Seek);
1394 /* Unmarshal */
1395 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1396 ok_ole_success(hr, CoUnmarshalInterface);
1398 hr = IMoniker_IsEqual(moniker1, moniker2);
1399 ok_ole_success(hr, IsEqual);
1401 IStream_Release(stream);
1402 if (moniker1)
1403 IMoniker_Release(moniker1);
1404 if (moniker2)
1405 IMoniker_Release(moniker2);
1408 static void test_file_monikers(void)
1410 static WCHAR wszFile[][30] = {
1411 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1412 {'\\', '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},
1413 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1414 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1415 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1416 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1417 * U+0100 .. = Latin extended-A
1419 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1422 int i;
1424 trace("ACP is %u\n", GetACP());
1426 for (i = 0; i < COUNTOF(wszFile); ++i)
1428 int j ;
1429 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1431 wszFile[i][j] = 0;
1432 test_file_moniker(wszFile[i]);
1437 static void test_item_moniker(void)
1439 HRESULT hr;
1440 IMoniker *moniker;
1441 DWORD moniker_type;
1442 DWORD hash;
1443 IBindCtx *bindctx;
1444 IMoniker *inverse;
1445 IUnknown *unknown;
1446 static const WCHAR wszDelimeter[] = {'!',0};
1447 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1448 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1450 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1451 ok_ole_success(hr, CreateItemMoniker);
1453 test_moniker("item moniker", moniker,
1454 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1455 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1456 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1457 expected_display_name);
1459 /* Hashing */
1461 hr = IMoniker_Hash(moniker, &hash);
1462 ok_ole_success(hr, IMoniker_Hash);
1464 ok(hash == 0x73c,
1465 "Hash value != 0x73c, instead was 0x%08x\n",
1466 hash);
1468 /* IsSystemMoniker test */
1470 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1471 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1473 ok(moniker_type == MKSYS_ITEMMONIKER,
1474 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1475 moniker_type);
1477 hr = CreateBindCtx(0, &bindctx);
1478 ok_ole_success(hr, CreateBindCtx);
1480 /* IsRunning test */
1481 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1482 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1484 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1485 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1487 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1488 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1490 IBindCtx_Release(bindctx);
1492 hr = IMoniker_Inverse(moniker, &inverse);
1493 ok_ole_success(hr, IMoniker_Inverse);
1494 IMoniker_Release(inverse);
1496 IMoniker_Release(moniker);
1499 static void test_anti_moniker(void)
1501 HRESULT hr;
1502 IMoniker *moniker;
1503 DWORD moniker_type;
1504 DWORD hash;
1505 IBindCtx *bindctx;
1506 FILETIME filetime;
1507 IMoniker *inverse;
1508 IUnknown *unknown;
1509 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1511 hr = CreateAntiMoniker(&moniker);
1512 ok_ole_success(hr, CreateAntiMoniker);
1513 if (!moniker) return;
1515 test_moniker("anti moniker", moniker,
1516 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1517 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1518 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1519 expected_display_name);
1521 /* Hashing */
1522 hr = IMoniker_Hash(moniker, &hash);
1523 ok_ole_success(hr, IMoniker_Hash);
1524 ok(hash == 0x80000001,
1525 "Hash value != 0x80000001, instead was 0x%08x\n",
1526 hash);
1528 /* IsSystemMoniker test */
1529 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1530 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1531 ok(moniker_type == MKSYS_ANTIMONIKER,
1532 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1533 moniker_type);
1535 hr = IMoniker_Inverse(moniker, &inverse);
1536 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1537 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1539 hr = CreateBindCtx(0, &bindctx);
1540 ok_ole_success(hr, CreateBindCtx);
1542 /* IsRunning test */
1543 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1544 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1546 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1547 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1549 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1550 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1552 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1553 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1555 IBindCtx_Release(bindctx);
1557 IMoniker_Release(moniker);
1560 static void test_generic_composite_moniker(void)
1562 HRESULT hr;
1563 IMoniker *moniker;
1564 IMoniker *moniker1;
1565 IMoniker *moniker2;
1566 DWORD moniker_type;
1567 DWORD hash;
1568 IBindCtx *bindctx;
1569 FILETIME filetime;
1570 IMoniker *inverse;
1571 IUnknown *unknown;
1572 static const WCHAR wszDelimeter1[] = {'!',0};
1573 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1574 static const WCHAR wszDelimeter2[] = {'#',0};
1575 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1576 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1578 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1579 ok_ole_success(hr, CreateItemMoniker);
1580 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1581 ok_ole_success(hr, CreateItemMoniker);
1582 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1583 ok_ole_success(hr, CreateGenericComposite);
1585 test_moniker("generic composite moniker", moniker,
1586 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1587 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1588 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1589 expected_display_name);
1591 /* Hashing */
1593 hr = IMoniker_Hash(moniker, &hash);
1594 ok_ole_success(hr, IMoniker_Hash);
1596 ok(hash == 0xd87,
1597 "Hash value != 0xd87, instead was 0x%08x\n",
1598 hash);
1600 /* IsSystemMoniker test */
1602 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1603 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1605 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1606 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1607 moniker_type);
1609 hr = CreateBindCtx(0, &bindctx);
1610 ok_ole_success(hr, CreateBindCtx);
1612 /* IsRunning test */
1613 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1614 todo_wine
1615 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1617 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1618 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1620 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1621 todo_wine
1622 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1624 todo_wine
1625 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1626 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1628 IBindCtx_Release(bindctx);
1630 hr = IMoniker_Inverse(moniker, &inverse);
1631 ok_ole_success(hr, IMoniker_Inverse);
1632 IMoniker_Release(inverse);
1634 IMoniker_Release(moniker);
1637 static void test_pointer_moniker(void)
1639 HRESULT hr;
1640 IMoniker *moniker;
1641 DWORD moniker_type;
1642 DWORD hash;
1643 IBindCtx *bindctx;
1644 FILETIME filetime;
1645 IMoniker *inverse;
1646 IUnknown *unknown;
1647 IStream *stream;
1648 IROTData *rotdata;
1649 LPOLESTR display_name;
1651 cLocks = 0;
1653 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1654 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1656 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1657 ok_ole_success(hr, CreatePointerMoniker);
1658 if (!moniker) return;
1660 ok_more_than_one_lock();
1662 /* Display Name */
1664 hr = CreateBindCtx(0, &bindctx);
1665 ok_ole_success(hr, CreateBindCtx);
1667 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1668 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1670 IBindCtx_Release(bindctx);
1672 hr = IMoniker_IsDirty(moniker);
1673 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1675 /* IROTData::GetComparisonData test */
1677 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1678 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1680 /* Saving */
1682 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1683 ok_ole_success(hr, CreateStreamOnHGlobal);
1685 hr = IMoniker_Save(moniker, stream, TRUE);
1686 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1688 IStream_Release(stream);
1690 /* Hashing */
1691 hr = IMoniker_Hash(moniker, &hash);
1692 ok_ole_success(hr, IMoniker_Hash);
1693 ok(hash == (DWORD)&Test_ClassFactory,
1694 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1695 (DWORD)&Test_ClassFactory, hash);
1697 /* IsSystemMoniker test */
1698 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1699 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1700 ok(moniker_type == MKSYS_POINTERMONIKER,
1701 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1702 moniker_type);
1704 hr = IMoniker_Inverse(moniker, &inverse);
1705 ok_ole_success(hr, IMoniker_Inverse);
1706 IMoniker_Release(inverse);
1708 hr = CreateBindCtx(0, &bindctx);
1709 ok_ole_success(hr, CreateBindCtx);
1711 /* IsRunning test */
1712 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1713 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1715 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1716 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1718 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1719 ok_ole_success(hr, IMoniker_BindToObject);
1720 IUnknown_Release(unknown);
1722 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1723 ok_ole_success(hr, IMoniker_BindToStorage);
1724 IUnknown_Release(unknown);
1726 IMoniker_Release(moniker);
1728 ok_no_locks();
1730 hr = CreatePointerMoniker(NULL, &moniker);
1731 ok_ole_success(hr, CreatePointerMoniker);
1733 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1734 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1736 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1737 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1739 IBindCtx_Release(bindctx);
1741 IMoniker_Release(moniker);
1744 static void test_bind_context(void)
1746 HRESULT hr;
1747 IBindCtx *pBindCtx;
1748 IEnumString *pEnumString;
1749 BIND_OPTS2 bind_opts;
1750 HeapUnknown *unknown;
1751 HeapUnknown *unknown2;
1752 IUnknown *param_obj;
1753 ULONG refs;
1754 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1755 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1757 hr = CreateBindCtx(0, NULL);
1758 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1760 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1761 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1763 hr = CreateBindCtx(0, &pBindCtx);
1764 ok_ole_success(hr, "CreateBindCtx");
1766 bind_opts.cbStruct = -1;
1767 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1768 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1769 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1771 bind_opts.cbStruct = sizeof(BIND_OPTS);
1772 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1773 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1774 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1776 bind_opts.cbStruct = sizeof(bind_opts);
1777 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1778 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1779 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1780 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1781 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1782 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1783 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1784 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1785 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1786 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1787 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1789 bind_opts.cbStruct = -1;
1790 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1791 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1793 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1794 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1796 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1797 unknown->lpVtbl = &HeapUnknown_Vtbl;
1798 unknown->refs = 1;
1799 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1800 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1802 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1803 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1804 IUnknown_Release(param_obj);
1806 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1807 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1808 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1810 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1811 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1813 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1814 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1815 ok(!pEnumString, "pEnumString should be NULL\n");
1817 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1818 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1820 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1821 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1823 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1824 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1825 unknown2->refs = 1;
1826 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1827 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1829 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1830 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1832 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1833 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1835 IBindCtx_Release(pBindCtx);
1837 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1838 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1840 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1841 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1844 START_TEST(moniker)
1846 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1848 test_ROT();
1849 test_ROT_multiple_entries();
1850 test_MkParseDisplayName();
1851 test_class_moniker();
1852 test_file_monikers();
1853 test_item_moniker();
1854 test_anti_moniker();
1855 test_generic_composite_moniker();
1856 test_pointer_moniker();
1858 /* FIXME: test moniker creation funcs and parsing other moniker formats */
1860 test_bind_context();
1862 CoUninitialize();