Sync to trunk head(r38096)
[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 HRESULT WINAPI Test_IClassFactory_QueryInterface(
86 LPCLASSFACTORY iface,
87 REFIID riid,
88 LPVOID *ppvObj)
89 {
90 if (ppvObj == NULL) return E_POINTER;
91
92 if (IsEqualGUID(riid, &IID_IUnknown) ||
93 IsEqualGUID(riid, &IID_IClassFactory))
94 {
95 *ppvObj = (LPVOID)iface;
96 IClassFactory_AddRef(iface);
97 return S_OK;
98 }
99
100 *ppvObj = NULL;
101 return E_NOINTERFACE;
102 }
103
104 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
105 {
106 LockModule();
107 return 2; /* non-heap-based object */
108 }
109
110 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
111 {
112 UnlockModule();
113 return 1; /* non-heap-based object */
114 }
115
116 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
117 LPCLASSFACTORY iface,
118 LPUNKNOWN pUnkOuter,
119 REFIID riid,
120 LPVOID *ppvObj)
121 {
122 return E_NOTIMPL;
123 }
124
125 static HRESULT WINAPI Test_IClassFactory_LockServer(
126 LPCLASSFACTORY iface,
127 BOOL fLock)
128 {
129 return S_OK;
130 }
131
132 static const IClassFactoryVtbl TestClassFactory_Vtbl =
133 {
134 Test_IClassFactory_QueryInterface,
135 Test_IClassFactory_AddRef,
136 Test_IClassFactory_Release,
137 Test_IClassFactory_CreateInstance,
138 Test_IClassFactory_LockServer
139 };
140
141 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
142
143 typedef struct
144 {
145 const IUnknownVtbl *lpVtbl;
146 ULONG refs;
147 } HeapUnknown;
148
149 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
150 {
151 if (IsEqualIID(riid, &IID_IUnknown))
152 {
153 IUnknown_AddRef(iface);
154 *ppv = (LPVOID)iface;
155 return S_OK;
156 }
157 *ppv = NULL;
158 return E_NOINTERFACE;
159 }
160
161 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
162 {
163 HeapUnknown *This = (HeapUnknown *)iface;
164 return InterlockedIncrement((LONG*)&This->refs);
165 }
166
167 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
168 {
169 HeapUnknown *This = (HeapUnknown *)iface;
170 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
171 if (!refs) HeapFree(GetProcessHeap(), 0, This);
172 return refs;
173 }
174
175 static const IUnknownVtbl HeapUnknown_Vtbl =
176 {
177 HeapUnknown_QueryInterface,
178 HeapUnknown_AddRef,
179 HeapUnknown_Release
180 };
181
182 static HRESULT WINAPI
183 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
184 {
185 if (!ppvObject)
186 return E_INVALIDARG;
187
188 *ppvObject = 0;
189
190 if (IsEqualIID(&IID_IUnknown, riid) ||
191 IsEqualIID(&IID_IPersist, riid) ||
192 IsEqualIID(&IID_IPersistStream,riid) ||
193 IsEqualIID(&IID_IMoniker, riid))
194 *ppvObject = iface;
195 if (IsEqualIID(&IID_IROTData, riid))
196 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
197
198 if ((*ppvObject)==0)
199 return E_NOINTERFACE;
200
201 IMoniker_AddRef(iface);
202
203 return S_OK;
204 }
205
206 static ULONG WINAPI
207 Moniker_AddRef(IMoniker* iface)
208 {
209 return 2;
210 }
211
212 static ULONG WINAPI
213 Moniker_Release(IMoniker* iface)
214 {
215 return 1;
216 }
217
218 static HRESULT WINAPI
219 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
220 {
221 CHECK_EXPECTED_METHOD("Moniker_GetClassID");
222
223 *pClassID = CLSID_TestMoniker;
224
225 return S_OK;
226 }
227
228 static HRESULT WINAPI
229 Moniker_IsDirty(IMoniker* iface)
230 {
231 CHECK_EXPECTED_METHOD("Moniker_IsDirty");
232
233 return S_FALSE;
234 }
235
236 static HRESULT WINAPI
237 Moniker_Load(IMoniker* iface, IStream* pStm)
238 {
239 CHECK_EXPECTED_METHOD("Moniker_Load");
240 return E_NOTIMPL;
241 }
242
243 static HRESULT WINAPI
244 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
245 {
246 CHECK_EXPECTED_METHOD("Moniker_Save");
247 return E_NOTIMPL;
248 }
249
250 static HRESULT WINAPI
251 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
252 {
253 CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
254 return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI
258 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
259 REFIID riid, VOID** ppvResult)
260 {
261 CHECK_EXPECTED_METHOD("Moniker_BindToObject");
262 return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI
266 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
267 REFIID riid, VOID** ppvObject)
268 {
269 CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
270 return E_NOTIMPL;
271 }
272
273 static HRESULT WINAPI
274 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
275 IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
276 {
277 CHECK_EXPECTED_METHOD("Moniker_Reduce");
278
279 if (ppmkReduced==NULL)
280 return E_POINTER;
281
282 IMoniker_AddRef(iface);
283
284 *ppmkReduced=iface;
285
286 return MK_S_REDUCED_TO_SELF;
287 }
288
289 static HRESULT WINAPI
290 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
291 BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
292 {
293 CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
294 return E_NOTIMPL;
295 }
296
297 static HRESULT WINAPI
298 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
299 {
300 CHECK_EXPECTED_METHOD("Moniker_Enum");
301
302 if (ppenumMoniker == NULL)
303 return E_POINTER;
304
305 *ppenumMoniker = NULL;
306
307 return S_OK;
308 }
309
310 static HRESULT WINAPI
311 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
312 {
313 CHECK_EXPECTED_METHOD("Moniker_IsEqual");
314 return E_NOTIMPL;
315 }
316
317 static HRESULT WINAPI
318 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
319 {
320 CHECK_EXPECTED_METHOD("Moniker_Hash");
321 return E_NOTIMPL;
322 }
323
324 static HRESULT WINAPI
325 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
326 IMoniker* pmkNewlyRunning)
327 {
328 CHECK_EXPECTED_METHOD("Moniker_IsRunning");
329 return E_NOTIMPL;
330 }
331
332 static HRESULT WINAPI
333 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
334 IMoniker* pmkToLeft, FILETIME* pFileTime)
335 {
336 CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
337 return E_NOTIMPL;
338 }
339
340 static HRESULT WINAPI
341 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
342 {
343 CHECK_EXPECTED_METHOD("Moniker_Inverse");
344 return E_NOTIMPL;
345 }
346
347 static HRESULT WINAPI
348 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
349 {
350 CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
351 return E_NOTIMPL;
352 }
353
354 static HRESULT WINAPI
355 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
356 {
357 CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
358 return E_NOTIMPL;
359 }
360
361 static HRESULT WINAPI
362 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
363 IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
364 {
365 static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
366 CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
367 *ppszDisplayName = (LPOLESTR)CoTaskMemAlloc(sizeof(wszDisplayName));
368 memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
369 return S_OK;
370 }
371
372 static HRESULT WINAPI
373 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
374 LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
375 {
376 CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
377 return E_NOTIMPL;
378 }
379
380 static HRESULT WINAPI
381 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
382 {
383 CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
384
385 if (!pwdMksys)
386 return E_POINTER;
387
388 (*pwdMksys)=MKSYS_NONE;
389
390 return S_FALSE;
391 }
392
393 static const IMonikerVtbl MonikerNoROTDataVtbl =
394 {
395 MonikerNoROTData_QueryInterface,
396 Moniker_AddRef,
397 Moniker_Release,
398 Moniker_GetClassID,
399 Moniker_IsDirty,
400 Moniker_Load,
401 Moniker_Save,
402 Moniker_GetSizeMax,
403 Moniker_BindToObject,
404 Moniker_BindToStorage,
405 Moniker_Reduce,
406 Moniker_ComposeWith,
407 Moniker_Enum,
408 Moniker_IsEqual,
409 Moniker_Hash,
410 Moniker_IsRunning,
411 Moniker_GetTimeOfLastChange,
412 Moniker_Inverse,
413 Moniker_CommonPrefixWith,
414 Moniker_RelativePathTo,
415 Moniker_GetDisplayName,
416 Moniker_ParseDisplayName,
417 Moniker_IsSystemMoniker
418 };
419
420 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
421
422 static IMoniker Moniker;
423
424 static HRESULT WINAPI
425 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
426 {
427 return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
428 }
429
430 static ULONG WINAPI
431 ROTData_AddRef(IROTData *iface)
432 {
433 return 2;
434 }
435
436 static ULONG WINAPI
437 ROTData_Release(IROTData* iface)
438 {
439 return 1;
440 }
441
442 static HRESULT WINAPI
443 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
444 ULONG cbMax, ULONG* pcbData)
445 {
446 CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
447
448 *pcbData = 1;
449 if (cbMax < *pcbData)
450 return E_OUTOFMEMORY;
451
452 *pbData = 0xde;
453
454 return S_OK;
455 }
456
457 static IROTDataVtbl ROTDataVtbl =
458 {
459 ROTData_QueryInterface,
460 ROTData_AddRef,
461 ROTData_Release,
462 ROTData_GetComparisonData
463 };
464
465 static IROTData ROTData = { &ROTDataVtbl };
466
467 static HRESULT WINAPI
468 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
469 {
470 if (!ppvObject)
471 return E_INVALIDARG;
472
473 *ppvObject = 0;
474
475 if (IsEqualIID(&IID_IUnknown, riid) ||
476 IsEqualIID(&IID_IPersist, riid) ||
477 IsEqualIID(&IID_IPersistStream,riid) ||
478 IsEqualIID(&IID_IMoniker, riid))
479 *ppvObject = iface;
480 if (IsEqualIID(&IID_IROTData, riid))
481 {
482 CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
483 *ppvObject = &ROTData;
484 }
485
486 if ((*ppvObject)==0)
487 return E_NOINTERFACE;
488
489 IMoniker_AddRef(iface);
490
491 return S_OK;
492 }
493
494 static const IMonikerVtbl MonikerVtbl =
495 {
496 Moniker_QueryInterface,
497 Moniker_AddRef,
498 Moniker_Release,
499 Moniker_GetClassID,
500 Moniker_IsDirty,
501 Moniker_Load,
502 Moniker_Save,
503 Moniker_GetSizeMax,
504 Moniker_BindToObject,
505 Moniker_BindToStorage,
506 Moniker_Reduce,
507 Moniker_ComposeWith,
508 Moniker_Enum,
509 Moniker_IsEqual,
510 Moniker_Hash,
511 Moniker_IsRunning,
512 Moniker_GetTimeOfLastChange,
513 Moniker_Inverse,
514 Moniker_CommonPrefixWith,
515 Moniker_RelativePathTo,
516 Moniker_GetDisplayName,
517 Moniker_ParseDisplayName,
518 Moniker_IsSystemMoniker
519 };
520
521 static IMoniker Moniker = { &MonikerVtbl };
522
523 static void test_ROT(void)
524 {
525 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
526 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
527 '2','0','4','6','E','5','8','6','C','9','2','5',0};
528 HRESULT hr;
529 IMoniker *pMoniker = NULL;
530 IRunningObjectTable *pROT = NULL;
531 DWORD dwCookie;
532 static const char *methods_register_no_ROTData[] =
533 {
534 "Moniker_Reduce",
535 "Moniker_GetTimeOfLastChange",
536 "Moniker_QueryInterface(IID_IROTData)",
537 "Moniker_GetDisplayName",
538 "Moniker_GetClassID",
539 NULL
540 };
541 static const char *methods_register[] =
542 {
543 "Moniker_Reduce",
544 "Moniker_GetTimeOfLastChange",
545 "Moniker_QueryInterface(IID_IROTData)",
546 "ROTData_GetComparisonData",
547 NULL
548 };
549 static const char *methods_isrunning_no_ROTData[] =
550 {
551 "Moniker_Reduce",
552 "Moniker_QueryInterface(IID_IROTData)",
553 "Moniker_GetDisplayName",
554 "Moniker_GetClassID",
555 NULL
556 };
557 static const char *methods_isrunning[] =
558 {
559 "Moniker_Reduce",
560 "Moniker_QueryInterface(IID_IROTData)",
561 "ROTData_GetComparisonData",
562 NULL
563 };
564
565 cLocks = 0;
566
567 hr = GetRunningObjectTable(0, &pROT);
568 ok_ole_success(hr, GetRunningObjectTable);
569
570 expected_method_list = methods_register_no_ROTData;
571 /* try with our own moniker that doesn't support IROTData */
572 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
573 (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
574 todo_wine { /* only fails because of lack of IMoniker marshaling */
575 ok_ole_success(hr, IRunningObjectTable_Register);
576 }
577 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
578
579 todo_wine { /* only fails because of lack of IMoniker marshaling */
580 ok_more_than_one_lock();
581 }
582
583 expected_method_list = methods_isrunning_no_ROTData;
584 hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
585 todo_wine { /* only fails because of lack of IMoniker marshaling */
586 ok_ole_success(hr, IRunningObjectTable_IsRunning);
587 }
588 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
589
590 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
591 todo_wine { /* only fails because of lack of IMoniker marshaling */
592 ok_ole_success(hr, IRunningObjectTable_Revoke);
593 }
594
595 ok_no_locks();
596
597 expected_method_list = methods_register;
598 /* try with our own moniker */
599 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
600 (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
601 todo_wine { /* only fails because of lack of IMoniker marshaling */
602 ok_ole_success(hr, IRunningObjectTable_Register);
603 }
604 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
605
606 todo_wine { /* only fails because of lack of IMoniker marshaling */
607 ok_more_than_one_lock();
608 }
609
610 expected_method_list = methods_isrunning;
611 hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
612 todo_wine { /* only fails because of lack of IMoniker marshaling */
613 ok_ole_success(hr, IRunningObjectTable_IsRunning);
614 }
615 ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
616
617 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
618 todo_wine { /* only fails because of lack of IMoniker marshaling */
619 ok_ole_success(hr, IRunningObjectTable_Revoke);
620 }
621
622 ok_no_locks();
623
624 hr = CreateFileMoniker(wszFileName, &pMoniker);
625 ok_ole_success(hr, CreateClassMoniker);
626
627 /* test flags: 0 */
628 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
629 pMoniker, &dwCookie);
630 ok_ole_success(hr, IRunningObjectTable_Register);
631
632 ok_more_than_one_lock();
633
634 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
635 ok_ole_success(hr, IRunningObjectTable_Revoke);
636
637 ok_no_locks();
638
639 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
640 hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
641 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
642 ok_ole_success(hr, IRunningObjectTable_Register);
643
644 ok_more_than_one_lock();
645
646 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
647 ok_ole_success(hr, IRunningObjectTable_Revoke);
648
649 ok_no_locks();
650
651 /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
652 /* only succeeds when process is started by SCM and has LocalService
653 * or RunAs AppId values */
654 hr = IRunningObjectTable_Register(pROT,
655 ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
656 (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
657 todo_wine {
658 ok(hr == CO_E_WRONG_SERVER_IDENTITY, "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 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 == sizeof_expected_moniker_saved_data,
1224 "%s: Size of saved data differs (expected %d, actual %d)\n",
1225 testname, sizeof_expected_moniker_saved_data, moniker_size);
1226
1227 /* then do a byte-by-byte comparison */
1228 for (i = 0; i < min(moniker_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 == sizeof_expected_moniker_marshal_data,
1270 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1271 testname, 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, 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, bindctx, NULL, NULL);
1352 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1353
1354 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1355 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1356
1357 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1358 ok_ole_success(hr, IMoniker_BindToObject);
1359 IUnknown_Release(unknown);
1360
1361 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1362 ok_ole_success(hr, IMoniker_BindToStorage);
1363 IUnknown_Release(unknown);
1364
1365 IBindCtx_Release(bindctx);
1366
1367 hr = IMoniker_Inverse(moniker, &inverse);
1368 ok_ole_success(hr, IMoniker_Inverse);
1369 IMoniker_Release(inverse);
1370
1371 IMoniker_Release(moniker);
1372 }
1373
1374 static void test_file_moniker(WCHAR* path)
1375 {
1376 IStream *stream;
1377 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1378 HRESULT hr;
1379
1380 hr = CreateFileMoniker(path, &moniker1);
1381 ok_ole_success(hr, CreateFileMoniker);
1382
1383 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1384
1385 /* Marshal */
1386 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1387 ok_ole_success(hr, CoMarshalInterface);
1388
1389 /* Rewind */
1390 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1391 ok_ole_success(hr, IStream_Seek);
1392
1393 /* Unmarshal */
1394 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1395 ok_ole_success(hr, CoUnmarshalInterface);
1396
1397 hr = IMoniker_IsEqual(moniker1, moniker2);
1398 ok_ole_success(hr, IsEqual);
1399
1400 IStream_Release(stream);
1401 if (moniker1)
1402 IMoniker_Release(moniker1);
1403 if (moniker2)
1404 IMoniker_Release(moniker2);
1405 }
1406
1407 static void test_file_monikers(void)
1408 {
1409 static WCHAR wszFile[][30] = {
1410 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1411 {'\\', '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},
1412 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1413 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1414 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1415 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1416 * U+0100 .. = Latin extended-A
1417 */
1418 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1419 };
1420
1421 int i;
1422
1423 trace("ACP is %u\n", GetACP());
1424
1425 for (i = 0; i < COUNTOF(wszFile); ++i)
1426 {
1427 int j ;
1428 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1429 {
1430 wszFile[i][j] = 0;
1431 test_file_moniker(wszFile[i]);
1432 }
1433 }
1434 }
1435
1436 static void test_item_moniker(void)
1437 {
1438 HRESULT hr;
1439 IMoniker *moniker;
1440 DWORD moniker_type;
1441 DWORD hash;
1442 IBindCtx *bindctx;
1443 IMoniker *inverse;
1444 IUnknown *unknown;
1445 static const WCHAR wszDelimeter[] = {'!',0};
1446 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1447 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1448
1449 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1450 ok_ole_success(hr, CreateItemMoniker);
1451
1452 test_moniker("item moniker", moniker,
1453 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1454 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1455 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1456 expected_display_name);
1457
1458 /* Hashing */
1459
1460 hr = IMoniker_Hash(moniker, &hash);
1461 ok_ole_success(hr, IMoniker_Hash);
1462
1463 ok(hash == 0x73c,
1464 "Hash value != 0x73c, instead was 0x%08x\n",
1465 hash);
1466
1467 /* IsSystemMoniker test */
1468
1469 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1470 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1471
1472 ok(moniker_type == MKSYS_ITEMMONIKER,
1473 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1474 moniker_type);
1475
1476 hr = CreateBindCtx(0, &bindctx);
1477 ok_ole_success(hr, CreateBindCtx);
1478
1479 /* IsRunning test */
1480 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1481 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1482
1483 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1484 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1485
1486 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1487 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1488
1489 IBindCtx_Release(bindctx);
1490
1491 hr = IMoniker_Inverse(moniker, &inverse);
1492 ok_ole_success(hr, IMoniker_Inverse);
1493 IMoniker_Release(inverse);
1494
1495 IMoniker_Release(moniker);
1496 }
1497
1498 static void test_anti_moniker(void)
1499 {
1500 HRESULT hr;
1501 IMoniker *moniker;
1502 DWORD moniker_type;
1503 DWORD hash;
1504 IBindCtx *bindctx;
1505 FILETIME filetime;
1506 IMoniker *inverse;
1507 IUnknown *unknown;
1508 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1509
1510 hr = CreateAntiMoniker(&moniker);
1511 ok_ole_success(hr, CreateAntiMoniker);
1512 if (!moniker) return;
1513
1514 test_moniker("anti moniker", moniker,
1515 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1516 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1517 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1518 expected_display_name);
1519
1520 /* Hashing */
1521 hr = IMoniker_Hash(moniker, &hash);
1522 ok_ole_success(hr, IMoniker_Hash);
1523 ok(hash == 0x80000001,
1524 "Hash value != 0x80000001, instead was 0x%08x\n",
1525 hash);
1526
1527 /* IsSystemMoniker test */
1528 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1529 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1530 ok(moniker_type == MKSYS_ANTIMONIKER,
1531 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1532 moniker_type);
1533
1534 hr = IMoniker_Inverse(moniker, &inverse);
1535 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1536 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1537
1538 hr = CreateBindCtx(0, &bindctx);
1539 ok_ole_success(hr, CreateBindCtx);
1540
1541 /* IsRunning test */
1542 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1543 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1544
1545 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1546 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1547
1548 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1549 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1550
1551 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1552 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1553
1554 IBindCtx_Release(bindctx);
1555
1556 IMoniker_Release(moniker);
1557 }
1558
1559 static void test_generic_composite_moniker(void)
1560 {
1561 HRESULT hr;
1562 IMoniker *moniker;
1563 IMoniker *moniker1;
1564 IMoniker *moniker2;
1565 DWORD moniker_type;
1566 DWORD hash;
1567 IBindCtx *bindctx;
1568 FILETIME filetime;
1569 IMoniker *inverse;
1570 IUnknown *unknown;
1571 static const WCHAR wszDelimeter1[] = {'!',0};
1572 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1573 static const WCHAR wszDelimeter2[] = {'#',0};
1574 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1575 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1576
1577 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1578 ok_ole_success(hr, CreateItemMoniker);
1579 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1580 ok_ole_success(hr, CreateItemMoniker);
1581 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1582 ok_ole_success(hr, CreateGenericComposite);
1583
1584 test_moniker("generic composite moniker", moniker,
1585 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1586 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1587 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1588 expected_display_name);
1589
1590 /* Hashing */
1591
1592 hr = IMoniker_Hash(moniker, &hash);
1593 ok_ole_success(hr, IMoniker_Hash);
1594
1595 ok(hash == 0xd87,
1596 "Hash value != 0xd87, instead was 0x%08x\n",
1597 hash);
1598
1599 /* IsSystemMoniker test */
1600
1601 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1602 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1603
1604 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1605 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1606 moniker_type);
1607
1608 hr = CreateBindCtx(0, &bindctx);
1609 ok_ole_success(hr, CreateBindCtx);
1610
1611 /* IsRunning test */
1612 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1613 todo_wine
1614 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1615
1616 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1617 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1618
1619 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1620 todo_wine
1621 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1622
1623 todo_wine
1624 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1625 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1626
1627 IBindCtx_Release(bindctx);
1628
1629 hr = IMoniker_Inverse(moniker, &inverse);
1630 ok_ole_success(hr, IMoniker_Inverse);
1631 IMoniker_Release(inverse);
1632
1633 IMoniker_Release(moniker);
1634 }
1635
1636 static void test_pointer_moniker(void)
1637 {
1638 HRESULT hr;
1639 IMoniker *moniker;
1640 DWORD moniker_type;
1641 DWORD hash;
1642 IBindCtx *bindctx;
1643 FILETIME filetime;
1644 IMoniker *inverse;
1645 IUnknown *unknown;
1646 IStream *stream;
1647 IROTData *rotdata;
1648 LPOLESTR display_name;
1649
1650 cLocks = 0;
1651
1652 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1653 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1654
1655 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1656 ok_ole_success(hr, CreatePointerMoniker);
1657 if (!moniker) return;
1658
1659 ok_more_than_one_lock();
1660
1661 /* Display Name */
1662
1663 hr = CreateBindCtx(0, &bindctx);
1664 ok_ole_success(hr, CreateBindCtx);
1665
1666 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1667 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1668
1669 IBindCtx_Release(bindctx);
1670
1671 hr = IMoniker_IsDirty(moniker);
1672 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1673
1674 /* IROTData::GetComparisonData test */
1675
1676 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1677 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1678
1679 /* Saving */
1680
1681 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1682 ok_ole_success(hr, CreateStreamOnHGlobal);
1683
1684 hr = IMoniker_Save(moniker, stream, TRUE);
1685 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1686
1687 IStream_Release(stream);
1688
1689 /* Hashing */
1690 hr = IMoniker_Hash(moniker, &hash);
1691 ok_ole_success(hr, IMoniker_Hash);
1692 ok(hash == (DWORD)&Test_ClassFactory,
1693 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1694 (DWORD)&Test_ClassFactory, hash);
1695
1696 /* IsSystemMoniker test */
1697 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1698 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1699 ok(moniker_type == MKSYS_POINTERMONIKER,
1700 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1701 moniker_type);
1702
1703 hr = IMoniker_Inverse(moniker, &inverse);
1704 ok_ole_success(hr, IMoniker_Inverse);
1705 IMoniker_Release(inverse);
1706
1707 hr = CreateBindCtx(0, &bindctx);
1708 ok_ole_success(hr, CreateBindCtx);
1709
1710 /* IsRunning test */
1711 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1712 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1713
1714 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1715 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1716
1717 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1718 ok_ole_success(hr, IMoniker_BindToObject);
1719 IUnknown_Release(unknown);
1720
1721 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1722 ok_ole_success(hr, IMoniker_BindToStorage);
1723 IUnknown_Release(unknown);
1724
1725 IMoniker_Release(moniker);
1726
1727 ok_no_locks();
1728
1729 hr = CreatePointerMoniker(NULL, &moniker);
1730 ok_ole_success(hr, CreatePointerMoniker);
1731
1732 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1733 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1734
1735 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1736 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1737
1738 IBindCtx_Release(bindctx);
1739
1740 IMoniker_Release(moniker);
1741 }
1742
1743 static void test_bind_context(void)
1744 {
1745 HRESULT hr;
1746 IBindCtx *pBindCtx;
1747 IEnumString *pEnumString;
1748 BIND_OPTS2 bind_opts;
1749 HeapUnknown *unknown;
1750 HeapUnknown *unknown2;
1751 IUnknown *param_obj;
1752 ULONG refs;
1753 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1754 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1755
1756 hr = CreateBindCtx(0, NULL);
1757 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1758
1759 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1760 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1761
1762 hr = CreateBindCtx(0, &pBindCtx);
1763 ok_ole_success(hr, "CreateBindCtx");
1764
1765 bind_opts.cbStruct = -1;
1766 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1767 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1768 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1769
1770 bind_opts.cbStruct = sizeof(BIND_OPTS);
1771 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1772 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1773 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1774
1775 bind_opts.cbStruct = sizeof(bind_opts);
1776 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1777 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1778 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1779 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1780 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1781 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1782 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1783 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1784 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1785 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1786 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1787
1788 bind_opts.cbStruct = -1;
1789 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1790 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1791
1792 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1793 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1794
1795 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1796 unknown->lpVtbl = &HeapUnknown_Vtbl;
1797 unknown->refs = 1;
1798 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1799 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1800
1801 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1802 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1803 IUnknown_Release(param_obj);
1804
1805 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1806 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1807 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1808
1809 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1810 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1811
1812 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1813 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1814 ok(!pEnumString, "pEnumString should be NULL\n");
1815
1816 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1817 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1818
1819 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1820 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1821
1822 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1823 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1824 unknown2->refs = 1;
1825 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1826 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1827
1828 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1829 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1830
1831 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1832 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1833
1834 IBindCtx_Release(pBindCtx);
1835
1836 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1837 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1838
1839 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1840 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1841 }
1842
1843 START_TEST(moniker)
1844 {
1845 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1846
1847 test_ROT();
1848 test_ROT_multiple_entries();
1849 test_MkParseDisplayName();
1850 test_class_moniker();
1851 test_file_monikers();
1852 test_item_moniker();
1853 test_anti_moniker();
1854 test_generic_composite_moniker();
1855 test_pointer_moniker();
1856
1857 /* FIXME: test moniker creation funcs and parsing other moniker formats */
1858
1859 test_bind_context();
1860
1861 CoUninitialize();
1862 }