advapi32: Remove a useless macro.
[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     hr = IRunningObjectTable_Register(pROT, ROTFLAGS_REGISTRATIONKEEPSALIVE,
588         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
589     ok_ole_success(hr, IRunningObjectTable_Register);
590
591     ok_more_than_one_lock();
592
593     hr = IRunningObjectTable_Revoke(pROT, dwCookie);
594     ok_ole_success(hr, IRunningObjectTable_Revoke);
595
596     ok_no_locks();
597
598     /* only succeeds when process is started by SCM and has LocalService
599      * or RunAs AppId values */
600     hr = IRunningObjectTable_Register(pROT,
601         ROTFLAGS_REGISTRATIONKEEPSALIVE|ROTFLAGS_ALLOWANYCLIENT,
602         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
603     todo_wine {
604     ok(hr == CO_E_WRONG_SERVER_IDENTITY, "IRunningObjectTable_Register should have returned CO_E_WRONG_SERVER_IDENTITY instead of 0x%08x\n", hr);
605     }
606
607     hr = IRunningObjectTable_Register(pROT, 0xdeadbeef,
608         (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
609     ok(hr == E_INVALIDARG, "IRunningObjectTable_Register should have returned E_INVALIDARG instead of 0x%08x\n", hr);
610
611     IMoniker_Release(pMoniker);
612
613     IRunningObjectTable_Release(pROT);
614 }
615
616 static int count_moniker_matches(IBindCtx * pbc, IEnumMoniker * spEM)
617 {
618     IMoniker * spMoniker;
619     int monCnt=0, matchCnt=0;
620
621     while ((IEnumMoniker_Next(spEM, 1, &spMoniker, NULL)==S_OK))
622     {
623         HRESULT hr;
624         WCHAR * szDisplayn;
625         monCnt++;
626         hr=IMoniker_GetDisplayName(spMoniker, pbc, NULL, &szDisplayn);
627         if (SUCCEEDED(hr))
628         {
629             if (!lstrcmpW(szDisplayn, wszFileName1) || !lstrcmpW(szDisplayn, wszFileName2))
630                 matchCnt++;
631             CoTaskMemFree(szDisplayn);
632         }
633     }
634     trace("Total number of monikers is %i\n", monCnt);
635     return matchCnt;
636 }
637
638 static void test_MkParseDisplayName(void)
639 {
640     IBindCtx * pbc = NULL;
641     HRESULT hr;
642     IMoniker * pmk  = NULL;
643     IMoniker * pmk1 = NULL;
644     IMoniker * pmk2 = NULL;
645     ULONG eaten;
646     int matchCnt;
647     IUnknown * object = NULL;
648
649     IUnknown *lpEM1;
650
651     IEnumMoniker *spEM1  = NULL;
652     IEnumMoniker *spEM2  = NULL;
653     IEnumMoniker *spEM3  = NULL;
654
655     DWORD pdwReg1=0;
656     DWORD grflags=0;
657     DWORD pdwReg2=0;
658     IRunningObjectTable * pprot=NULL;
659
660     /* CLSID of My Computer */
661     static const WCHAR wszDisplayName[] = {'c','l','s','i','d',':',
662         '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};
663
664     hr = CreateBindCtx(0, &pbc);
665     ok_ole_success(hr, CreateBindCtx);
666
667     hr = MkParseDisplayName(pbc, wszDisplayName, &eaten, &pmk);
668     todo_wine { ok_ole_success(hr, MkParseDisplayName); }
669
670     if (object)
671     {
672         hr = IMoniker_BindToObject(pmk, pbc, NULL, &IID_IUnknown, (LPVOID*)&object);
673         ok_ole_success(hr, IMoniker_BindToObject);
674
675         IUnknown_Release(object);
676     }
677     IBindCtx_Release(pbc);
678
679     /* Test the EnumMoniker interface */
680     hr = CreateBindCtx(0, &pbc);
681     ok_ole_success(hr, CreateBindCtx);
682
683     hr = CreateFileMoniker(wszFileName1, &pmk1);
684     ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
685     hr = CreateFileMoniker(wszFileName2, &pmk2);
686     ok(hr==0, "CreateFileMoniker for file hr=%08x\n", hr);
687     hr = IBindCtx_GetRunningObjectTable(pbc, &pprot);
688     ok(hr==0, "IBindCtx_GetRunningObjectTable hr=%08x\n", hr);
689
690     /* Check EnumMoniker before registering */
691     hr = IRunningObjectTable_EnumRunning(pprot, &spEM1);
692     ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
693     hr = IEnumMoniker_QueryInterface(spEM1, &IID_IUnknown, (void*) &lpEM1);
694     /* Register a couple of Monikers and check is ok */
695     ok(hr==0, "IEnumMoniker_QueryInterface hr %08x %p\n", hr, lpEM1);
696     hr = MK_E_NOOBJECT;
697     
698     matchCnt = count_moniker_matches(pbc, spEM1);
699     trace("Number of matches is %i\n", matchCnt);
700
701     grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
702     hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk1, &pdwReg1);
703     ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n",
704         hr, pprot, grflags, lpEM1, pmk1, pdwReg1);
705
706     trace("IROT::Register\n");
707     grflags=0;
708     grflags= grflags | ROTFLAGS_REGISTRATIONKEEPSALIVE;
709     hr = IRunningObjectTable_Register(pprot, grflags, lpEM1, pmk2, &pdwReg2);
710     ok(hr==0, "IRunningObjectTable_Register hr=%08x %p %08x %p %p %d\n", hr,
711        pprot, grflags, lpEM1, pmk2, pdwReg2);
712
713     hr = IRunningObjectTable_EnumRunning(pprot, &spEM2);
714     ok(hr==0, "IRunningObjectTable_EnumRunning hr=%08x\n", hr);
715
716     matchCnt = count_moniker_matches(pbc, spEM2);
717     ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
718
719     trace("IEnumMoniker::Clone\n");
720     IEnumMoniker_Clone(spEM2, &spEM3);
721
722     matchCnt = count_moniker_matches(pbc, spEM3);
723     ok(matchCnt==0, "Number of matches should be equal to 0 not %i\n", matchCnt);
724     trace("IEnumMoniker::Reset\n");
725     IEnumMoniker_Reset(spEM3);
726
727     matchCnt = count_moniker_matches(pbc, spEM3);
728     ok(matchCnt==2, "Number of matches should be equal to 2 not %i\n", matchCnt);
729
730     IRunningObjectTable_Revoke(pprot,pdwReg1);
731     IRunningObjectTable_Revoke(pprot,pdwReg2);
732     IEnumMoniker_Release(spEM1);
733     IEnumMoniker_Release(spEM1);
734     IEnumMoniker_Release(spEM2);
735     IEnumMoniker_Release(spEM3);
736     IMoniker_Release(pmk1);
737     IMoniker_Release(pmk2);
738     IRunningObjectTable_Release(pprot);
739
740     IBindCtx_Release(pbc);
741 }
742
743 static const LARGE_INTEGER llZero;
744
745 static const BYTE expected_class_moniker_marshal_data[] =
746 {
747     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
748     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
749     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
750     0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
751     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
752     0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
753     0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
754     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
755     0x00,0x00,0x00,0x00,
756 };
757
758 static const BYTE expected_class_moniker_saved_data[] =
759 {
760      0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
761      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
762      0x00,0x00,0x00,0x00,
763 };
764
765 static const BYTE expected_class_moniker_comparison_data[] =
766 {
767      0x1a,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
768      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
769      0x05,0xe0,0x02,0x00,0x00,0x00,0x00,0x00,
770      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
771 };
772
773 static const WCHAR expected_class_moniker_display_name[] =
774 {
775     'c','l','s','i','d',':','0','0','0','2','E','0','0','5','-','0','0','0',
776     '0','-','0','0','0','0','-','C','0','0','0','-','0','0','0','0','0','0',
777     '0','0','0','0','4','6',':',0
778 };
779
780 static const BYTE expected_item_moniker_comparison_data[] =
781 {
782      0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
783      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
784      0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
785      0x54,0x00,0x00,0x00,
786 };
787
788 static const BYTE expected_item_moniker_saved_data[] =
789 {
790      0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
791      0x00,0x00,0x54,0x65,0x73,0x74,0x00,
792 };
793
794 static const BYTE expected_item_moniker_marshal_data[] =
795 {
796      0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
797      0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
798      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
799      0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
800      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
801      0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
802      0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
803      0x00,0x00,0x54,0x65,0x73,0x74,0x00,
804 };
805
806 static const BYTE expected_anti_moniker_marshal_data[] =
807 {
808     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
809     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
810     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
811     0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
812     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
813     0x00,0x00,0x00,0x00,0x14,0x00,0x00,0x00,
814     0x01,0x00,0x00,0x00,
815 };
816
817 static const BYTE expected_anti_moniker_saved_data[] =
818 {
819     0x01,0x00,0x00,0x00,
820 };
821
822 static const BYTE expected_anti_moniker_comparison_data[] =
823 {
824     0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
825     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
826     0x01,0x00,0x00,0x00,
827 };
828
829 static const BYTE expected_gc_moniker_marshal_data[] =
830 {
831     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
832     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
833     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
834     0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
835     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
836     0x00,0x00,0x00,0x00,0x2c,0x01,0x00,0x00,
837     0x4d,0x45,0x4f,0x57,0x04,0x00,0x00,0x00,
838     0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
839     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
840     0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
841     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
842     0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,
843     0x02,0x00,0x00,0x00,0x21,0x00,0x05,0x00,
844     0x00,0x00,0x54,0x65,0x73,0x74,0x00,0x4d,
845     0x45,0x4f,0x57,0x04,0x00,0x00,0x00,0x0f,
846     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
847     0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x04,
848     0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,
849     0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,
850     0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x02,
851     0x00,0x00,0x00,0x23,0x00,0x05,0x00,0x00,
852     0x00,0x57,0x69,0x6e,0x65,0x00,
853 };
854
855 static const BYTE expected_gc_moniker_saved_data[] =
856 {
857     0x02,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
858     0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
859     0x00,0x00,0x00,0x46,0x02,0x00,0x00,0x00,
860     0x21,0x00,0x05,0x00,0x00,0x00,0x54,0x65,
861     0x73,0x74,0x00,0x04,0x03,0x00,0x00,0x00,
862     0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0x00,
863     0x00,0x00,0x46,0x02,0x00,0x00,0x00,0x23,
864     0x00,0x05,0x00,0x00,0x00,0x57,0x69,0x6e,
865     0x65,0x00,
866 };
867
868 static const BYTE expected_gc_moniker_comparison_data[] =
869 {
870     0x09,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
871     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
872     0x04,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
873     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
874     0x21,0x00,0x54,0x00,0x45,0x00,0x53,0x00,
875     0x54,0x00,0x00,0x00,0x04,0x03,0x00,0x00,
876     0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,
877     0x00,0x00,0x00,0x46,0x23,0x00,0x57,0x00,
878     0x49,0x00,0x4e,0x00,0x45,0x00,0x00,0x00,
879 };
880
881 static void test_moniker(
882     const char *testname, IMoniker *moniker,
883     const BYTE *expected_moniker_marshal_data, unsigned int sizeof_expected_moniker_marshal_data,
884     const BYTE *expected_moniker_saved_data, unsigned int sizeof_expected_moniker_saved_data,
885     const BYTE *expected_moniker_comparison_data, unsigned int sizeof_expected_moniker_comparison_data,
886     LPCWSTR expected_display_name)
887 {
888     IStream * stream;
889     IROTData * rotdata;
890     HRESULT hr;
891     HGLOBAL hglobal;
892     LPBYTE moniker_data;
893     DWORD moniker_size;
894     DWORD i;
895     BOOL same = TRUE;
896     BYTE buffer[128];
897     IMoniker * moniker_proxy;
898     LPOLESTR display_name;
899     IBindCtx *bindctx;
900
901     hr = IMoniker_IsDirty(moniker);
902     ok(hr == S_FALSE, "%s: IMoniker_IsDirty should return S_FALSE, not 0x%08x\n", testname, hr);
903
904     /* Display Name */
905
906     hr = CreateBindCtx(0, &bindctx);
907     ok_ole_success(hr, CreateBindCtx);
908
909     hr = IMoniker_GetDisplayName(moniker, bindctx, NULL, &display_name);
910     ok_ole_success(hr, IMoniker_GetDisplayName);
911         ok(!lstrcmpW(display_name, expected_display_name), "display name wasn't what was expected\n");
912
913     CoTaskMemFree(display_name);
914     IBindCtx_Release(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     /* IROTData::GetComparisonData test */
920
921     hr = IMoniker_QueryInterface(moniker, &IID_IROTData, (void **)&rotdata);
922     ok_ole_success(hr, IMoniker_QueryInterface_IID_IROTData);
923
924     hr = IROTData_GetComparisonData(rotdata, buffer, sizeof(buffer), &moniker_size);
925     ok_ole_success(hr, IROTData_GetComparisonData);
926
927     if (hr != S_OK) moniker_size = 0;
928
929     /* first check we have the right amount of data */
930     ok(moniker_size == sizeof_expected_moniker_comparison_data,
931         "%s: Size of comparison data differs (expected %d, actual %d)\n",
932         testname, sizeof_expected_moniker_comparison_data, moniker_size);
933
934     /* then do a byte-by-byte comparison */
935     for (i = 0; i < min(moniker_size, sizeof_expected_moniker_comparison_data); i++)
936     {
937         if (expected_moniker_comparison_data[i] != buffer[i])
938         {
939             same = FALSE;
940             break;
941         }
942     }
943
944     ok(same, "%s: Comparison data differs\n", testname);
945     if (!same)
946     {
947         for (i = 0; i < moniker_size; i++)
948         {
949             if (i % 8 == 0) printf("     ");
950             printf("0x%02x,", buffer[i]);
951             if (i % 8 == 7) printf("\n");
952         }
953         printf("\n");
954     }
955
956     IROTData_Release(rotdata);
957   
958     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
959   
960     /* Saving */
961
962     hr = IMoniker_Save(moniker, stream, TRUE);
963     ok_ole_success(hr, IMoniker_Save);
964
965     hr = GetHGlobalFromStream(stream, &hglobal);
966     ok_ole_success(hr, GetHGlobalFromStream);
967
968     moniker_size = GlobalSize(hglobal);
969
970     moniker_data = GlobalLock(hglobal);
971
972     /* first check we have the right amount of data */
973     ok(moniker_size == sizeof_expected_moniker_saved_data,
974         "%s: Size of saved data differs (expected %d, actual %d)\n",
975         testname, sizeof_expected_moniker_saved_data, moniker_size);
976
977     /* then do a byte-by-byte comparison */
978     for (i = 0; i < min(moniker_size, sizeof_expected_moniker_saved_data); i++)
979     {
980         if (expected_moniker_saved_data[i] != moniker_data[i])
981         {
982             same = FALSE;
983             break;
984         }
985     }
986
987     ok(same, "%s: Saved data differs\n", testname);
988     if (!same)
989     {
990         for (i = 0; i < moniker_size; i++)
991         {
992             if (i % 8 == 0) printf("     ");
993             printf("0x%02x,", moniker_data[i]);
994             if (i % 8 == 7) printf("\n");
995         }
996         printf("\n");
997     }
998
999     GlobalUnlock(hglobal);
1000
1001     IStream_Release(stream);
1002
1003     /* Marshaling tests */
1004
1005     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1006     ok_ole_success(hr, CreateStreamOnHGlobal);
1007
1008     hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1009     ok_ole_success(hr, CoMarshalInterface);
1010
1011     hr = GetHGlobalFromStream(stream, &hglobal);
1012     ok_ole_success(hr, GetHGlobalFromStream);
1013
1014     moniker_size = GlobalSize(hglobal);
1015
1016     moniker_data = GlobalLock(hglobal);
1017
1018     /* first check we have the right amount of data */
1019     ok(moniker_size == sizeof_expected_moniker_marshal_data,
1020         "%s: Size of marshaled data differs (expected %d, actual %d)\n",
1021         testname, sizeof_expected_moniker_marshal_data, moniker_size);
1022
1023     /* then do a byte-by-byte comparison */
1024     if (expected_moniker_marshal_data)
1025     {
1026         for (i = 0; i < min(moniker_size, sizeof_expected_moniker_marshal_data); i++)
1027         {
1028             if (expected_moniker_marshal_data[i] != moniker_data[i])
1029             {
1030                 same = FALSE;
1031                 break;
1032             }
1033         }
1034     }
1035
1036     ok(same, "%s: Marshaled data differs\n", testname);
1037     if (!same)
1038     {
1039         for (i = 0; i < moniker_size; i++)
1040         {
1041             if (i % 8 == 0) printf("     ");
1042             printf("0x%02x,", moniker_data[i]);
1043             if (i % 8 == 7) printf("\n");
1044         }
1045         printf("\n");
1046     }
1047
1048     GlobalUnlock(hglobal);
1049
1050     IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1051     hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void **)&moniker_proxy);
1052     ok_ole_success(hr, CoUnmarshalInterface);
1053
1054     IStream_Release(stream);
1055     IMoniker_Release(moniker_proxy);
1056 }
1057
1058 static void test_class_moniker(void)
1059 {
1060     HRESULT hr;
1061     IMoniker *moniker;
1062     DWORD moniker_type;
1063     DWORD hash;
1064     IBindCtx *bindctx;
1065     IMoniker *inverse;
1066     IUnknown *unknown;
1067     FILETIME filetime;
1068
1069     hr = CreateClassMoniker(&CLSID_StdComponentCategoriesMgr, &moniker);
1070     ok_ole_success(hr, CreateClassMoniker);
1071     if (!moniker) return;
1072
1073     test_moniker("class moniker", moniker, 
1074         expected_class_moniker_marshal_data, sizeof(expected_class_moniker_marshal_data),
1075         expected_class_moniker_saved_data, sizeof(expected_class_moniker_saved_data),
1076         expected_class_moniker_comparison_data, sizeof(expected_class_moniker_comparison_data),
1077         expected_class_moniker_display_name);
1078
1079     /* Hashing */
1080
1081     hr = IMoniker_Hash(moniker, &hash);
1082     ok_ole_success(hr, IMoniker_Hash);
1083
1084     ok(hash == CLSID_StdComponentCategoriesMgr.Data1,
1085         "Hash value != Data1 field of clsid, instead was 0x%08x\n",
1086         hash);
1087
1088     /* IsSystemMoniker test */
1089
1090     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1091     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1092
1093     ok(moniker_type == MKSYS_CLASSMONIKER,
1094         "dwMkSys != MKSYS_CLASSMONIKER, instead was 0x%08x\n",
1095         moniker_type);
1096
1097     hr = CreateBindCtx(0, &bindctx);
1098     ok_ole_success(hr, CreateBindCtx);
1099
1100     /* IsRunning test */
1101     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1102     ok(hr == E_NOTIMPL, "IMoniker_IsRunning should return E_NOTIMPL, not 0x%08x\n", hr);
1103
1104     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1105     ok(hr == MK_E_UNAVAILABLE, "IMoniker_GetTimeOfLastChange should return MK_E_UNAVAILABLE, not 0x%08x\n", hr);
1106
1107     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1108     ok_ole_success(hr, IMoniker_BindToStorage);
1109     IUnknown_Release(unknown);
1110
1111     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1112     ok_ole_success(hr, IMoniker_BindToStorage);
1113     IUnknown_Release(unknown);
1114
1115     IBindCtx_Release(bindctx);
1116
1117     hr = IMoniker_Inverse(moniker, &inverse);
1118     ok_ole_success(hr, IMoniker_Inverse);
1119     IMoniker_Release(inverse);
1120
1121     IMoniker_Release(moniker);
1122 }
1123
1124 static void test_file_moniker(WCHAR* path)
1125 {
1126     IStream *stream;
1127     IMoniker *moniker1 = NULL, *moniker2 = NULL;
1128     HRESULT hr;
1129
1130     hr = CreateFileMoniker(path, &moniker1);
1131     ok_ole_success(hr, CreateFileMoniker); 
1132
1133     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1134
1135     /* Marshal */
1136     hr = CoMarshalInterface(stream, &IID_IMoniker, (IUnknown *)moniker1, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1137     ok_ole_success(hr, CoMarshalInterface);
1138     
1139     /* Rewind */
1140     hr = IStream_Seek(stream, llZero, STREAM_SEEK_SET, NULL);
1141     ok_ole_success(hr, IStream_Seek);
1142
1143     /* Unmarshal */
1144     hr = CoUnmarshalInterface(stream, &IID_IMoniker, (void**)&moniker2);
1145     ok_ole_success(hr, CoUnmarshalInterface);
1146
1147     hr = IMoniker_IsEqual(moniker1, moniker2);
1148     ok_ole_success(hr, IsEqual);
1149
1150     IStream_Release(stream);
1151     if (moniker1) 
1152         IMoniker_Release(moniker1);
1153     if (moniker2) 
1154         IMoniker_Release(moniker2);
1155 }
1156
1157 static void test_file_monikers(void)
1158 {
1159     static WCHAR wszFile[][30] = {
1160         {'\\', 'w','i','n','d','o','w','s','\\','s','y','s','t','e','m','\\','t','e','s','t','1','.','d','o','c',0},
1161         {'\\', '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},
1162         /* These map to themselves in Windows-1252 & 932 (Shift-JIS) */
1163         {0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0},
1164         /* U+2020 = DAGGER     = 0x86 (1252) = 0x813f (932)
1165          * U+20AC = EURO SIGN  = 0x80 (1252) =  undef (932)
1166          * U+0100 .. = Latin extended-A
1167          */ 
1168         {0x20ac, 0x2020, 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108, 0x109, 0x10a, 0x10b, 0x10c,  0},
1169         };
1170
1171     int i; 
1172
1173     trace("ACP is %u\n", GetACP());
1174
1175     for (i = 0; i < COUNTOF(wszFile); ++i)
1176     {
1177         int j ;
1178         for (j = lstrlenW(wszFile[i]); j > 0; --j)
1179         {
1180             wszFile[i][j] = 0;
1181             test_file_moniker(wszFile[i]);
1182         }
1183     }
1184 }
1185
1186 static void test_item_moniker(void)
1187 {
1188     HRESULT hr;
1189     IMoniker *moniker;
1190     DWORD moniker_type;
1191     DWORD hash;
1192     IBindCtx *bindctx;
1193     IMoniker *inverse;
1194     IUnknown *unknown;
1195     static const WCHAR wszDelimeter[] = {'!',0};
1196     static const WCHAR wszObjectName[] = {'T','e','s','t',0};
1197     static const WCHAR expected_display_name[] = { '!','T','e','s','t',0 };
1198
1199     hr = CreateItemMoniker(wszDelimeter, wszObjectName, &moniker);
1200     ok_ole_success(hr, CreateItemMoniker);
1201
1202     test_moniker("item moniker", moniker, 
1203         expected_item_moniker_marshal_data, sizeof(expected_item_moniker_marshal_data),
1204         expected_item_moniker_saved_data, sizeof(expected_item_moniker_saved_data),
1205         expected_item_moniker_comparison_data, sizeof(expected_item_moniker_comparison_data),
1206         expected_display_name);
1207
1208     /* Hashing */
1209
1210     hr = IMoniker_Hash(moniker, &hash);
1211     ok_ole_success(hr, IMoniker_Hash);
1212
1213     ok(hash == 0x73c,
1214         "Hash value != 0x73c, instead was 0x%08x\n",
1215         hash);
1216
1217     /* IsSystemMoniker test */
1218
1219     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1220     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1221
1222     ok(moniker_type == MKSYS_ITEMMONIKER,
1223         "dwMkSys != MKSYS_ITEMMONIKER, instead was 0x%08x\n",
1224         moniker_type);
1225
1226     hr = CreateBindCtx(0, &bindctx);
1227     ok_ole_success(hr, CreateBindCtx);
1228
1229     /* IsRunning test */
1230     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1231     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1232
1233     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1234     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1235
1236     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1237     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1238
1239     IBindCtx_Release(bindctx);
1240
1241     hr = IMoniker_Inverse(moniker, &inverse);
1242     ok_ole_success(hr, IMoniker_Inverse);
1243     IMoniker_Release(inverse);
1244
1245     IMoniker_Release(moniker);
1246 }
1247
1248 static void test_anti_moniker(void)
1249 {
1250     HRESULT hr;
1251     IMoniker *moniker;
1252     DWORD moniker_type;
1253     DWORD hash;
1254     IBindCtx *bindctx;
1255     FILETIME filetime;
1256     IMoniker *inverse;
1257     IUnknown *unknown;
1258     static const WCHAR expected_display_name[] = { '\\','.','.',0 };
1259
1260     hr = CreateAntiMoniker(&moniker);
1261     ok_ole_success(hr, CreateAntiMoniker);
1262     if (!moniker) return;
1263
1264     test_moniker("anti moniker", moniker, 
1265         expected_anti_moniker_marshal_data, sizeof(expected_anti_moniker_marshal_data),
1266         expected_anti_moniker_saved_data, sizeof(expected_anti_moniker_saved_data),
1267         expected_anti_moniker_comparison_data, sizeof(expected_anti_moniker_comparison_data),
1268         expected_display_name);
1269
1270     /* Hashing */
1271     hr = IMoniker_Hash(moniker, &hash);
1272     ok_ole_success(hr, IMoniker_Hash);
1273     ok(hash == 0x80000001,
1274         "Hash value != 0x80000001, instead was 0x%08x\n",
1275         hash);
1276
1277     /* IsSystemMoniker test */
1278     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1279     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1280     ok(moniker_type == MKSYS_ANTIMONIKER,
1281         "dwMkSys != MKSYS_ANTIMONIKER, instead was 0x%08x\n",
1282         moniker_type);
1283
1284     hr = IMoniker_Inverse(moniker, &inverse);
1285     ok(hr == MK_E_NOINVERSE, "IMoniker_Inverse should have returned MK_E_NOINVERSE instead of 0x%08x\n", hr);
1286     ok(inverse == NULL, "inverse should have been set to NULL instead of %p\n", inverse);
1287
1288     hr = CreateBindCtx(0, &bindctx);
1289     ok_ole_success(hr, CreateBindCtx);
1290
1291     /* IsRunning test */
1292     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1293     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1294
1295     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1296     ok(hr == E_NOTIMPL, "IMoniker_GetTimeOfLastChange should return E_NOTIMPL, not 0x%08x\n", hr);
1297
1298     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1299     ok(hr == E_NOTIMPL, "IMoniker_BindToObject should return E_NOTIMPL, not 0x%08x\n", hr);
1300
1301     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1302     ok(hr == E_NOTIMPL, "IMoniker_BindToStorage should return E_NOTIMPL, not 0x%08x\n", hr);
1303
1304     IBindCtx_Release(bindctx);
1305
1306     IMoniker_Release(moniker);
1307 }
1308
1309 static void test_generic_composite_moniker(void)
1310 {
1311     HRESULT hr;
1312     IMoniker *moniker;
1313     IMoniker *moniker1;
1314     IMoniker *moniker2;
1315     DWORD moniker_type;
1316     DWORD hash;
1317     IBindCtx *bindctx;
1318     FILETIME filetime;
1319     IMoniker *inverse;
1320     IUnknown *unknown;
1321     static const WCHAR wszDelimeter1[] = {'!',0};
1322     static const WCHAR wszObjectName1[] = {'T','e','s','t',0};
1323     static const WCHAR wszDelimeter2[] = {'#',0};
1324     static const WCHAR wszObjectName2[] = {'W','i','n','e',0};
1325     static const WCHAR expected_display_name[] = { '!','T','e','s','t','#','W','i','n','e',0 };
1326
1327     hr = CreateItemMoniker(wszDelimeter1, wszObjectName1, &moniker1);
1328     ok_ole_success(hr, CreateItemMoniker);
1329     hr = CreateItemMoniker(wszDelimeter2, wszObjectName2, &moniker2);
1330     ok_ole_success(hr, CreateItemMoniker);
1331     hr = CreateGenericComposite(moniker1, moniker2, &moniker);
1332     ok_ole_success(hr, CreateGenericComposite);
1333
1334     test_moniker("generic composite moniker", moniker, 
1335         expected_gc_moniker_marshal_data, sizeof(expected_gc_moniker_marshal_data),
1336         expected_gc_moniker_saved_data, sizeof(expected_gc_moniker_saved_data),
1337         expected_gc_moniker_comparison_data, sizeof(expected_gc_moniker_comparison_data),
1338         expected_display_name);
1339
1340     /* Hashing */
1341
1342     hr = IMoniker_Hash(moniker, &hash);
1343     ok_ole_success(hr, IMoniker_Hash);
1344
1345     ok(hash == 0xd87,
1346         "Hash value != 0xd87, instead was 0x%08x\n",
1347         hash);
1348
1349     /* IsSystemMoniker test */
1350
1351     hr = IMoniker_IsSystemMoniker(moniker, &moniker_type);
1352     ok_ole_success(hr, IMoniker_IsSystemMoniker);
1353
1354     ok(moniker_type == MKSYS_GENERICCOMPOSITE,
1355         "dwMkSys != MKSYS_GENERICCOMPOSITE, instead was 0x%08x\n",
1356         moniker_type);
1357
1358     hr = CreateBindCtx(0, &bindctx);
1359     ok_ole_success(hr, CreateBindCtx);
1360
1361     /* IsRunning test */
1362     hr = IMoniker_IsRunning(moniker, bindctx, NULL, NULL);
1363     todo_wine
1364     ok(hr == S_FALSE, "IMoniker_IsRunning should return S_FALSE, not 0x%08x\n", hr);
1365
1366     hr = IMoniker_GetTimeOfLastChange(moniker, bindctx, NULL, &filetime);
1367     ok(hr == MK_E_NOTBINDABLE, "IMoniker_GetTimeOfLastChange should return MK_E_NOTBINDABLE, not 0x%08x\n", hr);
1368
1369     hr = IMoniker_BindToObject(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1370     todo_wine
1371     ok(hr == E_INVALIDARG, "IMoniker_BindToObject should return E_INVALIDARG, not 0x%08x\n", hr);
1372
1373     todo_wine
1374     hr = IMoniker_BindToStorage(moniker, bindctx, NULL, &IID_IUnknown, (void **)&unknown);
1375     ok(hr == E_INVALIDARG, "IMoniker_BindToStorage should return E_INVALIDARG, not 0x%08x\n", hr);
1376
1377     IBindCtx_Release(bindctx);
1378
1379     hr = IMoniker_Inverse(moniker, &inverse);
1380     ok_ole_success(hr, IMoniker_Inverse);
1381     IMoniker_Release(inverse);
1382
1383     IMoniker_Release(moniker);
1384 }
1385
1386 START_TEST(moniker)
1387 {
1388     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1389
1390     test_ROT();
1391     test_MkParseDisplayName();
1392     test_class_moniker();
1393     test_file_monikers();
1394     test_item_moniker();
1395     test_anti_moniker();
1396     test_generic_composite_moniker();
1397
1398     /* FIXME: test moniker creation funcs and parsing other moniker formats */
1399
1400     CoUninitialize();
1401 }