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