dmscript: Merge the IClassFactory implementations.
[wine/testsucceed.git] / dlls / ole32 / tests / moniker.c
blob54a5f8cb76405d7047b00542dc475d6ed098da4e
1 /*
2 * Moniker Tests
4 * Copyright 2004 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define _WIN32_DCOM
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "initguid.h"
32 #include "comcat.h"
33 #include "olectl.h"
35 #include "wine/test.h"
37 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
38 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
39 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
40 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
42 #define CHECK_EXPECTED_METHOD(method_name) \
43 do { \
44 trace("%s\n", method_name); \
45 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
46 if (*expected_method_list) \
47 { \
48 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
49 *expected_method_list, method_name); \
50 expected_method_list++; \
51 } \
52 } while(0)
54 static char const * const *expected_method_list;
55 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
56 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
58 static const CLSID CLSID_WineTest =
59 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
60 0x9474ba1a,
61 0x258b,
62 0x490b,
63 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
66 static const CLSID CLSID_TestMoniker =
67 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
68 0xb306bfbc,
69 0x496e,
70 0x4f53,
71 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
74 static LONG cLocks;
76 static void LockModule(void)
78 InterlockedIncrement(&cLocks);
81 static void UnlockModule(void)
83 InterlockedDecrement(&cLocks);
86 static SIZE_T round_global_size(SIZE_T size)
88 static SIZE_T global_size_alignment = -1;
89 if (global_size_alignment == -1)
91 void *p = GlobalAlloc(GMEM_FIXED, 1);
92 global_size_alignment = GlobalSize(p);
93 GlobalFree(p);
96 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
99 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
100 LPCLASSFACTORY iface,
101 REFIID riid,
102 LPVOID *ppvObj)
104 if (ppvObj == NULL) return E_POINTER;
106 if (IsEqualGUID(riid, &IID_IUnknown) ||
107 IsEqualGUID(riid, &IID_IClassFactory))
109 *ppvObj = iface;
110 IClassFactory_AddRef(iface);
111 return S_OK;
114 *ppvObj = NULL;
115 return E_NOINTERFACE;
118 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
120 LockModule();
121 return 2; /* non-heap-based object */
124 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
126 UnlockModule();
127 return 1; /* non-heap-based object */
130 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
131 LPCLASSFACTORY iface,
132 LPUNKNOWN pUnkOuter,
133 REFIID riid,
134 LPVOID *ppvObj)
136 return E_NOTIMPL;
139 static HRESULT WINAPI Test_IClassFactory_LockServer(
140 LPCLASSFACTORY iface,
141 BOOL fLock)
143 return S_OK;
146 static const IClassFactoryVtbl TestClassFactory_Vtbl =
148 Test_IClassFactory_QueryInterface,
149 Test_IClassFactory_AddRef,
150 Test_IClassFactory_Release,
151 Test_IClassFactory_CreateInstance,
152 Test_IClassFactory_LockServer
155 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
157 typedef struct
159 IUnknown IUnknown_iface;
160 ULONG refs;
161 } HeapUnknown;
163 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
165 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
168 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
170 if (IsEqualIID(riid, &IID_IUnknown))
172 IUnknown_AddRef(iface);
173 *ppv = iface;
174 return S_OK;
176 *ppv = NULL;
177 return E_NOINTERFACE;
180 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
182 HeapUnknown *This = impl_from_IUnknown(iface);
183 return InterlockedIncrement((LONG*)&This->refs);
186 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
188 HeapUnknown *This = impl_from_IUnknown(iface);
189 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
190 if (!refs) HeapFree(GetProcessHeap(), 0, This);
191 return refs;
194 static const IUnknownVtbl HeapUnknown_Vtbl =
196 HeapUnknown_QueryInterface,
197 HeapUnknown_AddRef,
198 HeapUnknown_Release
201 static HRESULT WINAPI
202 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
204 if (!ppvObject)
205 return E_INVALIDARG;
207 *ppvObject = 0;
209 if (IsEqualIID(&IID_IUnknown, riid) ||
210 IsEqualIID(&IID_IPersist, riid) ||
211 IsEqualIID(&IID_IPersistStream,riid) ||
212 IsEqualIID(&IID_IMoniker, riid))
213 *ppvObject = iface;
214 if (IsEqualIID(&IID_IROTData, riid))
215 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
217 if ((*ppvObject)==0)
218 return E_NOINTERFACE;
220 IMoniker_AddRef(iface);
222 return S_OK;
225 static ULONG WINAPI
226 Moniker_AddRef(IMoniker* iface)
228 return 2;
231 static ULONG WINAPI
232 Moniker_Release(IMoniker* iface)
234 return 1;
237 static HRESULT WINAPI
238 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
240 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
242 *pClassID = CLSID_TestMoniker;
244 return S_OK;
247 static HRESULT WINAPI
248 Moniker_IsDirty(IMoniker* iface)
250 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
252 return S_FALSE;
255 static HRESULT WINAPI
256 Moniker_Load(IMoniker* iface, IStream* pStm)
258 CHECK_EXPECTED_METHOD("Moniker_Load");
259 return E_NOTIMPL;
262 static HRESULT WINAPI
263 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
265 CHECK_EXPECTED_METHOD("Moniker_Save");
266 return E_NOTIMPL;
269 static HRESULT WINAPI
270 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
272 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
273 return E_NOTIMPL;
276 static HRESULT WINAPI
277 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
278 REFIID riid, VOID** ppvResult)
280 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
281 return E_NOTIMPL;
284 static HRESULT WINAPI
285 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
286 REFIID riid, VOID** ppvObject)
288 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
289 return E_NOTIMPL;
292 static HRESULT WINAPI
293 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
294 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
296 CHECK_EXPECTED_METHOD("Moniker_Reduce");
298 if (ppmkReduced==NULL)
299 return E_POINTER;
301 IMoniker_AddRef(iface);
303 *ppmkReduced=iface;
305 return MK_S_REDUCED_TO_SELF;
308 static HRESULT WINAPI
309 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
310 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
312 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
313 return E_NOTIMPL;
316 static HRESULT WINAPI
317 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
319 CHECK_EXPECTED_METHOD("Moniker_Enum");
321 if (ppenumMoniker == NULL)
322 return E_POINTER;
324 *ppenumMoniker = NULL;
326 return S_OK;
329 static HRESULT WINAPI
330 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
332 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
333 return E_NOTIMPL;
336 static HRESULT WINAPI
337 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
339 CHECK_EXPECTED_METHOD("Moniker_Hash");
340 return E_NOTIMPL;
343 static HRESULT WINAPI
344 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
345 IMoniker* pmkNewlyRunning)
347 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
348 return E_NOTIMPL;
351 static HRESULT WINAPI
352 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
353 IMoniker* pmkToLeft, FILETIME* pFileTime)
355 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
356 return E_NOTIMPL;
359 static HRESULT WINAPI
360 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
362 CHECK_EXPECTED_METHOD("Moniker_Inverse");
363 return E_NOTIMPL;
366 static HRESULT WINAPI
367 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
369 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
370 return E_NOTIMPL;
373 static HRESULT WINAPI
374 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
376 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
377 return E_NOTIMPL;
380 static HRESULT WINAPI
381 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
382 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
384 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
385 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
386 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
387 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
388 return S_OK;
391 static HRESULT WINAPI
392 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
393 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
395 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
396 return E_NOTIMPL;
399 static HRESULT WINAPI
400 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
402 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
404 if (!pwdMksys)
405 return E_POINTER;
407 (*pwdMksys)=MKSYS_NONE;
409 return S_FALSE;
412 static const IMonikerVtbl MonikerNoROTDataVtbl =
414 MonikerNoROTData_QueryInterface,
415 Moniker_AddRef,
416 Moniker_Release,
417 Moniker_GetClassID,
418 Moniker_IsDirty,
419 Moniker_Load,
420 Moniker_Save,
421 Moniker_GetSizeMax,
422 Moniker_BindToObject,
423 Moniker_BindToStorage,
424 Moniker_Reduce,
425 Moniker_ComposeWith,
426 Moniker_Enum,
427 Moniker_IsEqual,
428 Moniker_Hash,
429 Moniker_IsRunning,
430 Moniker_GetTimeOfLastChange,
431 Moniker_Inverse,
432 Moniker_CommonPrefixWith,
433 Moniker_RelativePathTo,
434 Moniker_GetDisplayName,
435 Moniker_ParseDisplayName,
436 Moniker_IsSystemMoniker
439 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
441 static IMoniker Moniker;
443 static HRESULT WINAPI
444 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
446 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
449 static ULONG WINAPI
450 ROTData_AddRef(IROTData *iface)
452 return 2;
455 static ULONG WINAPI
456 ROTData_Release(IROTData* iface)
458 return 1;
461 static HRESULT WINAPI
462 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
463 ULONG cbMax, ULONG* pcbData)
465 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
467 *pcbData = 1;
468 if (cbMax < *pcbData)
469 return E_OUTOFMEMORY;
471 *pbData = 0xde;
473 return S_OK;
476 static IROTDataVtbl ROTDataVtbl =
478 ROTData_QueryInterface,
479 ROTData_AddRef,
480 ROTData_Release,
481 ROTData_GetComparisonData
484 static IROTData ROTData = { &ROTDataVtbl };
486 static HRESULT WINAPI
487 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
489 if (!ppvObject)
490 return E_INVALIDARG;
492 *ppvObject = 0;
494 if (IsEqualIID(&IID_IUnknown, riid) ||
495 IsEqualIID(&IID_IPersist, riid) ||
496 IsEqualIID(&IID_IPersistStream,riid) ||
497 IsEqualIID(&IID_IMoniker, riid))
498 *ppvObject = iface;
499 if (IsEqualIID(&IID_IROTData, riid))
501 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
502 *ppvObject = &ROTData;
505 if ((*ppvObject)==0)
506 return E_NOINTERFACE;
508 IMoniker_AddRef(iface);
510 return S_OK;
513 static const IMonikerVtbl MonikerVtbl =
515 Moniker_QueryInterface,
516 Moniker_AddRef,
517 Moniker_Release,
518 Moniker_GetClassID,
519 Moniker_IsDirty,
520 Moniker_Load,
521 Moniker_Save,
522 Moniker_GetSizeMax,
523 Moniker_BindToObject,
524 Moniker_BindToStorage,
525 Moniker_Reduce,
526 Moniker_ComposeWith,
527 Moniker_Enum,
528 Moniker_IsEqual,
529 Moniker_Hash,
530 Moniker_IsRunning,
531 Moniker_GetTimeOfLastChange,
532 Moniker_Inverse,
533 Moniker_CommonPrefixWith,
534 Moniker_RelativePathTo,
535 Moniker_GetDisplayName,
536 Moniker_ParseDisplayName,
537 Moniker_IsSystemMoniker
540 static IMoniker Moniker = { &MonikerVtbl };
542 static void test_ROT(void)
544 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
545 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
546 '2','0','4','6','E','5','8','6','C','9','2','5',0};
547 HRESULT hr;
548 IMoniker *pMoniker = NULL;
549 IRunningObjectTable *pROT = NULL;
550 DWORD dwCookie;
551 static const char *methods_register_no_ROTData[] =
553 "Moniker_Reduce",
554 "Moniker_GetTimeOfLastChange",
555 "Moniker_QueryInterface(IID_IROTData)",
556 "Moniker_GetDisplayName",
557 "Moniker_GetClassID",
558 NULL
560 static const char *methods_register[] =
562 "Moniker_Reduce",
563 "Moniker_GetTimeOfLastChange",
564 "Moniker_QueryInterface(IID_IROTData)",
565 "ROTData_GetComparisonData",
566 NULL
568 static const char *methods_isrunning_no_ROTData[] =
570 "Moniker_Reduce",
571 "Moniker_QueryInterface(IID_IROTData)",
572 "Moniker_GetDisplayName",
573 "Moniker_GetClassID",
574 NULL
576 static const char *methods_isrunning[] =
578 "Moniker_Reduce",
579 "Moniker_QueryInterface(IID_IROTData)",
580 "ROTData_GetComparisonData",
581 NULL
584 cLocks = 0;
586 hr = GetRunningObjectTable(0, &pROT);
587 ok_ole_success(hr, GetRunningObjectTable);
589 expected_method_list = methods_register_no_ROTData;
590 /* try with our own moniker that doesn't support IROTData */
591 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
592 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
593 ok_ole_success(hr, IRunningObjectTable_Register);
594 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
596 ok_more_than_one_lock();
598 expected_method_list = methods_isrunning_no_ROTData;
599 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
600 ok_ole_success(hr, IRunningObjectTable_IsRunning);
601 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
603 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
604 ok_ole_success(hr, IRunningObjectTable_Revoke);
606 ok_no_locks();
608 expected_method_list = methods_register;
609 /* try with our own moniker */
610 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
611 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
612 ok_ole_success(hr, IRunningObjectTable_Register);
613 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
615 ok_more_than_one_lock();
617 expected_method_list = methods_isrunning;
618 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
619 ok_ole_success(hr, IRunningObjectTable_IsRunning);
620 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
622 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
623 ok_ole_success(hr, IRunningObjectTable_Revoke);
625 ok_no_locks();
627 hr = CreateFileMoniker(wszFileName, &pMoniker);
628 ok_ole_success(hr, CreateClassMoniker);
630 /* test flags: 0 */
631 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
632 pMoniker, &dwCookie);
633 ok_ole_success(hr, IRunningObjectTable_Register);
635 ok_more_than_one_lock();
637 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
638 ok_ole_success(hr, IRunningObjectTable_Revoke);
640 ok_no_locks();
642 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
643 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
644 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
645 ok_ole_success(hr, IRunningObjectTable_Register);
647 ok_more_than_one_lock();
649 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
650 ok_ole_success(hr, IRunningObjectTable_Revoke);
652 ok_no_locks();
654 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
655 /* only succeeds when process is started by SCM and has LocalService
656 * or RunAs AppId values */
657 hr = IRunningObjectTable_Register(pROT,
658 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
659 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
660 todo_wine {
661 ok(hr == CO_E_WRONG_SERVER_IDENTITY ||
662 broken(hr == S_OK) /* Win9x */,
663 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
665 if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie);
667 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
668 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
669 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
671 IMoniker_Release(pMoniker);
673 IRunningObjectTable_Release(pROT);
676 static void test_ROT_multiple_entries(void)
678 HRESULT hr;
679 IMoniker *pMoniker = NULL;
680 IRunningObjectTable *pROT = NULL;
681 DWORD dwCookie1, dwCookie2;
682 IUnknown *pObject = NULL;
683 static const WCHAR moniker_path[] =
684 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
686 hr = GetRunningObjectTable(0, &pROT);
687 ok_ole_success(hr, GetRunningObjectTable);
689 hr = CreateFileMoniker(moniker_path, &pMoniker);
690 ok_ole_success(hr, CreateFileMoniker);
692 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
693 ok_ole_success(hr, IRunningObjectTable_Register);
695 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
696 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
698 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
700 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
701 ok_ole_success(hr, IRunningObjectTable_GetObject);
702 IUnknown_Release(pObject);
704 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
705 ok_ole_success(hr, IRunningObjectTable_Revoke);
707 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
708 ok_ole_success(hr, IRunningObjectTable_GetObject);
709 IUnknown_Release(pObject);
711 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
712 ok_ole_success(hr, IRunningObjectTable_Revoke);
714 IMoniker_Release(pMoniker);
716 IRunningObjectTable_Release(pROT);
719 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
721 if (IsEqualIID(riid, &IID_IUnknown) ||
722 IsEqualIID(riid, &IID_IParseDisplayName))
724 *ppv = iface;
725 IUnknown_AddRef(iface);
726 return S_OK;
728 *ppv = NULL;
729 return E_NOINTERFACE;
732 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
734 return 2;
737 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
739 return 1;
742 static LPCWSTR expected_display_name;
744 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
745 IBindCtx *pbc,
746 LPOLESTR pszDisplayName,
747 ULONG *pchEaten,
748 IMoniker **ppmkOut)
750 char display_nameA[256];
751 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
752 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
753 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
754 *pchEaten = lstrlenW(pszDisplayName);
755 return CreateAntiMoniker(ppmkOut);
758 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
760 ParseDisplayName_QueryInterface,
761 ParseDisplayName_AddRef,
762 ParseDisplayName_Release,
763 ParseDisplayName_ParseDisplayName
766 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
768 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
770 IMoniker * spMoniker;
771 int monCnt=0, matchCnt=0;
773 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
775 HRESULT hr;
776 WCHAR * szDisplayn;
777 monCnt++;
778 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
779 if (SUCCEEDED(hr))
781 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
782 matchCnt++;
783 CoTaskMemFree(szDisplayn);
786 trace("Total number of monikers is %i\n", monCnt);
787 return matchCnt;
790 static void test_MkParseDisplayName(void)
792 IBindCtx * pbc = NULL;
793 HRESULT hr;
794 IMoniker * pmk = NULL;
795 IMoniker * pmk1 = NULL;
796 IMoniker * pmk2 = NULL;
797 ULONG eaten;
798 int matchCnt;
799 IUnknown * object = NULL;
801 IUnknown *lpEM1;
803 IEnumMoniker *spEM1 = NULL;
804 IEnumMoniker *spEM2 = NULL;
805 IEnumMoniker *spEM3 = NULL;
807 DWORD pdwReg1=0;
808 DWORD grflags=0;
809 DWORD pdwReg2=0;
810 DWORD moniker_type;
811 IRunningObjectTable * pprot=NULL;
813 /* CLSID of My Computer */
814 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
815 '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};
816 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
817 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
818 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
819 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
820 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
821 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
822 static const WCHAR wszEmpty[] = {0};
823 char szDisplayNameFile[256];
824 WCHAR wszDisplayNameFile[256];
825 int i, len;
827 const struct
829 LPBC *ppbc;
830 LPCOLESTR szDisplayName;
831 LPDWORD pchEaten;
832 LPMONIKER *ppmk;
833 } invalid_parameters[] =
835 {NULL, NULL, NULL, NULL},
836 {NULL, NULL, NULL, &pmk},
837 {NULL, NULL, &eaten, NULL},
838 {NULL, NULL, &eaten, &pmk},
839 {NULL, wszEmpty, NULL, NULL},
840 {NULL, wszEmpty, NULL, &pmk},
841 {NULL, wszEmpty, &eaten, NULL},
842 {NULL, wszEmpty, &eaten, &pmk},
843 {&pbc, NULL, NULL, NULL},
844 {&pbc, NULL, NULL, &pmk},
845 {&pbc, NULL, &eaten, NULL},
846 {&pbc, NULL, &eaten, &pmk},
847 {&pbc, wszEmpty, NULL, NULL},
848 {&pbc, wszEmpty, NULL, &pmk},
849 {&pbc, wszEmpty, &eaten, NULL},
850 {&pbc, wszEmpty, &eaten, &pmk},
853 hr = CreateBindCtx(0, &pbc);
854 ok_ole_success(hr, CreateBindCtx);
856 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
858 eaten = 0xdeadbeef;
859 pmk = (IMoniker *)0xdeadbeef;
860 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
861 invalid_parameters[i].szDisplayName,
862 invalid_parameters[i].pchEaten,
863 invalid_parameters[i].ppmk);
864 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
865 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
866 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
869 eaten = 0xdeadbeef;
870 pmk = (IMoniker *)0xdeadbeef;
871 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
872 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
873 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
874 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
875 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
877 /* no special handling of "clsid:" without the string form of the clsid
878 * following */
879 eaten = 0xdeadbeef;
880 pmk = (IMoniker *)0xdeadbeef;
881 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
882 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
883 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
884 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
885 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
887 /* shows clsid has higher precedence than a running object */
888 hr = CreateFileMoniker(wszDisplayName, &pmk);
889 ok_ole_success(hr, CreateFileMoniker);
890 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
891 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
892 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
893 ok_ole_success(hr, IRunningObjectTable_Register);
894 IMoniker_Release(pmk);
895 pmk = NULL;
896 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
897 ok_ole_success(hr, MkParseDisplayName);
898 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1,
899 "Processed character count should have been 43 instead of %u\n", eaten);
900 if (pmk)
902 IMoniker_IsSystemMoniker(pmk, &moniker_type);
903 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
904 IMoniker_Release(pmk);
906 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
907 ok_ole_success(hr, IRunningObjectTable_Revoke);
908 IRunningObjectTable_Release(pprot);
910 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
911 ok_ole_success(hr, CreateFileMoniker);
912 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
913 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
914 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
915 ok_ole_success(hr, IRunningObjectTable_Register);
916 IMoniker_Release(pmk);
917 pmk = NULL;
918 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
919 ok_ole_success(hr, MkParseDisplayName);
920 ok(eaten == sizeof(wszDisplayNameRunning)/sizeof(WCHAR) - 1,
921 "Processed character count should have been 15 instead of %u\n", eaten);
922 if (pmk)
924 IMoniker_IsSystemMoniker(pmk, &moniker_type);
925 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
926 IMoniker_Release(pmk);
928 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
929 ok_ole_success(hr, IRunningObjectTable_Revoke);
930 IRunningObjectTable_Release(pprot);
932 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
933 ok_ole_success(hr, CoRegisterClassObject);
935 expected_display_name = wszDisplayNameProgId1;
936 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
937 ok_ole_success(hr, MkParseDisplayName);
938 ok(eaten == sizeof(wszDisplayNameProgId1)/sizeof(WCHAR) - 1,
939 "Processed character count should have been 8 instead of %u\n", eaten);
940 if (pmk)
942 IMoniker_IsSystemMoniker(pmk, &moniker_type);
943 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
944 IMoniker_Release(pmk);
947 expected_display_name = wszDisplayNameProgId2;
948 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
949 ok_ole_success(hr, MkParseDisplayName);
950 ok(eaten == sizeof(wszDisplayNameProgId2)/sizeof(WCHAR) - 1,
951 "Processed character count should have been 8 instead of %u\n", eaten);
952 if (pmk)
954 IMoniker_IsSystemMoniker(pmk, &moniker_type);
955 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
956 IMoniker_Release(pmk);
959 eaten = 0xdeadbeef;
960 pmk = (IMoniker *)0xdeadbeef;
961 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
962 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
963 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
964 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
965 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
967 hr = CoRevokeClassObject(pdwReg1);
968 ok_ole_success(hr, CoRevokeClassObject);
970 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
971 strcat(szDisplayNameFile, "\\kernel32.dll");
972 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
973 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
974 ok_ole_success(hr, MkParseDisplayName);
975 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
976 if (pmk)
978 IMoniker_IsSystemMoniker(pmk, &moniker_type);
979 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
980 IMoniker_Release(pmk);
983 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
984 ok_ole_success(hr, MkParseDisplayName);
985 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1, "Processed character count should have been 43 instead of %u\n", eaten);
987 if (pmk)
989 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
990 ok_ole_success(hr, IMoniker_BindToObject);
992 if (SUCCEEDED(hr))
993 IUnknown_Release(object);
994 IMoniker_Release(pmk);
996 IBindCtx_Release(pbc);
998 /* Test the EnumMoniker interface */
999 hr = CreateBindCtx(0, &pbc);
1000 ok_ole_success(hr, CreateBindCtx);
1002 hr = CreateFileMoniker(wszFileName1, &pmk1);
1003 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1004 hr = CreateFileMoniker(wszFileName2, &pmk2);
1005 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1006 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1007 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
1009 /* Check EnumMoniker before registering */
1010 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1011 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1012 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
1013 /* Register a couple of Monikers and check is ok */
1014 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
1016 matchCnt = count_moniker_matches(pbc, spEM1);
1017 trace("Number of matches is %i\n", matchCnt);
1019 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1020 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1021 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
1022 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
1024 trace("IROT::Register\n");
1025 grflags=0;
1026 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1027 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1028 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
1029 pprot, grflags, lpEM1, pmk2, pdwReg2);
1031 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1032 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1034 matchCnt = count_moniker_matches(pbc, spEM2);
1035 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1037 trace("IEnumMoniker::Clone\n");
1038 IEnumMoniker_Clone(spEM2, &spEM3);
1040 matchCnt = count_moniker_matches(pbc, spEM3);
1041 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1042 trace("IEnumMoniker::Reset\n");
1043 IEnumMoniker_Reset(spEM3);
1045 matchCnt = count_moniker_matches(pbc, spEM3);
1046 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1048 IRunningObjectTable_Revoke(pprot,pdwReg1);
1049 IRunningObjectTable_Revoke(pprot,pdwReg2);
1050 IUnknown_Release(lpEM1);
1051 IEnumMoniker_Release(spEM1);
1052 IEnumMoniker_Release(spEM2);
1053 IEnumMoniker_Release(spEM3);
1054 IMoniker_Release(pmk1);
1055 IMoniker_Release(pmk2);
1056 IRunningObjectTable_Release(pprot);
1058 IBindCtx_Release(pbc);
1061 static const LARGE_INTEGER llZero;
1063 static const BYTE expected_class_moniker_marshal_data[] =
1065 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1066 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1067 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1068 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1069 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1070 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1071 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1072 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1073 0x00,0x00,0x00,0x00,
1076 static const BYTE expected_class_moniker_saved_data[] =
1078 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1079 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1080 0x00,0x00,0x00,0x00,
1083 static const BYTE expected_class_moniker_comparison_data[] =
1085 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1086 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1087 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1088 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1091 static const WCHAR expected_class_moniker_display_name[] =
1093 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1094 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1095 '0','0','0','0','4','6',':',0
1098 static const BYTE expected_item_moniker_comparison_data[] =
1100 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1101 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1102 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1103 0x54,0x00,0x00,0x00,
1106 static const BYTE expected_item_moniker_saved_data[] =
1108 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1109 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1112 static const BYTE expected_item_moniker_marshal_data[] =
1114 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1115 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1116 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1117 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1118 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1119 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1120 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1121 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1124 static const BYTE expected_anti_moniker_marshal_data[] =
1126 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1127 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1128 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1129 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1130 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1131 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1132 0x01,0x00,0x00,0x00,
1135 static const BYTE expected_anti_moniker_saved_data[] =
1137 0x01,0x00,0x00,0x00,
1140 static const BYTE expected_anti_moniker_comparison_data[] =
1142 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1143 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1144 0x01,0x00,0x00,0x00,
1147 static const BYTE expected_gc_moniker_marshal_data[] =
1149 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1150 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1151 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1152 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1153 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1154 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1155 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1156 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1157 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1158 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1159 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1160 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1161 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1162 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1163 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1164 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1165 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1166 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1167 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1168 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1169 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1170 0x00,0x57,0x69,0x6e,0x65,0x00,
1173 static const BYTE expected_gc_moniker_saved_data[] =
1175 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1176 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1177 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1178 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1179 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1180 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1181 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1182 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1183 0x65,0x00,
1186 static const BYTE expected_gc_moniker_comparison_data[] =
1188 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1189 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1190 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1191 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1192 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1193 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1194 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1195 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1196 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1199 static void test_moniker(
1200 const char *testname, IMoniker *moniker,
1201 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1202 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1203 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1204 LPCWSTR expected_display_name)
1206 IStream * stream;
1207 IROTData * rotdata;
1208 HRESULT hr;
1209 HGLOBAL hglobal;
1210 LPBYTE moniker_data;
1211 DWORD moniker_size;
1212 DWORD i;
1213 BOOL same;
1214 BYTE buffer[128];
1215 IMoniker * moniker_proxy;
1216 LPOLESTR display_name;
1217 IBindCtx *bindctx;
1219 hr = IMoniker_IsDirty(moniker);
1220 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1222 /* Display Name */
1224 hr = CreateBindCtx(0, &bindctx);
1225 ok_ole_success(hr, CreateBindCtx);
1227 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1228 ok_ole_success(hr, IMoniker_GetDisplayName);
1229 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1231 CoTaskMemFree(display_name);
1232 IBindCtx_Release(bindctx);
1234 hr = IMoniker_IsDirty(moniker);
1235 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1237 /* IROTData::GetComparisonData test */
1239 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1240 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1242 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1243 ok_ole_success(hr, IROTData_GetComparisonData);
1245 if (hr != S_OK) moniker_size = 0;
1247 /* first check we have the right amount of data */
1248 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1249 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1250 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1252 /* then do a byte-by-byte comparison */
1253 same = TRUE;
1254 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1256 if (expected_moniker_comparison_data[i] != buffer[i])
1258 same = FALSE;
1259 break;
1263 ok(same, "%s: Comparison data differs\n", testname);
1264 if (!same)
1266 for (i = 0; i < moniker_size; i++)
1268 if (i % 8 == 0) printf(" ");
1269 printf("0x%02x,", buffer[i]);
1270 if (i % 8 == 7) printf("\n");
1272 printf("\n");
1275 IROTData_Release(rotdata);
1277 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1278 ok_ole_success(hr, CreateStreamOnHGlobal);
1280 /* Saving */
1282 hr = IMoniker_Save(moniker, stream, TRUE);
1283 ok_ole_success(hr, IMoniker_Save);
1285 hr = GetHGlobalFromStream(stream, &hglobal);
1286 ok_ole_success(hr, GetHGlobalFromStream);
1288 moniker_size = GlobalSize(hglobal);
1290 moniker_data = GlobalLock(hglobal);
1292 /* first check we have the right amount of data */
1293 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1294 "%s: Size of saved data differs (expected %d, actual %d)\n",
1295 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1297 /* then do a byte-by-byte comparison */
1298 same = TRUE;
1299 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1301 if (expected_moniker_saved_data[i] != moniker_data[i])
1303 same = FALSE;
1304 break;
1308 ok(same, "%s: Saved data differs\n", testname);
1309 if (!same)
1311 for (i = 0; i < moniker_size; i++)
1313 if (i % 8 == 0) printf(" ");
1314 printf("0x%02x,", moniker_data[i]);
1315 if (i % 8 == 7) printf("\n");
1317 printf("\n");
1320 GlobalUnlock(hglobal);
1322 IStream_Release(stream);
1324 /* Marshaling tests */
1326 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1327 ok_ole_success(hr, CreateStreamOnHGlobal);
1329 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1330 ok_ole_success(hr, CoMarshalInterface);
1332 hr = GetHGlobalFromStream(stream, &hglobal);
1333 ok_ole_success(hr, GetHGlobalFromStream);
1335 moniker_size = GlobalSize(hglobal);
1337 moniker_data = GlobalLock(hglobal);
1339 /* first check we have the right amount of data */
1340 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1341 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1342 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1344 /* then do a byte-by-byte comparison */
1345 same = TRUE;
1346 if (expected_moniker_marshal_data)
1348 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1350 if (expected_moniker_marshal_data[i] != moniker_data[i])
1352 same = FALSE;
1353 break;
1358 ok(same, "%s: Marshaled data differs\n", testname);
1359 if (!same)
1361 for (i = 0; i < moniker_size; i++)
1363 if (i % 8 == 0) printf(" ");
1364 printf("0x%02x,", moniker_data[i]);
1365 if (i % 8 == 7) printf("\n");
1367 printf("\n");
1370 GlobalUnlock(hglobal);
1372 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1373 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1374 ok_ole_success(hr, CoUnmarshalInterface);
1376 IStream_Release(stream);
1377 IMoniker_Release(moniker_proxy);
1380 static void test_class_moniker(void)
1382 HRESULT hr;
1383 IMoniker *moniker;
1384 DWORD moniker_type;
1385 DWORD hash;
1386 IBindCtx *bindctx;
1387 IMoniker *inverse;
1388 IUnknown *unknown;
1389 FILETIME filetime;
1391 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1392 ok_ole_success(hr, CreateClassMoniker);
1393 if (!moniker) return;
1395 test_moniker("class moniker", moniker,
1396 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1397 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1398 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1399 expected_class_moniker_display_name);
1401 /* Hashing */
1403 hr = IMoniker_Hash(moniker, &hash);
1404 ok_ole_success(hr, IMoniker_Hash);
1406 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1407 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1408 hash);
1410 /* IsSystemMoniker test */
1412 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1413 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1415 ok(moniker_type == MKSYS_CLASSMONIKER,
1416 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1417 moniker_type);
1419 hr = CreateBindCtx(0, &bindctx);
1420 ok_ole_success(hr, CreateBindCtx);
1422 /* IsRunning test */
1423 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1424 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1426 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1427 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1429 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1430 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1432 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1433 ok_ole_success(hr, IMoniker_BindToObject);
1434 IUnknown_Release(unknown);
1436 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1437 ok_ole_success(hr, IMoniker_BindToStorage);
1438 IUnknown_Release(unknown);
1440 IBindCtx_Release(bindctx);
1442 hr = IMoniker_Inverse(moniker, &inverse);
1443 ok_ole_success(hr, IMoniker_Inverse);
1444 IMoniker_Release(inverse);
1446 IMoniker_Release(moniker);
1449 static void test_file_moniker(WCHAR* path)
1451 IStream *stream;
1452 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1453 HRESULT hr;
1455 hr = CreateFileMoniker(path, &moniker1);
1456 ok_ole_success(hr, CreateFileMoniker);
1458 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1459 ok_ole_success(hr, CreateStreamOnHGlobal);
1461 /* Marshal */
1462 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1463 ok_ole_success(hr, CoMarshalInterface);
1465 /* Rewind */
1466 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1467 ok_ole_success(hr, IStream_Seek);
1469 /* Unmarshal */
1470 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1471 ok_ole_success(hr, CoUnmarshalInterface);
1473 hr = IMoniker_IsEqual(moniker1, moniker2);
1474 ok_ole_success(hr, IsEqual);
1476 IStream_Release(stream);
1477 if (moniker1)
1478 IMoniker_Release(moniker1);
1479 if (moniker2)
1480 IMoniker_Release(moniker2);
1483 static void test_file_monikers(void)
1485 static WCHAR wszFile[][30] = {
1486 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1487 {'\\', '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},
1488 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1489 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1490 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1491 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1492 * U+0100 .. = Latin extended-A
1494 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1497 int i;
1499 trace("ACP is %u\n", GetACP());
1501 for (i = 0; i < COUNTOF(wszFile); ++i)
1503 int j ;
1504 if (i == 2)
1506 BOOL used;
1507 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1508 if (used)
1510 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1511 continue;
1514 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1516 wszFile[i][j] = 0;
1517 test_file_moniker(wszFile[i]);
1522 static void test_item_moniker(void)
1524 HRESULT hr;
1525 IMoniker *moniker;
1526 DWORD moniker_type;
1527 DWORD hash;
1528 IBindCtx *bindctx;
1529 IMoniker *inverse;
1530 IUnknown *unknown;
1531 static const WCHAR wszDelimeter[] = {'!',0};
1532 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1533 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1535 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1536 ok_ole_success(hr, CreateItemMoniker);
1538 test_moniker("item moniker", moniker,
1539 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1540 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1541 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1542 expected_display_name);
1544 /* Hashing */
1546 hr = IMoniker_Hash(moniker, &hash);
1547 ok_ole_success(hr, IMoniker_Hash);
1549 ok(hash == 0x73c,
1550 "Hash value != 0x73c, instead was 0x%08x\n",
1551 hash);
1553 /* IsSystemMoniker test */
1555 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1556 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1558 ok(moniker_type == MKSYS_ITEMMONIKER,
1559 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1560 moniker_type);
1562 hr = CreateBindCtx(0, &bindctx);
1563 ok_ole_success(hr, CreateBindCtx);
1565 /* IsRunning test */
1566 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1567 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1569 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1570 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1572 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1573 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1575 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1576 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1578 IBindCtx_Release(bindctx);
1580 hr = IMoniker_Inverse(moniker, &inverse);
1581 ok_ole_success(hr, IMoniker_Inverse);
1582 IMoniker_Release(inverse);
1584 IMoniker_Release(moniker);
1587 static void test_anti_moniker(void)
1589 HRESULT hr;
1590 IMoniker *moniker;
1591 DWORD moniker_type;
1592 DWORD hash;
1593 IBindCtx *bindctx;
1594 FILETIME filetime;
1595 IMoniker *inverse;
1596 IUnknown *unknown;
1597 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1599 hr = CreateAntiMoniker(&moniker);
1600 ok_ole_success(hr, CreateAntiMoniker);
1601 if (!moniker) return;
1603 test_moniker("anti moniker", moniker,
1604 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1605 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1606 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1607 expected_display_name);
1609 /* Hashing */
1610 hr = IMoniker_Hash(moniker, &hash);
1611 ok_ole_success(hr, IMoniker_Hash);
1612 ok(hash == 0x80000001,
1613 "Hash value != 0x80000001, instead was 0x%08x\n",
1614 hash);
1616 /* IsSystemMoniker test */
1617 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1618 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1619 ok(moniker_type == MKSYS_ANTIMONIKER,
1620 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1621 moniker_type);
1623 hr = IMoniker_Inverse(moniker, &inverse);
1624 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1625 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1627 hr = CreateBindCtx(0, &bindctx);
1628 ok_ole_success(hr, CreateBindCtx);
1630 /* IsRunning test */
1631 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1632 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1634 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1635 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1637 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1638 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1640 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1641 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1643 IBindCtx_Release(bindctx);
1645 IMoniker_Release(moniker);
1648 static void test_generic_composite_moniker(void)
1650 HRESULT hr;
1651 IMoniker *moniker;
1652 IMoniker *moniker1;
1653 IMoniker *moniker2;
1654 DWORD moniker_type;
1655 DWORD hash;
1656 IBindCtx *bindctx;
1657 FILETIME filetime;
1658 IMoniker *inverse;
1659 IUnknown *unknown;
1660 static const WCHAR wszDelimeter1[] = {'!',0};
1661 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1662 static const WCHAR wszDelimeter2[] = {'#',0};
1663 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1664 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1666 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1667 ok_ole_success(hr, CreateItemMoniker);
1668 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1669 ok_ole_success(hr, CreateItemMoniker);
1670 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1671 ok_ole_success(hr, CreateGenericComposite);
1673 test_moniker("generic composite moniker", moniker,
1674 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1675 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1676 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1677 expected_display_name);
1679 /* Hashing */
1681 hr = IMoniker_Hash(moniker, &hash);
1682 ok_ole_success(hr, IMoniker_Hash);
1684 ok(hash == 0xd87,
1685 "Hash value != 0xd87, instead was 0x%08x\n",
1686 hash);
1688 /* IsSystemMoniker test */
1690 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1691 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1693 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1694 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1695 moniker_type);
1697 hr = CreateBindCtx(0, &bindctx);
1698 ok_ole_success(hr, CreateBindCtx);
1700 /* IsRunning test */
1701 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1702 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1704 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1705 todo_wine
1706 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1708 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1709 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1711 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1712 todo_wine
1713 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1715 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1716 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1718 IBindCtx_Release(bindctx);
1720 hr = IMoniker_Inverse(moniker, &inverse);
1721 ok_ole_success(hr, IMoniker_Inverse);
1722 IMoniker_Release(inverse);
1724 IMoniker_Release(moniker);
1727 static void test_pointer_moniker(void)
1729 HRESULT hr;
1730 IMoniker *moniker;
1731 DWORD moniker_type;
1732 DWORD hash;
1733 IBindCtx *bindctx;
1734 FILETIME filetime;
1735 IMoniker *inverse;
1736 IUnknown *unknown;
1737 IStream *stream;
1738 IROTData *rotdata;
1739 LPOLESTR display_name;
1741 cLocks = 0;
1743 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1744 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1746 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1747 ok_ole_success(hr, CreatePointerMoniker);
1748 if (!moniker) return;
1750 ok_more_than_one_lock();
1752 /* Display Name */
1754 hr = CreateBindCtx(0, &bindctx);
1755 ok_ole_success(hr, CreateBindCtx);
1757 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1758 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1760 IBindCtx_Release(bindctx);
1762 hr = IMoniker_IsDirty(moniker);
1763 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1765 /* IROTData::GetComparisonData test */
1767 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1768 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1770 /* Saving */
1772 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1773 ok_ole_success(hr, CreateStreamOnHGlobal);
1775 hr = IMoniker_Save(moniker, stream, TRUE);
1776 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1778 IStream_Release(stream);
1780 /* Hashing */
1781 hr = IMoniker_Hash(moniker, &hash);
1782 ok_ole_success(hr, IMoniker_Hash);
1783 ok(hash == (DWORD)&Test_ClassFactory,
1784 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1785 (DWORD)&Test_ClassFactory, hash);
1787 /* IsSystemMoniker test */
1788 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1789 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1790 ok(moniker_type == MKSYS_POINTERMONIKER,
1791 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1792 moniker_type);
1794 hr = IMoniker_Inverse(moniker, &inverse);
1795 ok_ole_success(hr, IMoniker_Inverse);
1796 IMoniker_Release(inverse);
1798 hr = CreateBindCtx(0, &bindctx);
1799 ok_ole_success(hr, CreateBindCtx);
1801 /* IsRunning test */
1802 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1803 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1805 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1806 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1808 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1809 ok_ole_success(hr, IMoniker_BindToObject);
1810 IUnknown_Release(unknown);
1812 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1813 ok_ole_success(hr, IMoniker_BindToStorage);
1814 IUnknown_Release(unknown);
1816 IMoniker_Release(moniker);
1818 ok_no_locks();
1820 hr = CreatePointerMoniker(NULL, &moniker);
1821 ok_ole_success(hr, CreatePointerMoniker);
1823 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1824 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1826 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1827 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1829 IBindCtx_Release(bindctx);
1831 IMoniker_Release(moniker);
1834 static void test_bind_context(void)
1836 HRESULT hr;
1837 IBindCtx *pBindCtx;
1838 IEnumString *pEnumString;
1839 BIND_OPTS2 bind_opts;
1840 HeapUnknown *unknown;
1841 HeapUnknown *unknown2;
1842 IUnknown *param_obj;
1843 ULONG refs;
1844 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1845 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1847 hr = CreateBindCtx(0, NULL);
1848 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1850 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1851 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1853 hr = CreateBindCtx(0, &pBindCtx);
1854 ok_ole_success(hr, "CreateBindCtx");
1856 bind_opts.cbStruct = -1;
1857 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1858 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1859 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1860 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1861 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1863 bind_opts.cbStruct = sizeof(BIND_OPTS);
1864 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1865 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1866 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1868 bind_opts.cbStruct = sizeof(bind_opts);
1869 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1870 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1871 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1872 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1873 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1874 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1875 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1876 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1877 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1878 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1879 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1881 bind_opts.cbStruct = -1;
1882 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1883 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1885 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1886 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1888 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1889 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1890 unknown->refs = 1;
1891 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface);
1892 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1894 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1895 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1896 IUnknown_Release(param_obj);
1898 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1899 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1900 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1902 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1903 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1905 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1906 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1907 ok(!pEnumString, "pEnumString should be NULL\n");
1909 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1910 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1912 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1913 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1915 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1916 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1917 unknown2->refs = 1;
1918 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1919 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1921 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1922 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1924 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1925 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1927 IBindCtx_Release(pBindCtx);
1929 refs = IUnknown_Release(&unknown->IUnknown_iface);
1930 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1932 refs = IUnknown_Release(&unknown2->IUnknown_iface);
1933 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1936 static void test_save_load_filemoniker(void)
1938 IMoniker* pMk;
1939 IStream* pStm;
1940 HRESULT hr;
1941 ULARGE_INTEGER size;
1942 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
1943 DWORD some_val = 0xFEDCBA98;
1944 int i;
1946 /* see FileMonikerImpl_Save docs */
1947 zero_pos.QuadPart = 0;
1948 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
1949 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
1951 /* create the stream we're going to write to */
1952 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
1953 ok_ole_success(hr, "CreateStreamOnHGlobal");
1955 size.u.LowPart = 128;
1956 hr = IStream_SetSize(pStm, size);
1957 ok_ole_success(hr, "IStream_SetSize");
1959 /* create and save a moniker */
1960 hr = CreateFileMoniker(wszFileName1, &pMk);
1961 ok_ole_success(hr, "CreateFileMoniker");
1963 hr = IMoniker_Save(pMk, pStm, TRUE);
1964 ok_ole_success(hr, "IMoniker_Save");
1966 hr = IMoniker_Release(pMk);
1967 ok_ole_success(hr, "IMoniker_Release");
1969 /* overwrite the constants with various values */
1970 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1971 ok_ole_success(hr, "IStream_Seek");
1972 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1973 ok_ole_success(hr, "IStream_Write");
1975 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
1976 ok_ole_success(hr, "IStream_Seek");
1977 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1978 ok_ole_success(hr, "IStream_Write");
1980 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
1981 ok_ole_success(hr, "IStream_Seek");
1982 for(i = 0; i < 5; ++i){
1983 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
1984 ok_ole_success(hr, "IStream_Write");
1987 /* go back to the start of the stream */
1988 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1989 ok_ole_success(hr, "IStream_Seek");
1991 /* create a new moniker and load into it */
1992 hr = CreateFileMoniker(wszFileName1, &pMk);
1993 ok_ole_success(hr, "CreateFileMoniker");
1995 hr = IMoniker_Load(pMk, pStm);
1996 ok_ole_success(hr, "IMoniker_Load");
1998 hr = IMoniker_Release(pMk);
1999 ok_ole_success(hr, "IMoniker_Release");
2001 hr = IStream_Release(pStm);
2002 ok_ole_success(hr, "IStream_Release");
2005 START_TEST(moniker)
2007 if (!GetProcAddress(GetModuleHandleA("ole32.dll"), "CoRegisterSurrogateEx")) {
2008 win_skip("skipping test on win9x\n");
2009 return;
2012 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2014 test_ROT();
2015 test_ROT_multiple_entries();
2016 test_MkParseDisplayName();
2017 test_class_moniker();
2018 test_file_monikers();
2019 test_item_moniker();
2020 test_anti_moniker();
2021 test_generic_composite_moniker();
2022 test_pointer_moniker();
2023 test_save_load_filemoniker();
2025 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2027 test_bind_context();
2029 CoUninitialize();