configure: Changes from running autconf after previous patch.
[wine/hacks.git] / dlls / ole32 / tests / moniker.c
blob876d034bcbc92b7c7295f569ad66111f12b0dcea
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 const IUnknownVtbl *lpVtbl;
160 ULONG refs;
161 } HeapUnknown;
163 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
165 if (IsEqualIID(riid, &IID_IUnknown))
167 IUnknown_AddRef(iface);
168 *ppv = iface;
169 return S_OK;
171 *ppv = NULL;
172 return E_NOINTERFACE;
175 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
177 HeapUnknown *This = (HeapUnknown *)iface;
178 return InterlockedIncrement((LONG*)&This->refs);
181 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
183 HeapUnknown *This = (HeapUnknown *)iface;
184 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
185 if (!refs) HeapFree(GetProcessHeap(), 0, This);
186 return refs;
189 static const IUnknownVtbl HeapUnknown_Vtbl =
191 HeapUnknown_QueryInterface,
192 HeapUnknown_AddRef,
193 HeapUnknown_Release
196 static HRESULT WINAPI
197 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
199 if (!ppvObject)
200 return E_INVALIDARG;
202 *ppvObject = 0;
204 if (IsEqualIID(&IID_IUnknown, riid) ||
205 IsEqualIID(&IID_IPersist, riid) ||
206 IsEqualIID(&IID_IPersistStream,riid) ||
207 IsEqualIID(&IID_IMoniker, riid))
208 *ppvObject = iface;
209 if (IsEqualIID(&IID_IROTData, riid))
210 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
212 if ((*ppvObject)==0)
213 return E_NOINTERFACE;
215 IMoniker_AddRef(iface);
217 return S_OK;
220 static ULONG WINAPI
221 Moniker_AddRef(IMoniker* iface)
223 return 2;
226 static ULONG WINAPI
227 Moniker_Release(IMoniker* iface)
229 return 1;
232 static HRESULT WINAPI
233 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
235 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
237 *pClassID = CLSID_TestMoniker;
239 return S_OK;
242 static HRESULT WINAPI
243 Moniker_IsDirty(IMoniker* iface)
245 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
247 return S_FALSE;
250 static HRESULT WINAPI
251 Moniker_Load(IMoniker* iface, IStream* pStm)
253 CHECK_EXPECTED_METHOD("Moniker_Load");
254 return E_NOTIMPL;
257 static HRESULT WINAPI
258 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
260 CHECK_EXPECTED_METHOD("Moniker_Save");
261 return E_NOTIMPL;
264 static HRESULT WINAPI
265 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
267 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
268 return E_NOTIMPL;
271 static HRESULT WINAPI
272 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
273 REFIID riid, VOID** ppvResult)
275 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
276 return E_NOTIMPL;
279 static HRESULT WINAPI
280 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
281 REFIID riid, VOID** ppvObject)
283 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
284 return E_NOTIMPL;
287 static HRESULT WINAPI
288 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
289 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
291 CHECK_EXPECTED_METHOD("Moniker_Reduce");
293 if (ppmkReduced==NULL)
294 return E_POINTER;
296 IMoniker_AddRef(iface);
298 *ppmkReduced=iface;
300 return MK_S_REDUCED_TO_SELF;
303 static HRESULT WINAPI
304 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
305 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
307 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
308 return E_NOTIMPL;
311 static HRESULT WINAPI
312 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
314 CHECK_EXPECTED_METHOD("Moniker_Enum");
316 if (ppenumMoniker == NULL)
317 return E_POINTER;
319 *ppenumMoniker = NULL;
321 return S_OK;
324 static HRESULT WINAPI
325 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
327 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
328 return E_NOTIMPL;
331 static HRESULT WINAPI
332 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
334 CHECK_EXPECTED_METHOD("Moniker_Hash");
335 return E_NOTIMPL;
338 static HRESULT WINAPI
339 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
340 IMoniker* pmkNewlyRunning)
342 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
343 return E_NOTIMPL;
346 static HRESULT WINAPI
347 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
348 IMoniker* pmkToLeft, FILETIME* pFileTime)
350 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
351 return E_NOTIMPL;
354 static HRESULT WINAPI
355 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
357 CHECK_EXPECTED_METHOD("Moniker_Inverse");
358 return E_NOTIMPL;
361 static HRESULT WINAPI
362 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
364 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
365 return E_NOTIMPL;
368 static HRESULT WINAPI
369 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
371 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
372 return E_NOTIMPL;
375 static HRESULT WINAPI
376 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
377 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
379 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
380 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
381 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
382 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
383 return S_OK;
386 static HRESULT WINAPI
387 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
388 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
390 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
391 return E_NOTIMPL;
394 static HRESULT WINAPI
395 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
397 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
399 if (!pwdMksys)
400 return E_POINTER;
402 (*pwdMksys)=MKSYS_NONE;
404 return S_FALSE;
407 static const IMonikerVtbl MonikerNoROTDataVtbl =
409 MonikerNoROTData_QueryInterface,
410 Moniker_AddRef,
411 Moniker_Release,
412 Moniker_GetClassID,
413 Moniker_IsDirty,
414 Moniker_Load,
415 Moniker_Save,
416 Moniker_GetSizeMax,
417 Moniker_BindToObject,
418 Moniker_BindToStorage,
419 Moniker_Reduce,
420 Moniker_ComposeWith,
421 Moniker_Enum,
422 Moniker_IsEqual,
423 Moniker_Hash,
424 Moniker_IsRunning,
425 Moniker_GetTimeOfLastChange,
426 Moniker_Inverse,
427 Moniker_CommonPrefixWith,
428 Moniker_RelativePathTo,
429 Moniker_GetDisplayName,
430 Moniker_ParseDisplayName,
431 Moniker_IsSystemMoniker
434 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
436 static IMoniker Moniker;
438 static HRESULT WINAPI
439 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
441 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
444 static ULONG WINAPI
445 ROTData_AddRef(IROTData *iface)
447 return 2;
450 static ULONG WINAPI
451 ROTData_Release(IROTData* iface)
453 return 1;
456 static HRESULT WINAPI
457 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
458 ULONG cbMax, ULONG* pcbData)
460 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
462 *pcbData = 1;
463 if (cbMax < *pcbData)
464 return E_OUTOFMEMORY;
466 *pbData = 0xde;
468 return S_OK;
471 static IROTDataVtbl ROTDataVtbl =
473 ROTData_QueryInterface,
474 ROTData_AddRef,
475 ROTData_Release,
476 ROTData_GetComparisonData
479 static IROTData ROTData = { &ROTDataVtbl };
481 static HRESULT WINAPI
482 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
484 if (!ppvObject)
485 return E_INVALIDARG;
487 *ppvObject = 0;
489 if (IsEqualIID(&IID_IUnknown, riid) ||
490 IsEqualIID(&IID_IPersist, riid) ||
491 IsEqualIID(&IID_IPersistStream,riid) ||
492 IsEqualIID(&IID_IMoniker, riid))
493 *ppvObject = iface;
494 if (IsEqualIID(&IID_IROTData, riid))
496 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
497 *ppvObject = &ROTData;
500 if ((*ppvObject)==0)
501 return E_NOINTERFACE;
503 IMoniker_AddRef(iface);
505 return S_OK;
508 static const IMonikerVtbl MonikerVtbl =
510 Moniker_QueryInterface,
511 Moniker_AddRef,
512 Moniker_Release,
513 Moniker_GetClassID,
514 Moniker_IsDirty,
515 Moniker_Load,
516 Moniker_Save,
517 Moniker_GetSizeMax,
518 Moniker_BindToObject,
519 Moniker_BindToStorage,
520 Moniker_Reduce,
521 Moniker_ComposeWith,
522 Moniker_Enum,
523 Moniker_IsEqual,
524 Moniker_Hash,
525 Moniker_IsRunning,
526 Moniker_GetTimeOfLastChange,
527 Moniker_Inverse,
528 Moniker_CommonPrefixWith,
529 Moniker_RelativePathTo,
530 Moniker_GetDisplayName,
531 Moniker_ParseDisplayName,
532 Moniker_IsSystemMoniker
535 static IMoniker Moniker = { &MonikerVtbl };
537 static void test_ROT(void)
539 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
540 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
541 '2','0','4','6','E','5','8','6','C','9','2','5',0};
542 HRESULT hr;
543 IMoniker *pMoniker = NULL;
544 IRunningObjectTable *pROT = NULL;
545 DWORD dwCookie;
546 static const char *methods_register_no_ROTData[] =
548 "Moniker_Reduce",
549 "Moniker_GetTimeOfLastChange",
550 "Moniker_QueryInterface(IID_IROTData)",
551 "Moniker_GetDisplayName",
552 "Moniker_GetClassID",
553 NULL
555 static const char *methods_register[] =
557 "Moniker_Reduce",
558 "Moniker_GetTimeOfLastChange",
559 "Moniker_QueryInterface(IID_IROTData)",
560 "ROTData_GetComparisonData",
561 NULL
563 static const char *methods_isrunning_no_ROTData[] =
565 "Moniker_Reduce",
566 "Moniker_QueryInterface(IID_IROTData)",
567 "Moniker_GetDisplayName",
568 "Moniker_GetClassID",
569 NULL
571 static const char *methods_isrunning[] =
573 "Moniker_Reduce",
574 "Moniker_QueryInterface(IID_IROTData)",
575 "ROTData_GetComparisonData",
576 NULL
579 cLocks = 0;
581 hr = GetRunningObjectTable(0, &pROT);
582 ok_ole_success(hr, GetRunningObjectTable);
584 expected_method_list = methods_register_no_ROTData;
585 /* try with our own moniker that doesn't support IROTData */
586 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
587 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
588 ok_ole_success(hr, IRunningObjectTable_Register);
589 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
591 ok_more_than_one_lock();
593 expected_method_list = methods_isrunning_no_ROTData;
594 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
595 ok_ole_success(hr, IRunningObjectTable_IsRunning);
596 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
598 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
599 ok_ole_success(hr, IRunningObjectTable_Revoke);
601 ok_no_locks();
603 expected_method_list = methods_register;
604 /* try with our own moniker */
605 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
606 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
607 ok_ole_success(hr, IRunningObjectTable_Register);
608 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
610 ok_more_than_one_lock();
612 expected_method_list = methods_isrunning;
613 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
614 ok_ole_success(hr, IRunningObjectTable_IsRunning);
615 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
617 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
618 ok_ole_success(hr, IRunningObjectTable_Revoke);
620 ok_no_locks();
622 hr = CreateFileMoniker(wszFileName, &pMoniker);
623 ok_ole_success(hr, CreateClassMoniker);
625 /* test flags: 0 */
626 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
627 pMoniker, &dwCookie);
628 ok_ole_success(hr, IRunningObjectTable_Register);
630 ok_more_than_one_lock();
632 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
633 ok_ole_success(hr, IRunningObjectTable_Revoke);
635 ok_no_locks();
637 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
638 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
639 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
640 ok_ole_success(hr, IRunningObjectTable_Register);
642 ok_more_than_one_lock();
644 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
645 ok_ole_success(hr, IRunningObjectTable_Revoke);
647 ok_no_locks();
649 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
650 /* only succeeds when process is started by SCM and has LocalService
651 * or RunAs AppId values */
652 hr = IRunningObjectTable_Register(pROT,
653 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
654 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
655 todo_wine {
656 ok(hr == CO_E_WRONG_SERVER_IDENTITY ||
657 broken(hr == S_OK) /* Win9x */,
658 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
660 if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie);
662 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
663 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
664 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
666 IMoniker_Release(pMoniker);
668 IRunningObjectTable_Release(pROT);
671 static void test_ROT_multiple_entries(void)
673 HRESULT hr;
674 IMoniker *pMoniker = NULL;
675 IRunningObjectTable *pROT = NULL;
676 DWORD dwCookie1, dwCookie2;
677 IUnknown *pObject = NULL;
678 static const WCHAR moniker_path[] =
679 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
681 hr = GetRunningObjectTable(0, &pROT);
682 ok_ole_success(hr, GetRunningObjectTable);
684 hr = CreateFileMoniker(moniker_path, &pMoniker);
685 ok_ole_success(hr, CreateFileMoniker);
687 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
688 ok_ole_success(hr, IRunningObjectTable_Register);
690 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
691 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
693 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
695 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
696 ok_ole_success(hr, IRunningObjectTable_GetObject);
697 IUnknown_Release(pObject);
699 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
700 ok_ole_success(hr, IRunningObjectTable_Revoke);
702 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
703 ok_ole_success(hr, IRunningObjectTable_GetObject);
704 IUnknown_Release(pObject);
706 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
707 ok_ole_success(hr, IRunningObjectTable_Revoke);
709 IMoniker_Release(pMoniker);
711 IRunningObjectTable_Release(pROT);
714 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
716 if (IsEqualIID(riid, &IID_IUnknown) ||
717 IsEqualIID(riid, &IID_IParseDisplayName))
719 *ppv = iface;
720 IUnknown_AddRef(iface);
721 return S_OK;
723 *ppv = NULL;
724 return E_NOINTERFACE;
727 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
729 return 2;
732 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
734 return 1;
737 static LPCWSTR expected_display_name;
739 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
740 IBindCtx *pbc,
741 LPOLESTR pszDisplayName,
742 ULONG *pchEaten,
743 IMoniker **ppmkOut)
745 char display_nameA[256];
746 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
747 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
748 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
749 *pchEaten = lstrlenW(pszDisplayName);
750 return CreateAntiMoniker(ppmkOut);
753 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
755 ParseDisplayName_QueryInterface,
756 ParseDisplayName_AddRef,
757 ParseDisplayName_Release,
758 ParseDisplayName_ParseDisplayName
761 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
763 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
765 IMoniker * spMoniker;
766 int monCnt=0, matchCnt=0;
768 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
770 HRESULT hr;
771 WCHAR * szDisplayn;
772 monCnt++;
773 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
774 if (SUCCEEDED(hr))
776 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
777 matchCnt++;
778 CoTaskMemFree(szDisplayn);
781 trace("Total number of monikers is %i\n", monCnt);
782 return matchCnt;
785 static void test_MkParseDisplayName(void)
787 IBindCtx * pbc = NULL;
788 HRESULT hr;
789 IMoniker * pmk = NULL;
790 IMoniker * pmk1 = NULL;
791 IMoniker * pmk2 = NULL;
792 ULONG eaten;
793 int matchCnt;
794 IUnknown * object = NULL;
796 IUnknown *lpEM1;
798 IEnumMoniker *spEM1 = NULL;
799 IEnumMoniker *spEM2 = NULL;
800 IEnumMoniker *spEM3 = NULL;
802 DWORD pdwReg1=0;
803 DWORD grflags=0;
804 DWORD pdwReg2=0;
805 DWORD moniker_type;
806 IRunningObjectTable * pprot=NULL;
808 /* CLSID of My Computer */
809 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
810 '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};
811 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
812 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
813 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
814 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
815 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
816 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
817 static const WCHAR wszEmpty[] = {0};
818 char szDisplayNameFile[256];
819 WCHAR wszDisplayNameFile[256];
820 int i, len;
822 const struct
824 LPBC *ppbc;
825 LPCOLESTR szDisplayName;
826 LPDWORD pchEaten;
827 LPMONIKER *ppmk;
828 } invalid_parameters[] =
830 {NULL, NULL, NULL, NULL},
831 {NULL, NULL, NULL, &pmk},
832 {NULL, NULL, &eaten, NULL},
833 {NULL, NULL, &eaten, &pmk},
834 {NULL, wszEmpty, NULL, NULL},
835 {NULL, wszEmpty, NULL, &pmk},
836 {NULL, wszEmpty, &eaten, NULL},
837 {NULL, wszEmpty, &eaten, &pmk},
838 {&pbc, NULL, NULL, NULL},
839 {&pbc, NULL, NULL, &pmk},
840 {&pbc, NULL, &eaten, NULL},
841 {&pbc, NULL, &eaten, &pmk},
842 {&pbc, wszEmpty, NULL, NULL},
843 {&pbc, wszEmpty, NULL, &pmk},
844 {&pbc, wszEmpty, &eaten, NULL},
845 {&pbc, wszEmpty, &eaten, &pmk},
848 hr = CreateBindCtx(0, &pbc);
849 ok_ole_success(hr, CreateBindCtx);
851 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
853 eaten = 0xdeadbeef;
854 pmk = (IMoniker *)0xdeadbeef;
855 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
856 invalid_parameters[i].szDisplayName,
857 invalid_parameters[i].pchEaten,
858 invalid_parameters[i].ppmk);
859 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
860 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
861 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
864 eaten = 0xdeadbeef;
865 pmk = (IMoniker *)0xdeadbeef;
866 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
867 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
868 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
869 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
870 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
872 /* no special handling of "clsid:" without the string form of the clsid
873 * following */
874 eaten = 0xdeadbeef;
875 pmk = (IMoniker *)0xdeadbeef;
876 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
877 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
878 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
879 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
880 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
882 /* shows clsid has higher precedence than a running object */
883 hr = CreateFileMoniker(wszDisplayName, &pmk);
884 ok_ole_success(hr, CreateFileMoniker);
885 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
886 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
887 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
888 ok_ole_success(hr, IRunningObjectTable_Register);
889 IMoniker_Release(pmk);
890 pmk = NULL;
891 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
892 ok_ole_success(hr, MkParseDisplayName);
893 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1,
894 "Processed character count should have been 43 instead of %u\n", eaten);
895 if (pmk)
897 IMoniker_IsSystemMoniker(pmk, &moniker_type);
898 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
899 IMoniker_Release(pmk);
901 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
902 ok_ole_success(hr, IRunningObjectTable_Revoke);
903 IRunningObjectTable_Release(pprot);
905 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
906 ok_ole_success(hr, CreateFileMoniker);
907 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
908 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
909 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
910 ok_ole_success(hr, IRunningObjectTable_Register);
911 IMoniker_Release(pmk);
912 pmk = NULL;
913 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
914 ok_ole_success(hr, MkParseDisplayName);
915 ok(eaten == sizeof(wszDisplayNameRunning)/sizeof(WCHAR) - 1,
916 "Processed character count should have been 15 instead of %u\n", eaten);
917 if (pmk)
919 IMoniker_IsSystemMoniker(pmk, &moniker_type);
920 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
921 IMoniker_Release(pmk);
923 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
924 ok_ole_success(hr, IRunningObjectTable_Revoke);
925 IRunningObjectTable_Release(pprot);
927 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
928 ok_ole_success(hr, CoRegisterClassObject);
930 expected_display_name = wszDisplayNameProgId1;
931 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
932 ok_ole_success(hr, MkParseDisplayName);
933 ok(eaten == sizeof(wszDisplayNameProgId1)/sizeof(WCHAR) - 1,
934 "Processed character count should have been 8 instead of %u\n", eaten);
935 if (pmk)
937 IMoniker_IsSystemMoniker(pmk, &moniker_type);
938 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
939 IMoniker_Release(pmk);
942 expected_display_name = wszDisplayNameProgId2;
943 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
944 ok_ole_success(hr, MkParseDisplayName);
945 ok(eaten == sizeof(wszDisplayNameProgId2)/sizeof(WCHAR) - 1,
946 "Processed character count should have been 8 instead of %u\n", eaten);
947 if (pmk)
949 IMoniker_IsSystemMoniker(pmk, &moniker_type);
950 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
951 IMoniker_Release(pmk);
954 eaten = 0xdeadbeef;
955 pmk = (IMoniker *)0xdeadbeef;
956 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
957 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
958 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
959 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
960 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
962 hr = CoRevokeClassObject(pdwReg1);
963 ok_ole_success(hr, CoRevokeClassObject);
965 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
966 strcat(szDisplayNameFile, "\\kernel32.dll");
967 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
968 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
969 ok_ole_success(hr, MkParseDisplayName);
970 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
971 if (pmk)
973 IMoniker_IsSystemMoniker(pmk, &moniker_type);
974 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
975 IMoniker_Release(pmk);
978 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
979 ok_ole_success(hr, MkParseDisplayName);
980 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1, "Processed character count should have been 43 instead of %u\n", eaten);
982 if (pmk)
984 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
985 ok_ole_success(hr, IMoniker_BindToObject);
987 if (SUCCEEDED(hr))
988 IUnknown_Release(object);
989 IMoniker_Release(pmk);
991 IBindCtx_Release(pbc);
993 /* Test the EnumMoniker interface */
994 hr = CreateBindCtx(0, &pbc);
995 ok_ole_success(hr, CreateBindCtx);
997 hr = CreateFileMoniker(wszFileName1, &pmk1);
998 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
999 hr = CreateFileMoniker(wszFileName2, &pmk2);
1000 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1001 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1002 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
1004 /* Check EnumMoniker before registering */
1005 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1006 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1007 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
1008 /* Register a couple of Monikers and check is ok */
1009 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
1010 hr = MK_E_NOOBJECT;
1012 matchCnt = count_moniker_matches(pbc, spEM1);
1013 trace("Number of matches is %i\n", matchCnt);
1015 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1016 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1017 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
1018 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
1020 trace("IROT::Register\n");
1021 grflags=0;
1022 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1023 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1024 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
1025 pprot, grflags, lpEM1, pmk2, pdwReg2);
1027 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1028 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1030 matchCnt = count_moniker_matches(pbc, spEM2);
1031 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1033 trace("IEnumMoniker::Clone\n");
1034 IEnumMoniker_Clone(spEM2, &spEM3);
1036 matchCnt = count_moniker_matches(pbc, spEM3);
1037 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1038 trace("IEnumMoniker::Reset\n");
1039 IEnumMoniker_Reset(spEM3);
1041 matchCnt = count_moniker_matches(pbc, spEM3);
1042 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1044 IRunningObjectTable_Revoke(pprot,pdwReg1);
1045 IRunningObjectTable_Revoke(pprot,pdwReg2);
1046 IUnknown_Release(lpEM1);
1047 IEnumMoniker_Release(spEM1);
1048 IEnumMoniker_Release(spEM2);
1049 IEnumMoniker_Release(spEM3);
1050 IMoniker_Release(pmk1);
1051 IMoniker_Release(pmk2);
1052 IRunningObjectTable_Release(pprot);
1054 IBindCtx_Release(pbc);
1057 static const LARGE_INTEGER llZero;
1059 static const BYTE expected_class_moniker_marshal_data[] =
1061 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1062 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1063 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1064 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1065 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1066 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1067 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1068 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1069 0x00,0x00,0x00,0x00,
1072 static const BYTE expected_class_moniker_saved_data[] =
1074 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1075 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1076 0x00,0x00,0x00,0x00,
1079 static const BYTE expected_class_moniker_comparison_data[] =
1081 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1082 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1083 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1084 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1087 static const WCHAR expected_class_moniker_display_name[] =
1089 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1090 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1091 '0','0','0','0','4','6',':',0
1094 static const BYTE expected_item_moniker_comparison_data[] =
1096 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1097 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1098 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1099 0x54,0x00,0x00,0x00,
1102 static const BYTE expected_item_moniker_saved_data[] =
1104 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1105 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1108 static const BYTE expected_item_moniker_marshal_data[] =
1110 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1111 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1112 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1113 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1114 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1115 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1116 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1117 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1120 static const BYTE expected_anti_moniker_marshal_data[] =
1122 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1123 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1124 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1125 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1126 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1127 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1128 0x01,0x00,0x00,0x00,
1131 static const BYTE expected_anti_moniker_saved_data[] =
1133 0x01,0x00,0x00,0x00,
1136 static const BYTE expected_anti_moniker_comparison_data[] =
1138 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1139 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1140 0x01,0x00,0x00,0x00,
1143 static const BYTE expected_gc_moniker_marshal_data[] =
1145 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1146 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1147 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1148 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1149 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1150 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1151 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1152 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1153 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1154 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1155 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1156 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1157 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1158 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1159 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1160 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1161 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1162 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1163 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1164 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1165 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1166 0x00,0x57,0x69,0x6e,0x65,0x00,
1169 static const BYTE expected_gc_moniker_saved_data[] =
1171 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1172 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1173 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1174 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1175 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1176 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1177 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1178 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1179 0x65,0x00,
1182 static const BYTE expected_gc_moniker_comparison_data[] =
1184 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1185 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1186 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1187 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1188 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1189 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1190 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1191 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1192 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1195 static void test_moniker(
1196 const char *testname, IMoniker *moniker,
1197 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1198 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1199 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1200 LPCWSTR expected_display_name)
1202 IStream * stream;
1203 IROTData * rotdata;
1204 HRESULT hr;
1205 HGLOBAL hglobal;
1206 LPBYTE moniker_data;
1207 DWORD moniker_size;
1208 DWORD i;
1209 BOOL same;
1210 BYTE buffer[128];
1211 IMoniker * moniker_proxy;
1212 LPOLESTR display_name;
1213 IBindCtx *bindctx;
1215 hr = IMoniker_IsDirty(moniker);
1216 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1218 /* Display Name */
1220 hr = CreateBindCtx(0, &bindctx);
1221 ok_ole_success(hr, CreateBindCtx);
1223 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1224 ok_ole_success(hr, IMoniker_GetDisplayName);
1225 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1227 CoTaskMemFree(display_name);
1228 IBindCtx_Release(bindctx);
1230 hr = IMoniker_IsDirty(moniker);
1231 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1233 /* IROTData::GetComparisonData test */
1235 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1236 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1238 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1239 ok_ole_success(hr, IROTData_GetComparisonData);
1241 if (hr != S_OK) moniker_size = 0;
1243 /* first check we have the right amount of data */
1244 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1245 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1246 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1248 /* then do a byte-by-byte comparison */
1249 same = TRUE;
1250 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1252 if (expected_moniker_comparison_data[i] != buffer[i])
1254 same = FALSE;
1255 break;
1259 ok(same, "%s: Comparison data differs\n", testname);
1260 if (!same)
1262 for (i = 0; i < moniker_size; i++)
1264 if (i % 8 == 0) printf(" ");
1265 printf("0x%02x,", buffer[i]);
1266 if (i % 8 == 7) printf("\n");
1268 printf("\n");
1271 IROTData_Release(rotdata);
1273 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1275 /* Saving */
1277 hr = IMoniker_Save(moniker, stream, TRUE);
1278 ok_ole_success(hr, IMoniker_Save);
1280 hr = GetHGlobalFromStream(stream, &hglobal);
1281 ok_ole_success(hr, GetHGlobalFromStream);
1283 moniker_size = GlobalSize(hglobal);
1285 moniker_data = GlobalLock(hglobal);
1287 /* first check we have the right amount of data */
1288 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1289 "%s: Size of saved data differs (expected %d, actual %d)\n",
1290 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1292 /* then do a byte-by-byte comparison */
1293 same = TRUE;
1294 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1296 if (expected_moniker_saved_data[i] != moniker_data[i])
1298 same = FALSE;
1299 break;
1303 ok(same, "%s: Saved data differs\n", testname);
1304 if (!same)
1306 for (i = 0; i < moniker_size; i++)
1308 if (i % 8 == 0) printf(" ");
1309 printf("0x%02x,", moniker_data[i]);
1310 if (i % 8 == 7) printf("\n");
1312 printf("\n");
1315 GlobalUnlock(hglobal);
1317 IStream_Release(stream);
1319 /* Marshaling tests */
1321 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1322 ok_ole_success(hr, CreateStreamOnHGlobal);
1324 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1325 ok_ole_success(hr, CoMarshalInterface);
1327 hr = GetHGlobalFromStream(stream, &hglobal);
1328 ok_ole_success(hr, GetHGlobalFromStream);
1330 moniker_size = GlobalSize(hglobal);
1332 moniker_data = GlobalLock(hglobal);
1334 /* first check we have the right amount of data */
1335 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1336 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1337 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1339 /* then do a byte-by-byte comparison */
1340 same = TRUE;
1341 if (expected_moniker_marshal_data)
1343 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1345 if (expected_moniker_marshal_data[i] != moniker_data[i])
1347 same = FALSE;
1348 break;
1353 ok(same, "%s: Marshaled data differs\n", testname);
1354 if (!same)
1356 for (i = 0; i < moniker_size; i++)
1358 if (i % 8 == 0) printf(" ");
1359 printf("0x%02x,", moniker_data[i]);
1360 if (i % 8 == 7) printf("\n");
1362 printf("\n");
1365 GlobalUnlock(hglobal);
1367 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1368 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1369 ok_ole_success(hr, CoUnmarshalInterface);
1371 IStream_Release(stream);
1372 IMoniker_Release(moniker_proxy);
1375 static void test_class_moniker(void)
1377 HRESULT hr;
1378 IMoniker *moniker;
1379 DWORD moniker_type;
1380 DWORD hash;
1381 IBindCtx *bindctx;
1382 IMoniker *inverse;
1383 IUnknown *unknown;
1384 FILETIME filetime;
1386 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1387 ok_ole_success(hr, CreateClassMoniker);
1388 if (!moniker) return;
1390 test_moniker("class moniker", moniker,
1391 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1392 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1393 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1394 expected_class_moniker_display_name);
1396 /* Hashing */
1398 hr = IMoniker_Hash(moniker, &hash);
1399 ok_ole_success(hr, IMoniker_Hash);
1401 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1402 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1403 hash);
1405 /* IsSystemMoniker test */
1407 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1408 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1410 ok(moniker_type == MKSYS_CLASSMONIKER,
1411 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1412 moniker_type);
1414 hr = CreateBindCtx(0, &bindctx);
1415 ok_ole_success(hr, CreateBindCtx);
1417 /* IsRunning test */
1418 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1419 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1421 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1422 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1424 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1425 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1427 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1428 ok_ole_success(hr, IMoniker_BindToObject);
1429 IUnknown_Release(unknown);
1431 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1432 ok_ole_success(hr, IMoniker_BindToStorage);
1433 IUnknown_Release(unknown);
1435 IBindCtx_Release(bindctx);
1437 hr = IMoniker_Inverse(moniker, &inverse);
1438 ok_ole_success(hr, IMoniker_Inverse);
1439 IMoniker_Release(inverse);
1441 IMoniker_Release(moniker);
1444 static void test_file_moniker(WCHAR* path)
1446 IStream *stream;
1447 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1448 HRESULT hr;
1450 hr = CreateFileMoniker(path, &moniker1);
1451 ok_ole_success(hr, CreateFileMoniker);
1453 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1455 /* Marshal */
1456 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1457 ok_ole_success(hr, CoMarshalInterface);
1459 /* Rewind */
1460 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1461 ok_ole_success(hr, IStream_Seek);
1463 /* Unmarshal */
1464 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1465 ok_ole_success(hr, CoUnmarshalInterface);
1467 hr = IMoniker_IsEqual(moniker1, moniker2);
1468 ok_ole_success(hr, IsEqual);
1470 IStream_Release(stream);
1471 if (moniker1)
1472 IMoniker_Release(moniker1);
1473 if (moniker2)
1474 IMoniker_Release(moniker2);
1477 static void test_file_monikers(void)
1479 static WCHAR wszFile[][30] = {
1480 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1481 {'\\', '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},
1482 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1483 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1484 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1485 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1486 * U+0100 .. = Latin extended-A
1488 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1491 int i;
1493 trace("ACP is %u\n", GetACP());
1495 for (i = 0; i < COUNTOF(wszFile); ++i)
1497 int j ;
1498 if (i == 2)
1500 BOOL used;
1501 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1502 if (used)
1504 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1505 continue;
1508 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1510 wszFile[i][j] = 0;
1511 test_file_moniker(wszFile[i]);
1516 static void test_item_moniker(void)
1518 HRESULT hr;
1519 IMoniker *moniker;
1520 DWORD moniker_type;
1521 DWORD hash;
1522 IBindCtx *bindctx;
1523 IMoniker *inverse;
1524 IUnknown *unknown;
1525 static const WCHAR wszDelimeter[] = {'!',0};
1526 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1527 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1529 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1530 ok_ole_success(hr, CreateItemMoniker);
1532 test_moniker("item moniker", moniker,
1533 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1534 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1535 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1536 expected_display_name);
1538 /* Hashing */
1540 hr = IMoniker_Hash(moniker, &hash);
1541 ok_ole_success(hr, IMoniker_Hash);
1543 ok(hash == 0x73c,
1544 "Hash value != 0x73c, instead was 0x%08x\n",
1545 hash);
1547 /* IsSystemMoniker test */
1549 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1550 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1552 ok(moniker_type == MKSYS_ITEMMONIKER,
1553 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1554 moniker_type);
1556 hr = CreateBindCtx(0, &bindctx);
1557 ok_ole_success(hr, CreateBindCtx);
1559 /* IsRunning test */
1560 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1561 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1563 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1564 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1566 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1567 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1569 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1570 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1572 IBindCtx_Release(bindctx);
1574 hr = IMoniker_Inverse(moniker, &inverse);
1575 ok_ole_success(hr, IMoniker_Inverse);
1576 IMoniker_Release(inverse);
1578 IMoniker_Release(moniker);
1581 static void test_anti_moniker(void)
1583 HRESULT hr;
1584 IMoniker *moniker;
1585 DWORD moniker_type;
1586 DWORD hash;
1587 IBindCtx *bindctx;
1588 FILETIME filetime;
1589 IMoniker *inverse;
1590 IUnknown *unknown;
1591 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1593 hr = CreateAntiMoniker(&moniker);
1594 ok_ole_success(hr, CreateAntiMoniker);
1595 if (!moniker) return;
1597 test_moniker("anti moniker", moniker,
1598 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1599 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1600 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1601 expected_display_name);
1603 /* Hashing */
1604 hr = IMoniker_Hash(moniker, &hash);
1605 ok_ole_success(hr, IMoniker_Hash);
1606 ok(hash == 0x80000001,
1607 "Hash value != 0x80000001, instead was 0x%08x\n",
1608 hash);
1610 /* IsSystemMoniker test */
1611 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1612 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1613 ok(moniker_type == MKSYS_ANTIMONIKER,
1614 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1615 moniker_type);
1617 hr = IMoniker_Inverse(moniker, &inverse);
1618 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1619 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1621 hr = CreateBindCtx(0, &bindctx);
1622 ok_ole_success(hr, CreateBindCtx);
1624 /* IsRunning test */
1625 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1626 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1628 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1629 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1631 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1632 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1634 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1635 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1637 IBindCtx_Release(bindctx);
1639 IMoniker_Release(moniker);
1642 static void test_generic_composite_moniker(void)
1644 HRESULT hr;
1645 IMoniker *moniker;
1646 IMoniker *moniker1;
1647 IMoniker *moniker2;
1648 DWORD moniker_type;
1649 DWORD hash;
1650 IBindCtx *bindctx;
1651 FILETIME filetime;
1652 IMoniker *inverse;
1653 IUnknown *unknown;
1654 static const WCHAR wszDelimeter1[] = {'!',0};
1655 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1656 static const WCHAR wszDelimeter2[] = {'#',0};
1657 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1658 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1660 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1661 ok_ole_success(hr, CreateItemMoniker);
1662 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1663 ok_ole_success(hr, CreateItemMoniker);
1664 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1665 ok_ole_success(hr, CreateGenericComposite);
1667 test_moniker("generic composite moniker", moniker,
1668 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1669 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1670 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1671 expected_display_name);
1673 /* Hashing */
1675 hr = IMoniker_Hash(moniker, &hash);
1676 ok_ole_success(hr, IMoniker_Hash);
1678 ok(hash == 0xd87,
1679 "Hash value != 0xd87, instead was 0x%08x\n",
1680 hash);
1682 /* IsSystemMoniker test */
1684 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1685 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1687 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1688 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1689 moniker_type);
1691 hr = CreateBindCtx(0, &bindctx);
1692 ok_ole_success(hr, CreateBindCtx);
1694 /* IsRunning test */
1695 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1696 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1698 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1699 todo_wine
1700 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1702 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1703 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1705 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1706 todo_wine
1707 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1709 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1710 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1712 IBindCtx_Release(bindctx);
1714 hr = IMoniker_Inverse(moniker, &inverse);
1715 ok_ole_success(hr, IMoniker_Inverse);
1716 IMoniker_Release(inverse);
1718 IMoniker_Release(moniker);
1721 static void test_pointer_moniker(void)
1723 HRESULT hr;
1724 IMoniker *moniker;
1725 DWORD moniker_type;
1726 DWORD hash;
1727 IBindCtx *bindctx;
1728 FILETIME filetime;
1729 IMoniker *inverse;
1730 IUnknown *unknown;
1731 IStream *stream;
1732 IROTData *rotdata;
1733 LPOLESTR display_name;
1735 cLocks = 0;
1737 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1738 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1740 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1741 ok_ole_success(hr, CreatePointerMoniker);
1742 if (!moniker) return;
1744 ok_more_than_one_lock();
1746 /* Display Name */
1748 hr = CreateBindCtx(0, &bindctx);
1749 ok_ole_success(hr, CreateBindCtx);
1751 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1752 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1754 IBindCtx_Release(bindctx);
1756 hr = IMoniker_IsDirty(moniker);
1757 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1759 /* IROTData::GetComparisonData test */
1761 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1762 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1764 /* Saving */
1766 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1767 ok_ole_success(hr, CreateStreamOnHGlobal);
1769 hr = IMoniker_Save(moniker, stream, TRUE);
1770 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1772 IStream_Release(stream);
1774 /* Hashing */
1775 hr = IMoniker_Hash(moniker, &hash);
1776 ok_ole_success(hr, IMoniker_Hash);
1777 ok(hash == (DWORD)&Test_ClassFactory,
1778 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1779 (DWORD)&Test_ClassFactory, hash);
1781 /* IsSystemMoniker test */
1782 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1783 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1784 ok(moniker_type == MKSYS_POINTERMONIKER,
1785 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1786 moniker_type);
1788 hr = IMoniker_Inverse(moniker, &inverse);
1789 ok_ole_success(hr, IMoniker_Inverse);
1790 IMoniker_Release(inverse);
1792 hr = CreateBindCtx(0, &bindctx);
1793 ok_ole_success(hr, CreateBindCtx);
1795 /* IsRunning test */
1796 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1797 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1799 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1800 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1802 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1803 ok_ole_success(hr, IMoniker_BindToObject);
1804 IUnknown_Release(unknown);
1806 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1807 ok_ole_success(hr, IMoniker_BindToStorage);
1808 IUnknown_Release(unknown);
1810 IMoniker_Release(moniker);
1812 ok_no_locks();
1814 hr = CreatePointerMoniker(NULL, &moniker);
1815 ok_ole_success(hr, CreatePointerMoniker);
1817 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1818 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1820 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1821 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1823 IBindCtx_Release(bindctx);
1825 IMoniker_Release(moniker);
1828 static void test_bind_context(void)
1830 HRESULT hr;
1831 IBindCtx *pBindCtx;
1832 IEnumString *pEnumString;
1833 BIND_OPTS2 bind_opts;
1834 HeapUnknown *unknown;
1835 HeapUnknown *unknown2;
1836 IUnknown *param_obj;
1837 ULONG refs;
1838 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1839 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1841 hr = CreateBindCtx(0, NULL);
1842 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1844 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1845 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1847 hr = CreateBindCtx(0, &pBindCtx);
1848 ok_ole_success(hr, "CreateBindCtx");
1850 bind_opts.cbStruct = -1;
1851 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1852 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1853 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1854 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1855 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1857 bind_opts.cbStruct = sizeof(BIND_OPTS);
1858 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1859 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1860 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "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);
1866 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1867 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1868 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1869 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1870 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1871 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1872 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1873 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1875 bind_opts.cbStruct = -1;
1876 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1877 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1879 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1880 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1882 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1883 unknown->lpVtbl = &HeapUnknown_Vtbl;
1884 unknown->refs = 1;
1885 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1886 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1888 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1889 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1890 IUnknown_Release(param_obj);
1892 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1893 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1894 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1896 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1897 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1899 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1900 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1901 ok(!pEnumString, "pEnumString should be NULL\n");
1903 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1904 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1906 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1907 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1909 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1910 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1911 unknown2->refs = 1;
1912 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1913 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1915 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1916 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1918 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1919 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1921 IBindCtx_Release(pBindCtx);
1923 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1924 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1926 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1927 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1930 static void test_save_load_filemoniker(void)
1932 IMoniker* pMk;
1933 IStream* pStm;
1934 HRESULT hr;
1935 ULARGE_INTEGER size;
1936 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
1937 DWORD some_val = 0xFEDCBA98;
1938 int i;
1940 /* see FileMonikerImpl_Save docs */
1941 zero_pos.QuadPart = 0;
1942 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
1943 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
1945 /* create the stream we're going to write to */
1946 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
1947 ok_ole_success(hr, "CreateStreamOnHGlobal");
1949 size.u.LowPart = 128;
1950 hr = IStream_SetSize(pStm, size);
1951 ok_ole_success(hr, "IStream_SetSize");
1953 /* create and save a moniker */
1954 hr = CreateFileMoniker(wszFileName1, &pMk);
1955 ok_ole_success(hr, "CreateFileMoniker");
1957 hr = IMoniker_Save(pMk, pStm, TRUE);
1958 ok_ole_success(hr, "IMoniker_Save");
1960 hr = IMoniker_Release(pMk);
1961 ok_ole_success(hr, "IMoniker_Release");
1963 /* overwrite the constants with various values */
1964 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1965 ok_ole_success(hr, "IStream_Seek");
1966 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1967 ok_ole_success(hr, "IStream_Write");
1969 hr = IStream_Seek(pStm, dead_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, nulls_pos, STREAM_SEEK_SET, NULL);
1975 ok_ole_success(hr, "IStream_Seek");
1976 for(i = 0; i < 5; ++i){
1977 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
1978 ok_ole_success(hr, "IStream_Write");
1981 /* go back to the start of the stream */
1982 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1983 ok_ole_success(hr, "IStream_Seek");
1985 /* create a new moniker and load into it */
1986 hr = CreateFileMoniker(wszFileName1, &pMk);
1987 ok_ole_success(hr, "CreateFileMoniker");
1989 hr = IMoniker_Load(pMk, pStm);
1990 ok_ole_success(hr, "IMoniker_Load");
1992 hr = IMoniker_Release(pMk);
1993 ok_ole_success(hr, "IMoniker_Release");
1995 hr = IStream_Release(pStm);
1996 ok_ole_success(hr, "IStream_Release");
1999 START_TEST(moniker)
2001 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2003 test_ROT();
2004 test_ROT_multiple_entries();
2005 test_MkParseDisplayName();
2006 test_class_moniker();
2007 test_file_monikers();
2008 test_item_moniker();
2009 test_anti_moniker();
2010 test_generic_composite_moniker();
2011 test_pointer_moniker();
2012 test_save_load_filemoniker();
2014 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2016 test_bind_context();
2018 CoUninitialize();