user32: Flush window surfaces in all functions that are used to poll for input.
[wine.git] / dlls / ole32 / tests / moniker.c
blob2e5a6034e051c2d26a17d890efb3abf0cd32da55
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 "ocidl.h"
32 #include "initguid.h"
33 #include "comcat.h"
34 #include "olectl.h"
36 #include "wine/test.h"
38 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
41 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
43 #define CHECK_EXPECTED_METHOD(method_name) \
44 do { \
45 trace("%s\n", method_name); \
46 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
47 if (*expected_method_list) \
48 { \
49 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
50 *expected_method_list, method_name); \
51 expected_method_list++; \
52 } \
53 } while(0)
55 static char const * const *expected_method_list;
56 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
57 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
59 static const CLSID CLSID_WineTest =
60 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
61 0x9474ba1a,
62 0x258b,
63 0x490b,
64 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
67 static const CLSID CLSID_TestMoniker =
68 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
69 0xb306bfbc,
70 0x496e,
71 0x4f53,
72 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
75 static LONG cLocks;
77 static void LockModule(void)
79 InterlockedIncrement(&cLocks);
82 static void UnlockModule(void)
84 InterlockedDecrement(&cLocks);
87 static SIZE_T round_global_size(SIZE_T size)
89 static SIZE_T global_size_alignment = -1;
90 if (global_size_alignment == -1)
92 void *p = GlobalAlloc(GMEM_FIXED, 1);
93 global_size_alignment = GlobalSize(p);
94 GlobalFree(p);
97 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
100 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
101 LPCLASSFACTORY iface,
102 REFIID riid,
103 LPVOID *ppvObj)
105 if (ppvObj == NULL) return E_POINTER;
107 if (IsEqualGUID(riid, &IID_IUnknown) ||
108 IsEqualGUID(riid, &IID_IClassFactory))
110 *ppvObj = iface;
111 IClassFactory_AddRef(iface);
112 return S_OK;
115 *ppvObj = NULL;
116 return E_NOINTERFACE;
119 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
121 LockModule();
122 return 2; /* non-heap-based object */
125 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
127 UnlockModule();
128 return 1; /* non-heap-based object */
131 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
132 LPCLASSFACTORY iface,
133 LPUNKNOWN pUnkOuter,
134 REFIID riid,
135 LPVOID *ppvObj)
137 return E_NOTIMPL;
140 static HRESULT WINAPI Test_IClassFactory_LockServer(
141 LPCLASSFACTORY iface,
142 BOOL fLock)
144 return S_OK;
147 static const IClassFactoryVtbl TestClassFactory_Vtbl =
149 Test_IClassFactory_QueryInterface,
150 Test_IClassFactory_AddRef,
151 Test_IClassFactory_Release,
152 Test_IClassFactory_CreateInstance,
153 Test_IClassFactory_LockServer
156 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
158 typedef struct
160 IUnknown IUnknown_iface;
161 ULONG refs;
162 } HeapUnknown;
164 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
166 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
169 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
171 if (IsEqualIID(riid, &IID_IUnknown))
173 IUnknown_AddRef(iface);
174 *ppv = iface;
175 return S_OK;
177 *ppv = NULL;
178 return E_NOINTERFACE;
181 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
183 HeapUnknown *This = impl_from_IUnknown(iface);
184 return InterlockedIncrement((LONG*)&This->refs);
187 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
189 HeapUnknown *This = impl_from_IUnknown(iface);
190 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
191 if (!refs) HeapFree(GetProcessHeap(), 0, This);
192 return refs;
195 static const IUnknownVtbl HeapUnknown_Vtbl =
197 HeapUnknown_QueryInterface,
198 HeapUnknown_AddRef,
199 HeapUnknown_Release
202 static HRESULT WINAPI
203 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
205 if (!ppvObject)
206 return E_INVALIDARG;
208 *ppvObject = 0;
210 if (IsEqualIID(&IID_IUnknown, riid) ||
211 IsEqualIID(&IID_IPersist, riid) ||
212 IsEqualIID(&IID_IPersistStream,riid) ||
213 IsEqualIID(&IID_IMoniker, riid))
214 *ppvObject = iface;
215 if (IsEqualIID(&IID_IROTData, riid))
216 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
218 if ((*ppvObject)==0)
219 return E_NOINTERFACE;
221 IMoniker_AddRef(iface);
223 return S_OK;
226 static ULONG WINAPI
227 Moniker_AddRef(IMoniker* iface)
229 return 2;
232 static ULONG WINAPI
233 Moniker_Release(IMoniker* iface)
235 return 1;
238 static HRESULT WINAPI
239 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
241 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
243 *pClassID = CLSID_TestMoniker;
245 return S_OK;
248 static HRESULT WINAPI
249 Moniker_IsDirty(IMoniker* iface)
251 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
253 return S_FALSE;
256 static HRESULT WINAPI
257 Moniker_Load(IMoniker* iface, IStream* pStm)
259 CHECK_EXPECTED_METHOD("Moniker_Load");
260 return E_NOTIMPL;
263 static HRESULT WINAPI
264 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
266 CHECK_EXPECTED_METHOD("Moniker_Save");
267 return E_NOTIMPL;
270 static HRESULT WINAPI
271 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
273 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
274 return E_NOTIMPL;
277 static HRESULT WINAPI
278 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
279 REFIID riid, VOID** ppvResult)
281 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
282 return E_NOTIMPL;
285 static HRESULT WINAPI
286 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
287 REFIID riid, VOID** ppvObject)
289 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
290 return E_NOTIMPL;
293 static HRESULT WINAPI
294 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
295 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
297 CHECK_EXPECTED_METHOD("Moniker_Reduce");
299 if (ppmkReduced==NULL)
300 return E_POINTER;
302 IMoniker_AddRef(iface);
304 *ppmkReduced=iface;
306 return MK_S_REDUCED_TO_SELF;
309 static HRESULT WINAPI
310 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
311 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
313 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
314 return E_NOTIMPL;
317 static HRESULT WINAPI
318 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
320 CHECK_EXPECTED_METHOD("Moniker_Enum");
322 if (ppenumMoniker == NULL)
323 return E_POINTER;
325 *ppenumMoniker = NULL;
327 return S_OK;
330 static HRESULT WINAPI
331 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
333 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
334 return E_NOTIMPL;
337 static HRESULT WINAPI
338 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
340 CHECK_EXPECTED_METHOD("Moniker_Hash");
341 return E_NOTIMPL;
344 static HRESULT WINAPI
345 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
346 IMoniker* pmkNewlyRunning)
348 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
349 return E_NOTIMPL;
352 static HRESULT WINAPI
353 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
354 IMoniker* pmkToLeft, FILETIME* pFileTime)
356 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
357 return E_NOTIMPL;
360 static HRESULT WINAPI
361 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
363 CHECK_EXPECTED_METHOD("Moniker_Inverse");
364 return E_NOTIMPL;
367 static HRESULT WINAPI
368 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
370 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
371 return E_NOTIMPL;
374 static HRESULT WINAPI
375 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
377 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
378 return E_NOTIMPL;
381 static HRESULT WINAPI
382 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
383 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
385 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
386 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
387 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
388 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
389 return S_OK;
392 static HRESULT WINAPI
393 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
394 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
396 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
397 return E_NOTIMPL;
400 static HRESULT WINAPI
401 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
403 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
405 if (!pwdMksys)
406 return E_POINTER;
408 (*pwdMksys)=MKSYS_NONE;
410 return S_FALSE;
413 static const IMonikerVtbl MonikerNoROTDataVtbl =
415 MonikerNoROTData_QueryInterface,
416 Moniker_AddRef,
417 Moniker_Release,
418 Moniker_GetClassID,
419 Moniker_IsDirty,
420 Moniker_Load,
421 Moniker_Save,
422 Moniker_GetSizeMax,
423 Moniker_BindToObject,
424 Moniker_BindToStorage,
425 Moniker_Reduce,
426 Moniker_ComposeWith,
427 Moniker_Enum,
428 Moniker_IsEqual,
429 Moniker_Hash,
430 Moniker_IsRunning,
431 Moniker_GetTimeOfLastChange,
432 Moniker_Inverse,
433 Moniker_CommonPrefixWith,
434 Moniker_RelativePathTo,
435 Moniker_GetDisplayName,
436 Moniker_ParseDisplayName,
437 Moniker_IsSystemMoniker
440 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
442 static IMoniker Moniker;
444 static HRESULT WINAPI
445 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
447 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
450 static ULONG WINAPI
451 ROTData_AddRef(IROTData *iface)
453 return 2;
456 static ULONG WINAPI
457 ROTData_Release(IROTData* iface)
459 return 1;
462 static HRESULT WINAPI
463 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
464 ULONG cbMax, ULONG* pcbData)
466 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
468 *pcbData = 1;
469 if (cbMax < *pcbData)
470 return E_OUTOFMEMORY;
472 *pbData = 0xde;
474 return S_OK;
477 static IROTDataVtbl ROTDataVtbl =
479 ROTData_QueryInterface,
480 ROTData_AddRef,
481 ROTData_Release,
482 ROTData_GetComparisonData
485 static IROTData ROTData = { &ROTDataVtbl };
487 static HRESULT WINAPI
488 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
490 if (!ppvObject)
491 return E_INVALIDARG;
493 *ppvObject = 0;
495 if (IsEqualIID(&IID_IUnknown, riid) ||
496 IsEqualIID(&IID_IPersist, riid) ||
497 IsEqualIID(&IID_IPersistStream,riid) ||
498 IsEqualIID(&IID_IMoniker, riid))
499 *ppvObject = iface;
500 if (IsEqualIID(&IID_IROTData, riid))
502 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
503 *ppvObject = &ROTData;
506 if ((*ppvObject)==0)
507 return E_NOINTERFACE;
509 IMoniker_AddRef(iface);
511 return S_OK;
514 static const IMonikerVtbl MonikerVtbl =
516 Moniker_QueryInterface,
517 Moniker_AddRef,
518 Moniker_Release,
519 Moniker_GetClassID,
520 Moniker_IsDirty,
521 Moniker_Load,
522 Moniker_Save,
523 Moniker_GetSizeMax,
524 Moniker_BindToObject,
525 Moniker_BindToStorage,
526 Moniker_Reduce,
527 Moniker_ComposeWith,
528 Moniker_Enum,
529 Moniker_IsEqual,
530 Moniker_Hash,
531 Moniker_IsRunning,
532 Moniker_GetTimeOfLastChange,
533 Moniker_Inverse,
534 Moniker_CommonPrefixWith,
535 Moniker_RelativePathTo,
536 Moniker_GetDisplayName,
537 Moniker_ParseDisplayName,
538 Moniker_IsSystemMoniker
541 static IMoniker Moniker = { &MonikerVtbl };
543 static void test_ROT(void)
545 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
546 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
547 '2','0','4','6','E','5','8','6','C','9','2','5',0};
548 HRESULT hr;
549 IMoniker *pMoniker = NULL;
550 IRunningObjectTable *pROT = NULL;
551 DWORD dwCookie;
552 static const char *methods_register_no_ROTData[] =
554 "Moniker_Reduce",
555 "Moniker_GetTimeOfLastChange",
556 "Moniker_QueryInterface(IID_IROTData)",
557 "Moniker_GetDisplayName",
558 "Moniker_GetClassID",
559 NULL
561 static const char *methods_register[] =
563 "Moniker_Reduce",
564 "Moniker_GetTimeOfLastChange",
565 "Moniker_QueryInterface(IID_IROTData)",
566 "ROTData_GetComparisonData",
567 NULL
569 static const char *methods_isrunning_no_ROTData[] =
571 "Moniker_Reduce",
572 "Moniker_QueryInterface(IID_IROTData)",
573 "Moniker_GetDisplayName",
574 "Moniker_GetClassID",
575 NULL
577 static const char *methods_isrunning[] =
579 "Moniker_Reduce",
580 "Moniker_QueryInterface(IID_IROTData)",
581 "ROTData_GetComparisonData",
582 NULL
585 cLocks = 0;
587 hr = GetRunningObjectTable(0, &pROT);
588 ok_ole_success(hr, GetRunningObjectTable);
590 expected_method_list = methods_register_no_ROTData;
591 /* try with our own moniker that doesn't support IROTData */
592 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
593 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
594 ok_ole_success(hr, IRunningObjectTable_Register);
595 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
597 ok_more_than_one_lock();
599 expected_method_list = methods_isrunning_no_ROTData;
600 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
601 ok_ole_success(hr, IRunningObjectTable_IsRunning);
602 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
604 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
605 ok_ole_success(hr, IRunningObjectTable_Revoke);
607 ok_no_locks();
609 expected_method_list = methods_register;
610 /* try with our own moniker */
611 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
612 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
613 ok_ole_success(hr, IRunningObjectTable_Register);
614 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
616 ok_more_than_one_lock();
618 expected_method_list = methods_isrunning;
619 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
620 ok_ole_success(hr, IRunningObjectTable_IsRunning);
621 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
623 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
624 ok_ole_success(hr, IRunningObjectTable_Revoke);
626 ok_no_locks();
628 hr = CreateFileMoniker(wszFileName, &pMoniker);
629 ok_ole_success(hr, CreateClassMoniker);
631 /* test flags: 0 */
632 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
633 pMoniker, &dwCookie);
634 ok_ole_success(hr, IRunningObjectTable_Register);
636 ok_more_than_one_lock();
638 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
639 ok_ole_success(hr, IRunningObjectTable_Revoke);
641 ok_no_locks();
643 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
644 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
645 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
646 ok_ole_success(hr, IRunningObjectTable_Register);
648 ok_more_than_one_lock();
650 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
651 ok_ole_success(hr, IRunningObjectTable_Revoke);
653 ok_no_locks();
655 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
656 /* only succeeds when process is started by SCM and has LocalService
657 * or RunAs AppId values */
658 hr = IRunningObjectTable_Register(pROT,
659 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
660 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
661 todo_wine {
662 ok(hr == CO_E_WRONG_SERVER_IDENTITY ||
663 broken(hr == S_OK) /* Win9x */,
664 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
666 if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie);
668 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
669 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
670 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
672 IMoniker_Release(pMoniker);
674 IRunningObjectTable_Release(pROT);
677 static void test_ROT_multiple_entries(void)
679 HRESULT hr;
680 IMoniker *pMoniker = NULL;
681 IRunningObjectTable *pROT = NULL;
682 DWORD dwCookie1, dwCookie2;
683 IUnknown *pObject = NULL;
684 static const WCHAR moniker_path[] =
685 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
687 hr = GetRunningObjectTable(0, &pROT);
688 ok_ole_success(hr, GetRunningObjectTable);
690 hr = CreateFileMoniker(moniker_path, &pMoniker);
691 ok_ole_success(hr, CreateFileMoniker);
693 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
694 ok_ole_success(hr, IRunningObjectTable_Register);
696 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
697 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
699 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
701 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
702 ok_ole_success(hr, IRunningObjectTable_GetObject);
703 IUnknown_Release(pObject);
705 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
706 ok_ole_success(hr, IRunningObjectTable_Revoke);
708 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
709 ok_ole_success(hr, IRunningObjectTable_GetObject);
710 IUnknown_Release(pObject);
712 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
713 ok_ole_success(hr, IRunningObjectTable_Revoke);
715 IMoniker_Release(pMoniker);
717 IRunningObjectTable_Release(pROT);
720 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
722 if (IsEqualIID(riid, &IID_IUnknown) ||
723 IsEqualIID(riid, &IID_IParseDisplayName))
725 *ppv = iface;
726 IParseDisplayName_AddRef(iface);
727 return S_OK;
729 *ppv = NULL;
730 return E_NOINTERFACE;
733 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
735 return 2;
738 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
740 return 1;
743 static LPCWSTR expected_display_name;
745 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
746 IBindCtx *pbc,
747 LPOLESTR pszDisplayName,
748 ULONG *pchEaten,
749 IMoniker **ppmkOut)
751 char display_nameA[256];
752 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
753 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
754 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
755 *pchEaten = lstrlenW(pszDisplayName);
756 return CreateAntiMoniker(ppmkOut);
759 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
761 ParseDisplayName_QueryInterface,
762 ParseDisplayName_AddRef,
763 ParseDisplayName_Release,
764 ParseDisplayName_ParseDisplayName
767 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
769 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
771 IMoniker * spMoniker;
772 int monCnt=0, matchCnt=0;
774 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
776 HRESULT hr;
777 WCHAR * szDisplayn;
778 monCnt++;
779 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
780 if (SUCCEEDED(hr))
782 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
783 matchCnt++;
784 CoTaskMemFree(szDisplayn);
787 trace("Total number of monikers is %i\n", monCnt);
788 return matchCnt;
791 static void test_MkParseDisplayName(void)
793 IBindCtx * pbc = NULL;
794 HRESULT hr;
795 IMoniker * pmk = NULL;
796 IMoniker * pmk1 = NULL;
797 IMoniker * pmk2 = NULL;
798 ULONG eaten;
799 int matchCnt;
800 IUnknown * object = NULL;
802 IUnknown *lpEM1;
804 IEnumMoniker *spEM1 = NULL;
805 IEnumMoniker *spEM2 = NULL;
806 IEnumMoniker *spEM3 = NULL;
808 DWORD pdwReg1=0;
809 DWORD grflags=0;
810 DWORD pdwReg2=0;
811 DWORD moniker_type;
812 IRunningObjectTable * pprot=NULL;
814 /* CLSID of My Computer */
815 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
816 '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};
817 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
818 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
819 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
820 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
821 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
822 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
823 static const WCHAR wszEmpty[] = {0};
824 char szDisplayNameFile[256];
825 WCHAR wszDisplayNameFile[256];
826 int i, len;
828 const struct
830 LPBC *ppbc;
831 LPCOLESTR szDisplayName;
832 LPDWORD pchEaten;
833 LPMONIKER *ppmk;
834 } invalid_parameters[] =
836 {NULL, NULL, NULL, NULL},
837 {NULL, NULL, NULL, &pmk},
838 {NULL, NULL, &eaten, NULL},
839 {NULL, NULL, &eaten, &pmk},
840 {NULL, wszEmpty, NULL, NULL},
841 {NULL, wszEmpty, NULL, &pmk},
842 {NULL, wszEmpty, &eaten, NULL},
843 {NULL, wszEmpty, &eaten, &pmk},
844 {&pbc, NULL, NULL, NULL},
845 {&pbc, NULL, NULL, &pmk},
846 {&pbc, NULL, &eaten, NULL},
847 {&pbc, NULL, &eaten, &pmk},
848 {&pbc, wszEmpty, NULL, NULL},
849 {&pbc, wszEmpty, NULL, &pmk},
850 {&pbc, wszEmpty, &eaten, NULL},
851 {&pbc, wszEmpty, &eaten, &pmk},
854 hr = CreateBindCtx(0, &pbc);
855 ok_ole_success(hr, CreateBindCtx);
857 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
859 eaten = 0xdeadbeef;
860 pmk = (IMoniker *)0xdeadbeef;
861 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
862 invalid_parameters[i].szDisplayName,
863 invalid_parameters[i].pchEaten,
864 invalid_parameters[i].ppmk);
865 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
866 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
867 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
870 eaten = 0xdeadbeef;
871 pmk = (IMoniker *)0xdeadbeef;
872 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
873 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
874 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
875 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
876 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
878 /* no special handling of "clsid:" without the string form of the clsid
879 * following */
880 eaten = 0xdeadbeef;
881 pmk = (IMoniker *)0xdeadbeef;
882 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
883 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
884 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
885 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
886 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
888 /* shows clsid has higher precedence than a running object */
889 hr = CreateFileMoniker(wszDisplayName, &pmk);
890 ok_ole_success(hr, CreateFileMoniker);
891 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
892 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
893 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
894 ok_ole_success(hr, IRunningObjectTable_Register);
895 IMoniker_Release(pmk);
896 pmk = NULL;
897 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
898 ok_ole_success(hr, MkParseDisplayName);
899 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1,
900 "Processed character count should have been 43 instead of %u\n", eaten);
901 if (pmk)
903 IMoniker_IsSystemMoniker(pmk, &moniker_type);
904 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
905 IMoniker_Release(pmk);
907 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
908 ok_ole_success(hr, IRunningObjectTable_Revoke);
909 IRunningObjectTable_Release(pprot);
911 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
912 ok_ole_success(hr, CreateFileMoniker);
913 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
914 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
915 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
916 ok_ole_success(hr, IRunningObjectTable_Register);
917 IMoniker_Release(pmk);
918 pmk = NULL;
919 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
920 ok_ole_success(hr, MkParseDisplayName);
921 ok(eaten == sizeof(wszDisplayNameRunning)/sizeof(WCHAR) - 1,
922 "Processed character count should have been 15 instead of %u\n", eaten);
923 if (pmk)
925 IMoniker_IsSystemMoniker(pmk, &moniker_type);
926 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
927 IMoniker_Release(pmk);
929 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
930 ok_ole_success(hr, IRunningObjectTable_Revoke);
931 IRunningObjectTable_Release(pprot);
933 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
934 ok_ole_success(hr, CoRegisterClassObject);
936 expected_display_name = wszDisplayNameProgId1;
937 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
938 ok_ole_success(hr, MkParseDisplayName);
939 ok(eaten == sizeof(wszDisplayNameProgId1)/sizeof(WCHAR) - 1,
940 "Processed character count should have been 8 instead of %u\n", eaten);
941 if (pmk)
943 IMoniker_IsSystemMoniker(pmk, &moniker_type);
944 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
945 IMoniker_Release(pmk);
948 expected_display_name = wszDisplayNameProgId2;
949 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
950 ok_ole_success(hr, MkParseDisplayName);
951 ok(eaten == sizeof(wszDisplayNameProgId2)/sizeof(WCHAR) - 1,
952 "Processed character count should have been 8 instead of %u\n", eaten);
953 if (pmk)
955 IMoniker_IsSystemMoniker(pmk, &moniker_type);
956 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
957 IMoniker_Release(pmk);
960 eaten = 0xdeadbeef;
961 pmk = (IMoniker *)0xdeadbeef;
962 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
963 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
964 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
965 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
966 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
968 hr = CoRevokeClassObject(pdwReg1);
969 ok_ole_success(hr, CoRevokeClassObject);
971 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
972 strcat(szDisplayNameFile, "\\kernel32.dll");
973 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
974 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
975 ok_ole_success(hr, MkParseDisplayName);
976 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
977 if (pmk)
979 IMoniker_IsSystemMoniker(pmk, &moniker_type);
980 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
981 IMoniker_Release(pmk);
984 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
985 ok_ole_success(hr, MkParseDisplayName);
986 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1, "Processed character count should have been 43 instead of %u\n", eaten);
988 if (pmk)
990 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
991 ok_ole_success(hr, IMoniker_BindToObject);
993 if (SUCCEEDED(hr))
994 IUnknown_Release(object);
995 IMoniker_Release(pmk);
997 IBindCtx_Release(pbc);
999 /* Test the EnumMoniker interface */
1000 hr = CreateBindCtx(0, &pbc);
1001 ok_ole_success(hr, CreateBindCtx);
1003 hr = CreateFileMoniker(wszFileName1, &pmk1);
1004 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1005 hr = CreateFileMoniker(wszFileName2, &pmk2);
1006 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1007 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1008 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
1010 /* Check EnumMoniker before registering */
1011 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1012 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1013 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
1014 /* Register a couple of Monikers and check is ok */
1015 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
1017 matchCnt = count_moniker_matches(pbc, spEM1);
1018 trace("Number of matches is %i\n", matchCnt);
1020 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1021 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1022 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
1023 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
1025 trace("IROT::Register\n");
1026 grflags=0;
1027 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1028 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1029 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
1030 pprot, grflags, lpEM1, pmk2, pdwReg2);
1032 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1033 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1035 matchCnt = count_moniker_matches(pbc, spEM2);
1036 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1038 trace("IEnumMoniker::Clone\n");
1039 IEnumMoniker_Clone(spEM2, &spEM3);
1041 matchCnt = count_moniker_matches(pbc, spEM3);
1042 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1043 trace("IEnumMoniker::Reset\n");
1044 IEnumMoniker_Reset(spEM3);
1046 matchCnt = count_moniker_matches(pbc, spEM3);
1047 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1049 IRunningObjectTable_Revoke(pprot,pdwReg1);
1050 IRunningObjectTable_Revoke(pprot,pdwReg2);
1051 IUnknown_Release(lpEM1);
1052 IEnumMoniker_Release(spEM1);
1053 IEnumMoniker_Release(spEM2);
1054 IEnumMoniker_Release(spEM3);
1055 IMoniker_Release(pmk1);
1056 IMoniker_Release(pmk2);
1057 IRunningObjectTable_Release(pprot);
1059 IBindCtx_Release(pbc);
1062 static const LARGE_INTEGER llZero;
1064 static const BYTE expected_class_moniker_marshal_data[] =
1066 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1067 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1068 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1069 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1070 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1071 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1072 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1073 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1074 0x00,0x00,0x00,0x00,
1077 static const BYTE expected_class_moniker_saved_data[] =
1079 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1080 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1081 0x00,0x00,0x00,0x00,
1084 static const BYTE expected_class_moniker_comparison_data[] =
1086 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1087 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1088 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1089 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1092 static const WCHAR expected_class_moniker_display_name[] =
1094 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1095 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1096 '0','0','0','0','4','6',':',0
1099 static const BYTE expected_item_moniker_comparison_data[] =
1101 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1102 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1103 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1104 0x54,0x00,0x00,0x00,
1107 static const BYTE expected_item_moniker_saved_data[] =
1109 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1110 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1113 static const BYTE expected_item_moniker_marshal_data[] =
1115 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1116 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1117 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1118 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1119 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1120 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1121 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1122 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1125 static const BYTE expected_anti_moniker_marshal_data[] =
1127 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1128 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1129 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1130 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1131 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1132 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1133 0x01,0x00,0x00,0x00,
1136 static const BYTE expected_anti_moniker_saved_data[] =
1138 0x01,0x00,0x00,0x00,
1141 static const BYTE expected_anti_moniker_comparison_data[] =
1143 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1144 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1145 0x01,0x00,0x00,0x00,
1148 static const BYTE expected_gc_moniker_marshal_data[] =
1150 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1151 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1152 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1153 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1154 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1155 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1156 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1157 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1158 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1159 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1160 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1161 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1162 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1163 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1164 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1165 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1166 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1167 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1168 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1169 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1170 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1171 0x00,0x57,0x69,0x6e,0x65,0x00,
1174 static const BYTE expected_gc_moniker_saved_data[] =
1176 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1177 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1178 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1179 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1180 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1181 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1182 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1183 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1184 0x65,0x00,
1187 static const BYTE expected_gc_moniker_comparison_data[] =
1189 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1190 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1191 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1192 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1193 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1194 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1195 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1196 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1197 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1200 static void test_moniker(
1201 const char *testname, IMoniker *moniker,
1202 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1203 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1204 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1205 LPCWSTR expected_display_name)
1207 IStream * stream;
1208 IROTData * rotdata;
1209 HRESULT hr;
1210 HGLOBAL hglobal;
1211 LPBYTE moniker_data;
1212 DWORD moniker_size;
1213 DWORD i;
1214 BOOL same;
1215 BYTE buffer[128];
1216 IMoniker * moniker_proxy;
1217 LPOLESTR display_name;
1218 IBindCtx *bindctx;
1220 hr = IMoniker_IsDirty(moniker);
1221 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1223 /* Display Name */
1225 hr = CreateBindCtx(0, &bindctx);
1226 ok_ole_success(hr, CreateBindCtx);
1228 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1229 ok_ole_success(hr, IMoniker_GetDisplayName);
1230 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1232 CoTaskMemFree(display_name);
1233 IBindCtx_Release(bindctx);
1235 hr = IMoniker_IsDirty(moniker);
1236 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1238 /* IROTData::GetComparisonData test */
1240 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1241 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1243 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1244 ok_ole_success(hr, IROTData_GetComparisonData);
1246 if (hr != S_OK) moniker_size = 0;
1248 /* first check we have the right amount of data */
1249 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1250 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1251 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1253 /* then do a byte-by-byte comparison */
1254 same = TRUE;
1255 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1257 if (expected_moniker_comparison_data[i] != buffer[i])
1259 same = FALSE;
1260 break;
1264 ok(same, "%s: Comparison data differs\n", testname);
1265 if (!same)
1267 for (i = 0; i < moniker_size; i++)
1269 if (i % 8 == 0) printf(" ");
1270 printf("0x%02x,", buffer[i]);
1271 if (i % 8 == 7) printf("\n");
1273 printf("\n");
1276 IROTData_Release(rotdata);
1278 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1279 ok_ole_success(hr, CreateStreamOnHGlobal);
1281 /* Saving */
1283 hr = IMoniker_Save(moniker, stream, TRUE);
1284 ok_ole_success(hr, IMoniker_Save);
1286 hr = GetHGlobalFromStream(stream, &hglobal);
1287 ok_ole_success(hr, GetHGlobalFromStream);
1289 moniker_size = GlobalSize(hglobal);
1291 moniker_data = GlobalLock(hglobal);
1293 /* first check we have the right amount of data */
1294 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1295 "%s: Size of saved data differs (expected %d, actual %d)\n",
1296 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1298 /* then do a byte-by-byte comparison */
1299 same = TRUE;
1300 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1302 if (expected_moniker_saved_data[i] != moniker_data[i])
1304 same = FALSE;
1305 break;
1309 ok(same, "%s: Saved data differs\n", testname);
1310 if (!same)
1312 for (i = 0; i < moniker_size; i++)
1314 if (i % 8 == 0) printf(" ");
1315 printf("0x%02x,", moniker_data[i]);
1316 if (i % 8 == 7) printf("\n");
1318 printf("\n");
1321 GlobalUnlock(hglobal);
1323 IStream_Release(stream);
1325 /* Marshaling tests */
1327 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1328 ok_ole_success(hr, CreateStreamOnHGlobal);
1330 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1331 ok_ole_success(hr, CoMarshalInterface);
1333 hr = GetHGlobalFromStream(stream, &hglobal);
1334 ok_ole_success(hr, GetHGlobalFromStream);
1336 moniker_size = GlobalSize(hglobal);
1338 moniker_data = GlobalLock(hglobal);
1340 /* first check we have the right amount of data */
1341 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1342 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1343 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1345 /* then do a byte-by-byte comparison */
1346 same = TRUE;
1347 if (expected_moniker_marshal_data)
1349 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1351 if (expected_moniker_marshal_data[i] != moniker_data[i])
1353 same = FALSE;
1354 break;
1359 ok(same, "%s: Marshaled data differs\n", testname);
1360 if (!same)
1362 for (i = 0; i < moniker_size; i++)
1364 if (i % 8 == 0) printf(" ");
1365 printf("0x%02x,", moniker_data[i]);
1366 if (i % 8 == 7) printf("\n");
1368 printf("\n");
1371 GlobalUnlock(hglobal);
1373 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1374 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1375 ok_ole_success(hr, CoUnmarshalInterface);
1377 IStream_Release(stream);
1378 IMoniker_Release(moniker_proxy);
1381 static void test_class_moniker(void)
1383 HRESULT hr;
1384 IMoniker *moniker;
1385 DWORD moniker_type;
1386 DWORD hash;
1387 IBindCtx *bindctx;
1388 IMoniker *inverse;
1389 IUnknown *unknown;
1390 FILETIME filetime;
1392 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1393 ok_ole_success(hr, CreateClassMoniker);
1394 if (!moniker) return;
1396 test_moniker("class moniker", moniker,
1397 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1398 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1399 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1400 expected_class_moniker_display_name);
1402 /* Hashing */
1404 hr = IMoniker_Hash(moniker, &hash);
1405 ok_ole_success(hr, IMoniker_Hash);
1407 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1408 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1409 hash);
1411 /* IsSystemMoniker test */
1413 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1414 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1416 ok(moniker_type == MKSYS_CLASSMONIKER,
1417 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1418 moniker_type);
1420 hr = CreateBindCtx(0, &bindctx);
1421 ok_ole_success(hr, CreateBindCtx);
1423 /* IsRunning test */
1424 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1425 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1427 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1428 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1430 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1431 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1433 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1434 ok_ole_success(hr, IMoniker_BindToObject);
1435 IUnknown_Release(unknown);
1437 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1438 ok_ole_success(hr, IMoniker_BindToStorage);
1439 IUnknown_Release(unknown);
1441 IBindCtx_Release(bindctx);
1443 hr = IMoniker_Inverse(moniker, &inverse);
1444 ok_ole_success(hr, IMoniker_Inverse);
1445 IMoniker_Release(inverse);
1447 IMoniker_Release(moniker);
1450 static void test_file_moniker(WCHAR* path)
1452 IStream *stream;
1453 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1454 HRESULT hr;
1456 hr = CreateFileMoniker(path, &moniker1);
1457 ok_ole_success(hr, CreateFileMoniker);
1459 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1460 ok_ole_success(hr, CreateStreamOnHGlobal);
1462 /* Marshal */
1463 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1464 ok_ole_success(hr, CoMarshalInterface);
1466 /* Rewind */
1467 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1468 ok_ole_success(hr, IStream_Seek);
1470 /* Unmarshal */
1471 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1472 ok_ole_success(hr, CoUnmarshalInterface);
1474 hr = IMoniker_IsEqual(moniker1, moniker2);
1475 ok_ole_success(hr, IsEqual);
1477 IStream_Release(stream);
1478 if (moniker1)
1479 IMoniker_Release(moniker1);
1480 if (moniker2)
1481 IMoniker_Release(moniker2);
1484 static void test_file_monikers(void)
1486 static WCHAR wszFile[][30] = {
1487 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1488 {'\\', '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},
1489 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1490 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1491 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1492 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1493 * U+0100 .. = Latin extended-A
1495 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1498 int i;
1500 trace("ACP is %u\n", GetACP());
1502 for (i = 0; i < COUNTOF(wszFile); ++i)
1504 int j ;
1505 if (i == 2)
1507 BOOL used;
1508 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1509 if (used)
1511 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1512 continue;
1515 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1517 wszFile[i][j] = 0;
1518 test_file_moniker(wszFile[i]);
1523 static void test_item_moniker(void)
1525 HRESULT hr;
1526 IMoniker *moniker;
1527 DWORD moniker_type;
1528 DWORD hash;
1529 IBindCtx *bindctx;
1530 IMoniker *inverse;
1531 IUnknown *unknown;
1532 static const WCHAR wszDelimeter[] = {'!',0};
1533 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1534 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1536 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1537 ok_ole_success(hr, CreateItemMoniker);
1539 test_moniker("item moniker", moniker,
1540 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1541 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1542 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1543 expected_display_name);
1545 /* Hashing */
1547 hr = IMoniker_Hash(moniker, &hash);
1548 ok_ole_success(hr, IMoniker_Hash);
1550 ok(hash == 0x73c,
1551 "Hash value != 0x73c, instead was 0x%08x\n",
1552 hash);
1554 /* IsSystemMoniker test */
1556 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1557 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1559 ok(moniker_type == MKSYS_ITEMMONIKER,
1560 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1561 moniker_type);
1563 hr = CreateBindCtx(0, &bindctx);
1564 ok_ole_success(hr, CreateBindCtx);
1566 /* IsRunning test */
1567 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1568 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1570 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1571 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1573 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1574 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1576 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1577 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1579 IBindCtx_Release(bindctx);
1581 hr = IMoniker_Inverse(moniker, &inverse);
1582 ok_ole_success(hr, IMoniker_Inverse);
1583 IMoniker_Release(inverse);
1585 IMoniker_Release(moniker);
1588 static void test_anti_moniker(void)
1590 HRESULT hr;
1591 IMoniker *moniker;
1592 DWORD moniker_type;
1593 DWORD hash;
1594 IBindCtx *bindctx;
1595 FILETIME filetime;
1596 IMoniker *inverse;
1597 IUnknown *unknown;
1598 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1600 hr = CreateAntiMoniker(&moniker);
1601 ok_ole_success(hr, CreateAntiMoniker);
1602 if (!moniker) return;
1604 test_moniker("anti moniker", moniker,
1605 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1606 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1607 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1608 expected_display_name);
1610 /* Hashing */
1611 hr = IMoniker_Hash(moniker, &hash);
1612 ok_ole_success(hr, IMoniker_Hash);
1613 ok(hash == 0x80000001,
1614 "Hash value != 0x80000001, instead was 0x%08x\n",
1615 hash);
1617 /* IsSystemMoniker test */
1618 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1619 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1620 ok(moniker_type == MKSYS_ANTIMONIKER,
1621 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1622 moniker_type);
1624 hr = IMoniker_Inverse(moniker, &inverse);
1625 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1626 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1628 hr = CreateBindCtx(0, &bindctx);
1629 ok_ole_success(hr, CreateBindCtx);
1631 /* IsRunning test */
1632 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1633 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1635 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1636 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1638 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1639 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1641 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1642 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1644 IBindCtx_Release(bindctx);
1646 IMoniker_Release(moniker);
1649 static void test_generic_composite_moniker(void)
1651 HRESULT hr;
1652 IMoniker *moniker;
1653 IMoniker *moniker1;
1654 IMoniker *moniker2;
1655 DWORD moniker_type;
1656 DWORD hash;
1657 IBindCtx *bindctx;
1658 FILETIME filetime;
1659 IMoniker *inverse;
1660 IUnknown *unknown;
1661 static const WCHAR wszDelimeter1[] = {'!',0};
1662 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1663 static const WCHAR wszDelimeter2[] = {'#',0};
1664 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1665 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1667 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1668 ok_ole_success(hr, CreateItemMoniker);
1669 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1670 ok_ole_success(hr, CreateItemMoniker);
1671 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1672 ok_ole_success(hr, CreateGenericComposite);
1674 test_moniker("generic composite moniker", moniker,
1675 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1676 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1677 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1678 expected_display_name);
1680 /* Hashing */
1682 hr = IMoniker_Hash(moniker, &hash);
1683 ok_ole_success(hr, IMoniker_Hash);
1685 ok(hash == 0xd87,
1686 "Hash value != 0xd87, instead was 0x%08x\n",
1687 hash);
1689 /* IsSystemMoniker test */
1691 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1692 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1694 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1695 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1696 moniker_type);
1698 hr = CreateBindCtx(0, &bindctx);
1699 ok_ole_success(hr, CreateBindCtx);
1701 /* IsRunning test */
1702 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1703 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1705 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1706 todo_wine
1707 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1709 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1710 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1712 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1713 todo_wine
1714 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1716 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1717 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1719 IBindCtx_Release(bindctx);
1721 hr = IMoniker_Inverse(moniker, &inverse);
1722 ok_ole_success(hr, IMoniker_Inverse);
1723 IMoniker_Release(inverse);
1725 IMoniker_Release(moniker);
1728 static void test_pointer_moniker(void)
1730 HRESULT hr;
1731 IMoniker *moniker;
1732 DWORD moniker_type;
1733 DWORD hash;
1734 IBindCtx *bindctx;
1735 FILETIME filetime;
1736 IMoniker *inverse;
1737 IUnknown *unknown;
1738 IStream *stream;
1739 IROTData *rotdata;
1740 LPOLESTR display_name;
1742 cLocks = 0;
1744 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1745 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1747 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1748 ok_ole_success(hr, CreatePointerMoniker);
1749 if (!moniker) return;
1751 ok_more_than_one_lock();
1753 /* Display Name */
1755 hr = CreateBindCtx(0, &bindctx);
1756 ok_ole_success(hr, CreateBindCtx);
1758 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1759 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1761 IBindCtx_Release(bindctx);
1763 hr = IMoniker_IsDirty(moniker);
1764 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1766 /* IROTData::GetComparisonData test */
1768 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1769 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1771 /* Saving */
1773 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1774 ok_ole_success(hr, CreateStreamOnHGlobal);
1776 hr = IMoniker_Save(moniker, stream, TRUE);
1777 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1779 IStream_Release(stream);
1781 /* Hashing */
1782 hr = IMoniker_Hash(moniker, &hash);
1783 ok_ole_success(hr, IMoniker_Hash);
1784 ok(hash == PtrToUlong(&Test_ClassFactory),
1785 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1786 PtrToUlong(&Test_ClassFactory), hash);
1788 /* IsSystemMoniker test */
1789 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1790 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1791 ok(moniker_type == MKSYS_POINTERMONIKER,
1792 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1793 moniker_type);
1795 hr = IMoniker_Inverse(moniker, &inverse);
1796 ok_ole_success(hr, IMoniker_Inverse);
1797 IMoniker_Release(inverse);
1799 hr = CreateBindCtx(0, &bindctx);
1800 ok_ole_success(hr, CreateBindCtx);
1802 /* IsRunning test */
1803 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1804 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1806 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1807 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1809 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1810 ok_ole_success(hr, IMoniker_BindToObject);
1811 IUnknown_Release(unknown);
1813 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1814 ok_ole_success(hr, IMoniker_BindToStorage);
1815 IUnknown_Release(unknown);
1817 IMoniker_Release(moniker);
1819 ok_no_locks();
1821 hr = CreatePointerMoniker(NULL, &moniker);
1822 ok_ole_success(hr, CreatePointerMoniker);
1824 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1825 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1827 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1828 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1830 IBindCtx_Release(bindctx);
1832 IMoniker_Release(moniker);
1835 static void test_bind_context(void)
1837 HRESULT hr;
1838 IBindCtx *pBindCtx;
1839 IEnumString *pEnumString;
1840 BIND_OPTS2 bind_opts;
1841 HeapUnknown *unknown;
1842 HeapUnknown *unknown2;
1843 IUnknown *param_obj;
1844 ULONG refs;
1845 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1846 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1848 hr = CreateBindCtx(0, NULL);
1849 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1851 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1852 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1854 hr = CreateBindCtx(0, &pBindCtx);
1855 ok_ole_success(hr, "CreateBindCtx");
1857 bind_opts.cbStruct = -1;
1858 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1859 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1860 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1861 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1862 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1864 bind_opts.cbStruct = sizeof(BIND_OPTS);
1865 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1866 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1867 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1869 bind_opts.cbStruct = sizeof(bind_opts);
1870 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1871 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1872 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1873 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1874 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1875 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1876 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1877 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1878 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1879 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1880 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1882 bind_opts.cbStruct = -1;
1883 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1884 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1886 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1887 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1889 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1890 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1891 unknown->refs = 1;
1892 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface);
1893 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1895 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1896 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1897 IUnknown_Release(param_obj);
1899 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1900 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1901 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1903 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1904 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1906 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1907 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1908 ok(!pEnumString, "pEnumString should be NULL\n");
1910 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1911 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1913 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1914 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1916 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1917 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1918 unknown2->refs = 1;
1919 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1920 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1922 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1923 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1925 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1926 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1928 IBindCtx_Release(pBindCtx);
1930 refs = IUnknown_Release(&unknown->IUnknown_iface);
1931 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1933 refs = IUnknown_Release(&unknown2->IUnknown_iface);
1934 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1937 static void test_save_load_filemoniker(void)
1939 IMoniker* pMk;
1940 IStream* pStm;
1941 HRESULT hr;
1942 ULARGE_INTEGER size;
1943 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
1944 DWORD some_val = 0xFEDCBA98;
1945 int i;
1947 /* see FileMonikerImpl_Save docs */
1948 zero_pos.QuadPart = 0;
1949 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
1950 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
1952 /* create the stream we're going to write to */
1953 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
1954 ok_ole_success(hr, "CreateStreamOnHGlobal");
1956 size.u.LowPart = 128;
1957 hr = IStream_SetSize(pStm, size);
1958 ok_ole_success(hr, "IStream_SetSize");
1960 /* create and save a moniker */
1961 hr = CreateFileMoniker(wszFileName1, &pMk);
1962 ok_ole_success(hr, "CreateFileMoniker");
1964 hr = IMoniker_Save(pMk, pStm, TRUE);
1965 ok_ole_success(hr, "IMoniker_Save");
1967 hr = IMoniker_Release(pMk);
1968 ok_ole_success(hr, "IMoniker_Release");
1970 /* overwrite the constants with various values */
1971 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1972 ok_ole_success(hr, "IStream_Seek");
1973 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1974 ok_ole_success(hr, "IStream_Write");
1976 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
1977 ok_ole_success(hr, "IStream_Seek");
1978 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1979 ok_ole_success(hr, "IStream_Write");
1981 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
1982 ok_ole_success(hr, "IStream_Seek");
1983 for(i = 0; i < 5; ++i){
1984 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
1985 ok_ole_success(hr, "IStream_Write");
1988 /* go back to the start of the stream */
1989 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1990 ok_ole_success(hr, "IStream_Seek");
1992 /* create a new moniker and load into it */
1993 hr = CreateFileMoniker(wszFileName1, &pMk);
1994 ok_ole_success(hr, "CreateFileMoniker");
1996 hr = IMoniker_Load(pMk, pStm);
1997 ok_ole_success(hr, "IMoniker_Load");
1999 hr = IMoniker_Release(pMk);
2000 ok_ole_success(hr, "IMoniker_Release");
2002 hr = IStream_Release(pStm);
2003 ok_ole_success(hr, "IStream_Release");
2006 START_TEST(moniker)
2008 if (!GetProcAddress(GetModuleHandleA("ole32.dll"), "CoRegisterSurrogateEx")) {
2009 win_skip("skipping test on win9x\n");
2010 return;
2013 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2015 test_ROT();
2016 test_ROT_multiple_entries();
2017 test_MkParseDisplayName();
2018 test_class_moniker();
2019 test_file_monikers();
2020 test_item_moniker();
2021 test_anti_moniker();
2022 test_generic_composite_moniker();
2023 test_pointer_moniker();
2024 test_save_load_filemoniker();
2026 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2028 test_bind_context();
2030 CoUninitialize();