widl: Don't free the input file name since it's stored in various places in the locat...
[wine.git] / dlls / ole32 / tests / moniker.c
blobeb7973e4584ddc33ea497847abda0c067f026eab
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);
1015 hr = MK_E_NOOBJECT;
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);
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);
1460 /* Marshal */
1461 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1462 ok_ole_success(hr, CoMarshalInterface);
1464 /* Rewind */
1465 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1466 ok_ole_success(hr, IStream_Seek);
1468 /* Unmarshal */
1469 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1470 ok_ole_success(hr, CoUnmarshalInterface);
1472 hr = IMoniker_IsEqual(moniker1, moniker2);
1473 ok_ole_success(hr, IsEqual);
1475 IStream_Release(stream);
1476 if (moniker1)
1477 IMoniker_Release(moniker1);
1478 if (moniker2)
1479 IMoniker_Release(moniker2);
1482 static void test_file_monikers(void)
1484 static WCHAR wszFile[][30] = {
1485 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1486 {'\\', '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},
1487 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1488 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1489 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1490 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1491 * U+0100 .. = Latin extended-A
1493 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1496 int i;
1498 trace("ACP is %u\n", GetACP());
1500 for (i = 0; i < COUNTOF(wszFile); ++i)
1502 int j ;
1503 if (i == 2)
1505 BOOL used;
1506 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1507 if (used)
1509 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1510 continue;
1513 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1515 wszFile[i][j] = 0;
1516 test_file_moniker(wszFile[i]);
1521 static void test_item_moniker(void)
1523 HRESULT hr;
1524 IMoniker *moniker;
1525 DWORD moniker_type;
1526 DWORD hash;
1527 IBindCtx *bindctx;
1528 IMoniker *inverse;
1529 IUnknown *unknown;
1530 static const WCHAR wszDelimeter[] = {'!',0};
1531 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1532 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1534 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1535 ok_ole_success(hr, CreateItemMoniker);
1537 test_moniker("item moniker", moniker,
1538 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1539 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1540 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1541 expected_display_name);
1543 /* Hashing */
1545 hr = IMoniker_Hash(moniker, &hash);
1546 ok_ole_success(hr, IMoniker_Hash);
1548 ok(hash == 0x73c,
1549 "Hash value != 0x73c, instead was 0x%08x\n",
1550 hash);
1552 /* IsSystemMoniker test */
1554 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1555 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1557 ok(moniker_type == MKSYS_ITEMMONIKER,
1558 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1559 moniker_type);
1561 hr = CreateBindCtx(0, &bindctx);
1562 ok_ole_success(hr, CreateBindCtx);
1564 /* IsRunning test */
1565 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1566 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1568 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1569 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1571 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1572 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1574 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1575 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1577 IBindCtx_Release(bindctx);
1579 hr = IMoniker_Inverse(moniker, &inverse);
1580 ok_ole_success(hr, IMoniker_Inverse);
1581 IMoniker_Release(inverse);
1583 IMoniker_Release(moniker);
1586 static void test_anti_moniker(void)
1588 HRESULT hr;
1589 IMoniker *moniker;
1590 DWORD moniker_type;
1591 DWORD hash;
1592 IBindCtx *bindctx;
1593 FILETIME filetime;
1594 IMoniker *inverse;
1595 IUnknown *unknown;
1596 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1598 hr = CreateAntiMoniker(&moniker);
1599 ok_ole_success(hr, CreateAntiMoniker);
1600 if (!moniker) return;
1602 test_moniker("anti moniker", moniker,
1603 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1604 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1605 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1606 expected_display_name);
1608 /* Hashing */
1609 hr = IMoniker_Hash(moniker, &hash);
1610 ok_ole_success(hr, IMoniker_Hash);
1611 ok(hash == 0x80000001,
1612 "Hash value != 0x80000001, instead was 0x%08x\n",
1613 hash);
1615 /* IsSystemMoniker test */
1616 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1617 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1618 ok(moniker_type == MKSYS_ANTIMONIKER,
1619 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1620 moniker_type);
1622 hr = IMoniker_Inverse(moniker, &inverse);
1623 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1624 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1626 hr = CreateBindCtx(0, &bindctx);
1627 ok_ole_success(hr, CreateBindCtx);
1629 /* IsRunning test */
1630 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1631 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1633 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1634 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1636 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1637 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1639 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1640 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1642 IBindCtx_Release(bindctx);
1644 IMoniker_Release(moniker);
1647 static void test_generic_composite_moniker(void)
1649 HRESULT hr;
1650 IMoniker *moniker;
1651 IMoniker *moniker1;
1652 IMoniker *moniker2;
1653 DWORD moniker_type;
1654 DWORD hash;
1655 IBindCtx *bindctx;
1656 FILETIME filetime;
1657 IMoniker *inverse;
1658 IUnknown *unknown;
1659 static const WCHAR wszDelimeter1[] = {'!',0};
1660 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1661 static const WCHAR wszDelimeter2[] = {'#',0};
1662 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1663 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1665 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1666 ok_ole_success(hr, CreateItemMoniker);
1667 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1668 ok_ole_success(hr, CreateItemMoniker);
1669 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1670 ok_ole_success(hr, CreateGenericComposite);
1672 test_moniker("generic composite moniker", moniker,
1673 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1674 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1675 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1676 expected_display_name);
1678 /* Hashing */
1680 hr = IMoniker_Hash(moniker, &hash);
1681 ok_ole_success(hr, IMoniker_Hash);
1683 ok(hash == 0xd87,
1684 "Hash value != 0xd87, instead was 0x%08x\n",
1685 hash);
1687 /* IsSystemMoniker test */
1689 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1690 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1692 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1693 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1694 moniker_type);
1696 hr = CreateBindCtx(0, &bindctx);
1697 ok_ole_success(hr, CreateBindCtx);
1699 /* IsRunning test */
1700 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1701 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1703 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1704 todo_wine
1705 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1707 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1708 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1710 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1711 todo_wine
1712 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1714 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1715 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1717 IBindCtx_Release(bindctx);
1719 hr = IMoniker_Inverse(moniker, &inverse);
1720 ok_ole_success(hr, IMoniker_Inverse);
1721 IMoniker_Release(inverse);
1723 IMoniker_Release(moniker);
1726 static void test_pointer_moniker(void)
1728 HRESULT hr;
1729 IMoniker *moniker;
1730 DWORD moniker_type;
1731 DWORD hash;
1732 IBindCtx *bindctx;
1733 FILETIME filetime;
1734 IMoniker *inverse;
1735 IUnknown *unknown;
1736 IStream *stream;
1737 IROTData *rotdata;
1738 LPOLESTR display_name;
1740 cLocks = 0;
1742 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1743 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1745 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1746 ok_ole_success(hr, CreatePointerMoniker);
1747 if (!moniker) return;
1749 ok_more_than_one_lock();
1751 /* Display Name */
1753 hr = CreateBindCtx(0, &bindctx);
1754 ok_ole_success(hr, CreateBindCtx);
1756 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1757 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1759 IBindCtx_Release(bindctx);
1761 hr = IMoniker_IsDirty(moniker);
1762 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1764 /* IROTData::GetComparisonData test */
1766 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1767 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1769 /* Saving */
1771 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1772 ok_ole_success(hr, CreateStreamOnHGlobal);
1774 hr = IMoniker_Save(moniker, stream, TRUE);
1775 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1777 IStream_Release(stream);
1779 /* Hashing */
1780 hr = IMoniker_Hash(moniker, &hash);
1781 ok_ole_success(hr, IMoniker_Hash);
1782 ok(hash == (DWORD)&Test_ClassFactory,
1783 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1784 (DWORD)&Test_ClassFactory, hash);
1786 /* IsSystemMoniker test */
1787 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1788 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1789 ok(moniker_type == MKSYS_POINTERMONIKER,
1790 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1791 moniker_type);
1793 hr = IMoniker_Inverse(moniker, &inverse);
1794 ok_ole_success(hr, IMoniker_Inverse);
1795 IMoniker_Release(inverse);
1797 hr = CreateBindCtx(0, &bindctx);
1798 ok_ole_success(hr, CreateBindCtx);
1800 /* IsRunning test */
1801 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1802 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1804 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1805 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1807 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1808 ok_ole_success(hr, IMoniker_BindToObject);
1809 IUnknown_Release(unknown);
1811 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1812 ok_ole_success(hr, IMoniker_BindToStorage);
1813 IUnknown_Release(unknown);
1815 IMoniker_Release(moniker);
1817 ok_no_locks();
1819 hr = CreatePointerMoniker(NULL, &moniker);
1820 ok_ole_success(hr, CreatePointerMoniker);
1822 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1823 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1825 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1826 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1828 IBindCtx_Release(bindctx);
1830 IMoniker_Release(moniker);
1833 static void test_bind_context(void)
1835 HRESULT hr;
1836 IBindCtx *pBindCtx;
1837 IEnumString *pEnumString;
1838 BIND_OPTS2 bind_opts;
1839 HeapUnknown *unknown;
1840 HeapUnknown *unknown2;
1841 IUnknown *param_obj;
1842 ULONG refs;
1843 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1844 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1846 hr = CreateBindCtx(0, NULL);
1847 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1849 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1850 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1852 hr = CreateBindCtx(0, &pBindCtx);
1853 ok_ole_success(hr, "CreateBindCtx");
1855 bind_opts.cbStruct = -1;
1856 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1857 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1858 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1859 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1860 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1862 bind_opts.cbStruct = sizeof(BIND_OPTS);
1863 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1864 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1865 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1867 bind_opts.cbStruct = sizeof(bind_opts);
1868 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1869 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1870 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1871 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1872 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1873 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1874 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1875 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1876 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1877 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1878 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1880 bind_opts.cbStruct = -1;
1881 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1882 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1884 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1885 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1887 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1888 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1889 unknown->refs = 1;
1890 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface);
1891 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1893 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1894 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1895 IUnknown_Release(param_obj);
1897 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1898 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1899 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1901 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1902 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1904 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1905 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1906 ok(!pEnumString, "pEnumString should be NULL\n");
1908 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1909 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1911 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1912 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1914 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1915 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1916 unknown2->refs = 1;
1917 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1918 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1920 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1921 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1923 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1924 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1926 IBindCtx_Release(pBindCtx);
1928 refs = IUnknown_Release(&unknown->IUnknown_iface);
1929 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1931 refs = IUnknown_Release(&unknown2->IUnknown_iface);
1932 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1935 static void test_save_load_filemoniker(void)
1937 IMoniker* pMk;
1938 IStream* pStm;
1939 HRESULT hr;
1940 ULARGE_INTEGER size;
1941 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
1942 DWORD some_val = 0xFEDCBA98;
1943 int i;
1945 /* see FileMonikerImpl_Save docs */
1946 zero_pos.QuadPart = 0;
1947 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
1948 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
1950 /* create the stream we're going to write to */
1951 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
1952 ok_ole_success(hr, "CreateStreamOnHGlobal");
1954 size.u.LowPart = 128;
1955 hr = IStream_SetSize(pStm, size);
1956 ok_ole_success(hr, "IStream_SetSize");
1958 /* create and save a moniker */
1959 hr = CreateFileMoniker(wszFileName1, &pMk);
1960 ok_ole_success(hr, "CreateFileMoniker");
1962 hr = IMoniker_Save(pMk, pStm, TRUE);
1963 ok_ole_success(hr, "IMoniker_Save");
1965 hr = IMoniker_Release(pMk);
1966 ok_ole_success(hr, "IMoniker_Release");
1968 /* overwrite the constants with various values */
1969 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1970 ok_ole_success(hr, "IStream_Seek");
1971 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1972 ok_ole_success(hr, "IStream_Write");
1974 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
1975 ok_ole_success(hr, "IStream_Seek");
1976 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1977 ok_ole_success(hr, "IStream_Write");
1979 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
1980 ok_ole_success(hr, "IStream_Seek");
1981 for(i = 0; i < 5; ++i){
1982 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
1983 ok_ole_success(hr, "IStream_Write");
1986 /* go back to the start of the stream */
1987 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1988 ok_ole_success(hr, "IStream_Seek");
1990 /* create a new moniker and load into it */
1991 hr = CreateFileMoniker(wszFileName1, &pMk);
1992 ok_ole_success(hr, "CreateFileMoniker");
1994 hr = IMoniker_Load(pMk, pStm);
1995 ok_ole_success(hr, "IMoniker_Load");
1997 hr = IMoniker_Release(pMk);
1998 ok_ole_success(hr, "IMoniker_Release");
2000 hr = IStream_Release(pStm);
2001 ok_ole_success(hr, "IStream_Release");
2004 START_TEST(moniker)
2006 if (!GetProcAddress(GetModuleHandleA("ole32.dll"), "CoRegisterSurrogateEx")) {
2007 win_skip("skipping test on win9x\n");
2008 return;
2011 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2013 test_ROT();
2014 test_ROT_multiple_entries();
2015 test_MkParseDisplayName();
2016 test_class_moniker();
2017 test_file_monikers();
2018 test_item_moniker();
2019 test_anti_moniker();
2020 test_generic_composite_moniker();
2021 test_pointer_moniker();
2022 test_save_load_filemoniker();
2024 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2026 test_bind_context();
2028 CoUninitialize();