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