push 88671f85dcf7a7cd89c63d6e9f34ad6b6ad2ae64
[wine/hacks.git] / dlls / ole32 / tests / moniker.c
blob3f3579ae7658ccbbcd744dd78eef29de02b2ec77
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);
661 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
662 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
663 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
665 IMoniker_Release(pMoniker);
667 IRunningObjectTable_Release(pROT);
670 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
672 if (IsEqualIID(riid, &IID_IUnknown) ||
673 IsEqualIID(riid, &IID_IParseDisplayName))
675 *ppv = iface;
676 IUnknown_AddRef(iface);
677 return S_OK;
679 *ppv = NULL;
680 return E_NOINTERFACE;
683 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
685 return 2;
688 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
690 return 1;
693 static LPCWSTR expected_display_name;
695 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
696 IBindCtx *pbc,
697 LPOLESTR pszDisplayName,
698 ULONG *pchEaten,
699 IMoniker **ppmkOut)
701 char display_nameA[256];
702 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
703 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
704 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
705 *pchEaten = lstrlenW(pszDisplayName);
706 return CreateAntiMoniker(ppmkOut);
709 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
711 ParseDisplayName_QueryInterface,
712 ParseDisplayName_AddRef,
713 ParseDisplayName_Release,
714 ParseDisplayName_ParseDisplayName
717 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
719 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
721 IMoniker * spMoniker;
722 int monCnt=0, matchCnt=0;
724 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
726 HRESULT hr;
727 WCHAR * szDisplayn;
728 monCnt++;
729 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
730 if (SUCCEEDED(hr))
732 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
733 matchCnt++;
734 CoTaskMemFree(szDisplayn);
737 trace("Total number of monikers is %i\n", monCnt);
738 return matchCnt;
741 static void test_MkParseDisplayName(void)
743 IBindCtx * pbc = NULL;
744 HRESULT hr;
745 IMoniker * pmk = NULL;
746 IMoniker * pmk1 = NULL;
747 IMoniker * pmk2 = NULL;
748 ULONG eaten;
749 int matchCnt;
750 IUnknown * object = NULL;
752 IUnknown *lpEM1;
754 IEnumMoniker *spEM1 = NULL;
755 IEnumMoniker *spEM2 = NULL;
756 IEnumMoniker *spEM3 = NULL;
758 DWORD pdwReg1=0;
759 DWORD grflags=0;
760 DWORD pdwReg2=0;
761 DWORD moniker_type;
762 IRunningObjectTable * pprot=NULL;
764 /* CLSID of My Computer */
765 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
766 '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};
767 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
768 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
769 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
770 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
771 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
772 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
773 char szDisplayNameFile[256];
774 WCHAR wszDisplayNameFile[256];
776 hr = CreateBindCtx(0, &pbc);
777 ok_ole_success(hr, CreateBindCtx);
779 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
780 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
781 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
783 /* no special handling of "clsid:" without the string form of the clsid
784 * following */
785 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
786 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
787 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
789 /* shows clsid has higher precedence than a running object */
790 hr = CreateFileMoniker(wszDisplayName, &pmk);
791 ok_ole_success(hr, CreateFileMoniker);
792 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
793 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
794 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
795 ok_ole_success(hr, IRunningObjectTable_Register);
796 IMoniker_Release(pmk);
797 pmk = NULL;
798 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
799 ok_ole_success(hr, MkParseDisplayName);
800 if (pmk)
802 IMoniker_IsSystemMoniker(pmk, &moniker_type);
803 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
804 IMoniker_Release(pmk);
806 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
807 ok_ole_success(hr, IRunningObjectTable_Revoke);
808 IRunningObjectTable_Release(pprot);
810 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
811 ok_ole_success(hr, CreateFileMoniker);
812 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
813 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
814 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
815 ok_ole_success(hr, IRunningObjectTable_Register);
816 IMoniker_Release(pmk);
817 pmk = NULL;
818 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
819 ok_ole_success(hr, MkParseDisplayName);
820 if (pmk)
822 IMoniker_IsSystemMoniker(pmk, &moniker_type);
823 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
824 IMoniker_Release(pmk);
826 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
827 ok_ole_success(hr, IRunningObjectTable_Revoke);
828 IRunningObjectTable_Release(pprot);
830 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
831 ok_ole_success(hr, CoRegisterClassObject);
833 expected_display_name = wszDisplayNameProgId1;
834 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
835 ok_ole_success(hr, MkParseDisplayName);
836 if (pmk)
838 IMoniker_IsSystemMoniker(pmk, &moniker_type);
839 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
840 IMoniker_Release(pmk);
843 expected_display_name = wszDisplayNameProgId2;
844 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
845 ok_ole_success(hr, MkParseDisplayName);
846 if (pmk)
848 IMoniker_IsSystemMoniker(pmk, &moniker_type);
849 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
850 IMoniker_Release(pmk);
853 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
854 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
855 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
857 hr = CoRevokeClassObject(pdwReg1);
858 ok_ole_success(hr, CoRevokeClassObject);
860 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
861 strcat(szDisplayNameFile, "\\kernel32.dll");
862 MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
863 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &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);
872 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
873 ok_ole_success(hr, MkParseDisplayName);
875 if (pmk)
877 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
878 ok_ole_success(hr, IMoniker_BindToObject);
880 IUnknown_Release(object);
881 IMoniker_Release(pmk);
883 IBindCtx_Release(pbc);
885 /* Test the EnumMoniker interface */
886 hr = CreateBindCtx(0, &pbc);
887 ok_ole_success(hr, CreateBindCtx);
889 hr = CreateFileMoniker(wszFileName1, &pmk1);
890 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
891 hr = CreateFileMoniker(wszFileName2, &pmk2);
892 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
893 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
894 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
896 /* Check EnumMoniker before registering */
897 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
898 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
899 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
900 /* Register a couple of Monikers and check is ok */
901 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
902 hr = MK_E_NOOBJECT;
904 matchCnt = count_moniker_matches(pbc, spEM1);
905 trace("Number of matches is %i\n", matchCnt);
907 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
908 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
909 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
910 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
912 trace("IROT::Register\n");
913 grflags=0;
914 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
915 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
916 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
917 pprot, grflags, lpEM1, pmk2, pdwReg2);
919 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
920 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
922 matchCnt = count_moniker_matches(pbc, spEM2);
923 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
925 trace("IEnumMoniker::Clone\n");
926 IEnumMoniker_Clone(spEM2, &spEM3);
928 matchCnt = count_moniker_matches(pbc, spEM3);
929 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
930 trace("IEnumMoniker::Reset\n");
931 IEnumMoniker_Reset(spEM3);
933 matchCnt = count_moniker_matches(pbc, spEM3);
934 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
936 IRunningObjectTable_Revoke(pprot,pdwReg1);
937 IRunningObjectTable_Revoke(pprot,pdwReg2);
938 IUnknown_Release(lpEM1);
939 IEnumMoniker_Release(spEM1);
940 IEnumMoniker_Release(spEM2);
941 IEnumMoniker_Release(spEM3);
942 IMoniker_Release(pmk1);
943 IMoniker_Release(pmk2);
944 IRunningObjectTable_Release(pprot);
946 IBindCtx_Release(pbc);
949 static const LARGE_INTEGER llZero;
951 static const BYTE expected_class_moniker_marshal_data[] =
953 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
954 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
955 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
956 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
957 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
958 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
959 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
960 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
961 0x00,0x00,0x00,0x00,
964 static const BYTE expected_class_moniker_saved_data[] =
966 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
967 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
968 0x00,0x00,0x00,0x00,
971 static const BYTE expected_class_moniker_comparison_data[] =
973 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
974 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
975 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
976 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
979 static const WCHAR expected_class_moniker_display_name[] =
981 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
982 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
983 '0','0','0','0','4','6',':',0
986 static const BYTE expected_item_moniker_comparison_data[] =
988 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
989 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
990 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
991 0x54,0x00,0x00,0x00,
994 static const BYTE expected_item_moniker_saved_data[] =
996 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
997 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1000 static const BYTE expected_item_moniker_marshal_data[] =
1002 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1003 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1004 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1005 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1006 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1007 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1008 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1009 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1012 static const BYTE expected_anti_moniker_marshal_data[] =
1014 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1015 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1016 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1017 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1018 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1019 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1020 0x01,0x00,0x00,0x00,
1023 static const BYTE expected_anti_moniker_saved_data[] =
1025 0x01,0x00,0x00,0x00,
1028 static const BYTE expected_anti_moniker_comparison_data[] =
1030 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1031 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1032 0x01,0x00,0x00,0x00,
1035 static const BYTE expected_gc_moniker_marshal_data[] =
1037 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1038 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1039 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1040 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1041 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1042 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1043 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1044 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1045 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1046 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1047 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1048 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1049 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1050 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1051 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1052 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1053 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1054 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1055 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1056 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1057 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1058 0x00,0x57,0x69,0x6e,0x65,0x00,
1061 static const BYTE expected_gc_moniker_saved_data[] =
1063 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1064 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1065 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1066 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1067 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1068 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1069 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1070 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1071 0x65,0x00,
1074 static const BYTE expected_gc_moniker_comparison_data[] =
1076 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1077 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1078 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1079 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1080 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1081 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1082 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1083 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1084 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1087 static void test_moniker(
1088 const char *testname, IMoniker *moniker,
1089 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1090 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1091 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1092 LPCWSTR expected_display_name)
1094 IStream * stream;
1095 IROTData * rotdata;
1096 HRESULT hr;
1097 HGLOBAL hglobal;
1098 LPBYTE moniker_data;
1099 DWORD moniker_size;
1100 DWORD i;
1101 BOOL same = TRUE;
1102 BYTE buffer[128];
1103 IMoniker * moniker_proxy;
1104 LPOLESTR display_name;
1105 IBindCtx *bindctx;
1107 hr = IMoniker_IsDirty(moniker);
1108 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1110 /* Display Name */
1112 hr = CreateBindCtx(0, &bindctx);
1113 ok_ole_success(hr, CreateBindCtx);
1115 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1116 ok_ole_success(hr, IMoniker_GetDisplayName);
1117 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1119 CoTaskMemFree(display_name);
1120 IBindCtx_Release(bindctx);
1122 hr = IMoniker_IsDirty(moniker);
1123 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1125 /* IROTData::GetComparisonData test */
1127 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1128 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1130 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1131 ok_ole_success(hr, IROTData_GetComparisonData);
1133 if (hr != S_OK) moniker_size = 0;
1135 /* first check we have the right amount of data */
1136 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1137 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1138 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1140 /* then do a byte-by-byte comparison */
1141 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1143 if (expected_moniker_comparison_data[i] != buffer[i])
1145 same = FALSE;
1146 break;
1150 ok(same, "%s: Comparison data differs\n", testname);
1151 if (!same)
1153 for (i = 0; i < moniker_size; i++)
1155 if (i % 8 == 0) printf(" ");
1156 printf("0x%02x,", buffer[i]);
1157 if (i % 8 == 7) printf("\n");
1159 printf("\n");
1162 IROTData_Release(rotdata);
1164 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1166 /* Saving */
1168 hr = IMoniker_Save(moniker, stream, TRUE);
1169 ok_ole_success(hr, IMoniker_Save);
1171 hr = GetHGlobalFromStream(stream, &hglobal);
1172 ok_ole_success(hr, GetHGlobalFromStream);
1174 moniker_size = GlobalSize(hglobal);
1176 moniker_data = GlobalLock(hglobal);
1178 /* first check we have the right amount of data */
1179 ok(moniker_size == sizeof_expected_moniker_saved_data,
1180 "%s: Size of saved data differs (expected %d, actual %d)\n",
1181 testname, sizeof_expected_moniker_saved_data, moniker_size);
1183 /* then do a byte-by-byte comparison */
1184 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
1186 if (expected_moniker_saved_data[i] != moniker_data[i])
1188 same = FALSE;
1189 break;
1193 ok(same, "%s: Saved data differs\n", testname);
1194 if (!same)
1196 for (i = 0; i < moniker_size; i++)
1198 if (i % 8 == 0) printf(" ");
1199 printf("0x%02x,", moniker_data[i]);
1200 if (i % 8 == 7) printf("\n");
1202 printf("\n");
1205 GlobalUnlock(hglobal);
1207 IStream_Release(stream);
1209 /* Marshaling tests */
1211 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1212 ok_ole_success(hr, CreateStreamOnHGlobal);
1214 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1215 ok_ole_success(hr, CoMarshalInterface);
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 == sizeof_expected_moniker_marshal_data,
1226 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1227 testname, sizeof_expected_moniker_marshal_data, moniker_size);
1229 /* then do a byte-by-byte comparison */
1230 if (expected_moniker_marshal_data)
1232 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1234 if (expected_moniker_marshal_data[i] != moniker_data[i])
1236 same = FALSE;
1237 break;
1242 ok(same, "%s: Marshaled data differs\n", testname);
1243 if (!same)
1245 for (i = 0; i < moniker_size; i++)
1247 if (i % 8 == 0) printf(" ");
1248 printf("0x%02x,", moniker_data[i]);
1249 if (i % 8 == 7) printf("\n");
1251 printf("\n");
1254 GlobalUnlock(hglobal);
1256 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1257 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1258 ok_ole_success(hr, CoUnmarshalInterface);
1260 IStream_Release(stream);
1261 IMoniker_Release(moniker_proxy);
1264 static void test_class_moniker(void)
1266 HRESULT hr;
1267 IMoniker *moniker;
1268 DWORD moniker_type;
1269 DWORD hash;
1270 IBindCtx *bindctx;
1271 IMoniker *inverse;
1272 IUnknown *unknown;
1273 FILETIME filetime;
1275 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1276 ok_ole_success(hr, CreateClassMoniker);
1277 if (!moniker) return;
1279 test_moniker("class moniker", moniker,
1280 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1281 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1282 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1283 expected_class_moniker_display_name);
1285 /* Hashing */
1287 hr = IMoniker_Hash(moniker, &hash);
1288 ok_ole_success(hr, IMoniker_Hash);
1290 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1291 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1292 hash);
1294 /* IsSystemMoniker test */
1296 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1297 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1299 ok(moniker_type == MKSYS_CLASSMONIKER,
1300 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1301 moniker_type);
1303 hr = CreateBindCtx(0, &bindctx);
1304 ok_ole_success(hr, CreateBindCtx);
1306 /* IsRunning test */
1307 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1308 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1310 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1311 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1313 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1314 ok_ole_success(hr, IMoniker_BindToObject);
1315 IUnknown_Release(unknown);
1317 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1318 ok_ole_success(hr, IMoniker_BindToStorage);
1319 IUnknown_Release(unknown);
1321 IBindCtx_Release(bindctx);
1323 hr = IMoniker_Inverse(moniker, &inverse);
1324 ok_ole_success(hr, IMoniker_Inverse);
1325 IMoniker_Release(inverse);
1327 IMoniker_Release(moniker);
1330 static void test_file_moniker(WCHAR* path)
1332 IStream *stream;
1333 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1334 HRESULT hr;
1336 hr = CreateFileMoniker(path, &moniker1);
1337 ok_ole_success(hr, CreateFileMoniker);
1339 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1341 /* Marshal */
1342 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1343 ok_ole_success(hr, CoMarshalInterface);
1345 /* Rewind */
1346 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1347 ok_ole_success(hr, IStream_Seek);
1349 /* Unmarshal */
1350 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1351 ok_ole_success(hr, CoUnmarshalInterface);
1353 hr = IMoniker_IsEqual(moniker1, moniker2);
1354 ok_ole_success(hr, IsEqual);
1356 IStream_Release(stream);
1357 if (moniker1)
1358 IMoniker_Release(moniker1);
1359 if (moniker2)
1360 IMoniker_Release(moniker2);
1363 static void test_file_monikers(void)
1365 static WCHAR wszFile[][30] = {
1366 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1367 {'\\', '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},
1368 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1369 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1370 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1371 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1372 * U+0100 .. = Latin extended-A
1374 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1377 int i;
1379 trace("ACP is %u\n", GetACP());
1381 for (i = 0; i < COUNTOF(wszFile); ++i)
1383 int j ;
1384 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1386 wszFile[i][j] = 0;
1387 test_file_moniker(wszFile[i]);
1392 static void test_item_moniker(void)
1394 HRESULT hr;
1395 IMoniker *moniker;
1396 DWORD moniker_type;
1397 DWORD hash;
1398 IBindCtx *bindctx;
1399 IMoniker *inverse;
1400 IUnknown *unknown;
1401 static const WCHAR wszDelimeter[] = {'!',0};
1402 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1403 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1405 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1406 ok_ole_success(hr, CreateItemMoniker);
1408 test_moniker("item moniker", moniker,
1409 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1410 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1411 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1412 expected_display_name);
1414 /* Hashing */
1416 hr = IMoniker_Hash(moniker, &hash);
1417 ok_ole_success(hr, IMoniker_Hash);
1419 ok(hash == 0x73c,
1420 "Hash value != 0x73c, instead was 0x%08x\n",
1421 hash);
1423 /* IsSystemMoniker test */
1425 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1426 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1428 ok(moniker_type == MKSYS_ITEMMONIKER,
1429 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1430 moniker_type);
1432 hr = CreateBindCtx(0, &bindctx);
1433 ok_ole_success(hr, CreateBindCtx);
1435 /* IsRunning test */
1436 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1437 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1439 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1440 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1442 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1443 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1445 IBindCtx_Release(bindctx);
1447 hr = IMoniker_Inverse(moniker, &inverse);
1448 ok_ole_success(hr, IMoniker_Inverse);
1449 IMoniker_Release(inverse);
1451 IMoniker_Release(moniker);
1454 static void test_anti_moniker(void)
1456 HRESULT hr;
1457 IMoniker *moniker;
1458 DWORD moniker_type;
1459 DWORD hash;
1460 IBindCtx *bindctx;
1461 FILETIME filetime;
1462 IMoniker *inverse;
1463 IUnknown *unknown;
1464 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1466 hr = CreateAntiMoniker(&moniker);
1467 ok_ole_success(hr, CreateAntiMoniker);
1468 if (!moniker) return;
1470 test_moniker("anti moniker", moniker,
1471 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1472 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1473 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1474 expected_display_name);
1476 /* Hashing */
1477 hr = IMoniker_Hash(moniker, &hash);
1478 ok_ole_success(hr, IMoniker_Hash);
1479 ok(hash == 0x80000001,
1480 "Hash value != 0x80000001, instead was 0x%08x\n",
1481 hash);
1483 /* IsSystemMoniker test */
1484 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1485 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1486 ok(moniker_type == MKSYS_ANTIMONIKER,
1487 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1488 moniker_type);
1490 hr = IMoniker_Inverse(moniker, &inverse);
1491 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1492 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1494 hr = CreateBindCtx(0, &bindctx);
1495 ok_ole_success(hr, CreateBindCtx);
1497 /* IsRunning test */
1498 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1499 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1501 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1502 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1504 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1505 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1507 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1508 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1510 IBindCtx_Release(bindctx);
1512 IMoniker_Release(moniker);
1515 static void test_generic_composite_moniker(void)
1517 HRESULT hr;
1518 IMoniker *moniker;
1519 IMoniker *moniker1;
1520 IMoniker *moniker2;
1521 DWORD moniker_type;
1522 DWORD hash;
1523 IBindCtx *bindctx;
1524 FILETIME filetime;
1525 IMoniker *inverse;
1526 IUnknown *unknown;
1527 static const WCHAR wszDelimeter1[] = {'!',0};
1528 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1529 static const WCHAR wszDelimeter2[] = {'#',0};
1530 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1531 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1533 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1534 ok_ole_success(hr, CreateItemMoniker);
1535 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1536 ok_ole_success(hr, CreateItemMoniker);
1537 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1538 ok_ole_success(hr, CreateGenericComposite);
1540 test_moniker("generic composite moniker", moniker,
1541 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1542 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1543 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1544 expected_display_name);
1546 /* Hashing */
1548 hr = IMoniker_Hash(moniker, &hash);
1549 ok_ole_success(hr, IMoniker_Hash);
1551 ok(hash == 0xd87,
1552 "Hash value != 0xd87, instead was 0x%08x\n",
1553 hash);
1555 /* IsSystemMoniker test */
1557 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1558 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1560 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1561 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1562 moniker_type);
1564 hr = CreateBindCtx(0, &bindctx);
1565 ok_ole_success(hr, CreateBindCtx);
1567 /* IsRunning test */
1568 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1569 todo_wine
1570 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1572 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1573 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1575 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1576 todo_wine
1577 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1579 todo_wine
1580 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1581 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1583 IBindCtx_Release(bindctx);
1585 hr = IMoniker_Inverse(moniker, &inverse);
1586 ok_ole_success(hr, IMoniker_Inverse);
1587 IMoniker_Release(inverse);
1589 IMoniker_Release(moniker);
1592 static void test_pointer_moniker(void)
1594 HRESULT hr;
1595 IMoniker *moniker;
1596 DWORD moniker_type;
1597 DWORD hash;
1598 IBindCtx *bindctx;
1599 FILETIME filetime;
1600 IMoniker *inverse;
1601 IUnknown *unknown;
1602 IStream *stream;
1603 IROTData *rotdata;
1604 LPOLESTR display_name;
1606 cLocks = 0;
1608 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1609 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1611 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1612 ok_ole_success(hr, CreatePointerMoniker);
1613 if (!moniker) return;
1615 ok_more_than_one_lock();
1617 /* Display Name */
1619 hr = CreateBindCtx(0, &bindctx);
1620 ok_ole_success(hr, CreateBindCtx);
1622 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1623 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1625 IBindCtx_Release(bindctx);
1627 hr = IMoniker_IsDirty(moniker);
1628 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1630 /* IROTData::GetComparisonData test */
1632 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1633 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1635 /* Saving */
1637 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1638 ok_ole_success(hr, CreateStreamOnHGlobal);
1640 hr = IMoniker_Save(moniker, stream, TRUE);
1641 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1643 IStream_Release(stream);
1645 /* Hashing */
1646 hr = IMoniker_Hash(moniker, &hash);
1647 ok_ole_success(hr, IMoniker_Hash);
1648 ok(hash == (DWORD)&Test_ClassFactory,
1649 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1650 (DWORD)&Test_ClassFactory, hash);
1652 /* IsSystemMoniker test */
1653 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1654 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1655 ok(moniker_type == MKSYS_POINTERMONIKER,
1656 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1657 moniker_type);
1659 hr = IMoniker_Inverse(moniker, &inverse);
1660 ok_ole_success(hr, IMoniker_Inverse);
1661 IMoniker_Release(inverse);
1663 hr = CreateBindCtx(0, &bindctx);
1664 ok_ole_success(hr, CreateBindCtx);
1666 /* IsRunning test */
1667 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1668 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1670 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1671 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1673 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1674 ok_ole_success(hr, IMoniker_BindToObject);
1675 IUnknown_Release(unknown);
1677 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1678 ok_ole_success(hr, IMoniker_BindToStorage);
1679 IUnknown_Release(unknown);
1681 IMoniker_Release(moniker);
1683 ok_no_locks();
1685 hr = CreatePointerMoniker(NULL, &moniker);
1686 ok_ole_success(hr, CreatePointerMoniker);
1688 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1689 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1691 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1692 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1694 IBindCtx_Release(bindctx);
1696 IMoniker_Release(moniker);
1699 static void test_bind_context(void)
1701 HRESULT hr;
1702 IBindCtx *pBindCtx;
1703 IEnumString *pEnumString;
1704 BIND_OPTS2 bind_opts;
1705 HeapUnknown *unknown;
1706 HeapUnknown *unknown2;
1707 IUnknown *param_obj;
1708 ULONG refs;
1709 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1710 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1712 hr = CreateBindCtx(0, NULL);
1713 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1715 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1716 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1718 hr = CreateBindCtx(0, &pBindCtx);
1719 ok_ole_success(hr, "CreateBindCtx");
1721 bind_opts.cbStruct = -1;
1722 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1723 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1724 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1726 bind_opts.cbStruct = sizeof(BIND_OPTS);
1727 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1728 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1729 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1731 bind_opts.cbStruct = sizeof(bind_opts);
1732 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1733 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1734 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1735 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1736 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1737 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1738 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1739 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1740 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1741 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1742 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1744 bind_opts.cbStruct = -1;
1745 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1746 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1748 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1749 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1751 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1752 unknown->lpVtbl = &HeapUnknown_Vtbl;
1753 unknown->refs = 1;
1754 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1755 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1757 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1758 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1759 IUnknown_Release(param_obj);
1761 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1762 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1763 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1765 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1766 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1768 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1769 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1770 ok(!pEnumString, "pEnumString should be NULL\n");
1772 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1773 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1775 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1776 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1778 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1779 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1780 unknown2->refs = 1;
1781 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1782 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1784 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1785 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1787 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1788 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1790 IBindCtx_Release(pBindCtx);
1792 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1793 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1795 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1796 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1799 START_TEST(moniker)
1801 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1803 test_ROT();
1804 test_MkParseDisplayName();
1805 test_class_moniker();
1806 test_file_monikers();
1807 test_item_moniker();
1808 test_anti_moniker();
1809 test_generic_composite_moniker();
1810 test_pointer_moniker();
1812 /* FIXME: test moniker creation funcs and parsing other moniker formats */
1814 test_bind_context();
1816 CoUninitialize();