1 /* 2 * Copyright 2013 Ludger Sprenker 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 <stdarg.h> 20 #include <math.h> 21 22 #define COBJMACROS 23 #define CONST_VTABLE 24 25 #include "windef.h" 26 #include "objbase.h" 27 #include "wincodec.h" 28 #include "wincodecsdk.h" 29 #include "wine/test.h" 30 31 static const WCHAR wszTestProperty1[] = {'P','r','o','p','e','r','t','y','1',0}; 32 static const WCHAR wszTestProperty2[] = {'P','r','o','p','e','r','t','y','2',0}; 33 static const WCHAR wszTestInvalidProperty[] = {'I','n','v','a','l','i','d',0}; 34 35 static void test_propertybag_getpropertyinfo(IPropertyBag2 *property, ULONG expected_count) 36 { 37 HRESULT hr; 38 PROPBAG2 pb[2]; 39 ULONG out_count; 40 41 /* iProperty: Out of bounce */ 42 hr = IPropertyBag2_GetPropertyInfo(property, expected_count, 1, pb, &out_count); 43 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, 44 "GetPropertyInfo handled iProperty out of bounce wrong, hr=%x\n", hr); 45 46 /* cProperty: Out of bounce */ 47 hr = IPropertyBag2_GetPropertyInfo(property, 0, expected_count+1, pb, &out_count); 48 ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE, 49 "GetPropertyInfo handled cProperty out of bounce wrong, hr=%x\n", hr); 50 51 /* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */ 52 if (expected_count == 0) 53 return; 54 55 hr = IPropertyBag2_GetPropertyInfo(property, 0, expected_count, pb, &out_count); 56 ok(hr == S_OK, "GetPropertyInfo failed, hr=%x\n", hr); 57 if (FAILED(hr)) 58 return; 59 60 ok(expected_count == out_count, 61 "GetPropertyInfo returned unexpected property count, %i != %i)\n", 62 expected_count, out_count); 63 64 if(expected_count != 2) 65 return; 66 67 ok(pb[0].vt == VT_UI1, "Invalid variant type, pb[0].vt=%x\n", pb[0].vt); 68 ok(pb[0].dwType == PROPBAG2_TYPE_DATA, "Invalid variant type, pb[0].dwType=%x\n", pb[0].dwType); 69 ok(lstrcmpW(pb[0].pstrName, wszTestProperty1) == 0, "Invalid property name, pb[0].pstrName=%s\n", wine_dbgstr_w(pb[0].pstrName)); 70 CoTaskMemFree(pb[0].pstrName); 71 72 ok(pb[1].vt == VT_R4, "Invalid variant type, pb[1].vt=%x\n", pb[1].vt); 73 ok(pb[1].dwType == PROPBAG2_TYPE_DATA, "Invalid variant type, pb[1].dwType=%x\n", pb[1].dwType); 74 ok(lstrcmpW(pb[1].pstrName, wszTestProperty2) == 0, "Invalid property name, pb[1].pstrName=%s\n", wine_dbgstr_w(pb[1].pstrName)); 75 CoTaskMemFree(pb[1].pstrName); 76 } 77 78 static void test_propertybag_countproperties(IPropertyBag2 *property, ULONG expected_count) 79 { 80 ULONG count = (ULONG)-1; 81 HRESULT hr; 82 83 hr = IPropertyBag2_CountProperties(property, NULL); 84 ok(hr == E_INVALIDARG, "CountProperties returned unexpected result, hr=%x\n", hr); 85 86 hr = IPropertyBag2_CountProperties(property, &count); 87 ok(hr == S_OK, "CountProperties failed, hr=%x\n", hr); 88 89 if (FAILED(hr)) 90 return; 91 92 ok(count == expected_count, "CountProperties returned invalid value, count=%i\n", count); 93 } 94 95 static void test_propertybag_read(IPropertyBag2 *property) 96 { 97 HRESULT hr; 98 PROPBAG2 options[3] = {{0}}; 99 VARIANT values[3]; 100 HRESULT itm_hr[3] = {S_OK, S_OK, S_OK}; 101 102 /* 1. One unknown property */ 103 options[0].pstrName = (LPOLESTR)wszTestInvalidProperty; 104 hr = IPropertyBag2_Read(property, 1, options, NULL, values, itm_hr); 105 ok(hr == E_FAIL, 106 "Read for an unknown property did not fail with expected code, hr=%x\n", hr); 107 108 /* 2. One known property */ 109 options[0].pstrName = (LPOLESTR)wszTestProperty1; 110 itm_hr[0] = E_FAIL; 111 hr = IPropertyBag2_Read(property, 1, options, NULL, values, itm_hr); 112 ok(hr == S_OK, "Read failed, hr=%x\n", hr); 113 if (SUCCEEDED(hr)) 114 { 115 ok(itm_hr[0] == S_OK, 116 "Read failed, itm_hr[0]=%x\n", itm_hr[0]); 117 ok(V_VT(&values[0]) == VT_UI1, 118 "Read failed, V_VT(&values[0])=%x\n", V_VT(&values[0])); 119 ok(V_UNION(&values[0], bVal) == 12, 120 "Read failed, &values[0]=%i\n", V_UNION(&values[0], bVal)); 121 122 VariantClear(&values[0]); 123 } 124 125 /* 3. Two known properties */ 126 options[0].pstrName = (LPOLESTR)wszTestProperty1; 127 options[1].pstrName = (LPOLESTR)wszTestProperty2; 128 itm_hr[0] = E_FAIL; 129 itm_hr[1] = E_FAIL; 130 hr = IPropertyBag2_Read(property, 2, options, NULL, values, itm_hr); 131 ok(hr == S_OK, "Read failed, hr=%x\n", hr); 132 if (SUCCEEDED(hr)) 133 { 134 ok(itm_hr[0] == S_OK, "Read failed, itm_hr[0]=%x\n", itm_hr[0]); 135 ok(V_VT(&values[0]) == VT_UI1, "Read failed, V_VT(&values[0])=%x\n", V_VT(&values[0])); 136 ok(V_UNION(&values[0], bVal) == 12, "Read failed, &values[0]=%i\n", V_UNION(&values[0], bVal)); 137 138 ok(itm_hr[1] == S_OK, "Read failed, itm_hr[1]=%x\n", itm_hr[1]); 139 ok(V_VT(&values[1]) == VT_R4, "Read failed, V_VT(&values[1])=%x\n", V_VT(&values[1])); 140 ok(V_UNION(&values[1], fltVal) == (float)3.14, "Read failed, &values[1]=%f\n", V_UNION(&values[1], fltVal)); 141 142 VariantClear(&values[0]); 143 VariantClear(&values[1]); 144 } 145 146 147 /* 4. One unknown property between two valid */ 148 149 /* Exotic initializations so we can detect what is unchanged */ 150 itm_hr[0] = -1; itm_hr[1] = -1; itm_hr[2] = -1; 151 V_VT(&values[0]) = VT_NULL; 152 V_VT(&values[1]) = VT_NULL; 153 V_VT(&values[2]) = VT_NULL; 154 V_UNION(&values[0], bVal) = 254; 155 V_UNION(&values[1], bVal) = 254; 156 V_UNION(&values[2], bVal) = 254; 157 158 options[0].pstrName = (LPOLESTR)wszTestProperty1; 159 options[1].pstrName = (LPOLESTR)wszTestInvalidProperty; 160 options[2].pstrName = (LPOLESTR)wszTestProperty2; 161 162 hr = IPropertyBag2_Read(property, 3, options, NULL, values, itm_hr); 163 ok(hr == E_FAIL, "Read failed, hr=%x\n", hr); 164 if (hr == E_FAIL) 165 { 166 ok(itm_hr[0] == S_OK, "Read error code has unexpected value, itm_hr[0]=%x\n", itm_hr[0]); 167 ok(itm_hr[1] == -1, "Read error code has unexpected value, itm_hr[1]=%x\n", itm_hr[1]); 168 ok(itm_hr[2] == -1, "Read error code has unexpected value, itm_hr[2]=%x\n", itm_hr[2]); 169 170 ok(V_VT(&values[0]) == VT_UI1, "Read variant has unexpected type, V_VT(&values[0])=%x\n", V_VT(&values[0])); 171 ok(V_VT(&values[1]) == VT_NULL, "Read variant has unexpected type, V_VT(&values[1])=%x\n", V_VT(&values[1])); 172 ok(V_VT(&values[2]) == VT_NULL, "Read variant has unexpected type, V_VT(&values[2])=%x\n", V_VT(&values[2])); 173 174 ok(V_UNION(&values[0], bVal) == 12, "Read variant has unexpected value, V_UNION(&values[0])=%i\n", V_UNION(&values[0], bVal)); 175 ok(V_UNION(&values[1], bVal) == 254, "Read variant has unexpected value, V_UNION(&values[1])=%i\n", V_UNION(&values[1], bVal)); 176 ok(V_UNION(&values[2], bVal) == 254, "Read variant has unexpected value, V_UNION(&values[2])=%i\n", V_UNION(&values[2], bVal)); 177 } 178 } 179 180 static void test_propertybag_write(IPropertyBag2 *property) 181 { 182 HRESULT hr; 183 PROPBAG2 options[2] = {{0}}; 184 VARIANT values[2]; 185 186 VariantInit(&values[0]); 187 VariantInit(&values[1]); 188 189 /* 1. One unknown property */ 190 options[0].pstrName = (LPOLESTR)wszTestInvalidProperty; 191 hr = IPropertyBag2_Write(property, 1, options, values); 192 ok(hr == E_FAIL, "Write for an unknown property did not fail with expected code, hr=%x\n", hr); 193 194 /* 2. One property without correct type */ 195 options[0].pstrName = (LPOLESTR)wszTestProperty1; 196 V_VT(&values[0]) = VT_UI1; 197 V_UNION(&values[0], bVal) = 1; 198 hr = IPropertyBag2_Write(property, 1, options, values); 199 ok(hr == S_OK, "Write for one property failed, hr=%x\n", hr); 200 201 /* 3. One property with mismatching type */ 202 options[0].pstrName = (LPOLESTR)wszTestProperty1; 203 V_VT(&values[0]) = VT_I1; 204 V_UNION(&values[0], bVal) = 2; 205 hr = IPropertyBag2_Write(property, 1, options, values); 206 ok(hr == WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE, 207 "Write with mismatching type did not fail with expected code hr=%x\n", hr); 208 209 /* 4. Reset one property to empty */ 210 options[0].pstrName = (LPOLESTR)wszTestProperty1; 211 VariantClear(&values[0]); 212 hr = IPropertyBag2_Write(property, 1, options, values); 213 ok(hr == WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE, 214 "Write to reset to empty value does not fail with expected code, hr=%x\n", hr); 215 216 /* 5. Set two properties */ 217 options[0].pstrName = (LPOLESTR)wszTestProperty1; 218 V_VT(&values[0]) = VT_UI1; 219 V_UNION(&values[0], bVal) = 12; 220 options[1].pstrName = (LPOLESTR)wszTestProperty2; 221 V_VT(&values[1]) = VT_R4; 222 V_UNION(&values[1], fltVal) = (float)3.14; 223 hr = IPropertyBag2_Write(property, 2, options, values); 224 ok(hr == S_OK, "Write for two properties failed, hr=%x\n", hr); 225 } 226 227 static void test_empty_propertybag(void) 228 { 229 HRESULT hr; 230 IWICComponentFactory *factory; 231 IPropertyBag2 *property; 232 233 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, 234 &IID_IWICComponentFactory, (void**)&factory); 235 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); 236 237 hr = IWICComponentFactory_CreateEncoderPropertyBag(factory, NULL, 0, &property); 238 239 ok(hr == S_OK, "Creating EncoderPropertyBag failed, hr=%x\n", hr); 240 if (FAILED(hr)) return; 241 242 test_propertybag_countproperties(property, 0); 243 244 test_propertybag_getpropertyinfo(property, 0); 245 246 IPropertyBag2_Release(property); 247 248 IWICComponentFactory_Release(factory); 249 } 250 251 static void test_filled_propertybag(void) 252 { 253 HRESULT hr; 254 IWICComponentFactory *factory; 255 IPropertyBag2 *property; 256 PROPBAG2 opts[2]= { 257 {PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszTestProperty1, {0}}, 258 {PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszTestProperty2, {0}} 259 }; 260 261 hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, 262 &IID_IWICComponentFactory, (void**)&factory); 263 ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr); 264 265 hr = IWICComponentFactory_CreateEncoderPropertyBag(factory, opts, 2, &property); 266 267 ok(hr == S_OK, "Creating EncoderPropertyBag failed, hr=%x\n", hr); 268 if (FAILED(hr)) return; 269 270 test_propertybag_countproperties(property, 2); 271 272 test_propertybag_getpropertyinfo(property, 2); 273 274 test_propertybag_write(property); 275 276 test_propertybag_read(property); 277 278 IPropertyBag2_Release(property); 279 280 IWICComponentFactory_Release(factory); 281 } 282 283 START_TEST(propertybag) 284 { 285 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 286 287 test_empty_propertybag(); 288 289 test_filled_propertybag(); 290 291 CoUninitialize(); 292 } 293