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