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