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();