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