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