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