2 * Copyright 2010 Piotr Caban for CodeWeavers
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.
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.
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
21 #define NONAMELESSUNION
24 #include <wine/test.h>
30 DEFINE_GUID(FMTID_Test,0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12);
31 DEFINE_GUID(FMTID_NotExisting, 0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x13);
33 #define DEFINE_EXPECT(func) \
34 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
36 #define SET_EXPECT(func) \
37 expect_ ## func = TRUE
39 #define CHECK_EXPECT2(func) \
41 ok(expect_ ##func, "unexpected call " #func "\n"); \
42 called_ ## func = TRUE; \
45 #define CHECK_EXPECT(func) \
47 CHECK_EXPECT2(func); \
48 expect_ ## func = FALSE; \
51 #define CHECK_CALLED(func) \
53 ok(called_ ## func, "expected " #func "\n"); \
54 expect_ ## func = called_ ## func = FALSE; \
57 DEFINE_EXPECT(Create);
58 DEFINE_EXPECT(Delete);
60 DEFINE_EXPECT(ReadMultiple);
61 DEFINE_EXPECT(ReadMultipleCodePage);
62 DEFINE_EXPECT(Release);
64 DEFINE_EXPECT(WriteMultiple);
66 static HRESULT (WINAPI *pSHPropStgCreate)(IPropertySetStorage*, REFFMTID, const CLSID*,
67 DWORD, DWORD, DWORD, IPropertyStorage**, UINT*);
68 static HRESULT (WINAPI *pSHPropStgReadMultiple)(IPropertyStorage*, UINT,
69 ULONG, const PROPSPEC*, PROPVARIANT*);
70 static HRESULT (WINAPI *pSHPropStgWriteMultiple)(IPropertyStorage*, UINT*,
71 ULONG, const PROPSPEC*, PROPVARIANT*, PROPID);
73 static void init(void)
75 HMODULE hmod = GetModuleHandleA("shell32.dll");
77 pSHPropStgCreate = (void*)GetProcAddress(hmod, "SHPropStgCreate");
78 pSHPropStgReadMultiple = (void*)GetProcAddress(hmod, "SHPropStgReadMultiple");
79 pSHPropStgWriteMultiple = (void*)GetProcAddress(hmod, "SHPropStgWriteMultiple");
82 static HRESULT WINAPI PropertyStorage_QueryInterface(IPropertyStorage *This,
83 REFIID riid, void **ppvObject)
85 ok(0, "unexpected call\n");
89 static ULONG WINAPI PropertyStorage_AddRef(IPropertyStorage *This)
91 ok(0, "unexpected call\n");
95 static ULONG WINAPI PropertyStorage_Release(IPropertyStorage *This)
97 CHECK_EXPECT(Release);
101 static HRESULT WINAPI PropertyStorage_ReadMultiple(IPropertyStorage *This, ULONG cpspec,
102 const PROPSPEC *rgpspec, PROPVARIANT *rgpropvar)
105 CHECK_EXPECT(ReadMultipleCodePage);
107 ok(rgpspec != NULL, "rgpspec = NULL\n");
108 ok(rgpropvar != NULL, "rgpropvar = NULL\n");
110 ok(rgpspec[0].ulKind == PRSPEC_PROPID, "rgpspec[0].ulKind = %d\n", rgpspec[0].ulKind);
111 ok(rgpspec[0].u.propid == PID_CODEPAGE, "rgpspec[0].propid = %d\n", rgpspec[0].u.propid);
113 rgpropvar[0].vt = VT_I2;
114 rgpropvar[0].u.iVal = 1234;
116 CHECK_EXPECT(ReadMultiple);
118 ok(cpspec == 10, "cpspec = %u\n", cpspec);
119 ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec);
120 ok(rgpropvar != NULL, "rgpropvar = NULL\n");
122 ok(rgpropvar[0].vt==0 || broken(rgpropvar[0].vt==VT_BSTR), "rgpropvar[0].vt = %d\n", rgpropvar[0].vt);
124 rgpropvar[0].vt = VT_BSTR;
125 rgpropvar[0].u.bstrVal = (void*)0xdeadbeef;
126 rgpropvar[1].vt = VT_LPSTR;
127 rgpropvar[1].u.pszVal = (void*)0xdeadbeef;
128 rgpropvar[2].vt = VT_BYREF|VT_I1;
129 rgpropvar[2].u.pcVal = (void*)0xdeadbeef;
130 rgpropvar[3].vt = VT_BYREF|VT_VARIANT;
131 rgpropvar[3].u.pvarVal = (void*)0xdeadbeef;
137 static HRESULT WINAPI PropertyStorage_WriteMultiple(IPropertyStorage *This, ULONG cpspec,
138 const PROPSPEC *rgpspec, const PROPVARIANT *rgpropvar,
139 PROPID propidNameFirst)
141 CHECK_EXPECT(WriteMultiple);
143 ok(cpspec == 20, "cpspec = %d\n", cpspec);
144 ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec);
145 ok(rgpropvar == (void*)0xdeadbeef, "rgpropvar = %p\n", rgpspec);
146 ok(propidNameFirst == PID_FIRST_USABLE, "propidNameFirst = %d\n", propidNameFirst);
150 static HRESULT WINAPI PropertyStorage_DeleteMultiple(IPropertyStorage *This, ULONG cpspec,
151 const PROPSPEC *rgpspec)
153 ok(0, "unexpected call\n");
157 static HRESULT WINAPI PropertyStorage_ReadPropertyNames(IPropertyStorage *This, ULONG cpropid,
158 const PROPID *rgpropid, LPOLESTR *rglpwstrName)
160 ok(0, "unexpected call\n");
164 static HRESULT WINAPI PropertyStorage_WritePropertyNames(IPropertyStorage *This, ULONG cpropid,
165 const PROPID *rgpropid, const LPOLESTR *rglpwstrName)
167 ok(0, "unexpected call\n");
171 static HRESULT WINAPI PropertyStorage_DeletePropertyNames(IPropertyStorage *This, ULONG cpropid,
172 const PROPID *rgpropid)
174 ok(0, "unexpected call\n");
178 static HRESULT WINAPI PropertyStorage_Commit(IPropertyStorage *This, DWORD grfCommitFlags)
180 ok(0, "unexpected call\n");
184 static HRESULT WINAPI PropertyStorage_Revert(IPropertyStorage *This)
186 ok(0, "unexpected call\n");
190 static HRESULT WINAPI PropertyStorage_Enum(IPropertyStorage *This, IEnumSTATPROPSTG **ppenum)
192 ok(0, "unexpected call\n");
196 static HRESULT WINAPI PropertyStorage_SetTimes(IPropertyStorage *This, const FILETIME *pctime,
197 const FILETIME *patime, const FILETIME *pmtime)
199 ok(0, "unexpected call\n");
203 static HRESULT WINAPI PropertyStorage_SetClass(IPropertyStorage *This, REFCLSID clsid)
205 ok(0, "unexpected call\n");
209 static HRESULT WINAPI PropertyStorage_Stat(IPropertyStorage *This, STATPROPSETSTG *statpsstg)
213 memset(statpsstg, 0, sizeof(STATPROPSETSTG));
214 memcpy(&statpsstg->fmtid, &FMTID_Test, sizeof(FMTID));
215 statpsstg->grfFlags = PROPSETFLAG_ANSI;
219 static IPropertyStorageVtbl PropertyStorageVtbl = {
220 PropertyStorage_QueryInterface,
221 PropertyStorage_AddRef,
222 PropertyStorage_Release,
223 PropertyStorage_ReadMultiple,
224 PropertyStorage_WriteMultiple,
225 PropertyStorage_DeleteMultiple,
226 PropertyStorage_ReadPropertyNames,
227 PropertyStorage_WritePropertyNames,
228 PropertyStorage_DeletePropertyNames,
229 PropertyStorage_Commit,
230 PropertyStorage_Revert,
231 PropertyStorage_Enum,
232 PropertyStorage_SetTimes,
233 PropertyStorage_SetClass,
237 static IPropertyStorage PropertyStorage = { &PropertyStorageVtbl };
239 static HRESULT WINAPI PropertySetStorage_QueryInterface(IPropertySetStorage *This,
240 REFIID riid, void **ppvObject)
242 ok(0, "unexpected call\n");
246 static ULONG WINAPI PropertySetStorage_AddRef(IPropertySetStorage *This)
248 ok(0, "unexpected call\n");
252 static ULONG WINAPI PropertySetStorage_Release(IPropertySetStorage *This)
254 ok(0, "unexpected call\n");
258 static HRESULT WINAPI PropertySetStorage_Create(IPropertySetStorage *This,
259 REFFMTID rfmtid, const CLSID *pclsid, DWORD grfFlags,
260 DWORD grfMode, IPropertyStorage **ppprstg)
262 CHECK_EXPECT(Create);
263 ok(IsEqualGUID(rfmtid, &FMTID_Test) || IsEqualGUID(rfmtid, &FMTID_NotExisting),
264 "Incorrect rfmtid value\n");
265 ok(pclsid == NULL, "pclsid != NULL\n");
266 ok(grfFlags == PROPSETFLAG_ANSI, "grfFlags = %x\n", grfFlags);
267 ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode);
269 *ppprstg = &PropertyStorage;
273 static HRESULT WINAPI PropertySetStorage_Open(IPropertySetStorage *This,
274 REFFMTID rfmtid, DWORD grfMode, IPropertyStorage **ppprstg)
278 if(IsEqualGUID(rfmtid, &FMTID_Test)) {
279 ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode);
281 *ppprstg = &PropertyStorage;
285 return STG_E_FILENOTFOUND;
288 static HRESULT WINAPI PropertySetStorage_Delete(IPropertySetStorage *This,
291 CHECK_EXPECT(Delete);
292 ok(IsEqualGUID(rfmtid, &FMTID_Test), "wrong rfmtid value\n");
296 static HRESULT WINAPI PropertySetStorage_Enum(IPropertySetStorage *This,
297 IEnumSTATPROPSETSTG **ppenum)
299 ok(0, "unexpected call\n");
303 static IPropertySetStorageVtbl PropertySetStorageVtbl = {
304 PropertySetStorage_QueryInterface,
305 PropertySetStorage_AddRef,
306 PropertySetStorage_Release,
307 PropertySetStorage_Create,
308 PropertySetStorage_Open,
309 PropertySetStorage_Delete,
310 PropertySetStorage_Enum
313 static IPropertySetStorage PropertySetStorage = { &PropertySetStorageVtbl };
315 static void test_SHPropStg_functions(void)
317 IPropertyStorage *property_storage;
319 PROPVARIANT read[10];
322 if(!pSHPropStgCreate || !pSHPropStgReadMultiple || !pSHPropStgWriteMultiple) {
323 win_skip("SHPropStg* functions are missing\n");
328 /* Crashes on Windows */
329 pSHPropStgCreate(NULL, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
330 STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
331 pSHPropStgCreate(&PropertySetStorage, NULL, NULL, PROPSETFLAG_DEFAULT,
332 STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
333 pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
334 STGM_READ, OPEN_EXISTING, NULL, &codepage);
338 SET_EXPECT(ReadMultipleCodePage);
339 hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
340 STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
341 ok(codepage == 1234, "codepage = %d\n", codepage);
342 ok(hres == S_OK, "hres = %x\n", hres);
344 CHECK_CALLED(ReadMultipleCodePage);
347 hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL,
348 PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
349 ok(hres == STG_E_FILENOTFOUND, "hres = %x\n", hres);
356 SET_EXPECT(ReadMultipleCodePage);
357 hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_ANSI,
358 STGM_READ, CREATE_ALWAYS, &property_storage, &codepage);
359 ok(codepage == 1234, "codepage = %d\n", codepage);
360 ok(hres == S_OK, "hres = %x\n", hres);
362 CHECK_CALLED(Release);
363 CHECK_CALLED(Delete);
364 CHECK_CALLED(Create);
365 CHECK_CALLED(ReadMultipleCodePage);
369 SET_EXPECT(ReadMultipleCodePage);
370 hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL, PROPSETFLAG_ANSI,
371 STGM_READ, CREATE_ALWAYS, &property_storage, &codepage);
372 ok(codepage == 1234, "codepage = %d\n", codepage);
373 ok(hres == S_OK, "hres = %x\n", hres);
375 CHECK_CALLED(Create);
376 CHECK_CALLED(ReadMultipleCodePage);
379 hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, &FMTID_NotExisting,
380 PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, NULL);
381 ok(hres == S_OK, "hres = %x\n", hres);
385 SET_EXPECT(ReadMultipleCodePage);
386 SET_EXPECT(WriteMultiple);
388 hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
389 ok(hres == S_OK, "hres = %x\n", hres);
390 ok(codepage == 1234, "codepage = %d\n", codepage);
392 CHECK_CALLED(ReadMultipleCodePage);
393 CHECK_CALLED(WriteMultiple);
396 SET_EXPECT(ReadMultipleCodePage);
397 SET_EXPECT(WriteMultiple);
398 hres = pSHPropStgWriteMultiple(property_storage, NULL, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
399 ok(hres == S_OK, "hres = %x\n", hres);
401 CHECK_CALLED(ReadMultipleCodePage);
402 CHECK_CALLED(WriteMultiple);
405 SET_EXPECT(WriteMultiple);
407 hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
408 ok(hres == S_OK, "hres = %x\n", hres);
409 ok(codepage == 1000, "codepage = %d\n", codepage);
411 CHECK_CALLED(WriteMultiple);
413 read[0].vt = VT_BSTR;
414 read[0].u.bstrVal = (void*)0xdeadbeef;
415 SET_EXPECT(ReadMultiple);
416 SET_EXPECT(ReadMultipleCodePage);
418 hres = pSHPropStgReadMultiple(property_storage, 0, 10, (void*)0xdeadbeef, read);
419 ok(hres == S_OK, "hres = %x\n", hres);
420 CHECK_CALLED(ReadMultiple);
421 CHECK_CALLED(ReadMultipleCodePage);
424 SET_EXPECT(ReadMultiple);
426 hres = pSHPropStgReadMultiple(property_storage, 1251, 10, (void*)0xdeadbeef, read);
427 ok(hres == S_OK, "hres = %x\n", hres);
428 CHECK_CALLED(ReadMultiple);
436 test_SHPropStg_functions();