1 /*
2  * Unit tests for IPropertyStore and related interfaces
3  *
4  * Copyright 2012 Vincent Povirk
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 COBJMACROS
22 
23 #include <stdarg.h>
24 #include <stdio.h>
25 
26 #define NONAMELESSUNION
27 
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "propsys.h"
32 #include "wine/test.h"
33 
34 #include "initguid.h"
35 
36 DEFINE_GUID(PKEY_WineTest, 0x7b317433, 0xdfa3, 0x4c44, 0xad, 0x3e, 0x2f, 0x80, 0x4b, 0x90, 0xdb, 0xf4);
37 
38 static void test_inmemorystore(void)
39 {
40     IPropertyStoreCache *propcache;
41     HRESULT hr;
42     PROPERTYKEY pkey;
43     PROPVARIANT propvar;
44     DWORD count;
45     PSC_STATE state;
46 
47     hr = CoCreateInstance(&CLSID_InMemoryPropertyStore, NULL, CLSCTX_INPROC_SERVER,
48         &IID_IPropertyStoreCache, (void**)&propcache);
49     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
50 
51     if (FAILED(hr))
52     {
53         skip("CLSID_InMemoryPropertyStore not supported\n");
54         return;
55     }
56 
57     hr = IPropertyStoreCache_GetCount(propcache, NULL);
58     ok(hr == E_POINTER, "GetCount failed, hr=%x\n", hr);
59 
60     hr = IPropertyStoreCache_GetCount(propcache, &count);
61     ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
62     ok(count == 0, "GetCount returned %i, expected 0\n", count);
63 
64     hr = IPropertyStoreCache_Commit(propcache);
65     ok(hr == S_OK, "Commit failed, hr=%x\n", hr);
66 
67     hr = IPropertyStoreCache_Commit(propcache);
68     ok(hr == S_OK, "Commit failed, hr=%x\n", hr);
69 
70     hr = IPropertyStoreCache_GetAt(propcache, 0, &pkey);
71     ok(hr == E_INVALIDARG, "GetAt failed, hr=%x\n", hr);
72 
73     pkey.fmtid = PKEY_WineTest;
74     pkey.pid = 4;
75 
76     memset(&propvar, 0, sizeof(propvar));
77     propvar.vt = VT_I4;
78     propvar.u.lVal = 12345;
79 
80     if (0)
81     {
82         /* Crashes on Windows 7 */
83         hr = IPropertyStoreCache_SetValue(propcache, NULL, &propvar);
84         ok(hr == E_POINTER, "SetValue failed, hr=%x\n", hr);
85 
86         hr = IPropertyStoreCache_SetValue(propcache, &pkey, NULL);
87         ok(hr == E_POINTER, "SetValue failed, hr=%x\n", hr);
88     }
89 
90     hr = IPropertyStoreCache_SetValue(propcache, &pkey, &propvar);
91     ok(hr == S_OK, "SetValue failed, hr=%x\n", hr);
92 
93     hr = IPropertyStoreCache_GetCount(propcache, &count);
94     ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
95     ok(count == 1, "GetCount returned %i, expected 0\n", count);
96 
97     memset(&pkey, 0, sizeof(pkey));
98 
99     hr = IPropertyStoreCache_GetAt(propcache, 0, &pkey);
100     ok(hr == S_OK, "GetAt failed, hr=%x\n", hr);
101     ok(IsEqualGUID(&pkey.fmtid, &PKEY_WineTest), "got wrong pkey\n");
102     ok(pkey.pid == 4, "got pid of %i, expected 4\n", pkey.pid);
103 
104     pkey.fmtid = PKEY_WineTest;
105     pkey.pid = 4;
106 
107     memset(&propvar, 0, sizeof(propvar));
108 
109     if (0)
110     {
111         /* Crashes on Windows 7 */
112         hr = IPropertyStoreCache_GetValue(propcache, NULL, &propvar);
113         ok(hr == E_POINTER, "GetValue failed, hr=%x\n", hr);
114     }
115 
116     hr = IPropertyStoreCache_GetValue(propcache, &pkey, NULL);
117     ok(hr == E_POINTER, "GetValue failed, hr=%x\n", hr);
118 
119     hr = IPropertyStoreCache_GetValue(propcache, &pkey, &propvar);
120     ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
121     ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt);
122     ok(propvar.u.lVal == 12345, "expected 12345, got %d\n", propvar.u.lVal);
123 
124     pkey.fmtid = PKEY_WineTest;
125     pkey.pid = 10;
126 
127     /* Get information for field that isn't set yet */
128     propvar.vt = VT_I2;
129     hr = IPropertyStoreCache_GetValue(propcache, &pkey, &propvar);
130     ok(hr == S_OK, "GetValue failed, hr=%x\n", hr);
131     ok(propvar.vt == VT_EMPTY, "expected VT_EMPTY, got %d\n", propvar.vt);
132 
133     state = 0xdeadbeef;
134     hr = IPropertyStoreCache_GetState(propcache, &pkey, &state);
135     ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetState failed, hr=%x\n", hr);
136     ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state);
137 
138     propvar.vt = VT_I2;
139     state = 0xdeadbeef;
140     hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state);
141     ok(hr == TYPE_E_ELEMENTNOTFOUND, "GetValueAndState failed, hr=%x\n", hr);
142     ok(propvar.vt == VT_EMPTY, "expected VT_EMPTY, got %d\n", propvar.vt);
143     ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state);
144 
145     /* Set state on an unset field */
146     hr = IPropertyStoreCache_SetState(propcache, &pkey, PSC_NORMAL);
147     ok(hr == TYPE_E_ELEMENTNOTFOUND, "SetState failed, hr=%x\n", hr);
148 
149     /* Manipulate state on already set field */
150     pkey.fmtid = PKEY_WineTest;
151     pkey.pid = 4;
152 
153     state = 0xdeadbeef;
154     hr = IPropertyStoreCache_GetState(propcache, &pkey, &state);
155     ok(hr == S_OK, "GetState failed, hr=%x\n", hr);
156     ok(state == PSC_NORMAL, "expected PSC_NORMAL, got %d\n", state);
157 
158     hr = IPropertyStoreCache_SetState(propcache, &pkey, 10);
159     ok(hr == S_OK, "SetState failed, hr=%x\n", hr);
160 
161     state = 0xdeadbeef;
162     hr = IPropertyStoreCache_GetState(propcache, &pkey, &state);
163     ok(hr == S_OK, "GetState failed, hr=%x\n", hr);
164     ok(state == 10, "expected 10, got %d\n", state);
165 
166     propvar.vt = VT_I4;
167     propvar.u.lVal = 12346;
168     hr = IPropertyStoreCache_SetValueAndState(propcache, &pkey, &propvar, 5);
169     ok(hr == S_OK, "SetValueAndState failed, hr=%x\n", hr);
170 
171     memset(&propvar, 0, sizeof(propvar));
172     state = 0xdeadbeef;
173     hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state);
174     ok(hr == S_OK, "GetValueAndState failed, hr=%x\n", hr);
175     ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt);
176     ok(propvar.u.lVal == 12346, "expected 12346, got %d\n", propvar.vt);
177     ok(state == 5, "expected 5, got %d\n", state);
178 
179     /* Set new field with state */
180     pkey.fmtid = PKEY_WineTest;
181     pkey.pid = 8;
182 
183     propvar.vt = VT_I4;
184     propvar.u.lVal = 12347;
185     hr = IPropertyStoreCache_SetValueAndState(propcache, &pkey, &propvar, PSC_DIRTY);
186     ok(hr == S_OK, "SetValueAndState failed, hr=%x\n", hr);
187 
188     memset(&propvar, 0, sizeof(propvar));
189     state = 0xdeadbeef;
190     hr = IPropertyStoreCache_GetValueAndState(propcache, &pkey, &propvar, &state);
191     ok(hr == S_OK, "GetValueAndState failed, hr=%x\n", hr);
192     ok(propvar.vt == VT_I4, "expected VT_I4, got %d\n", propvar.vt);
193     ok(propvar.u.lVal == 12347, "expected 12347, got %d\n", propvar.vt);
194     ok(state == PSC_DIRTY, "expected PSC_DIRTY, got %d\n", state);
195 
196     IPropertyStoreCache_Release(propcache);
197 }
198 
199 static void test_persistserialized(void)
200 {
201     IPropertyStore *propstore;
202     IPersistSerializedPropStorage *serialized;
203     HRESULT hr;
204     SERIALIZEDPROPSTORAGE *result;
205     DWORD result_size;
206 
207     hr = CoCreateInstance(&CLSID_InMemoryPropertyStore, NULL, CLSCTX_INPROC_SERVER,
208         &IID_IPropertyStore, (void**)&propstore);
209     ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
210 
211     hr = IPropertyStore_QueryInterface(propstore, &IID_IPersistSerializedPropStorage,
212         (void**)&serialized);
213     todo_wine ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr);
214 
215     if (FAILED(hr))
216     {
217         skip("IPersistSerializedPropStorage not supported\n");
218         return;
219     }
220 
221     hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, NULL, &result_size);
222     ok(hr == E_POINTER, "GetPropertyStorage failed, hr=%x\n", hr);
223 
224     hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, &result, NULL);
225     ok(hr == E_POINTER, "GetPropertyStorage failed, hr=%x\n", hr);
226 
227     hr = IPersistSerializedPropStorage_GetPropertyStorage(serialized, &result, &result_size);
228     ok(hr == S_OK, "GetPropertyStorage failed, hr=%x\n", hr);
229 
230     if (SUCCEEDED(hr))
231     {
232         ok(result_size == 0, "expected 0 bytes, got %i\n", result_size);
233 
234         CoTaskMemFree(result);
235     }
236 
237     hr = IPersistSerializedPropStorage_SetPropertyStorage(serialized, NULL, 4);
238     ok(hr == E_POINTER, "SetPropertyStorage failed, hr=%x\n", hr);
239 
240     hr = IPersistSerializedPropStorage_SetPropertyStorage(serialized, NULL, 0);
241     ok(hr == S_OK, "SetPropertyStorage failed, hr=%x\n", hr);
242 
243     hr = IPropertyStore_GetCount(propstore, &result_size);
244     ok(hr == S_OK, "GetCount failed, hr=%x\n", hr);
245     ok(result_size == 0, "expecting 0, got %d\n", result_size);
246 
247     IPropertyStore_Release(propstore);
248     IPersistSerializedPropStorage_Release(serialized);
249 }
250 
251 START_TEST(propstore)
252 {
253     CoInitialize(NULL);
254 
255     test_inmemorystore();
256     test_persistserialized();
257 
258     CoUninitialize();
259 }
260