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
34 #include "wine/test.h"
36 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
37 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
38 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
39 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
41 #define CHECK_EXPECTED_METHOD(method_name) \
43 trace("%s\n", method_name); \
44 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
45 if (*expected_method_list) \
47 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
48 *expected_method_list, method_name); \
49 expected_method_list++; \
53 static char const * const *expected_method_list;
54 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
55 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
57 static const CLSID CLSID_WineTest =
58 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
62 {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
65 static const CLSID CLSID_TestMoniker =
66 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
70 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
75 static void LockModule(void)
77 InterlockedIncrement(&cLocks);
80 static void UnlockModule(void)
82 InterlockedDecrement(&cLocks);
85 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
90 if (ppvObj == NULL) return E_POINTER;
92 if (IsEqualGUID(riid, &IID_IUnknown) ||
93 IsEqualGUID(riid, &IID_IClassFactory))
95 *ppvObj = (LPVOID)iface;
96 IClassFactory_AddRef(iface);
101 return E_NOINTERFACE;
104 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
107 return 2; /* non-heap-based object */
110 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
113 return 1; /* non-heap-based object */
116 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
117 LPCLASSFACTORY iface,
125 static HRESULT WINAPI Test_IClassFactory_LockServer(
126 LPCLASSFACTORY iface,
132 static const IClassFactoryVtbl TestClassFactory_Vtbl =
134 Test_IClassFactory_QueryInterface,
135 Test_IClassFactory_AddRef,
136 Test_IClassFactory_Release,
137 Test_IClassFactory_CreateInstance,
138 Test_IClassFactory_LockServer
141 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
145 const IUnknownVtbl *lpVtbl;
149 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
151 if (IsEqualIID(riid, &IID_IUnknown))
153 IUnknown_AddRef(iface);
154 *ppv = (LPVOID)iface;
158 return E_NOINTERFACE;
161 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
163 HeapUnknown *This = (HeapUnknown *)iface;
164 return InterlockedIncrement((LONG*)&This->refs);
167 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
169 HeapUnknown *This = (HeapUnknown *)iface;
170 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
171 if (!refs) HeapFree(GetProcessHeap(), 0, This);
175 static const IUnknownVtbl HeapUnknown_Vtbl =
177 HeapUnknown_QueryInterface,
182 static HRESULT WINAPI
183 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
190 if (IsEqualIID(&IID_IUnknown, riid) ||
191 IsEqualIID(&IID_IPersist, riid) ||
192 IsEqualIID(&IID_IPersistStream,riid) ||
193 IsEqualIID(&IID_IMoniker, riid))
195 if (IsEqualIID(&IID_IROTData, riid))
196 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
199 return E_NOINTERFACE;
201 IMoniker_AddRef(iface);
207 Moniker_AddRef(IMoniker* iface)
213 Moniker_Release(IMoniker* iface)
218 static HRESULT WINAPI
219 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
221 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
223 *pClassID = CLSID_TestMoniker;
228 static HRESULT WINAPI
229 Moniker_IsDirty(IMoniker* iface)
231 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
236 static HRESULT WINAPI
237 Moniker_Load(IMoniker* iface, IStream* pStm)
239 CHECK_EXPECTED_METHOD("Moniker_Load");
243 static HRESULT WINAPI
244 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
246 CHECK_EXPECTED_METHOD("Moniker_Save");
250 static HRESULT WINAPI
251 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
253 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
257 static HRESULT WINAPI
258 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
259 REFIID riid, VOID** ppvResult)
261 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
265 static HRESULT WINAPI
266 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
267 REFIID riid, VOID** ppvObject)
269 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
273 static HRESULT WINAPI
274 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
275 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
277 CHECK_EXPECTED_METHOD("Moniker_Reduce");
279 if (ppmkReduced==NULL)
282 IMoniker_AddRef(iface);
286 return MK_S_REDUCED_TO_SELF;
289 static HRESULT WINAPI
290 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
291 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
293 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
297 static HRESULT WINAPI
298 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
300 CHECK_EXPECTED_METHOD("Moniker_Enum");
302 if (ppenumMoniker == NULL)
305 *ppenumMoniker = NULL;
310 static HRESULT WINAPI
311 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
313 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
317 static HRESULT WINAPI
318 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
320 CHECK_EXPECTED_METHOD("Moniker_Hash");
324 static HRESULT WINAPI
325 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
326 IMoniker* pmkNewlyRunning)
328 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
332 static HRESULT WINAPI
333 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
334 IMoniker* pmkToLeft, FILETIME* pFileTime)
336 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
340 static HRESULT WINAPI
341 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
343 CHECK_EXPECTED_METHOD("Moniker_Inverse");
347 static HRESULT WINAPI
348 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
350 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
354 static HRESULT WINAPI
355 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
357 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
361 static HRESULT WINAPI
362 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
363 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
365 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
366 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
367 *ppszDisplayName = (LPOLESTR)CoTaskMemAlloc(sizeof(wszDisplayName));
368 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
372 static HRESULT WINAPI
373 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
374 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
376 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
380 static HRESULT WINAPI
381 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
383 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
388 (*pwdMksys)=MKSYS_NONE;
393 static const IMonikerVtbl MonikerNoROTDataVtbl =
395 MonikerNoROTData_QueryInterface,
403 Moniker_BindToObject,
404 Moniker_BindToStorage,
411 Moniker_GetTimeOfLastChange,
413 Moniker_CommonPrefixWith,
414 Moniker_RelativePathTo,
415 Moniker_GetDisplayName,
416 Moniker_ParseDisplayName,
417 Moniker_IsSystemMoniker
420 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
422 static IMoniker Moniker;
424 static HRESULT WINAPI
425 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
427 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
431 ROTData_AddRef(IROTData *iface)
437 ROTData_Release(IROTData* iface)
442 static HRESULT WINAPI
443 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
444 ULONG cbMax, ULONG* pcbData)
446 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
449 if (cbMax < *pcbData)
450 return E_OUTOFMEMORY;
457 static IROTDataVtbl ROTDataVtbl =
459 ROTData_QueryInterface,
462 ROTData_GetComparisonData
465 static IROTData ROTData = { &ROTDataVtbl };
467 static HRESULT WINAPI
468 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
475 if (IsEqualIID(&IID_IUnknown, riid) ||
476 IsEqualIID(&IID_IPersist, riid) ||
477 IsEqualIID(&IID_IPersistStream,riid) ||
478 IsEqualIID(&IID_IMoniker, riid))
480 if (IsEqualIID(&IID_IROTData, riid))
482 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
483 *ppvObject = &ROTData;
487 return E_NOINTERFACE;
489 IMoniker_AddRef(iface);
494 static const IMonikerVtbl MonikerVtbl =
496 Moniker_QueryInterface,
504 Moniker_BindToObject,
505 Moniker_BindToStorage,
512 Moniker_GetTimeOfLastChange,
514 Moniker_CommonPrefixWith,
515 Moniker_RelativePathTo,
516 Moniker_GetDisplayName,
517 Moniker_ParseDisplayName,
518 Moniker_IsSystemMoniker
521 static IMoniker Moniker = { &MonikerVtbl };
523 static void test_ROT(void)
525 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
526 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
527 '2','0','4','6','E','5','8','6','C','9','2','5',0};
529 IMoniker *pMoniker = NULL;
530 IRunningObjectTable *pROT = NULL;
532 static const char *methods_register_no_ROTData[] =
535 "Moniker_GetTimeOfLastChange",
536 "Moniker_QueryInterface(IID_IROTData)",
537 "Moniker_GetDisplayName",
538 "Moniker_GetClassID",
541 static const char *methods_register[] =
544 "Moniker_GetTimeOfLastChange",
545 "Moniker_QueryInterface(IID_IROTData)",
546 "ROTData_GetComparisonData",
549 static const char *methods_isrunning_no_ROTData[] =
552 "Moniker_QueryInterface(IID_IROTData)",
553 "Moniker_GetDisplayName",
554 "Moniker_GetClassID",
557 static const char *methods_isrunning[] =
560 "Moniker_QueryInterface(IID_IROTData)",
561 "ROTData_GetComparisonData",
567 hr = GetRunningObjectTable(0, &pROT);
568 ok_ole_success(hr, GetRunningObjectTable);
570 expected_method_list = methods_register_no_ROTData;
571 /* try with our own moniker that doesn't support IROTData */
572 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
573 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
574 todo_wine { /* only fails because of lack of IMoniker marshaling */
575 ok_ole_success(hr, IRunningObjectTable_Register);
577 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
579 todo_wine { /* only fails because of lack of IMoniker marshaling */
580 ok_more_than_one_lock();
583 expected_method_list = methods_isrunning_no_ROTData;
584 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
585 todo_wine { /* only fails because of lack of IMoniker marshaling */
586 ok_ole_success(hr, IRunningObjectTable_IsRunning);
588 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
590 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
591 todo_wine { /* only fails because of lack of IMoniker marshaling */
592 ok_ole_success(hr, IRunningObjectTable_Revoke);
597 expected_method_list = methods_register;
598 /* try with our own moniker */
599 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
600 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
601 todo_wine { /* only fails because of lack of IMoniker marshaling */
602 ok_ole_success(hr, IRunningObjectTable_Register);
604 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
606 todo_wine { /* only fails because of lack of IMoniker marshaling */
607 ok_more_than_one_lock();
610 expected_method_list = methods_isrunning;
611 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
612 todo_wine { /* only fails because of lack of IMoniker marshaling */
613 ok_ole_success(hr, IRunningObjectTable_IsRunning);
615 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
617 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
618 todo_wine { /* only fails because of lack of IMoniker marshaling */
619 ok_ole_success(hr, IRunningObjectTable_Revoke);
624 hr = CreateFileMoniker(wszFileName, &pMoniker);
625 ok_ole_success(hr, CreateClassMoniker);
628 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
629 pMoniker, &dwCookie);
630 ok_ole_success(hr, IRunningObjectTable_Register);
632 ok_more_than_one_lock();
634 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
635 ok_ole_success(hr, IRunningObjectTable_Revoke);
639 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
640 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
641 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
642 ok_ole_success(hr, IRunningObjectTable_Register);
644 ok_more_than_one_lock();
646 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
647 ok_ole_success(hr, IRunningObjectTable_Revoke);
651 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
652 /* only succeeds when process is started by SCM and has LocalService
653 * or RunAs AppId values */
654 hr = IRunningObjectTable_Register(pROT,
655 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
656 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
658 ok(hr == CO_E_WRONG_SERVER_IDENTITY, "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
661 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
662 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
663 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
665 IMoniker_Release(pMoniker);
667 IRunningObjectTable_Release(pROT);
670 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
672 if (IsEqualIID(riid, &IID_IUnknown) ||
673 IsEqualIID(riid, &IID_IParseDisplayName))
676 IUnknown_AddRef(iface);
680 return E_NOINTERFACE;
683 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
688 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
693 static LPCWSTR expected_display_name;
695 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
697 LPOLESTR pszDisplayName,
701 char display_nameA[256];
702 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
703 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
704 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
705 *pchEaten = lstrlenW(pszDisplayName);
706 return CreateAntiMoniker(ppmkOut);
709 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
711 ParseDisplayName_QueryInterface,
712 ParseDisplayName_AddRef,
713 ParseDisplayName_Release,
714 ParseDisplayName_ParseDisplayName
717 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
719 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
721 IMoniker * spMoniker;
722 int monCnt=0, matchCnt=0;
724 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
729 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
732 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
734 CoTaskMemFree(szDisplayn);
737 trace("Total number of monikers is %i\n", monCnt);
741 static void test_MkParseDisplayName(void)
743 IBindCtx * pbc = NULL;
745 IMoniker * pmk = NULL;
746 IMoniker * pmk1 = NULL;
747 IMoniker * pmk2 = NULL;
750 IUnknown * object = NULL;
754 IEnumMoniker *spEM1 = NULL;
755 IEnumMoniker *spEM2 = NULL;
756 IEnumMoniker *spEM3 = NULL;
762 IRunningObjectTable * pprot=NULL;
764 /* CLSID of My Computer */
765 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
766 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8','-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
767 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
768 static const WCHAR wszNonExistantProgId[] = {'N','o','n','E','x','i','s','t','a','n','t','P','r','o','g','I','d',':',0};
769 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
770 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
771 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
772 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
773 char szDisplayNameFile[256];
774 WCHAR wszDisplayNameFile[256];
776 hr = CreateBindCtx(0, &pbc);
777 ok_ole_success(hr, CreateBindCtx);
779 hr = MkParseDisplayName(pbc, wszNonExistantProgId, &eaten, &pmk);
780 todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
782 /* no special handling of "clsid:" without the string form of the clsid
784 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
785 todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName should have failed with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
787 /* shows clsid has higher precedence than a running object */
788 hr = CreateFileMoniker(wszDisplayName, &pmk);
789 ok_ole_success(hr, CreateFileMoniker);
790 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
791 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
792 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
793 ok_ole_success(hr, IRunningObjectTable_Register);
794 IMoniker_Release(pmk);
796 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
797 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
800 IMoniker_IsSystemMoniker(pmk, &moniker_type);
801 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
802 IMoniker_Release(pmk);
804 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
805 ok_ole_success(hr, IRunningObjectTable_Revoke);
806 IRunningObjectTable_Release(pprot);
808 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
809 ok_ole_success(hr, CreateFileMoniker);
810 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
811 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
812 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
813 ok_ole_success(hr, IRunningObjectTable_Register);
814 IMoniker_Release(pmk);
816 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
817 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
820 IMoniker_IsSystemMoniker(pmk, &moniker_type);
821 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
822 IMoniker_Release(pmk);
824 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
825 ok_ole_success(hr, IRunningObjectTable_Revoke);
826 IRunningObjectTable_Release(pprot);
828 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
829 ok_ole_success(hr, CoRegisterClassObject);
831 expected_display_name = wszDisplayNameProgId1;
832 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
833 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
836 IMoniker_IsSystemMoniker(pmk, &moniker_type);
837 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
838 IMoniker_Release(pmk);
841 expected_display_name = wszDisplayNameProgId2;
842 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
843 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
846 IMoniker_IsSystemMoniker(pmk, &moniker_type);
847 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
848 IMoniker_Release(pmk);
851 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
852 todo_wine { ok(hr == MK_E_CANTOPENFILE, "MkParseDisplayName with ProgId without marker should fail with MK_E_CANTOPENFILE instead of 0x%08x\n", hr); }
854 hr = CoRevokeClassObject(pdwReg1);
855 ok_ole_success(hr, CoRevokeClassObject);
857 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
858 strcat(szDisplayNameFile, "\\kernel32.dll");
859 MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
860 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
861 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
864 IMoniker_IsSystemMoniker(pmk, &moniker_type);
865 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
866 IMoniker_Release(pmk);
869 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
870 todo_wine { ok_ole_success(hr, MkParseDisplayName); }
874 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
875 ok_ole_success(hr, IMoniker_BindToObject);
877 IUnknown_Release(object);
879 IBindCtx_Release(pbc);
881 /* Test the EnumMoniker interface */
882 hr = CreateBindCtx(0, &pbc);
883 ok_ole_success(hr, CreateBindCtx);
885 hr = CreateFileMoniker(wszFileName1, &pmk1);
886 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
887 hr = CreateFileMoniker(wszFileName2, &pmk2);
888 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
889 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
890 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
892 /* Check EnumMoniker before registering */
893 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
894 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
895 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
896 /* Register a couple of Monikers and check is ok */
897 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
900 matchCnt = count_moniker_matches(pbc, spEM1);
901 trace("Number of matches is %i\n", matchCnt);
903 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
904 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
905 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
906 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
908 trace("IROT::Register\n");
910 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
911 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
912 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
913 pprot, grflags, lpEM1, pmk2, pdwReg2);
915 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
916 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
918 matchCnt = count_moniker_matches(pbc, spEM2);
919 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
921 trace("IEnumMoniker::Clone\n");
922 IEnumMoniker_Clone(spEM2, &spEM3);
924 matchCnt = count_moniker_matches(pbc, spEM3);
925 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
926 trace("IEnumMoniker::Reset\n");
927 IEnumMoniker_Reset(spEM3);
929 matchCnt = count_moniker_matches(pbc, spEM3);
930 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
932 IRunningObjectTable_Revoke(pprot,pdwReg1);
933 IRunningObjectTable_Revoke(pprot,pdwReg2);
934 IEnumMoniker_Release(spEM1);
935 IEnumMoniker_Release(spEM1);
936 IEnumMoniker_Release(spEM2);
937 IEnumMoniker_Release(spEM3);
938 IMoniker_Release(pmk1);
939 IMoniker_Release(pmk2);
940 IRunningObjectTable_Release(pprot);
942 IBindCtx_Release(pbc);
945 static const LARGE_INTEGER llZero;
947 static const BYTE expected_class_moniker_marshal_data[] =
949 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
950 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
951 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
952 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
953 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
954 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
955 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
956 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
960 static const BYTE expected_class_moniker_saved_data[] =
962 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
963 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
967 static const BYTE expected_class_moniker_comparison_data[] =
969 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
970 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
971 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
972 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
975 static const WCHAR expected_class_moniker_display_name[] =
977 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
978 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
979 '0','0','0','0','4','6',':',0
982 static const BYTE expected_item_moniker_comparison_data[] =
984 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
985 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
986 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
990 static const BYTE expected_item_moniker_saved_data[] =
992 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
993 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
996 static const BYTE expected_item_moniker_marshal_data[] =
998 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
999 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1000 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1001 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1002 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1003 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1004 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1005 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1008 static const BYTE expected_anti_moniker_marshal_data[] =
1010 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1011 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1012 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1013 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1014 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1015 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1016 0x01,0x00,0x00,0x00,
1019 static const BYTE expected_anti_moniker_saved_data[] =
1021 0x01,0x00,0x00,0x00,
1024 static const BYTE expected_anti_moniker_comparison_data[] =
1026 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1027 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1028 0x01,0x00,0x00,0x00,
1031 static const BYTE expected_gc_moniker_marshal_data[] =
1033 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1034 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1035 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1036 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1037 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1038 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1039 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1040 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1041 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1042 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1043 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1044 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1045 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1046 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1047 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1048 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1049 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1050 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1051 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1052 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1053 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1054 0x00,0x57,0x69,0x6e,0x65,0x00,
1057 static const BYTE expected_gc_moniker_saved_data[] =
1059 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1060 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1061 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1062 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1063 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1064 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1065 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1066 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1070 static const BYTE expected_gc_moniker_comparison_data[] =
1072 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1073 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1074 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1075 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1076 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1077 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1078 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1079 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1080 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1083 static void test_moniker(
1084 const char *testname, IMoniker *moniker,
1085 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1086 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1087 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1088 LPCWSTR expected_display_name)
1094 LPBYTE moniker_data;
1099 IMoniker * moniker_proxy;
1100 LPOLESTR display_name;
1103 hr = IMoniker_IsDirty(moniker);
1104 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1108 hr = CreateBindCtx(0, &bindctx);
1109 ok_ole_success(hr, CreateBindCtx);
1111 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1112 ok_ole_success(hr, IMoniker_GetDisplayName);
1113 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1115 CoTaskMemFree(display_name);
1116 IBindCtx_Release(bindctx);
1118 hr = IMoniker_IsDirty(moniker);
1119 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1121 /* IROTData::GetComparisonData test */
1123 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1124 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1126 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1127 ok_ole_success(hr, IROTData_GetComparisonData);
1129 if (hr != S_OK) moniker_size = 0;
1131 /* first check we have the right amount of data */
1132 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1133 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1134 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1136 /* then do a byte-by-byte comparison */
1137 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1139 if (expected_moniker_comparison_data[i] != buffer[i])
1146 ok(same, "%s: Comparison data differs\n", testname);
1149 for (i = 0; i < moniker_size; i++)
1151 if (i % 8 == 0) printf(" ");
1152 printf("0x%02x,", buffer[i]);
1153 if (i % 8 == 7) printf("\n");
1158 IROTData_Release(rotdata);
1160 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1164 hr = IMoniker_Save(moniker, stream, TRUE);
1165 ok_ole_success(hr, IMoniker_Save);
1167 hr = GetHGlobalFromStream(stream, &hglobal);
1168 ok_ole_success(hr, GetHGlobalFromStream);
1170 moniker_size = GlobalSize(hglobal);
1172 moniker_data = GlobalLock(hglobal);
1174 /* first check we have the right amount of data */
1175 ok(moniker_size == sizeof_expected_moniker_saved_data,
1176 "%s: Size of saved data differs (expected %d, actual %d)\n",
1177 testname, sizeof_expected_moniker_saved_data, moniker_size);
1179 /* then do a byte-by-byte comparison */
1180 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
1182 if (expected_moniker_saved_data[i] != moniker_data[i])
1189 ok(same, "%s: Saved data differs\n", testname);
1192 for (i = 0; i < moniker_size; i++)
1194 if (i % 8 == 0) printf(" ");
1195 printf("0x%02x,", moniker_data[i]);
1196 if (i % 8 == 7) printf("\n");
1201 GlobalUnlock(hglobal);
1203 IStream_Release(stream);
1205 /* Marshaling tests */
1207 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1208 ok_ole_success(hr, CreateStreamOnHGlobal);
1210 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1211 ok_ole_success(hr, CoMarshalInterface);
1213 hr = GetHGlobalFromStream(stream, &hglobal);
1214 ok_ole_success(hr, GetHGlobalFromStream);
1216 moniker_size = GlobalSize(hglobal);
1218 moniker_data = GlobalLock(hglobal);
1220 /* first check we have the right amount of data */
1221 ok(moniker_size == sizeof_expected_moniker_marshal_data,
1222 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1223 testname, sizeof_expected_moniker_marshal_data, moniker_size);
1225 /* then do a byte-by-byte comparison */
1226 if (expected_moniker_marshal_data)
1228 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1230 if (expected_moniker_marshal_data[i] != moniker_data[i])
1238 ok(same, "%s: Marshaled data differs\n", testname);
1241 for (i = 0; i < moniker_size; i++)
1243 if (i % 8 == 0) printf(" ");
1244 printf("0x%02x,", moniker_data[i]);
1245 if (i % 8 == 7) printf("\n");
1250 GlobalUnlock(hglobal);
1252 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1253 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1254 ok_ole_success(hr, CoUnmarshalInterface);
1256 IStream_Release(stream);
1257 IMoniker_Release(moniker_proxy);
1260 static void test_class_moniker(void)
1271 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1272 ok_ole_success(hr, CreateClassMoniker);
1273 if (!moniker) return;
1275 test_moniker("class moniker", moniker,
1276 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1277 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1278 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1279 expected_class_moniker_display_name);
1283 hr = IMoniker_Hash(moniker, &hash);
1284 ok_ole_success(hr, IMoniker_Hash);
1286 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1287 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1290 /* IsSystemMoniker test */
1292 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1293 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1295 ok(moniker_type == MKSYS_CLASSMONIKER,
1296 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1299 hr = CreateBindCtx(0, &bindctx);
1300 ok_ole_success(hr, CreateBindCtx);
1302 /* IsRunning test */
1303 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1304 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1306 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1307 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1309 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1310 ok_ole_success(hr, IMoniker_BindToStorage);
1311 IUnknown_Release(unknown);
1313 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1314 ok_ole_success(hr, IMoniker_BindToStorage);
1315 IUnknown_Release(unknown);
1317 IBindCtx_Release(bindctx);
1319 hr = IMoniker_Inverse(moniker, &inverse);
1320 ok_ole_success(hr, IMoniker_Inverse);
1321 IMoniker_Release(inverse);
1323 IMoniker_Release(moniker);
1326 static void test_file_moniker(WCHAR* path)
1329 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1332 hr = CreateFileMoniker(path, &moniker1);
1333 ok_ole_success(hr, CreateFileMoniker);
1335 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1338 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1339 ok_ole_success(hr, CoMarshalInterface);
1342 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1343 ok_ole_success(hr, IStream_Seek);
1346 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1347 ok_ole_success(hr, CoUnmarshalInterface);
1349 hr = IMoniker_IsEqual(moniker1, moniker2);
1350 ok_ole_success(hr, IsEqual);
1352 IStream_Release(stream);
1354 IMoniker_Release(moniker1);
1356 IMoniker_Release(moniker2);
1359 static void test_file_monikers(void)
1361 static WCHAR wszFile[][30] = {
1362 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1363 {'\\', '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},
1364 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1365 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1366 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1367 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1368 * U+0100 .. = Latin extended-A
1370 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1375 trace("ACP is %u\n", GetACP());
1377 for (i = 0; i < COUNTOF(wszFile); ++i)
1380 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1383 test_file_moniker(wszFile[i]);
1388 static void test_item_moniker(void)
1397 static const WCHAR wszDelimeter[] = {'!',0};
1398 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1399 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1401 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1402 ok_ole_success(hr, CreateItemMoniker);
1404 test_moniker("item moniker", moniker,
1405 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1406 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1407 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1408 expected_display_name);
1412 hr = IMoniker_Hash(moniker, &hash);
1413 ok_ole_success(hr, IMoniker_Hash);
1416 "Hash value != 0x73c, instead was 0x%08x\n",
1419 /* IsSystemMoniker test */
1421 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1422 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1424 ok(moniker_type == MKSYS_ITEMMONIKER,
1425 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1428 hr = CreateBindCtx(0, &bindctx);
1429 ok_ole_success(hr, CreateBindCtx);
1431 /* IsRunning test */
1432 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1433 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1435 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1436 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1438 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1439 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1441 IBindCtx_Release(bindctx);
1443 hr = IMoniker_Inverse(moniker, &inverse);
1444 ok_ole_success(hr, IMoniker_Inverse);
1445 IMoniker_Release(inverse);
1447 IMoniker_Release(moniker);
1450 static void test_anti_moniker(void)
1460 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1462 hr = CreateAntiMoniker(&moniker);
1463 ok_ole_success(hr, CreateAntiMoniker);
1464 if (!moniker) return;
1466 test_moniker("anti moniker", moniker,
1467 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1468 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1469 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1470 expected_display_name);
1473 hr = IMoniker_Hash(moniker, &hash);
1474 ok_ole_success(hr, IMoniker_Hash);
1475 ok(hash == 0x80000001,
1476 "Hash value != 0x80000001, instead was 0x%08x\n",
1479 /* IsSystemMoniker test */
1480 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1481 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1482 ok(moniker_type == MKSYS_ANTIMONIKER,
1483 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1486 hr = IMoniker_Inverse(moniker, &inverse);
1487 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1488 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1490 hr = CreateBindCtx(0, &bindctx);
1491 ok_ole_success(hr, CreateBindCtx);
1493 /* IsRunning test */
1494 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1495 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1497 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1498 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1500 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1501 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1503 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1504 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1506 IBindCtx_Release(bindctx);
1508 IMoniker_Release(moniker);
1511 static void test_generic_composite_moniker(void)
1523 static const WCHAR wszDelimeter1[] = {'!',0};
1524 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1525 static const WCHAR wszDelimeter2[] = {'#',0};
1526 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1527 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1529 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1530 ok_ole_success(hr, CreateItemMoniker);
1531 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1532 ok_ole_success(hr, CreateItemMoniker);
1533 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1534 ok_ole_success(hr, CreateGenericComposite);
1536 test_moniker("generic composite moniker", moniker,
1537 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1538 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1539 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1540 expected_display_name);
1544 hr = IMoniker_Hash(moniker, &hash);
1545 ok_ole_success(hr, IMoniker_Hash);
1548 "Hash value != 0xd87, instead was 0x%08x\n",
1551 /* IsSystemMoniker test */
1553 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1554 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1556 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1557 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1560 hr = CreateBindCtx(0, &bindctx);
1561 ok_ole_success(hr, CreateBindCtx);
1563 /* IsRunning test */
1564 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1566 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1568 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1569 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1571 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1573 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1576 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1577 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1579 IBindCtx_Release(bindctx);
1581 hr = IMoniker_Inverse(moniker, &inverse);
1582 ok_ole_success(hr, IMoniker_Inverse);
1583 IMoniker_Release(inverse);
1585 IMoniker_Release(moniker);
1588 static void test_bind_context(void)
1592 IEnumString *pEnumString;
1593 BIND_OPTS2 bind_opts;
1594 HeapUnknown *unknown;
1595 HeapUnknown *unknown2;
1596 IUnknown *param_obj;
1598 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1599 static const WCHAR wszNonExistant[] = {'N','o','n','E','x','i','s','t','a','n','t',0};
1601 hr = CreateBindCtx(0, NULL);
1602 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1604 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1605 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1607 hr = CreateBindCtx(0, &pBindCtx);
1608 ok_ole_success(hr, "CreateBindCtx");
1610 bind_opts.cbStruct = -1;
1611 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1612 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1613 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1615 bind_opts.cbStruct = sizeof(BIND_OPTS);
1616 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1617 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1618 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1620 bind_opts.cbStruct = sizeof(bind_opts);
1621 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1622 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1623 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1624 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1625 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1626 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1627 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1628 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1629 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1630 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1631 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1633 bind_opts.cbStruct = -1;
1634 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1635 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1637 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1638 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1640 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1641 unknown->lpVtbl = &HeapUnknown_Vtbl;
1643 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1644 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1646 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, ¶m_obj);
1647 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1648 IUnknown_Release(param_obj);
1650 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistant, ¶m_obj);
1651 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with non-existing key should have failed with E_FAIL instead of 0x%08x\n", hr);
1652 ok(param_obj == NULL, "IBindCtx_GetObjectParam with non-existing key should have set output parameter to NULL instead of %p\n", param_obj);
1654 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistant);
1655 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with non-existing key should have failed with E_FAIL instead of 0x%08x\n", hr);
1657 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1658 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1659 ok(!pEnumString, "pEnumString should be NULL\n");
1661 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1662 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1664 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1665 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1667 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1668 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1670 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1671 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1673 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1674 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1676 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1677 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1679 IBindCtx_Release(pBindCtx);
1681 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1682 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1684 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1685 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1690 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1693 test_MkParseDisplayName();
1694 test_class_moniker();
1695 test_file_monikers();
1696 test_item_moniker();
1697 test_anti_moniker();
1698 test_generic_composite_moniker();
1700 /* FIXME: test moniker creation funcs and parsing other moniker formats */
1702 test_bind_context();