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