[OLEAUT32_WINETEST]

* Sync with Wine 1.7.17.
CORE-8080

svn path=/trunk/; revision=62943
This commit is contained in:
Amine Khaldi
2014-04-24 15:13:22 +00:00
parent 3d27a0b5ac
commit 559ca8b24e
12 changed files with 2103 additions and 386 deletions
+7 -3
View File
@@ -2,8 +2,8 @@
add_definitions(-DUSE_WINE_TODOS)
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
add_typelib(test_reg.idl test_tlb.idl tmarshal.idl)
add_idl_Headers(oleaut32_idlheaders test_reg.idl tmarshal.idl)
generate_idl_iids(tmarshal.idl test_reg.idl)
add_idl_Headers(oleaut32_idlheaders test_reg.idl test_tlb.idl tmarshal.idl)
generate_idl_iids(test_reg.idl test_tlb.idl tmarshal.idl)
list(APPEND SOURCE
dispatch.c
@@ -18,6 +18,7 @@ list(APPEND SOURCE
vartest.c
vartype.c
${CMAKE_CURRENT_BINARY_DIR}/test_reg_i.c
${CMAKE_CURRENT_BINARY_DIR}/test_tlb_i.c
${CMAKE_CURRENT_BINARY_DIR}/tmarshal_i.c)
set(tmarshal.rc_DEPS
@@ -30,6 +31,9 @@ set_source_files_properties(tmarshal.rc PROPERTIES OBJECT_DEPENDS "${tmarshal.rc
add_executable(oleaut32_winetest ${SOURCE} tmarshal.rc)
target_link_libraries(oleaut32_winetest uuid)
set_module_type(oleaut32_winetest win32cui)
add_importlibs(oleaut32_winetest oleaut32 ole32 rpcrt4 user32 gdi32 advapi32 msvcrt kernel32 ntdll)
add_importlibs(oleaut32_winetest oleaut32 ole32 rpcrt4 user32 gdi32 advapi32 msvcrt kernel32)
if(MSVC)
add_importlibs(oleaut32_winetest ntdll)
endif()
add_dependencies(oleaut32_winetest stdole2 oleaut32_typelibs oleaut32_idlheaders)
add_cd_file(TARGET oleaut32_winetest DESTINATION reactos/bin FOR all)
+70
View File
@@ -22,6 +22,9 @@
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
#define COBJMACROS
#define CONST_VTABLE
#include <wine/test.h>
//#include <windef.h>
//#include <winbase.h>
@@ -273,7 +276,74 @@ static void test_DispGetParam(void)
VariantClear(&result);
}
static HRESULT WINAPI unk_QI(IUnknown *iface, REFIID riid, void **obj)
{
if (IsEqualIID(riid, &IID_IUnknown))
{
*obj = iface;
return S_OK;
}
else
{
*obj = NULL;
return E_NOINTERFACE;
}
}
static ULONG WINAPI unk_AddRef(IUnknown *iface)
{
return 2;
}
static ULONG WINAPI unk_Release(IUnknown *iface)
{
return 1;
}
static const IUnknownVtbl unkvtbl =
{
unk_QI,
unk_AddRef,
unk_Release
};
static IUnknown test_unk = { &unkvtbl };
static void test_CreateStdDispatch(void)
{
static const WCHAR stdole2W[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
ITypeLib *tl;
ITypeInfo *ti;
IUnknown *unk;
HRESULT hr;
hr = CreateStdDispatch(NULL, NULL, NULL, NULL);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = CreateStdDispatch(NULL, NULL, NULL, &unk);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
hr = LoadTypeLib(stdole2W, &tl);
ok(hr == S_OK, "got %08x\n", hr);
hr = ITypeLib_GetTypeInfoOfGuid(tl, &IID_IUnknown, &ti);
ok(hr == S_OK, "got %08x\n", hr);
ITypeLib_Release(tl);
hr = CreateStdDispatch(NULL, &test_unk, NULL, &unk);
ok(hr == E_INVALIDARG, "got %08x\n", hr);
hr = CreateStdDispatch(NULL, NULL, ti, &unk);
ok(hr == E_INVALIDARG, "got %08x\n", hr);
hr = CreateStdDispatch(NULL, &test_unk, ti, &unk);
ok(hr == S_OK, "got %08x\n", hr);
IUnknown_Release(unk);
ITypeInfo_Release(ti);
}
START_TEST(dispatch)
{
test_DispGetParam();
test_CreateStdDispatch();
}
+189 -66
View File
@@ -71,7 +71,7 @@ static void test_ifont_size(LONG lo_size, LONG hi_size,
LPVOID pvObj = NULL;
IFont* ifnt = NULL;
HFONT hfont;
LOGFONT lf;
LOGFONTA lf;
CY psize;
HRESULT hres;
DWORD rtnval;
@@ -82,9 +82,9 @@ static void test_ifont_size(LONG lo_size, LONG hi_size,
S(fd.cySize).Hi = hi_size;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
fd.fItalic = FALSE;
fd.fUnderline = FALSE;
fd.fStrikethrough = FALSE;
/* Create font, test that it worked. */
hres = pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj);
@@ -93,13 +93,10 @@ static void test_ifont_size(LONG lo_size, LONG hi_size,
test_name, hres);
ok(pvObj != NULL,"%s: OCFI returns NULL.\n", test_name);
/* If scaling ration specified, change ratio. */
if(ratio_logical && ratio_himetric)
{
hres = IFont_SetRatio(ifnt, ratio_logical, ratio_himetric);
ok(hres == S_OK,"%s: IFont_SetRatio returns 0x%08x instead of S_OK.\n",
test_name, hres);
}
/* Change the scaling ratio */
hres = IFont_SetRatio(ifnt, ratio_logical, ratio_himetric);
ok((ratio_logical && ratio_himetric) ? hres == S_OK : hres == E_FAIL,
"%s: IFont_SetRatio unexpectedly returned 0x%08x.\n", test_name, hres);
/* Read back size. */
hres = IFont_get_Size(ifnt, &psize);
@@ -115,7 +112,7 @@ static void test_ifont_size(LONG lo_size, LONG hi_size,
hres = IFont_get_hFont (ifnt, &hfont);
ok(hres == S_OK, "%s: IFont_get_hFont returns 0x%08x instead of S_OK.\n",
test_name, hres);
rtnval = GetObject (hfont, sizeof(LOGFONT), &lf);
rtnval = GetObjectA(hfont, sizeof(LOGFONTA), &lf);
ok(rtnval > 0, "GetObject(hfont) failed\n");
/* Since font scaling may encounter rounding errors, allow 1 pixel deviation. */
@@ -156,6 +153,41 @@ static void test_ifont_sizes(void)
test_ifont_size(180000, 0, 144, 2540, -36, "ratio2"); /* another ratio */
test_ifont_size(180000, 0, 72, 1270, -36, "ratio3"); /* yet another ratio */
test_ifont_size(186000, 0, 72, 2540, -19, "rounding+ratio"); /* test rounding with ratio */
/* test various combinations of logical == himetric */
test_ifont_size(180000, 0, 10, 10, -635, "identical ratio 1");
test_ifont_size(240000, 0, 10, 10, -848, "identical ratio 2");
test_ifont_size(300000, 0, 10, 10, -1058, "identical ratio 3");
/* test various combinations of logical and himetric both set to 1 */
test_ifont_size(180000, 0, 1, 1, -24, "1:1 ratio 1");
test_ifont_size(240000, 0, 1, 1, -32, "1:1 ratio 2");
test_ifont_size(300000, 0, 1, 1, -40, "1:1 ratio 3");
/* test various combinations of logical set to 1 */
test_ifont_size(180000, 0, 1, 0, -24, "1:0 ratio 1");
test_ifont_size(240000, 0, 1, 0, -32, "1:0 ratio 2");
test_ifont_size(300000, 0, 1, 0, -40, "1:0 ratio 3");
/* test various combinations of himetric set to 1 */
test_ifont_size(180000, 0, 0, 1, -24, "0:1 ratio 1");
test_ifont_size(240000, 0, 0, 1, -32, "0:1 ratio 2");
test_ifont_size(300000, 0, 0, 1, -40, "0:1 ratio 3");
/* test various combinations of 2:1 logical:himetric */
test_ifont_size(180000, 0, 2, 1, -1270, "2:1 ratio 1");
test_ifont_size(240000, 0, 2, 1, -1694, "2:1 ratio 2");
test_ifont_size(300000, 0, 2, 1, -2117, "2:1 ratio 3");
/* test various combinations of 1:2 logical:himetric */
test_ifont_size(180000, 0, 1, 2, -318, "1:2 ratio 1");
test_ifont_size(240000, 0, 1, 2, -424, "1:2 ratio 2");
test_ifont_size(300000, 0, 1, 2, -529, "1:2 ratio 3");
/* test various combinations of logical and himetric both set to 2 */
test_ifont_size(180000, 0, 2, 2, -635, "2:2 ratio 1");
test_ifont_size(240000, 0, 2, 2, -848, "2:2 ratio 2");
test_ifont_size(300000, 0, 2, 2, -1058, "2:2 ratio 3");
}
static void test_QueryInterface(void)
@@ -234,10 +266,7 @@ static void test_type_info(void)
IFontDisp_Release(fontdisp);
}
static HRESULT WINAPI FontEventsDisp_QueryInterface(
IFontEventsDisp *iface,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
static HRESULT WINAPI FontEventsDisp_QueryInterface(IFontEventsDisp *iface, REFIID riid, void **ppvObject)
{
if (IsEqualIID(riid, &IID_IFontEventsDisp) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
{
@@ -264,26 +293,48 @@ static ULONG WINAPI FontEventsDisp_Release(
return 1;
}
static int fonteventsdisp_invoke_called = 0;
static HRESULT WINAPI FontEventsDisp_GetTypeInfoCount(IFontEventsDisp *iface, UINT *pctinfo)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI FontEventsDisp_GetTypeInfo(IFontEventsDisp *iface, UINT itinfo, LCID lcid, ITypeInfo **pptinfo)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI FontEventsDisp_GetIDsOfNames(IFontEventsDisp *iface, REFIID riid, LPOLESTR *names, UINT cNames, LCID lcid,
DISPID *dispid)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static int fonteventsdisp_invoke_called;
static BSTR fonteventsdisp_invoke_arg0;
static HRESULT WINAPI FontEventsDisp_Invoke(
IFontEventsDisp __RPC_FAR * iface,
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
/* [out] */ VARIANT __RPC_FAR *pVarResult,
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
/* [out] */ UINT __RPC_FAR *puArgErr)
IFontEventsDisp *iface,
DISPID dispid,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr)
{
static const WCHAR wszBold[] = {'B','o','l','d',0};
ok(wFlags == INVOKE_FUNC, "invoke flags should have been INVOKE_FUNC instead of 0x%x\n", wFlags);
ok(dispIdMember == DISPID_FONT_CHANGED, "dispIdMember should have been DISPID_FONT_CHANGED instead of 0x%x\n", dispIdMember);
ok(pDispParams->cArgs == 1, "pDispParams->cArgs should have been 1 instead of %d\n", pDispParams->cArgs);
ok(V_VT(&pDispParams->rgvarg[0]) == VT_BSTR, "VT of first param should have been VT_BSTR instead of %d\n", V_VT(&pDispParams->rgvarg[0]));
ok(!lstrcmpW(V_BSTR(&pDispParams->rgvarg[0]), wszBold), "String in first param should have been \"Bold\"\n");
VARIANTARG *arg0 = &pDispParams->rgvarg[0];
ok(dispid == DISPID_FONT_CHANGED, "expected DISPID_FONT_CHANGED instead of 0x%x\n", dispid);
ok(IsEqualGUID(riid, &GUID_NULL), "got riid %s\n", wine_dbgstr_guid(riid));
ok(wFlags == INVOKE_FUNC, "expected INVOKE_FUNC instead of 0x%x\n", wFlags);
ok(pDispParams->cArgs == 1, "expected arg count 1, got %d\n", pDispParams->cArgs);
ok(V_VT(arg0) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(arg0));
fonteventsdisp_invoke_arg0 = SysAllocString(V_BSTR(arg0));
fonteventsdisp_invoke_called++;
return S_OK;
}
@@ -293,16 +344,43 @@ static IFontEventsDispVtbl FontEventsDisp_Vtbl =
FontEventsDisp_QueryInterface,
FontEventsDisp_AddRef,
FontEventsDisp_Release,
NULL,
NULL,
NULL,
FontEventsDisp_GetTypeInfoCount,
FontEventsDisp_GetTypeInfo,
FontEventsDisp_GetIDsOfNames,
FontEventsDisp_Invoke
};
static IFontEventsDisp FontEventsDisp = { &FontEventsDisp_Vtbl };
struct font_dispid
{
DISPID dispid;
const WCHAR *name;
};
static void test_font_events_disp(void)
{
static const WCHAR nameW[] = {'N','a','m','e',0};
static const WCHAR sizeW[] = {'S','i','z','e',0};
static const WCHAR boldW[] = {'B','o','l','d',0};
static const WCHAR italicW[] = {'I','t','a','l','i','c',0};
static const WCHAR underlineW[] = {'U','n','d','e','r','l','i','n','e',0};
static const WCHAR strikeW[] = {'S','t','r','i','k','e','t','h','r','o','u','g','h',0};
static const WCHAR weightW[] = {'W','e','i','g','h','t',0};
static const WCHAR charsetW[] = {'C','h','a','r','s','e','t',0};
static const struct font_dispid font_dispids[] =
{
{ DISPID_FONT_NAME, nameW },
{ DISPID_FONT_SIZE, sizeW },
{ DISPID_FONT_BOLD, boldW },
{ DISPID_FONT_ITALIC, italicW },
{ DISPID_FONT_UNDER, underlineW },
{ DISPID_FONT_STRIKE, strikeW },
{ DISPID_FONT_WEIGHT, weightW },
{ DISPID_FONT_CHARSET, charsetW }
};
IFont *pFont;
IFont *pFont2;
IConnectionPointContainer *pCPC;
@@ -313,6 +391,7 @@ static void test_font_events_disp(void)
IFontDisp *pFontDisp;
DISPPARAMS dispparams;
VARIANTARG vararg;
INT i;
fontdesc.cbSizeofstruct = sizeof(fontdesc);
fontdesc.lpstrName = MSSansSerif_font;
@@ -337,6 +416,7 @@ static void test_font_events_disp(void)
EXPECT_HR(hr, S_OK);
IConnectionPoint_Release(pCP);
fonteventsdisp_invoke_called = 0;
hr = IFont_put_Bold(pFont, TRUE);
EXPECT_HR(hr, S_OK);
@@ -345,30 +425,73 @@ static void test_font_events_disp(void)
hr = IFont_QueryInterface(pFont, &IID_IFontDisp, (void **)&pFontDisp);
EXPECT_HR(hr, S_OK);
V_VT(&vararg) = VT_BOOL;
V_BOOL(&vararg) = VARIANT_FALSE;
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
hr = IFontDisp_Invoke(pFontDisp, DISPID_FONT_BOLD, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
EXPECT_HR(hr, S_OK);
for (i = 0; i < sizeof(font_dispids)/sizeof(font_dispids[0]); i++)
{
switch (font_dispids[i].dispid)
{
case DISPID_FONT_NAME:
{
static const WCHAR arialW[] = {'A','r','i','a','l',0};
V_VT(&vararg) = VT_BSTR;
V_BSTR(&vararg) = SysAllocString(arialW);
break;
}
case DISPID_FONT_SIZE:
V_VT(&vararg) = VT_CY;
S(V_CY(&vararg)).Lo = 25;
S(V_CY(&vararg)).Hi = 0;
break;
case DISPID_FONT_BOLD:
V_VT(&vararg) = VT_BOOL;
V_BOOL(&vararg) = VARIANT_FALSE;
break;
case DISPID_FONT_ITALIC:
case DISPID_FONT_UNDER:
case DISPID_FONT_STRIKE:
V_VT(&vararg) = VT_BOOL;
V_BOOL(&vararg) = VARIANT_TRUE;
break;
case DISPID_FONT_WEIGHT:
V_VT(&vararg) = VT_I2;
V_I2(&vararg) = FW_BLACK;
break;
case DISPID_FONT_CHARSET:
V_VT(&vararg) = VT_I2;
V_I2(&vararg) = 1;
break;
default:
;
}
dispparams.cNamedArgs = 0;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cArgs = 1;
dispparams.rgvarg = &vararg;
fonteventsdisp_invoke_called = 0;
hr = IFontDisp_Invoke(pFontDisp, font_dispids[i].dispid, &IID_NULL, 0, DISPATCH_PROPERTYPUT, &dispparams, NULL, NULL, NULL);
ok(hr == S_OK, "dispid=%d, got 0x%08x\n", font_dispids[i].dispid, hr);
ok(fonteventsdisp_invoke_called == 1, "dispid=%d, DISPID_FONT_CHANGED not called, got %d\n", font_dispids[i].dispid,
fonteventsdisp_invoke_called);
if (hr == S_OK)
{
ok(!lstrcmpW(font_dispids[i].name, fonteventsdisp_invoke_arg0), "dispid=%d, got %s, expected %s\n",
font_dispids[i].dispid, wine_dbgstr_w(fonteventsdisp_invoke_arg0), wine_dbgstr_w(font_dispids[i].name));
SysFreeString(fonteventsdisp_invoke_arg0);
}
VariantClear(&vararg);
}
IFontDisp_Release(pFontDisp);
ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
fonteventsdisp_invoke_called);
hr = IFont_Clone(pFont, &pFont2);
EXPECT_HR(hr, S_OK);
IFont_Release(pFont);
/* this test shows that the notification routine isn't called again */
fonteventsdisp_invoke_called = 0;
hr = IFont_put_Bold(pFont2, FALSE);
EXPECT_HR(hr, S_OK);
/* this test shows that the notification routine isn't called again */
ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
fonteventsdisp_invoke_called);
ok(fonteventsdisp_invoke_called == 0, "got %d\n", fonteventsdisp_invoke_called);
IFont_Release(pFont2);
}
@@ -544,9 +667,9 @@ static void test_IsEqual(void)
S(fd.cySize).Hi = 100;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
fd.fItalic = FALSE;
fd.fUnderline = FALSE;
fd.fStrikethrough = FALSE;
/* Create font */
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt);
@@ -609,30 +732,30 @@ static void test_IsEqual(void)
IFont_Release(ifnt2);
/* Test italic setting */
fd.fItalic = 1;
fd.fItalic = TRUE;
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Italic) Expected S_FALSE but got 0x%08x\n",hres);
fd.fItalic = 0;
fd.fItalic = FALSE;
IFont_Release(ifnt2);
/* Test underline setting */
fd.fUnderline = 1;
fd.fUnderline = TRUE;
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Underline) Expected S_FALSE but got 0x%08x\n",hres);
fd.fUnderline = 0;
fd.fUnderline = FALSE;
IFont_Release(ifnt2);
/* Test strikethrough setting */
fd.fStrikethrough = 1;
fd.fStrikethrough = TRUE;
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt2);
hres = IFont_IsEqual(ifnt,ifnt2);
ok(hres == S_FALSE,
"IFont_IsEqual: (Strikethrough) Expected S_FALSE but got 0x%08x\n",hres);
fd.fStrikethrough = 0;
fd.fStrikethrough = FALSE;
IFont_Release(ifnt2);
/* Free IFont. */
@@ -657,9 +780,9 @@ static void test_ReleaseHfont(void)
S(fd.cySize).Hi = 100;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
fd.fItalic = FALSE;
fd.fUnderline = FALSE;
fd.fStrikethrough = FALSE;
/* Create HFONTs and IFONTs */
pOleCreateFontIndirect(&fd, &IID_IFont, &pvObj1);
@@ -727,9 +850,9 @@ static void test_AddRefHfont(void)
S(fd.cySize).Hi = 100;
fd.sWeight = 0;
fd.sCharset = 0;
fd.fItalic = 0;
fd.fUnderline = 0;
fd.fStrikethrough = 0;
fd.fItalic = FALSE;
fd.fUnderline = FALSE;
fd.fStrikethrough = FALSE;
/* Create HFONTs and IFONTs */
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt1);
@@ -818,7 +941,7 @@ static void test_AddRefHfont(void)
IFont_Release(ifnt2);
/* Need to make a new IFONT for testing */
fd.fUnderline = 1;
fd.fUnderline = TRUE;
pOleCreateFontIndirect(&fd, &IID_IFont, (void **)&ifnt3);
IFont_get_hFont(ifnt3,&hfnt3);
+160 -23
View File
@@ -224,7 +224,7 @@ test_pic_with_stream(LPSTREAM stream, unsigned int imgsize)
if (handle)
{
BITMAP bmp;
GetObject(UlongToHandle(handle), sizeof(BITMAP), &bmp);
GetObjectA(UlongToHandle(handle), sizeof(BITMAP), &bmp);
todo_wine ok(bmp.bmBits != 0, "not a dib\n");
}
@@ -416,12 +416,14 @@ static void test_Invoke(void)
{
IPictureDisp *picdisp;
HRESULT hr;
VARIANTARG vararg;
VARIANTARG vararg, args[10];
DISPPARAMS dispparams;
VARIANT varresult;
IStream *stream;
HGLOBAL hglob;
void *data;
HDC hdc;
int i;
hglob = GlobalAlloc (0, sizeof(gifimage));
data = GlobalLock(hglob);
@@ -481,6 +483,44 @@ static void test_Invoke(void)
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_HPAL, &IID_NULL, 0, DISPATCH_PROPERTYGET, &dispparams, &varresult, NULL, NULL);
ok(hr == DISP_E_BADPARAMCOUNT, "IPictureDisp_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
/* DISPID_PICT_RENDER */
hdc = GetDC(0);
for (i = 0; i < sizeof(args)/sizeof(args[0]); i++)
V_VT(&args[i]) = VT_I4;
V_I4(&args[0]) = 0;
V_I4(&args[1]) = 10;
V_I4(&args[2]) = 10;
V_I4(&args[3]) = 0;
V_I4(&args[4]) = 0;
V_I4(&args[5]) = 10;
V_I4(&args[6]) = 10;
V_I4(&args[7]) = 0;
V_I4(&args[8]) = 0;
V_I4(&args[9]) = HandleToLong(hdc);
dispparams.rgvarg = args;
dispparams.rgdispidNamedArgs = NULL;
dispparams.cArgs = 10;
dispparams.cNamedArgs = 0;
V_VT(&varresult) = VT_EMPTY;
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* Try with one argument set to VT_I2, it'd still work if coerced. */
V_VT(&args[3]) = VT_I2;
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
ok(hr == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hr);
V_VT(&args[3]) = VT_I4;
/* Wrong argument count */
dispparams.cArgs = 9;
hr = IPictureDisp_Invoke(picdisp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD, &dispparams, &varresult, NULL, NULL);
ok(hr == DISP_E_BADPARAMCOUNT, "got 0x%08x\n", hr);
ReleaseDC(NULL, hdc);
IPictureDisp_Release(picdisp);
}
@@ -616,6 +656,55 @@ static void test_enhmetafile(void)
IStream_Release(stream);
}
static HRESULT picture_render(IPicture *iface, HDC hdc, LONG x, LONG y, LONG cx, LONG cy,
OLE_XPOS_HIMETRIC xSrc,
OLE_YPOS_HIMETRIC ySrc,
OLE_XSIZE_HIMETRIC cxSrc,
OLE_YSIZE_HIMETRIC cySrc,
const RECT *bounds)
{
VARIANT ret, args[10];
HRESULT hr, hr_disp;
DISPPARAMS params;
IDispatch *disp;
int i;
hr = IPicture_Render(iface, hdc, x, y, cx, cy, xSrc, ySrc, cxSrc, cySrc, bounds);
IPicture_QueryInterface(iface, &IID_IDispatch, (void**)&disp);
/* This is broken on 64 bits - accepted pointer argument type is still VT_I4 */
for (i = 0; i < sizeof(args)/sizeof(args[0]); i++)
V_VT(&args[i]) = VT_I4;
/* pack arguments and call */
V_INT_PTR(&args[0]) = (INT_PTR)bounds;
V_I4(&args[1]) = cySrc;
V_I4(&args[2]) = cxSrc;
V_I4(&args[3]) = ySrc;
V_I4(&args[4]) = xSrc;
V_I4(&args[5]) = cy;
V_I4(&args[6]) = cx;
V_I4(&args[7]) = y;
V_I4(&args[8]) = x;
V_I4(&args[9]) = HandleToLong(hdc);
params.rgvarg = args;
params.rgdispidNamedArgs = NULL;
params.cArgs = 10;
params.cNamedArgs = 0;
V_VT(&ret) = VT_EMPTY;
hr_disp = IDispatch_Invoke(disp, DISPID_PICT_RENDER, &GUID_NULL, 0, DISPATCH_METHOD,
&params, &ret, NULL, NULL);
ok(hr == hr_disp, "DISPID_PICT_RENDER returned wrong code, 0x%08x, expected 0x%08x\n",
hr_disp, hr);
IDispatch_Release(disp);
return hr;
}
static void test_Render(void)
{
IPicture *pic;
@@ -633,28 +722,28 @@ static void test_Render(void)
ok(hres == S_OK, "IPicture_get_Type does not return S_OK, but 0x%08x\n", hres);
ok(type == PICTYPE_UNINITIALIZED, "Expected type = PICTYPE_UNINITIALIZED, got = %d\n", type);
/* zero dimensions */
hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
/* nonzero dimensions, PICTYPE_UNINITIALIZED */
hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 10, NULL);
ole_expect(hres, S_OK);
IPicture_Release(pic);
desc.cbSizeofstruct = sizeof(PICTDESC);
desc.picType = PICTYPE_ICON;
desc.u.icon.hicon = LoadIcon(NULL, IDI_APPLICATION);
desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
if(!desc.u.icon.hicon){
win_skip("LoadIcon failed. Skipping...\n");
ReleaseDC(NULL, hdc);
@@ -663,19 +752,19 @@ static void test_Render(void)
OleCreatePictureIndirect(&desc, &IID_IPicture, TRUE, (VOID**)&pic);
/* zero dimensions, PICTYPE_ICON */
hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 10, 0, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 10, 0, 0, 0, 0, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 0, 10, 0, 0, 10, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 10, 0, 0, 0, 10, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
hres = IPicture_Render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
hres = picture_render(pic, hdc, 0, 0, 0, 0, 0, 0, 10, 10, NULL);
ole_expect(hres, CTL_E_INVALIDPROPERTYVALUE);
/* Check if target size and position is respected */
@@ -687,7 +776,7 @@ static void test_Render(void)
SetPixelV(hdc, 10, 10, 0x00223344);
expected = GetPixel(hdc, 0, 0);
hres = IPicture_Render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
hres = picture_render(pic, hdc, 1, 1, 9, 9, 0, 0, pWidth, -pHeight, NULL);
ole_expect(hres, S_OK);
if(hres != S_OK) {
@@ -1034,7 +1123,7 @@ static void test_load_save_icon(void)
desc.cbSizeofstruct = sizeof(desc);
desc.picType = PICTYPE_ICON;
desc.u.icon.hicon = LoadIcon(0, IDI_APPLICATION);
desc.u.icon.hicon = LoadIconA(NULL, (LPCSTR)IDI_APPLICATION);
hr = OleCreatePictureIndirect(&desc, &IID_IPicture, FALSE, (void**)&pic);
ok(hr == S_OK, "OleCreatePictureIndirect error %#x\n", hr);
@@ -1082,7 +1171,8 @@ static void test_load_save_empty_picture(void)
HGLOBAL hmem;
DWORD *mem;
IPersistStream *src_stream;
IStream *dst_stream;
IStream *dst_stream, *stream;
LARGE_INTEGER offset;
HRESULT hr;
memset(&pic, 0, sizeof(pic));
@@ -1117,10 +1207,57 @@ static void test_load_save_empty_picture(void)
GlobalUnlock(hmem);
IPersistStream_Release(src_stream);
IPicture_Release(pic);
/* first with statable and seekable stream */
offset.QuadPart = 0;
hr = IStream_Seek(dst_stream, offset, SEEK_SET, NULL);
ok(hr == S_OK, "IStream_Seek %#x\n", hr);
pic = NULL;
hr = pOleLoadPicture(dst_stream, 0, FALSE, &IID_IPicture, (void **)&pic);
ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
ok(pic != NULL,"picture should not be not NULL\n");
if (pic != NULL)
{
type = -1;
hr = IPicture_get_Type(pic, &type);
ok(hr == S_OK,"get_Type error %#8x\n", hr);
ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
handle = (OLE_HANDLE)0xdeadbeef;
hr = IPicture_get_Handle(pic, &handle);
ok(hr == S_OK,"get_Handle error %#8x\n", hr);
ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
IPicture_Release(pic);
}
IStream_Release(dst_stream);
GlobalFree(hmem);
IPicture_Release(pic);
/* again with non-statable and non-seekable stream */
stream = NoStatStream_Construct(hmem);
ok(stream != NULL, "failed to create empty image stream\n");
pic = NULL;
hr = pOleLoadPicture(stream, 0, FALSE, &IID_IPicture, (void **)&pic);
ok(hr == S_OK, "OleLoadPicture error %#x\n", hr);
ok(pic != NULL,"picture should not be not NULL\n");
if (pic != NULL)
{
type = -1;
hr = IPicture_get_Type(pic, &type);
ok(hr == S_OK,"get_Type error %#8x\n", hr);
ok(type == PICTYPE_NONE,"expected picture type PICTYPE_NONE, got %d\n", type);
handle = (OLE_HANDLE)0xdeadbeef;
hr = IPicture_get_Handle(pic, &handle);
ok(hr == S_OK,"get_Handle error %#8x\n", hr);
ok(!handle, "get_Handle returned wrong handle %#x\n", handle);
IPicture_Release(pic);
}
/* Non-statable impl always deletes on release */
IStream_Release(stream);
}
START_TEST(olepicture)
+344 -69
View File
@@ -43,6 +43,10 @@
//#include "wtypes.h"
#include <oleauto.h>
#ifndef FADF_CREATEVECTOR
const USHORT FADF_CREATEVECTOR = 0x2000;
#endif
static HMODULE hOleaut32;
static HRESULT (WINAPI *pSafeArrayAllocDescriptorEx)(VARTYPE,UINT,SAFEARRAY**);
@@ -61,6 +65,14 @@ static BOOL has_i8;
/* Has INT_PTR/UINT_PTR type? */
static BOOL has_int_ptr;
static const USHORT ignored_copy_features[] =
{
FADF_AUTO,
FADF_STATIC,
FADF_EMBEDDED,
FADF_FIXEDSIZE
};
#define START_REF_COUNT 1
#define RECORD_SIZE 64
#define RECORD_SIZE_FAIL 17
@@ -71,36 +83,38 @@ typedef struct IRecordInfoImpl
{
IRecordInfo IRecordInfo_iface;
LONG ref;
DWORD sizeCalled;
DWORD clearCalled;
unsigned int sizeCalled;
unsigned int clearCalled;
unsigned int recordcopy;
} IRecordInfoImpl;
static const IRecordInfoVtbl IRecordInfoImpl_VTable;
static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface)
{
return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
}
static IRecordInfoImpl *IRecordInfoImpl_Construct(void)
static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj)
{
IRecordInfoImpl *rec;
*obj = NULL;
rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
rec->IRecordInfo_iface.lpVtbl = &IRecordInfoImpl_VTable;
rec->ref = START_REF_COUNT;
rec->clearCalled = 0;
rec->sizeCalled = 0;
return rec;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IRecordInfo))
{
*obj = iface;
IRecordInfo_AddRef(iface);
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG CALLBACK IRecordInfoImpl_AddRef(IRecordInfo *iface)
static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG CALLBACK IRecordInfoImpl_Release(IRecordInfo *iface)
static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
ULONG ref = InterlockedDecrement(&This->ref);
@@ -111,16 +125,41 @@ static ULONG CALLBACK IRecordInfoImpl_Release(IRecordInfo *iface)
return ref;
}
static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static BOOL fail_GetSize; /* Whether to fail the GetSize call */
static HRESULT CALLBACK IRecordInfoImpl_RecordClear(IRecordInfo *iface, PVOID pvExisting)
static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, PVOID pvExisting)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
This->clearCalled++;
return S_OK;
}
static HRESULT CALLBACK IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG* size)
static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, PVOID pvExisting, PVOID pvNew)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
This->recordcopy++;
return S_OK;
}
static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
This->sizeCalled++;
@@ -133,37 +172,107 @@ static HRESULT CALLBACK IRecordInfoImpl_GetSize(IRecordInfo *iface, ULONG* size)
return S_OK;
}
static HRESULT CALLBACK IRecordInfoImpl_Dummy(IRecordInfo *iface)
static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
{
trace("Called an unexpected IRecordInfo method - please report!\n");
/* Quit because we'll just crash anyway */
fflush(NULL);
exit(255);
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static const IRecordInfoVtbl IRecordInfoImpl_VTable =
static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData,
LPCOLESTR szFieldName, VARIANT *pvarField)
{
(PVOID)IRecordInfoImpl_Dummy,
IRecordInfoImpl_AddRef,
IRecordInfoImpl_Release,
(PVOID)IRecordInfoImpl_Dummy,
IRecordInfoImpl_RecordClear,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
IRecordInfoImpl_GetSize,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy,
(PVOID)IRecordInfoImpl_Dummy
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
LPCOLESTR szFieldName, VARIANT *pvarField)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
BSTR *rgBstrNames)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface)
{
ok(0, "unexpected call\n");
return NULL;
}
static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
PVOID *ppvDest)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static const IRecordInfoVtbl RecordInfoVtbl =
{
RecordInfo_QueryInterface,
RecordInfo_AddRef,
RecordInfo_Release,
RecordInfo_RecordInit,
RecordInfo_RecordClear,
RecordInfo_RecordCopy,
RecordInfo_GetGuid,
RecordInfo_GetName,
RecordInfo_GetSize,
RecordInfo_GetTypeInfo,
RecordInfo_GetField,
RecordInfo_GetFieldNoCopy,
RecordInfo_PutField,
RecordInfo_PutFieldNoCopy,
RecordInfo_GetFieldNames,
RecordInfo_IsMatchingType,
RecordInfo_RecordCreate,
RecordInfo_RecordCreateCopy,
RecordInfo_RecordDestroy
};
static IRecordInfoImpl *IRecordInfoImpl_Construct(void)
{
IRecordInfoImpl *rec;
rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl;
rec->ref = START_REF_COUNT;
rec->clearCalled = 0;
rec->sizeCalled = 0;
return rec;
}
static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
{
switch (vt)
@@ -957,10 +1066,11 @@ test_LockUnlock_Vector:
static void test_SafeArrayGetPutElement(void)
{
SAFEARRAYBOUND sab[4];
LONG indices[NUM_DIMENSIONS];
LONG indices[NUM_DIMENSIONS], index;
SAFEARRAY *sa;
HRESULT hres;
int value = 0, gotvalue, dimension;
IRecordInfoImpl *irec;
unsigned int x,y,z,a;
for (dimension = 0; dimension < NUM_DIMENSIONS; dimension++)
@@ -974,8 +1084,6 @@ static void test_SafeArrayGetPutElement(void)
return; /* Some early versions can't handle > 3 dims */
ok(sa->cbElements == sizeof(value), "int size mismatch\n");
if (sa->cbElements != sizeof(value))
return;
/* Failure cases */
for (x = 0; x < NUM_DIMENSIONS; x++)
@@ -1079,6 +1187,34 @@ static void test_SafeArrayGetPutElement(void)
}
hres = SafeArrayDestroy(sa);
ok(hres == S_OK, "got 0x%08x\n", hres);
/* VT_RECORD array */
irec = IRecordInfoImpl_Construct();
irec->ref = 1;
sab[0].lLbound = 0;
sab[0].cElements = 8;
sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &irec->IRecordInfo_iface);
ok(sa != NULL, "failed to create array\n");
ok(irec->ref == 2, "got %d\n", irec->ref);
index = 0;
irec->recordcopy = 0;
hres = SafeArrayPutElement(sa, &index, (void*)0xdeadbeef);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
index = 0;
irec->recordcopy = 0;
hres = SafeArrayGetElement(sa, &index, (void*)0xdeadbeef);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(irec->recordcopy == 1, "got %d\n", irec->recordcopy);
hres = SafeArrayDestroy(sa);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(irec->ref == 1, "got %d\n", irec->ref);
IRecordInfo_Release(&irec->IRecordInfo_iface);
}
static void test_SafeArrayGetPutElement_BSTR(void)
@@ -1099,8 +1235,6 @@ static void test_SafeArrayGetPutElement_BSTR(void)
return;
ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
if (sa->cbElements != sizeof(BSTR))
return;
indices[0] = sab.lLbound;
value = SysAllocString(szTest);
@@ -1163,8 +1297,6 @@ static void test_SafeArrayGetPutElement_IUnknown(void)
return;
ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
if (sa->cbElements != sizeof(LPUNKNOWN))
return;
indices[0] = sab.lLbound;
xtunk.ref = 1;
@@ -1197,8 +1329,6 @@ static void test_SafeArrayRedim_IUnknown(void)
return;
ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
if (sa->cbElements != sizeof(LPUNKNOWN))
return;
indices[0] = 2;
xtunk.ref = 1;
@@ -1229,8 +1359,6 @@ static void test_SafeArrayGetPutElement_VARIANT(void)
return;
ok(sa->cbElements == sizeof(VARIANT), "VARIANT size mismatch\n");
if (sa->cbElements != sizeof(VARIANT))
return;
indices[0] = sab.lLbound;
V_VT(&value) = VT_I4;
@@ -1254,14 +1382,13 @@ static void test_SafeArrayGetPutElement_VARIANT(void)
ok(hres == S_OK, "got 0x%08x\n", hres);
}
static void test_SafeArrayCopyData(void)
{
SAFEARRAYBOUND sab[4];
SAFEARRAY *sa;
SAFEARRAY *sacopy;
HRESULT hres;
int dimension,size=1;
int dimension, size = 1, i;
if (!pSafeArrayCopyData)
{
@@ -1285,8 +1412,6 @@ static void test_SafeArrayCopyData(void)
return;
ok(sa->cbElements == sizeof(int), "int size mismatch\n");
if (sa->cbElements != sizeof(int))
return;
/* Fill the source array with some data; it doesn't matter what */
for (dimension = 0; dimension < size; dimension++)
@@ -1334,17 +1459,58 @@ static void test_SafeArrayCopyData(void)
hres = SafeArrayCopy(sa, &sacopy);
ok(hres == S_OK, "copy failed hres 0x%x\n", hres);
if (hres == S_OK)
ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
hres = SafeArrayDestroy(sacopy);
ok(hres == S_OK, "got 0x%08x\n", hres);
sacopy = SafeArrayCreate(VT_INT, NUM_DIMENSIONS, sab);
ok(sacopy != NULL, "Copy test couldn't create copy array\n");
ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
for (i = 0; i < sizeof(ignored_copy_features)/sizeof(USHORT); i++)
{
ok(SafeArrayGetElemsize(sa) == SafeArrayGetElemsize(sacopy),"elemsize wrong\n");
ok(SafeArrayGetDim(sa) == SafeArrayGetDim(sacopy),"dimensions wrong\n");
ok(!memcmp(sa->pvData, sacopy->pvData, size * sizeof(int)), "compared different\n");
hres = SafeArrayDestroy(sacopy);
ok(hres == S_OK, "got 0x%08x\n", hres);
USHORT feature = ignored_copy_features[i];
USHORT orig = sacopy->fFeatures;
sa->fFeatures |= feature;
hres = SafeArrayCopyData(sa, sacopy);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(sacopy->fFeatures == orig && orig == FADF_HAVEVARTYPE, "got features 0x%04x\n", sacopy->fFeatures);
sa->fFeatures &= ~feature;
}
hres = SafeArrayDestroy(sacopy);
ok(hres == S_OK, "got 0x%08x\n", hres);
hres = SafeArrayDestroy(sa);
ok(hres == S_OK, "got 0x%08x\n", hres);
/* copy data from a vector */
sa = SafeArrayCreateVector(VT_UI1, 0, 2);
sacopy = SafeArrayCreateVector(VT_UI1, 0, 2);
ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
"got 0x%08x\n", sa->fFeatures);
ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
"got 0x%08x\n", sacopy->fFeatures);
hres = SafeArrayCopyData(sa, sacopy);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(sacopy->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
broken(sacopy->fFeatures == FADF_CREATEVECTOR /* W2k */),
"got 0x%04x\n", sacopy->fFeatures);
SafeArrayDestroy(sacopy);
sacopy = SafeArrayCreate(VT_UI1, NUM_DIMENSIONS, sab);
ok(sacopy != NULL, "Copy test couldn't create copy array\n");
ok(sacopy->fFeatures == FADF_HAVEVARTYPE, "0x%04x\n", sacopy->fFeatures);
hres = SafeArrayCopyData(sa, sacopy);
ok(hres == E_INVALIDARG, "got 0x%08x\n", hres);
SafeArrayDestroy(sacopy);
SafeArrayDestroy(sa);
}
static void test_SafeArrayCreateEx(void)
@@ -1447,7 +1613,7 @@ static void test_SafeArrayCreateEx(void)
/* Win32 doesn't care if GetSize fails */
fail_GetSize = TRUE;
sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, iRec);
sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
ok(sa != NULL, "CreateEx (Fail Size) failed\n");
ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
@@ -1466,7 +1632,7 @@ static void test_SafeArrayCreateEx(void)
iRec->ref = START_REF_COUNT;
iRec->sizeCalled = 0;
iRec->clearCalled = 0;
sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, iRec);
sa = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
ok(sa != NULL, "CreateEx (Rec) failed\n");
ok(iRec->ref == START_REF_COUNT + 1, "Wrong iRec refcount %d\n", iRec->ref);
ok(iRec->sizeCalled == 1, "GetSize called %d times\n", iRec->sizeCalled);
@@ -1474,19 +1640,34 @@ static void test_SafeArrayCreateEx(void)
if (sa && pSafeArrayGetRecordInfo)
{
IRecordInfo* saRec = NULL;
hres = pSafeArrayGetRecordInfo(sa, &saRec);
SAFEARRAY *sacopy;
hres = pSafeArrayGetRecordInfo(sa, &saRec);
ok(hres == S_OK,"GRI failed\n");
ok(saRec == &iRec->IRecordInfo_iface, "Different saRec\n");
ok(iRec->ref == START_REF_COUNT + 2, "Didn't AddRef %d\n", iRec->ref);
if (iRec->ref == START_REF_COUNT + 2)
IRecordInfo_Release(saRec);
IRecordInfo_Release(saRec);
ok(sa->cbElements == RECORD_SIZE,"Elemsize is %d\n", sa->cbElements);
/* try to copy record based arrays */
sacopy = pSafeArrayCreateEx(VT_RECORD, 1, sab, &iRec->IRecordInfo_iface);
iRec->recordcopy = 0;
iRec->clearCalled = 0;
/* array copy code doesn't explicitely clear a record */
hres = SafeArrayCopyData(sa, sacopy);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(iRec->recordcopy == sab[0].cElements, "got %d\n", iRec->recordcopy);
ok(iRec->clearCalled == 0, "got %d\n", iRec->clearCalled);
hres = SafeArrayDestroy(sacopy);
ok(hres == S_OK, "got 0x%08x\n", hres);
iRec->clearCalled = 0;
iRec->sizeCalled = 0;
hres = SafeArrayDestroy(sa);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(iRec->sizeCalled == 1, "Destroy->GetSize called %d times\n", iRec->sizeCalled);
ok(iRec->sizeCalled == 0, "Destroy->GetSize called %d times\n", iRec->sizeCalled);
ok(iRec->clearCalled == sab[0].cElements, "Destroy->Clear called %d times\n", iRec->clearCalled);
ok(iRec->ref == START_REF_COUNT, "Wrong iRec refcount %d\n", iRec->ref);
}
@@ -1545,6 +1726,7 @@ static void test_SafeArrayCopy(void)
SAFEARRAY *sa, *sa2;
VARIANTARG vSrc, vDst;
HRESULT hres;
int i;
sab.lLbound = 0;
sab.cElements = 10;
@@ -1609,6 +1791,41 @@ static void test_SafeArrayCopy(void)
ok(hres == S_OK, "got 0x%08x\n", hres);
hres = SafeArrayDestroy(sa);
ok(hres == S_OK, "got 0x%08x\n", hres);
/* test feature copy */
hres = SafeArrayAllocDescriptor(1, &sa);
ok(hres == S_OK, "SafeArrayAllocDescriptor failed with error 0x%08x\n", hres);
ok(sa->fFeatures == 0, "got src features 0x%04x\n", sa->fFeatures);
sa->cbElements = 16;
for (i = 0; i < sizeof(ignored_copy_features)/sizeof(USHORT); i++)
{
USHORT feature = ignored_copy_features[i];
sa->fFeatures |= feature;
hres = SafeArrayCopy(sa, &sa2);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(sa2->fFeatures == 0, "got features 0x%04x\n", sa2->fFeatures);
hres = SafeArrayDestroy(sa2);
ok(hres == S_OK, "got 0x%08x\n", hres);
sa->fFeatures &= ~feature;
}
SafeArrayDestroy(sa);
/* copy from a vector */
sa = SafeArrayCreateVector(VT_UI1, 0, 2);
ok(sa->fFeatures == (FADF_HAVEVARTYPE|FADF_CREATEVECTOR) ||
broken(sa->fFeatures == FADF_CREATEVECTOR /* W2k */),
"got 0x%08x\n", sa->fFeatures);
hres = SafeArrayCopy(sa, &sa2);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(sa2->fFeatures == FADF_HAVEVARTYPE ||
broken(!sa2->fFeatures /* W2k */), "got 0x%04x\n",
sa2->fFeatures);
SafeArrayDestroy(sa2);
SafeArrayDestroy(sa);
}
#define MKARRAY(low,num,typ) sab.lLbound = low; sab.cElements = num; \
@@ -1753,7 +1970,7 @@ static void test_SafeArrayDestroyData (void)
HRESULT hres;
int value = 0xdeadbeef;
LONG index[1];
void HUGEP *temp_pvData;
void *temp_pvData;
sab.lLbound = 0;
sab.cElements = 10;
@@ -1784,6 +2001,63 @@ static void test_SafeArrayDestroyData (void)
ok(hres == S_OK, "SAD failed, error code %x.\n", hres);
}
static void test_safearray_layout(void)
{
IRecordInfoImpl *irec;
IRecordInfo *record;
GUID guid, *guidptr;
SAFEARRAYBOUND sab;
SAFEARRAY *sa;
DWORD *dwptr;
HRESULT hr;
sab.lLbound = 0;
sab.cElements = 10;
/* GUID field */
sa = SafeArrayCreate(VT_UNKNOWN, 1, &sab);
ok(sa != NULL, "got %p\n", sa);
guidptr = (GUID*)sa - 1;
ok(IsEqualIID(guidptr, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(guidptr));
hr = SafeArraySetIID(sa, &IID_IDispatch);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(IsEqualIID(guidptr, &IID_IDispatch), "got %s\n", wine_dbgstr_guid(guidptr));
memcpy(guidptr, &IID_IUnknown, sizeof(GUID));
hr = SafeArrayGetIID(sa, &guid);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(IsEqualIID(&guid, &IID_IUnknown), "got %s\n", wine_dbgstr_guid(&guid));
hr = SafeArrayDestroy(sa);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* VARTYPE field */
sa = SafeArrayCreate(VT_UI1, 1, &sab);
ok(sa != NULL, "got %p\n", sa);
dwptr = (DWORD*)sa - 1;
ok(*dwptr == VT_UI1, "got %d\n", *dwptr);
hr = SafeArrayDestroy(sa);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* IRecordInfo pointer */
irec = IRecordInfoImpl_Construct();
irec->ref = 1;
sa = pSafeArrayCreateEx(VT_RECORD, 1, &sab, &irec->IRecordInfo_iface);
ok(sa != NULL, "failed to create array\n");
record = *((IRecordInfo**)sa - 1);
ok(record == &irec->IRecordInfo_iface, "got %p\n", record);
hr = SafeArrayDestroy(sa);
ok(hr == S_OK, "got 0x%08x\n", hr);
IRecordInfo_Release(&irec->IRecordInfo_iface);
}
START_TEST(safearray)
{
hOleaut32 = GetModuleHandleA("oleaut32.dll");
@@ -1816,4 +2090,5 @@ START_TEST(safearray)
test_SafeArrayGetPutElement_IUnknown();
test_SafeArrayRedim_IUnknown();
test_SafeArrayGetPutElement_VARIANT();
test_safearray_layout();
}
+7
View File
@@ -18,6 +18,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma makedep ident
#pragma makedep typelib
import "oaidl.idl"; /* needed by widl */
[
@@ -134,5 +137,9 @@ library register_test
{
[propget, id(DISPID_VALUE)]
LONG test([in] LONG i);
[propputref, id(1)]
LONG testprop([in] LONG *i);
[propputref, id(2)]
LONG testprop2([in] IUnknown *i);
}
}
+12
View File
@@ -18,6 +18,9 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#pragma makedep ident
#pragma makedep typelib
import "oaidl.idl"; /* needed by widl */
[uuid(8b05fe77-4a6c-4133-b9cd-8f81747af784)]
@@ -36,4 +39,13 @@ library Test
{
HRESULT test();
}
[uuid(4029f190-ca4a-4611-aeb9-673983cb96dd)]
struct test_struct
{
HRESULT hr;
VARIANT_BOOL b;
IDispatch *disp;
BSTR bstr;
};
}
+13 -14
View File
@@ -41,7 +41,7 @@
static HRESULT (WINAPI *pVarAdd)(LPVARIANT,LPVARIANT,LPVARIANT);
#define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", (unsigned long int)hr)
#define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
/* ULL suffix is not portable */
#define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
@@ -89,11 +89,11 @@ static DWORD CALLBACK host_object_proc(LPVOID p)
ok_ole_success(hr, CoMarshalInterface);
/* force the message queue to be created before signaling parent thread */
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
SetEvent(data->marshal_event);
while (GetMessage(&msg, NULL, 0, 0))
while (GetMessageA(&msg, NULL, 0, 0))
{
if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
{
@@ -102,7 +102,7 @@ static DWORD CALLBACK host_object_proc(LPVOID p)
SetEvent((HANDLE)msg.lParam);
}
else
DispatchMessage(&msg);
DispatchMessageA(&msg);
}
HeapFree(GetProcessHeap(), 0, data);
@@ -115,7 +115,7 @@ static DWORD CALLBACK host_object_proc(LPVOID p)
static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
{
DWORD tid = 0;
HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
data->stream = stream;
@@ -144,8 +144,8 @@ static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, M
* same thread that marshaled the interface in the first place. */
static void release_host_object(DWORD tid)
{
HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
PostThreadMessageA(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
@@ -153,7 +153,7 @@ static void release_host_object(DWORD tid)
static void end_host_object(DWORD tid, HANDLE thread)
{
BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
/* be careful of races - don't return until hosting thread has terminated */
WaitForSingleObject(thread, INFINITE);
@@ -730,9 +730,8 @@ static BOOL mystruct_uint_ordered(MYSTRUCT *mystruct)
int i;
for (i = 0; i < sizeof(mystruct->uarr)/sizeof(mystruct->uarr[0]); i++)
if (mystruct->uarr[i] != i)
return 0;
return 1;
return FALSE;
return TRUE;
}
static HRESULT WINAPI Widget_StructArgs(
@@ -835,7 +834,7 @@ static HRESULT WINAPI Widget_put_prop_req_arg(
return S_OK;
}
static HRESULT WINAPI Widget_do_restrict(IWidget* iface, INT *i)
static HRESULT WINAPI Widget__restrict(IWidget* iface, INT *i)
{
trace("restrict\n");
*i = DISPID_TM_RESTRICTED;
@@ -885,7 +884,7 @@ static const struct IWidgetVtbl Widget_VTable =
Widget_ByRefUInt,
Widget_put_prop_opt_arg,
Widget_put_prop_req_arg,
Widget_do_restrict,
Widget__restrict,
Widget_neg_restrict
};
@@ -1204,7 +1203,7 @@ static void test_typelibmarshal(void)
{
static const WCHAR szCat[] = { 'C','a','t',0 };
static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
static WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
HRESULT hr;
IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
IWidget *pWidget;
+3
View File
@@ -17,6 +17,9 @@
*
*/
#pragma makedep ident
#pragma makedep typelib
#include "tmarshal_dispids.h"
import "ocidl.idl";
File diff suppressed because it is too large Load Diff
+268 -27
View File
@@ -28,6 +28,7 @@
#include <math.h>
#include <float.h>
#define COBJMACROS
#define CONST_VTABLE
//#include "windef.h"
@@ -100,6 +101,198 @@ static BOOL has_i8;
#define R8_MAX DBL_MAX
#define R8_MIN DBL_MIN
typedef struct IRecordInfoImpl
{
IRecordInfo IRecordInfo_iface;
LONG ref;
unsigned int recordclear;
unsigned int getsize;
unsigned int recordcopy;
struct __tagBRECORD *rec;
} IRecordInfoImpl;
static inline IRecordInfoImpl *impl_from_IRecordInfo(IRecordInfo *iface)
{
return CONTAINING_RECORD(iface, IRecordInfoImpl, IRecordInfo_iface);
}
static HRESULT WINAPI RecordInfo_QueryInterface(IRecordInfo *iface, REFIID riid, void **obj)
{
*obj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IRecordInfo))
{
*obj = iface;
IRecordInfo_AddRef(iface);
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI RecordInfo_AddRef(IRecordInfo *iface)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI RecordInfo_Release(IRecordInfo *iface)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (!ref)
HeapFree(GetProcessHeap(), 0, This);
return ref;
}
static HRESULT WINAPI RecordInfo_RecordInit(IRecordInfo *iface, PVOID pvNew)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_RecordClear(IRecordInfo *iface, void *data)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
This->recordclear++;
This->rec->pvRecord = NULL;
return S_OK;
}
static HRESULT WINAPI RecordInfo_RecordCopy(IRecordInfo *iface, void *src, void *dest)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
This->recordcopy++;
ok(src == (void*)0xdeadbeef, "wrong src pointer %p\n", src);
return S_OK;
}
static HRESULT WINAPI RecordInfo_GetGuid(IRecordInfo *iface, GUID *pguid)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetName(IRecordInfo *iface, BSTR *pbstrName)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetSize(IRecordInfo *iface, ULONG* size)
{
IRecordInfoImpl* This = impl_from_IRecordInfo(iface);
This->getsize++;
*size = 0;
return S_OK;
}
static HRESULT WINAPI RecordInfo_GetTypeInfo(IRecordInfo *iface, ITypeInfo **ppTypeInfo)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetField(IRecordInfo *iface, PVOID pvData,
LPCOLESTR szFieldName, VARIANT *pvarField)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_PutField(IRecordInfo *iface, ULONG wFlags, PVOID pvData,
LPCOLESTR szFieldName, VARIANT *pvarField)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_PutFieldNoCopy(IRecordInfo *iface, ULONG wFlags,
PVOID pvData, LPCOLESTR szFieldName, VARIANT *pvarField)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_GetFieldNames(IRecordInfo *iface, ULONG *pcNames,
BSTR *rgBstrNames)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static BOOL WINAPI RecordInfo_IsMatchingType(IRecordInfo *iface, IRecordInfo *info2)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static PVOID WINAPI RecordInfo_RecordCreate(IRecordInfo *iface)
{
ok(0, "unexpected call\n");
return NULL;
}
static HRESULT WINAPI RecordInfo_RecordCreateCopy(IRecordInfo *iface, PVOID pvSource,
PVOID *ppvDest)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI RecordInfo_RecordDestroy(IRecordInfo *iface, PVOID pvRecord)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static const IRecordInfoVtbl RecordInfoVtbl =
{
RecordInfo_QueryInterface,
RecordInfo_AddRef,
RecordInfo_Release,
RecordInfo_RecordInit,
RecordInfo_RecordClear,
RecordInfo_RecordCopy,
RecordInfo_GetGuid,
RecordInfo_GetName,
RecordInfo_GetSize,
RecordInfo_GetTypeInfo,
RecordInfo_GetField,
RecordInfo_GetFieldNoCopy,
RecordInfo_PutField,
RecordInfo_PutFieldNoCopy,
RecordInfo_GetFieldNames,
RecordInfo_IsMatchingType,
RecordInfo_RecordCreate,
RecordInfo_RecordCreateCopy,
RecordInfo_RecordDestroy
};
static IRecordInfoImpl *get_test_recordinfo(void)
{
IRecordInfoImpl *rec;
rec = HeapAlloc(GetProcessHeap(), 0, sizeof(IRecordInfoImpl));
rec->IRecordInfo_iface.lpVtbl = &RecordInfoVtbl;
rec->ref = 1;
rec->recordclear = 0;
rec->getsize = 0;
rec->recordcopy = 0;
return rec;
}
static void init(void)
{
BSTR bstr;
@@ -120,7 +313,7 @@ static void init(void)
if (bstr) memcpy(&sz12_false[2], bstr, SysStringByteLen(bstr) + sizeof(WCHAR));
SysFreeString(bstr);
hOleaut32 = GetModuleHandle("oleaut32.dll");
hOleaut32 = GetModuleHandleA("oleaut32.dll");
has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
if (!has_i8)
skip("No support for I8 and UI8 data types\n");
@@ -294,7 +487,7 @@ static BOOL is_expected_variant( const VARIANT *result, const VARIANT *expected
return !memcmp( &V_DECIMAL(result), &V_DECIMAL(expected), sizeof(DECIMAL) );
default:
ok(0, "unhandled variant type %s\n",vtstr(V_VT(expected)));
return 0;
return FALSE;
}
}
@@ -353,14 +546,11 @@ static void _test_bstr_var(unsigned line, const VARIANT *v, const char *str)
static void test_VariantInit(void)
{
VARIANTARG v1, v2;
VARIANT v;
/* Test that VariantInit() only sets the type */
memset(&v1, -1, sizeof(v1));
v2 = v1;
V_VT(&v2) = VT_EMPTY;
VariantInit(&v1);
ok(!memcmp(&v1, &v2, sizeof(v1)), "VariantInit() set extra fields\n");
memset(&v, -1, sizeof(v));
VariantInit(&v);
ok(V_VT(&v) == VT_EMPTY, "VariantInit() returned vt %d\n", V_VT(&v));
}
/* All possible combinations of extra V_VT() flags */
@@ -385,9 +575,9 @@ static const VARTYPE ExtraFlags[16] =
};
/* Determine if a vt is valid for VariantClear() */
static int IsValidVariantClearVT(VARTYPE vt, VARTYPE extraFlags)
static BOOL IsValidVariantClearVT(VARTYPE vt, VARTYPE extraFlags)
{
int ret = 0;
BOOL ret = FALSE;
/* Only the following flags/types are valid */
if ((vt <= VT_LPWSTR || vt == VT_RECORD || vt == VT_CLSID) &&
@@ -396,10 +586,10 @@ static int IsValidVariantClearVT(VARTYPE vt, VARTYPE extraFlags)
(!(extraFlags & (VT_BYREF|VT_ARRAY)) || vt > VT_NULL) &&
(extraFlags == 0 || extraFlags == VT_BYREF || extraFlags == VT_ARRAY ||
extraFlags == (VT_ARRAY|VT_BYREF)))
ret = 1; /* ok */
ret = TRUE; /* ok */
if (!has_i8 && (vt == VT_I8 || vt == VT_UI8))
ret = 0; /* Old versions of oleaut32 */
ret = FALSE; /* Old versions of oleaut32 */
return ret;
}
@@ -445,6 +635,8 @@ static test_VariantClearImpl test_myVariantClearImpl = {{&test_VariantClear_vtbl
static void test_VariantClear(void)
{
struct __tagBRECORD *rec;
IRecordInfoImpl *recinfo;
HRESULT hres;
VARIANTARG v;
VARIANT v2;
@@ -563,10 +755,28 @@ static void test_VariantClear(void)
ok(V_DISPATCHREF(&v) == (IDispatch**)&punk, "dispatch ref %p\n", V_DISPATCHREF(&v));
/* Check that nothing got called */
ok(test_myVariantClearImpl.events == 0, "Unexpected call. events %08x\n", test_myVariantClearImpl.events);
/* RECORD */
recinfo = get_test_recordinfo();
V_VT(&v) = VT_RECORD;
rec = &V_UNION(&v, brecVal);
rec->pRecInfo = &recinfo->IRecordInfo_iface;
rec->pvRecord = (void*)0xdeadbeef;
recinfo->recordclear = 0;
recinfo->ref = 2;
recinfo->rec = rec;
hres = VariantClear(&v);
ok(hres == S_OK, "ret %08x\n", hres);
ok(rec->pvRecord == NULL, "got %p\n", rec->pvRecord);
ok(recinfo->recordclear == 1, "got %d\n", recinfo->recordclear);
ok(recinfo->ref == 1, "got %d\n", recinfo->ref);
IRecordInfo_Release(&recinfo->IRecordInfo_iface);
}
static void test_VariantCopy(void)
{
struct __tagBRECORD *rec;
IRecordInfoImpl *recinfo;
VARIANTARG vSrc, vDst;
VARTYPE vt;
size_t i;
@@ -682,18 +892,45 @@ static void test_VariantCopy(void)
}
VariantClear(&vDst);
}
/* copy RECORD */
recinfo = get_test_recordinfo();
memset(&vDst, 0, sizeof(vDst));
V_VT(&vDst) = VT_EMPTY;
V_VT(&vSrc) = VT_RECORD;
rec = &V_UNION(&vSrc, brecVal);
rec->pRecInfo = &recinfo->IRecordInfo_iface;
rec->pvRecord = (void*)0xdeadbeef;
recinfo->recordclear = 0;
recinfo->recordcopy = 0;
recinfo->getsize = 0;
recinfo->rec = rec;
hres = VariantCopy(&vDst, &vSrc);
ok(hres == S_OK, "ret %08x\n", hres);
rec = &V_UNION(&vDst, brecVal);
ok(rec->pvRecord != (void*)0xdeadbeef && rec->pvRecord != NULL, "got %p\n", rec->pvRecord);
ok(rec->pRecInfo == &recinfo->IRecordInfo_iface, "got %p\n", rec->pRecInfo);
ok(recinfo->getsize == 1, "got %d\n", recinfo->recordclear);
ok(recinfo->recordcopy == 1, "got %d\n", recinfo->recordclear);
VariantClear(&vDst);
VariantClear(&vSrc);
}
/* Determine if a vt is valid for VariantCopyInd() */
static int IsValidVariantCopyIndVT(VARTYPE vt, VARTYPE extraFlags)
static BOOL IsValidVariantCopyIndVT(VARTYPE vt, VARTYPE extraFlags)
{
int ret = 0;
BOOL ret = FALSE;
if ((extraFlags & VT_ARRAY) ||
(vt > VT_NULL && vt != (VARTYPE)15 && vt < VT_VOID &&
!(extraFlags & (VT_VECTOR|VT_RESERVED))))
{
ret = 1; /* ok */
ret = TRUE; /* ok */
}
return ret;
}
@@ -1731,6 +1968,10 @@ static void test_SystemTimeToVariantTime(void)
ST2DT(2,1,1980,0,0,0,0,TRUE,29222.0);
ST2DT(0,1,1980,0,0,0,0,TRUE,29220.0); /* Rolls back to 31 Dec 1899 */
ST2DT(1,13,1980,0,0,0,0,FALSE,29587.0); /* Fails on invalid month */
ST2DT(32,1,1980,0,0,0,0,FALSE,0.0); /* Fails on invalid day */
ST2DT(1,1,-1,0,0,0,0,FALSE,0.0); /* Fails on invalid year */
ST2DT(1,1,10000,0,0,0,0,FALSE,0.0); /* Fails on invalid year */
ST2DT(1,1,9999,0,0,0,0,TRUE,2958101.0); /* 9999 is last valid year */
ST2DT(31,12,90,0,0,0,0,TRUE,33238.0); /* 30 <= year < 100 is 1900+year */
ST2DT(1,1,30,0,0,0,0,TRUE,10959.0); /* 30 <= year < 100 is 1900+year */
ST2DT(1,1,29,0,0,0,0,TRUE,47119.0); /* 0 <= year < 30 is 2000+year */
@@ -2879,7 +3120,7 @@ static void test_VarFix(void)
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
{
HRESULT bFail = TRUE;
BOOL bFail = TRUE;
SKIPTESTS(vt);
@@ -2994,7 +3235,7 @@ static void test_VarInt(void)
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
{
HRESULT bFail = TRUE;
BOOL bFail = TRUE;
SKIPTESTS(vt);
@@ -3115,7 +3356,7 @@ static void test_VarNeg(void)
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
{
HRESULT bFail = TRUE;
BOOL bFail = TRUE;
SKIPTESTS(vt);
@@ -5370,7 +5611,7 @@ static void test_VarCat(void)
static const WCHAR sz12_date[] = {'1','2','9','/','3','0','/','1','9','8','0','\0'};
static const WCHAR sz12_date_broken[] = {'1','2','9','/','3','0','/','8','0','\0'};
static const WCHAR sz_empty[] = {'\0'};
TCHAR orig_date_format[128];
CHAR orig_date_format[128];
VARTYPE leftvt, rightvt, resultvt;
HRESULT hres;
HRESULT expected_error_num;
@@ -5379,8 +5620,8 @@ static void test_VarCat(void)
/* Set date format for testing */
lcid = LOCALE_USER_DEFAULT;
GetLocaleInfo(lcid,LOCALE_SSHORTDATE,orig_date_format,128);
SetLocaleInfo(lcid,LOCALE_SSHORTDATE,"M/d/yyyy");
GetLocaleInfoA(lcid,LOCALE_SSHORTDATE,orig_date_format,128);
SetLocaleInfoA(lcid,LOCALE_SSHORTDATE,"M/d/yyyy");
VariantInit(&left);
VariantInit(&right);
@@ -5701,7 +5942,7 @@ static void test_VarCat(void)
"VarCat: EMPTY concat with EMPTY did not return empty VT_BSTR\n");
/* Restore original date format settings */
SetLocaleInfo(lcid,LOCALE_SSHORTDATE,orig_date_format);
SetLocaleInfoA(lcid,LOCALE_SSHORTDATE,orig_date_format);
VariantClear(&left);
VariantClear(&right);
@@ -5763,11 +6004,11 @@ static void test_VarAnd(void)
VARTYPE i;
HRESULT hres;
CHECKPTR(VarAnd);
true_str = SysAllocString(szTrue);
false_str = SysAllocString(szFalse);
CHECKPTR(VarAnd);
/* Test all possible flag/vt combinations & the resulting vt type */
for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
{
@@ -7242,11 +7483,11 @@ static void test_VarDiv(void)
HRESULT hres;
double r;
CHECKPTR(VarDiv);
num1_str = SysAllocString(str1);
num2_str = SysAllocString(str2);
CHECKPTR(VarDiv);
/* Test all possible flag/vt combinations & the resulting vt type */
for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
{
+464 -110
View File
@@ -23,12 +23,18 @@
#define COM_NO_WINDOWS_H
#define CONST_VTABLE
#define COBJMACROS
#include <wine/test.h>
#include <winnls.h>
#include <objbase.h>
#include <oleauto.h>
#include <math.h>
#include <test_tlb.h>
#include <initguid.h>
DEFINE_GUID(UUID_test_struct, 0x4029f190, 0xca4a, 0x4611, 0xae,0xb9,0x67,0x39,0x83,0xcb,0x96,0xdd);
/* Some Visual C++ versions choke on __uint64 to float conversions.
* To fix this you need either VC++ 6.0 plus the processor pack
@@ -251,6 +257,32 @@ static BOOL has_locales;
BADVAR(VT_CLSID); \
BADVAR(VT_BSTR_BLOB)
#define DEFINE_EXPECT(func) \
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
#define SET_EXPECT(func) \
do { called_ ## func = FALSE; expect_ ## func = TRUE; } while(0)
#define CHECK_EXPECT2(func) \
do { \
ok(expect_ ##func, "unexpected call " #func "\n"); \
called_ ## func = TRUE; \
}while(0)
#define CHECK_EXPECT(func) \
do { \
CHECK_EXPECT2(func); \
expect_ ## func = FALSE; \
}while(0)
#define CHECK_CALLED(func) \
do { \
ok(called_ ## func, "expected " #func "\n"); \
expect_ ## func = called_ ## func = FALSE; \
}while(0)
DEFINE_EXPECT(dispatch_invoke);
/* Early versions of oleaut32 are missing many functions */
static HRESULT (WINAPI *pVarI1FromUI1)(BYTE,signed char*);
static HRESULT (WINAPI *pVarI1FromI2)(SHORT,signed char*);
@@ -461,6 +493,7 @@ static HRESULT (WINAPI *pVarDecDiv)(const DECIMAL*,const DECIMAL*,DECIMAL*);
static HRESULT (WINAPI *pVarDecCmp)(const DECIMAL*,const DECIMAL*);
static HRESULT (WINAPI *pVarDecCmpR8)(const DECIMAL*,double);
static HRESULT (WINAPI *pVarDecNeg)(const DECIMAL*,DECIMAL*);
static HRESULT (WINAPI *pVarDecRound)(const DECIMAL*,int,DECIMAL*);
static HRESULT (WINAPI *pVarBoolFromUI1)(BYTE,VARIANT_BOOL*);
static HRESULT (WINAPI *pVarBoolFromI2)(SHORT,VARIANT_BOOL*);
@@ -502,73 +535,93 @@ typedef struct
BOOL bFailInvoke;
} DummyDispatch;
static DummyDispatch dispatch;
static inline DummyDispatch *impl_from_IDispatch(IDispatch *iface)
{
return CONTAINING_RECORD(iface, DummyDispatch, IDispatch_iface);
}
static ULONG WINAPI DummyDispatch_AddRef(LPDISPATCH iface)
static ULONG WINAPI DummyDispatch_AddRef(IDispatch *iface)
{
DummyDispatch *This = impl_from_IDispatch(iface);
trace("AddRef(%p)\n", iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI DummyDispatch_Release(LPDISPATCH iface)
static ULONG WINAPI DummyDispatch_Release(IDispatch *iface)
{
DummyDispatch *This = impl_from_IDispatch(iface);
trace("Release(%p)\n", iface);
return InterlockedDecrement(&This->ref);
}
static HRESULT WINAPI DummyDispatch_QueryInterface(LPDISPATCH iface,
static HRESULT WINAPI DummyDispatch_QueryInterface(IDispatch *iface,
REFIID riid,
void** ppvObject)
{
trace("QueryInterface(%p)\n", iface);
if (ppvObject)
*ppvObject = NULL;
if (IsEqualIID(riid, &IID_IDispatch) ||
IsEqualIID(riid, &IID_IUnknown))
{
*ppvObject = NULL;
if (IsEqualIID(riid, &IID_IDispatch))
{
trace("Asked for IID_IDispatch\n");
*ppvObject = iface;
}
else if (IsEqualIID(riid, &IID_IUnknown))
{
trace("Asked for IID_IUnknown\n");
*ppvObject = iface;
}
if (*ppvObject)
{
DummyDispatch_AddRef(*ppvObject);
return S_OK;
}
IDispatch_AddRef(iface);
}
return E_NOINTERFACE;
return *ppvObject ? S_OK : E_NOINTERFACE;
}
static HRESULT WINAPI DummyDispatch_Invoke(LPDISPATCH iface,
DISPID dispIdMember, REFIID riid,
LCID lcid, WORD wFlags,
DISPPARAMS *pDispParams,
VARIANT *pVarResult,
EXCEPINFO *pExcepInfo,
UINT *puArgErr)
static HRESULT WINAPI DummyDispatch_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
{
trace("Invoke(%p)\n", iface);
ok(wFlags == DISPATCH_PROPERTYGET, "Flags wrong\n");
ok(pDispParams->cArgs == 0, "Property get has args\n");
ok(0, "Unexpected call\n");
return E_NOTIMPL;
}
if (dispatch.bFailInvoke)
static HRESULT WINAPI DummyDispatch_GetTypeInfo(IDispatch *iface, UINT tinfo, LCID lcid, ITypeInfo **ti)
{
ok(0, "Unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DummyDispatch_GetIDsOfNames(IDispatch *iface, REFIID riid, LPOLESTR *names,
UINT cnames, LCID lcid, DISPID *dispid)
{
ok(0, "Unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI DummyDispatch_Invoke(IDispatch *iface,
DISPID dispid, REFIID riid,
LCID lcid, WORD wFlags,
DISPPARAMS *params,
VARIANT *res,
EXCEPINFO *ei,
UINT *arg_err)
{
DummyDispatch *This = impl_from_IDispatch(iface);
CHECK_EXPECT(dispatch_invoke);
ok(dispid == DISPID_VALUE, "got dispid %d\n", dispid);
ok(IsEqualIID(riid, &IID_NULL), "go riid %s\n", wine_dbgstr_guid(riid));
ok(wFlags == DISPATCH_PROPERTYGET, "Flags wrong\n");
ok(params->rgvarg == NULL, "got %p\n", params->rgvarg);
ok(params->rgdispidNamedArgs == NULL, "got %p\n", params->rgdispidNamedArgs);
ok(params->cArgs == 0, "got %d\n", params->cArgs);
ok(params->cNamedArgs == 0, "got %d\n", params->cNamedArgs);
ok(res != NULL, "got %p\n", res);
ok(V_VT(res) == VT_EMPTY, "got %d\n", V_VT(res));
ok(ei == NULL, "got %p\n", ei);
ok(arg_err == NULL, "got %p\n", arg_err);
if (This->bFailInvoke)
return E_OUTOFMEMORY;
memset(pVarResult, 0, sizeof(*pVarResult));
V_VT(pVarResult) = dispatch.vt;
V_VT(res) = This->vt;
if (This->vt == VT_UI1)
V_UI1(res) = 1;
else
memset(res, 0, sizeof(*res));
return S_OK;
}
@@ -577,13 +630,19 @@ static const IDispatchVtbl DummyDispatch_VTable =
DummyDispatch_QueryInterface,
DummyDispatch_AddRef,
DummyDispatch_Release,
NULL,
NULL,
NULL,
DummyDispatch_GetTypeInfoCount,
DummyDispatch_GetTypeInfo,
DummyDispatch_GetIDsOfNames,
DummyDispatch_Invoke
};
static DummyDispatch dispatch = { { &DummyDispatch_VTable }, 1, 0, 0 };
static void init_test_dispatch(LONG ref, VARTYPE vt, DummyDispatch *dispatch)
{
dispatch->IDispatch_iface.lpVtbl = &DummyDispatch_VTable;
dispatch->ref = ref;
dispatch->vt = vt;
dispatch->bFailInvoke = FALSE;
}
/*
* VT_I1/VT_UI1
@@ -685,11 +744,15 @@ static void test_VarI1FromR4(void)
CHECKPTR(VarI1FromR4);
CONVERT(VarI1FromR4, -129.0f); EXPECT_OVERFLOW;
CONVERT(VarI1FromR4, -128.51f); EXPECT_OVERFLOW;
CONVERT(VarI1FromR4, -128.5f); EXPECT(-128);
CONVERT(VarI1FromR4, -128.0f); EXPECT(-128);
CONVERT(VarI1FromR4, -1.0f); EXPECT(-1);
CONVERT(VarI1FromR4, 0.0f); EXPECT(0);
CONVERT(VarI1FromR4, 1.0f); EXPECT(1);
CONVERT(VarI1FromR4, 127.0f); EXPECT(127);
CONVERT(VarI1FromR4, 127.49f); EXPECT(127);
CONVERT(VarI1FromR4, 127.5f); EXPECT_OVERFLOW;
CONVERT(VarI1FromR4, 128.0f); EXPECT_OVERFLOW;
CONVERT(VarI1FromR4, -1.5f); EXPECT(-2);
@@ -708,11 +771,15 @@ static void test_VarI1FromR8(void)
CHECKPTR(VarI1FromR8);
CONVERT(VarI1FromR8, -129.0); EXPECT_OVERFLOW;
CONVERT(VarI1FromR8, -128.51); EXPECT_OVERFLOW;
CONVERT(VarI1FromR8, -128.5); EXPECT(-128);
CONVERT(VarI1FromR8, -128.0); EXPECT(-128);
CONVERT(VarI1FromR8, -1.0); EXPECT(-1);
CONVERT(VarI1FromR8, 0.0); EXPECT(0);
CONVERT(VarI1FromR8, 1.0); EXPECT(1);
CONVERT(VarI1FromR8, 127.0); EXPECT(127);
CONVERT(VarI1FromR8, 127.49); EXPECT(127);
CONVERT(VarI1FromR8, 127.5); EXPECT_OVERFLOW;
CONVERT(VarI1FromR8, 128.0); EXPECT_OVERFLOW;
CONVERT(VarI1FromR8, -1.5); EXPECT(-2);
@@ -929,9 +996,13 @@ static void test_VarUI1FromR4(void)
CHECKPTR(VarUI1FromR4);
CONVERT(VarUI1FromR4, -1.0f); EXPECT_OVERFLOW;
CONVERT(VarUI1FromR4, -0.51f); EXPECT_OVERFLOW;
CONVERT(VarUI1FromR4, -0.5f); EXPECT(0);
CONVERT(VarUI1FromR4, 0.0f); EXPECT(0);
CONVERT(VarUI1FromR4, 1.0f); EXPECT(1);
CONVERT(VarUI1FromR4, 255.0f); EXPECT(255);
CONVERT(VarUI1FromR4, 255.49f); EXPECT(255);
CONVERT(VarUI1FromR4, 255.5f); EXPECT_OVERFLOW;
CONVERT(VarUI1FromR4, 256.0f); EXPECT_OVERFLOW;
/* Rounding */
@@ -951,9 +1022,13 @@ static void test_VarUI1FromR8(void)
CHECKPTR(VarUI1FromR8);
CONVERT(VarUI1FromR8, -1.0); EXPECT_OVERFLOW;
CONVERT(VarUI1FromR8, -0.51); EXPECT_OVERFLOW;
CONVERT(VarUI1FromR8, -0.5); EXPECT(0);
CONVERT(VarUI1FromR8, 0.0); EXPECT(0);
CONVERT(VarUI1FromR8, 1.0); EXPECT(1);
CONVERT(VarUI1FromR8, 255.0); EXPECT(255);
CONVERT(VarUI1FromR8, 255.49); EXPECT(255);
CONVERT(VarUI1FromR8, 255.5); EXPECT_OVERFLOW;
CONVERT(VarUI1FromR8, 256.0); EXPECT_OVERFLOW;
/* Rounding */
@@ -1057,6 +1132,7 @@ static void test_VarUI1FromStr(void)
static void test_VarUI1FromDisp(void)
{
DummyDispatch dispatch;
CONVVARS(LCID);
VARIANTARG vSrc, vDst;
@@ -1079,24 +1155,41 @@ static void test_VarUI1FromDisp(void)
VariantInit(&vSrc);
VariantInit(&vDst);
init_test_dispatch(1, VT_UI1, &dispatch);
V_VT(&vSrc) = VT_DISPATCH;
V_DISPATCH(&vSrc) = &dispatch.IDispatch_iface;
dispatch.vt = VT_UI1;
dispatch.bFailInvoke = FALSE;
SET_EXPECT(dispatch_invoke);
out = 10;
hres = pVarUI1FromDisp(&dispatch.IDispatch_iface, in, &out);
trace("0x%08x\n", hres);
ok(broken(hres == DISP_E_BADVARTYPE) || hres == S_OK, "got 0x%08x\n", hres);
ok(broken(out == 10) || out == 1, "got %d\n", out);
CHECK_CALLED(dispatch_invoke);
SET_EXPECT(dispatch_invoke);
V_VT(&vDst) = VT_EMPTY;
V_UI1(&vDst) = 0;
hres = VariantChangeTypeEx(&vDst, &vSrc, in, 0, VT_UI1);
trace("0x%08x\n", hres);
ok(hres == S_OK, "got 0x%08x\n", hres);
ok(V_VT(&vDst) == VT_UI1, "got %d\n", V_VT(&vDst));
ok(V_UI1(&vDst) == 1, "got %d\n", V_UI1(&vDst));
CHECK_CALLED(dispatch_invoke);
dispatch.bFailInvoke = TRUE;
SET_EXPECT(dispatch_invoke);
out = 10;
hres = pVarUI1FromDisp(&dispatch.IDispatch_iface, in, &out);
trace("0x%08x\n", hres);
ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hres);
ok(out == 10, "got %d\n", out);
CHECK_CALLED(dispatch_invoke);
SET_EXPECT(dispatch_invoke);
V_VT(&vDst) = VT_EMPTY;
hres = VariantChangeTypeEx(&vDst, &vSrc, in, 0, VT_UI1);
trace("0x%08x\n", hres);
ok(hres == DISP_E_TYPEMISMATCH, "got 0x%08x\n", hres);
ok(V_VT(&vDst) == VT_EMPTY, "got %d\n", V_VT(&vDst));
CHECK_CALLED(dispatch_invoke);
}
static void test_VarUI1Copy(void)
@@ -1209,11 +1302,15 @@ static void test_VarI2FromR4(void)
CHECKPTR(VarI2FromR4);
CONVERT(VarI2FromR4, -32769.0f); EXPECT_OVERFLOW;
CONVERT(VarI2FromR4, -32768.51f); EXPECT_OVERFLOW;
CONVERT(VarI2FromR4, -32768.5f); EXPECT(-32768);
CONVERT(VarI2FromR4, -32768.0f); EXPECT(-32768);
CONVERT(VarI2FromR4, -1.0f); EXPECT(-1);
CONVERT(VarI2FromR4, 0.0f); EXPECT(0);
CONVERT(VarI2FromR4, 1.0f); EXPECT(1);
CONVERT(VarI2FromR4, 32767.0f); EXPECT(32767);
CONVERT(VarI2FromR4, 32767.49f); EXPECT(32767);
CONVERT(VarI2FromR4, 32767.5f); EXPECT_OVERFLOW;
CONVERT(VarI2FromR4, 32768.0f); EXPECT_OVERFLOW;
/* Rounding */
@@ -1233,11 +1330,15 @@ static void test_VarI2FromR8(void)
CHECKPTR(VarI2FromR8);
CONVERT(VarI2FromR8, -32769.0); EXPECT_OVERFLOW;
CONVERT(VarI2FromR8, -32768.51); EXPECT_OVERFLOW;
CONVERT(VarI2FromR8, -32768.5); EXPECT(-32768);
CONVERT(VarI2FromR8, -32768.0); EXPECT(-32768);
CONVERT(VarI2FromR8, -1.0); EXPECT(-1);
CONVERT(VarI2FromR8, 0.0); EXPECT(0);
CONVERT(VarI2FromR8, 1.0); EXPECT(1);
CONVERT(VarI2FromR8, 32767.0); EXPECT(32767);
CONVERT(VarI2FromR8, 32767.49); EXPECT(32767);
CONVERT(VarI2FromR8, 32767.5); EXPECT_OVERFLOW;
CONVERT(VarI2FromR8, 32768.0); EXPECT_OVERFLOW;
/* Rounding */
@@ -1457,9 +1558,13 @@ static void test_VarUI2FromR4(void)
CHECKPTR(VarUI2FromR4);
CONVERT(VarUI2FromR4, -1.0f); EXPECT_OVERFLOW;
CONVERT(VarUI2FromR4, -0.51f); EXPECT_OVERFLOW;
CONVERT(VarUI2FromR4, -0.5f); EXPECT(0);
CONVERT(VarUI2FromR4, 0.0f); EXPECT(0);
CONVERT(VarUI2FromR4, 1.0f); EXPECT(1);
CONVERT(VarUI2FromR4, 65535.0f); EXPECT(65535);
CONVERT(VarUI2FromR4, 65535.49f); EXPECT(65535);
CONVERT(VarUI2FromR4, 65535.5f); EXPECT_OVERFLOW;
CONVERT(VarUI2FromR4, 65536.0f); EXPECT_OVERFLOW;
/* Rounding */
@@ -1479,9 +1584,13 @@ static void test_VarUI2FromR8(void)
CHECKPTR(VarUI2FromR8);
CONVERT(VarUI2FromR8, -1.0); EXPECT_OVERFLOW;
CONVERT(VarUI2FromR8, -0.51); EXPECT_OVERFLOW;
CONVERT(VarUI2FromR8, -0.5); EXPECT(0);
CONVERT(VarUI2FromR8, 0.0); EXPECT(0);
CONVERT(VarUI2FromR8, 1.0); EXPECT(1);
CONVERT(VarUI2FromR8, 65535.0); EXPECT(65535);
CONVERT(VarUI2FromR8, 65535.49); EXPECT(65535);
CONVERT(VarUI2FromR8, 65535.5); EXPECT_OVERFLOW;
CONVERT(VarUI2FromR8, 65536.0); EXPECT_OVERFLOW;
/* Rounding */
@@ -1720,11 +1829,15 @@ static void test_VarI4FromR8(void)
CHECKPTR(VarI4FromR8);
CONVERT(VarI4FromR8, -2147483649.0); EXPECT_OVERFLOW;
CONVERT(VarI4FromR8, -2147483648.51); EXPECT_OVERFLOW;
CONVERT(VarI4FromR8, -2147483648.5); EXPECT(-2147483647 - 1);
CONVERT(VarI4FromR8, -2147483648.0); EXPECT(-2147483647 - 1);
CONVERT(VarI4FromR8, -1.0); EXPECT(-1);
CONVERT(VarI4FromR8, 0.0); EXPECT(0);
CONVERT(VarI4FromR8, 1.0); EXPECT(1);
CONVERT(VarI4FromR8, 2147483647.0); EXPECT(2147483647);
CONVERT(VarI4FromR8, 2147483647.49); EXPECT(2147483647);
CONVERT(VarI4FromR8, 2147483647.5); EXPECT_OVERFLOW;
CONVERT(VarI4FromR8, 2147483648.0); EXPECT_OVERFLOW;
CONVERT(VarI4FromR8, -1.5); EXPECT(-2);
@@ -1945,6 +2058,8 @@ static void test_VarUI4FromR4(void)
CHECKPTR(VarUI4FromR4);
/* We can't test max values as they are not exactly representable in a float */
CONVERT(VarUI4FromR4, -1.0f); EXPECT_OVERFLOW;
CONVERT(VarUI4FromR4, -0.51f); EXPECT_OVERFLOW;
CONVERT(VarUI4FromR4, -0.5f); EXPECT(0);
CONVERT(VarUI4FromR4, 0.0f); EXPECT(0);
CONVERT(VarUI4FromR4, 1.0f); EXPECT(1);
@@ -1965,9 +2080,13 @@ static void test_VarUI4FromR8(void)
CHECKPTR(VarUI4FromR8);
CONVERT(VarUI4FromR8, -1.0); EXPECT_OVERFLOW;
CONVERT(VarUI4FromR4, -0.51f); EXPECT_OVERFLOW;
CONVERT(VarUI4FromR4, -0.5f); EXPECT(0);
CONVERT(VarUI4FromR8, 0.0); EXPECT(0);
CONVERT(VarUI4FromR8, 1.0); EXPECT(1);
CONVERT(VarUI4FromR8, 4294967295.0); EXPECT(4294967295ul);
CONVERT(VarUI4FromR8, 4294967295.49); EXPECT(4294967295ul);
CONVERT(VarUI4FromR8, 4294967295.5); EXPECT_OVERFLOW;
CONVERT(VarUI4FromR8, 4294967296.0); EXPECT_OVERFLOW;
CONVERT(VarUI4FromR8, -1.5); EXPECT_OVERFLOW;
@@ -4551,6 +4670,39 @@ static void test_VarDecCmpR8(void)
SETDEC(l,0,DECIMAL_NEG,-1,-1); r = DECIMAL_NEG; MATH3(VarDecCmpR8); EXPECT_LT;
}
#define CLEAR(x) memset(&(x), 0xBB, sizeof(x))
static void test_VarDecRound(void)
{
HRESULT hres;
DECIMAL l, out;
CHECKPTR(VarDecRound);
CLEAR(out); SETDEC(l, 0, 0, 0, 1); hres = pVarDecRound(&l, 3, &out); EXPECTDEC(0, 0, 0, 1);
CLEAR(out); SETDEC(l, 0, 0, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, 0, 0, 1);
CLEAR(out); SETDEC(l, 1, 0, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, 0, 0, 0);
CLEAR(out); SETDEC(l, 1, 0, 0, 1); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 1);
CLEAR(out); SETDEC(l, 2, 0, 0, 11); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 1);
CLEAR(out); SETDEC(l, 2, 0, 0, 15); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 2);
CLEAR(out); SETDEC(l, 6, 0, 0, 550001); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 6);
CLEAR(out); SETDEC(l, 0, DECIMAL_NEG, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, DECIMAL_NEG, 0, 1);
CLEAR(out); SETDEC(l, 1, DECIMAL_NEG, 0, 1); hres = pVarDecRound(&l, 0, &out); EXPECTDEC(0, DECIMAL_NEG, 0, 0);
CLEAR(out); SETDEC(l, 1, DECIMAL_NEG, 0, 1); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 1);
CLEAR(out); SETDEC(l, 2, DECIMAL_NEG, 0, 11); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 1);
CLEAR(out); SETDEC(l, 2, DECIMAL_NEG, 0, 15); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 2);
CLEAR(out); SETDEC(l, 6, DECIMAL_NEG, 0, 550001); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, DECIMAL_NEG, 0, 6);
CLEAR(out); SETDEC64(l, 0, 0, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, 0, 0xffffffff, 0xffffffff, 0xffffffff);
CLEAR(out); SETDEC64(l, 28, 0, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, 0, 0, 0, 8);
CLEAR(out); SETDEC64(l, 0, DECIMAL_NEG, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, DECIMAL_NEG, 0xffffffff, 0xffffffff, 0xffffffff);
CLEAR(out); SETDEC64(l, 28, DECIMAL_NEG, 0xffffffff, 0xffffffff, 0xffffffff); hres = pVarDecRound(&l, 0, &out); EXPECTDEC64(0, DECIMAL_NEG, 0, 0, 8);
CLEAR(out); SETDEC(l, 2, 0, 0, 0); hres = pVarDecRound(&l, 1, &out); EXPECTDEC(1, 0, 0, 0);
}
/*
* VT_BOOL
*/
@@ -5588,8 +5740,11 @@ static void test_IUnknownClear(void)
{
HRESULT hres;
VARIANTARG v;
DummyDispatch u = { { &DummyDispatch_VTable }, 1, VT_UI1, FALSE };
IUnknown* pu = (IUnknown*)&u.IDispatch_iface;
DummyDispatch u;
IUnknown* pu;
init_test_dispatch(1, VT_UI1, &u);
pu = (IUnknown*)&u.IDispatch_iface;
/* Test that IUnknown_Release is called on by-value */
V_VT(&v) = VT_UNKNOWN;
@@ -5613,8 +5768,11 @@ static void test_IUnknownCopy(void)
{
HRESULT hres;
VARIANTARG vSrc, vDst;
DummyDispatch u = { { &DummyDispatch_VTable }, 1, VT_UI1, FALSE };
IUnknown* pu = (IUnknown*)&u.IDispatch_iface;
DummyDispatch u;
IUnknown* pu;
init_test_dispatch(1, VT_UI1, &u);
pu = (IUnknown*)&u.IDispatch_iface;
/* AddRef is called on by-value copy */
VariantInit(&vDst);
@@ -5661,8 +5819,11 @@ static void test_IUnknownChangeTypeEx(void)
VARIANTARG vSrc, vDst;
LCID lcid;
VARTYPE vt;
DummyDispatch u = { { &DummyDispatch_VTable }, 1, VT_UI1, FALSE };
IUnknown* pu = (IUnknown*)&u.IDispatch_iface;
DummyDispatch u;
IUnknown* pu;
init_test_dispatch(1, VT_UI1, &u);
pu = (IUnknown*)&u.IDispatch_iface;
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
@@ -5726,8 +5887,11 @@ static void test_IDispatchClear(void)
{
HRESULT hres;
VARIANTARG v;
DummyDispatch d = { { &DummyDispatch_VTable }, 1, VT_UI1, FALSE };
IDispatch* pd = &d.IDispatch_iface;
DummyDispatch d;
IDispatch* pd;
init_test_dispatch(1, VT_UI1, &d);
pd = &d.IDispatch_iface;
/* As per IUnknown */
@@ -5751,8 +5915,11 @@ static void test_IDispatchCopy(void)
{
HRESULT hres;
VARIANTARG vSrc, vDst;
DummyDispatch d = { { &DummyDispatch_VTable }, 1, VT_UI1, FALSE };
IDispatch* pd = &d.IDispatch_iface;
DummyDispatch d;
IDispatch* pd;
init_test_dispatch(1, VT_UI1, &d);
pd = &d.IDispatch_iface;
/* As per IUnknown */
@@ -5796,8 +5963,11 @@ static void test_IDispatchChangeTypeEx(void)
HRESULT hres;
VARIANTARG vSrc, vDst;
LCID lcid;
DummyDispatch d = { { &DummyDispatch_VTable }, 1, VT_UI1, FALSE };
IDispatch* pd = &d.IDispatch_iface;
DummyDispatch d;
IDispatch* pd;
init_test_dispatch(1, VT_UI1, &d);
pd = &d.IDispatch_iface;
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
@@ -5872,89 +6042,147 @@ static void test_ErrorChangeTypeEx(void)
/* VT_EMPTY */
static void test_EmptyChangeTypeEx(void)
{
HRESULT hres;
VARIANTARG vSrc, vDst;
VARTYPE vt;
LCID lcid;
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
for (vt = VT_EMPTY; vt <= VT_BSTR_BLOB; vt++)
{
HRESULT hExpected = DISP_E_BADVARTYPE;
HRESULT hExpected, hres;
VARIANTARG vSrc, vDst;
VariantInit(&vSrc);
memset(&vDst, 0, sizeof(vDst));
V_VT(&vDst) = VT_EMPTY;
/* skip for undefined types */
if ((vt == 15) || (vt > VT_VERSIONED_STREAM && vt < VT_BSTR_BLOB))
continue;
if (vt == VT_I8 || vt == VT_UI8)
switch (vt)
{
case VT_I8:
case VT_UI8:
if (has_i8)
hExpected = S_OK;
}
else if (vt == VT_RECORD)
{
else
hExpected = DISP_E_BADVARTYPE;
break;
case VT_RECORD:
case VT_VARIANT:
case VT_DISPATCH:
case VT_UNKNOWN:
case VT_ERROR:
hExpected = DISP_E_TYPEMISMATCH;
}
else if (vt == VT_VARIANT || vt == VT_DISPATCH ||
vt == VT_UNKNOWN || vt == VT_ERROR)
{
hExpected = DISP_E_TYPEMISMATCH;
}
else if (vt <= VT_UINT && vt != (VARTYPE)15)
break;
case VT_EMPTY:
case VT_NULL:
case VT_I2:
case VT_I4:
case VT_R4:
case VT_R8:
case VT_CY:
case VT_DATE:
case VT_BSTR:
case VT_BOOL:
case VT_DECIMAL:
case VT_I1:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_INT:
case VT_UINT:
hExpected = S_OK;
break;
default:
hExpected = DISP_E_BADVARTYPE;
}
VariantInit(&vSrc);
V_VT(&vSrc) = VT_EMPTY;
memset(&vDst, 0, sizeof(vDst));
V_VT(&vDst) = VT_NULL;
hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
ok(hres == hExpected && (hres != S_OK || V_VT(&vDst) == vt),
"change empty: vt %d expected 0x%08x, got 0x%08x, vt %d\n",
vt, hExpected, hres, V_VT(&vDst));
if(hres == S_OK) VariantClear(&vDst);
ok(hres == hExpected, "change empty: vt %d expected 0x%08x, got 0x%08x, vt %d\n",
vt, hExpected, hres, V_VT(&vDst));
if (hres == S_OK)
{
ok(V_VT(&vDst) == vt, "change empty: vt %d, got %d\n", vt, V_VT(&vDst));
VariantClear(&vDst);
}
}
}
/* VT_NULL */
static void test_NullChangeTypeEx(void)
{
HRESULT hres;
VARIANTARG vSrc, vDst;
VARTYPE vt;
LCID lcid;
lcid = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
for (vt = VT_EMPTY; vt <= VT_BSTR_BLOB; vt++)
{
HRESULT hExpected = DISP_E_BADVARTYPE;
VARIANTARG vSrc, vDst;
HRESULT hExpected, hres;
/* skip for undefined types */
if ((vt == 15) || (vt > VT_VERSIONED_STREAM && vt < VT_BSTR_BLOB))
continue;
switch (vt)
{
case VT_I8:
case VT_UI8:
if (has_i8)
hExpected = DISP_E_TYPEMISMATCH;
else
hExpected = DISP_E_BADVARTYPE;
break;
case VT_NULL:
hExpected = S_OK;
break;
case VT_EMPTY:
case VT_I2:
case VT_I4:
case VT_R4:
case VT_R8:
case VT_CY:
case VT_DATE:
case VT_BSTR:
case VT_DISPATCH:
case VT_ERROR:
case VT_BOOL:
case VT_VARIANT:
case VT_UNKNOWN:
case VT_DECIMAL:
case VT_I1:
case VT_UI1:
case VT_UI2:
case VT_UI4:
case VT_INT:
case VT_UINT:
case VT_RECORD:
hExpected = DISP_E_TYPEMISMATCH;
break;
default:
hExpected = DISP_E_BADVARTYPE;
}
VariantInit(&vSrc);
V_VT(&vSrc) = VT_NULL;
memset(&vDst, 0, sizeof(vDst));
V_VT(&vDst) = VT_EMPTY;
if (vt == VT_I8 || vt == VT_UI8)
{
if (has_i8)
hExpected = DISP_E_TYPEMISMATCH;
}
else if (vt == VT_RECORD)
{
hExpected = DISP_E_TYPEMISMATCH;
}
else if (vt == VT_NULL)
{
hExpected = S_OK;
}
else if (vt == VT_VARIANT || vt == VT_DISPATCH ||
vt == VT_UNKNOWN || vt == VT_ERROR ||
(vt <= VT_UINT && vt != (VARTYPE)15))
hExpected = DISP_E_TYPEMISMATCH;
hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
ok(hres == hExpected && (hres != S_OK || V_VT(&vDst) == vt),
"change null: vt %d expected 0x%08x, got 0x%08x, vt %d\n",
ok(hres == hExpected, "change null: vt %d expected 0x%08x, got 0x%08x, vt %d\n",
vt, hExpected, hres, V_VT(&vDst));
/* should work only for VT_NULL -> VT_NULL case */
if (hres == S_OK)
ok(V_VT(&vDst) == VT_NULL, "change null: VT_NULL expected 0x%08x, got 0x%08x, vt %d\n",
hExpected, hres, V_VT(&vDst));
else
ok(V_VT(&vDst) == VT_EMPTY, "change null: vt %d expected 0x%08x, got 0x%08x, vt %d\n",
vt, hExpected, hres, V_VT(&vDst));
}
}
@@ -6090,6 +6318,129 @@ static void test_bstr_cache(void)
SysFreeString(str2);
}
static void write_typelib(int res_no, const char *filename)
{
DWORD written;
HANDLE file;
HRSRC res;
void *ptr;
file = CreateFileA( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
ok( file != INVALID_HANDLE_VALUE, "file creation failed\n" );
if (file == INVALID_HANDLE_VALUE) return;
res = FindResourceA( GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(res_no), "TYPELIB" );
ok( res != 0, "couldn't find resource\n" );
ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res ));
WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL );
ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" );
CloseHandle( file );
}
static const char *create_test_typelib(int res_no)
{
static char filename[MAX_PATH];
GetTempFileNameA( ".", "tlb", 0, filename );
write_typelib(res_no, filename);
return filename;
}
static void test_recinfo(void)
{
static const WCHAR testW[] = {'t','e','s','t',0};
static WCHAR teststructW[] = {'t','e','s','t','_','s','t','r','u','c','t',0};
struct test_struct teststruct, testcopy;
WCHAR filenameW[MAX_PATH];
const char *filename;
IRecordInfo *recinfo;
ITypeInfo *typeinfo;
DummyDispatch dispatch;
ITypeLib *typelib;
TYPEATTR *attr;
MEMBERID memid;
UINT16 found;
HRESULT hr;
ULONG size;
filename = create_test_typelib(2);
MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, MAX_PATH);
hr = LoadTypeLibEx(filenameW, REGKIND_NONE, &typelib);
ok(hr == S_OK, "got 0x%08x\n", hr);
typeinfo = NULL;
found = 1;
hr = ITypeLib_FindName(typelib, teststructW, 0, &typeinfo, &memid, &found);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(typeinfo != NULL, "got %p\n", typeinfo);
hr = ITypeInfo_GetTypeAttr(typeinfo, &attr);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(IsEqualGUID(&attr->guid, &UUID_test_struct), "got %s\n", wine_dbgstr_guid(&attr->guid));
ok(attr->typekind == TKIND_RECORD, "got %d\n", attr->typekind);
hr = GetRecordInfoFromTypeInfo(typeinfo, &recinfo);
ok(hr == S_OK, "got 0x%08x\n", hr);
size = 0;
hr = IRecordInfo_GetSize(recinfo, &size);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(size == sizeof(struct test_struct), "got size %d\n", size);
ok(attr->cbSizeInstance == sizeof(struct test_struct), "got instance size %d\n", attr->cbSizeInstance);
ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
/* RecordInit() */
teststruct.hr = E_FAIL;
teststruct.b = 0x1;
teststruct.disp = (void*)0xdeadbeef;
teststruct.bstr = (void*)0xdeadbeef;
hr = IRecordInfo_RecordInit(recinfo, &teststruct);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(teststruct.hr == 0, "got 0x%08x\n", teststruct.hr);
ok(teststruct.b == 0, "got 0x%08x\n", teststruct.b);
ok(teststruct.disp == NULL, "got %p\n", teststruct.disp);
ok(teststruct.bstr == NULL, "got %p\n", teststruct.bstr);
init_test_dispatch(10, VT_UI1, &dispatch);
/* RecordCopy(), interface field reference increased */
teststruct.hr = S_FALSE;
teststruct.b = VARIANT_TRUE;
teststruct.disp = &dispatch.IDispatch_iface;
teststruct.bstr = SysAllocString(testW);
memset(&testcopy, 0, sizeof(testcopy));
hr = IRecordInfo_RecordCopy(recinfo, &teststruct, &testcopy);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(testcopy.hr == S_FALSE, "got 0x%08x\n", testcopy.hr);
ok(testcopy.b == VARIANT_TRUE, "got %d\n", testcopy.b);
ok(testcopy.disp == teststruct.disp, "got %p\n", testcopy.disp);
ok(dispatch.ref == 11, "got %d\n", dispatch.ref);
ok(testcopy.bstr != teststruct.bstr, "got %p\n", testcopy.bstr);
ok(!lstrcmpW(testcopy.bstr, teststruct.bstr), "got %s, %s\n", wine_dbgstr_w(testcopy.bstr), wine_dbgstr_w(teststruct.bstr));
/* RecordClear() */
hr = IRecordInfo_RecordClear(recinfo, &teststruct);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(teststruct.bstr == NULL, "got %p\n", teststruct.bstr);
hr = IRecordInfo_RecordClear(recinfo, &testcopy);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(testcopy.bstr == NULL, "got %p\n", testcopy.bstr);
/* now destination contains inteface pointer */
memset(&testcopy, 0, sizeof(testcopy));
testcopy.disp = &dispatch.IDispatch_iface;
dispatch.ref = 10;
hr = IRecordInfo_RecordCopy(recinfo, &teststruct, &testcopy);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(dispatch.ref == 9, "got %d\n", dispatch.ref);
IRecordInfo_Release(recinfo);
ITypeInfo_Release(typeinfo);
ITypeLib_Release(typelib);
DeleteFileA(filename);
}
START_TEST(vartype)
{
hOleaut32 = GetModuleHandleA("oleaut32.dll");
@@ -6340,6 +6691,7 @@ START_TEST(vartype)
test_VarDecCmpR8();
test_VarDecMul();
test_VarDecDiv();
test_VarDecRound();
test_VarBoolFromI1();
test_VarBoolFromUI1();
@@ -6390,4 +6742,6 @@ START_TEST(vartype)
test_NullByRef();
test_ChangeType_keep_dst();
test_recinfo();
}