msi: Only insert entries into listbox if property value matches.
[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
33 #include "wine/test.h"
34
35 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
36 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
37 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
38 #define COUNTOF(x) (sizeof(x) / sizeof(x[0]))
39
40 #define CHECK_EXPECTED_METHOD(method_name) \
41 do { \
42     trace("%s\n", method_name); \
43         ok(*expected_method_list != NULL, "Extra method %s called\n", method_name); \
44             if (*expected_method_list) \
45             { \
46                 ok(!strcmp(*expected_method_list, method_name), "Expected %s to be called instead of %s\n", \
47                    *expected_method_list, method_name); \
48                        expected_method_list++; \
49             } \
50 } while(0)
51
52 static char const * const *expected_method_list;
53 static const WCHAR wszFileName1[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','1','.','d','o','c',0};
54 static const WCHAR wszFileName2[] = {'c',':','\\','w','i','n','d','o','w','s','\\','t','e','s','t','2','.','d','o','c',0};
55
56 static const CLSID CLSID_WineTest =
57 { /* 9474ba1a-258b-490b-bc13-516e9239ace0 */
58     0x9474ba1a,
59     0x258b,
60     0x490b,
61     {0xbc, 0x13, 0x51, 0x6e, 0x92, 0x39, 0xac, 0xe0}
62 };
63
64 static const CLSID CLSID_TestMoniker =
65 { /* b306bfbc-496e-4f53-b93e-2ff9c83223d7 */
66     0xb306bfbc,
67     0x496e,
68     0x4f53,
69     {0xb9, 0x3e, 0x2f, 0xf9, 0xc8, 0x32, 0x23, 0xd7}
70 };
71
72 static LONG cLocks;
73
74 static void LockModule(void)
75 {
76     InterlockedIncrement(&cLocks);
77 }
78
79 static void UnlockModule(void)
80 {
81     InterlockedDecrement(&cLocks);
82 }
83
84 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
85     LPCLASSFACTORY iface,
86     REFIID riid,
87     LPVOID *ppvObj)
88 {
89     if (ppvObj == NULL) return E_POINTER;
90
91     if (IsEqualGUID(riid, &IID_IUnknown) ||
92         IsEqualGUID(riid, &IID_IClassFactory))
93     {
94         *ppvObj = (LPVOID)iface;
95         IClassFactory_AddRef(iface);
96         return S_OK;
97     }
98
99     *ppvObj = NULL;
100     return E_NOINTERFACE;
101 }
102
103 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
104 {
105     LockModule();
106     return 2; /* non-heap-based object */
107 }
108
109 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
110 {
111     UnlockModule();
112     return 1; /* non-heap-based object */
113 }
114
115 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
116     LPCLASSFACTORY iface,
117     LPUNKNOWN pUnkOuter,
118     REFIID riid,
119     LPVOID *ppvObj)
120 {
121     return E_NOTIMPL;
122 }
123
124 static HRESULT WINAPI Test_IClassFactory_LockServer(
125     LPCLASSFACTORY iface,
126     BOOL fLock)
127 {
128     return S_OK;
129 }
130
131 static const IClassFactoryVtbl TestClassFactory_Vtbl =
132 {
133     Test_IClassFactory_QueryInterface,
134     Test_IClassFactory_AddRef,
135     Test_IClassFactory_Release,
136     Test_IClassFactory_CreateInstance,
137     Test_IClassFactory_LockServer
138 };
139
140 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
141
142 static HRESULT WINAPI
143 MonikerNoROTData_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
144 {
145     if (!ppvObject)
146         return E_INVALIDARG;
147
148     *ppvObject = 0;
149
150     if (IsEqualIID(&IID_IUnknown, riid)      ||
151         IsEqualIID(&IID_IPersist, riid)      ||
152         IsEqualIID(&IID_IPersistStream,riid) ||
153         IsEqualIID(&IID_IMoniker, riid))
154         *ppvObject = iface;
155     if (IsEqualIID(&IID_IROTData, riid))
156         CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
157
158     if ((*ppvObject)==0)
159         return E_NOINTERFACE;
160
161     IMoniker_AddRef(iface);
162
163     return S_OK;
164 }
165
166 static ULONG WINAPI
167 Moniker_AddRef(IMoniker* iface)
168 {
169     return 2;
170 }
171
172 static ULONG WINAPI
173 Moniker_Release(IMoniker* iface)
174 {
175     return 1;
176 }
177
178 static HRESULT WINAPI
179 Moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
180 {
181     CHECK_EXPECTED_METHOD("Moniker_GetClassID");
182
183     *pClassID = CLSID_TestMoniker;
184
185     return S_OK;
186 }
187
188 static HRESULT WINAPI
189 Moniker_IsDirty(IMoniker* iface)
190 {
191     CHECK_EXPECTED_METHOD("Moniker_IsDirty");
192
193     return S_FALSE;
194 }
195
196 static HRESULT WINAPI
197 Moniker_Load(IMoniker* iface, IStream* pStm)
198 {
199     CHECK_EXPECTED_METHOD("Moniker_Load");
200     return E_NOTIMPL;
201 }
202
203 static HRESULT WINAPI
204 Moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
205 {
206     CHECK_EXPECTED_METHOD("Moniker_Save");
207     return E_NOTIMPL;
208 }
209
210 static HRESULT WINAPI
211 Moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
212 {
213     CHECK_EXPECTED_METHOD("Moniker_GetSizeMax");
214     return E_NOTIMPL;
215 }
216
217 static HRESULT WINAPI
218 Moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
219                              REFIID riid, VOID** ppvResult)
220 {
221     CHECK_EXPECTED_METHOD("Moniker_BindToObject");
222     return E_NOTIMPL;
223 }
224
225 static HRESULT WINAPI
226 Moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
227                               REFIID riid, VOID** ppvObject)
228 {
229     CHECK_EXPECTED_METHOD("Moniker_BindToStorage");
230     return E_NOTIMPL;
231 }
232
233 static HRESULT WINAPI
234 Moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar,
235                        IMoniker** ppmkToLeft, IMoniker** ppmkReduced)
236 {
237     CHECK_EXPECTED_METHOD("Moniker_Reduce");
238
239     if (ppmkReduced==NULL)
240         return E_POINTER;
241
242     IMoniker_AddRef(iface);
243
244     *ppmkReduced=iface;
245
246     return MK_S_REDUCED_TO_SELF;
247 }
248
249 static HRESULT WINAPI
250 Moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight,
251                             BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite)
252 {
253     CHECK_EXPECTED_METHOD("Moniker_ComposeWith");
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI
258 Moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
259 {
260     CHECK_EXPECTED_METHOD("Moniker_Enum");
261
262     if (ppenumMoniker == NULL)
263         return E_POINTER;
264
265     *ppenumMoniker = NULL;
266
267     return S_OK;
268 }
269
270 static HRESULT WINAPI
271 Moniker_IsEqual(IMoniker* iface,IMoniker* pmkOtherMoniker)
272 {
273     CHECK_EXPECTED_METHOD("Moniker_IsEqual");
274     return E_NOTIMPL;
275 }
276
277 static HRESULT WINAPI
278 Moniker_Hash(IMoniker* iface,DWORD* pdwHash)
279 {
280     CHECK_EXPECTED_METHOD("Moniker_Hash");
281     return E_NOTIMPL;
282 }
283
284 static HRESULT WINAPI
285 Moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
286                           IMoniker* pmkNewlyRunning)
287 {
288     CHECK_EXPECTED_METHOD("Moniker_IsRunning");
289     return E_NOTIMPL;
290 }
291
292 static HRESULT WINAPI
293 Moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc,
294                                     IMoniker* pmkToLeft, FILETIME* pFileTime)
295 {
296     CHECK_EXPECTED_METHOD("Moniker_GetTimeOfLastChange");
297     return E_NOTIMPL;
298 }
299
300 static HRESULT WINAPI
301 Moniker_Inverse(IMoniker* iface,IMoniker** ppmk)
302 {
303     CHECK_EXPECTED_METHOD("Moniker_Inverse");
304     return E_NOTIMPL;
305 }
306
307 static HRESULT WINAPI
308 Moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
309 {
310     CHECK_EXPECTED_METHOD("Moniker_CommonPrefixWith");
311     return E_NOTIMPL;
312 }
313
314 static HRESULT WINAPI
315 Moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
316 {
317     CHECK_EXPECTED_METHOD("Moniker_RelativePathTo");
318     return E_NOTIMPL;
319 }
320
321 static HRESULT WINAPI
322 Moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
323                                IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
324 {
325     static const WCHAR wszDisplayName[] = {'*','*','G','e','m','m','a',0};
326     CHECK_EXPECTED_METHOD("Moniker_GetDisplayName");
327     *ppszDisplayName = (LPOLESTR)CoTaskMemAlloc(sizeof(wszDisplayName));
328     memcpy(*ppszDisplayName, wszDisplayName, sizeof(wszDisplayName));
329     return S_OK;
330 }
331
332 static HRESULT WINAPI
333 Moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft,
334                      LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut)
335 {
336     CHECK_EXPECTED_METHOD("Moniker_ParseDisplayName");
337     return E_NOTIMPL;
338 }
339
340 static HRESULT WINAPI
341 Moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
342 {
343     CHECK_EXPECTED_METHOD("Moniker_IsSystemMoniker");
344
345     if (!pwdMksys)
346         return E_POINTER;
347
348     (*pwdMksys)=MKSYS_NONE;
349
350     return S_FALSE;
351 }
352
353 static const IMonikerVtbl MonikerNoROTDataVtbl =
354 {
355     MonikerNoROTData_QueryInterface,
356     Moniker_AddRef,
357     Moniker_Release,
358     Moniker_GetClassID,
359     Moniker_IsDirty,
360     Moniker_Load,
361     Moniker_Save,
362     Moniker_GetSizeMax,
363     Moniker_BindToObject,
364     Moniker_BindToStorage,
365     Moniker_Reduce,
366     Moniker_ComposeWith,
367     Moniker_Enum,
368     Moniker_IsEqual,
369     Moniker_Hash,
370     Moniker_IsRunning,
371     Moniker_GetTimeOfLastChange,
372     Moniker_Inverse,
373     Moniker_CommonPrefixWith,
374     Moniker_RelativePathTo,
375     Moniker_GetDisplayName,
376     Moniker_ParseDisplayName,
377     Moniker_IsSystemMoniker
378 };
379
380 static IMoniker MonikerNoROTData = { &MonikerNoROTDataVtbl };
381
382 static IMoniker Moniker;
383
384 static HRESULT WINAPI
385 ROTData_QueryInterface(IROTData *iface,REFIID riid,VOID** ppvObject)
386 {
387     return IMoniker_QueryInterface(&Moniker, riid, ppvObject);
388 }
389
390 static ULONG WINAPI
391 ROTData_AddRef(IROTData *iface)
392 {
393     return 2;
394 }
395
396 static ULONG WINAPI
397 ROTData_Release(IROTData* iface)
398 {
399     return 1;
400 }
401
402 static HRESULT WINAPI
403 ROTData_GetComparisonData(IROTData* iface, BYTE* pbData,
404                                           ULONG cbMax, ULONG* pcbData)
405 {
406     CHECK_EXPECTED_METHOD("ROTData_GetComparisonData");
407
408     *pcbData = 1;
409     if (cbMax < *pcbData)
410         return E_OUTOFMEMORY;
411
412     *pbData = 0xde;
413
414     return S_OK;
415 }
416
417 static IROTDataVtbl ROTDataVtbl =
418 {
419     ROTData_QueryInterface,
420     ROTData_AddRef,
421     ROTData_Release,
422     ROTData_GetComparisonData
423 };
424
425 static IROTData ROTData = { &ROTDataVtbl };
426
427 static HRESULT WINAPI
428 Moniker_QueryInterface(IMoniker* iface,REFIID riid,void** ppvObject)
429 {
430     if (!ppvObject)
431         return E_INVALIDARG;
432
433     *ppvObject = 0;
434
435     if (IsEqualIID(&IID_IUnknown, riid)      ||
436         IsEqualIID(&IID_IPersist, riid)      ||
437         IsEqualIID(&IID_IPersistStream,riid) ||
438         IsEqualIID(&IID_IMoniker, riid))
439         *ppvObject = iface;
440     if (IsEqualIID(&IID_IROTData, riid))
441     {
442         CHECK_EXPECTED_METHOD("Moniker_QueryInterface(IID_IROTData)");
443         *ppvObject = &ROTData;
444     }
445
446     if ((*ppvObject)==0)
447         return E_NOINTERFACE;
448
449     IMoniker_AddRef(iface);
450
451     return S_OK;
452 }
453
454 static const IMonikerVtbl MonikerVtbl =
455 {
456     Moniker_QueryInterface,
457     Moniker_AddRef,
458     Moniker_Release,
459     Moniker_GetClassID,
460     Moniker_IsDirty,
461     Moniker_Load,
462     Moniker_Save,
463     Moniker_GetSizeMax,
464     Moniker_BindToObject,
465     Moniker_BindToStorage,
466     Moniker_Reduce,
467     Moniker_ComposeWith,
468     Moniker_Enum,
469     Moniker_IsEqual,
470     Moniker_Hash,
471     Moniker_IsRunning,
472     Moniker_GetTimeOfLastChange,
473     Moniker_Inverse,
474     Moniker_CommonPrefixWith,
475     Moniker_RelativePathTo,
476     Moniker_GetDisplayName,
477     Moniker_ParseDisplayName,
478     Moniker_IsSystemMoniker
479 };
480
481 static IMoniker Moniker = { &MonikerVtbl };
482
483 static void test_ROT(void)
484 {
485     static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
486         '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
487         '2','0','4','6','E','5','8','6','C','9','2','5',0};
488     HRESULT hr;
489     IMoniker *pMoniker = NULL;
490     IRunningObjectTable *pROT = NULL;
491     DWORD dwCookie;
492     static const char *methods_register_no_ROTData[] =
493     {
494         "Moniker_Reduce",
495         "Moniker_GetTimeOfLastChange",
496         "Moniker_QueryInterface(IID_IROTData)",
497         "Moniker_GetDisplayName",
498         "Moniker_GetClassID",
499         NULL
500     };
501     static const char *methods_register[] =
502     {
503         "Moniker_Reduce",
504         "Moniker_GetTimeOfLastChange",
505         "Moniker_QueryInterface(IID_IROTData)",
506         "ROTData_GetComparisonData",
507         NULL
508     };
509     static const char *methods_isrunning_no_ROTData[] =
510     {
511         "Moniker_Reduce",
512         "Moniker_QueryInterface(IID_IROTData)",
513         "Moniker_GetDisplayName",
514         "Moniker_GetClassID",
515         NULL
516     };
517     static const char *methods_isrunning[] =
518     {
519         "Moniker_Reduce",
520         "Moniker_QueryInterface(IID_IROTData)",
521         "ROTData_GetComparisonData",
522         NULL
523     };
524
525     cLocks = 0;
526
527     hr = GetRunningObjectTable(0, &pROT);
528     ok_ole_success(hr, GetRunningObjectTable);
529
530     expected_method_list = methods_register_no_ROTData;
531     /* try with our own moniker that doesn't support IROTData */
532     hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
533         (IUnknown*)&Test_ClassFactory, &MonikerNoROTData, &dwCookie);
534     todo_wine { /* only fails because of lack of IMoniker marshaling */
535     ok_ole_success(hr, IRunningObjectTable_Register);
536     }
537     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
538
539     todo_wine { /* only fails because of lack of IMoniker marshaling */
540     ok_more_than_one_lock();
541     }
542
543     expected_method_list = methods_isrunning_no_ROTData;
544     hr = IRunningObjectTable_IsRunning(pROT, &MonikerNoROTData);
545     todo_wine { /* only fails because of lack of IMoniker marshaling */
546     ok_ole_success(hr, IRunningObjectTable_IsRunning);
547     }
548     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
549
550     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
551     todo_wine { /* only fails because of lack of IMoniker marshaling */
552     ok_ole_success(hr, IRunningObjectTable_Revoke);
553     }
554
555     ok_no_locks();
556
557     expected_method_list = methods_register;
558     /* try with our own moniker */
559     hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
560         (IUnknown*)&Test_ClassFactory, &Moniker, &dwCookie);
561     todo_wine { /* only fails because of lack of IMoniker marshaling */
562     ok_ole_success(hr, IRunningObjectTable_Register);
563     }
564     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
565
566     todo_wine { /* only fails because of lack of IMoniker marshaling */
567     ok_more_than_one_lock();
568     }
569
570     expected_method_list = methods_isrunning;
571     hr = IRunningObjectTable_IsRunning(pROT, &Moniker);
572     todo_wine { /* only fails because of lack of IMoniker marshaling */
573     ok_ole_success(hr, IRunningObjectTable_IsRunning);
574     }
575     ok(!*expected_method_list, "Method sequence starting from %s not called\n", *expected_method_list);
576
577     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
578     todo_wine { /* only fails because of lack of IMoniker marshaling */
579     ok_ole_success(hr, IRunningObjectTable_Revoke);
580     }
581
582     ok_no_locks();
583
584     hr = CreateFileMoniker(wszFileName, &pMoniker);
585     ok_ole_success(hr, CreateClassMoniker);
586
587     /* test flags: 0 */
588     hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory,
589                                       pMoniker, &dwCookie);
590     ok_ole_success(hr, IRunningObjectTable_Register);
591     IMoniker_Release(pMoniker);
592
593     ok_more_than_one_lock();
594
595     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
596     ok_ole_success(hr, IRunningObjectTable_Revoke);
597
598     ok_no_locks();
599
600     /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE */
601     hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
602         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
603     ok_ole_success(hr, IRunningObjectTable_Register);
604
605     ok_more_than_one_lock();
606
607     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
608     ok_ole_success(hr, IRunningObjectTable_Revoke);
609
610     ok_no_locks();
611
612     /* test flags: ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT */
613     /* only succeeds when process is started by SCM and has LocalService
614      * or RunAs AppId values */
615     hr = IRunningObjectTable_Register(pROT,
616         ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
617         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
618     todo_wine {
619     ok(hr == CO_E_WRONG_SERVER_IDENTITY, "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
620     }
621
622     hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
623         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
624     ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
625
626     IMoniker_Release(pMoniker);
627
628     IRunningObjectTable_Release(pROT);
629 }
630
631 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
632 {
633     IMoniker * spMoniker;
634     int monCnt=0, matchCnt=0;
635
636     while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
637     {
638         HRESULT hr;
639         WCHAR * szDisplayn;
640         monCnt++;
641         hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
642         if (SUCCEEDED(hr))
643         {
644             if (!lstrcmpW(szDisplayn, wszFileName1) || !lstrcmpW(szDisplayn, wszFileName2))
645                 matchCnt++;
646             CoTaskMemFree(szDisplayn);
647         }
648     }
649     trace("Total number of monikers is %i\n", monCnt);
650     return matchCnt;
651 }
652
653 static void test_MkParseDisplayName(void)
654 {
655     IBindCtx * pbc = NULL;
656     HRESULT hr;
657     IMoniker * pmk  = NULL;
658     IMoniker * pmk1 = NULL;
659     IMoniker * pmk2 = NULL;
660     ULONG eaten;
661     int matchCnt;
662     IUnknown * object = NULL;
663
664     IUnknown *lpEM1;
665
666     IEnumMoniker *spEM1  = NULL;
667     IEnumMoniker *spEM2  = NULL;
668     IEnumMoniker *spEM3  = NULL;
669
670     DWORD pdwReg1=0;
671     DWORD grflags=0;
672     DWORD pdwReg2=0;
673     IRunningObjectTable * pprot=NULL;
674
675     /* CLSID of My Computer */
676     static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
677         '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};
678
679     hr = CreateBindCtx(0, &pbc);
680     ok_ole_success(hr, CreateBindCtx);
681
682     hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
683     todo_wine { ok_ole_success(hr, MkParseDisplayName); }
684
685     if (object)
686     {
687         hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
688         ok_ole_success(hr, IMoniker_BindToObject);
689
690         IUnknown_Release(object);
691     }
692     IBindCtx_Release(pbc);
693
694     /* Test the EnumMoniker interface */
695     hr = CreateBindCtx(0, &pbc);
696     ok_ole_success(hr, CreateBindCtx);
697
698     hr = CreateFileMoniker(wszFileName1, &pmk1);
699     ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
700     hr = CreateFileMoniker(wszFileName2, &pmk2);
701     ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
702     hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
703     ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
704
705     /* Check EnumMoniker before registering */
706     hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
707     ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
708     hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
709     /* Register a couple of Monikers and check is ok */
710     ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
711     hr = MK_E_NOOBJECT;
712     
713     matchCnt = count_moniker_matches(pbc, spEM1);
714     trace("Number of matches is %i\n", matchCnt);
715
716     grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
717     hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
718     ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
719         hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
720
721     trace("IROT::Register\n");
722     grflags=0;
723     grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
724     hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
725     ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
726        pprot, grflags, lpEM1, pmk2, pdwReg2);
727
728     hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
729     ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
730
731     matchCnt = count_moniker_matches(pbc, spEM2);
732     ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
733
734     trace("IEnumMoniker::Clone\n");
735     IEnumMoniker_Clone(spEM2, &spEM3);
736
737     matchCnt = count_moniker_matches(pbc, spEM3);
738     ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
739     trace("IEnumMoniker::Reset\n");
740     IEnumMoniker_Reset(spEM3);
741
742     matchCnt = count_moniker_matches(pbc, spEM3);
743     ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
744
745     IRunningObjectTable_Revoke(pprot,pdwReg1);
746     IRunningObjectTable_Revoke(pprot,pdwReg2);
747     IEnumMoniker_Release(spEM1);
748     IEnumMoniker_Release(spEM1);
749     IEnumMoniker_Release(spEM2);
750     IEnumMoniker_Release(spEM3);
751     IMoniker_Release(pmk1);
752     IMoniker_Release(pmk2);
753     IRunningObjectTable_Release(pprot);
754
755     IBindCtx_Release(pbc);
756 }
757
758 static const LARGE_INTEGER llZero;
759
760 static const BYTE expected_class_moniker_marshal_data[] =
761 {
762     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
763     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
764     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
765     0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
766     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
767     0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
768     0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
769     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
770     0x00,0x00,0x00,0x00,
771 };
772
773 static const BYTE expected_class_moniker_saved_data[] =
774 {
775      0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
776      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
777      0x00,0x00,0x00,0x00,
778 };
779
780 static const BYTE expected_class_moniker_comparison_data[] =
781 {
782      0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
783      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
784      0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
785      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
786 };
787
788 static const WCHAR expected_class_moniker_display_name[] =
789 {
790     'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
791     '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
792     '0','0','0','0','4','6',':',0
793 };
794
795 static const BYTE expected_item_moniker_comparison_data[] =
796 {
797      0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
798      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
799      0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
800      0x54,0x00,0x00,0x00,
801 };
802
803 static const BYTE expected_item_moniker_saved_data[] =
804 {
805      0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
806      0x00,0x00,0x54,0x65,0x73,0x74,0x00,
807 };
808
809 static const BYTE expected_item_moniker_marshal_data[] =
810 {
811      0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
812      0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
813      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
814      0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
815      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
816      0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
817      0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
818      0x00,0x00,0x54,0x65,0x73,0x74,0x00,
819 };
820
821 static const BYTE expected_anti_moniker_marshal_data[] =
822 {
823     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
824     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
825     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
826     0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
827     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
828     0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
829     0x01,0x00,0x00,0x00,
830 };
831
832 static const BYTE expected_anti_moniker_saved_data[] =
833 {
834     0x01,0x00,0x00,0x00,
835 };
836
837 static const BYTE expected_anti_moniker_comparison_data[] =
838 {
839     0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
840     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
841     0x01,0x00,0x00,0x00,
842 };
843
844 static const BYTE expected_gc_moniker_marshal_data[] =
845 {
846     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
847     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
848     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
849     0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
850     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
851     0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
852     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
853     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
854     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
855     0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
856     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
857     0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
858     0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
859     0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
860     0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
861     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
862     0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
863     0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
864     0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
865     0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
866     0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
867     0x00,0x57,0x69,0x6e,0x65,0x00,
868 };
869
870 static const BYTE expected_gc_moniker_saved_data[] =
871 {
872     0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
873     0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
874     0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
875     0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
876     0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
877     0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
878     0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
879     0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
880     0x65,0x00,
881 };
882
883 static const BYTE expected_gc_moniker_comparison_data[] =
884 {
885     0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
886     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
887     0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
888     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
889     0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
890     0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
891     0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
892     0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
893     0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
894 };
895
896 static void test_moniker(
897     const char *testname, IMoniker *moniker,
898     const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
899     const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
900     const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
901     LPCWSTR expected_display_name)
902 {
903     IStream * stream;
904     IROTData * rotdata;
905     HRESULT hr;
906     HGLOBAL hglobal;
907     LPBYTE moniker_data;
908     DWORD moniker_size;
909     DWORD i;
910     BOOL same = TRUE;
911     BYTE buffer[128];
912     IMoniker * moniker_proxy;
913     LPOLESTR display_name;
914     IBindCtx *bindctx;
915
916     hr = IMoniker_IsDirty(moniker);
917     ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
918
919     /* Display Name */
920
921     hr = CreateBindCtx(0, &bindctx);
922     ok_ole_success(hr, CreateBindCtx);
923
924     hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
925     ok_ole_success(hr, IMoniker_GetDisplayName);
926         ok(!lstrcmpW(display_name, expected_display_name), "display name wasn't what was expected\n");
927
928     CoTaskMemFree(display_name);
929     IBindCtx_Release(bindctx);
930
931     hr = IMoniker_IsDirty(moniker);
932     ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
933
934     /* IROTData::GetComparisonData test */
935
936     hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
937     ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
938
939     hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
940     ok_ole_success(hr, IROTData_GetComparisonData);
941
942     if (hr != S_OK) moniker_size = 0;
943
944     /* first check we have the right amount of data */
945     ok(moniker_size == sizeof_expected_moniker_comparison_data,
946         "%s: Size of comparison data differs (expected %d, actual %d)\n",
947         testname, sizeof_expected_moniker_comparison_data, moniker_size);
948
949     /* then do a byte-by-byte comparison */
950     for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
951     {
952         if (expected_moniker_comparison_data[i] != buffer[i])
953         {
954             same = FALSE;
955             break;
956         }
957     }
958
959     ok(same, "%s: Comparison data differs\n", testname);
960     if (!same)
961     {
962         for (i = 0; i < moniker_size; i++)
963         {
964             if (i % 8 == 0) printf("     ");
965             printf("0x%02x,", buffer[i]);
966             if (i % 8 == 7) printf("\n");
967         }
968         printf("\n");
969     }
970
971     IROTData_Release(rotdata);
972   
973     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
974   
975     /* Saving */
976
977     hr = IMoniker_Save(moniker, stream, TRUE);
978     ok_ole_success(hr, IMoniker_Save);
979
980     hr = GetHGlobalFromStream(stream, &hglobal);
981     ok_ole_success(hr, GetHGlobalFromStream);
982
983     moniker_size = GlobalSize(hglobal);
984
985     moniker_data = GlobalLock(hglobal);
986
987     /* first check we have the right amount of data */
988     ok(moniker_size == sizeof_expected_moniker_saved_data,
989         "%s: Size of saved data differs (expected %d, actual %d)\n",
990         testname, sizeof_expected_moniker_saved_data, moniker_size);
991
992     /* then do a byte-by-byte comparison */
993     for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
994     {
995         if (expected_moniker_saved_data[i] != moniker_data[i])
996         {
997             same = FALSE;
998             break;
999         }
1000     }
1001
1002     ok(same, "%s: Saved data differs\n", testname);
1003     if (!same)
1004     {
1005         for (i = 0; i < moniker_size; i++)
1006         {
1007             if (i % 8 == 0) printf("     ");
1008             printf("0x%02x,", moniker_data[i]);
1009             if (i % 8 == 7) printf("\n");
1010         }
1011         printf("\n");
1012     }
1013
1014     GlobalUnlock(hglobal);
1015
1016     IStream_Release(stream);
1017
1018     /* Marshaling tests */
1019
1020     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1021     ok_ole_success(hr, CreateStreamOnHGlobal);
1022
1023     hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1024     ok_ole_success(hr, CoMarshalInterface);
1025
1026     hr = GetHGlobalFromStream(stream, &hglobal);
1027     ok_ole_success(hr, GetHGlobalFromStream);
1028
1029     moniker_size = GlobalSize(hglobal);
1030
1031     moniker_data = GlobalLock(hglobal);
1032
1033     /* first check we have the right amount of data */
1034     ok(moniker_size == sizeof_expected_moniker_marshal_data,
1035         "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1036         testname, sizeof_expected_moniker_marshal_data, moniker_size);
1037
1038     /* then do a byte-by-byte comparison */
1039     if (expected_moniker_marshal_data)
1040     {
1041         for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1042         {
1043             if (expected_moniker_marshal_data[i] != moniker_data[i])
1044             {
1045                 same = FALSE;
1046                 break;
1047             }
1048         }
1049     }
1050
1051     ok(same, "%s: Marshaled data differs\n", testname);
1052     if (!same)
1053     {
1054         for (i = 0; i < moniker_size; i++)
1055         {
1056             if (i % 8 == 0) printf("     ");
1057             printf("0x%02x,", moniker_data[i]);
1058             if (i % 8 == 7) printf("\n");
1059         }
1060         printf("\n");
1061     }
1062
1063     GlobalUnlock(hglobal);
1064
1065     IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1066     hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1067     ok_ole_success(hr, CoUnmarshalInterface);
1068
1069     IStream_Release(stream);
1070     IMoniker_Release(moniker_proxy);
1071 }
1072
1073 static void test_class_moniker(void)
1074 {
1075     HRESULT hr;
1076     IMoniker *moniker;
1077     DWORD moniker_type;
1078     DWORD hash;
1079     IBindCtx *bindctx;
1080     IMoniker *inverse;
1081     IUnknown *unknown;
1082     FILETIME filetime;
1083
1084     hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1085     ok_ole_success(hr, CreateClassMoniker);
1086     if (!moniker) return;
1087
1088     test_moniker("class moniker", moniker, 
1089         expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1090         expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1091         expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1092         expected_class_moniker_display_name);
1093
1094     /* Hashing */
1095
1096     hr = IMoniker_Hash(moniker, &hash);
1097     ok_ole_success(hr, IMoniker_Hash);
1098
1099     ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1100         "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1101         hash);
1102
1103     /* IsSystemMoniker test */
1104
1105     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1106     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1107
1108     ok(moniker_type == MKSYS_CLASSMONIKER,
1109         "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1110         moniker_type);
1111
1112     hr = CreateBindCtx(0, &bindctx);
1113     ok_ole_success(hr, CreateBindCtx);
1114
1115     /* IsRunning test */
1116     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1117     ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1118
1119     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1120     ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1121
1122     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1123     ok_ole_success(hr, IMoniker_BindToStorage);
1124     IUnknown_Release(unknown);
1125
1126     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1127     ok_ole_success(hr, IMoniker_BindToStorage);
1128     IUnknown_Release(unknown);
1129
1130     IBindCtx_Release(bindctx);
1131
1132     hr = IMoniker_Inverse(moniker, &inverse);
1133     ok_ole_success(hr, IMoniker_Inverse);
1134     IMoniker_Release(inverse);
1135
1136     IMoniker_Release(moniker);
1137 }
1138
1139 static void test_file_moniker(WCHAR* path)
1140 {
1141     IStream *stream;
1142     IMoniker *moniker1 = NULL, *moniker2 = NULL;
1143     HRESULT hr;
1144
1145     hr = CreateFileMoniker(path, &moniker1);
1146     ok_ole_success(hr, CreateFileMoniker); 
1147
1148     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1149
1150     /* Marshal */
1151     hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1152     ok_ole_success(hr, CoMarshalInterface);
1153     
1154     /* Rewind */
1155     hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1156     ok_ole_success(hr, IStream_Seek);
1157
1158     /* Unmarshal */
1159     hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1160     ok_ole_success(hr, CoUnmarshalInterface);
1161
1162     hr = IMoniker_IsEqual(moniker1, moniker2);
1163     ok_ole_success(hr, IsEqual);
1164
1165     IStream_Release(stream);
1166     if (moniker1) 
1167         IMoniker_Release(moniker1);
1168     if (moniker2) 
1169         IMoniker_Release(moniker2);
1170 }
1171
1172 static void test_file_monikers(void)
1173 {
1174     static WCHAR wszFile[][30] = {
1175         {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1176         {'\\', '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},
1177         /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1178         {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1179         /* U+2020 = DAGGER     = 0x86 (1252) = 0x813f (932)
1180          * U+20AC = EURO SIGN  = 0x80 (1252) =  undef (932)
1181          * U+0100 .. = Latin extended-A
1182          */ 
1183         {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c,  0},
1184         };
1185
1186     int i; 
1187
1188     trace("ACP is %u\n", GetACP());
1189
1190     for (i = 0; i < COUNTOF(wszFile); ++i)
1191     {
1192         int j ;
1193         for (j = lstrlenW(wszFile[i]); j > 0; --j)
1194         {
1195             wszFile[i][j] = 0;
1196             test_file_moniker(wszFile[i]);
1197         }
1198     }
1199 }
1200
1201 static void test_item_moniker(void)
1202 {
1203     HRESULT hr;
1204     IMoniker *moniker;
1205     DWORD moniker_type;
1206     DWORD hash;
1207     IBindCtx *bindctx;
1208     IMoniker *inverse;
1209     IUnknown *unknown;
1210     static const WCHAR wszDelimeter[] = {'!',0};
1211     static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1212     static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1213
1214     hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1215     ok_ole_success(hr, CreateItemMoniker);
1216
1217     test_moniker("item moniker", moniker, 
1218         expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1219         expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1220         expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1221         expected_display_name);
1222
1223     /* Hashing */
1224
1225     hr = IMoniker_Hash(moniker, &hash);
1226     ok_ole_success(hr, IMoniker_Hash);
1227
1228     ok(hash == 0x73c,
1229         "Hash value != 0x73c, instead was 0x%08x\n",
1230         hash);
1231
1232     /* IsSystemMoniker test */
1233
1234     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1235     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1236
1237     ok(moniker_type == MKSYS_ITEMMONIKER,
1238         "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1239         moniker_type);
1240
1241     hr = CreateBindCtx(0, &bindctx);
1242     ok_ole_success(hr, CreateBindCtx);
1243
1244     /* IsRunning test */
1245     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1246     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1247
1248     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1249     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1250
1251     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1252     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1253
1254     IBindCtx_Release(bindctx);
1255
1256     hr = IMoniker_Inverse(moniker, &inverse);
1257     ok_ole_success(hr, IMoniker_Inverse);
1258     IMoniker_Release(inverse);
1259
1260     IMoniker_Release(moniker);
1261 }
1262
1263 static void test_anti_moniker(void)
1264 {
1265     HRESULT hr;
1266     IMoniker *moniker;
1267     DWORD moniker_type;
1268     DWORD hash;
1269     IBindCtx *bindctx;
1270     FILETIME filetime;
1271     IMoniker *inverse;
1272     IUnknown *unknown;
1273     static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1274
1275     hr = CreateAntiMoniker(&moniker);
1276     ok_ole_success(hr, CreateAntiMoniker);
1277     if (!moniker) return;
1278
1279     test_moniker("anti moniker", moniker, 
1280         expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1281         expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1282         expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1283         expected_display_name);
1284
1285     /* Hashing */
1286     hr = IMoniker_Hash(moniker, &hash);
1287     ok_ole_success(hr, IMoniker_Hash);
1288     ok(hash == 0x80000001,
1289         "Hash value != 0x80000001, instead was 0x%08x\n",
1290         hash);
1291
1292     /* IsSystemMoniker test */
1293     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1294     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1295     ok(moniker_type == MKSYS_ANTIMONIKER,
1296         "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1297         moniker_type);
1298
1299     hr = IMoniker_Inverse(moniker, &inverse);
1300     ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1301     ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1302
1303     hr = CreateBindCtx(0, &bindctx);
1304     ok_ole_success(hr, CreateBindCtx);
1305
1306     /* IsRunning test */
1307     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1308     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1309
1310     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1311     ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1312
1313     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1314     ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1315
1316     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1317     ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1318
1319     IBindCtx_Release(bindctx);
1320
1321     IMoniker_Release(moniker);
1322 }
1323
1324 static void test_generic_composite_moniker(void)
1325 {
1326     HRESULT hr;
1327     IMoniker *moniker;
1328     IMoniker *moniker1;
1329     IMoniker *moniker2;
1330     DWORD moniker_type;
1331     DWORD hash;
1332     IBindCtx *bindctx;
1333     FILETIME filetime;
1334     IMoniker *inverse;
1335     IUnknown *unknown;
1336     static const WCHAR wszDelimeter1[] = {'!',0};
1337     static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1338     static const WCHAR wszDelimeter2[] = {'#',0};
1339     static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1340     static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1341
1342     hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1343     ok_ole_success(hr, CreateItemMoniker);
1344     hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1345     ok_ole_success(hr, CreateItemMoniker);
1346     hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1347     ok_ole_success(hr, CreateGenericComposite);
1348
1349     test_moniker("generic composite moniker", moniker, 
1350         expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1351         expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1352         expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1353         expected_display_name);
1354
1355     /* Hashing */
1356
1357     hr = IMoniker_Hash(moniker, &hash);
1358     ok_ole_success(hr, IMoniker_Hash);
1359
1360     ok(hash == 0xd87,
1361         "Hash value != 0xd87, instead was 0x%08x\n",
1362         hash);
1363
1364     /* IsSystemMoniker test */
1365
1366     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1367     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1368
1369     ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1370         "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1371         moniker_type);
1372
1373     hr = CreateBindCtx(0, &bindctx);
1374     ok_ole_success(hr, CreateBindCtx);
1375
1376     /* IsRunning test */
1377     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1378     todo_wine
1379     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1380
1381     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1382     ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1383
1384     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1385     todo_wine
1386     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1387
1388     todo_wine
1389     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1390     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1391
1392     IBindCtx_Release(bindctx);
1393
1394     hr = IMoniker_Inverse(moniker, &inverse);
1395     ok_ole_success(hr, IMoniker_Inverse);
1396     IMoniker_Release(inverse);
1397
1398     IMoniker_Release(moniker);
1399 }
1400
1401 START_TEST(moniker)
1402 {
1403     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1404
1405     test_ROT();
1406     test_MkParseDisplayName();
1407     test_class_moniker();
1408     test_file_monikers();
1409     test_item_moniker();
1410     test_anti_moniker();
1411     test_generic_composite_moniker();
1412
1413     /* FIXME: test moniker creation funcs and parsing other moniker formats */
1414
1415     CoUninitialize();
1416 }