293 lines
11 KiB
C
293 lines
11 KiB
C
/*
|
|
* Copyright 2013 Ludger Sprenker
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
#include <math.h>
|
|
|
|
#define COBJMACROS
|
|
#define CONST_VTABLE
|
|
|
|
#include "windef.h"
|
|
#include "objbase.h"
|
|
#include "wincodec.h"
|
|
#include "wincodecsdk.h"
|
|
#include "wine/test.h"
|
|
|
|
static const WCHAR wszTestProperty1[] = {'P','r','o','p','e','r','t','y','1',0};
|
|
static const WCHAR wszTestProperty2[] = {'P','r','o','p','e','r','t','y','2',0};
|
|
static const WCHAR wszTestInvalidProperty[] = {'I','n','v','a','l','i','d',0};
|
|
|
|
static void test_propertybag_getpropertyinfo(IPropertyBag2 *property, ULONG expected_count)
|
|
{
|
|
HRESULT hr;
|
|
PROPBAG2 pb[2];
|
|
ULONG out_count;
|
|
|
|
/* iProperty: Out of bounce */
|
|
hr = IPropertyBag2_GetPropertyInfo(property, expected_count, 1, pb, &out_count);
|
|
ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE,
|
|
"GetPropertyInfo handled iProperty out of bounce wrong, hr=%x\n", hr);
|
|
|
|
/* cProperty: Out of bounce */
|
|
hr = IPropertyBag2_GetPropertyInfo(property, 0, expected_count+1, pb, &out_count);
|
|
ok(hr == WINCODEC_ERR_VALUEOUTOFRANGE,
|
|
"GetPropertyInfo handled cProperty out of bounce wrong, hr=%x\n", hr);
|
|
|
|
/* GetPropertyInfo can be called for zero items on Windows 8 but not on Windows 7 (wine behaves like Win8) */
|
|
if (expected_count == 0)
|
|
return;
|
|
|
|
hr = IPropertyBag2_GetPropertyInfo(property, 0, expected_count, pb, &out_count);
|
|
ok(hr == S_OK, "GetPropertyInfo failed, hr=%x\n", hr);
|
|
if (FAILED(hr))
|
|
return;
|
|
|
|
ok(expected_count == out_count,
|
|
"GetPropertyInfo returned unexpected property count, %i != %i)\n",
|
|
expected_count, out_count);
|
|
|
|
if(expected_count != 2)
|
|
return;
|
|
|
|
ok(pb[0].vt == VT_UI1, "Invalid variant type, pb[0].vt=%x\n", pb[0].vt);
|
|
ok(pb[0].dwType == PROPBAG2_TYPE_DATA, "Invalid variant type, pb[0].dwType=%x\n", pb[0].dwType);
|
|
ok(lstrcmpW(pb[0].pstrName, wszTestProperty1) == 0, "Invalid property name, pb[0].pstrName=%s\n", wine_dbgstr_w(pb[0].pstrName));
|
|
CoTaskMemFree(pb[0].pstrName);
|
|
|
|
ok(pb[1].vt == VT_R4, "Invalid variant type, pb[1].vt=%x\n", pb[1].vt);
|
|
ok(pb[1].dwType == PROPBAG2_TYPE_DATA, "Invalid variant type, pb[1].dwType=%x\n", pb[1].dwType);
|
|
ok(lstrcmpW(pb[1].pstrName, wszTestProperty2) == 0, "Invalid property name, pb[1].pstrName=%s\n", wine_dbgstr_w(pb[1].pstrName));
|
|
CoTaskMemFree(pb[1].pstrName);
|
|
}
|
|
|
|
static void test_propertybag_countproperties(IPropertyBag2 *property, ULONG expected_count)
|
|
{
|
|
ULONG count = (ULONG)-1;
|
|
HRESULT hr;
|
|
|
|
hr = IPropertyBag2_CountProperties(property, NULL);
|
|
ok(hr == E_INVALIDARG, "CountProperties returned unexpected result, hr=%x\n", hr);
|
|
|
|
hr = IPropertyBag2_CountProperties(property, &count);
|
|
ok(hr == S_OK, "CountProperties failed, hr=%x\n", hr);
|
|
|
|
if (FAILED(hr))
|
|
return;
|
|
|
|
ok(count == expected_count, "CountProperties returned invalid value, count=%i\n", count);
|
|
}
|
|
|
|
static void test_propertybag_read(IPropertyBag2 *property)
|
|
{
|
|
HRESULT hr;
|
|
PROPBAG2 options[3] = {{0}};
|
|
VARIANT values[3];
|
|
HRESULT itm_hr[3] = {S_OK, S_OK, S_OK};
|
|
|
|
/* 1. One unknown property */
|
|
options[0].pstrName = (LPOLESTR)wszTestInvalidProperty;
|
|
hr = IPropertyBag2_Read(property, 1, options, NULL, values, itm_hr);
|
|
ok(hr == E_FAIL,
|
|
"Read for an unknown property did not fail with expected code, hr=%x\n", hr);
|
|
|
|
/* 2. One known property */
|
|
options[0].pstrName = (LPOLESTR)wszTestProperty1;
|
|
itm_hr[0] = E_FAIL;
|
|
hr = IPropertyBag2_Read(property, 1, options, NULL, values, itm_hr);
|
|
ok(hr == S_OK, "Read failed, hr=%x\n", hr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ok(itm_hr[0] == S_OK,
|
|
"Read failed, itm_hr[0]=%x\n", itm_hr[0]);
|
|
ok(V_VT(&values[0]) == VT_UI1,
|
|
"Read failed, V_VT(&values[0])=%x\n", V_VT(&values[0]));
|
|
ok(V_UNION(&values[0], bVal) == 12,
|
|
"Read failed, &values[0]=%i\n", V_UNION(&values[0], bVal));
|
|
|
|
VariantClear(&values[0]);
|
|
}
|
|
|
|
/* 3. Two known properties */
|
|
options[0].pstrName = (LPOLESTR)wszTestProperty1;
|
|
options[1].pstrName = (LPOLESTR)wszTestProperty2;
|
|
itm_hr[0] = E_FAIL;
|
|
itm_hr[1] = E_FAIL;
|
|
hr = IPropertyBag2_Read(property, 2, options, NULL, values, itm_hr);
|
|
ok(hr == S_OK, "Read failed, hr=%x\n", hr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ok(itm_hr[0] == S_OK, "Read failed, itm_hr[0]=%x\n", itm_hr[0]);
|
|
ok(V_VT(&values[0]) == VT_UI1, "Read failed, V_VT(&values[0])=%x\n", V_VT(&values[0]));
|
|
ok(V_UNION(&values[0], bVal) == 12, "Read failed, &values[0]=%i\n", V_UNION(&values[0], bVal));
|
|
|
|
ok(itm_hr[1] == S_OK, "Read failed, itm_hr[1]=%x\n", itm_hr[1]);
|
|
ok(V_VT(&values[1]) == VT_R4, "Read failed, V_VT(&values[1])=%x\n", V_VT(&values[1]));
|
|
ok(V_UNION(&values[1], fltVal) == (float)3.14, "Read failed, &values[1]=%f\n", V_UNION(&values[1], fltVal));
|
|
|
|
VariantClear(&values[0]);
|
|
VariantClear(&values[1]);
|
|
}
|
|
|
|
|
|
/* 4. One unknown property between two valid */
|
|
|
|
/* Exotic initializations so we can detect what is unchanged */
|
|
itm_hr[0] = -1; itm_hr[1] = -1; itm_hr[2] = -1;
|
|
V_VT(&values[0]) = VT_NULL;
|
|
V_VT(&values[1]) = VT_NULL;
|
|
V_VT(&values[2]) = VT_NULL;
|
|
V_UNION(&values[0], bVal) = 254;
|
|
V_UNION(&values[1], bVal) = 254;
|
|
V_UNION(&values[2], bVal) = 254;
|
|
|
|
options[0].pstrName = (LPOLESTR)wszTestProperty1;
|
|
options[1].pstrName = (LPOLESTR)wszTestInvalidProperty;
|
|
options[2].pstrName = (LPOLESTR)wszTestProperty2;
|
|
|
|
hr = IPropertyBag2_Read(property, 3, options, NULL, values, itm_hr);
|
|
ok(hr == E_FAIL, "Read failed, hr=%x\n", hr);
|
|
if (hr == E_FAIL)
|
|
{
|
|
ok(itm_hr[0] == S_OK, "Read error code has unexpected value, itm_hr[0]=%x\n", itm_hr[0]);
|
|
ok(itm_hr[1] == -1, "Read error code has unexpected value, itm_hr[1]=%x\n", itm_hr[1]);
|
|
ok(itm_hr[2] == -1, "Read error code has unexpected value, itm_hr[2]=%x\n", itm_hr[2]);
|
|
|
|
ok(V_VT(&values[0]) == VT_UI1, "Read variant has unexpected type, V_VT(&values[0])=%x\n", V_VT(&values[0]));
|
|
ok(V_VT(&values[1]) == VT_NULL, "Read variant has unexpected type, V_VT(&values[1])=%x\n", V_VT(&values[1]));
|
|
ok(V_VT(&values[2]) == VT_NULL, "Read variant has unexpected type, V_VT(&values[2])=%x\n", V_VT(&values[2]));
|
|
|
|
ok(V_UNION(&values[0], bVal) == 12, "Read variant has unexpected value, V_UNION(&values[0])=%i\n", V_UNION(&values[0], bVal));
|
|
ok(V_UNION(&values[1], bVal) == 254, "Read variant has unexpected value, V_UNION(&values[1])=%i\n", V_UNION(&values[1], bVal));
|
|
ok(V_UNION(&values[2], bVal) == 254, "Read variant has unexpected value, V_UNION(&values[2])=%i\n", V_UNION(&values[2], bVal));
|
|
}
|
|
}
|
|
|
|
static void test_propertybag_write(IPropertyBag2 *property)
|
|
{
|
|
HRESULT hr;
|
|
PROPBAG2 options[2] = {{0}};
|
|
VARIANT values[2];
|
|
|
|
VariantInit(&values[0]);
|
|
VariantInit(&values[1]);
|
|
|
|
/* 1. One unknown property */
|
|
options[0].pstrName = (LPOLESTR)wszTestInvalidProperty;
|
|
hr = IPropertyBag2_Write(property, 1, options, values);
|
|
ok(hr == E_FAIL, "Write for an unknown property did not fail with expected code, hr=%x\n", hr);
|
|
|
|
/* 2. One property without correct type */
|
|
options[0].pstrName = (LPOLESTR)wszTestProperty1;
|
|
V_VT(&values[0]) = VT_UI1;
|
|
V_UNION(&values[0], bVal) = 1;
|
|
hr = IPropertyBag2_Write(property, 1, options, values);
|
|
ok(hr == S_OK, "Write for one property failed, hr=%x\n", hr);
|
|
|
|
/* 3. One property with mismatching type */
|
|
options[0].pstrName = (LPOLESTR)wszTestProperty1;
|
|
V_VT(&values[0]) = VT_I1;
|
|
V_UNION(&values[0], bVal) = 2;
|
|
hr = IPropertyBag2_Write(property, 1, options, values);
|
|
ok(hr == WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE,
|
|
"Write with mismatching type did not fail with expected code hr=%x\n", hr);
|
|
|
|
/* 4. Reset one property to empty */
|
|
options[0].pstrName = (LPOLESTR)wszTestProperty1;
|
|
VariantClear(&values[0]);
|
|
hr = IPropertyBag2_Write(property, 1, options, values);
|
|
ok(hr == WINCODEC_ERR_PROPERTYUNEXPECTEDTYPE,
|
|
"Write to reset to empty value does not fail with expected code, hr=%x\n", hr);
|
|
|
|
/* 5. Set two properties */
|
|
options[0].pstrName = (LPOLESTR)wszTestProperty1;
|
|
V_VT(&values[0]) = VT_UI1;
|
|
V_UNION(&values[0], bVal) = 12;
|
|
options[1].pstrName = (LPOLESTR)wszTestProperty2;
|
|
V_VT(&values[1]) = VT_R4;
|
|
V_UNION(&values[1], fltVal) = (float)3.14;
|
|
hr = IPropertyBag2_Write(property, 2, options, values);
|
|
ok(hr == S_OK, "Write for two properties failed, hr=%x\n", hr);
|
|
}
|
|
|
|
static void test_empty_propertybag(void)
|
|
{
|
|
HRESULT hr;
|
|
IWICComponentFactory *factory;
|
|
IPropertyBag2 *property;
|
|
|
|
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
|
|
&IID_IWICComponentFactory, (void**)&factory);
|
|
ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
|
|
|
|
hr = IWICComponentFactory_CreateEncoderPropertyBag(factory, NULL, 0, &property);
|
|
|
|
ok(hr == S_OK, "Creating EncoderPropertyBag failed, hr=%x\n", hr);
|
|
if (FAILED(hr)) return;
|
|
|
|
test_propertybag_countproperties(property, 0);
|
|
|
|
test_propertybag_getpropertyinfo(property, 0);
|
|
|
|
IPropertyBag2_Release(property);
|
|
|
|
IWICComponentFactory_Release(factory);
|
|
}
|
|
|
|
static void test_filled_propertybag(void)
|
|
{
|
|
HRESULT hr;
|
|
IWICComponentFactory *factory;
|
|
IPropertyBag2 *property;
|
|
PROPBAG2 opts[2]= {
|
|
{.pstrName = (LPOLESTR)wszTestProperty1, .vt=VT_UI1, .dwType=PROPBAG2_TYPE_DATA},
|
|
{.pstrName = (LPOLESTR)wszTestProperty2, .vt=VT_R4, .dwType=PROPBAG2_TYPE_DATA}
|
|
};
|
|
|
|
hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
|
|
&IID_IWICComponentFactory, (void**)&factory);
|
|
ok(hr == S_OK, "CoCreateInstance failed, hr=%x\n", hr);
|
|
|
|
hr = IWICComponentFactory_CreateEncoderPropertyBag(factory, opts, 2, &property);
|
|
|
|
ok(hr == S_OK, "Creating EncoderPropertyBag failed, hr=%x\n", hr);
|
|
if (FAILED(hr)) return;
|
|
|
|
test_propertybag_countproperties(property, 2);
|
|
|
|
test_propertybag_getpropertyinfo(property, 2);
|
|
|
|
test_propertybag_write(property);
|
|
|
|
test_propertybag_read(property);
|
|
|
|
IPropertyBag2_Release(property);
|
|
|
|
IWICComponentFactory_Release(factory);
|
|
}
|
|
|
|
START_TEST(propertybag)
|
|
{
|
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
|
|
|
test_empty_propertybag();
|
|
|
|
test_filled_propertybag();
|
|
|
|
CoUninitialize();
|
|
}
|