shell32: Add a test for ABM_GETTASKBARPOS.
[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     todo_wine { /* only fails because of lack of IMoniker marshaling */
575     ok_ole_success(hr, IRunningObjectTable_Register);
576     }
577     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
578
579     todo_wine { /* only fails because of lack of IMoniker marshaling */
580     ok_more_than_one_lock();
581     }
582
583     expected_method_list = methods_isrunning_no_ROTData;
584     hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
585     todo_wine { /* only fails because of lack of IMoniker marshaling */
586     ok_ole_success(hr, IRunningObjectTable_IsRunning);
587     }
588     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
589
590     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
591     todo_wine { /* only fails because of lack of IMoniker marshaling */
592     ok_ole_success(hr, IRunningObjectTable_Revoke);
593     }
594
595     ok_no_locks();
596
597     expected_method_list = methods_register;
598     /* try with our own moniker */
599     hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
600         (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
601     todo_wine { /* only fails because of lack of IMoniker marshaling */
602     ok_ole_success(hr, IRunningObjectTable_Register);
603     }
604     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
605
606     todo_wine { /* only fails because of lack of IMoniker marshaling */
607     ok_more_than_one_lock();
608     }
609
610     expected_method_list = methods_isrunning;
611     hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
612     todo_wine { /* only fails because of lack of IMoniker marshaling */
613     ok_ole_success(hr, IRunningObjectTable_IsRunning);
614     }
615     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
616
617     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
618     todo_wine { /* only fails because of lack of IMoniker marshaling */
619     ok_ole_success(hr, IRunningObjectTable_Revoke);
620     }
621
622     ok_no_locks();
623
624     hr = CreateFileMoniker(wszFileName, &pMoniker);
625     ok_ole_success(hr, CreateClassMoniker);
626
627     /* test flags: 0 */
628     hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
629                                       pMoniker, &dwCookie);
630     ok_ole_success(hr, IRunningObjectTable_Register);
631
632     ok_more_than_one_lock();
633
634     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
635     ok_ole_success(hr, IRunningObjectTable_Revoke);
636
637     ok_no_locks();
638
639     /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
640     hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
641         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
642     ok_ole_success(hr, IRunningObjectTable_Register);
643
644     ok_more_than_one_lock();
645
646     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
647     ok_ole_success(hr, IRunningObjectTable_Revoke);
648
649     ok_no_locks();
650
651     /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
652     /* only succeeds when process is started by SCM and has LocalService
653      * or RunAs AppId values */
654     hr = IRunningObjectTable_Register(pROT,
655         ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
656         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
657     todo_wine {
658     ok(hr == CO_E_WRONG_SERVER_IDENTITY, "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
659     }
660
661     hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
662         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
663     ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
664
665     IMoniker_Release(pMoniker);
666
667     IRunningObjectTable_Release(pROT);
668 }
669
670 static HRESULT WINAPI ParseDisplayName_QueryInterface(IParseDisplayName *iface, REFIID riid, void **ppv)
671 {
672     if (IsEqualIID(riid, &IID_IUnknown) ||
673         IsEqualIID(riid, &IID_IParseDisplayName))
674     {
675         *ppv = iface;
676         IUnknown_AddRef(iface);
677         return S_OK;
678     }
679     *ppv = NULL;
680     return E_NOINTERFACE;
681 }
682
683 static ULONG WINAPI ParseDisplayName_AddRef(IParseDisplayName *iface)
684 {
685     return 2;
686 }
687
688 static ULONG WINAPI ParseDisplayName_Release(IParseDisplayName *iface)
689 {
690     return 1;
691 }
692
693 static LPCWSTR expected_display_name;
694
695 static HRESULT WINAPI ParseDisplayName_ParseDisplayName(IParseDisplayName *iface,
696                                                         IBindCtx *pbc,
697                                                         LPOLESTR pszDisplayName,
698                                                         ULONG *pchEaten,
699                                                         IMoniker **ppmkOut)
700 {
701     char display_nameA[256];
702     WideCharToMultiByte(CP_ACP, 0, pszDisplayName, -1, display_nameA, sizeof(display_nameA), NULL, NULL);
703     ok(!lstrcmpW(pszDisplayName, expected_display_name), "unexpected display name \"%s\"\n", display_nameA);
704     ok(pszDisplayName == expected_display_name, "pszDisplayName should be the same pointer as passed into MkParseDisplayName\n");
705     *pchEaten = lstrlenW(pszDisplayName);
706     return CreateAntiMoniker(ppmkOut);
707 }
708
709 static const IParseDisplayNameVtbl ParseDisplayName_Vtbl =
710 {
711     ParseDisplayName_QueryInterface,
712     ParseDisplayName_AddRef,
713     ParseDisplayName_Release,
714     ParseDisplayName_ParseDisplayName
715 };
716
717 static IParseDisplayName ParseDisplayName = { &ParseDisplayName_Vtbl };
718
719 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
720 {
721     IMoniker * spMoniker;
722     int monCnt=0, matchCnt=0;
723
724     while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
725     {
726         HRESULT hr;
727         WCHAR * szDisplayn;
728         monCnt++;
729         hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
730         if (SUCCEEDED(hr))
731         {
732             if (!lstrcmpiW(szDisplayn, wszFileName1) || !lstrcmpiW(szDisplayn, wszFileName2))
733                 matchCnt++;
734             CoTaskMemFree(szDisplayn);
735         }
736     }
737     trace("Total number of monikers is %i\n", monCnt);
738     return matchCnt;
739 }
740
741 static void test_MkParseDisplayName(void)
742 {
743     IBindCtx * pbc = NULL;
744     HRESULT hr;
745     IMoniker * pmk  = NULL;
746     IMoniker * pmk1 = NULL;
747     IMoniker * pmk2 = NULL;
748     ULONG eaten;
749     int matchCnt;
750     IUnknown * object = NULL;
751
752     IUnknown *lpEM1;
753
754     IEnumMoniker *spEM1  = NULL;
755     IEnumMoniker *spEM2  = NULL;
756     IEnumMoniker *spEM3  = NULL;
757
758     DWORD pdwReg1=0;
759     DWORD grflags=0;
760     DWORD pdwReg2=0;
761     DWORD moniker_type;
762     IRunningObjectTable * pprot=NULL;
763
764     /* CLSID of My Computer */
765     static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
766         '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};
767     static const WCHAR wszDisplayNameClsid[] = {'c','l','s','i','d',':',0};
768     static const WCHAR wszNonExistentProgId[] = {'N','o','n','E','x','i','s','t','e','n','t','P','r','o','g','I','d',':',0};
769     static const WCHAR wszDisplayNameRunning[] = {'W','i','n','e','T','e','s','t','R','u','n','n','i','n','g',0};
770     static const WCHAR wszDisplayNameProgId1[] = {'S','t','d','F','o','n','t',':',0};
771     static const WCHAR wszDisplayNameProgId2[] = {'@','S','t','d','F','o','n','t',0};
772     static const WCHAR wszDisplayNameProgIdFail[] = {'S','t','d','F','o','n','t',0};
773     char szDisplayNameFile[256];
774     WCHAR wszDisplayNameFile[256];
775
776     hr = CreateBindCtx(0, &pbc);
777     ok_ole_success(hr, CreateBindCtx);
778
779     hr = MkParseDisplayName(pbc, wszNonExistentProgId, &eaten, &pmk);
780     ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
781         "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
782
783     /* no special handling of "clsid:" without the string form of the clsid
784      * following */
785     hr = MkParseDisplayName(pbc, wszDisplayNameClsid, &eaten, &pmk);
786     ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
787         "MkParseDisplayName should have failed with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
788
789     /* shows clsid has higher precedence than a running object */
790     hr = CreateFileMoniker(wszDisplayName, &pmk);
791     ok_ole_success(hr, CreateFileMoniker);
792     hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
793     ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
794     hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
795     ok_ole_success(hr, IRunningObjectTable_Register);
796     IMoniker_Release(pmk);
797     pmk = NULL;
798     hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
799     ok_ole_success(hr, MkParseDisplayName);
800     if (pmk)
801     {
802         IMoniker_IsSystemMoniker(pmk, &moniker_type);
803         ok(moniker_type == MKSYS_CLASSMONIKER, "moniker_type was %d instead of MKSYS_CLASSMONIKER\n", moniker_type);
804         IMoniker_Release(pmk);
805     }
806     hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
807     ok_ole_success(hr, IRunningObjectTable_Revoke);
808     IRunningObjectTable_Release(pprot);
809
810     hr = CreateFileMoniker(wszDisplayNameRunning, &pmk);
811     ok_ole_success(hr, CreateFileMoniker);
812     hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
813     ok_ole_success(hr, IBindCtx_GetRunningObjectTable);
814     hr = IRunningObjectTable_Register(pprot, 0, (IUnknown *)&Test_ClassFactory, pmk, &pdwReg1);
815     ok_ole_success(hr, IRunningObjectTable_Register);
816     IMoniker_Release(pmk);
817     pmk = NULL;
818     hr = MkParseDisplayName(pbc, wszDisplayNameRunning, &eaten, &pmk);
819     ok_ole_success(hr, MkParseDisplayName);
820     if (pmk)
821     {
822         IMoniker_IsSystemMoniker(pmk, &moniker_type);
823         ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
824         IMoniker_Release(pmk);
825     }
826     hr = IRunningObjectTable_Revoke(pprot, pdwReg1);
827     ok_ole_success(hr, IRunningObjectTable_Revoke);
828     IRunningObjectTable_Release(pprot);
829
830     hr = CoRegisterClassObject(&CLSID_StdFont, (IUnknown *)&ParseDisplayName, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, &pdwReg1);
831     ok_ole_success(hr, CoRegisterClassObject);
832
833     expected_display_name = wszDisplayNameProgId1;
834     hr = MkParseDisplayName(pbc, wszDisplayNameProgId1, &eaten, &pmk);
835     ok_ole_success(hr, MkParseDisplayName);
836     if (pmk)
837     {
838         IMoniker_IsSystemMoniker(pmk, &moniker_type);
839         ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
840         IMoniker_Release(pmk);
841     }
842
843     expected_display_name = wszDisplayNameProgId2;
844     hr = MkParseDisplayName(pbc, wszDisplayNameProgId2, &eaten, &pmk);
845     ok_ole_success(hr, MkParseDisplayName);
846     if (pmk)
847     {
848         IMoniker_IsSystemMoniker(pmk, &moniker_type);
849         ok(moniker_type == MKSYS_ANTIMONIKER, "moniker_type was %d instead of MKSYS_ANTIMONIKER\n", moniker_type);
850         IMoniker_Release(pmk);
851     }
852
853     hr = MkParseDisplayName(pbc, wszDisplayNameProgIdFail, &eaten, &pmk);
854     ok(hr == MK_E_SYNTAX || hr == MK_E_CANTOPENFILE /* Win9x */,
855         "MkParseDisplayName with ProgId without marker should fail with MK_E_SYNTAX or MK_E_CANTOPENFILE instead of 0x%08x\n", hr);
856
857     hr = CoRevokeClassObject(pdwReg1);
858     ok_ole_success(hr, CoRevokeClassObject);
859
860     GetSystemDirectoryA(szDisplayNameFile, sizeof(szDisplayNameFile));
861     strcat(szDisplayNameFile, "\\kernel32.dll");
862     MultiByteToWideChar(CP_ACP, 0, szDisplayNameFile, -1, wszDisplayNameFile, sizeof(wszDisplayNameFile)/sizeof(wszDisplayNameFile[0]));
863     hr = MkParseDisplayName(pbc, wszDisplayNameFile, &eaten, &pmk);
864     ok_ole_success(hr, MkParseDisplayName);
865     if (pmk)
866     {
867         IMoniker_IsSystemMoniker(pmk, &moniker_type);
868         ok(moniker_type == MKSYS_FILEMONIKER, "moniker_type was %d instead of MKSYS_FILEMONIKER\n", moniker_type);
869         IMoniker_Release(pmk);
870     }
871
872     hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
873     ok_ole_success(hr, MkParseDisplayName);
874
875     if (pmk)
876     {
877         hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
878         ok_ole_success(hr, IMoniker_BindToObject);
879
880         IUnknown_Release(object);
881         IMoniker_Release(pmk);
882     }
883     IBindCtx_Release(pbc);
884
885     /* Test the EnumMoniker interface */
886     hr = CreateBindCtx(0, &pbc);
887     ok_ole_success(hr, CreateBindCtx);
888
889     hr = CreateFileMoniker(wszFileName1, &pmk1);
890     ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
891     hr = CreateFileMoniker(wszFileName2, &pmk2);
892     ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
893     hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
894     ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
895
896     /* Check EnumMoniker before registering */
897     hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
898     ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
899     hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
900     /* Register a couple of Monikers and check is ok */
901     ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
902     hr = MK_E_NOOBJECT;
903     
904     matchCnt = count_moniker_matches(pbc, spEM1);
905     trace("Number of matches is %i\n", matchCnt);
906
907     grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
908     hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
909     ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
910         hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
911
912     trace("IROT::Register\n");
913     grflags=0;
914     grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
915     hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
916     ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
917        pprot, grflags, lpEM1, pmk2, pdwReg2);
918
919     hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
920     ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
921
922     matchCnt = count_moniker_matches(pbc, spEM2);
923     ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
924
925     trace("IEnumMoniker::Clone\n");
926     IEnumMoniker_Clone(spEM2, &spEM3);
927
928     matchCnt = count_moniker_matches(pbc, spEM3);
929     ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
930     trace("IEnumMoniker::Reset\n");
931     IEnumMoniker_Reset(spEM3);
932
933     matchCnt = count_moniker_matches(pbc, spEM3);
934     ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
935
936     IRunningObjectTable_Revoke(pprot,pdwReg1);
937     IRunningObjectTable_Revoke(pprot,pdwReg2);
938     IUnknown_Release(lpEM1);
939     IEnumMoniker_Release(spEM1);
940     IEnumMoniker_Release(spEM2);
941     IEnumMoniker_Release(spEM3);
942     IMoniker_Release(pmk1);
943     IMoniker_Release(pmk2);
944     IRunningObjectTable_Release(pprot);
945
946     IBindCtx_Release(pbc);
947 }
948
949 static const LARGE_INTEGER llZero;
950
951 static const BYTE expected_class_moniker_marshal_data[] =
952 {
953     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
954     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
955     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
956     0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
957     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
958     0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
959     0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
960     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
961     0x00,0x00,0x00,0x00,
962 };
963
964 static const BYTE expected_class_moniker_saved_data[] =
965 {
966      0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
967      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
968      0x00,0x00,0x00,0x00,
969 };
970
971 static const BYTE expected_class_moniker_comparison_data[] =
972 {
973      0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
974      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
975      0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
976      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
977 };
978
979 static const WCHAR expected_class_moniker_display_name[] =
980 {
981     'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
982     '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
983     '0','0','0','0','4','6',':',0
984 };
985
986 static const BYTE expected_item_moniker_comparison_data[] =
987 {
988      0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
989      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
990      0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
991      0x54,0x00,0x00,0x00,
992 };
993
994 static const BYTE expected_item_moniker_saved_data[] =
995 {
996      0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
997      0x00,0x00,0x54,0x65,0x73,0x74,0x00,
998 };
999
1000 static const BYTE expected_item_moniker_marshal_data[] =
1001 {
1002      0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1003      0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1004      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1005      0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1006      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1007      0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1008      0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1009      0x00,0x00,0x54,0x65,0x73,0x74,0x00,
1010 };
1011
1012 static const BYTE expected_anti_moniker_marshal_data[] =
1013 {
1014     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1015     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1016     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1017     0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1018     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1019     0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
1020     0x01,0x00,0x00,0x00,
1021 };
1022
1023 static const BYTE expected_anti_moniker_saved_data[] =
1024 {
1025     0x01,0x00,0x00,0x00,
1026 };
1027
1028 static const BYTE expected_anti_moniker_comparison_data[] =
1029 {
1030     0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1031     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1032     0x01,0x00,0x00,0x00,
1033 };
1034
1035 static const BYTE expected_gc_moniker_marshal_data[] =
1036 {
1037     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1038     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1039     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1040     0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1041     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1042     0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
1043     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
1044     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1045     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1046     0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1047     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1048     0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
1049     0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
1050     0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
1051     0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
1052     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1053     0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
1054     0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
1055     0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
1056     0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
1057     0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
1058     0x00,0x57,0x69,0x6e,0x65,0x00,
1059 };
1060
1061 static const BYTE expected_gc_moniker_saved_data[] =
1062 {
1063     0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1064     0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1065     0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
1066     0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
1067     0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
1068     0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
1069     0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
1070     0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
1071     0x65,0x00,
1072 };
1073
1074 static const BYTE expected_gc_moniker_comparison_data[] =
1075 {
1076     0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1077     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1078     0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
1079     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
1080     0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
1081     0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
1082     0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
1083     0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
1084     0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
1085 };
1086
1087 static void test_moniker(
1088     const char *testname, IMoniker *moniker,
1089     const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
1090     const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
1091     const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
1092     LPCWSTR expected_display_name)
1093 {
1094     IStream * stream;
1095     IROTData * rotdata;
1096     HRESULT hr;
1097     HGLOBAL hglobal;
1098     LPBYTE moniker_data;
1099     DWORD moniker_size;
1100     DWORD i;
1101     BOOL same = TRUE;
1102     BYTE buffer[128];
1103     IMoniker * moniker_proxy;
1104     LPOLESTR display_name;
1105     IBindCtx *bindctx;
1106
1107     hr = IMoniker_IsDirty(moniker);
1108     ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1109
1110     /* Display Name */
1111
1112     hr = CreateBindCtx(0, &bindctx);
1113     ok_ole_success(hr, CreateBindCtx);
1114
1115     hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1116     ok_ole_success(hr, IMoniker_GetDisplayName);
1117     ok(!lstrcmpW(display_name, expected_display_name), "%s: display name wasn't what was expected\n", testname);
1118
1119     CoTaskMemFree(display_name);
1120     IBindCtx_Release(bindctx);
1121
1122     hr = IMoniker_IsDirty(moniker);
1123     ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
1124
1125     /* IROTData::GetComparisonData test */
1126
1127     hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1128     ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
1129
1130     hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
1131     ok_ole_success(hr, IROTData_GetComparisonData);
1132
1133     if (hr != S_OK) moniker_size = 0;
1134
1135     /* first check we have the right amount of data */
1136     ok(moniker_size == sizeof_expected_moniker_comparison_data,
1137         "%s: Size of comparison data differs (expected %d, actual %d)\n",
1138         testname, sizeof_expected_moniker_comparison_data, moniker_size);
1139
1140     /* then do a byte-by-byte comparison */
1141     for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
1142     {
1143         if (expected_moniker_comparison_data[i] != buffer[i])
1144         {
1145             same = FALSE;
1146             break;
1147         }
1148     }
1149
1150     ok(same, "%s: Comparison data differs\n", testname);
1151     if (!same)
1152     {
1153         for (i = 0; i < moniker_size; i++)
1154         {
1155             if (i % 8 == 0) printf("     ");
1156             printf("0x%02x,", buffer[i]);
1157             if (i % 8 == 7) printf("\n");
1158         }
1159         printf("\n");
1160     }
1161
1162     IROTData_Release(rotdata);
1163   
1164     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1165   
1166     /* Saving */
1167
1168     hr = IMoniker_Save(moniker, stream, TRUE);
1169     ok_ole_success(hr, IMoniker_Save);
1170
1171     hr = GetHGlobalFromStream(stream, &hglobal);
1172     ok_ole_success(hr, GetHGlobalFromStream);
1173
1174     moniker_size = GlobalSize(hglobal);
1175
1176     moniker_data = GlobalLock(hglobal);
1177
1178     /* first check we have the right amount of data */
1179     ok(moniker_size == sizeof_expected_moniker_saved_data,
1180         "%s: Size of saved data differs (expected %d, actual %d)\n",
1181         testname, sizeof_expected_moniker_saved_data, moniker_size);
1182
1183     /* then do a byte-by-byte comparison */
1184     for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
1185     {
1186         if (expected_moniker_saved_data[i] != moniker_data[i])
1187         {
1188             same = FALSE;
1189             break;
1190         }
1191     }
1192
1193     ok(same, "%s: Saved data differs\n", testname);
1194     if (!same)
1195     {
1196         for (i = 0; i < moniker_size; i++)
1197         {
1198             if (i % 8 == 0) printf("     ");
1199             printf("0x%02x,", moniker_data[i]);
1200             if (i % 8 == 7) printf("\n");
1201         }
1202         printf("\n");
1203     }
1204
1205     GlobalUnlock(hglobal);
1206
1207     IStream_Release(stream);
1208
1209     /* Marshaling tests */
1210
1211     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1212     ok_ole_success(hr, CreateStreamOnHGlobal);
1213
1214     hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1215     ok_ole_success(hr, CoMarshalInterface);
1216
1217     hr = GetHGlobalFromStream(stream, &hglobal);
1218     ok_ole_success(hr, GetHGlobalFromStream);
1219
1220     moniker_size = GlobalSize(hglobal);
1221
1222     moniker_data = GlobalLock(hglobal);
1223
1224     /* first check we have the right amount of data */
1225     ok(moniker_size == sizeof_expected_moniker_marshal_data,
1226         "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1227         testname, sizeof_expected_moniker_marshal_data, moniker_size);
1228
1229     /* then do a byte-by-byte comparison */
1230     if (expected_moniker_marshal_data)
1231     {
1232         for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1233         {
1234             if (expected_moniker_marshal_data[i] != moniker_data[i])
1235             {
1236                 same = FALSE;
1237                 break;
1238             }
1239         }
1240     }
1241
1242     ok(same, "%s: Marshaled data differs\n", testname);
1243     if (!same)
1244     {
1245         for (i = 0; i < moniker_size; i++)
1246         {
1247             if (i % 8 == 0) printf("     ");
1248             printf("0x%02x,", moniker_data[i]);
1249             if (i % 8 == 7) printf("\n");
1250         }
1251         printf("\n");
1252     }
1253
1254     GlobalUnlock(hglobal);
1255
1256     IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1257     hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1258     ok_ole_success(hr, CoUnmarshalInterface);
1259
1260     IStream_Release(stream);
1261     IMoniker_Release(moniker_proxy);
1262 }
1263
1264 static void test_class_moniker(void)
1265 {
1266     HRESULT hr;
1267     IMoniker *moniker;
1268     DWORD moniker_type;
1269     DWORD hash;
1270     IBindCtx *bindctx;
1271     IMoniker *inverse;
1272     IUnknown *unknown;
1273     FILETIME filetime;
1274
1275     hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1276     ok_ole_success(hr, CreateClassMoniker);
1277     if (!moniker) return;
1278
1279     test_moniker("class moniker", moniker, 
1280         expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1281         expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1282         expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1283         expected_class_moniker_display_name);
1284
1285     /* Hashing */
1286
1287     hr = IMoniker_Hash(moniker, &hash);
1288     ok_ole_success(hr, IMoniker_Hash);
1289
1290     ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1291         "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1292         hash);
1293
1294     /* IsSystemMoniker test */
1295
1296     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1297     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1298
1299     ok(moniker_type == MKSYS_CLASSMONIKER,
1300         "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1301         moniker_type);
1302
1303     hr = CreateBindCtx(0, &bindctx);
1304     ok_ole_success(hr, CreateBindCtx);
1305
1306     /* IsRunning test */
1307     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1308     ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1309
1310     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1311     ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1312
1313     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1314     ok_ole_success(hr, IMoniker_BindToObject);
1315     IUnknown_Release(unknown);
1316
1317     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1318     ok_ole_success(hr, IMoniker_BindToStorage);
1319     IUnknown_Release(unknown);
1320
1321     IBindCtx_Release(bindctx);
1322
1323     hr = IMoniker_Inverse(moniker, &inverse);
1324     ok_ole_success(hr, IMoniker_Inverse);
1325     IMoniker_Release(inverse);
1326
1327     IMoniker_Release(moniker);
1328 }
1329
1330 static void test_file_moniker(WCHAR* path)
1331 {
1332     IStream *stream;
1333     IMoniker *moniker1 = NULL, *moniker2 = NULL;
1334     HRESULT hr;
1335
1336     hr = CreateFileMoniker(path, &moniker1);
1337     ok_ole_success(hr, CreateFileMoniker); 
1338
1339     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1340
1341     /* Marshal */
1342     hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1343     ok_ole_success(hr, CoMarshalInterface);
1344     
1345     /* Rewind */
1346     hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1347     ok_ole_success(hr, IStream_Seek);
1348
1349     /* Unmarshal */
1350     hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1351     ok_ole_success(hr, CoUnmarshalInterface);
1352
1353     hr = IMoniker_IsEqual(moniker1, moniker2);
1354     ok_ole_success(hr, IsEqual);
1355
1356     IStream_Release(stream);
1357     if (moniker1) 
1358         IMoniker_Release(moniker1);
1359     if (moniker2) 
1360         IMoniker_Release(moniker2);
1361 }
1362
1363 static void test_file_monikers(void)
1364 {
1365     static WCHAR wszFile[][30] = {
1366         {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1367         {'\\', '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},
1368         /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1369         {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1370         /* U+2020 = DAGGER     = 0x86 (1252) = 0x813f (932)
1371          * U+20AC = EURO SIGN  = 0x80 (1252) =  undef (932)
1372          * U+0100 .. = Latin extended-A
1373          */ 
1374         {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c,  0},
1375         };
1376
1377     int i; 
1378
1379     trace("ACP is %u\n", GetACP());
1380
1381     for (i = 0; i < COUNTOF(wszFile); ++i)
1382     {
1383         int j ;
1384         for (j = lstrlenW(wszFile[i]); j > 0; --j)
1385         {
1386             wszFile[i][j] = 0;
1387             test_file_moniker(wszFile[i]);
1388         }
1389     }
1390 }
1391
1392 static void test_item_moniker(void)
1393 {
1394     HRESULT hr;
1395     IMoniker *moniker;
1396     DWORD moniker_type;
1397     DWORD hash;
1398     IBindCtx *bindctx;
1399     IMoniker *inverse;
1400     IUnknown *unknown;
1401     static const WCHAR wszDelimeter[] = {'!',0};
1402     static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1403     static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1404
1405     hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1406     ok_ole_success(hr, CreateItemMoniker);
1407
1408     test_moniker("item moniker", moniker, 
1409         expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1410         expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1411         expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1412         expected_display_name);
1413
1414     /* Hashing */
1415
1416     hr = IMoniker_Hash(moniker, &hash);
1417     ok_ole_success(hr, IMoniker_Hash);
1418
1419     ok(hash == 0x73c,
1420         "Hash value != 0x73c, instead was 0x%08x\n",
1421         hash);
1422
1423     /* IsSystemMoniker test */
1424
1425     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1426     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1427
1428     ok(moniker_type == MKSYS_ITEMMONIKER,
1429         "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1430         moniker_type);
1431
1432     hr = CreateBindCtx(0, &bindctx);
1433     ok_ole_success(hr, CreateBindCtx);
1434
1435     /* IsRunning test */
1436     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1437     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1438
1439     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1440     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1441
1442     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1443     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1444
1445     IBindCtx_Release(bindctx);
1446
1447     hr = IMoniker_Inverse(moniker, &inverse);
1448     ok_ole_success(hr, IMoniker_Inverse);
1449     IMoniker_Release(inverse);
1450
1451     IMoniker_Release(moniker);
1452 }
1453
1454 static void test_anti_moniker(void)
1455 {
1456     HRESULT hr;
1457     IMoniker *moniker;
1458     DWORD moniker_type;
1459     DWORD hash;
1460     IBindCtx *bindctx;
1461     FILETIME filetime;
1462     IMoniker *inverse;
1463     IUnknown *unknown;
1464     static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1465
1466     hr = CreateAntiMoniker(&moniker);
1467     ok_ole_success(hr, CreateAntiMoniker);
1468     if (!moniker) return;
1469
1470     test_moniker("anti moniker", moniker, 
1471         expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1472         expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1473         expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1474         expected_display_name);
1475
1476     /* Hashing */
1477     hr = IMoniker_Hash(moniker, &hash);
1478     ok_ole_success(hr, IMoniker_Hash);
1479     ok(hash == 0x80000001,
1480         "Hash value != 0x80000001, instead was 0x%08x\n",
1481         hash);
1482
1483     /* IsSystemMoniker test */
1484     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1485     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1486     ok(moniker_type == MKSYS_ANTIMONIKER,
1487         "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1488         moniker_type);
1489
1490     hr = IMoniker_Inverse(moniker, &inverse);
1491     ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1492     ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1493
1494     hr = CreateBindCtx(0, &bindctx);
1495     ok_ole_success(hr, CreateBindCtx);
1496
1497     /* IsRunning test */
1498     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1499     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1500
1501     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1502     ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1503
1504     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1505     ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1506
1507     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1508     ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1509
1510     IBindCtx_Release(bindctx);
1511
1512     IMoniker_Release(moniker);
1513 }
1514
1515 static void test_generic_composite_moniker(void)
1516 {
1517     HRESULT hr;
1518     IMoniker *moniker;
1519     IMoniker *moniker1;
1520     IMoniker *moniker2;
1521     DWORD moniker_type;
1522     DWORD hash;
1523     IBindCtx *bindctx;
1524     FILETIME filetime;
1525     IMoniker *inverse;
1526     IUnknown *unknown;
1527     static const WCHAR wszDelimeter1[] = {'!',0};
1528     static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1529     static const WCHAR wszDelimeter2[] = {'#',0};
1530     static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1531     static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1532
1533     hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1534     ok_ole_success(hr, CreateItemMoniker);
1535     hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1536     ok_ole_success(hr, CreateItemMoniker);
1537     hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1538     ok_ole_success(hr, CreateGenericComposite);
1539
1540     test_moniker("generic composite moniker", moniker, 
1541         expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1542         expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1543         expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1544         expected_display_name);
1545
1546     /* Hashing */
1547
1548     hr = IMoniker_Hash(moniker, &hash);
1549     ok_ole_success(hr, IMoniker_Hash);
1550
1551     ok(hash == 0xd87,
1552         "Hash value != 0xd87, instead was 0x%08x\n",
1553         hash);
1554
1555     /* IsSystemMoniker test */
1556
1557     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1558     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1559
1560     ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1561         "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1562         moniker_type);
1563
1564     hr = CreateBindCtx(0, &bindctx);
1565     ok_ole_success(hr, CreateBindCtx);
1566
1567     /* IsRunning test */
1568     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1569     todo_wine
1570     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1571
1572     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1573     ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1574
1575     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1576     todo_wine
1577     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1578
1579     todo_wine
1580     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1581     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1582
1583     IBindCtx_Release(bindctx);
1584
1585     hr = IMoniker_Inverse(moniker, &inverse);
1586     ok_ole_success(hr, IMoniker_Inverse);
1587     IMoniker_Release(inverse);
1588
1589     IMoniker_Release(moniker);
1590 }
1591
1592 static void test_pointer_moniker(void)
1593 {
1594     HRESULT hr;
1595     IMoniker *moniker;
1596     DWORD moniker_type;
1597     DWORD hash;
1598     IBindCtx *bindctx;
1599     FILETIME filetime;
1600     IMoniker *inverse;
1601     IUnknown *unknown;
1602     IStream *stream;
1603     IROTData *rotdata;
1604     LPOLESTR display_name;
1605
1606     cLocks = 0;
1607
1608     hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1609     ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1610
1611     hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1612     ok_ole_success(hr, CreatePointerMoniker);
1613     if (!moniker) return;
1614
1615     ok_more_than_one_lock();
1616
1617     /* Display Name */
1618
1619     hr = CreateBindCtx(0, &bindctx);
1620     ok_ole_success(hr, CreateBindCtx);
1621
1622     hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1623     ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1624
1625     IBindCtx_Release(bindctx);
1626
1627     hr = IMoniker_IsDirty(moniker);
1628     ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1629
1630     /* IROTData::GetComparisonData test */
1631
1632     hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1633     ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1634
1635     /* Saving */
1636
1637     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1638     ok_ole_success(hr, CreateStreamOnHGlobal);
1639
1640     hr = IMoniker_Save(moniker, stream, TRUE);
1641     ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1642
1643     IStream_Release(stream);
1644
1645     /* Hashing */
1646     hr = IMoniker_Hash(moniker, &hash);
1647     ok_ole_success(hr, IMoniker_Hash);
1648     ok(hash == (DWORD)&Test_ClassFactory,
1649         "Hash value should have been 0x%08x, instead of 0x%08x\n",
1650         (DWORD)&Test_ClassFactory, hash);
1651
1652     /* IsSystemMoniker test */
1653     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1654     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1655     ok(moniker_type == MKSYS_POINTERMONIKER,
1656         "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1657         moniker_type);
1658
1659     hr = IMoniker_Inverse(moniker, &inverse);
1660     ok_ole_success(hr, IMoniker_Inverse);
1661     IMoniker_Release(inverse);
1662
1663     hr = CreateBindCtx(0, &bindctx);
1664     ok_ole_success(hr, CreateBindCtx);
1665
1666     /* IsRunning test */
1667     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1668     ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1669
1670     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1671     ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1672
1673     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1674     ok_ole_success(hr, IMoniker_BindToObject);
1675     IUnknown_Release(unknown);
1676
1677     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1678     ok_ole_success(hr, IMoniker_BindToStorage);
1679     IUnknown_Release(unknown);
1680
1681     IMoniker_Release(moniker);
1682
1683     ok_no_locks();
1684
1685     hr = CreatePointerMoniker(NULL, &moniker);
1686     ok_ole_success(hr, CreatePointerMoniker);
1687
1688     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1689     ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1690
1691     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1692     ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1693
1694     IBindCtx_Release(bindctx);
1695
1696     IMoniker_Release(moniker);
1697 }
1698
1699 static void test_bind_context(void)
1700 {
1701     HRESULT hr;
1702     IBindCtx *pBindCtx;
1703     IEnumString *pEnumString;
1704     BIND_OPTS2 bind_opts;
1705     HeapUnknown *unknown;
1706     HeapUnknown *unknown2;
1707     IUnknown *param_obj;
1708     ULONG refs;
1709     static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1710     static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1711
1712     hr = CreateBindCtx(0, NULL);
1713     ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1714
1715     hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1716     ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1717
1718     hr = CreateBindCtx(0, &pBindCtx);
1719     ok_ole_success(hr, "CreateBindCtx");
1720
1721     bind_opts.cbStruct = -1;
1722     hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1723     ok_ole_success(hr, "IBindCtx_GetBindOptions");
1724     ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1725
1726     bind_opts.cbStruct = sizeof(BIND_OPTS);
1727     hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1728     ok_ole_success(hr, "IBindCtx_GetBindOptions");
1729     ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1730
1731     bind_opts.cbStruct = sizeof(bind_opts);
1732     hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1733     ok_ole_success(hr, "IBindCtx_GetBindOptions");
1734     ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1735     ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1736     ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1737     ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1738     ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1739     ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1740         "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1741     ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1742     ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1743
1744     bind_opts.cbStruct = -1;
1745     hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1746     ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1747
1748     hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1749     ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1750
1751     unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1752     unknown->lpVtbl = &HeapUnknown_Vtbl;
1753     unknown->refs = 1;
1754     hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1755     ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1756
1757     hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1758     ok_ole_success(hr, "IBindCtx_GetObjectParam");
1759     IUnknown_Release(param_obj);
1760
1761     hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1762     ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1763     ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1764
1765     hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1766     ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1767
1768     hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1769     ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1770     ok(!pEnumString, "pEnumString should be NULL\n");
1771
1772     hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1773     ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1774
1775     hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1776     ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1777
1778     unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1779     unknown2->lpVtbl = &HeapUnknown_Vtbl;
1780     unknown2->refs = 1;
1781     hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1782     ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1783
1784     hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1785     ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1786
1787     hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1788     ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1789
1790     IBindCtx_Release(pBindCtx);
1791
1792     refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1793     ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1794
1795     refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1796     ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1797 }
1798
1799 START_TEST(moniker)
1800 {
1801     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1802
1803     test_ROT();
1804     test_MkParseDisplayName();
1805     test_class_moniker();
1806     test_file_monikers();
1807     test_item_moniker();
1808     test_anti_moniker();
1809     test_generic_composite_moniker();
1810     test_pointer_moniker();
1811
1812     /* FIXME: test moniker creation funcs and parsing other moniker formats */
1813
1814     test_bind_context();
1815
1816     CoUninitialize();
1817 }