[OLE32_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / ole32 / moniker.c
1 /*
2 * Moniker Tests
3 *
4 * Copyright 2004 Robert Shearman
5 *
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.
10 *
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.
15 *
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
19 */
20
21 #define WIN32_NO_STATUS
22 #define _INC_WINDOWS
23 #define COM_NO_WINDOWS_H
24
25 #define _WIN32_DCOM
26 #define COBJMACROS
27 #define CONST_VTABLE
28
29 //#include <stdarg.h>
30 #include <stdio.h>
31
32 #include <windef.h>
33 #include <winbase.h>
34 #include <winnls.h>
35 #include <ole2.h>
36 //#include "objbase.h"
37 //#include "ocidl.h"
38 //#include "initguid.h"
39 #include <comcat.h>
40 #include <olectl.h>
41
42 #include <wine/test.h>
43
44 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
45 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
46 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
47 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
48
49 #define CHECK_EXPECTED_METHOD(method_name) \
50 do { \
51 trace("%s\n", method_name); \
52 ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
53 if (*expected_method_list) \
54 { \
55 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
56 *expected_method_list, method_name); \
57 expected_method_list++; \
58 } \
59 } while(0)
60
61 static char const * const *expected_method_list;
62 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
63 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
64
65 static const CLSID CLSID_TestMoniker =
66 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
67 0xb306bfbc,
68 0x496e,
69 0x4f53,
70 {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
71 };
72
73 static LONG cLocks;
74
75 static void LockModule(void)
76 {
77 InterlockedIncrement(&cLocks);
78 }
79
80 static void UnlockModule(void)
81 {
82 InterlockedDecrement(&cLocks);
83 }
84
85 static SIZE_T round_global_size(SIZE_T size)
86 {
87 static SIZE_T global_size_alignment = -1;
88 if (global_size_alignment == -1)
89 {
90 void *p = GlobalAlloc(GMEM_FIXED, 1);
91 global_size_alignment = GlobalSize(p);
92 GlobalFree(p);
93 }
94
95 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
96 }
97
98 static DWORD external_connections;
99
100 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
101 {
102 ok(0, "unexpected call\n");
103 *ppv = NULL;
104 return E_NOINTERFACE;
105 }
106
107 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
108 {
109 return 2;
110 }
111
112 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
113 {
114 return 1;
115 }
116
117 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
118 {
119 trace("add connection\n");
120
121 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
122 ok(!reserved, "reserved = %x\n", reserved);
123 return ++external_connections;
124 }
125
126 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
127 DWORD reserved, BOOL fLastReleaseCloses)
128 {
129 trace("release connection\n");
130
131 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
132 ok(!reserved, "reserved = %x\n", reserved);
133
134 return --external_connections;
135 }
136
137 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
138 ExternalConnection_QueryInterface,
139 ExternalConnection_AddRef,
140 ExternalConnection_Release,
141 ExternalConnection_AddConnection,
142 ExternalConnection_ReleaseConnection
143 };
144
145 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
146
147 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
148 LPCLASSFACTORY iface,
149 REFIID riid,
150 LPVOID *ppvObj)
151 {
152 if (ppvObj == NULL) return E_POINTER;
153
154 if (IsEqualGUID(riid, &IID_IUnknown) ||
155 IsEqualGUID(riid, &IID_IClassFactory))
156 {
157 *ppvObj = iface;
158 IClassFactory_AddRef(iface);
159 return S_OK;
160 }
161
162 if(IsEqualGUID(riid, &IID_IExternalConnection)) {
163 *ppvObj = &ExternalConnection;
164 return S_OK;
165 }
166
167 *ppvObj = NULL;
168 return E_NOINTERFACE;
169 }
170
171 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
172 {
173 LockModule();
174 return 2; /* non-heap-based object */
175 }
176
177 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
178 {
179 UnlockModule();
180 return 1; /* non-heap-based object */
181 }
182
183 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
184 LPCLASSFACTORY iface,
185 LPUNKNOWN pUnkOuter,
186 REFIID riid,
187 LPVOID *ppvObj)
188 {
189 return E_NOTIMPL;
190 }
191
192 static HRESULT WINAPI Test_IClassFactory_LockServer(
193 LPCLASSFACTORY iface,
194 BOOL fLock)
195 {
196 return S_OK;
197 }
198
199 static const IClassFactoryVtbl TestClassFactory_Vtbl =
200 {
201 Test_IClassFactory_QueryInterface,
202 Test_IClassFactory_AddRef,
203 Test_IClassFactory_Release,
204 Test_IClassFactory_CreateInstance,
205 Test_IClassFactory_LockServer
206 };
207
208 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
209
210 typedef struct
211 {
212 IUnknown IUnknown_iface;
213 ULONG refs;
214 } HeapUnknown;
215
216 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
217 {
218 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
219 }
220
221 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
222 {
223 if (IsEqualIID(riid, &IID_IUnknown))
224 {
225 IUnknown_AddRef(iface);
226 *ppv = iface;
227 return S_OK;
228 }
229 *ppv = NULL;
230 return E_NOINTERFACE;
231 }
232
233 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
234 {
235 HeapUnknown *This = impl_from_IUnknown(iface);
236 return InterlockedIncrement((LONG*)&This->refs);
237 }
238
239 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
240 {
241 HeapUnknown *This = impl_from_IUnknown(iface);
242 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
243 if (!refs) HeapFree(GetProcessHeap(), 0, This);
244 return refs;
245 }
246
247 static const IUnknownVtbl HeapUnknown_Vtbl =
248 {
249 HeapUnknown_QueryInterface,
250 HeapUnknown_AddRef,
251 HeapUnknown_Release
252 };
253
254 static HRESULT WINAPI
255 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
256 {
257 if (!ppvObject)
258 return E_INVALIDARG;
259
260 *ppvObject = 0;
261
262 if (IsEqualIID(&IID_IUnknown, riid) ||
263 IsEqualIID(&IID_IPersist, riid) ||
264 IsEqualIID(&IID_IPersistStream,riid) ||
265 IsEqualIID(&IID_IMoniker, riid))
266 *ppvObject = iface;
267 if (IsEqualIID(&IID_IROTData, riid))
268 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
269
270 if ((*ppvObject)==0)
271 return E_NOINTERFACE;
272
273 IMoniker_AddRef(iface);
274
275 return S_OK;
276 }
277
278 static ULONG WINAPI
279 Moniker_AddRef(IMoniker* iface)
280 {
281 return 2;
282 }
283
284 static ULONG WINAPI
285 Moniker_Release(IMoniker* iface)
286 {
287 return 1;
288 }
289
290 static HRESULT WINAPI
291 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
292 {
293 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
294
295 *pClassID = CLSID_TestMoniker;
296
297 return S_OK;
298 }
299
300 static HRESULT WINAPI
301 Moniker_IsDirty(IMoniker* iface)
302 {
303 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
304
305 return S_FALSE;
306 }
307
308 static HRESULT WINAPI
309 Moniker_Load(IMoniker* iface, IStream* pStm)
310 {
311 CHECK_EXPECTED_METHOD("Moniker_Load");
312 return E_NOTIMPL;
313 }
314
315 static HRESULT WINAPI
316 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
317 {
318 CHECK_EXPECTED_METHOD("Moniker_Save");
319 return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI
323 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
324 {
325 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
326 return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI
330 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
331 REFIID riid, VOID** ppvResult)
332 {
333 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
334 return E_NOTIMPL;
335 }
336
337 static HRESULT WINAPI
338 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
339 REFIID riid, VOID** ppvObject)
340 {
341 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
342 return E_NOTIMPL;
343 }
344
345 static HRESULT WINAPI
346 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
347 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
348 {
349 CHECK_EXPECTED_METHOD("Moniker_Reduce");
350
351 if (ppmkReduced==NULL)
352 return E_POINTER;
353
354 IMoniker_AddRef(iface);
355
356 *ppmkReduced=iface;
357
358 return MK_S_REDUCED_TO_SELF;
359 }
360
361 static HRESULT WINAPI
362 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
363 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
364 {
365 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
366 return E_NOTIMPL;
367 }
368
369 static HRESULT WINAPI
370 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
371 {
372 CHECK_EXPECTED_METHOD("Moniker_Enum");
373
374 if (ppenumMoniker == NULL)
375 return E_POINTER;
376
377 *ppenumMoniker = NULL;
378
379 return S_OK;
380 }
381
382 static HRESULT WINAPI
383 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
384 {
385 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
386 return E_NOTIMPL;
387 }
388
389 static HRESULT WINAPI
390 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
391 {
392 CHECK_EXPECTED_METHOD("Moniker_Hash");
393 return E_NOTIMPL;
394 }
395
396 static HRESULT WINAPI
397 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
398 IMoniker* pmkNewlyRunning)
399 {
400 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
401 return E_NOTIMPL;
402 }
403
404 static HRESULT WINAPI
405 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
406 IMoniker* pmkToLeft, FILETIME* pFileTime)
407 {
408 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
409 return E_NOTIMPL;
410 }
411
412 static HRESULT WINAPI
413 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
414 {
415 CHECK_EXPECTED_METHOD("Moniker_Inverse");
416 return E_NOTIMPL;
417 }
418
419 static HRESULT WINAPI
420 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
421 {
422 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
423 return E_NOTIMPL;
424 }
425
426 static HRESULT WINAPI
427 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
428 {
429 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
430 return E_NOTIMPL;
431 }
432
433 static HRESULT WINAPI
434 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
435 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
436 {
437 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
438 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
439 *ppszDisplayName = CoTaskMemAlloc(sizeof(wszDisplayName));
440 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
441 return S_OK;
442 }
443
444 static HRESULT WINAPI
445 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
446 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
447 {
448 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
449 return E_NOTIMPL;
450 }
451
452 static HRESULT WINAPI
453 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
454 {
455 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
456
457 if (!pwdMksys)
458 return E_POINTER;
459
460 (*pwdMksys)=MKSYS_NONE;
461
462 return S_FALSE;
463 }
464
465 static const IMonikerVtbl MonikerNoROTDataVtbl =
466 {
467 MonikerNoROTData_QueryInterface,
468 Moniker_AddRef,
469 Moniker_Release,
470 Moniker_GetClassID,
471 Moniker_IsDirty,
472 Moniker_Load,
473 Moniker_Save,
474 Moniker_GetSizeMax,
475 Moniker_BindToObject,
476 Moniker_BindToStorage,
477 Moniker_Reduce,
478 Moniker_ComposeWith,
479 Moniker_Enum,
480 Moniker_IsEqual,
481 Moniker_Hash,
482 Moniker_IsRunning,
483 Moniker_GetTimeOfLastChange,
484 Moniker_Inverse,
485 Moniker_CommonPrefixWith,
486 Moniker_RelativePathTo,
487 Moniker_GetDisplayName,
488 Moniker_ParseDisplayName,
489 Moniker_IsSystemMoniker
490 };
491
492 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
493
494 static IMoniker Moniker;
495
496 static HRESULT WINAPI
497 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
498 {
499 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
500 }
501
502 static ULONG WINAPI
503 ROTData_AddRef(IROTData *iface)
504 {
505 return 2;
506 }
507
508 static ULONG WINAPI
509 ROTData_Release(IROTData* iface)
510 {
511 return 1;
512 }
513
514 static HRESULT WINAPI
515 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
516 ULONG cbMax, ULONG* pcbData)
517 {
518 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
519
520 *pcbData = 1;
521 if (cbMax < *pcbData)
522 return E_OUTOFMEMORY;
523
524 *pbData = 0xde;
525
526 return S_OK;
527 }
528
529 static IROTDataVtbl ROTDataVtbl =
530 {
531 ROTData_QueryInterface,
532 ROTData_AddRef,
533 ROTData_Release,
534 ROTData_GetComparisonData
535 };
536
537 static IROTData ROTData = { &ROTDataVtbl };
538
539 static HRESULT WINAPI
540 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
541 {
542 if (!ppvObject)
543 return E_INVALIDARG;
544
545 *ppvObject = 0;
546
547 if (IsEqualIID(&IID_IUnknown, riid) ||
548 IsEqualIID(&IID_IPersist, riid) ||
549 IsEqualIID(&IID_IPersistStream,riid) ||
550 IsEqualIID(&IID_IMoniker, riid))
551 *ppvObject = iface;
552 if (IsEqualIID(&IID_IROTData, riid))
553 {
554 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
555 *ppvObject = &ROTData;
556 }
557
558 if ((*ppvObject)==0)
559 return E_NOINTERFACE;
560
561 IMoniker_AddRef(iface);
562
563 return S_OK;
564 }
565
566 static const IMonikerVtbl MonikerVtbl =
567 {
568 Moniker_QueryInterface,
569 Moniker_AddRef,
570 Moniker_Release,
571 Moniker_GetClassID,
572 Moniker_IsDirty,
573 Moniker_Load,
574 Moniker_Save,
575 Moniker_GetSizeMax,
576 Moniker_BindToObject,
577 Moniker_BindToStorage,
578 Moniker_Reduce,
579 Moniker_ComposeWith,
580 Moniker_Enum,
581 Moniker_IsEqual,
582 Moniker_Hash,
583 Moniker_IsRunning,
584 Moniker_GetTimeOfLastChange,
585 Moniker_Inverse,
586 Moniker_CommonPrefixWith,
587 Moniker_RelativePathTo,
588 Moniker_GetDisplayName,
589 Moniker_ParseDisplayName,
590 Moniker_IsSystemMoniker
591 };
592
593 static IMoniker Moniker = { &MonikerVtbl };
594
595 static void test_ROT(void)
596 {
597 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
598 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
599 '2','0','4','6','E','5','8','6','C','9','2','5',0};
600 HRESULT hr;
601 IMoniker *pMoniker = NULL;
602 IRunningObjectTable *pROT = NULL;
603 DWORD dwCookie;
604 static const char *methods_register_no_ROTData[] =
605 {
606 "Moniker_Reduce",
607 "Moniker_GetTimeOfLastChange",
608 "Moniker_QueryInterface(IID_IROTData)",
609 "Moniker_GetDisplayName",
610 "Moniker_GetClassID",
611 NULL
612 };
613 static const char *methods_register[] =
614 {
615 "Moniker_Reduce",
616 "Moniker_GetTimeOfLastChange",
617 "Moniker_QueryInterface(IID_IROTData)",
618 "ROTData_GetComparisonData",
619 NULL
620 };
621 static const char *methods_isrunning_no_ROTData[] =
622 {
623 "Moniker_Reduce",
624 "Moniker_QueryInterface(IID_IROTData)",
625 "Moniker_GetDisplayName",
626 "Moniker_GetClassID",
627 NULL
628 };
629 static const char *methods_isrunning[] =
630 {
631 "Moniker_Reduce",
632 "Moniker_QueryInterface(IID_IROTData)",
633 "ROTData_GetComparisonData",
634 NULL
635 };
636
637 cLocks = 0;
638
639 hr = GetRunningObjectTable(0, &pROT);
640 ok_ole_success(hr, GetRunningObjectTable);
641
642 expected_method_list = methods_register_no_ROTData;
643 external_connections = 0;
644 /* try with our own moniker that doesn't support IROTData */
645 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
646 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
647 ok_ole_success(hr, IRunningObjectTable_Register);
648 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
649 ok(external_connections == 1, "external_connections = %d\n", external_connections);
650
651 ok_more_than_one_lock();
652
653 expected_method_list = methods_isrunning_no_ROTData;
654 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
655 ok_ole_success(hr, IRunningObjectTable_IsRunning);
656 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
657
658 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
659 ok_ole_success(hr, IRunningObjectTable_Revoke);
660 ok(external_connections == 0, "external_connections = %d\n", external_connections);
661
662 ok_no_locks();
663
664 expected_method_list = methods_register;
665 /* try with our own moniker */
666 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
667 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
668 ok_ole_success(hr, IRunningObjectTable_Register);
669 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
670
671 ok_more_than_one_lock();
672
673 expected_method_list = methods_isrunning;
674 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
675 ok_ole_success(hr, IRunningObjectTable_IsRunning);
676 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
677
678 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
679 ok_ole_success(hr, IRunningObjectTable_Revoke);
680
681 ok_no_locks();
682
683 hr = CreateFileMoniker(wszFileName, &pMoniker);
684 ok_ole_success(hr, CreateClassMoniker);
685
686 /* test flags: 0 */
687 external_connections = 0;
688 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
689 pMoniker, &dwCookie);
690 ok_ole_success(hr, IRunningObjectTable_Register);
691 ok(external_connections == 0, "external_connections = %d\n", external_connections);
692
693 ok_more_than_one_lock();
694
695 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
696 ok_ole_success(hr, IRunningObjectTable_Revoke);
697
698 ok_no_locks();
699
700 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
701 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
702 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
703 ok_ole_success(hr, IRunningObjectTable_Register);
704
705 ok_more_than_one_lock();
706
707 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
708 ok_ole_success(hr, IRunningObjectTable_Revoke);
709
710 ok_no_locks();
711
712 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
713 /* only succeeds when process is started by SCM and has LocalService
714 * or RunAs AppId values */
715 hr = IRunningObjectTable_Register(pROT,
716 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
717 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
718 todo_wine {
719 ok(hr == CO_E_WRONG_SERVER_IDENTITY ||
720 broken(hr == S_OK) /* Win9x */,
721 "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
722 }
723 if (hr == S_OK) IRunningObjectTable_Revoke(pROT, dwCookie);
724
725 hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
726 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
727 ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
728
729 IMoniker_Release(pMoniker);
730
731 IRunningObjectTable_Release(pROT);
732 }
733
734 static void test_ROT_multiple_entries(void)
735 {
736 HRESULT hr;
737 IMoniker *pMoniker = NULL;
738 IRunningObjectTable *pROT = NULL;
739 DWORD dwCookie1, dwCookie2;
740 IUnknown *pObject = NULL;
741 static const WCHAR moniker_path[] =
742 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0};
743
744 hr = GetRunningObjectTable(0, &pROT);
745 ok_ole_success(hr, GetRunningObjectTable);
746
747 hr = CreateFileMoniker(moniker_path, &pMoniker);
748 ok_ole_success(hr, CreateFileMoniker);
749
750 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie1);
751 ok_ole_success(hr, IRunningObjectTable_Register);
752
753 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown *)&Test_ClassFactory, pMoniker, &dwCookie2);
754 ok(hr == MK_S_MONIKERALREADYREGISTERED, "IRunningObjectTable_Register should have returned MK_S_MONIKERALREADYREGISTERED instead of 0x%08x\n", hr);
755
756 ok(dwCookie1 != dwCookie2, "cookie returned for registering duplicate object shouldn't match cookie of original object (0x%x)\n", dwCookie1);
757
758 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
759 ok_ole_success(hr, IRunningObjectTable_GetObject);
760 IUnknown_Release(pObject);
761
762 hr = IRunningObjectTable_Revoke(pROT, dwCookie1);
763 ok_ole_success(hr, IRunningObjectTable_Revoke);
764
765 hr = IRunningObjectTable_GetObject(pROT, pMoniker, &pObject);
766 ok_ole_success(hr, IRunningObjectTable_GetObject);
767 IUnknown_Release(pObject);
768
769 hr = IRunningObjectTable_Revoke(pROT, dwCookie2);
770 ok_ole_success(hr, IRunningObjectTable_Revoke);
771
772 IMoniker_Release(pMoniker);
773
774 IRunningObjectTable_Release(pROT);
775 }
776
777 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
778 {
779 if (IsEqualIID(riid, &IID_IUnknown) ||
780 IsEqualIID(riid, &IID_IParseDisplayName))
781 {
782 *ppv = iface;
783 IParseDisplayName_AddRef(iface);
784 return S_OK;
785 }
786 *ppv = NULL;
787 return E_NOINTERFACE;
788 }
789
790 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
791 {
792 return 2;
793 }
794
795 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
796 {
797 return 1;
798 }
799
800 static LPCWSTR expected_display_name;
801
802 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
803 IBindCtx *pbc,
804 LPOLESTR pszDisplayName,
805 ULONG *pchEaten,
806 IMoniker **ppmkOut)
807 {
808 char display_nameA[256];
809 WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
810 ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
811 ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
812 *pchEaten = lstrlenW(pszDisplayName);
813 return CreateAntiMoniker(ppmkOut);
814 }
815
816 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
817 {
818 ParseDisplayName_QueryInterface,
819 ParseDisplayName_AddRef,
820 ParseDisplayName_Release,
821 ParseDisplayName_ParseDisplayName
822 };
823
824 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
825
826 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
827 {
828 IMoniker * spMoniker;
829 int monCnt=0, matchCnt=0;
830
831 while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
832 {
833 HRESULT hr;
834 WCHAR * szDisplayn;
835 monCnt++;
836 hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
837 if (SUCCEEDED(hr))
838 {
839 if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
840 matchCnt++;
841 CoTaskMemFree(szDisplayn);
842 }
843 }
844 trace("Total number of monikers is %i\n", monCnt);
845 return matchCnt;
846 }
847
848 static void test_MkParseDisplayName(void)
849 {
850 IBindCtx * pbc = NULL;
851 HRESULT hr;
852 IMoniker * pmk = NULL;
853 IMoniker * pmk1 = NULL;
854 IMoniker * pmk2 = NULL;
855 ULONG eaten;
856 int matchCnt;
857 IUnknown * object = NULL;
858
859 IUnknown *lpEM1;
860
861 IEnumMoniker *spEM1 = NULL;
862 IEnumMoniker *spEM2 = NULL;
863 IEnumMoniker *spEM3 = NULL;
864
865 DWORD pdwReg1=0;
866 DWORD grflags=0;
867 DWORD pdwReg2=0;
868 DWORD moniker_type;
869 IRunningObjectTable * pprot=NULL;
870
871 /* CLSID of My Computer */
872 static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
873 '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};
874 static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
875 static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
876 static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
877 static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
878 static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
879 static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
880 static const WCHAR wszEmpty[] = {0};
881 char szDisplayNameFile[256];
882 WCHAR wszDisplayNameFile[256];
883 int i, len;
884
885 const struct
886 {
887 LPBC *ppbc;
888 LPCOLESTR szDisplayName;
889 LPDWORD pchEaten;
890 LPMONIKER *ppmk;
891 } invalid_parameters[] =
892 {
893 {NULL, NULL, NULL, NULL},
894 {NULL, NULL, NULL, &pmk},
895 {NULL, NULL, &eaten, NULL},
896 {NULL, NULL, &eaten, &pmk},
897 {NULL, wszEmpty, NULL, NULL},
898 {NULL, wszEmpty, NULL, &pmk},
899 {NULL, wszEmpty, &eaten, NULL},
900 {NULL, wszEmpty, &eaten, &pmk},
901 {&pbc, NULL, NULL, NULL},
902 {&pbc, NULL, NULL, &pmk},
903 {&pbc, NULL, &eaten, NULL},
904 {&pbc, NULL, &eaten, &pmk},
905 {&pbc, wszEmpty, NULL, NULL},
906 {&pbc, wszEmpty, NULL, &pmk},
907 {&pbc, wszEmpty, &eaten, NULL},
908 {&pbc, wszEmpty, &eaten, &pmk},
909 };
910
911 hr = CreateBindCtx(0, &pbc);
912 ok_ole_success(hr, CreateBindCtx);
913
914 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
915 {
916 eaten = 0xdeadbeef;
917 pmk = (IMoniker *)0xdeadbeef;
918 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
919 invalid_parameters[i].szDisplayName,
920 invalid_parameters[i].pchEaten,
921 invalid_parameters[i].ppmk);
922 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
923 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
924 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
925 }
926
927 eaten = 0xdeadbeef;
928 pmk = (IMoniker *)0xdeadbeef;
929 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
930 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
931 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
932 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
933 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
934
935 /* no special handling of "clsid:" without the string form of the clsid
936 * following */
937 eaten = 0xdeadbeef;
938 pmk = (IMoniker *)0xdeadbeef;
939 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
940 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
941 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
942 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
943 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
944
945 /* shows clsid has higher precedence than a running object */
946 hr = CreateFileMoniker(wszDisplayName, &pmk);
947 ok_ole_success(hr, CreateFileMoniker);
948 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
949 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
950 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
951 ok_ole_success(hr, IRunningObjectTable_Register);
952 IMoniker_Release(pmk);
953 pmk = NULL;
954 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
955 ok_ole_success(hr, MkParseDisplayName);
956 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1,
957 "Processed character count should have been 43 instead of %u\n", eaten);
958 if (pmk)
959 {
960 IMoniker_IsSystemMoniker(pmk, &moniker_type);
961 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
962 IMoniker_Release(pmk);
963 }
964 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
965 ok_ole_success(hr, IRunningObjectTable_Revoke);
966 IRunningObjectTable_Release(pprot);
967
968 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
969 ok_ole_success(hr, CreateFileMoniker);
970 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
971 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
972 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
973 ok_ole_success(hr, IRunningObjectTable_Register);
974 IMoniker_Release(pmk);
975 pmk = NULL;
976 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
977 ok_ole_success(hr, MkParseDisplayName);
978 ok(eaten == sizeof(wszDisplayNameRunning)/sizeof(WCHAR) - 1,
979 "Processed character count should have been 15 instead of %u\n", eaten);
980 if (pmk)
981 {
982 IMoniker_IsSystemMoniker(pmk, &moniker_type);
983 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
984 IMoniker_Release(pmk);
985 }
986 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
987 ok_ole_success(hr, IRunningObjectTable_Revoke);
988 IRunningObjectTable_Release(pprot);
989
990 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
991 ok_ole_success(hr, CoRegisterClassObject);
992
993 expected_display_name = wszDisplayNameProgId1;
994 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
995 ok_ole_success(hr, MkParseDisplayName);
996 ok(eaten == sizeof(wszDisplayNameProgId1)/sizeof(WCHAR) - 1,
997 "Processed character count should have been 8 instead of %u\n", eaten);
998 if (pmk)
999 {
1000 IMoniker_IsSystemMoniker(pmk, &moniker_type);
1001 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
1002 IMoniker_Release(pmk);
1003 }
1004
1005 expected_display_name = wszDisplayNameProgId2;
1006 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
1007 ok_ole_success(hr, MkParseDisplayName);
1008 ok(eaten == sizeof(wszDisplayNameProgId2)/sizeof(WCHAR) - 1,
1009 "Processed character count should have been 8 instead of %u\n", eaten);
1010 if (pmk)
1011 {
1012 IMoniker_IsSystemMoniker(pmk, &moniker_type);
1013 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
1014 IMoniker_Release(pmk);
1015 }
1016
1017 eaten = 0xdeadbeef;
1018 pmk = (IMoniker *)0xdeadbeef;
1019 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
1020 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
1021 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
1022 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
1023 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
1024
1025 hr = CoRevokeClassObject(pdwReg1);
1026 ok_ole_success(hr, CoRevokeClassObject);
1027
1028 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
1029 strcat(szDisplayNameFile, "\\kernel32.dll");
1030 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
1031 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
1032 ok_ole_success(hr, MkParseDisplayName);
1033 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
1034 if (pmk)
1035 {
1036 IMoniker_IsSystemMoniker(pmk, &moniker_type);
1037 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
1038 IMoniker_Release(pmk);
1039 }
1040
1041 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
1042 ok_ole_success(hr, MkParseDisplayName);
1043 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1, "Processed character count should have been 43 instead of %u\n", eaten);
1044
1045 if (pmk)
1046 {
1047 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
1048 ok_ole_success(hr, IMoniker_BindToObject);
1049
1050 if (SUCCEEDED(hr))
1051 IUnknown_Release(object);
1052 IMoniker_Release(pmk);
1053 }
1054 IBindCtx_Release(pbc);
1055
1056 /* Test the EnumMoniker interface */
1057 hr = CreateBindCtx(0, &pbc);
1058 ok_ole_success(hr, CreateBindCtx);
1059
1060 hr = CreateFileMoniker(wszFileName1, &pmk1);
1061 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1062 hr = CreateFileMoniker(wszFileName2, &pmk2);
1063 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1064 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1065 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
1066
1067 /* Check EnumMoniker before registering */
1068 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1069 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1070 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
1071 /* Register a couple of Monikers and check is ok */
1072 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
1073
1074 matchCnt = count_moniker_matches(pbc, spEM1);
1075 trace("Number of matches is %i\n", matchCnt);
1076
1077 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1078 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1079 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
1080 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
1081
1082 trace("IROT::Register\n");
1083 grflags=0;
1084 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1085 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1086 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
1087 pprot, grflags, lpEM1, pmk2, pdwReg2);
1088
1089 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1090 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1091
1092 matchCnt = count_moniker_matches(pbc, spEM2);
1093 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1094
1095 trace("IEnumMoniker::Clone\n");
1096 IEnumMoniker_Clone(spEM2, &spEM3);
1097
1098 matchCnt = count_moniker_matches(pbc, spEM3);
1099 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1100 trace("IEnumMoniker::Reset\n");
1101 IEnumMoniker_Reset(spEM3);
1102
1103 matchCnt = count_moniker_matches(pbc, spEM3);
1104 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1105
1106 IRunningObjectTable_Revoke(pprot,pdwReg1);
1107 IRunningObjectTable_Revoke(pprot,pdwReg2);
1108 IUnknown_Release(lpEM1);
1109 IEnumMoniker_Release(spEM1);
1110 IEnumMoniker_Release(spEM2);
1111 IEnumMoniker_Release(spEM3);
1112 IMoniker_Release(pmk1);
1113 IMoniker_Release(pmk2);
1114 IRunningObjectTable_Release(pprot);
1115
1116 IBindCtx_Release(pbc);
1117 }
1118
1119 static const LARGE_INTEGER llZero;
1120
1121 static const BYTE expected_class_moniker_marshal_data[] =
1122 {
1123 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1124 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1125 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1126 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1127 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1128 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1129 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1130 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1131 0x00,0x00,0x00,0x00,
1132 };
1133
1134 static const BYTE expected_class_moniker_saved_data[] =
1135 {
1136 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1137 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1138 0x00,0x00,0x00,0x00,
1139 };
1140
1141 static const BYTE expected_class_moniker_comparison_data[] =
1142 {
1143 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1144 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1145 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1146 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1147 };
1148
1149 static const WCHAR expected_class_moniker_display_name[] =
1150 {
1151 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1152 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1153 '0','0','0','0','4','6',':',0
1154 };
1155
1156 static const BYTE expected_item_moniker_comparison_data[] =
1157 {
1158 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1159 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1160 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1161 0x54,0x00,0x00,0x00,
1162 };
1163
1164 static const BYTE expected_item_moniker_saved_data[] =
1165 {
1166 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1167 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1168 };
1169
1170 static const BYTE expected_item_moniker_marshal_data[] =
1171 {
1172 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1173 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1174 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1175 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1176 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1177 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1178 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1179 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1180 };
1181
1182 static const BYTE expected_anti_moniker_marshal_data[] =
1183 {
1184 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1185 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1186 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1187 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1188 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1189 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1190 0x01,0x00,0x00,0x00,
1191 };
1192
1193 static const BYTE expected_anti_moniker_saved_data[] =
1194 {
1195 0x01,0x00,0x00,0x00,
1196 };
1197
1198 static const BYTE expected_anti_moniker_comparison_data[] =
1199 {
1200 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1201 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1202 0x01,0x00,0x00,0x00,
1203 };
1204
1205 static const BYTE expected_gc_moniker_marshal_data[] =
1206 {
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 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1211 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1212 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1213 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1214 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1215 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1216 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1217 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1218 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1219 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1220 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1221 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1222 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1223 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1224 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1225 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1226 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1227 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1228 0x00,0x57,0x69,0x6e,0x65,0x00,
1229 };
1230
1231 static const BYTE expected_gc_moniker_saved_data[] =
1232 {
1233 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1234 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1235 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1236 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1237 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1238 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1239 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1240 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1241 0x65,0x00,
1242 };
1243
1244 static const BYTE expected_gc_moniker_comparison_data[] =
1245 {
1246 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1247 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1248 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1249 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1250 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1251 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1252 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1253 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1254 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1255 };
1256
1257 static void test_moniker(
1258 const char *testname, IMoniker *moniker,
1259 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1260 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1261 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1262 LPCWSTR expected_display_name)
1263 {
1264 IStream * stream;
1265 IROTData * rotdata;
1266 HRESULT hr;
1267 HGLOBAL hglobal;
1268 LPBYTE moniker_data;
1269 DWORD moniker_size;
1270 DWORD i;
1271 BOOL same;
1272 BYTE buffer[128];
1273 IMoniker * moniker_proxy;
1274 LPOLESTR display_name;
1275 IBindCtx *bindctx;
1276
1277 hr = IMoniker_IsDirty(moniker);
1278 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1279
1280 /* Display Name */
1281
1282 hr = CreateBindCtx(0, &bindctx);
1283 ok_ole_success(hr, CreateBindCtx);
1284
1285 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1286 ok_ole_success(hr, IMoniker_GetDisplayName);
1287 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1288
1289 CoTaskMemFree(display_name);
1290 IBindCtx_Release(bindctx);
1291
1292 hr = IMoniker_IsDirty(moniker);
1293 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1294
1295 /* IROTData::GetComparisonData test */
1296
1297 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1298 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1299
1300 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1301 ok_ole_success(hr, IROTData_GetComparisonData);
1302
1303 if (hr != S_OK) moniker_size = 0;
1304
1305 /* first check we have the right amount of data */
1306 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1307 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1308 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1309
1310 /* then do a byte-by-byte comparison */
1311 same = TRUE;
1312 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1313 {
1314 if (expected_moniker_comparison_data[i] != buffer[i])
1315 {
1316 same = FALSE;
1317 break;
1318 }
1319 }
1320
1321 ok(same, "%s: Comparison data differs\n", testname);
1322 if (!same)
1323 {
1324 for (i = 0; i < moniker_size; i++)
1325 {
1326 if (i % 8 == 0) printf(" ");
1327 printf("0x%02x,", buffer[i]);
1328 if (i % 8 == 7) printf("\n");
1329 }
1330 printf("\n");
1331 }
1332
1333 IROTData_Release(rotdata);
1334
1335 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1336 ok_ole_success(hr, CreateStreamOnHGlobal);
1337
1338 /* Saving */
1339
1340 hr = IMoniker_Save(moniker, stream, TRUE);
1341 ok_ole_success(hr, IMoniker_Save);
1342
1343 hr = GetHGlobalFromStream(stream, &hglobal);
1344 ok_ole_success(hr, GetHGlobalFromStream);
1345
1346 moniker_size = GlobalSize(hglobal);
1347
1348 moniker_data = GlobalLock(hglobal);
1349
1350 /* first check we have the right amount of data */
1351 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1352 "%s: Size of saved data differs (expected %d, actual %d)\n",
1353 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1354
1355 /* then do a byte-by-byte comparison */
1356 same = TRUE;
1357 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1358 {
1359 if (expected_moniker_saved_data[i] != moniker_data[i])
1360 {
1361 same = FALSE;
1362 break;
1363 }
1364 }
1365
1366 ok(same, "%s: Saved data differs\n", testname);
1367 if (!same)
1368 {
1369 for (i = 0; i < moniker_size; i++)
1370 {
1371 if (i % 8 == 0) printf(" ");
1372 printf("0x%02x,", moniker_data[i]);
1373 if (i % 8 == 7) printf("\n");
1374 }
1375 printf("\n");
1376 }
1377
1378 GlobalUnlock(hglobal);
1379
1380 IStream_Release(stream);
1381
1382 /* Marshaling tests */
1383
1384 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1385 ok_ole_success(hr, CreateStreamOnHGlobal);
1386
1387 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1388 ok_ole_success(hr, CoMarshalInterface);
1389
1390 hr = GetHGlobalFromStream(stream, &hglobal);
1391 ok_ole_success(hr, GetHGlobalFromStream);
1392
1393 moniker_size = GlobalSize(hglobal);
1394
1395 moniker_data = GlobalLock(hglobal);
1396
1397 /* first check we have the right amount of data */
1398 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1399 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1400 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1401
1402 /* then do a byte-by-byte comparison */
1403 same = TRUE;
1404 if (expected_moniker_marshal_data)
1405 {
1406 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1407 {
1408 if (expected_moniker_marshal_data[i] != moniker_data[i])
1409 {
1410 same = FALSE;
1411 break;
1412 }
1413 }
1414 }
1415
1416 ok(same, "%s: Marshaled data differs\n", testname);
1417 if (!same)
1418 {
1419 for (i = 0; i < moniker_size; i++)
1420 {
1421 if (i % 8 == 0) printf(" ");
1422 printf("0x%02x,", moniker_data[i]);
1423 if (i % 8 == 7) printf("\n");
1424 }
1425 printf("\n");
1426 }
1427
1428 GlobalUnlock(hglobal);
1429
1430 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1431 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1432 ok_ole_success(hr, CoUnmarshalInterface);
1433
1434 IStream_Release(stream);
1435 IMoniker_Release(moniker_proxy);
1436 }
1437
1438 static void test_class_moniker(void)
1439 {
1440 HRESULT hr;
1441 IMoniker *moniker;
1442 DWORD moniker_type;
1443 DWORD hash;
1444 IBindCtx *bindctx;
1445 IMoniker *inverse;
1446 IUnknown *unknown;
1447 FILETIME filetime;
1448
1449 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1450 ok_ole_success(hr, CreateClassMoniker);
1451 if (!moniker) return;
1452
1453 test_moniker("class moniker", moniker,
1454 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1455 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1456 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1457 expected_class_moniker_display_name);
1458
1459 /* Hashing */
1460
1461 hr = IMoniker_Hash(moniker, &hash);
1462 ok_ole_success(hr, IMoniker_Hash);
1463
1464 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1465 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1466 hash);
1467
1468 /* IsSystemMoniker test */
1469
1470 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1471 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1472
1473 ok(moniker_type == MKSYS_CLASSMONIKER,
1474 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1475 moniker_type);
1476
1477 hr = CreateBindCtx(0, &bindctx);
1478 ok_ole_success(hr, CreateBindCtx);
1479
1480 /* IsRunning test */
1481 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1482 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1483
1484 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1485 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1486
1487 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1488 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1489
1490 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1491 ok_ole_success(hr, IMoniker_BindToObject);
1492 IUnknown_Release(unknown);
1493
1494 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1495 ok_ole_success(hr, IMoniker_BindToStorage);
1496 IUnknown_Release(unknown);
1497
1498 IBindCtx_Release(bindctx);
1499
1500 hr = IMoniker_Inverse(moniker, &inverse);
1501 ok_ole_success(hr, IMoniker_Inverse);
1502 IMoniker_Release(inverse);
1503
1504 IMoniker_Release(moniker);
1505 }
1506
1507 static void test_file_moniker(WCHAR* path)
1508 {
1509 IStream *stream;
1510 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1511 HRESULT hr;
1512
1513 hr = CreateFileMoniker(path, &moniker1);
1514 ok_ole_success(hr, CreateFileMoniker);
1515
1516 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1517 ok_ole_success(hr, CreateStreamOnHGlobal);
1518
1519 /* Marshal */
1520 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1521 ok_ole_success(hr, CoMarshalInterface);
1522
1523 /* Rewind */
1524 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1525 ok_ole_success(hr, IStream_Seek);
1526
1527 /* Unmarshal */
1528 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1529 ok_ole_success(hr, CoUnmarshalInterface);
1530
1531 hr = IMoniker_IsEqual(moniker1, moniker2);
1532 ok_ole_success(hr, IsEqual);
1533
1534 IStream_Release(stream);
1535 if (moniker1)
1536 IMoniker_Release(moniker1);
1537 if (moniker2)
1538 IMoniker_Release(moniker2);
1539 }
1540
1541 static void test_file_monikers(void)
1542 {
1543 static WCHAR wszFile[][30] = {
1544 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1545 {'\\', '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},
1546 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1547 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1548 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1549 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1550 * U+0100 .. = Latin extended-A
1551 */
1552 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1553 };
1554
1555 int i;
1556
1557 trace("ACP is %u\n", GetACP());
1558
1559 for (i = 0; i < COUNTOF(wszFile); ++i)
1560 {
1561 int j ;
1562 if (i == 2)
1563 {
1564 BOOL used;
1565 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1566 if (used)
1567 {
1568 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1569 continue;
1570 }
1571 }
1572 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1573 {
1574 wszFile[i][j] = 0;
1575 test_file_moniker(wszFile[i]);
1576 }
1577 }
1578 }
1579
1580 static void test_item_moniker(void)
1581 {
1582 HRESULT hr;
1583 IMoniker *moniker;
1584 DWORD moniker_type;
1585 DWORD hash;
1586 IBindCtx *bindctx;
1587 IMoniker *inverse;
1588 IUnknown *unknown;
1589 static const WCHAR wszDelimeter[] = {'!',0};
1590 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1591 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1592
1593 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1594 ok_ole_success(hr, CreateItemMoniker);
1595
1596 test_moniker("item moniker", moniker,
1597 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1598 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1599 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1600 expected_display_name);
1601
1602 /* Hashing */
1603
1604 hr = IMoniker_Hash(moniker, &hash);
1605 ok_ole_success(hr, IMoniker_Hash);
1606
1607 ok(hash == 0x73c,
1608 "Hash value != 0x73c, instead was 0x%08x\n",
1609 hash);
1610
1611 /* IsSystemMoniker test */
1612
1613 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1614 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1615
1616 ok(moniker_type == MKSYS_ITEMMONIKER,
1617 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1618 moniker_type);
1619
1620 hr = CreateBindCtx(0, &bindctx);
1621 ok_ole_success(hr, CreateBindCtx);
1622
1623 /* IsRunning test */
1624 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1625 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1626
1627 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1628 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1629
1630 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1631 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1632
1633 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1634 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1635
1636 IBindCtx_Release(bindctx);
1637
1638 hr = IMoniker_Inverse(moniker, &inverse);
1639 ok_ole_success(hr, IMoniker_Inverse);
1640 IMoniker_Release(inverse);
1641
1642 IMoniker_Release(moniker);
1643 }
1644
1645 static void test_anti_moniker(void)
1646 {
1647 HRESULT hr;
1648 IMoniker *moniker;
1649 DWORD moniker_type;
1650 DWORD hash;
1651 IBindCtx *bindctx;
1652 FILETIME filetime;
1653 IMoniker *inverse;
1654 IUnknown *unknown;
1655 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1656
1657 hr = CreateAntiMoniker(&moniker);
1658 ok_ole_success(hr, CreateAntiMoniker);
1659 if (!moniker) return;
1660
1661 test_moniker("anti moniker", moniker,
1662 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1663 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1664 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1665 expected_display_name);
1666
1667 /* Hashing */
1668 hr = IMoniker_Hash(moniker, &hash);
1669 ok_ole_success(hr, IMoniker_Hash);
1670 ok(hash == 0x80000001,
1671 "Hash value != 0x80000001, instead was 0x%08x\n",
1672 hash);
1673
1674 /* IsSystemMoniker test */
1675 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1676 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1677 ok(moniker_type == MKSYS_ANTIMONIKER,
1678 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1679 moniker_type);
1680
1681 hr = IMoniker_Inverse(moniker, &inverse);
1682 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1683 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1684
1685 hr = CreateBindCtx(0, &bindctx);
1686 ok_ole_success(hr, CreateBindCtx);
1687
1688 /* IsRunning test */
1689 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1690 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1691
1692 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1693 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1694
1695 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1696 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1697
1698 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1699 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1700
1701 IBindCtx_Release(bindctx);
1702
1703 IMoniker_Release(moniker);
1704 }
1705
1706 static void test_generic_composite_moniker(void)
1707 {
1708 HRESULT hr;
1709 IMoniker *moniker;
1710 IMoniker *moniker1;
1711 IMoniker *moniker2;
1712 DWORD moniker_type;
1713 DWORD hash;
1714 IBindCtx *bindctx;
1715 FILETIME filetime;
1716 IMoniker *inverse;
1717 IUnknown *unknown;
1718 static const WCHAR wszDelimeter1[] = {'!',0};
1719 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1720 static const WCHAR wszDelimeter2[] = {'#',0};
1721 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1722 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1723
1724 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1725 ok_ole_success(hr, CreateItemMoniker);
1726 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1727 ok_ole_success(hr, CreateItemMoniker);
1728 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1729 ok_ole_success(hr, CreateGenericComposite);
1730
1731 test_moniker("generic composite moniker", moniker,
1732 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1733 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1734 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1735 expected_display_name);
1736
1737 /* Hashing */
1738
1739 hr = IMoniker_Hash(moniker, &hash);
1740 ok_ole_success(hr, IMoniker_Hash);
1741
1742 ok(hash == 0xd87,
1743 "Hash value != 0xd87, instead was 0x%08x\n",
1744 hash);
1745
1746 /* IsSystemMoniker test */
1747
1748 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1749 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1750
1751 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1752 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1753 moniker_type);
1754
1755 hr = CreateBindCtx(0, &bindctx);
1756 ok_ole_success(hr, CreateBindCtx);
1757
1758 /* IsRunning test */
1759 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1760 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1761
1762 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1763 todo_wine
1764 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1765
1766 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1767 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1768
1769 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1770 todo_wine
1771 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1772
1773 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1774 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1775
1776 IBindCtx_Release(bindctx);
1777
1778 hr = IMoniker_Inverse(moniker, &inverse);
1779 ok_ole_success(hr, IMoniker_Inverse);
1780 IMoniker_Release(inverse);
1781
1782 IMoniker_Release(moniker);
1783 }
1784
1785 static void test_pointer_moniker(void)
1786 {
1787 HRESULT hr;
1788 IMoniker *moniker;
1789 DWORD moniker_type;
1790 DWORD hash;
1791 IBindCtx *bindctx;
1792 FILETIME filetime;
1793 IMoniker *inverse;
1794 IUnknown *unknown;
1795 IStream *stream;
1796 IROTData *rotdata;
1797 LPOLESTR display_name;
1798
1799 cLocks = 0;
1800
1801 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1802 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1803
1804 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1805 ok_ole_success(hr, CreatePointerMoniker);
1806 if (!moniker) return;
1807
1808 ok_more_than_one_lock();
1809
1810 /* Display Name */
1811
1812 hr = CreateBindCtx(0, &bindctx);
1813 ok_ole_success(hr, CreateBindCtx);
1814
1815 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1816 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1817
1818 IBindCtx_Release(bindctx);
1819
1820 hr = IMoniker_IsDirty(moniker);
1821 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1822
1823 /* IROTData::GetComparisonData test */
1824
1825 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1826 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1827
1828 /* Saving */
1829
1830 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1831 ok_ole_success(hr, CreateStreamOnHGlobal);
1832
1833 hr = IMoniker_Save(moniker, stream, TRUE);
1834 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1835
1836 IStream_Release(stream);
1837
1838 /* Hashing */
1839 hr = IMoniker_Hash(moniker, &hash);
1840 ok_ole_success(hr, IMoniker_Hash);
1841 ok(hash == PtrToUlong(&Test_ClassFactory),
1842 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1843 PtrToUlong(&Test_ClassFactory), hash);
1844
1845 /* IsSystemMoniker test */
1846 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1847 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1848 ok(moniker_type == MKSYS_POINTERMONIKER,
1849 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1850 moniker_type);
1851
1852 hr = IMoniker_Inverse(moniker, &inverse);
1853 ok_ole_success(hr, IMoniker_Inverse);
1854 IMoniker_Release(inverse);
1855
1856 hr = CreateBindCtx(0, &bindctx);
1857 ok_ole_success(hr, CreateBindCtx);
1858
1859 /* IsRunning test */
1860 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1861 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1862
1863 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1864 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1865
1866 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1867 ok_ole_success(hr, IMoniker_BindToObject);
1868 IUnknown_Release(unknown);
1869
1870 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1871 ok_ole_success(hr, IMoniker_BindToStorage);
1872 IUnknown_Release(unknown);
1873
1874 IMoniker_Release(moniker);
1875
1876 ok_no_locks();
1877
1878 hr = CreatePointerMoniker(NULL, &moniker);
1879 ok_ole_success(hr, CreatePointerMoniker);
1880
1881 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1882 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1883
1884 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1885 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1886
1887 IBindCtx_Release(bindctx);
1888
1889 IMoniker_Release(moniker);
1890 }
1891
1892 static void test_bind_context(void)
1893 {
1894 HRESULT hr;
1895 IBindCtx *pBindCtx;
1896 IEnumString *pEnumString;
1897 BIND_OPTS2 bind_opts;
1898 HeapUnknown *unknown;
1899 HeapUnknown *unknown2;
1900 IUnknown *param_obj;
1901 ULONG refs;
1902 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1903 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1904
1905 hr = CreateBindCtx(0, NULL);
1906 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1907
1908 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1909 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1910
1911 hr = CreateBindCtx(0, &pBindCtx);
1912 ok_ole_success(hr, "CreateBindCtx");
1913
1914 bind_opts.cbStruct = -1;
1915 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1916 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1917 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1918 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1919 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1920
1921 bind_opts.cbStruct = sizeof(BIND_OPTS);
1922 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1923 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1924 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1925
1926 bind_opts.cbStruct = sizeof(bind_opts);
1927 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1928 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1929 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1930 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1931 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1932 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1933 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1934 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1935 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1936 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1937 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1938
1939 bind_opts.cbStruct = -1;
1940 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1941 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1942
1943 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1944 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1945
1946 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1947 unknown->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1948 unknown->refs = 1;
1949 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, &unknown->IUnknown_iface);
1950 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1951
1952 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1953 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1954 IUnknown_Release(param_obj);
1955
1956 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1957 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1958 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1959
1960 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1961 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1962
1963 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1964 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1965 ok(!pEnumString, "pEnumString should be NULL\n");
1966
1967 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1968 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1969
1970 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1971 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1972
1973 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1974 unknown2->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
1975 unknown2->refs = 1;
1976 hr = IBindCtx_RegisterObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1977 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1978
1979 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1980 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1981
1982 hr = IBindCtx_RevokeObjectBound(pBindCtx, &unknown2->IUnknown_iface);
1983 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1984
1985 IBindCtx_Release(pBindCtx);
1986
1987 refs = IUnknown_Release(&unknown->IUnknown_iface);
1988 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1989
1990 refs = IUnknown_Release(&unknown2->IUnknown_iface);
1991 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1992 }
1993
1994 static void test_save_load_filemoniker(void)
1995 {
1996 IMoniker* pMk;
1997 IStream* pStm;
1998 HRESULT hr;
1999 ULARGE_INTEGER size;
2000 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
2001 DWORD some_val = 0xFEDCBA98;
2002 int i;
2003
2004 /* see FileMonikerImpl_Save docs */
2005 zero_pos.QuadPart = 0;
2006 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
2007 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
2008
2009 /* create the stream we're going to write to */
2010 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
2011 ok_ole_success(hr, "CreateStreamOnHGlobal");
2012
2013 size.u.LowPart = 128;
2014 hr = IStream_SetSize(pStm, size);
2015 ok_ole_success(hr, "IStream_SetSize");
2016
2017 /* create and save a moniker */
2018 hr = CreateFileMoniker(wszFileName1, &pMk);
2019 ok_ole_success(hr, "CreateFileMoniker");
2020
2021 hr = IMoniker_Save(pMk, pStm, TRUE);
2022 ok_ole_success(hr, "IMoniker_Save");
2023 IMoniker_Release(pMk);
2024
2025 /* overwrite the constants with various values */
2026 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
2027 ok_ole_success(hr, "IStream_Seek");
2028 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
2029 ok_ole_success(hr, "IStream_Write");
2030
2031 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
2032 ok_ole_success(hr, "IStream_Seek");
2033 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
2034 ok_ole_success(hr, "IStream_Write");
2035
2036 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
2037 ok_ole_success(hr, "IStream_Seek");
2038 for(i = 0; i < 5; ++i){
2039 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
2040 ok_ole_success(hr, "IStream_Write");
2041 }
2042
2043 /* go back to the start of the stream */
2044 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
2045 ok_ole_success(hr, "IStream_Seek");
2046
2047 /* create a new moniker and load into it */
2048 hr = CreateFileMoniker(wszFileName1, &pMk);
2049 ok_ole_success(hr, "CreateFileMoniker");
2050
2051 hr = IMoniker_Load(pMk, pStm);
2052 ok_ole_success(hr, "IMoniker_Load");
2053
2054 IMoniker_Release(pMk);
2055 IStream_Release(pStm);
2056 }
2057
2058 START_TEST(moniker)
2059 {
2060 if (!GetProcAddress(GetModuleHandleA("ole32.dll"), "CoRegisterSurrogateEx")) {
2061 win_skip("skipping test on win9x\n");
2062 return;
2063 }
2064
2065 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2066
2067 test_ROT();
2068 test_ROT_multiple_entries();
2069 test_MkParseDisplayName();
2070 test_class_moniker();
2071 test_file_monikers();
2072 test_item_moniker();
2073 test_anti_moniker();
2074 test_generic_composite_moniker();
2075 test_pointer_moniker();
2076 test_save_load_filemoniker();
2077
2078 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2079
2080 test_bind_context();
2081
2082 CoUninitialize();
2083 }