ole32/tests: Fix marshalling data layout for Win64.
[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 = 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, NULL, NULL, NULL);
1336     ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1337
1338     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1339     ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1340
1341     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1342     ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1343
1344     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1345     ok_ole_success(hr, IMoniker_BindToObject);
1346     IUnknown_Release(unknown);
1347
1348     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1349     ok_ole_success(hr, IMoniker_BindToStorage);
1350     IUnknown_Release(unknown);
1351
1352     IBindCtx_Release(bindctx);
1353
1354     hr = IMoniker_Inverse(moniker, &inverse);
1355     ok_ole_success(hr, IMoniker_Inverse);
1356     IMoniker_Release(inverse);
1357
1358     IMoniker_Release(moniker);
1359 }
1360
1361 static void test_file_moniker(WCHAR* path)
1362 {
1363     IStream *stream;
1364     IMoniker *moniker1 = NULL, *moniker2 = NULL;
1365     HRESULT hr;
1366
1367     hr = CreateFileMoniker(path, &moniker1);
1368     ok_ole_success(hr, CreateFileMoniker); 
1369
1370     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1371
1372     /* Marshal */
1373     hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1374     ok_ole_success(hr, CoMarshalInterface);
1375     
1376     /* Rewind */
1377     hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1378     ok_ole_success(hr, IStream_Seek);
1379
1380     /* Unmarshal */
1381     hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1382     ok_ole_success(hr, CoUnmarshalInterface);
1383
1384     hr = IMoniker_IsEqual(moniker1, moniker2);
1385     ok_ole_success(hr, IsEqual);
1386
1387     IStream_Release(stream);
1388     if (moniker1) 
1389         IMoniker_Release(moniker1);
1390     if (moniker2) 
1391         IMoniker_Release(moniker2);
1392 }
1393
1394 static void test_file_monikers(void)
1395 {
1396     static WCHAR wszFile[][30] = {
1397         {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1398         {'\\', '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},
1399         /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1400         {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1401         /* U+2020 = DAGGER     = 0x86 (1252) = 0x813f (932)
1402          * U+20AC = EURO SIGN  = 0x80 (1252) =  undef (932)
1403          * U+0100 .. = Latin extended-A
1404          */ 
1405         {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c,  0},
1406         };
1407
1408     int i; 
1409
1410     trace("ACP is %u\n", GetACP());
1411
1412     for (i = 0; i < COUNTOF(wszFile); ++i)
1413     {
1414         int j ;
1415         for (j = lstrlenW(wszFile[i]); j > 0; --j)
1416         {
1417             wszFile[i][j] = 0;
1418             test_file_moniker(wszFile[i]);
1419         }
1420     }
1421 }
1422
1423 static void test_item_moniker(void)
1424 {
1425     HRESULT hr;
1426     IMoniker *moniker;
1427     DWORD moniker_type;
1428     DWORD hash;
1429     IBindCtx *bindctx;
1430     IMoniker *inverse;
1431     IUnknown *unknown;
1432     static const WCHAR wszDelimeter[] = {'!',0};
1433     static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1434     static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1435
1436     hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1437     ok_ole_success(hr, CreateItemMoniker);
1438
1439     test_moniker("item moniker", moniker, 
1440         expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1441         expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1442         expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1443         expected_display_name);
1444
1445     /* Hashing */
1446
1447     hr = IMoniker_Hash(moniker, &hash);
1448     ok_ole_success(hr, IMoniker_Hash);
1449
1450     ok(hash == 0x73c,
1451         "Hash value != 0x73c, instead was 0x%08x\n",
1452         hash);
1453
1454     /* IsSystemMoniker test */
1455
1456     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1457     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1458
1459     ok(moniker_type == MKSYS_ITEMMONIKER,
1460         "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1461         moniker_type);
1462
1463     hr = CreateBindCtx(0, &bindctx);
1464     ok_ole_success(hr, CreateBindCtx);
1465
1466     /* IsRunning test */
1467     hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1468     todo_wine
1469     ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1470
1471     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1472     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1473
1474     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1475     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1476
1477     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1478     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1479
1480     IBindCtx_Release(bindctx);
1481
1482     hr = IMoniker_Inverse(moniker, &inverse);
1483     ok_ole_success(hr, IMoniker_Inverse);
1484     IMoniker_Release(inverse);
1485
1486     IMoniker_Release(moniker);
1487 }
1488
1489 static void test_anti_moniker(void)
1490 {
1491     HRESULT hr;
1492     IMoniker *moniker;
1493     DWORD moniker_type;
1494     DWORD hash;
1495     IBindCtx *bindctx;
1496     FILETIME filetime;
1497     IMoniker *inverse;
1498     IUnknown *unknown;
1499     static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1500
1501     hr = CreateAntiMoniker(&moniker);
1502     ok_ole_success(hr, CreateAntiMoniker);
1503     if (!moniker) return;
1504
1505     test_moniker("anti moniker", moniker, 
1506         expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1507         expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1508         expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1509         expected_display_name);
1510
1511     /* Hashing */
1512     hr = IMoniker_Hash(moniker, &hash);
1513     ok_ole_success(hr, IMoniker_Hash);
1514     ok(hash == 0x80000001,
1515         "Hash value != 0x80000001, instead was 0x%08x\n",
1516         hash);
1517
1518     /* IsSystemMoniker test */
1519     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1520     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1521     ok(moniker_type == MKSYS_ANTIMONIKER,
1522         "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1523         moniker_type);
1524
1525     hr = IMoniker_Inverse(moniker, &inverse);
1526     ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1527     ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1528
1529     hr = CreateBindCtx(0, &bindctx);
1530     ok_ole_success(hr, CreateBindCtx);
1531
1532     /* IsRunning test */
1533     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1534     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1535
1536     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1537     ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1538
1539     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1540     ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1541
1542     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1543     ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1544
1545     IBindCtx_Release(bindctx);
1546
1547     IMoniker_Release(moniker);
1548 }
1549
1550 static void test_generic_composite_moniker(void)
1551 {
1552     HRESULT hr;
1553     IMoniker *moniker;
1554     IMoniker *moniker1;
1555     IMoniker *moniker2;
1556     DWORD moniker_type;
1557     DWORD hash;
1558     IBindCtx *bindctx;
1559     FILETIME filetime;
1560     IMoniker *inverse;
1561     IUnknown *unknown;
1562     static const WCHAR wszDelimeter1[] = {'!',0};
1563     static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1564     static const WCHAR wszDelimeter2[] = {'#',0};
1565     static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1566     static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1567
1568     hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1569     ok_ole_success(hr, CreateItemMoniker);
1570     hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1571     ok_ole_success(hr, CreateItemMoniker);
1572     hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1573     ok_ole_success(hr, CreateGenericComposite);
1574
1575     test_moniker("generic composite moniker", moniker, 
1576         expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1577         expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1578         expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1579         expected_display_name);
1580
1581     /* Hashing */
1582
1583     hr = IMoniker_Hash(moniker, &hash);
1584     ok_ole_success(hr, IMoniker_Hash);
1585
1586     ok(hash == 0xd87,
1587         "Hash value != 0xd87, instead was 0x%08x\n",
1588         hash);
1589
1590     /* IsSystemMoniker test */
1591
1592     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1593     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1594
1595     ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1596         "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1597         moniker_type);
1598
1599     hr = CreateBindCtx(0, &bindctx);
1600     ok_ole_success(hr, CreateBindCtx);
1601
1602     /* IsRunning test */
1603     hr = IMoniker_IsRunning(moniker, NULL, NULL, NULL);
1604     todo_wine
1605     ok(hr == E_INVALIDARG, "IMoniker_IsRunning should return E_INVALIDARG, not 0x%08x\n", hr);
1606
1607     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1608     todo_wine
1609     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1610
1611     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1612     ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1613
1614     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1615     todo_wine
1616     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1617
1618     todo_wine
1619     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1620     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1621
1622     IBindCtx_Release(bindctx);
1623
1624     hr = IMoniker_Inverse(moniker, &inverse);
1625     ok_ole_success(hr, IMoniker_Inverse);
1626     IMoniker_Release(inverse);
1627
1628     IMoniker_Release(moniker);
1629 }
1630
1631 static void test_pointer_moniker(void)
1632 {
1633     HRESULT hr;
1634     IMoniker *moniker;
1635     DWORD moniker_type;
1636     DWORD hash;
1637     IBindCtx *bindctx;
1638     FILETIME filetime;
1639     IMoniker *inverse;
1640     IUnknown *unknown;
1641     IStream *stream;
1642     IROTData *rotdata;
1643     LPOLESTR display_name;
1644
1645     cLocks = 0;
1646
1647     hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, NULL);
1648     ok(hr == E_INVALIDARG, "CreatePointerMoniker(x, NULL) should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1649
1650     hr = CreatePointerMoniker((IUnknown *)&Test_ClassFactory, &moniker);
1651     ok_ole_success(hr, CreatePointerMoniker);
1652     if (!moniker) return;
1653
1654     ok_more_than_one_lock();
1655
1656     /* Display Name */
1657
1658     hr = CreateBindCtx(0, &bindctx);
1659     ok_ole_success(hr, CreateBindCtx);
1660
1661     hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
1662     ok(hr == E_NOTIMPL, "IMoniker_GetDisplayName should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1663
1664     IBindCtx_Release(bindctx);
1665
1666     hr = IMoniker_IsDirty(moniker);
1667     ok(hr == S_FALSE, "IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", hr);
1668
1669     /* IROTData::GetComparisonData test */
1670
1671     hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
1672     ok(hr == E_NOINTERFACE, "IMoniker_QueryInterface(IID_IROTData) should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
1673
1674     /* Saving */
1675
1676     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1677     ok_ole_success(hr, CreateStreamOnHGlobal);
1678
1679     hr = IMoniker_Save(moniker, stream, TRUE);
1680     ok(hr == E_NOTIMPL, "IMoniker_Save should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1681
1682     IStream_Release(stream);
1683
1684     /* Hashing */
1685     hr = IMoniker_Hash(moniker, &hash);
1686     ok_ole_success(hr, IMoniker_Hash);
1687     ok(hash == (DWORD)&Test_ClassFactory,
1688         "Hash value should have been 0x%08x, instead of 0x%08x\n",
1689         (DWORD)&Test_ClassFactory, hash);
1690
1691     /* IsSystemMoniker test */
1692     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1693     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1694     ok(moniker_type == MKSYS_POINTERMONIKER,
1695         "dwMkSys != MKSYS_POINTERMONIKER, instead was 0x%08x\n",
1696         moniker_type);
1697
1698     hr = IMoniker_Inverse(moniker, &inverse);
1699     ok_ole_success(hr, IMoniker_Inverse);
1700     IMoniker_Release(inverse);
1701
1702     hr = CreateBindCtx(0, &bindctx);
1703     ok_ole_success(hr, CreateBindCtx);
1704
1705     /* IsRunning test */
1706     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1707     ok(hr == S_OK, "IMoniker_IsRunning should return S_OK, not 0x%08x\n", hr);
1708
1709     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1710     ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1711
1712     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1713     ok_ole_success(hr, IMoniker_BindToObject);
1714     IUnknown_Release(unknown);
1715
1716     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1717     ok_ole_success(hr, IMoniker_BindToStorage);
1718     IUnknown_Release(unknown);
1719
1720     IMoniker_Release(moniker);
1721
1722     ok_no_locks();
1723
1724     hr = CreatePointerMoniker(NULL, &moniker);
1725     ok_ole_success(hr, CreatePointerMoniker);
1726
1727     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1728     ok(hr == E_UNEXPECTED, "IMoniker_BindToObject should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1729
1730     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1731     ok(hr == E_UNEXPECTED, "IMoniker_BindToStorage should have returned E_UNEXPECTED instead of 0x%08x\n", hr);
1732
1733     IBindCtx_Release(bindctx);
1734
1735     IMoniker_Release(moniker);
1736 }
1737
1738 static void test_bind_context(void)
1739 {
1740     HRESULT hr;
1741     IBindCtx *pBindCtx;
1742     IEnumString *pEnumString;
1743     BIND_OPTS2 bind_opts;
1744     HeapUnknown *unknown;
1745     HeapUnknown *unknown2;
1746     IUnknown *param_obj;
1747     ULONG refs;
1748     static const WCHAR wszParamName[] = {'G','e','m','m','a',0};
1749     static const WCHAR wszNonExistent[] = {'N','o','n','E','x','i','s','t','e','n','t',0};
1750
1751     hr = CreateBindCtx(0, NULL);
1752     ok(hr == E_INVALIDARG, "CreateBindCtx with NULL ppbc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1753
1754     hr = CreateBindCtx(0xdeadbeef, &pBindCtx);
1755     ok(hr == E_INVALIDARG, "CreateBindCtx with reserved value non-zero should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1756
1757     hr = CreateBindCtx(0, &pBindCtx);
1758     ok_ole_success(hr, "CreateBindCtx");
1759
1760     bind_opts.cbStruct = -1;
1761     hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1762     ok_ole_success(hr, "IBindCtx_GetBindOptions");
1763     ok(bind_opts.cbStruct == sizeof(bind_opts) ||
1764        bind_opts.cbStruct == sizeof(bind_opts) + sizeof(void*), /* Vista */
1765        "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1766
1767     bind_opts.cbStruct = sizeof(BIND_OPTS);
1768     hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1769     ok_ole_success(hr, "IBindCtx_GetBindOptions");
1770     ok(bind_opts.cbStruct == sizeof(BIND_OPTS), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1771
1772     bind_opts.cbStruct = sizeof(bind_opts);
1773     hr = IBindCtx_GetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1774     ok_ole_success(hr, "IBindCtx_GetBindOptions");
1775     ok(bind_opts.cbStruct == sizeof(bind_opts), "bind_opts.cbStruct was %d\n", bind_opts.cbStruct);
1776     ok(bind_opts.grfFlags == 0, "bind_opts.grfFlags was 0x%x instead of 0\n", bind_opts.grfFlags);
1777     ok(bind_opts.grfMode == STGM_READWRITE, "bind_opts.grfMode was 0x%x instead of STGM_READWRITE\n", bind_opts.grfMode);
1778     ok(bind_opts.dwTickCountDeadline == 0, "bind_opts.dwTickCountDeadline was %d instead of 0\n", bind_opts.dwTickCountDeadline);
1779     ok(bind_opts.dwTrackFlags == 0, "bind_opts.dwTrackFlags was 0x%x instead of 0\n", bind_opts.dwTrackFlags);
1780     ok(bind_opts.dwClassContext == (CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER|CLSCTX_REMOTE_SERVER),
1781         "bind_opts.dwClassContext should have been 0x15 instead of 0x%x\n", bind_opts.dwClassContext);
1782     ok(bind_opts.locale == GetThreadLocale(), "bind_opts.locale should have been 0x%x instead of 0x%x\n", GetThreadLocale(), bind_opts.locale);
1783     ok(bind_opts.pServerInfo == NULL, "bind_opts.pServerInfo should have been NULL instead of %p\n", bind_opts.pServerInfo);
1784
1785     bind_opts.cbStruct = -1;
1786     hr = IBindCtx_SetBindOptions(pBindCtx, (BIND_OPTS *)&bind_opts);
1787     ok(hr == E_INVALIDARG, "IBindCtx_SetBindOptions with bad cbStruct should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1788
1789     hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, NULL);
1790     ok(hr == E_INVALIDARG, "IBindCtx_RegisterObjectParam should have returned E_INVALIDARG instead of 0x%08x\n", hr);
1791
1792     unknown = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1793     unknown->lpVtbl = &HeapUnknown_Vtbl;
1794     unknown->refs = 1;
1795     hr = IBindCtx_RegisterObjectParam(pBindCtx, (WCHAR *)wszParamName, (IUnknown *)&unknown->lpVtbl);
1796     ok_ole_success(hr, "IBindCtx_RegisterObjectParam");
1797
1798     hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszParamName, &param_obj);
1799     ok_ole_success(hr, "IBindCtx_GetObjectParam");
1800     IUnknown_Release(param_obj);
1801
1802     hr = IBindCtx_GetObjectParam(pBindCtx, (WCHAR *)wszNonExistent, &param_obj);
1803     ok(hr == E_FAIL, "IBindCtx_GetObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1804     ok(param_obj == NULL, "IBindCtx_GetObjectParam with nonexistent key should have set output parameter to NULL instead of %p\n", param_obj);
1805
1806     hr = IBindCtx_RevokeObjectParam(pBindCtx, (WCHAR *)wszNonExistent);
1807     ok(hr == E_FAIL, "IBindCtx_RevokeObjectParam with nonexistent key should have failed with E_FAIL instead of 0x%08x\n", hr);
1808
1809     hr = IBindCtx_EnumObjectParam(pBindCtx, &pEnumString);
1810     ok(hr == E_NOTIMPL, "IBindCtx_EnumObjectParam should have returned E_NOTIMPL instead of 0x%08x\n", hr);
1811     ok(!pEnumString, "pEnumString should be NULL\n");
1812
1813     hr = IBindCtx_RegisterObjectBound(pBindCtx, NULL);
1814     ok_ole_success(hr, "IBindCtx_RegisterObjectBound(NULL)");
1815
1816     hr = IBindCtx_RevokeObjectBound(pBindCtx, NULL);
1817     ok(hr == E_INVALIDARG, "IBindCtx_RevokeObjectBound(NULL) should have return E_INVALIDARG instead of 0x%08x\n", hr);
1818
1819     unknown2 = HeapAlloc(GetProcessHeap(), 0, sizeof(*unknown));
1820     unknown2->lpVtbl = &HeapUnknown_Vtbl;
1821     unknown2->refs = 1;
1822     hr = IBindCtx_RegisterObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1823     ok_ole_success(hr, "IBindCtx_RegisterObjectBound");
1824
1825     hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1826     ok_ole_success(hr, "IBindCtx_RevokeObjectBound");
1827
1828     hr = IBindCtx_RevokeObjectBound(pBindCtx, (IUnknown *)&unknown2->lpVtbl);
1829     ok(hr == MK_E_NOTBOUND, "IBindCtx_RevokeObjectBound with not bound object should have returned MK_E_NOTBOUND instead of 0x%08x\n", hr);
1830
1831     IBindCtx_Release(pBindCtx);
1832
1833     refs = IUnknown_Release((IUnknown *)&unknown->lpVtbl);
1834     ok(!refs, "object param should have been destroyed, instead of having %d refs\n", refs);
1835
1836     refs = IUnknown_Release((IUnknown *)&unknown2->lpVtbl);
1837     ok(!refs, "bound object should have been destroyed, instead of having %d refs\n", refs);
1838 }
1839
1840 START_TEST(moniker)
1841 {
1842     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1843
1844     test_ROT();
1845     test_ROT_multiple_entries();
1846     test_MkParseDisplayName();
1847     test_class_moniker();
1848     test_file_monikers();
1849     test_item_moniker();
1850     test_anti_moniker();
1851     test_generic_composite_moniker();
1852     test_pointer_moniker();
1853
1854     /* FIXME: test moniker creation funcs and parsing other moniker formats */
1855
1856     test_bind_context();
1857
1858     CoUninitialize();
1859 }