Sync advapi32, comctl32, crypt32, cryptui, cryptnet, fusion, gdi32, gdiplus, hlink...
[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 static const WCHAR wszEmpty[] = {0};
818 char szDisplayNameFile[256];
819 WCHAR wszDisplayNameFile[256];
820 int i, len;
821
822 const struct
823 {
824 LPBC *ppbc;
825 LPCOLESTR szDisplayName;
826 LPDWORD pchEaten;
827 LPMONIKER *ppmk;
828 } invalid_parameters[] =
829 {
830 {NULL, NULL, NULL, NULL},
831 {NULL, NULL, NULL, &pmk},
832 {NULL, NULL, &eaten, NULL},
833 {NULL, NULL, &eaten, &pmk},
834 {NULL, wszEmpty, NULL, NULL},
835 {NULL, wszEmpty, NULL, &pmk},
836 {NULL, wszEmpty, &eaten, NULL},
837 {NULL, wszEmpty, &eaten, &pmk},
838 {&pbc, NULL, NULL, NULL},
839 {&pbc, NULL, NULL, &pmk},
840 {&pbc, NULL, &eaten, NULL},
841 {&pbc, NULL, &eaten, &pmk},
842 {&pbc, wszEmpty, NULL, NULL},
843 {&pbc, wszEmpty, NULL, &pmk},
844 {&pbc, wszEmpty, &eaten, NULL},
845 {&pbc, wszEmpty, &eaten, &pmk},
846 };
847
848 hr = CreateBindCtx(0, &pbc);
849 ok_ole_success(hr, CreateBindCtx);
850
851 for (i = 0; i < sizeof(invalid_parameters)/sizeof(invalid_parameters[0]); i++)
852 {
853 eaten = 0xdeadbeef;
854 pmk = (IMoniker *)0xdeadbeef;
855 hr = MkParseDisplayName(invalid_parameters[i].ppbc ? *invalid_parameters[i].ppbc : NULL,
856 invalid_parameters[i].szDisplayName,
857 invalid_parameters[i].pchEaten,
858 invalid_parameters[i].ppmk);
859 ok(hr == E_INVALIDARG, "[%d] MkParseDisplayName should have failed with E_INVALIDARG instead of 0x%08x\n", i, hr);
860 ok(eaten == 0xdeadbeef, "[%d] Processed character count should have been 0xdeadbeef instead of %u\n", i, eaten);
861 ok(pmk == (IMoniker *)0xdeadbeef, "[%d] Output moniker pointer should have been 0xdeadbeef instead of %p\n", i, pmk);
862 }
863
864 eaten = 0xdeadbeef;
865 pmk = (IMoniker *)0xdeadbeef;
866 hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
867 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
868 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
869 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
870 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
871
872 /* no special handling of "clsid:" without the string form of the clsid
873 * following */
874 eaten = 0xdeadbeef;
875 pmk = (IMoniker *)0xdeadbeef;
876 hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
877 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
878 "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
879 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
880 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
881
882 /* shows clsid has higher precedence than a running object */
883 hr = CreateFileMoniker(wszDisplayName, &pmk);
884 ok_ole_success(hr, CreateFileMoniker);
885 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
886 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
887 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
888 ok_ole_success(hr, IRunningObjectTable_Register);
889 IMoniker_Release(pmk);
890 pmk = NULL;
891 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
892 ok_ole_success(hr, MkParseDisplayName);
893 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1,
894 "Processed character count should have been 43 instead of %u\n", eaten);
895 if (pmk)
896 {
897 IMoniker_IsSystemMoniker(pmk, &moniker_type);
898 ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
899 IMoniker_Release(pmk);
900 }
901 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
902 ok_ole_success(hr, IRunningObjectTable_Revoke);
903 IRunningObjectTable_Release(pprot);
904
905 hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
906 ok_ole_success(hr, CreateFileMoniker);
907 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
908 ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
909 hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
910 ok_ole_success(hr, IRunningObjectTable_Register);
911 IMoniker_Release(pmk);
912 pmk = NULL;
913 hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
914 ok_ole_success(hr, MkParseDisplayName);
915 ok(eaten == sizeof(wszDisplayNameRunning)/sizeof(WCHAR) - 1,
916 "Processed character count should have been 15 instead of %u\n", eaten);
917 if (pmk)
918 {
919 IMoniker_IsSystemMoniker(pmk, &moniker_type);
920 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
921 IMoniker_Release(pmk);
922 }
923 hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
924 ok_ole_success(hr, IRunningObjectTable_Revoke);
925 IRunningObjectTable_Release(pprot);
926
927 hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
928 ok_ole_success(hr, CoRegisterClassObject);
929
930 expected_display_name = wszDisplayNameProgId1;
931 hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
932 ok_ole_success(hr, MkParseDisplayName);
933 ok(eaten == sizeof(wszDisplayNameProgId1)/sizeof(WCHAR) - 1,
934 "Processed character count should have been 8 instead of %u\n", eaten);
935 if (pmk)
936 {
937 IMoniker_IsSystemMoniker(pmk, &moniker_type);
938 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
939 IMoniker_Release(pmk);
940 }
941
942 expected_display_name = wszDisplayNameProgId2;
943 hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
944 ok_ole_success(hr, MkParseDisplayName);
945 ok(eaten == sizeof(wszDisplayNameProgId2)/sizeof(WCHAR) - 1,
946 "Processed character count should have been 8 instead of %u\n", eaten);
947 if (pmk)
948 {
949 IMoniker_IsSystemMoniker(pmk, &moniker_type);
950 ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
951 IMoniker_Release(pmk);
952 }
953
954 eaten = 0xdeadbeef;
955 pmk = (IMoniker *)0xdeadbeef;
956 hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
957 ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
958 "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
959 ok(eaten == 0, "Processed character count should have been 0 instead of %u\n", eaten);
960 ok(pmk == NULL, "Output moniker pointer should have been NULL instead of %p\n", pmk);
961
962 hr = CoRevokeClassObject(pdwReg1);
963 ok_ole_success(hr, CoRevokeClassObject);
964
965 GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
966 strcat(szDisplayNameFile, "\\kernel32.dll");
967 len = MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
968 hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
969 ok_ole_success(hr, MkParseDisplayName);
970 ok(eaten == len - 1, "Processed character count should have been %d instead of %u\n", len - 1, eaten);
971 if (pmk)
972 {
973 IMoniker_IsSystemMoniker(pmk, &moniker_type);
974 ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
975 IMoniker_Release(pmk);
976 }
977
978 hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
979 ok_ole_success(hr, MkParseDisplayName);
980 ok(eaten == sizeof(wszDisplayName)/sizeof(WCHAR) - 1, "Processed character count should have been 43 instead of %u\n", eaten);
981
982 if (pmk)
983 {
984 hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
985 ok_ole_success(hr, IMoniker_BindToObject);
986
987 if (SUCCEEDED(hr))
988 IUnknown_Release(object);
989 IMoniker_Release(pmk);
990 }
991 IBindCtx_Release(pbc);
992
993 /* Test the EnumMoniker interface */
994 hr = CreateBindCtx(0, &pbc);
995 ok_ole_success(hr, CreateBindCtx);
996
997 hr = CreateFileMoniker(wszFileName1, &pmk1);
998 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
999 hr = CreateFileMoniker(wszFileName2, &pmk2);
1000 ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
1001 hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
1002 ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
1003
1004 /* Check EnumMoniker before registering */
1005 hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
1006 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1007 hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
1008 /* Register a couple of Monikers and check is ok */
1009 ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
1010 hr = MK_E_NOOBJECT;
1011
1012 matchCnt = count_moniker_matches(pbc, spEM1);
1013 trace("Number of matches is %i\n", matchCnt);
1014
1015 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1016 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
1017 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
1018 hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
1019
1020 trace("IROT::Register\n");
1021 grflags=0;
1022 grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
1023 hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
1024 ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
1025 pprot, grflags, lpEM1, pmk2, pdwReg2);
1026
1027 hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
1028 ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
1029
1030 matchCnt = count_moniker_matches(pbc, spEM2);
1031 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1032
1033 trace("IEnumMoniker::Clone\n");
1034 IEnumMoniker_Clone(spEM2, &spEM3);
1035
1036 matchCnt = count_moniker_matches(pbc, spEM3);
1037 ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
1038 trace("IEnumMoniker::Reset\n");
1039 IEnumMoniker_Reset(spEM3);
1040
1041 matchCnt = count_moniker_matches(pbc, spEM3);
1042 ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
1043
1044 IRunningObjectTable_Revoke(pprot,pdwReg1);
1045 IRunningObjectTable_Revoke(pprot,pdwReg2);
1046 IUnknown_Release(lpEM1);
1047 IEnumMoniker_Release(spEM1);
1048 IEnumMoniker_Release(spEM2);
1049 IEnumMoniker_Release(spEM3);
1050 IMoniker_Release(pmk1);
1051 IMoniker_Release(pmk2);
1052 IRunningObjectTable_Release(pprot);
1053
1054 IBindCtx_Release(pbc);
1055 }
1056
1057 static const LARGE_INTEGER llZero;
1058
1059 static const BYTE expected_class_moniker_marshal_data[] =
1060 {
1061 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1062 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1063 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1064 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1065 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1066 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1067 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1068 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1069 0x00,0x00,0x00,0x00,
1070 };
1071
1072 static const BYTE expected_class_moniker_saved_data[] =
1073 {
1074 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1075 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1076 0x00,0x00,0x00,0x00,
1077 };
1078
1079 static const BYTE expected_class_moniker_comparison_data[] =
1080 {
1081 0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1082 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1083 0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
1084 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1085 };
1086
1087 static const WCHAR expected_class_moniker_display_name[] =
1088 {
1089 'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
1090 '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
1091 '0','0','0','0','4','6',':',0
1092 };
1093
1094 static const BYTE expected_item_moniker_comparison_data[] =
1095 {
1096 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1097 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1098 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1099 0x54,0x00,0x00,0x00,
1100 };
1101
1102 static const BYTE expected_item_moniker_saved_data[] =
1103 {
1104 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1105 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1106 };
1107
1108 static const BYTE expected_item_moniker_marshal_data[] =
1109 {
1110 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1111 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1112 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1113 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1114 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1115 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1116 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1117 0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1118 };
1119
1120 static const BYTE expected_anti_moniker_marshal_data[] =
1121 {
1122 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1123 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1124 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1125 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1126 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1127 0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1128 0x01,0x00,0x00,0x00,
1129 };
1130
1131 static const BYTE expected_anti_moniker_saved_data[] =
1132 {
1133 0x01,0x00,0x00,0x00,
1134 };
1135
1136 static const BYTE expected_anti_moniker_comparison_data[] =
1137 {
1138 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1139 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1140 0x01,0x00,0x00,0x00,
1141 };
1142
1143 static const BYTE expected_gc_moniker_marshal_data[] =
1144 {
1145 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1146 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1147 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1148 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1149 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1150 0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1151 0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1152 0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1153 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1154 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1155 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1156 0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1157 0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1158 0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1159 0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1160 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1161 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1162 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1163 0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1164 0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1165 0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1166 0x00,0x57,0x69,0x6e,0x65,0x00,
1167 };
1168
1169 static const BYTE expected_gc_moniker_saved_data[] =
1170 {
1171 0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1172 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1173 0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1174 0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1175 0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1176 0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1177 0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1178 0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1179 0x65,0x00,
1180 };
1181
1182 static const BYTE expected_gc_moniker_comparison_data[] =
1183 {
1184 0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1185 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1186 0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1187 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1188 0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1189 0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1190 0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1191 0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1192 0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1193 };
1194
1195 static void test_moniker(
1196 const char *testname, IMoniker *moniker,
1197 const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1198 const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1199 const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1200 LPCWSTR expected_display_name)
1201 {
1202 IStream * stream;
1203 IROTData * rotdata;
1204 HRESULT hr;
1205 HGLOBAL hglobal;
1206 LPBYTE moniker_data;
1207 DWORD moniker_size;
1208 DWORD i;
1209 BOOL same;
1210 BYTE buffer[128];
1211 IMoniker * moniker_proxy;
1212 LPOLESTR display_name;
1213 IBindCtx *bindctx;
1214
1215 hr = IMoniker_IsDirty(moniker);
1216 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1217
1218 /* Display Name */
1219
1220 hr = CreateBindCtx(0, &bindctx);
1221 ok_ole_success(hr, CreateBindCtx);
1222
1223 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1224 ok_ole_success(hr, IMoniker_GetDisplayName);
1225 ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1226
1227 CoTaskMemFree(display_name);
1228 IBindCtx_Release(bindctx);
1229
1230 hr = IMoniker_IsDirty(moniker);
1231 ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1232
1233 /* IROTData::GetComparisonData test */
1234
1235 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1236 ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1237
1238 hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1239 ok_ole_success(hr, IROTData_GetComparisonData);
1240
1241 if (hr != S_OK) moniker_size = 0;
1242
1243 /* first check we have the right amount of data */
1244 ok(moniker_size == sizeof_expected_moniker_comparison_data,
1245 "%s: Size of comparison data differs (expected %d, actual %d)\n",
1246 testname, sizeof_expected_moniker_comparison_data, moniker_size);
1247
1248 /* then do a byte-by-byte comparison */
1249 same = TRUE;
1250 for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1251 {
1252 if (expected_moniker_comparison_data[i] != buffer[i])
1253 {
1254 same = FALSE;
1255 break;
1256 }
1257 }
1258
1259 ok(same, "%s: Comparison data differs\n", testname);
1260 if (!same)
1261 {
1262 for (i = 0; i < moniker_size; i++)
1263 {
1264 if (i % 8 == 0) printf(" ");
1265 printf("0x%02x,", buffer[i]);
1266 if (i % 8 == 7) printf("\n");
1267 }
1268 printf("\n");
1269 }
1270
1271 IROTData_Release(rotdata);
1272
1273 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1274
1275 /* Saving */
1276
1277 hr = IMoniker_Save(moniker, stream, TRUE);
1278 ok_ole_success(hr, IMoniker_Save);
1279
1280 hr = GetHGlobalFromStream(stream, &hglobal);
1281 ok_ole_success(hr, GetHGlobalFromStream);
1282
1283 moniker_size = GlobalSize(hglobal);
1284
1285 moniker_data = GlobalLock(hglobal);
1286
1287 /* first check we have the right amount of data */
1288 ok(moniker_size == round_global_size(sizeof_expected_moniker_saved_data),
1289 "%s: Size of saved data differs (expected %d, actual %d)\n",
1290 testname, (DWORD)round_global_size(sizeof_expected_moniker_saved_data), moniker_size);
1291
1292 /* then do a byte-by-byte comparison */
1293 same = TRUE;
1294 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_saved_data)); i++)
1295 {
1296 if (expected_moniker_saved_data[i] != moniker_data[i])
1297 {
1298 same = FALSE;
1299 break;
1300 }
1301 }
1302
1303 ok(same, "%s: Saved data differs\n", testname);
1304 if (!same)
1305 {
1306 for (i = 0; i < moniker_size; i++)
1307 {
1308 if (i % 8 == 0) printf(" ");
1309 printf("0x%02x,", moniker_data[i]);
1310 if (i % 8 == 7) printf("\n");
1311 }
1312 printf("\n");
1313 }
1314
1315 GlobalUnlock(hglobal);
1316
1317 IStream_Release(stream);
1318
1319 /* Marshaling tests */
1320
1321 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1322 ok_ole_success(hr, CreateStreamOnHGlobal);
1323
1324 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1325 ok_ole_success(hr, CoMarshalInterface);
1326
1327 hr = GetHGlobalFromStream(stream, &hglobal);
1328 ok_ole_success(hr, GetHGlobalFromStream);
1329
1330 moniker_size = GlobalSize(hglobal);
1331
1332 moniker_data = GlobalLock(hglobal);
1333
1334 /* first check we have the right amount of data */
1335 ok(moniker_size == round_global_size(sizeof_expected_moniker_marshal_data),
1336 "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1337 testname, (DWORD)round_global_size(sizeof_expected_moniker_marshal_data), moniker_size);
1338
1339 /* then do a byte-by-byte comparison */
1340 same = TRUE;
1341 if (expected_moniker_marshal_data)
1342 {
1343 for (i = 0; i < min(moniker_size, round_global_size(sizeof_expected_moniker_marshal_data)); i++)
1344 {
1345 if (expected_moniker_marshal_data[i] != moniker_data[i])
1346 {
1347 same = FALSE;
1348 break;
1349 }
1350 }
1351 }
1352
1353 ok(same, "%s: Marshaled data differs\n", testname);
1354 if (!same)
1355 {
1356 for (i = 0; i < moniker_size; i++)
1357 {
1358 if (i % 8 == 0) printf(" ");
1359 printf("0x%02x,", moniker_data[i]);
1360 if (i % 8 == 7) printf("\n");
1361 }
1362 printf("\n");
1363 }
1364
1365 GlobalUnlock(hglobal);
1366
1367 IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1368 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1369 ok_ole_success(hr, CoUnmarshalInterface);
1370
1371 IStream_Release(stream);
1372 IMoniker_Release(moniker_proxy);
1373 }
1374
1375 static void test_class_moniker(void)
1376 {
1377 HRESULT hr;
1378 IMoniker *moniker;
1379 DWORD moniker_type;
1380 DWORD hash;
1381 IBindCtx *bindctx;
1382 IMoniker *inverse;
1383 IUnknown *unknown;
1384 FILETIME filetime;
1385
1386 hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1387 ok_ole_success(hr, CreateClassMoniker);
1388 if (!moniker) return;
1389
1390 test_moniker("class moniker", moniker,
1391 expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1392 expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1393 expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1394 expected_class_moniker_display_name);
1395
1396 /* Hashing */
1397
1398 hr = IMoniker_Hash(moniker, &hash);
1399 ok_ole_success(hr, IMoniker_Hash);
1400
1401 ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1402 "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1403 hash);
1404
1405 /* IsSystemMoniker test */
1406
1407 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1408 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1409
1410 ok(moniker_type == MKSYS_CLASSMONIKER,
1411 "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1412 moniker_type);
1413
1414 hr = CreateBindCtx(0, &bindctx);
1415 ok_ole_success(hr, CreateBindCtx);
1416
1417 /* IsRunning test */
1418 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1419 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1420
1421 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1422 ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1423
1424 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1425 ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1426
1427 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1428 ok_ole_success(hr, IMoniker_BindToObject);
1429 IUnknown_Release(unknown);
1430
1431 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1432 ok_ole_success(hr, IMoniker_BindToStorage);
1433 IUnknown_Release(unknown);
1434
1435 IBindCtx_Release(bindctx);
1436
1437 hr = IMoniker_Inverse(moniker, &inverse);
1438 ok_ole_success(hr, IMoniker_Inverse);
1439 IMoniker_Release(inverse);
1440
1441 IMoniker_Release(moniker);
1442 }
1443
1444 static void test_file_moniker(WCHAR* path)
1445 {
1446 IStream *stream;
1447 IMoniker *moniker1 = NULL, *moniker2 = NULL;
1448 HRESULT hr;
1449
1450 hr = CreateFileMoniker(path, &moniker1);
1451 ok_ole_success(hr, CreateFileMoniker);
1452
1453 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1454
1455 /* Marshal */
1456 hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1457 ok_ole_success(hr, CoMarshalInterface);
1458
1459 /* Rewind */
1460 hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1461 ok_ole_success(hr, IStream_Seek);
1462
1463 /* Unmarshal */
1464 hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1465 ok_ole_success(hr, CoUnmarshalInterface);
1466
1467 hr = IMoniker_IsEqual(moniker1, moniker2);
1468 ok_ole_success(hr, IsEqual);
1469
1470 IStream_Release(stream);
1471 if (moniker1)
1472 IMoniker_Release(moniker1);
1473 if (moniker2)
1474 IMoniker_Release(moniker2);
1475 }
1476
1477 static void test_file_monikers(void)
1478 {
1479 static WCHAR wszFile[][30] = {
1480 {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1481 {'\\', '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},
1482 /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1483 {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1484 /* U+2020 = DAGGER = 0x86 (1252) = 0x813f (932)
1485 * U+20AC = EURO SIGN = 0x80 (1252) = undef (932)
1486 * U+0100 .. = Latin extended-A
1487 */
1488 {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c, 0},
1489 };
1490
1491 int i;
1492
1493 trace("ACP is %u\n", GetACP());
1494
1495 for (i = 0; i < COUNTOF(wszFile); ++i)
1496 {
1497 int j ;
1498 if (i == 2)
1499 {
1500 BOOL used;
1501 WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS, wszFile[i], -1, NULL, 0, NULL, &used );
1502 if (used)
1503 {
1504 skip("string 2 doesn't round trip in codepage %u\n", GetACP() );
1505 continue;
1506 }
1507 }
1508 for (j = lstrlenW(wszFile[i]); j > 0; --j)
1509 {
1510 wszFile[i][j] = 0;
1511 test_file_moniker(wszFile[i]);
1512 }
1513 }
1514 }
1515
1516 static void test_item_moniker(void)
1517 {
1518 HRESULT hr;
1519 IMoniker *moniker;
1520 DWORD moniker_type;
1521 DWORD hash;
1522 IBindCtx *bindctx;
1523 IMoniker *inverse;
1524 IUnknown *unknown;
1525 static const WCHAR wszDelimeter[] = {'!',0};
1526 static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1527 static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1528
1529 hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1530 ok_ole_success(hr, CreateItemMoniker);
1531
1532 test_moniker("item moniker", moniker,
1533 expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1534 expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1535 expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1536 expected_display_name);
1537
1538 /* Hashing */
1539
1540 hr = IMoniker_Hash(moniker, &hash);
1541 ok_ole_success(hr, IMoniker_Hash);
1542
1543 ok(hash == 0x73c,
1544 "Hash value != 0x73c, instead was 0x%08x\n",
1545 hash);
1546
1547 /* IsSystemMoniker test */
1548
1549 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1550 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1551
1552 ok(moniker_type == MKSYS_ITEMMONIKER,
1553 "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1554 moniker_type);
1555
1556 hr = CreateBindCtx(0, &bindctx);
1557 ok_ole_success(hr, CreateBindCtx);
1558
1559 /* IsRunning test */
1560 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1561 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1562
1563 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1564 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1565
1566 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1567 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1568
1569 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1570 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1571
1572 IBindCtx_Release(bindctx);
1573
1574 hr = IMoniker_Inverse(moniker, &inverse);
1575 ok_ole_success(hr, IMoniker_Inverse);
1576 IMoniker_Release(inverse);
1577
1578 IMoniker_Release(moniker);
1579 }
1580
1581 static void test_anti_moniker(void)
1582 {
1583 HRESULT hr;
1584 IMoniker *moniker;
1585 DWORD moniker_type;
1586 DWORD hash;
1587 IBindCtx *bindctx;
1588 FILETIME filetime;
1589 IMoniker *inverse;
1590 IUnknown *unknown;
1591 static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1592
1593 hr = CreateAntiMoniker(&moniker);
1594 ok_ole_success(hr, CreateAntiMoniker);
1595 if (!moniker) return;
1596
1597 test_moniker("anti moniker", moniker,
1598 expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1599 expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1600 expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1601 expected_display_name);
1602
1603 /* Hashing */
1604 hr = IMoniker_Hash(moniker, &hash);
1605 ok_ole_success(hr, IMoniker_Hash);
1606 ok(hash == 0x80000001,
1607 "Hash value != 0x80000001, instead was 0x%08x\n",
1608 hash);
1609
1610 /* IsSystemMoniker test */
1611 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1612 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1613 ok(moniker_type == MKSYS_ANTIMONIKER,
1614 "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1615 moniker_type);
1616
1617 hr = IMoniker_Inverse(moniker, &inverse);
1618 ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1619 ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1620
1621 hr = CreateBindCtx(0, &bindctx);
1622 ok_ole_success(hr, CreateBindCtx);
1623
1624 /* IsRunning test */
1625 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1626 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1627
1628 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1629 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1630
1631 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1632 ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1633
1634 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1635 ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1636
1637 IBindCtx_Release(bindctx);
1638
1639 IMoniker_Release(moniker);
1640 }
1641
1642 static void test_generic_composite_moniker(void)
1643 {
1644 HRESULT hr;
1645 IMoniker *moniker;
1646 IMoniker *moniker1;
1647 IMoniker *moniker2;
1648 DWORD moniker_type;
1649 DWORD hash;
1650 IBindCtx *bindctx;
1651 FILETIME filetime;
1652 IMoniker *inverse;
1653 IUnknown *unknown;
1654 static const WCHAR wszDelimeter1[] = {'!',0};
1655 static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1656 static const WCHAR wszDelimeter2[] = {'#',0};
1657 static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1658 static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1659
1660 hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1661 ok_ole_success(hr, CreateItemMoniker);
1662 hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1663 ok_ole_success(hr, CreateItemMoniker);
1664 hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1665 ok_ole_success(hr, CreateGenericComposite);
1666
1667 test_moniker("generic composite moniker", moniker,
1668 expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1669 expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1670 expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1671 expected_display_name);
1672
1673 /* Hashing */
1674
1675 hr = IMoniker_Hash(moniker, &hash);
1676 ok_ole_success(hr, IMoniker_Hash);
1677
1678 ok(hash == 0xd87,
1679 "Hash value != 0xd87, instead was 0x%08x\n",
1680 hash);
1681
1682 /* IsSystemMoniker test */
1683
1684 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1685 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1686
1687 ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1688 "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1689 moniker_type);
1690
1691 hr = CreateBindCtx(0, &bindctx);
1692 ok_ole_success(hr, CreateBindCtx);
1693
1694 /* IsRunning test */
1695 hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1696 ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1697
1698 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1699 todo_wine
1700 ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1701
1702 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1703 ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1704
1705 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1706 todo_wine
1707 ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1708
1709 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1710 ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1711
1712 IBindCtx_Release(bindctx);
1713
1714 hr = IMoniker_Inverse(moniker, &inverse);
1715 ok_ole_success(hr, IMoniker_Inverse);
1716 IMoniker_Release(inverse);
1717
1718 IMoniker_Release(moniker);
1719 }
1720
1721 static void test_pointer_moniker(void)
1722 {
1723 HRESULT hr;
1724 IMoniker *moniker;
1725 DWORD moniker_type;
1726 DWORD hash;
1727 IBindCtx *bindctx;
1728 FILETIME filetime;
1729 IMoniker *inverse;
1730 IUnknown *unknown;
1731 IStream *stream;
1732 IROTData *rotdata;
1733 LPOLESTR display_name;
1734
1735 cLocks = 0;
1736
1737 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1738 ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1739
1740 hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1741 ok_ole_success(hr, CreatePointerMoniker);
1742 if (!moniker) return;
1743
1744 ok_more_than_one_lock();
1745
1746 /* Display Name */
1747
1748 hr = CreateBindCtx(0, &bindctx);
1749 ok_ole_success(hr, CreateBindCtx);
1750
1751 hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1752 ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1753
1754 IBindCtx_Release(bindctx);
1755
1756 hr = IMoniker_IsDirty(moniker);
1757 ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1758
1759 /* IROTData::GetComparisonData test */
1760
1761 hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1762 ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1763
1764 /* Saving */
1765
1766 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1767 ok_ole_success(hr, CreateStreamOnHGlobal);
1768
1769 hr = IMoniker_Save(moniker, stream, TRUE);
1770 ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1771
1772 IStream_Release(stream);
1773
1774 /* Hashing */
1775 hr = IMoniker_Hash(moniker, &hash);
1776 ok_ole_success(hr, IMoniker_Hash);
1777 ok(hash == (DWORD)&Test_ClassFactory,
1778 "Hash value should have been 0x%08x, instead of 0x%08x\n",
1779 (DWORD)&Test_ClassFactory, hash);
1780
1781 /* IsSystemMoniker test */
1782 hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1783 ok_ole_success(hr, IMoniker_IsSystemMoniker);
1784 ok(moniker_type == MKSYS_POINTERMONIKER,
1785 "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1786 moniker_type);
1787
1788 hr = IMoniker_Inverse(moniker, &inverse);
1789 ok_ole_success(hr, IMoniker_Inverse);
1790 IMoniker_Release(inverse);
1791
1792 hr = CreateBindCtx(0, &bindctx);
1793 ok_ole_success(hr, CreateBindCtx);
1794
1795 /* IsRunning test */
1796 hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1797 ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1798
1799 hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1800 ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1801
1802 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1803 ok_ole_success(hr, IMoniker_BindToObject);
1804 IUnknown_Release(unknown);
1805
1806 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1807 ok_ole_success(hr, IMoniker_BindToStorage);
1808 IUnknown_Release(unknown);
1809
1810 IMoniker_Release(moniker);
1811
1812 ok_no_locks();
1813
1814 hr = CreatePointerMoniker(NULL, &moniker);
1815 ok_ole_success(hr, CreatePointerMoniker);
1816
1817 hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1818 ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1819
1820 hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1821 ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1822
1823 IBindCtx_Release(bindctx);
1824
1825 IMoniker_Release(moniker);
1826 }
1827
1828 static void test_bind_context(void)
1829 {
1830 HRESULT hr;
1831 IBindCtx *pBindCtx;
1832 IEnumString *pEnumString;
1833 BIND_OPTS2 bind_opts;
1834 HeapUnknown *unknown;
1835 HeapUnknown *unknown2;
1836 IUnknown *param_obj;
1837 ULONG refs;
1838 static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1839 static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1840
1841 hr = CreateBindCtx(0, NULL);
1842 ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1843
1844 hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1845 ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1846
1847 hr = CreateBindCtx(0, &pBindCtx);
1848 ok_ole_success(hr, "CreateBindCtx");
1849
1850 bind_opts.cbStruct = -1;
1851 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1852 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1853 ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1854 bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1855 "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1856
1857 bind_opts.cbStruct = sizeof(BIND_OPTS);
1858 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1859 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1860 ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1861
1862 bind_opts.cbStruct = sizeof(bind_opts);
1863 hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1864 ok_ole_success(hr, "IBindCtx_GetBindOptions");
1865 ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1866 ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1867 ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1868 ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1869 ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1870 ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1871 "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1872 ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1873 ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1874
1875 bind_opts.cbStruct = -1;
1876 hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1877 ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1878
1879 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1880 ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1881
1882 unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1883 unknown->lpVtbl = &HeapUnknown_Vtbl;
1884 unknown->refs = 1;
1885 hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1886 ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1887
1888 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1889 ok_ole_success(hr, "IBindCtx_GetObjectParam");
1890 IUnknown_Release(param_obj);
1891
1892 hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1893 ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1894 ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1895
1896 hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1897 ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1898
1899 hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1900 ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1901 ok(!pEnumString, "pEnumString should be NULL\n");
1902
1903 hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1904 ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1905
1906 hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1907 ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1908
1909 unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1910 unknown2->lpVtbl = &HeapUnknown_Vtbl;
1911 unknown2->refs = 1;
1912 hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1913 ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1914
1915 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1916 ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1917
1918 hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1919 ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1920
1921 IBindCtx_Release(pBindCtx);
1922
1923 refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1924 ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1925
1926 refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1927 ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1928 }
1929
1930 static void test_save_load_filemoniker(void)
1931 {
1932 IMoniker* pMk;
1933 IStream* pStm;
1934 HRESULT hr;
1935 ULARGE_INTEGER size;
1936 LARGE_INTEGER zero_pos, dead_pos, nulls_pos;
1937 DWORD some_val = 0xFEDCBA98;
1938 int i;
1939
1940 /* see FileMonikerImpl_Save docs */
1941 zero_pos.QuadPart = 0;
1942 dead_pos.QuadPart = sizeof(WORD) + sizeof(DWORD) + (lstrlenW(wszFileName1) + 1) + sizeof(WORD);
1943 nulls_pos.QuadPart = dead_pos.QuadPart + sizeof(WORD);
1944
1945 /* create the stream we're going to write to */
1946 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
1947 ok_ole_success(hr, "CreateStreamOnHGlobal");
1948
1949 size.u.LowPart = 128;
1950 hr = IStream_SetSize(pStm, size);
1951 ok_ole_success(hr, "IStream_SetSize");
1952
1953 /* create and save a moniker */
1954 hr = CreateFileMoniker(wszFileName1, &pMk);
1955 ok_ole_success(hr, "CreateFileMoniker");
1956
1957 hr = IMoniker_Save(pMk, pStm, TRUE);
1958 ok_ole_success(hr, "IMoniker_Save");
1959
1960 hr = IMoniker_Release(pMk);
1961 ok_ole_success(hr, "IMoniker_Release");
1962
1963 /* overwrite the constants with various values */
1964 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1965 ok_ole_success(hr, "IStream_Seek");
1966 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1967 ok_ole_success(hr, "IStream_Write");
1968
1969 hr = IStream_Seek(pStm, dead_pos, STREAM_SEEK_SET, NULL);
1970 ok_ole_success(hr, "IStream_Seek");
1971 hr = IStream_Write(pStm, &some_val, sizeof(WORD), NULL);
1972 ok_ole_success(hr, "IStream_Write");
1973
1974 hr = IStream_Seek(pStm, nulls_pos, STREAM_SEEK_SET, NULL);
1975 ok_ole_success(hr, "IStream_Seek");
1976 for(i = 0; i < 5; ++i){
1977 hr = IStream_Write(pStm, &some_val, sizeof(DWORD), NULL);
1978 ok_ole_success(hr, "IStream_Write");
1979 }
1980
1981 /* go back to the start of the stream */
1982 hr = IStream_Seek(pStm, zero_pos, STREAM_SEEK_SET, NULL);
1983 ok_ole_success(hr, "IStream_Seek");
1984
1985 /* create a new moniker and load into it */
1986 hr = CreateFileMoniker(wszFileName1, &pMk);
1987 ok_ole_success(hr, "CreateFileMoniker");
1988
1989 hr = IMoniker_Load(pMk, pStm);
1990 ok_ole_success(hr, "IMoniker_Load");
1991
1992 hr = IMoniker_Release(pMk);
1993 ok_ole_success(hr, "IMoniker_Release");
1994
1995 hr = IStream_Release(pStm);
1996 ok_ole_success(hr, "IStream_Release");
1997 }
1998
1999 START_TEST(moniker)
2000 {
2001 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2002
2003 test_ROT();
2004 test_ROT_multiple_entries();
2005 test_MkParseDisplayName();
2006 test_class_moniker();
2007 test_file_monikers();
2008 test_item_moniker();
2009 test_anti_moniker();
2010 test_generic_composite_moniker();
2011 test_pointer_moniker();
2012 test_save_load_filemoniker();
2013
2014 /* FIXME: test moniker creation funcs and parsing other moniker formats */
2015
2016 test_bind_context();
2017
2018 CoUninitialize();
2019 }