1 /*
2  * Copyright 2010 Piotr Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "precomp.h"
20 
21 #include <initguid.h>
22 
23 DEFINE_GUID(FMTID_Test,0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12);
24 DEFINE_GUID(FMTID_NotExisting, 0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x13);
25 DEFINE_GUID(CLSID_ClassMoniker, 0x0000031a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
26 
27 #define DEFINE_EXPECT(func) \
28     static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
29 
30 #define SET_EXPECT(func) \
31     expect_ ## func = TRUE
32 
33 #define CHECK_EXPECT2(func) \
34     do { \
35         ok(expect_ ##func, "unexpected call " #func "\n"); \
36         called_ ## func = TRUE; \
37     }while(0)
38 
39 #define CHECK_EXPECT(func) \
40     do { \
41         CHECK_EXPECT2(func); \
42         expect_ ## func = FALSE; \
43     }while(0)
44 
45 #define CHECK_CALLED(func) \
46     do { \
47         ok(called_ ## func, "expected " #func "\n"); \
48         expect_ ## func = called_ ## func = FALSE; \
49     }while(0)
50 
51 DEFINE_EXPECT(Create);
52 DEFINE_EXPECT(Delete);
53 DEFINE_EXPECT(Open);
54 DEFINE_EXPECT(ReadMultiple);
55 DEFINE_EXPECT(ReadMultipleCodePage);
56 DEFINE_EXPECT(Release);
57 DEFINE_EXPECT(Stat);
58 DEFINE_EXPECT(WriteMultiple);
59 
60 DEFINE_EXPECT(autoplay_BindToObject);
61 DEFINE_EXPECT(autoplay_GetClassObject);
62 
63 static HRESULT (WINAPI *pSHPropStgCreate)(IPropertySetStorage*, REFFMTID, const CLSID*,
64         DWORD, DWORD, DWORD, IPropertyStorage**, UINT*);
65 static HRESULT (WINAPI *pSHPropStgReadMultiple)(IPropertyStorage*, UINT,
66         ULONG, const PROPSPEC*, PROPVARIANT*);
67 static HRESULT (WINAPI *pSHPropStgWriteMultiple)(IPropertyStorage*, UINT*,
68         ULONG, const PROPSPEC*, PROPVARIANT*, PROPID);
69 static HRESULT (WINAPI *pSHCreateQueryCancelAutoPlayMoniker)(IMoniker**);
70 static HRESULT (WINAPI *pSHCreateSessionKey)(REGSAM, HKEY*);
71 
72 static void init(void)
73 {
74     HMODULE hmod = GetModuleHandleA("shell32.dll");
75 
76     pSHPropStgCreate = (void*)GetProcAddress(hmod, "SHPropStgCreate");
77     pSHPropStgReadMultiple = (void*)GetProcAddress(hmod, "SHPropStgReadMultiple");
78     pSHPropStgWriteMultiple = (void*)GetProcAddress(hmod, "SHPropStgWriteMultiple");
79     pSHCreateQueryCancelAutoPlayMoniker = (void*)GetProcAddress(hmod, "SHCreateQueryCancelAutoPlayMoniker");
80     pSHCreateSessionKey = (void*)GetProcAddress(hmod, (char*)723);
81 }
82 
83 static HRESULT WINAPI PropertyStorage_QueryInterface(IPropertyStorage *This,
84         REFIID riid, void **ppvObject)
85 {
86     ok(0, "unexpected call\n");
87     return E_NOTIMPL;
88 }
89 
90 static ULONG WINAPI PropertyStorage_AddRef(IPropertyStorage *This)
91 {
92     ok(0, "unexpected call\n");
93     return 2;
94 }
95 
96 static ULONG WINAPI PropertyStorage_Release(IPropertyStorage *This)
97 {
98     CHECK_EXPECT(Release);
99     return 1;
100 }
101 
102 static HRESULT WINAPI PropertyStorage_ReadMultiple(IPropertyStorage *This, ULONG cpspec,
103         const PROPSPEC *rgpspec, PROPVARIANT *rgpropvar)
104 {
105     if(cpspec == 1) {
106         CHECK_EXPECT(ReadMultipleCodePage);
107 
108         ok(rgpspec != NULL, "rgpspec = NULL\n");
109         ok(rgpropvar != NULL, "rgpropvar = NULL\n");
110 
111         ok(rgpspec[0].ulKind == PRSPEC_PROPID, "rgpspec[0].ulKind = %d\n", rgpspec[0].ulKind);
112         ok(rgpspec[0].propid == PID_CODEPAGE, "rgpspec[0].propid = %d\n", rgpspec[0].propid);
113 
114         rgpropvar[0].vt = VT_I2;
115         rgpropvar[0].iVal = 1234;
116     } else {
117         CHECK_EXPECT(ReadMultiple);
118 
119         ok(cpspec == 10, "cpspec = %u\n", cpspec);
120         ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec);
121         ok(rgpropvar != NULL, "rgpropvar = NULL\n");
122 
123         ok(rgpropvar[0].vt==0 || broken(rgpropvar[0].vt==VT_BSTR), "rgpropvar[0].vt = %d\n", rgpropvar[0].vt);
124 
125         rgpropvar[0].vt = VT_BSTR;
126         rgpropvar[0].bstrVal = (void*)0xdeadbeef;
127         rgpropvar[1].vt = VT_LPSTR;
128         rgpropvar[1].pszVal = (void*)0xdeadbeef;
129         rgpropvar[2].vt = VT_BYREF|VT_I1;
130         rgpropvar[2].pcVal = (void*)0xdeadbeef;
131         rgpropvar[3].vt = VT_BYREF|VT_VARIANT;
132         rgpropvar[3].pvarVal = (void*)0xdeadbeef;
133     }
134 
135     return S_OK;
136 }
137 
138 static HRESULT WINAPI PropertyStorage_WriteMultiple(IPropertyStorage *This, ULONG cpspec,
139         const PROPSPEC *rgpspec, const PROPVARIANT *rgpropvar,
140         PROPID propidNameFirst)
141 {
142     CHECK_EXPECT(WriteMultiple);
143 
144     ok(cpspec == 20, "cpspec = %d\n", cpspec);
145     ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec);
146     ok(rgpropvar == (void*)0xdeadbeef, "rgpropvar = %p\n", rgpspec);
147     ok(propidNameFirst == PID_FIRST_USABLE, "propidNameFirst = %d\n", propidNameFirst);
148     return S_OK;
149 }
150 
151 static HRESULT WINAPI PropertyStorage_DeleteMultiple(IPropertyStorage *This, ULONG cpspec,
152         const PROPSPEC *rgpspec)
153 {
154     ok(0, "unexpected call\n");
155     return E_NOTIMPL;
156 }
157 
158 static HRESULT WINAPI PropertyStorage_ReadPropertyNames(IPropertyStorage *This, ULONG cpropid,
159         const PROPID *rgpropid, LPOLESTR *rglpwstrName)
160 {
161     ok(0, "unexpected call\n");
162     return E_NOTIMPL;
163 }
164 
165 static HRESULT WINAPI PropertyStorage_WritePropertyNames(IPropertyStorage *This, ULONG cpropid,
166         const PROPID *rgpropid, const LPOLESTR *rglpwstrName)
167 {
168     ok(0, "unexpected call\n");
169     return E_NOTIMPL;
170 }
171 
172 static HRESULT WINAPI PropertyStorage_DeletePropertyNames(IPropertyStorage *This, ULONG cpropid,
173         const PROPID *rgpropid)
174 {
175     ok(0, "unexpected call\n");
176     return E_NOTIMPL;
177 }
178 
179 static HRESULT WINAPI PropertyStorage_Commit(IPropertyStorage *This, DWORD grfCommitFlags)
180 {
181     ok(0, "unexpected call\n");
182     return E_NOTIMPL;
183 }
184 
185 static HRESULT WINAPI PropertyStorage_Revert(IPropertyStorage *This)
186 {
187     ok(0, "unexpected call\n");
188     return E_NOTIMPL;
189 }
190 
191 static HRESULT WINAPI PropertyStorage_Enum(IPropertyStorage *This, IEnumSTATPROPSTG **ppenum)
192 {
193     ok(0, "unexpected call\n");
194     return E_NOTIMPL;
195 }
196 
197 static HRESULT WINAPI PropertyStorage_SetTimes(IPropertyStorage *This, const FILETIME *pctime,
198         const FILETIME *patime, const FILETIME *pmtime)
199 {
200     ok(0, "unexpected call\n");
201     return E_NOTIMPL;
202 }
203 
204 static HRESULT WINAPI PropertyStorage_SetClass(IPropertyStorage *This, REFCLSID clsid)
205 {
206     ok(0, "unexpected call\n");
207     return E_NOTIMPL;
208 }
209 
210 static HRESULT WINAPI PropertyStorage_Stat(IPropertyStorage *This, STATPROPSETSTG *statpsstg)
211 {
212     CHECK_EXPECT(Stat);
213 
214     memset(statpsstg, 0, sizeof(STATPROPSETSTG));
215     memcpy(&statpsstg->fmtid, &FMTID_Test, sizeof(FMTID));
216     statpsstg->grfFlags = PROPSETFLAG_ANSI;
217     return S_OK;
218 }
219 
220 static IPropertyStorageVtbl PropertyStorageVtbl = {
221     PropertyStorage_QueryInterface,
222     PropertyStorage_AddRef,
223     PropertyStorage_Release,
224     PropertyStorage_ReadMultiple,
225     PropertyStorage_WriteMultiple,
226     PropertyStorage_DeleteMultiple,
227     PropertyStorage_ReadPropertyNames,
228     PropertyStorage_WritePropertyNames,
229     PropertyStorage_DeletePropertyNames,
230     PropertyStorage_Commit,
231     PropertyStorage_Revert,
232     PropertyStorage_Enum,
233     PropertyStorage_SetTimes,
234     PropertyStorage_SetClass,
235     PropertyStorage_Stat
236 };
237 
238 static IPropertyStorage PropertyStorage = { &PropertyStorageVtbl };
239 
240 static HRESULT WINAPI PropertySetStorage_QueryInterface(IPropertySetStorage *This,
241         REFIID riid, void **ppvObject)
242 {
243     ok(0, "unexpected call\n");
244     return E_NOTIMPL;
245 }
246 
247 static ULONG WINAPI PropertySetStorage_AddRef(IPropertySetStorage *This)
248 {
249     ok(0, "unexpected call\n");
250     return 2;
251 }
252 
253 static ULONG WINAPI PropertySetStorage_Release(IPropertySetStorage *This)
254 {
255     ok(0, "unexpected call\n");
256     return 1;
257 }
258 
259 static HRESULT WINAPI PropertySetStorage_Create(IPropertySetStorage *This,
260         REFFMTID rfmtid, const CLSID *pclsid, DWORD grfFlags,
261         DWORD grfMode, IPropertyStorage **ppprstg)
262 {
263     CHECK_EXPECT(Create);
264     ok(IsEqualGUID(rfmtid, &FMTID_Test) || IsEqualGUID(rfmtid, &FMTID_NotExisting),
265             "Incorrect rfmtid value\n");
266     ok(pclsid == NULL, "pclsid != NULL\n");
267     ok(grfFlags == PROPSETFLAG_ANSI, "grfFlags = %x\n", grfFlags);
268     ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode);
269 
270     *ppprstg = &PropertyStorage;
271     return S_OK;
272 }
273 
274 static HRESULT WINAPI PropertySetStorage_Open(IPropertySetStorage *This,
275         REFFMTID rfmtid, DWORD grfMode, IPropertyStorage **ppprstg)
276 {
277     CHECK_EXPECT(Open);
278 
279     if(IsEqualGUID(rfmtid, &FMTID_Test)) {
280         ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode);
281 
282         *ppprstg = &PropertyStorage;
283         return S_OK;
284     }
285 
286     return STG_E_FILENOTFOUND;
287 }
288 
289 static HRESULT WINAPI PropertySetStorage_Delete(IPropertySetStorage *This,
290         REFFMTID rfmtid)
291 {
292     CHECK_EXPECT(Delete);
293     ok(IsEqualGUID(rfmtid, &FMTID_Test), "wrong rfmtid value\n");
294     return S_OK;
295 }
296 
297 static HRESULT WINAPI PropertySetStorage_Enum(IPropertySetStorage *This,
298         IEnumSTATPROPSETSTG **ppenum)
299 {
300     ok(0, "unexpected call\n");
301     return E_NOTIMPL;
302 }
303 
304 static IPropertySetStorageVtbl PropertySetStorageVtbl = {
305     PropertySetStorage_QueryInterface,
306     PropertySetStorage_AddRef,
307     PropertySetStorage_Release,
308     PropertySetStorage_Create,
309     PropertySetStorage_Open,
310     PropertySetStorage_Delete,
311     PropertySetStorage_Enum
312 };
313 
314 static IPropertySetStorage PropertySetStorage = { &PropertySetStorageVtbl };
315 
316 static void test_SHPropStg_functions(void)
317 {
318     IPropertyStorage *property_storage;
319     UINT codepage;
320     PROPVARIANT read[10];
321     HRESULT hres;
322 
323     if(!pSHPropStgCreate || !pSHPropStgReadMultiple || !pSHPropStgWriteMultiple) {
324         win_skip("SHPropStg* functions are missing\n");
325         return;
326     }
327 
328     if(0) {
329         /* Crashes on Windows */
330         pSHPropStgCreate(NULL, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
331                 STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
332         pSHPropStgCreate(&PropertySetStorage, NULL, NULL, PROPSETFLAG_DEFAULT,
333                 STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
334         pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
335                 STGM_READ, OPEN_EXISTING, NULL, &codepage);
336     }
337 
338     SET_EXPECT(Open);
339     SET_EXPECT(ReadMultipleCodePage);
340     hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
341             STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
342     ok(codepage == 1234, "codepage = %d\n", codepage);
343     ok(hres == S_OK, "hres = %x\n", hres);
344     CHECK_CALLED(Open);
345     CHECK_CALLED(ReadMultipleCodePage);
346 
347     SET_EXPECT(Open);
348     hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL,
349             PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
350     ok(hres == STG_E_FILENOTFOUND, "hres = %x\n", hres);
351     CHECK_CALLED(Open);
352 
353     SET_EXPECT(Open);
354     SET_EXPECT(Release);
355     SET_EXPECT(Delete);
356     SET_EXPECT(Create);
357     SET_EXPECT(ReadMultipleCodePage);
358     hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_ANSI,
359             STGM_READ, CREATE_ALWAYS, &property_storage, &codepage);
360     ok(codepage == 1234, "codepage = %d\n", codepage);
361     ok(hres == S_OK, "hres = %x\n", hres);
362     CHECK_CALLED(Open);
363     CHECK_CALLED(Release);
364     CHECK_CALLED(Delete);
365     CHECK_CALLED(Create);
366     CHECK_CALLED(ReadMultipleCodePage);
367 
368     SET_EXPECT(Open);
369     SET_EXPECT(Create);
370     SET_EXPECT(ReadMultipleCodePage);
371     hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL, PROPSETFLAG_ANSI,
372             STGM_READ, CREATE_ALWAYS, &property_storage, &codepage);
373     ok(codepage == 1234, "codepage = %d\n", codepage);
374     ok(hres == S_OK, "hres = %x\n", hres);
375     CHECK_CALLED(Open);
376     CHECK_CALLED(Create);
377     CHECK_CALLED(ReadMultipleCodePage);
378 
379     SET_EXPECT(Open);
380     hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, &FMTID_NotExisting,
381             PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, NULL);
382     ok(hres == S_OK, "hres = %x\n", hres);
383     CHECK_CALLED(Open);
384 
385     SET_EXPECT(Stat);
386     SET_EXPECT(ReadMultipleCodePage);
387     SET_EXPECT(WriteMultiple);
388     codepage = 0;
389     hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
390     ok(hres == S_OK, "hres = %x\n", hres);
391     ok(codepage == 1234, "codepage = %d\n", codepage);
392     CHECK_CALLED(Stat);
393     CHECK_CALLED(ReadMultipleCodePage);
394     CHECK_CALLED(WriteMultiple);
395 
396     SET_EXPECT(Stat);
397     SET_EXPECT(ReadMultipleCodePage);
398     SET_EXPECT(WriteMultiple);
399     hres = pSHPropStgWriteMultiple(property_storage, NULL, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
400     ok(hres == S_OK, "hres = %x\n", hres);
401     CHECK_CALLED(Stat);
402     CHECK_CALLED(ReadMultipleCodePage);
403     CHECK_CALLED(WriteMultiple);
404 
405     SET_EXPECT(Stat);
406     SET_EXPECT(WriteMultiple);
407     codepage = 1000;
408     hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
409     ok(hres == S_OK, "hres = %x\n", hres);
410     ok(codepage == 1000, "codepage = %d\n", codepage);
411     CHECK_CALLED(Stat);
412     CHECK_CALLED(WriteMultiple);
413 
414     read[0].vt = VT_BSTR;
415     read[0].bstrVal = (void*)0xdeadbeef;
416     SET_EXPECT(ReadMultiple);
417     SET_EXPECT(ReadMultipleCodePage);
418     SET_EXPECT(Stat);
419     hres = pSHPropStgReadMultiple(property_storage, 0, 10, (void*)0xdeadbeef, read);
420     ok(hres == S_OK, "hres = %x\n", hres);
421     CHECK_CALLED(ReadMultiple);
422     CHECK_CALLED(ReadMultipleCodePage);
423     CHECK_CALLED(Stat);
424 
425     SET_EXPECT(ReadMultiple);
426     SET_EXPECT(Stat);
427     hres = pSHPropStgReadMultiple(property_storage, 1251, 10, (void*)0xdeadbeef, read);
428     ok(hres == S_OK, "hres = %x\n", hres);
429     CHECK_CALLED(ReadMultiple);
430     CHECK_CALLED(Stat);
431 }
432 
433 static HRESULT WINAPI test_activator_QI(IClassActivator *iface, REFIID riid, void **ppv)
434 {
435     *ppv = NULL;
436 
437     if (IsEqualIID(riid, &IID_IUnknown) ||
438         IsEqualIID(riid, &IID_IClassActivator))
439     {
440         *ppv = iface;
441     }
442 
443     if (!*ppv) return E_NOINTERFACE;
444 
445     IClassActivator_AddRef(iface);
446 
447     return S_OK;
448 }
449 
450 static ULONG WINAPI test_activator_AddRef(IClassActivator *iface)
451 {
452     return 2;
453 }
454 
455 static ULONG WINAPI test_activator_Release(IClassActivator *iface)
456 {
457     return 1;
458 }
459 
460 static HRESULT WINAPI test_activator_GetClassObject(IClassActivator *iface, REFCLSID clsid,
461     DWORD context, LCID locale, REFIID riid, void **ppv)
462 {
463     CHECK_EXPECT(autoplay_GetClassObject);
464     ok(IsEqualGUID(clsid, &CLSID_QueryCancelAutoPlay), "clsid %s\n", wine_dbgstr_guid(clsid));
465     ok(IsEqualIID(riid, &IID_IQueryCancelAutoPlay), "riid %s\n", wine_dbgstr_guid(riid));
466     return E_NOTIMPL;
467 }
468 
469 static const IClassActivatorVtbl test_activator_vtbl = {
470     test_activator_QI,
471     test_activator_AddRef,
472     test_activator_Release,
473     test_activator_GetClassObject
474 };
475 
476 static IClassActivator test_activator = { &test_activator_vtbl };
477 
478 static HRESULT WINAPI test_moniker_QueryInterface(IMoniker* iface, REFIID riid, void **ppvObject)
479 {
480     *ppvObject = 0;
481 
482     if (IsEqualIID(&IID_IUnknown, riid) ||
483         IsEqualIID(&IID_IPersist, riid) ||
484         IsEqualIID(&IID_IPersistStream, riid) ||
485         IsEqualIID(&IID_IMoniker, riid))
486     {
487         *ppvObject = iface;
488     }
489 
490     if (!*ppvObject)
491         return E_NOINTERFACE;
492 
493     return S_OK;
494 }
495 
496 static ULONG WINAPI test_moniker_AddRef(IMoniker* iface)
497 {
498     return 2;
499 }
500 
501 static ULONG WINAPI test_moniker_Release(IMoniker* iface)
502 {
503     return 1;
504 }
505 
506 static HRESULT WINAPI test_moniker_GetClassID(IMoniker* iface, CLSID *pClassID)
507 {
508     ok(0, "unexpected call\n");
509     return E_NOTIMPL;
510 }
511 
512 static HRESULT WINAPI test_moniker_IsDirty(IMoniker* iface)
513 {
514     ok(0, "unexpected call\n");
515     return E_NOTIMPL;
516 }
517 
518 static HRESULT WINAPI test_moniker_Load(IMoniker* iface, IStream* pStm)
519 {
520     ok(0, "unexpected call\n");
521     return E_NOTIMPL;
522 }
523 
524 static HRESULT WINAPI test_moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty)
525 {
526     ok(0, "unexpected call\n");
527     return E_NOTIMPL;
528 }
529 
530 static HRESULT WINAPI test_moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize)
531 {
532     ok(0, "unexpected call\n");
533     return E_NOTIMPL;
534 }
535 
536 static HRESULT WINAPI test_moniker_BindToObject(IMoniker* iface,
537                                                 IBindCtx* pbc,
538                                                 IMoniker* moniker_to_left,
539                                                 REFIID riid,
540                                                 void** ppv)
541 {
542     CHECK_EXPECT(autoplay_BindToObject);
543     ok(pbc != NULL, "got %p\n", pbc);
544     ok(moniker_to_left == NULL, "got %p\n", moniker_to_left);
545     ok(IsEqualIID(riid, &IID_IClassActivator), "got riid %s\n", wine_dbgstr_guid(riid));
546 
547     if (IsEqualIID(riid, &IID_IClassActivator))
548     {
549         *ppv = &test_activator;
550         return S_OK;
551     }
552 
553     return E_NOTIMPL;
554 }
555 
556 static HRESULT WINAPI test_moniker_BindToStorage(IMoniker* iface,
557                                              IBindCtx* pbc,
558                                              IMoniker* pmkToLeft,
559                                              REFIID riid,
560                                              VOID** ppvResult)
561 {
562     ok(0, "unexpected call\n");
563     return E_NOTIMPL;
564 }
565 
566 static HRESULT WINAPI test_moniker_Reduce(IMoniker* iface,
567                                       IBindCtx* pbc,
568                                       DWORD dwReduceHowFar,
569                                       IMoniker** ppmkToLeft,
570                                       IMoniker** ppmkReduced)
571 {
572     ok(0, "unexpected call\n");
573     return E_NOTIMPL;
574 }
575 
576 static HRESULT WINAPI test_moniker_ComposeWith(IMoniker* iface,
577                                            IMoniker* pmkRight,
578                                            BOOL fOnlyIfNotGeneric,
579                                            IMoniker** ppmkComposite)
580 {
581     ok(0, "unexpected call\n");
582     return E_NOTIMPL;
583 }
584 
585 static HRESULT WINAPI test_moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker)
586 {
587     ok(0, "unexpected call\n");
588     return E_NOTIMPL;
589 }
590 
591 static HRESULT WINAPI test_moniker_IsEqual(IMoniker* iface, IMoniker* pmkOtherMoniker)
592 {
593     ok(0, "unexpected call\n");
594     return E_NOTIMPL;
595 }
596 
597 static HRESULT WINAPI test_moniker_Hash(IMoniker* iface, DWORD* pdwHash)
598 {
599     ok(0, "unexpected call\n");
600     return E_NOTIMPL;
601 }
602 
603 static HRESULT WINAPI test_moniker_IsRunning(IMoniker* iface,
604                                          IBindCtx* pbc,
605                                          IMoniker* pmkToLeft,
606                                          IMoniker* pmkNewlyRunning)
607 {
608     ok(0, "unexpected call\n");
609     return E_NOTIMPL;
610 }
611 
612 static HRESULT WINAPI test_moniker_GetTimeOfLastChange(IMoniker* iface,
613                                                    IBindCtx* pbc,
614                                                    IMoniker* pmkToLeft,
615                                                    FILETIME* pItemTime)
616 {
617     ok(0, "unexpected call\n");
618     return E_NOTIMPL;
619 }
620 
621 static HRESULT WINAPI test_moniker_Inverse(IMoniker* iface, IMoniker** ppmk)
622 {
623     ok(0, "unexpected call\n");
624     return E_NOTIMPL;
625 }
626 
627 static HRESULT WINAPI test_moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix)
628 {
629     ok(0, "unexpected call\n");
630     return E_NOTIMPL;
631 }
632 
633 static HRESULT WINAPI test_moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath)
634 {
635     ok(0, "unexpected call\n");
636     return E_NOTIMPL;
637 }
638 
639 static HRESULT WINAPI test_moniker_GetDisplayName(IMoniker* iface,
640                                               IBindCtx* pbc,
641                                               IMoniker* pmkToLeft,
642                                               LPOLESTR *ppszDisplayName)
643 {
644     ok(0, "unexpected call\n");
645     return E_NOTIMPL;
646 }
647 
648 static HRESULT WINAPI test_moniker_ParseDisplayName(IMoniker* iface,
649                                                 IBindCtx* pbc,
650                                                 IMoniker* pmkToLeft,
651                                                 LPOLESTR pszDisplayName,
652                                                 ULONG* pchEaten,
653                                                 IMoniker** ppmkOut)
654 {
655     ok(0, "unexpected call\n");
656     return E_NOTIMPL;
657 }
658 
659 static HRESULT WINAPI test_moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
660 {
661     ok(0, "unexpected call\n");
662     return E_NOTIMPL;
663 }
664 
665 static const IMonikerVtbl test_moniker_vtbl =
666 {
667     test_moniker_QueryInterface,
668     test_moniker_AddRef,
669     test_moniker_Release,
670     test_moniker_GetClassID,
671     test_moniker_IsDirty,
672     test_moniker_Load,
673     test_moniker_Save,
674     test_moniker_GetSizeMax,
675     test_moniker_BindToObject,
676     test_moniker_BindToStorage,
677     test_moniker_Reduce,
678     test_moniker_ComposeWith,
679     test_moniker_Enum,
680     test_moniker_IsEqual,
681     test_moniker_Hash,
682     test_moniker_IsRunning,
683     test_moniker_GetTimeOfLastChange,
684     test_moniker_Inverse,
685     test_moniker_CommonPrefixWith,
686     test_moniker_RelativePathTo,
687     test_moniker_GetDisplayName,
688     test_moniker_ParseDisplayName,
689     test_moniker_IsSystemMoniker
690 };
691 
692 static IMoniker test_moniker = { &test_moniker_vtbl };
693 
694 static void test_SHCreateQueryCancelAutoPlayMoniker(void)
695 {
696     IBindCtx *ctxt;
697     IMoniker *mon;
698     IUnknown *unk;
699     CLSID clsid;
700     HRESULT hr;
701     DWORD sys;
702 
703     if (!pSHCreateQueryCancelAutoPlayMoniker)
704     {
705         win_skip("SHCreateQueryCancelAutoPlayMoniker is not available, skipping tests.\n");
706         return;
707     }
708 
709     hr = pSHCreateQueryCancelAutoPlayMoniker(NULL);
710     ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
711 
712     hr = pSHCreateQueryCancelAutoPlayMoniker(&mon);
713     ok(hr == S_OK, "got 0x%08x\n", hr);
714 
715     sys = -1;
716     hr = IMoniker_IsSystemMoniker(mon, &sys);
717     ok(hr == S_OK, "got 0x%08x\n", hr);
718     ok(sys == MKSYS_CLASSMONIKER, "got %d\n", sys);
719 
720     memset(&clsid, 0, sizeof(clsid));
721     hr = IMoniker_GetClassID(mon, &clsid);
722     ok(hr == S_OK, "got 0x%08x\n", hr);
723     ok(IsEqualGUID(&clsid, &CLSID_ClassMoniker), "got %s\n", wine_dbgstr_guid(&clsid));
724 
725     /* extract used CLSID that implements this hook */
726     SET_EXPECT(autoplay_BindToObject);
727     SET_EXPECT(autoplay_GetClassObject);
728 
729     CreateBindCtx(0, &ctxt);
730     hr = IMoniker_BindToObject(mon, ctxt, &test_moniker, &IID_IQueryCancelAutoPlay, (void**)&unk);
731     ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
732     IBindCtx_Release(ctxt);
733 
734     CHECK_CALLED(autoplay_BindToObject);
735     CHECK_CALLED(autoplay_GetClassObject);
736 
737     IMoniker_Release(mon);
738 }
739 
740 #define DROPTEST_FILENAME "c:\\wintest.bin"
741 struct DragParam {
742     HWND hwnd;
743     HANDLE ready;
744 };
745 
746 static LRESULT WINAPI drop_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
747 {
748     switch (msg) {
749     case WM_DROPFILES:
750     {
751         HDROP hDrop = (HDROP)wparam;
752         char filename[MAX_PATH] = "dummy";
753         UINT num;
754         num = DragQueryFileA(hDrop, 0xffffffff, NULL, 0);
755         ok(num == 1, "expected 1, got %u\n", num);
756         num = DragQueryFileA(hDrop, 0xffffffff, (char*)0xdeadbeef, 0xffffffff);
757         ok(num == 1, "expected 1, got %u\n", num);
758         num = DragQueryFileA(hDrop, 0, filename, sizeof(filename));
759         ok(num == strlen(DROPTEST_FILENAME), "got %u\n", num);
760         ok(!strcmp(filename, DROPTEST_FILENAME), "got %s\n", filename);
761         DragFinish(hDrop);
762         return 0;
763     }
764     }
765     return DefWindowProcA(hwnd, msg, wparam, lparam);
766 }
767 
768 static DWORD WINAPI drop_window_therad(void *arg)
769 {
770     struct DragParam *param = arg;
771     WNDCLASSA cls;
772     WINDOWINFO info;
773     BOOL r;
774     MSG msg;
775 
776     memset(&cls, 0, sizeof(cls));
777     cls.lpfnWndProc = drop_window_proc;
778     cls.hInstance = GetModuleHandleA(NULL);
779     cls.lpszClassName = "drop test";
780     RegisterClassA(&cls);
781 
782     param->hwnd = CreateWindowA("drop test", NULL, 0, 0, 0, 0, 0,
783                                 NULL, 0, NULL, 0);
784     ok(param->hwnd != NULL, "CreateWindow failed: %d\n", GetLastError());
785 
786     memset(&info, 0, sizeof(info));
787     info.cbSize = sizeof(info);
788     r = GetWindowInfo(param->hwnd, &info);
789     ok(r, "got %d\n", r);
790     ok(!(info.dwExStyle & WS_EX_ACCEPTFILES), "got %08x\n", info.dwExStyle);
791 
792     DragAcceptFiles(param->hwnd, TRUE);
793 
794     memset(&info, 0, sizeof(info));
795     info.cbSize = sizeof(info);
796     r = GetWindowInfo(param->hwnd, &info);
797     ok(r, "got %d\n", r);
798     ok((info.dwExStyle & WS_EX_ACCEPTFILES), "got %08x\n", info.dwExStyle);
799 
800     SetEvent(param->ready);
801 
802     while ((r = GetMessageA(&msg, NULL, 0, 0)) != 0) {
803         if (r == (BOOL)-1) {
804             ok(0, "unexpected return value, got %d\n", r);
805             break;
806         }
807         DispatchMessageA(&msg);
808     }
809 
810     DestroyWindow(param->hwnd);
811     UnregisterClassA("drop test", GetModuleHandleA(NULL));
812     return 0;
813 }
814 
815 static void test_DragQueryFile(void)
816 {
817     struct DragParam param;
818     HANDLE hThread;
819     DWORD rc;
820     HGLOBAL hDrop;
821     DROPFILES *pDrop;
822     int ret;
823     BOOL r;
824 
825     param.ready = CreateEventA(NULL, FALSE, FALSE, NULL);
826     ok(param.ready != NULL, "can't create event\n");
827     hThread = CreateThread(NULL, 0, drop_window_therad, &param, 0, NULL);
828 
829     rc = WaitForSingleObject(param.ready, 5000);
830     ok(rc == WAIT_OBJECT_0, "got %u\n", rc);
831 
832     hDrop = GlobalAlloc(GHND, sizeof(DROPFILES) + (strlen(DROPTEST_FILENAME) + 2) * sizeof(WCHAR));
833     pDrop = GlobalLock(hDrop);
834     pDrop->pFiles = sizeof(DROPFILES);
835     ret = MultiByteToWideChar(CP_ACP, 0, DROPTEST_FILENAME, -1,
836                               (LPWSTR)(pDrop + 1), strlen(DROPTEST_FILENAME) + 1);
837     ok(ret > 0, "got %d\n", ret);
838     pDrop->fWide = TRUE;
839     GlobalUnlock(hDrop);
840 
841     r = PostMessageA(param.hwnd, WM_DROPFILES, (WPARAM)hDrop, 0);
842     ok(r, "got %d\n", r);
843 
844     r = PostMessageA(param.hwnd, WM_QUIT, 0, 0);
845     ok(r, "got %d\n", r);
846 
847     rc = WaitForSingleObject(hThread, 5000);
848     ok(rc == WAIT_OBJECT_0, "got %d\n", rc);
849 
850     CloseHandle(param.ready);
851     CloseHandle(hThread);
852 }
853 #undef DROPTEST_FILENAME
854 
855 static void test_SHCreateSessionKey(void)
856 {
857     HKEY hkey, hkey2;
858     HRESULT hr;
859 
860     if (!pSHCreateSessionKey)
861     {
862         win_skip("SHCreateSessionKey is not implemented\n");
863         return;
864     }
865 
866     if (0) /* crashes on native */
867         hr = pSHCreateSessionKey(KEY_READ, NULL);
868 
869     hkey = (HKEY)0xdeadbeef;
870     hr = pSHCreateSessionKey(0, &hkey);
871     todo_wine ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr);
872     todo_wine ok(hkey == NULL, "got %p\n", hkey);
873 
874     hr = pSHCreateSessionKey(KEY_READ, &hkey);
875     ok(hr == S_OK, "got 0x%08x\n", hr);
876 
877     hr = pSHCreateSessionKey(KEY_READ, &hkey2);
878     ok(hr == S_OK, "got 0x%08x\n", hr);
879     ok(hkey != hkey2, "got %p, %p\n", hkey, hkey2);
880 
881     RegCloseKey(hkey);
882     RegCloseKey(hkey2);
883 }
884 
885 static void test_dragdrophelper(void)
886 {
887     IDragSourceHelper *dragsource;
888     IDropTargetHelper *target;
889     HRESULT hr;
890 
891     hr = CoCreateInstance(&CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER, &IID_IDropTargetHelper, (void **)&target);
892     ok(hr == S_OK, "Failed to create IDropTargetHelper, %#x\n", hr);
893 
894     hr = IDropTargetHelper_QueryInterface(target, &IID_IDragSourceHelper, (void **)&dragsource);
895     ok(hr == S_OK, "QI failed, %#x\n", hr);
896     IDragSourceHelper_Release(dragsource);
897 
898     IDropTargetHelper_Release(target);
899 }
900 
901 START_TEST(shellole)
902 {
903     HRESULT hr;
904 
905     init();
906 
907     hr = CoInitialize(NULL);
908     ok(hr == S_OK, "CoInitialize failed (0x%08x)\n", hr);
909     if (hr != S_OK)
910         return;
911 
912     test_SHPropStg_functions();
913     test_SHCreateQueryCancelAutoPlayMoniker();
914     test_DragQueryFile();
915     test_SHCreateSessionKey();
916     test_dragdrophelper();
917 
918     CoUninitialize();
919 }
920