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
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)
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_TestMoniker
=
58 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
62 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
67 static void LockModule(void)
69 InterlockedIncrement(&cLocks
);
72 static void UnlockModule(void)
74 InterlockedDecrement(&cLocks
);
77 static SIZE_T
round_global_size(SIZE_T size
)
79 static SIZE_T global_size_alignment
= -1;
80 if (global_size_alignment
== -1)
82 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
83 global_size_alignment
= GlobalSize(p
);
87 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
90 static DWORD external_connections
;
92 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
94 ok(0, "unexpected call\n");
99 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
104 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
109 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
111 trace("add connection\n");
113 ok(extconn
== EXTCONN_STRONG
, "extconn = %d\n", extconn
);
114 ok(!reserved
, "reserved = %x\n", reserved
);
115 return ++external_connections
;
118 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
119 DWORD reserved
, BOOL fLastReleaseCloses
)
121 trace("release connection\n");
123 ok(extconn
== EXTCONN_STRONG
, "extconn = %d\n", extconn
);
124 ok(!reserved
, "reserved = %x\n", reserved
);
126 return --external_connections
;
129 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
130 ExternalConnection_QueryInterface
,
131 ExternalConnection_AddRef
,
132 ExternalConnection_Release
,
133 ExternalConnection_AddConnection
,
134 ExternalConnection_ReleaseConnection
137 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
139 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
140 LPCLASSFACTORY iface
,
144 if (ppvObj
== NULL
) return E_POINTER
;
146 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
147 IsEqualGUID(riid
, &IID_IClassFactory
))
150 IClassFactory_AddRef(iface
);
154 if(IsEqualGUID(riid
, &IID_IExternalConnection
)) {
155 *ppvObj
= &ExternalConnection
;
160 return E_NOINTERFACE
;
163 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
166 return 2; /* non-heap-based object */
169 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
172 return 1; /* non-heap-based object */
175 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
176 LPCLASSFACTORY iface
,
184 static HRESULT WINAPI
Test_IClassFactory_LockServer(
185 LPCLASSFACTORY iface
,
191 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
193 Test_IClassFactory_QueryInterface
,
194 Test_IClassFactory_AddRef
,
195 Test_IClassFactory_Release
,
196 Test_IClassFactory_CreateInstance
,
197 Test_IClassFactory_LockServer
200 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
204 IUnknown IUnknown_iface
;
208 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
210 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
213 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
215 if (IsEqualIID(riid
, &IID_IUnknown
))
217 IUnknown_AddRef(iface
);
222 return E_NOINTERFACE
;
225 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
227 HeapUnknown
*This
= impl_from_IUnknown(iface
);
228 return InterlockedIncrement((LONG
*)&This
->refs
);
231 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
233 HeapUnknown
*This
= impl_from_IUnknown(iface
);
234 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
235 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
239 static const IUnknownVtbl HeapUnknown_Vtbl
=
241 HeapUnknown_QueryInterface
,
246 static HRESULT WINAPI
247 MonikerNoROTData_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
254 if (IsEqualIID(&IID_IUnknown
, riid
) ||
255 IsEqualIID(&IID_IPersist
, riid
) ||
256 IsEqualIID(&IID_IPersistStream
,riid
) ||
257 IsEqualIID(&IID_IMoniker
, riid
))
259 if (IsEqualIID(&IID_IROTData
, riid
))
260 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
263 return E_NOINTERFACE
;
265 IMoniker_AddRef(iface
);
271 Moniker_AddRef(IMoniker
* iface
)
277 Moniker_Release(IMoniker
* iface
)
282 static HRESULT WINAPI
283 Moniker_GetClassID(IMoniker
* iface
, CLSID
*pClassID
)
285 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
287 *pClassID
= CLSID_TestMoniker
;
292 static HRESULT WINAPI
293 Moniker_IsDirty(IMoniker
* iface
)
295 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
300 static HRESULT WINAPI
301 Moniker_Load(IMoniker
* iface
, IStream
* pStm
)
303 CHECK_EXPECTED_METHOD("Moniker_Load");
307 static HRESULT WINAPI
308 Moniker_Save(IMoniker
* iface
, IStream
* pStm
, BOOL fClearDirty
)
310 CHECK_EXPECTED_METHOD("Moniker_Save");
314 static HRESULT WINAPI
315 Moniker_GetSizeMax(IMoniker
* iface
, ULARGE_INTEGER
* pcbSize
)
317 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
321 static HRESULT WINAPI
322 Moniker_BindToObject(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
323 REFIID riid
, VOID
** ppvResult
)
325 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
329 static HRESULT WINAPI
330 Moniker_BindToStorage(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
331 REFIID riid
, VOID
** ppvObject
)
333 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
337 static HRESULT WINAPI
338 Moniker_Reduce(IMoniker
* iface
, IBindCtx
* pbc
, DWORD dwReduceHowFar
,
339 IMoniker
** ppmkToLeft
, IMoniker
** ppmkReduced
)
341 CHECK_EXPECTED_METHOD("Moniker_Reduce");
343 if (ppmkReduced
==NULL
)
346 IMoniker_AddRef(iface
);
350 return MK_S_REDUCED_TO_SELF
;
353 static HRESULT WINAPI
354 Moniker_ComposeWith(IMoniker
* iface
, IMoniker
* pmkRight
,
355 BOOL fOnlyIfNotGeneric
, IMoniker
** ppmkComposite
)
357 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
361 static HRESULT WINAPI
362 Moniker_Enum(IMoniker
* iface
,BOOL fForward
, IEnumMoniker
** ppenumMoniker
)
364 CHECK_EXPECTED_METHOD("Moniker_Enum");
366 if (ppenumMoniker
== NULL
)
369 *ppenumMoniker
= NULL
;
374 static HRESULT WINAPI
375 Moniker_IsEqual(IMoniker
* iface
,IMoniker
* pmkOtherMoniker
)
377 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
381 static HRESULT WINAPI
382 Moniker_Hash(IMoniker
* iface
,DWORD
* pdwHash
)
384 CHECK_EXPECTED_METHOD("Moniker_Hash");
388 static HRESULT WINAPI
389 Moniker_IsRunning(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
390 IMoniker
* pmkNewlyRunning
)
392 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
396 static HRESULT WINAPI
397 Moniker_GetTimeOfLastChange(IMoniker
* iface
, IBindCtx
* pbc
,
398 IMoniker
* pmkToLeft
, FILETIME
* pFileTime
)
400 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
404 static HRESULT WINAPI
405 Moniker_Inverse(IMoniker
* iface
,IMoniker
** ppmk
)
407 CHECK_EXPECTED_METHOD("Moniker_Inverse");
411 static HRESULT WINAPI
412 Moniker_CommonPrefixWith(IMoniker
* iface
,IMoniker
* pmkOther
,IMoniker
** ppmkPrefix
)
414 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
418 static HRESULT WINAPI
419 Moniker_RelativePathTo(IMoniker
* iface
,IMoniker
* pmOther
, IMoniker
** ppmkRelPath
)
421 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
425 static HRESULT WINAPI
426 Moniker_GetDisplayName(IMoniker
* iface
, IBindCtx
* pbc
,
427 IMoniker
* pmkToLeft
, LPOLESTR
*ppszDisplayName
)
429 static const WCHAR wszDisplayName
[] = {'*','*','G','e','m','m','a',0};
430 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
431 *ppszDisplayName
= CoTaskMemAlloc(sizeof(wszDisplayName
));
432 memcpy(*ppszDisplayName
, wszDisplayName
, sizeof(wszDisplayName
));
436 static HRESULT WINAPI
437 Moniker_ParseDisplayName(IMoniker
* iface
, IBindCtx
* pbc
, IMoniker
* pmkToLeft
,
438 LPOLESTR pszDisplayName
, ULONG
* pchEaten
, IMoniker
** ppmkOut
)
440 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
444 static HRESULT WINAPI
445 Moniker_IsSystemMoniker(IMoniker
* iface
,DWORD
* pwdMksys
)
447 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
452 (*pwdMksys
)=MKSYS_NONE
;
457 static const IMonikerVtbl MonikerNoROTDataVtbl
=
459 MonikerNoROTData_QueryInterface
,
467 Moniker_BindToObject
,
468 Moniker_BindToStorage
,
475 Moniker_GetTimeOfLastChange
,
477 Moniker_CommonPrefixWith
,
478 Moniker_RelativePathTo
,
479 Moniker_GetDisplayName
,
480 Moniker_ParseDisplayName
,
481 Moniker_IsSystemMoniker
484 static IMoniker MonikerNoROTData
= { &MonikerNoROTDataVtbl
};
486 static IMoniker Moniker
;
488 static HRESULT WINAPI
489 ROTData_QueryInterface(IROTData
*iface
,REFIID riid
,VOID
** ppvObject
)
491 return IMoniker_QueryInterface(&Moniker
, riid
, ppvObject
);
495 ROTData_AddRef(IROTData
*iface
)
501 ROTData_Release(IROTData
* iface
)
506 static HRESULT WINAPI
507 ROTData_GetComparisonData(IROTData
* iface
, BYTE
* pbData
,
508 ULONG cbMax
, ULONG
* pcbData
)
510 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
513 if (cbMax
< *pcbData
)
514 return E_OUTOFMEMORY
;
521 static IROTDataVtbl ROTDataVtbl
=
523 ROTData_QueryInterface
,
526 ROTData_GetComparisonData
529 static IROTData ROTData
= { &ROTDataVtbl
};
531 static HRESULT WINAPI
532 Moniker_QueryInterface(IMoniker
* iface
,REFIID riid
,void** ppvObject
)
539 if (IsEqualIID(&IID_IUnknown
, riid
) ||
540 IsEqualIID(&IID_IPersist
, riid
) ||
541 IsEqualIID(&IID_IPersistStream
,riid
) ||
542 IsEqualIID(&IID_IMoniker
, riid
))
544 if (IsEqualIID(&IID_IROTData
, riid
))
546 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
547 *ppvObject
= &ROTData
;
551 return E_NOINTERFACE
;
553 IMoniker_AddRef(iface
);
558 static const IMonikerVtbl MonikerVtbl
=
560 Moniker_QueryInterface
,
568 Moniker_BindToObject
,
569 Moniker_BindToStorage
,
576 Moniker_GetTimeOfLastChange
,
578 Moniker_CommonPrefixWith
,
579 Moniker_RelativePathTo
,
580 Moniker_GetDisplayName
,
581 Moniker_ParseDisplayName
,
582 Moniker_IsSystemMoniker
585 static IMoniker Moniker
= { &MonikerVtbl
};
587 static void test_ROT(void)
589 static const WCHAR wszFileName
[] = {'B','E','2','0','E','2','F','5','-',
590 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
591 '2','0','4','6','E','5','8','6','C','9','2','5',0};
593 IMoniker
*pMoniker
= NULL
;
594 IRunningObjectTable
*pROT
= NULL
;
596 static const char *methods_register_no_ROTData
[] =
599 "Moniker_GetTimeOfLastChange",
600 "Moniker_QueryInterface(IID_IROTData)",
601 "Moniker_GetDisplayName",
602 "Moniker_GetClassID",
605 static const char *methods_register
[] =
608 "Moniker_GetTimeOfLastChange",
609 "Moniker_QueryInterface(IID_IROTData)",
610 "ROTData_GetComparisonData",
613 static const char *methods_isrunning_no_ROTData
[] =
616 "Moniker_QueryInterface(IID_IROTData)",
617 "Moniker_GetDisplayName",
618 "Moniker_GetClassID",
621 static const char *methods_isrunning
[] =
624 "Moniker_QueryInterface(IID_IROTData)",
625 "ROTData_GetComparisonData",
631 hr
= GetRunningObjectTable(0, &pROT
);
632 ok_ole_success(hr
, GetRunningObjectTable
);
634 expected_method_list
= methods_register_no_ROTData
;
635 external_connections
= 0;
636 /* try with our own moniker that doesn't support IROTData */
637 hr
= IRunningObjectTable_Register(pROT
, ROTFLAGS_REGISTRATIONKEEPSALIVE
,
638 (IUnknown
*)&Test_ClassFactory
, &MonikerNoROTData
, &dwCookie
);
639 ok_ole_success(hr
, IRunningObjectTable_Register
);
640 ok(!*expected_method_list
, "Method sequence starting from %s not called\n", *expected_method_list
);
641 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
643 ok_more_than_one_lock();
645 expected_method_list
= methods_isrunning_no_ROTData
;
646 hr
= IRunningObjectTable_IsRunning(pROT
, &MonikerNoROTData
);
647 ok_ole_success(hr
, IRunningObjectTable_IsRunning
);
648 ok(!*expected_method_list
, "Method sequence starting from %s not called\n", *expected_method_list
);
650 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie
);
651 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
652 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
656 expected_method_list
= methods_register
;
657 /* try with our own moniker */
658 hr
= IRunningObjectTable_Register(pROT
, ROTFLAGS_REGISTRATIONKEEPSALIVE
,
659 (IUnknown
*)&Test_ClassFactory
, &Moniker
, &dwCookie
);
660 ok_ole_success(hr
, IRunningObjectTable_Register
);
661 ok(!*expected_method_list
, "Method sequence starting from %s not called\n", *expected_method_list
);
663 ok_more_than_one_lock();
665 expected_method_list
= methods_isrunning
;
666 hr
= IRunningObjectTable_IsRunning(pROT
, &Moniker
);
667 ok_ole_success(hr
, IRunningObjectTable_IsRunning
);
668 ok(!*expected_method_list
, "Method sequence starting from %s not called\n", *expected_method_list
);
670 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie
);
671 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
675 hr
= CreateFileMoniker(wszFileName
, &pMoniker
);
676 ok_ole_success(hr
, CreateClassMoniker
);
679 external_connections
= 0;
680 hr
= IRunningObjectTable_Register(pROT
, 0, (IUnknown
*)&Test_ClassFactory
,
681 pMoniker
, &dwCookie
);
682 ok_ole_success(hr
, IRunningObjectTable_Register
);
683 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
685 ok_more_than_one_lock();
687 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie
);
688 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
692 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
693 hr
= IRunningObjectTable_Register(pROT
, ROTFLAGS_REGISTRATIONKEEPSALIVE
,
694 (IUnknown
*)&Test_ClassFactory
, pMoniker
, &dwCookie
);
695 ok_ole_success(hr
, IRunningObjectTable_Register
);
697 ok_more_than_one_lock();
699 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie
);
700 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
704 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
705 /* only succeeds when process is started by SCM and has LocalService
706 * or RunAs AppId values */
707 hr
= IRunningObjectTable_Register(pROT
,
708 ROTFLAGS_REGISTRATIONKEEPSALIVE
|ROTFLAGS_ALLOWANYCLIENT
,
709 (IUnknown
*)&Test_ClassFactory
, pMoniker
, &dwCookie
);
711 ok(hr
== CO_E_WRONG_SERVER_IDENTITY
||
712 broken(hr
== S_OK
) /* Win9x */,
713 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr
);
715 if (hr
== S_OK
) IRunningObjectTable_Revoke(pROT
, dwCookie
);
717 hr
= IRunningObjectTable_Register(pROT
, 0xdeadbeef,
718 (IUnknown
*)&Test_ClassFactory
, pMoniker
, &dwCookie
);
719 ok(hr
== E_INVALIDARG
, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
721 IMoniker_Release(pMoniker
);
723 IRunningObjectTable_Release(pROT
);
726 static void test_ROT_multiple_entries(void)
729 IMoniker
*pMoniker
= NULL
;
730 IRunningObjectTable
*pROT
= NULL
;
731 DWORD dwCookie1
, dwCookie2
;
732 IUnknown
*pObject
= NULL
;
733 static const WCHAR moniker_path
[] =
734 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
736 hr
= GetRunningObjectTable(0, &pROT
);
737 ok_ole_success(hr
, GetRunningObjectTable
);
739 hr
= CreateFileMoniker(moniker_path
, &pMoniker
);
740 ok_ole_success(hr
, CreateFileMoniker
);
742 hr
= IRunningObjectTable_Register(pROT
, 0, (IUnknown
*)&Test_ClassFactory
, pMoniker
, &dwCookie1
);
743 ok_ole_success(hr
, IRunningObjectTable_Register
);
745 hr
= IRunningObjectTable_Register(pROT
, 0, (IUnknown
*)&Test_ClassFactory
, pMoniker
, &dwCookie2
);
746 ok(hr
== MK_S_MONIKERALREADYREGISTERED
, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr
);
748 ok(dwCookie1
!= dwCookie2
, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1
);
750 hr
= IRunningObjectTable_GetObject(pROT
, pMoniker
, &pObject
);
751 ok_ole_success(hr
, IRunningObjectTable_GetObject
);
752 IUnknown_Release(pObject
);
754 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie1
);
755 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
757 hr
= IRunningObjectTable_GetObject(pROT
, pMoniker
, &pObject
);
758 ok_ole_success(hr
, IRunningObjectTable_GetObject
);
759 IUnknown_Release(pObject
);
761 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie2
);
762 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
764 IMoniker_Release(pMoniker
);
766 IRunningObjectTable_Release(pROT
);
769 static HRESULT WINAPI
ParseDisplayName_QueryInterface(IParseDisplayName
*iface
, REFIID riid
, void **ppv
)
771 if (IsEqualIID(riid
, &IID_IUnknown
) ||
772 IsEqualIID(riid
, &IID_IParseDisplayName
))
775 IParseDisplayName_AddRef(iface
);
779 return E_NOINTERFACE
;
782 static ULONG WINAPI
ParseDisplayName_AddRef(IParseDisplayName
*iface
)
787 static ULONG WINAPI
ParseDisplayName_Release(IParseDisplayName
*iface
)
792 static LPCWSTR expected_display_name
;
794 static HRESULT WINAPI
ParseDisplayName_ParseDisplayName(IParseDisplayName
*iface
,
796 LPOLESTR pszDisplayName
,
800 char display_nameA
[256];
801 WideCharToMultiByte(CP_ACP
, 0, pszDisplayName
, -1, display_nameA
, sizeof(display_nameA
), NULL
, NULL
);
802 ok(!lstrcmpW(pszDisplayName
, expected_display_name
), "unexpected display name \"%s\"\n", display_nameA
);
803 ok(pszDisplayName
== expected_display_name
, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
804 *pchEaten
= lstrlenW(pszDisplayName
);
805 return CreateAntiMoniker(ppmkOut
);
808 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl
=
810 ParseDisplayName_QueryInterface
,
811 ParseDisplayName_AddRef
,
812 ParseDisplayName_Release
,
813 ParseDisplayName_ParseDisplayName
816 static IParseDisplayName ParseDisplayName
= { &ParseDisplayName_Vtbl
};
818 static int count_moniker_matches(IBindCtx
* pbc
, IEnumMoniker
* spEM
)
820 IMoniker
* spMoniker
;
821 int monCnt
=0, matchCnt
=0;
823 while ((IEnumMoniker_Next(spEM
, 1, &spMoniker
, NULL
)==S_OK
))
828 hr
=IMoniker_GetDisplayName(spMoniker
, pbc
, NULL
, &szDisplayn
);
831 if (!lstrcmpiW(szDisplayn
, wszFileName1
) || !lstrcmpiW(szDisplayn
, wszFileName2
))
833 CoTaskMemFree(szDisplayn
);
836 trace("Total number of monikers is %i\n", monCnt
);
840 static void test_MkParseDisplayName(void)
842 IBindCtx
* pbc
= NULL
;
844 IMoniker
* pmk
= NULL
;
845 IMoniker
* pmk1
= NULL
;
846 IMoniker
* pmk2
= NULL
;
849 IUnknown
* object
= NULL
;
853 IEnumMoniker
*spEM1
= NULL
;
854 IEnumMoniker
*spEM2
= NULL
;
855 IEnumMoniker
*spEM3
= NULL
;
861 IRunningObjectTable
* pprot
=NULL
;
863 /* CLSID of My Computer */
864 static const WCHAR wszDisplayName
[] = {'c','l','s','i','d',':',
865 '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};
866 static const WCHAR wszDisplayNameClsid
[] = {'c','l','s','i','d',':',0};
867 static const WCHAR wszNonExistentProgId
[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
868 static const WCHAR wszDisplayNameRunning
[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
869 static const WCHAR wszDisplayNameProgId1
[] = {'S','t','d','F','o','n','t',':',0};
870 static const WCHAR wszDisplayNameProgId2
[] = {'@','S','t','d','F','o','n','t',0};
871 static const WCHAR wszDisplayNameProgIdFail
[] = {'S','t','d','F','o','n','t',0};
872 static const WCHAR wszEmpty
[] = {0};
873 char szDisplayNameFile
[256];
874 WCHAR wszDisplayNameFile
[256];
880 LPCOLESTR szDisplayName
;
883 } invalid_parameters
[] =
885 {NULL
, NULL
, NULL
, NULL
},
886 {NULL
, NULL
, NULL
, &pmk
},
887 {NULL
, NULL
, &eaten
, NULL
},
888 {NULL
, NULL
, &eaten
, &pmk
},
889 {NULL
, wszEmpty
, NULL
, NULL
},
890 {NULL
, wszEmpty
, NULL
, &pmk
},
891 {NULL
, wszEmpty
, &eaten
, NULL
},
892 {NULL
, wszEmpty
, &eaten
, &pmk
},
893 {&pbc
, NULL
, NULL
, NULL
},
894 {&pbc
, NULL
, NULL
, &pmk
},
895 {&pbc
, NULL
, &eaten
, NULL
},
896 {&pbc
, NULL
, &eaten
, &pmk
},
897 {&pbc
, wszEmpty
, NULL
, NULL
},
898 {&pbc
, wszEmpty
, NULL
, &pmk
},
899 {&pbc
, wszEmpty
, &eaten
, NULL
},
900 {&pbc
, wszEmpty
, &eaten
, &pmk
},
903 hr
= CreateBindCtx(0, &pbc
);
904 ok_ole_success(hr
, CreateBindCtx
);
906 for (i
= 0; i
< ARRAY_SIZE(invalid_parameters
); i
++)
909 pmk
= (IMoniker
*)0xdeadbeef;
910 hr
= MkParseDisplayName(invalid_parameters
[i
].ppbc
? *invalid_parameters
[i
].ppbc
: NULL
,
911 invalid_parameters
[i
].szDisplayName
,
912 invalid_parameters
[i
].pchEaten
,
913 invalid_parameters
[i
].ppmk
);
914 ok(hr
== E_INVALIDARG
, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i
, hr
);
915 ok(eaten
== 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i
, eaten
);
916 ok(pmk
== (IMoniker
*)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i
, pmk
);
920 pmk
= (IMoniker
*)0xdeadbeef;
921 hr
= MkParseDisplayName(pbc
, wszNonExistentProgId
, &eaten
, &pmk
);
922 ok(hr
== MK_E_SYNTAX
|| hr
== MK_E_CANTOPENFILE
/* Win9x */,
923 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr
);
924 ok(eaten
== 0, "Processed character count should have been 0 instead of %u\n", eaten
);
925 ok(pmk
== NULL
, "Output moniker pointer should have been NULL instead of %p\n", pmk
);
927 /* no special handling of "clsid:" without the string form of the clsid
930 pmk
= (IMoniker
*)0xdeadbeef;
931 hr
= MkParseDisplayName(pbc
, wszDisplayNameClsid
, &eaten
, &pmk
);
932 ok(hr
== MK_E_SYNTAX
|| hr
== MK_E_CANTOPENFILE
/* Win9x */,
933 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr
);
934 ok(eaten
== 0, "Processed character count should have been 0 instead of %u\n", eaten
);
935 ok(pmk
== NULL
, "Output moniker pointer should have been NULL instead of %p\n", pmk
);
937 /* shows clsid has higher precedence than a running object */
938 hr
= CreateFileMoniker(wszDisplayName
, &pmk
);
939 ok_ole_success(hr
, CreateFileMoniker
);
940 hr
= IBindCtx_GetRunningObjectTable(pbc
, &pprot
);
941 ok_ole_success(hr
, IBindCtx_GetRunningObjectTable
);
942 hr
= IRunningObjectTable_Register(pprot
, 0, (IUnknown
*)&Test_ClassFactory
, pmk
, &pdwReg1
);
943 ok_ole_success(hr
, IRunningObjectTable_Register
);
944 IMoniker_Release(pmk
);
946 hr
= MkParseDisplayName(pbc
, wszDisplayName
, &eaten
, &pmk
);
947 ok_ole_success(hr
, MkParseDisplayName
);
948 ok(eaten
== ARRAY_SIZE(wszDisplayName
) - 1,
949 "Processed character count should have been 43 instead of %u\n", eaten
);
952 IMoniker_IsSystemMoniker(pmk
, &moniker_type
);
953 ok(moniker_type
== MKSYS_CLASSMONIKER
, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type
);
954 IMoniker_Release(pmk
);
956 hr
= IRunningObjectTable_Revoke(pprot
, pdwReg1
);
957 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
958 IRunningObjectTable_Release(pprot
);
960 hr
= CreateFileMoniker(wszDisplayNameRunning
, &pmk
);
961 ok_ole_success(hr
, CreateFileMoniker
);
962 hr
= IBindCtx_GetRunningObjectTable(pbc
, &pprot
);
963 ok_ole_success(hr
, IBindCtx_GetRunningObjectTable
);
964 hr
= IRunningObjectTable_Register(pprot
, 0, (IUnknown
*)&Test_ClassFactory
, pmk
, &pdwReg1
);
965 ok_ole_success(hr
, IRunningObjectTable_Register
);
966 IMoniker_Release(pmk
);
968 hr
= MkParseDisplayName(pbc
, wszDisplayNameRunning
, &eaten
, &pmk
);
969 ok_ole_success(hr
, MkParseDisplayName
);
970 ok(eaten
== ARRAY_SIZE(wszDisplayNameRunning
) - 1,
971 "Processed character count should have been 15 instead of %u\n", eaten
);
974 IMoniker_IsSystemMoniker(pmk
, &moniker_type
);
975 ok(moniker_type
== MKSYS_FILEMONIKER
, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type
);
976 IMoniker_Release(pmk
);
978 hr
= IRunningObjectTable_Revoke(pprot
, pdwReg1
);
979 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
980 IRunningObjectTable_Release(pprot
);
982 hr
= CoRegisterClassObject(&CLSID_StdFont
, (IUnknown
*)&ParseDisplayName
, CLSCTX_INPROC_SERVER
, REGCLS_MULTI_SEPARATE
, &pdwReg1
);
983 ok_ole_success(hr
, CoRegisterClassObject
);
985 expected_display_name
= wszDisplayNameProgId1
;
986 hr
= MkParseDisplayName(pbc
, wszDisplayNameProgId1
, &eaten
, &pmk
);
987 ok_ole_success(hr
, MkParseDisplayName
);
988 ok(eaten
== ARRAY_SIZE(wszDisplayNameProgId1
) - 1,
989 "Processed character count should have been 8 instead of %u\n", eaten
);
992 IMoniker_IsSystemMoniker(pmk
, &moniker_type
);
993 ok(moniker_type
== MKSYS_ANTIMONIKER
, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type
);
994 IMoniker_Release(pmk
);
997 expected_display_name
= wszDisplayNameProgId2
;
998 hr
= MkParseDisplayName(pbc
, wszDisplayNameProgId2
, &eaten
, &pmk
);
999 ok_ole_success(hr
, MkParseDisplayName
);
1000 ok(eaten
== ARRAY_SIZE(wszDisplayNameProgId2
) - 1,
1001 "Processed character count should have been 8 instead of %u\n", eaten
);
1004 IMoniker_IsSystemMoniker(pmk
, &moniker_type
);
1005 ok(moniker_type
== MKSYS_ANTIMONIKER
, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type
);
1006 IMoniker_Release(pmk
);
1010 pmk
= (IMoniker
*)0xdeadbeef;
1011 hr
= MkParseDisplayName(pbc
, wszDisplayNameProgIdFail
, &eaten
, &pmk
);
1012 ok(hr
== MK_E_SYNTAX
|| hr
== MK_E_CANTOPENFILE
/* Win9x */,
1013 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr
);
1014 ok(eaten
== 0, "Processed character count should have been 0 instead of %u\n", eaten
);
1015 ok(pmk
== NULL
, "Output moniker pointer should have been NULL instead of %p\n", pmk
);
1017 hr
= CoRevokeClassObject(pdwReg1
);
1018 ok_ole_success(hr
, CoRevokeClassObject
);
1020 GetSystemDirectoryA(szDisplayNameFile
, sizeof(szDisplayNameFile
));
1021 strcat(szDisplayNameFile
, "\\kernel32.dll");
1022 len
= MultiByteToWideChar(CP_ACP
, 0, szDisplayNameFile
, -1, wszDisplayNameFile
,
1023 ARRAY_SIZE(wszDisplayNameFile
));
1024 hr
= MkParseDisplayName(pbc
, wszDisplayNameFile
, &eaten
, &pmk
);
1025 ok_ole_success(hr
, MkParseDisplayName
);
1026 ok(eaten
== len
- 1, "Processed character count should have been %d instead of %u\n", len
- 1, eaten
);
1029 IMoniker_IsSystemMoniker(pmk
, &moniker_type
);
1030 ok(moniker_type
== MKSYS_FILEMONIKER
, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type
);
1031 IMoniker_Release(pmk
);
1034 hr
= MkParseDisplayName(pbc
, wszDisplayName
, &eaten
, &pmk
);
1035 ok_ole_success(hr
, MkParseDisplayName
);
1036 ok(eaten
== ARRAY_SIZE(wszDisplayName
) - 1,
1037 "Processed character count should have been 43 instead of %u\n", eaten
);
1041 hr
= IMoniker_BindToObject(pmk
, pbc
, NULL
, &IID_IUnknown
, (LPVOID
*)&object
);
1042 ok_ole_success(hr
, IMoniker_BindToObject
);
1045 IUnknown_Release(object
);
1046 IMoniker_Release(pmk
);
1048 IBindCtx_Release(pbc
);
1050 /* Test the EnumMoniker interface */
1051 hr
= CreateBindCtx(0, &pbc
);
1052 ok_ole_success(hr
, CreateBindCtx
);
1054 hr
= CreateFileMoniker(wszFileName1
, &pmk1
);
1055 ok(hr
==0, "CreateFileMoniker for file hr=%08x\n", hr
);
1056 hr
= CreateFileMoniker(wszFileName2
, &pmk2
);
1057 ok(hr
==0, "CreateFileMoniker for file hr=%08x\n", hr
);
1058 hr
= IBindCtx_GetRunningObjectTable(pbc
, &pprot
);
1059 ok(hr
==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr
);
1061 /* Check EnumMoniker before registering */
1062 hr
= IRunningObjectTable_EnumRunning(pprot
, &spEM1
);
1063 ok(hr
==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr
);
1064 hr
= IEnumMoniker_QueryInterface(spEM1
, &IID_IUnknown
, (void*) &lpEM1
);
1065 /* Register a couple of Monikers and check is ok */
1066 ok(hr
==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr
, lpEM1
);
1068 matchCnt
= count_moniker_matches(pbc
, spEM1
);
1069 trace("Number of matches is %i\n", matchCnt
);
1071 grflags
= grflags
| ROTFLAGS_REGISTRATIONKEEPSALIVE
;
1072 hr
= IRunningObjectTable_Register(pprot
, grflags
, lpEM1
, pmk1
, &pdwReg1
);
1073 ok(hr
==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
1074 hr
, pprot
, grflags
, lpEM1
, pmk1
, pdwReg1
);
1076 trace("IROT::Register\n");
1078 grflags
= grflags
| ROTFLAGS_REGISTRATIONKEEPSALIVE
;
1079 hr
= IRunningObjectTable_Register(pprot
, grflags
, lpEM1
, pmk2
, &pdwReg2
);
1080 ok(hr
==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr
,
1081 pprot
, grflags
, lpEM1
, pmk2
, pdwReg2
);
1083 hr
= IRunningObjectTable_EnumRunning(pprot
, &spEM2
);
1084 ok(hr
==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr
);
1086 matchCnt
= count_moniker_matches(pbc
, spEM2
);
1087 ok(matchCnt
==2, "Number of matches should be equal to 2 not %i\n", matchCnt
);
1089 trace("IEnumMoniker::Clone\n");
1090 IEnumMoniker_Clone(spEM2
, &spEM3
);
1092 matchCnt
= count_moniker_matches(pbc
, spEM3
);
1093 ok(matchCnt
==0, "Number of matches should be equal to 0 not %i\n", matchCnt
);
1094 trace("IEnumMoniker::Reset\n");
1095 IEnumMoniker_Reset(spEM3
);
1097 matchCnt
= count_moniker_matches(pbc
, spEM3
);
1098 ok(matchCnt
==2, "Number of matches should be equal to 2 not %i\n", matchCnt
);
1100 IRunningObjectTable_Revoke(pprot
,pdwReg1
);
1101 IRunningObjectTable_Revoke(pprot
,pdwReg2
);
1102 IUnknown_Release(lpEM1
);
1103 IEnumMoniker_Release(spEM1
);
1104 IEnumMoniker_Release(spEM2
);
1105 IEnumMoniker_Release(spEM3
);
1106 IMoniker_Release(pmk1
);
1107 IMoniker_Release(pmk2
);
1108 IRunningObjectTable_Release(pprot
);
1110 IBindCtx_Release(pbc
);
1113 static const LARGE_INTEGER llZero
;
1115 static const BYTE expected_class_moniker_marshal_data
[] =
1117 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1118 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1119 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1120 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1121 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1122 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1123 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1124 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1125 0x00,0x00,0x00,0x00,
1128 static const BYTE expected_class_moniker_saved_data
[] =
1130 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1131 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1132 0x00,0x00,0x00,0x00,
1135 static const BYTE expected_class_moniker_comparison_data
[] =
1137 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1138 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1139 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1140 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1143 static const WCHAR expected_class_moniker_display_name
[] =
1145 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1146 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1147 '0','0','0','0','4','6',':',0
1150 static const BYTE expected_item_moniker_comparison_data
[] =
1152 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1153 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1154 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1155 0x54,0x00,0x00,0x00,
1158 static const BYTE expected_item_moniker_saved_data
[] =
1160 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1161 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1164 static const BYTE expected_item_moniker_marshal_data
[] =
1166 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1167 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1168 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1169 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1170 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1171 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1172 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1173 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1176 static const BYTE expected_anti_moniker_marshal_data
[] =
1178 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1179 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1180 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1181 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1182 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1183 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1184 0x01,0x00,0x00,0x00,
1187 static const BYTE expected_anti_moniker_saved_data
[] =
1189 0x01,0x00,0x00,0x00,
1192 static const BYTE expected_anti_moniker_comparison_data
[] =
1194 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1195 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1196 0x01,0x00,0x00,0x00,
1199 static const BYTE expected_gc_moniker_marshal_data
[] =
1201 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1202 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1203 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1204 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1205 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1206 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1207 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1208 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1209 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1210 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1211 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1212 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1213 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1214 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1215 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1216 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1217 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1218 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1219 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1220 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1221 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1222 0x00,0x57,0x69,0x6e,0x65,0x00,
1225 static const BYTE expected_gc_moniker_saved_data
[] =
1227 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1228 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1229 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1230 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1231 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1232 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1233 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1234 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1238 static const BYTE expected_gc_moniker_comparison_data
[] =
1240 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1241 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1242 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1243 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1244 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1245 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1246 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1247 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1248 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1251 static void test_moniker(
1252 const char *testname
, IMoniker
*moniker
,
1253 const BYTE
*expected_moniker_marshal_data
, unsigned int sizeof_expected_moniker_marshal_data
,
1254 const BYTE
*expected_moniker_saved_data
, unsigned int sizeof_expected_moniker_saved_data
,
1255 const BYTE
*expected_moniker_comparison_data
, unsigned int sizeof_expected_moniker_comparison_data
,
1256 LPCWSTR expected_display_name
)
1262 LPBYTE moniker_data
;
1267 IMoniker
* moniker_proxy
;
1268 LPOLESTR display_name
;
1271 hr
= IMoniker_IsDirty(moniker
);
1272 ok(hr
== S_FALSE
, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname
, hr
);
1276 hr
= CreateBindCtx(0, &bindctx
);
1277 ok_ole_success(hr
, CreateBindCtx
);
1279 hr
= IMoniker_GetDisplayName(moniker
, bindctx
, NULL
, &display_name
);
1280 ok_ole_success(hr
, IMoniker_GetDisplayName
);
1281 ok(!lstrcmpW(display_name
, expected_display_name
), "%s: display name wasn't what was expected\n", testname
);
1283 CoTaskMemFree(display_name
);
1284 IBindCtx_Release(bindctx
);
1286 hr
= IMoniker_IsDirty(moniker
);
1287 ok(hr
== S_FALSE
, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname
, hr
);
1289 /* IROTData::GetComparisonData test */
1291 hr
= IMoniker_QueryInterface(moniker
, &IID_IROTData
, (void **)&rotdata
);
1292 ok_ole_success(hr
, IMoniker_QueryInterface_IID_IROTData
);
1294 hr
= IROTData_GetComparisonData(rotdata
, buffer
, sizeof(buffer
), &moniker_size
);
1295 ok_ole_success(hr
, IROTData_GetComparisonData
);
1297 if (hr
!= S_OK
) moniker_size
= 0;
1299 /* first check we have the right amount of data */
1300 ok(moniker_size
== sizeof_expected_moniker_comparison_data
,
1301 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1302 testname
, sizeof_expected_moniker_comparison_data
, moniker_size
);
1304 /* then do a byte-by-byte comparison */
1306 for (i
= 0; i
< min(moniker_size
, sizeof_expected_moniker_comparison_data
); i
++)
1308 if (expected_moniker_comparison_data
[i
] != buffer
[i
])
1315 ok(same
, "%s: Comparison data differs\n", testname
);
1318 for (i
= 0; i
< moniker_size
; i
++)
1320 if (i
% 8 == 0) printf(" ");
1321 printf("0x%02x,", buffer
[i
]);
1322 if (i
% 8 == 7) printf("\n");
1327 IROTData_Release(rotdata
);
1329 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1330 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1334 hr
= IMoniker_Save(moniker
, stream
, TRUE
);
1335 ok_ole_success(hr
, IMoniker_Save
);
1337 hr
= GetHGlobalFromStream(stream
, &hglobal
);
1338 ok_ole_success(hr
, GetHGlobalFromStream
);
1340 moniker_size
= GlobalSize(hglobal
);
1342 moniker_data
= GlobalLock(hglobal
);
1344 /* first check we have the right amount of data */
1345 ok(moniker_size
== round_global_size(sizeof_expected_moniker_saved_data
),
1346 "%s: Size of saved data differs (expected %d, actual %d)\n",
1347 testname
, (DWORD
)round_global_size(sizeof_expected_moniker_saved_data
), moniker_size
);
1349 /* then do a byte-by-byte comparison */
1351 for (i
= 0; i
< min(moniker_size
, round_global_size(sizeof_expected_moniker_saved_data
)); i
++)
1353 if (expected_moniker_saved_data
[i
] != moniker_data
[i
])
1360 ok(same
, "%s: Saved data differs\n", testname
);
1363 for (i
= 0; i
< moniker_size
; i
++)
1365 if (i
% 8 == 0) printf(" ");
1366 printf("0x%02x,", moniker_data
[i
]);
1367 if (i
% 8 == 7) printf("\n");
1372 GlobalUnlock(hglobal
);
1374 IStream_Release(stream
);
1376 /* Marshaling tests */
1378 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1379 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1381 hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1382 ok_ole_success(hr
, CoMarshalInterface
);
1384 hr
= GetHGlobalFromStream(stream
, &hglobal
);
1385 ok_ole_success(hr
, GetHGlobalFromStream
);
1387 moniker_size
= GlobalSize(hglobal
);
1389 moniker_data
= GlobalLock(hglobal
);
1391 /* first check we have the right amount of data */
1392 ok(moniker_size
== round_global_size(sizeof_expected_moniker_marshal_data
),
1393 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1394 testname
, (DWORD
)round_global_size(sizeof_expected_moniker_marshal_data
), moniker_size
);
1396 /* then do a byte-by-byte comparison */
1398 if (expected_moniker_marshal_data
)
1400 for (i
= 0; i
< min(moniker_size
, round_global_size(sizeof_expected_moniker_marshal_data
)); i
++)
1402 if (expected_moniker_marshal_data
[i
] != moniker_data
[i
])
1410 ok(same
, "%s: Marshaled data differs\n", testname
);
1413 for (i
= 0; i
< moniker_size
; i
++)
1415 if (i
% 8 == 0) printf(" ");
1416 printf("0x%02x,", moniker_data
[i
]);
1417 if (i
% 8 == 7) printf("\n");
1422 GlobalUnlock(hglobal
);
1424 IStream_Seek(stream
, llZero
, STREAM_SEEK_SET
, NULL
);
1425 hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void **)&moniker_proxy
);
1426 ok_ole_success(hr
, CoUnmarshalInterface
);
1428 IStream_Release(stream
);
1429 IMoniker_Release(moniker_proxy
);
1432 static void test_class_moniker(void)
1443 hr
= CreateClassMoniker(&CLSID_StdComponentCategoriesMgr
, &moniker
);
1444 ok_ole_success(hr
, CreateClassMoniker
);
1445 if (!moniker
) return;
1447 test_moniker("class moniker", moniker
,
1448 expected_class_moniker_marshal_data
, sizeof(expected_class_moniker_marshal_data
),
1449 expected_class_moniker_saved_data
, sizeof(expected_class_moniker_saved_data
),
1450 expected_class_moniker_comparison_data
, sizeof(expected_class_moniker_comparison_data
),
1451 expected_class_moniker_display_name
);
1455 hr
= IMoniker_Hash(moniker
, &hash
);
1456 ok_ole_success(hr
, IMoniker_Hash
);
1458 ok(hash
== CLSID_StdComponentCategoriesMgr
.Data1
,
1459 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1462 /* IsSystemMoniker test */
1464 hr
= IMoniker_IsSystemMoniker(moniker
, &moniker_type
);
1465 ok_ole_success(hr
, IMoniker_IsSystemMoniker
);
1467 ok(moniker_type
== MKSYS_CLASSMONIKER
,
1468 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1471 hr
= CreateBindCtx(0, &bindctx
);
1472 ok_ole_success(hr
, CreateBindCtx
);
1474 /* IsRunning test */
1475 hr
= IMoniker_IsRunning(moniker
, NULL
, NULL
, NULL
);
1476 ok(hr
== E_NOTIMPL
, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr
);
1478 hr
= IMoniker_IsRunning(moniker
, bindctx
, NULL
, NULL
);
1479 ok(hr
== E_NOTIMPL
, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr
);
1481 hr
= IMoniker_GetTimeOfLastChange(moniker
, bindctx
, NULL
, &filetime
);
1482 ok(hr
== MK_E_UNAVAILABLE
, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr
);
1484 hr
= IMoniker_BindToObject(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1485 ok_ole_success(hr
, IMoniker_BindToObject
);
1486 IUnknown_Release(unknown
);
1488 hr
= IMoniker_BindToStorage(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1489 ok_ole_success(hr
, IMoniker_BindToStorage
);
1490 IUnknown_Release(unknown
);
1492 IBindCtx_Release(bindctx
);
1494 hr
= IMoniker_Inverse(moniker
, &inverse
);
1495 ok_ole_success(hr
, IMoniker_Inverse
);
1496 IMoniker_Release(inverse
);
1498 IMoniker_Release(moniker
);
1501 static void test_file_moniker(WCHAR
* path
)
1504 IMoniker
*moniker1
= NULL
, *moniker2
= NULL
;
1507 hr
= CreateFileMoniker(path
, &moniker1
);
1508 ok_ole_success(hr
, CreateFileMoniker
);
1510 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1511 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1514 hr
= CoMarshalInterface(stream
, &IID_IMoniker
, (IUnknown
*)moniker1
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1515 ok_ole_success(hr
, CoMarshalInterface
);
1518 hr
= IStream_Seek(stream
, llZero
, STREAM_SEEK_SET
, NULL
);
1519 ok_ole_success(hr
, IStream_Seek
);
1522 hr
= CoUnmarshalInterface(stream
, &IID_IMoniker
, (void**)&moniker2
);
1523 ok_ole_success(hr
, CoUnmarshalInterface
);
1525 hr
= IMoniker_IsEqual(moniker1
, moniker2
);
1526 ok_ole_success(hr
, IsEqual
);
1528 IStream_Release(stream
);
1530 IMoniker_Release(moniker1
);
1532 IMoniker_Release(moniker2
);
1535 static void test_file_monikers(void)
1537 static WCHAR wszFile
[][30] = {
1538 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1539 {'\\', '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},
1540 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1541 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1542 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1543 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1544 * U+0100 .. = Latin extended-A
1546 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1551 trace("ACP is %u\n", GetACP());
1553 for (i
= 0; i
< ARRAY_SIZE(wszFile
); ++i
)
1559 WideCharToMultiByte( CP_ACP
, WC_NO_BEST_FIT_CHARS
, wszFile
[i
], -1, NULL
, 0, NULL
, &used
);
1562 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1566 for (j
= lstrlenW(wszFile
[i
]); j
> 0; --j
)
1569 test_file_moniker(wszFile
[i
]);
1574 static void test_item_moniker(void)
1583 static const WCHAR wszDelimiter
[] = {'!',0};
1584 static const WCHAR wszObjectName
[] = {'T','e','s','t',0};
1585 static const WCHAR expected_display_name
[] = { '!','T','e','s','t',0 };
1587 hr
= CreateItemMoniker(wszDelimiter
, wszObjectName
, &moniker
);
1588 ok_ole_success(hr
, CreateItemMoniker
);
1590 test_moniker("item moniker", moniker
,
1591 expected_item_moniker_marshal_data
, sizeof(expected_item_moniker_marshal_data
),
1592 expected_item_moniker_saved_data
, sizeof(expected_item_moniker_saved_data
),
1593 expected_item_moniker_comparison_data
, sizeof(expected_item_moniker_comparison_data
),
1594 expected_display_name
);
1598 hr
= IMoniker_Hash(moniker
, &hash
);
1599 ok_ole_success(hr
, IMoniker_Hash
);
1602 "Hash value != 0x73c, instead was 0x%08x\n",
1605 /* IsSystemMoniker test */
1607 hr
= IMoniker_IsSystemMoniker(moniker
, &moniker_type
);
1608 ok_ole_success(hr
, IMoniker_IsSystemMoniker
);
1610 ok(moniker_type
== MKSYS_ITEMMONIKER
,
1611 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1614 hr
= CreateBindCtx(0, &bindctx
);
1615 ok_ole_success(hr
, CreateBindCtx
);
1617 /* IsRunning test */
1618 hr
= IMoniker_IsRunning(moniker
, NULL
, NULL
, NULL
);
1619 ok(hr
== E_INVALIDARG
, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr
);
1621 hr
= IMoniker_IsRunning(moniker
, bindctx
, NULL
, NULL
);
1622 ok(hr
== S_FALSE
, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr
);
1624 hr
= IMoniker_BindToObject(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1625 ok(hr
== E_INVALIDARG
, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr
);
1627 hr
= IMoniker_BindToStorage(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1628 ok(hr
== E_INVALIDARG
, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr
);
1630 IBindCtx_Release(bindctx
);
1632 hr
= IMoniker_Inverse(moniker
, &inverse
);
1633 ok_ole_success(hr
, IMoniker_Inverse
);
1634 IMoniker_Release(inverse
);
1636 IMoniker_Release(moniker
);
1639 static void test_anti_moniker(void)
1649 static const WCHAR expected_display_name
[] = { '\\','.','.',0 };
1651 hr
= CreateAntiMoniker(&moniker
);
1652 ok_ole_success(hr
, CreateAntiMoniker
);
1653 if (!moniker
) return;
1655 test_moniker("anti moniker", moniker
,
1656 expected_anti_moniker_marshal_data
, sizeof(expected_anti_moniker_marshal_data
),
1657 expected_anti_moniker_saved_data
, sizeof(expected_anti_moniker_saved_data
),
1658 expected_anti_moniker_comparison_data
, sizeof(expected_anti_moniker_comparison_data
),
1659 expected_display_name
);
1662 hr
= IMoniker_Hash(moniker
, &hash
);
1663 ok_ole_success(hr
, IMoniker_Hash
);
1664 ok(hash
== 0x80000001,
1665 "Hash value != 0x80000001, instead was 0x%08x\n",
1668 /* IsSystemMoniker test */
1669 hr
= IMoniker_IsSystemMoniker(moniker
, &moniker_type
);
1670 ok_ole_success(hr
, IMoniker_IsSystemMoniker
);
1671 ok(moniker_type
== MKSYS_ANTIMONIKER
,
1672 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1675 hr
= IMoniker_Inverse(moniker
, &inverse
);
1676 ok(hr
== MK_E_NOINVERSE
, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr
);
1677 ok(inverse
== NULL
, "inverse should have been set to NULL instead of %p\n", inverse
);
1679 hr
= CreateBindCtx(0, &bindctx
);
1680 ok_ole_success(hr
, CreateBindCtx
);
1682 /* IsRunning test */
1683 hr
= IMoniker_IsRunning(moniker
, bindctx
, NULL
, NULL
);
1684 ok(hr
== S_FALSE
, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr
);
1686 hr
= IMoniker_GetTimeOfLastChange(moniker
, bindctx
, NULL
, &filetime
);
1687 ok(hr
== E_NOTIMPL
, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr
);
1689 hr
= IMoniker_BindToObject(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1690 ok(hr
== E_NOTIMPL
, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr
);
1692 hr
= IMoniker_BindToStorage(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1693 ok(hr
== E_NOTIMPL
, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr
);
1695 IBindCtx_Release(bindctx
);
1697 IMoniker_Release(moniker
);
1700 static void test_generic_composite_moniker(void)
1712 static const WCHAR wszDelimiter1
[] = {'!',0};
1713 static const WCHAR wszObjectName1
[] = {'T','e','s','t',0};
1714 static const WCHAR wszDelimiter2
[] = {'#',0};
1715 static const WCHAR wszObjectName2
[] = {'W','i','n','e',0};
1716 static const WCHAR expected_display_name
[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1718 hr
= CreateItemMoniker(wszDelimiter1
, wszObjectName1
, &moniker1
);
1719 ok_ole_success(hr
, CreateItemMoniker
);
1720 hr
= CreateItemMoniker(wszDelimiter2
, wszObjectName2
, &moniker2
);
1721 ok_ole_success(hr
, CreateItemMoniker
);
1722 hr
= CreateGenericComposite(moniker1
, moniker2
, &moniker
);
1723 ok_ole_success(hr
, CreateGenericComposite
);
1725 test_moniker("generic composite moniker", moniker
,
1726 expected_gc_moniker_marshal_data
, sizeof(expected_gc_moniker_marshal_data
),
1727 expected_gc_moniker_saved_data
, sizeof(expected_gc_moniker_saved_data
),
1728 expected_gc_moniker_comparison_data
, sizeof(expected_gc_moniker_comparison_data
),
1729 expected_display_name
);
1733 hr
= IMoniker_Hash(moniker
, &hash
);
1734 ok_ole_success(hr
, IMoniker_Hash
);
1737 "Hash value != 0xd87, instead was 0x%08x\n",
1740 /* IsSystemMoniker test */
1742 hr
= IMoniker_IsSystemMoniker(moniker
, &moniker_type
);
1743 ok_ole_success(hr
, IMoniker_IsSystemMoniker
);
1745 ok(moniker_type
== MKSYS_GENERICCOMPOSITE
,
1746 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1749 hr
= CreateBindCtx(0, &bindctx
);
1750 ok_ole_success(hr
, CreateBindCtx
);
1752 /* IsRunning test */
1753 hr
= IMoniker_IsRunning(moniker
, NULL
, NULL
, NULL
);
1754 ok(hr
== E_INVALIDARG
, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr
);
1756 hr
= IMoniker_IsRunning(moniker
, bindctx
, NULL
, NULL
);
1758 ok(hr
== S_FALSE
, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr
);
1760 hr
= IMoniker_GetTimeOfLastChange(moniker
, bindctx
, NULL
, &filetime
);
1761 ok(hr
== MK_E_NOTBINDABLE
, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr
);
1763 hr
= IMoniker_BindToObject(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1765 ok(hr
== E_INVALIDARG
, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr
);
1767 hr
= IMoniker_BindToStorage(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1768 ok(hr
== E_INVALIDARG
, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr
);
1770 IBindCtx_Release(bindctx
);
1772 hr
= IMoniker_Inverse(moniker
, &inverse
);
1773 ok_ole_success(hr
, IMoniker_Inverse
);
1774 IMoniker_Release(inverse
);
1776 IMoniker_Release(moniker
);
1779 static void test_pointer_moniker(void)
1791 LPOLESTR display_name
;
1795 hr
= CreatePointerMoniker((IUnknown
*)&Test_ClassFactory
, NULL
);
1796 ok(hr
== E_INVALIDARG
, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1798 hr
= CreatePointerMoniker((IUnknown
*)&Test_ClassFactory
, &moniker
);
1799 ok_ole_success(hr
, CreatePointerMoniker
);
1800 if (!moniker
) return;
1802 ok_more_than_one_lock();
1806 hr
= CreateBindCtx(0, &bindctx
);
1807 ok_ole_success(hr
, CreateBindCtx
);
1809 hr
= IMoniker_GetDisplayName(moniker
, bindctx
, NULL
, &display_name
);
1810 ok(hr
== E_NOTIMPL
, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr
);
1812 IBindCtx_Release(bindctx
);
1814 hr
= IMoniker_IsDirty(moniker
);
1815 ok(hr
== S_FALSE
, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr
);
1817 /* IROTData::GetComparisonData test */
1819 hr
= IMoniker_QueryInterface(moniker
, &IID_IROTData
, (void **)&rotdata
);
1820 ok(hr
== E_NOINTERFACE
, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
1824 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1825 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1827 hr
= IMoniker_Save(moniker
, stream
, TRUE
);
1828 ok(hr
== E_NOTIMPL
, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr
);
1830 IStream_Release(stream
);
1833 hr
= IMoniker_Hash(moniker
, &hash
);
1834 ok_ole_success(hr
, IMoniker_Hash
);
1835 ok(hash
== PtrToUlong(&Test_ClassFactory
),
1836 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1837 PtrToUlong(&Test_ClassFactory
), hash
);
1839 /* IsSystemMoniker test */
1840 hr
= IMoniker_IsSystemMoniker(moniker
, &moniker_type
);
1841 ok_ole_success(hr
, IMoniker_IsSystemMoniker
);
1842 ok(moniker_type
== MKSYS_POINTERMONIKER
,
1843 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1846 hr
= IMoniker_Inverse(moniker
, &inverse
);
1847 ok_ole_success(hr
, IMoniker_Inverse
);
1848 IMoniker_Release(inverse
);
1850 hr
= CreateBindCtx(0, &bindctx
);
1851 ok_ole_success(hr
, CreateBindCtx
);
1853 /* IsRunning test */
1854 hr
= IMoniker_IsRunning(moniker
, bindctx
, NULL
, NULL
);
1855 ok(hr
== S_OK
, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr
);
1857 hr
= IMoniker_GetTimeOfLastChange(moniker
, bindctx
, NULL
, &filetime
);
1858 ok(hr
== E_NOTIMPL
, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr
);
1860 hr
= IMoniker_BindToObject(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1861 ok_ole_success(hr
, IMoniker_BindToObject
);
1862 IUnknown_Release(unknown
);
1864 hr
= IMoniker_BindToStorage(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1865 ok_ole_success(hr
, IMoniker_BindToStorage
);
1866 IUnknown_Release(unknown
);
1868 IMoniker_Release(moniker
);
1872 hr
= CreatePointerMoniker(NULL
, &moniker
);
1873 ok_ole_success(hr
, CreatePointerMoniker
);
1875 hr
= IMoniker_BindToObject(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1876 ok(hr
== E_UNEXPECTED
, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr
);
1878 hr
= IMoniker_BindToStorage(moniker
, bindctx
, NULL
, &IID_IUnknown
, (void **)&unknown
);
1879 ok(hr
== E_UNEXPECTED
, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr
);
1881 IBindCtx_Release(bindctx
);
1883 IMoniker_Release(moniker
);
1886 static void test_bind_context(void)
1890 IEnumString
*pEnumString
;
1891 BIND_OPTS2 bind_opts
;
1892 HeapUnknown
*unknown
;
1893 HeapUnknown
*unknown2
;
1894 IUnknown
*param_obj
;
1896 static const WCHAR wszParamName
[] = {'G','e','m','m','a',0};
1897 static const WCHAR wszNonExistent
[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1899 hr
= CreateBindCtx(0, NULL
);
1900 ok(hr
== E_INVALIDARG
, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1902 hr
= CreateBindCtx(0xdeadbeef, &pBindCtx
);
1903 ok(hr
== E_INVALIDARG
, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1905 hr
= CreateBindCtx(0, &pBindCtx
);
1906 ok_ole_success(hr
, "CreateBindCtx");
1908 bind_opts
.cbStruct
= -1;
1909 hr
= IBindCtx_GetBindOptions(pBindCtx
, (BIND_OPTS
*)&bind_opts
);
1910 ok_ole_success(hr
, "IBindCtx_GetBindOptions");
1911 ok(bind_opts
.cbStruct
== sizeof(bind_opts
) ||
1912 bind_opts
.cbStruct
== sizeof(bind_opts
) + sizeof(void*), /* Vista */
1913 "bind_opts.cbStruct was %d\n", bind_opts
.cbStruct
);
1915 bind_opts
.cbStruct
= sizeof(BIND_OPTS
);
1916 hr
= IBindCtx_GetBindOptions(pBindCtx
, (BIND_OPTS
*)&bind_opts
);
1917 ok_ole_success(hr
, "IBindCtx_GetBindOptions");
1918 ok(bind_opts
.cbStruct
== sizeof(BIND_OPTS
), "bind_opts.cbStruct was %d\n", bind_opts
.cbStruct
);
1920 bind_opts
.cbStruct
= sizeof(bind_opts
);
1921 hr
= IBindCtx_GetBindOptions(pBindCtx
, (BIND_OPTS
*)&bind_opts
);
1922 ok_ole_success(hr
, "IBindCtx_GetBindOptions");
1923 ok(bind_opts
.cbStruct
== sizeof(bind_opts
), "bind_opts.cbStruct was %d\n", bind_opts
.cbStruct
);
1924 ok(bind_opts
.grfFlags
== 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts
.grfFlags
);
1925 ok(bind_opts
.grfMode
== STGM_READWRITE
, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts
.grfMode
);
1926 ok(bind_opts
.dwTickCountDeadline
== 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts
.dwTickCountDeadline
);
1927 ok(bind_opts
.dwTrackFlags
== 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts
.dwTrackFlags
);
1928 ok(bind_opts
.dwClassContext
== (CLSCTX_INPROC_SERVER
|CLSCTX_LOCAL_SERVER
|CLSCTX_REMOTE_SERVER
),
1929 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts
.dwClassContext
);
1930 ok(bind_opts
.locale
== GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts
.locale
);
1931 ok(bind_opts
.pServerInfo
== NULL
, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts
.pServerInfo
);
1933 bind_opts
.cbStruct
= -1;
1934 hr
= IBindCtx_SetBindOptions(pBindCtx
, (BIND_OPTS
*)&bind_opts
);
1935 ok(hr
== E_INVALIDARG
, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1937 hr
= IBindCtx_RegisterObjectParam(pBindCtx
, (WCHAR
*)wszParamName
, NULL
);
1938 ok(hr
== E_INVALIDARG
, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
1940 unknown
= HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown
));
1941 unknown
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
1943 hr
= IBindCtx_RegisterObjectParam(pBindCtx
, (WCHAR
*)wszParamName
, &unknown
->IUnknown_iface
);
1944 ok_ole_success(hr
, "IBindCtx_RegisterObjectParam");
1946 hr
= IBindCtx_GetObjectParam(pBindCtx
, (WCHAR
*)wszParamName
, ¶m_obj
);
1947 ok_ole_success(hr
, "IBindCtx_GetObjectParam");
1948 IUnknown_Release(param_obj
);
1950 hr
= IBindCtx_GetObjectParam(pBindCtx
, (WCHAR
*)wszNonExistent
, ¶m_obj
);
1951 ok(hr
== E_FAIL
, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr
);
1952 ok(param_obj
== NULL
, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj
);
1954 hr
= IBindCtx_RevokeObjectParam(pBindCtx
, (WCHAR
*)wszNonExistent
);
1955 ok(hr
== E_FAIL
, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr
);
1957 hr
= IBindCtx_EnumObjectParam(pBindCtx
, &pEnumString
);
1958 ok(hr
== E_NOTIMPL
, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr
);
1959 ok(!pEnumString
, "pEnumString should be NULL\n");
1961 hr
= IBindCtx_RegisterObjectBound(pBindCtx
, NULL
);
1962 ok_ole_success(hr
, "IBindCtx_RegisterObjectBound(NULL)");
1964 hr
= IBindCtx_RevokeObjectBound(pBindCtx
, NULL
);
1965 ok(hr
== E_INVALIDARG
, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr
);
1967 unknown2
= HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown
));
1968 unknown2
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
1970 hr
= IBindCtx_RegisterObjectBound(pBindCtx
, &unknown2
->IUnknown_iface
);
1971 ok_ole_success(hr
, "IBindCtx_RegisterObjectBound");
1973 hr
= IBindCtx_RevokeObjectBound(pBindCtx
, &unknown2
->IUnknown_iface
);
1974 ok_ole_success(hr
, "IBindCtx_RevokeObjectBound");
1976 hr
= IBindCtx_RevokeObjectBound(pBindCtx
, &unknown2
->IUnknown_iface
);
1977 ok(hr
== MK_E_NOTBOUND
, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr
);
1979 IBindCtx_Release(pBindCtx
);
1981 refs
= IUnknown_Release(&unknown
->IUnknown_iface
);
1982 ok(!refs
, "object param should have been destroyed, instead of having %d refs\n", refs
);
1984 refs
= IUnknown_Release(&unknown2
->IUnknown_iface
);
1985 ok(!refs
, "bound object should have been destroyed, instead of having %d refs\n", refs
);
1988 static void test_save_load_filemoniker(void)
1993 ULARGE_INTEGER size
;
1994 LARGE_INTEGER zero_pos
, dead_pos
, nulls_pos
;
1995 DWORD some_val
= 0xFEDCBA98;
1998 /* see FileMonikerImpl_Save docs */
1999 zero_pos
.QuadPart
= 0;
2000 dead_pos
.QuadPart
= sizeof(WORD
) + sizeof(DWORD
) + (lstrlenW(wszFileName1
) + 1) + sizeof(WORD
);
2001 nulls_pos
.QuadPart
= dead_pos
.QuadPart
+ sizeof(WORD
);
2003 /* create the stream we're going to write to */
2004 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStm
);
2005 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2007 size
.u
.LowPart
= 128;
2008 hr
= IStream_SetSize(pStm
, size
);
2009 ok_ole_success(hr
, "IStream_SetSize");
2011 /* create and save a moniker */
2012 hr
= CreateFileMoniker(wszFileName1
, &pMk
);
2013 ok_ole_success(hr
, "CreateFileMoniker");
2015 hr
= IMoniker_Save(pMk
, pStm
, TRUE
);
2016 ok_ole_success(hr
, "IMoniker_Save");
2017 IMoniker_Release(pMk
);
2019 /* overwrite the constants with various values */
2020 hr
= IStream_Seek(pStm
, zero_pos
, STREAM_SEEK_SET
, NULL
);
2021 ok_ole_success(hr
, "IStream_Seek");
2022 hr
= IStream_Write(pStm
, &some_val
, sizeof(WORD
), NULL
);
2023 ok_ole_success(hr
, "IStream_Write");
2025 hr
= IStream_Seek(pStm
, dead_pos
, STREAM_SEEK_SET
, NULL
);
2026 ok_ole_success(hr
, "IStream_Seek");
2027 hr
= IStream_Write(pStm
, &some_val
, sizeof(WORD
), NULL
);
2028 ok_ole_success(hr
, "IStream_Write");
2030 hr
= IStream_Seek(pStm
, nulls_pos
, STREAM_SEEK_SET
, NULL
);
2031 ok_ole_success(hr
, "IStream_Seek");
2032 for(i
= 0; i
< 5; ++i
){
2033 hr
= IStream_Write(pStm
, &some_val
, sizeof(DWORD
), NULL
);
2034 ok_ole_success(hr
, "IStream_Write");
2037 /* go back to the start of the stream */
2038 hr
= IStream_Seek(pStm
, zero_pos
, STREAM_SEEK_SET
, NULL
);
2039 ok_ole_success(hr
, "IStream_Seek");
2041 /* create a new moniker and load into it */
2042 hr
= CreateFileMoniker(wszFileName1
, &pMk
);
2043 ok_ole_success(hr
, "CreateFileMoniker");
2045 hr
= IMoniker_Load(pMk
, pStm
);
2046 ok_ole_success(hr
, "IMoniker_Load");
2048 IMoniker_Release(pMk
);
2049 IStream_Release(pStm
);
2054 if (!GetProcAddress(GetModuleHandleA("ole32.dll"), "CoRegisterSurrogateEx")) {
2055 win_skip("skipping test on win9x\n");
2059 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2062 test_ROT_multiple_entries();
2063 test_MkParseDisplayName();
2064 test_class_moniker();
2065 test_file_monikers();
2066 test_item_moniker();
2067 test_anti_moniker();
2068 test_generic_composite_moniker();
2069 test_pointer_moniker();
2070 test_save_load_filemoniker();
2072 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2074 test_bind_context();