* Sync with Wine 1.7.17.
CORE-8080
svn path=/trunk/; revision=62943
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
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
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)
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
+#define COBJMACROS
+#define CONST_VTABLE
+
#include <wine/test.h>
//#include <windef.h>
//#include <winbase.h>
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();
}
LPVOID pvObj = NULL;
IFont* ifnt = NULL;
HFONT hfont;
- LOGFONT lf;
+ LOGFONTA lf;
CY psize;
HRESULT hres;
DWORD rtnval;
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);
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);
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. */
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)
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))
{
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;
}
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;
IFontDisp *pFontDisp;
DISPPARAMS dispparams;
VARIANTARG vararg;
+ INT i;
fontdesc.cbSizeofstruct = sizeof(fontdesc);
fontdesc.lpstrName = MSSansSerif_font;
EXPECT_HR(hr, S_OK);
IConnectionPoint_Release(pCP);
+ fonteventsdisp_invoke_called = 0;
hr = IFont_put_Bold(pFont, TRUE);
EXPECT_HR(hr, S_OK);
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:
+ ;
+ }
- IFontDisp_Release(pFontDisp);
+ 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);
+ }
- ok(fonteventsdisp_invoke_called == 2, "IFontEventDisp::Invoke was called %d times instead of twice\n",
- fonteventsdisp_invoke_called);
+ IFontDisp_Release(pFontDisp);
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);
}
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);
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. */
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);
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);
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);
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");
}
{
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);
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);
}
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,
+ ¶ms, &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;
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);
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 */
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) {
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);
HGLOBAL hmem;
DWORD *mem;
IPersistStream *src_stream;
- IStream *dst_stream;
+ IStream *dst_stream, *stream;
+ LARGE_INTEGER offset;
HRESULT hr;
memset(&pic, 0, sizeof(pic));
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)
//#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**);
/* 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
{
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);
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++;
return S_OK;
}
-static HRESULT CALLBACK IRecordInfoImpl_Dummy(IRecordInfo *iface)
+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)
{
- 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_GetFieldNoCopy(IRecordInfo *iface, PVOID pvData,
+ LPCOLESTR szFieldName, VARIANT *pvarField, PVOID *ppvDataCArray)
{
- (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_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)
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++)
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++)
}
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)
return;
ok(sa->cbElements == sizeof(BSTR), "BSTR size mismatch\n");
- if (sa->cbElements != sizeof(BSTR))
- return;
indices[0] = sab.lLbound;
value = SysAllocString(szTest);
return;
ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
- if (sa->cbElements != sizeof(LPUNKNOWN))
- return;
indices[0] = sab.lLbound;
xtunk.ref = 1;
return;
ok(sa->cbElements == sizeof(LPUNKNOWN), "LPUNKNOWN size mismatch\n");
- if (sa->cbElements != sizeof(LPUNKNOWN))
- return;
indices[0] = 2;
xtunk.ref = 1;
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;
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)
{
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++)
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)
/* 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);
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);
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);
}
SAFEARRAY *sa, *sa2;
VARIANTARG vSrc, vDst;
HRESULT hres;
+ int i;
sab.lLbound = 0;
sab.cElements = 10;
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; \
HRESULT hres;
int value = 0xdeadbeef;
LONG index[1];
- void HUGEP *temp_pvData;
+ void *temp_pvData;
sab.lLbound = 0;
sab.cElements = 10;
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");
test_SafeArrayGetPutElement_IUnknown();
test_SafeArrayRedim_IUnknown();
test_SafeArrayGetPutElement_VARIANT();
+ test_safearray_layout();
}
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#pragma makedep ident
+#pragma makedep typelib
+
import "oaidl.idl"; /* needed by widl */
[
{
[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);
}
}
* 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)]
{
HRESULT test();
}
+
+ [uuid(4029f190-ca4a-4611-aeb9-673983cb96dd)]
+ struct test_struct
+ {
+ HRESULT hr;
+ VARIANT_BOOL b;
+ IDispatch *disp;
+ BSTR bstr;
+ };
}
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)
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)
{
SetEvent((HANDLE)msg.lParam);
}
else
- DispatchMessage(&msg);
+ DispatchMessageA(&msg);
}
HeapFree(GetProcessHeap(), 0, data);
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;
* 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);
}
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);
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(
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;
Widget_ByRefUInt,
Widget_put_prop_opt_arg,
Widget_put_prop_req_arg,
- Widget_do_restrict,
+ Widget__restrict,
Widget_neg_restrict
};
{
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;
*
*/
+#pragma makedep ident
+#pragma makedep typelib
+
#include "tmarshal_dispids.h"
import "ocidl.idl";
#include <tmarshal.h>
#include <test_reg.h>
+#include <test_tlb.h>
#define expect_eq(expr, value, type, format) { type _ret = (expr); ok((value) == _ret, #expr " expected " format " got " format "\n", value, _ret); }
#define expect_int(expr, value) expect_eq(expr, (int)(value), int, "%d")
#define expect_hex(expr, value) expect_eq(expr, (int)(value), int, "0x%x")
#define expect_null(expr) expect_eq(expr, NULL, const void *, "%p")
+#define expect_guid(expected, guid) { ok(IsEqualGUID(expected, guid), "got wrong guid\n"); }
#define expect_wstr_acpval(expr, value) \
{ \
CHAR buf[260]; \
expect_eq(!WideCharToMultiByte(CP_ACP, 0, (expr), -1, buf, 260, NULL, NULL), 0, int, "%d"); \
- ok(lstrcmp(value, buf) == 0, #expr " expected \"%s\" got \"%s\"\n", value, buf); \
+ ok(strcmp(value, buf) == 0, #expr " expected \"%s\" got \"%s\"\n", value, buf); \
}
#define ole_expect(expr, expect) { \
static WCHAR wszGUID[] = {'G','U','I','D',0};
static WCHAR wszguid[] = {'g','u','i','d',0};
-static const int is_win64 = sizeof(void *) > sizeof(int);
+static const BOOL is_win64 = sizeof(void *) > sizeof(int);
static HRESULT WINAPI invoketest_QueryInterface(IInvokeTest *iface, REFIID riid, void **ret)
{
return i+1;
}
+static LONG WINAPI invoketest_putref_testprop(IInvokeTest *iface, LONG *i)
+{
+ return *i+2;
+}
+
+static LONG WINAPI invoketest_putref_testprop2(IInvokeTest *iface, IUnknown *i)
+{
+ return 6;
+}
+
static const IInvokeTestVtbl invoketestvtbl = {
invoketest_QueryInterface,
invoketest_AddRef,
invoketest_GetTypeInfo,
invoketest_GetIDsOfNames,
invoketest_Invoke,
- invoketest_get_test
+ invoketest_get_test,
+ invoketest_putref_testprop,
+ invoketest_putref_testprop2
};
static IInvokeTest invoketest = { &invoketestvtbl };
HRSRC res;
void *ptr;
- file = CreateFile( filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 );
+ 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 = FindResource( GetModuleHandle(0), MAKEINTRESOURCE(res_no), "TYPELIB" );
+ res = FindResourceA( GetModuleHandleA(NULL), (LPCSTR)MAKEINTRESOURCE(res_no), "TYPELIB" );
ok( res != 0, "couldn't find resource\n" );
- ptr = LockResource( LoadResource( GetModuleHandle(0), res ));
- WriteFile( file, ptr, SizeofResource( GetModuleHandle(0), res ), &written, NULL );
- ok( written == SizeofResource( GetModuleHandle(0), res ), "couldn't write 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 void test_TypeInfo(void)
{
ITypeLib *pTypeLib;
- ITypeInfo *pTypeInfo;
+ ITypeInfo *pTypeInfo, *ti;
ITypeInfo2 *pTypeInfo2;
HRESULT hr;
static WCHAR wszBogus[] = { 'b','o','g','u','s',0 };
TYPEKIND kind;
const char *filenameA;
WCHAR filename[MAX_PATH];
+ TYPEATTR *attr;
+ LONG l;
hr = LoadTypeLib(wszStdOle2, &pTypeLib);
ok_ole_success(hr, LoadTypeLib);
ITypeInfo_Release(pTypeInfo);
-
-
hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IDispatch, &pTypeInfo);
ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
VariantClear(&var);
}
+ /* Check instance size for IDispatch, typelib is loaded using system SYS_WIN* kind so it always matches
+ system bitness. */
+ hr = ITypeInfo_GetTypeAttr(pTypeInfo, &attr);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(attr->cbSizeInstance == sizeof(void*), "got size %d\n", attr->cbSizeInstance);
+ ok(attr->typekind == TKIND_INTERFACE, "got typekind %d\n", attr->typekind);
+ ITypeInfo_ReleaseTypeAttr(pTypeInfo, attr);
+
+ /* same size check with some general interface */
+ hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_IEnumVARIANT, &ti);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = ITypeInfo_GetTypeAttr(ti, &attr);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(attr->cbSizeInstance == sizeof(void*), "got size %d\n", attr->cbSizeInstance);
+ ITypeInfo_ReleaseTypeAttr(ti, attr);
+ ITypeInfo_Release(ti);
+
/* test invoking a method with a [restricted] keyword */
/* correct member id -- wrong flags -- cNamedArgs not bigger than cArgs */
V_VT(&args[0]) = VT_I4;
V_I4(&args[0]) = 0;
- V_VT(&res) = VT_EMPTY;
-
i = 0;
V_VT(&res) = VT_EMPTY;
V_I4(&res) = 0;
ok(V_VT(&res) == VT_I4, "got %d\n", V_VT(&res));
ok(V_I4(&res) == 1, "got %d\n", V_I4(&res));
+ /* DISPATCH_PROPERTYPUTREF */
+ l = 1;
+ V_VT(&args[0]) = VT_I4|VT_BYREF;
+ V_I4REF(&args[0]) = &l;
+
+ dispidMember = DISPID_PROPERTYPUT;
+ dispparams.cArgs = 1;
+ dispparams.cNamedArgs = 1;
+ dispparams.rgdispidNamedArgs = &dispidMember;
+ dispparams.rgvarg = args;
+
+ i = 0;
+ V_VT(&res) = VT_EMPTY;
+ V_I4(&res) = 0;
+ hr = ITypeInfo_Invoke(pTypeInfo, &invoketest, 1, DISPATCH_PROPERTYPUTREF, &dispparams, &res, NULL, &i);
+ ok(hr == S_OK, "got 0x%08x, %d\n", hr, i);
+ ok(V_VT(&res) == VT_I4, "got %d\n", V_VT(&res));
+ ok(V_I4(&res) == 3, "got %d\n", V_I4(&res));
+
+ i = 0;
+ V_VT(&res) = VT_EMPTY;
+ V_I4(&res) = 0;
+ hr = ITypeInfo_Invoke(pTypeInfo, &invoketest, 1, DISPATCH_PROPERTYPUT, &dispparams, &res, NULL, &i);
+ ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x, %d\n", hr, i);
+
+ i = 0;
+ V_VT(&args[0]) = VT_UNKNOWN;
+ V_UNKNOWN(&args[0]) = NULL;
+
+ V_VT(&res) = VT_EMPTY;
+ V_I4(&res) = 0;
+ hr = ITypeInfo_Invoke(pTypeInfo, &invoketest, 2, DISPATCH_PROPERTYPUTREF, &dispparams, &res, NULL, &i);
+ ok(hr == S_OK, "got 0x%08x, %d\n", hr, i);
+ ok(V_VT(&res) == VT_I4, "got %d\n", V_VT(&res));
+ ok(V_I4(&res) == 6, "got %d\n", V_I4(&res));
+
+ i = 0;
+ V_VT(&res) = VT_EMPTY;
+ V_I4(&res) = 0;
+ hr = ITypeInfo_Invoke(pTypeInfo, &invoketest, 2, DISPATCH_PROPERTYPUT, &dispparams, &res, NULL, &i);
+ ok(hr == DISP_E_MEMBERNOTFOUND, "got 0x%08x, %d\n", hr, i);
+
ITypeInfo_Release(pTypeInfo);
ITypeLib_Release(pTypeLib);
DeleteFileA(filenameA);
CHAR pathA[MAX_PATH];
static const WCHAR tl_path[] = {'.','\\','m','i','d','l','_','t','m','a','r','s','h','a','l','.','t','l','b',0};
- BOOL use_midl_tlb = 0;
+ BOOL use_midl_tlb = FALSE;
GetModuleFileNameA(NULL, pathA, MAX_PATH);
MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
}
static void test_CreateTypeLib(SYSKIND sys) {
- static const WCHAR stdoleW[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
static OLECHAR typelibW[] = {'t','y','p','e','l','i','b',0};
static OLECHAR helpfileW[] = {'C',':','\\','b','o','g','u','s','.','h','l','p',0};
static OLECHAR interface1W[] = {'i','n','t','e','r','f','a','c','e','1',0};
static OLECHAR interface3W[] = {'i','n','t','e','r','f','a','c','e','3',0};
static OLECHAR dualW[] = {'d','u','a','l',0};
static OLECHAR coclassW[] = {'c','o','c','l','a','s','s',0};
- static WCHAR defaultW[] = {'d','e','f','a','u','l','t',0x3213,0};
- static WCHAR defaultQW[] = {'d','e','f','a','u','l','t','?',0};
+ static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0x3213,0};
+ static const WCHAR defaultQW[] = {'d','e','f','a','u','l','t','?',0};
static OLECHAR func1W[] = {'f','u','n','c','1',0};
static OLECHAR func2W[] = {'f','u','n','c','2',0};
static OLECHAR prop1W[] = {'P','r','o','p','1',0};
static OLECHAR param2W[] = {'p','a','r','a','m','2',0};
static OLECHAR asdfW[] = {'A','s','d','f',0};
static OLECHAR aliasW[] = {'a','l','i','a','s',0};
+ static OLECHAR invokeW[] = {'I','n','v','o','k','e',0};
static OLECHAR *names1[] = {func1W, param1W, param2W};
static OLECHAR *names2[] = {func2W, param1W, param2W};
static OLECHAR *propname[] = {prop1W, param1W};
ICreateTypeInfo2 *createti2;
ITypeLib *tl, *stdole;
ITypeInfo *interface1, *interface2, *dual, *unknown, *dispatch, *ti;
+ ITypeInfo *tinfos[2];
ITypeInfo2 *ti2;
+ ITypeComp *tcomp;
+ MEMBERID memids[2];
FUNCDESC funcdesc, *pfuncdesc;
ELEMDESC elemdesc[5], *edesc;
PARAMDESCEX paramdescex;
DWORD helpcontext, ptr_size, alignment;
int impltypeflags;
unsigned int cnames;
+ USHORT found;
VARIANT cust_data;
HRESULT hres;
TYPEKIND kind;
+ DESCKIND desckind;
+ BINDPTR bindptr;
switch(sys){
case SYS_WIN32:
trace("CreateTypeLib tests\n");
- hres = LoadTypeLib(stdoleW, &stdole);
+ hres = LoadTypeLib(wszStdOle2, &stdole);
ok(hres == S_OK, "got %08x\n", hres);
hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IUnknown, &unknown);
ok(libattr->syskind == sys, "syskind = %d\n", libattr->syskind);
ok(libattr->wMajorVerNum == 0, "wMajorVer = %d\n", libattr->wMajorVerNum);
ok(libattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", libattr->wMinorVerNum);
- todo_wine
- ok(libattr->wLibFlags == LIBFLAG_FHASDISKIMAGE, "wLibFlags = %d\n", libattr->wLibFlags);
+ ok(libattr->wLibFlags == LIBFLAG_FHASDISKIMAGE, "wLibFlags = %d\n", libattr->wLibFlags);
ITypeLib_ReleaseTLibAttr(tl, libattr);
+ found = 2;
+ memset(tinfos, 0, sizeof(tinfos));
+ memids[0] = 0xdeadbeef;
+ memids[1] = 0xdeadbeef;
+ hres = ITypeLib_FindName(tl, param1W, 0, tinfos, memids, &found);
+ ok(hres == S_OK, "got: %08x\n", hres);
+ ok(found == 0, "got wrong count: %u\n", found);
+ ok(tinfos[0] == NULL, "got invalid typeinfo[0]\n");
+ ok(tinfos[1] == NULL, "got invalid typeinfo[1]\n");
+ ok(memids[0] == 0xdeadbeef, "got invalid memid[0]\n");
+ ok(memids[1] == 0xdeadbeef, "got invalid memid[1]\n");
+
+ found = 2;
+ memset(tinfos, 0, sizeof(tinfos));
+ memids[0] = 0xdeadbeef;
+ memids[1] = 0xdeadbeef;
+ hres = ITypeLib_FindName(tl, func1W, 0, tinfos, memids, &found);
+ ok(hres == S_OK, "got: %08x\n", hres);
+ ok(found == 1, "got wrong count: %u\n", found);
+ ok(tinfos[0] != NULL, "got invalid typeinfo[0]\n");
+ ok(tinfos[1] == NULL, "got invalid typeinfo[1]\n");
+ ok(memids[0] == 0, "got invalid memid[0]\n");
+ ok(memids[1] == 0xdeadbeef, "got invalid memid[1]\n");
+ if(tinfos[0])
+ ITypeInfo_Release(tinfos[0]);
+
+ found = 2;
+ memset(tinfos, 0, sizeof(tinfos));
+ memids[0] = 0xdeadbeef;
+ memids[1] = 0xdeadbeef;
+ hres = ITypeLib_FindName(tl, interface1W, 0, tinfos, memids, &found);
+ ok(hres == S_OK, "got: %08x\n", hres);
+ ok(found == 1, "got wrong count: %u\n", found);
+ ok(tinfos[0] != NULL, "got invalid typeinfo[0]\n");
+ ok(tinfos[1] == NULL, "got invalid typeinfo[1]\n");
+ ok(memids[0] == MEMBERID_NIL, "got invalid memid[0]: %x\n", memids[0]);
+ ok(memids[1] == 0xdeadbeef, "got invalid memid[1]\n");
+ if(tinfos[0])
+ ITypeInfo_Release(tinfos[0]);
+
hres = ITypeLib_GetDocumentation(tl, -1, &name, &docstring, &helpcontext, &helpfile);
ok(hres == S_OK, "got %08x\n", hres);
ok(memcmp(typelibW, name, sizeof(typelibW)) == 0, "got wrong typelib name: %s\n",
ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+ hres = ITypeInfo_GetTypeComp(ti, &tcomp);
+ ok(hres == S_OK, "got %08x\n", hres);
+
+ hres = ITypeComp_Bind(tcomp, invokeW, 0, INVOKE_FUNC, &interface1, &desckind, &bindptr);
+ ok(hres == S_OK, "got %08x\n", hres);
+ ok(desckind == DESCKIND_FUNCDESC, "got wrong desckind: 0x%x\n", desckind);
+ ok(bindptr.lpfuncdesc->memid == 0x60010003, "got %x\n", bindptr.lpfuncdesc->memid);
+ ok(bindptr.lpfuncdesc->lprgscode == NULL, "got %p\n", bindptr.lpfuncdesc->lprgscode);
+ ok(bindptr.lpfuncdesc->lprgelemdescParam != NULL, "got %p\n", bindptr.lpfuncdesc->lprgelemdescParam);
+ ok(bindptr.lpfuncdesc->funckind == FUNC_DISPATCH, "got 0x%x\n", bindptr.lpfuncdesc->funckind);
+ ok(bindptr.lpfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", bindptr.lpfuncdesc->invkind);
+ ok(bindptr.lpfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", bindptr.lpfuncdesc->callconv);
+ ok(bindptr.lpfuncdesc->cParams == 8, "got %d\n", bindptr.lpfuncdesc->cParams);
+ ok(bindptr.lpfuncdesc->cParamsOpt == 0, "got %d\n", bindptr.lpfuncdesc->cParamsOpt);
+#ifdef _WIN64
+ if(sys == SYS_WIN32)
+ todo_wine ok(bindptr.lpfuncdesc->oVft == 6 * sizeof(void*), "got %x\n", bindptr.lpfuncdesc->oVft);
+ else
+#endif
+ ok(bindptr.lpfuncdesc->oVft == 6 * sizeof(void*), "got %x\n", bindptr.lpfuncdesc->oVft);
+ ok(bindptr.lpfuncdesc->cScodes == 0, "got %d\n", bindptr.lpfuncdesc->cScodes);
+ ok(bindptr.lpfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", bindptr.lpfuncdesc->elemdescFunc.tdesc.vt);
+ ok(bindptr.lpfuncdesc->wFuncFlags == FUNCFLAG_FRESTRICTED, "got 0x%x\n", bindptr.lpfuncdesc->wFuncFlags);
+
+ ITypeInfo_ReleaseFuncDesc(interface1, bindptr.lpfuncdesc);
+ ITypeInfo_Release(interface1);
+ ITypeComp_Release(tcomp);
+
hres = ITypeInfo_GetRefTypeOfImplType(ti, -1, &hreftype);
ok(hres == S_OK, "got %08x\n", hres);
ok(hreftype == -2, "got wrong hreftype: %x\n", hreftype);
LPCSTR names[15];
} function_info;
-typedef struct _interface_info
+typedef struct _type_info
{
LPCSTR name;
+ LPCSTR uuid;
TYPEKIND type;
WORD wTypeFlags;
USHORT cbAlignment;
USHORT cbSizeVft;
USHORT cFuncs;
function_info funcs[20];
-} interface_info;
+} type_info;
-static const interface_info info[] = {
-/* interfaces count: 2 */
+static const type_info info[] = {
{
"IDualIface",
- /*kind*/ TKIND_DISPATCH, /*flags*/ 0x1040, /*align*/ 4, /*size*/ 4,
+ "{b14b6bb5-904e-4ff9-b247-bd361f7aaedd}",
+ /*kind*/ TKIND_DISPATCH, /*flags*/ TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL, /*align*/ 4, /*size*/ sizeof(void*),
/*#vtbl*/ 7, /*#func*/ 8,
{
{
- 0x60000000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60000000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 2, /*#opt*/ 0, /*vtbl*/ 0, /*#scodes*/ 0, /*flags*/ 0x1,
{24, 0}, /* ret */
{ /* params */
},
},
{
- 0x60000001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60000001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 1, /*#scodes*/ 0, /*flags*/ 0x1,
{19, 0}, /* ret */
{ /* params */
},
},
{
- 0x60000002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60000002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 2, /*#scodes*/ 0, /*flags*/ 0x1,
{19, 0}, /* ret */
{ /* params */
},
},
{
- 0x60010000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60010000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 1, /*#opt*/ 0, /*vtbl*/ 3, /*#scodes*/ 0, /*flags*/ 0x1,
{24, 0}, /* ret */
{ /* params */
},
},
{
- 0x60010001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60010001, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 3, /*#opt*/ 0, /*vtbl*/ 4, /*#scodes*/ 0, /*flags*/ 0x1,
{24, 0}, /* ret */
{ /* params */
},
},
{
- 0x60010002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60010002, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 5, /*#opt*/ 0, /*vtbl*/ 5, /*#scodes*/ 0, /*flags*/ 0x1,
{24, 0}, /* ret */
{ /* params */
},
},
{
- 0x60010003, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60010003, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 8, /*#opt*/ 0, /*vtbl*/ 6, /*#scodes*/ 0, /*flags*/ 0x1,
{24, 0}, /* ret */
{ /* params */
},
},
{
- 0x60020000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60020000, /*func*/ FUNC_DISPATCH, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 7, /*#scodes*/ 0, /*flags*/ 0x0,
{24, 0}, /* ret */
{ /* params */
},
{
"ISimpleIface",
- /*kind*/ TKIND_INTERFACE, /*flags*/ 0x1000, /*align*/ 4, /*size*/ 4,
+ "{ec5dfcd6-eeb0-4cd6-b51e-8030e1dac009}",
+ /*kind*/ TKIND_INTERFACE, /*flags*/ TYPEFLAG_FDISPATCHABLE, /*align*/ 4, /*size*/ sizeof(void*),
/*#vtbl*/ 8, /*#func*/ 1,
{
{
- 0x60020000, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ 0x4,
+ 0x60020000, /*func*/ FUNC_PUREVIRTUAL, /*inv*/ INVOKE_FUNC, /*call*/ CC_STDCALL,
/*#param*/ 0, /*#opt*/ 0, /*vtbl*/ 7, /*#scodes*/ 0, /*flags*/ 0x0,
{25, 0}, /* ret */
{ /* params */
},
}
},
+{
+ "test_struct",
+ "{4029f190-ca4a-4611-aeb9-673983cb96dd}",
+ /* kind */ TKIND_RECORD, /*flags*/ 0, /*align*/ 4, /*size*/ sizeof(struct test_struct)
+}
};
#define check_type(elem, info) { \
{
WCHAR wszName[MAX_PATH];
ITypeLib *typelib;
- int ifcount = sizeof(info)/sizeof(info[0]);
+ int ticount = sizeof(info)/sizeof(info[0]);
int iface, func;
MultiByteToWideChar(CP_ACP, 0, name, -1, wszName, MAX_PATH);
ole_check(LoadTypeLibEx(wszName, REGKIND_NONE, &typelib));
- expect_eq(ITypeLib_GetTypeInfoCount(typelib), ifcount, UINT, "%d");
- for (iface = 0; iface < ifcount; iface++)
+ expect_eq(ITypeLib_GetTypeInfoCount(typelib), ticount, UINT, "%d");
+ for (iface = 0; iface < ticount; iface++)
{
- const interface_info *if_info = &info[iface];
+ const type_info *ti = &info[iface];
ITypeInfo *typeinfo;
TYPEATTR *typeattr;
BSTR bstrIfName;
- trace("Interface %s\n", if_info->name);
+ trace("Interface %s\n", ti->name);
ole_check(ITypeLib_GetTypeInfo(typelib, iface, &typeinfo));
ole_check(ITypeLib_GetDocumentation(typelib, iface, &bstrIfName, NULL, NULL, NULL));
- expect_wstr_acpval(bstrIfName, if_info->name);
+ expect_wstr_acpval(bstrIfName, ti->name);
SysFreeString(bstrIfName);
ole_check(ITypeInfo_GetTypeAttr(typeinfo, &typeattr));
- expect_int(typeattr->typekind, if_info->type);
- expect_hex(typeattr->wTypeFlags, if_info->wTypeFlags);
- expect_int(typeattr->cbAlignment, if_info->cbAlignment);
- expect_int(typeattr->cbSizeInstance, if_info->cbSizeInstance);
- expect_int(typeattr->cbSizeVft, if_info->cbSizeVft * sizeof(void*));
- expect_int(typeattr->cFuncs, if_info->cFuncs);
+ expect_int(typeattr->typekind, ti->type);
+ expect_hex(typeattr->wTypeFlags, ti->wTypeFlags);
+ expect_int(typeattr->cbAlignment, ti->cbAlignment);
+ expect_int(typeattr->cbSizeInstance, ti->cbSizeInstance);
+ expect_int(typeattr->cbSizeVft, ti->cbSizeVft * sizeof(void*));
+ expect_int(typeattr->cFuncs, ti->cFuncs);
+
+ /* compare type uuid */
+ if (ti->uuid && *ti->uuid)
+ {
+ WCHAR guidW[39];
+ ITypeInfo *typeinfo2;
+ HRESULT hr;
+ GUID guid;
+
+ MultiByteToWideChar(CP_ACP, 0, ti->uuid, -1, guidW, sizeof(guidW)/sizeof(guidW[0]));
+ IIDFromString(guidW, &guid);
+ expect_guid(&guid, &typeattr->guid);
+
+ /* check that it's possible to search using this uuid */
+ typeinfo2 = NULL;
+ hr = ITypeLib_GetTypeInfoOfGuid(typelib, &guid, &typeinfo2);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ITypeInfo_Release(typeinfo2);
+ }
for (func = 0; func < typeattr->cFuncs; func++)
{
- function_info *fn_info = (function_info *)&if_info->funcs[func];
+ function_info *fn_info = (function_info *)&ti->funcs[func];
FUNCDESC *desc;
BSTR namesTab[256];
UINT cNames;
HRESULT hr;
ICreateTypeLib2 *tl;
HANDLE file;
- DWORD msft_header[7];
+ DWORD msft_header[8];
+ ITypeLib *typelib;
+ TLIBATTR *attr;
DWORD read;
GetTempFileNameA( ".", "tlb", 0, filename );
hr = CreateTypeLib2(SYS_WIN32, name, &tl);
ok(hr == S_OK, "got %08x\n", hr);
+ hr = ICreateTypeLib2_QueryInterface(tl, &IID_ITypeLib, (void**)&typelib);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ITypeLib_GetLibAttr(typelib, &attr);
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(attr->wLibFlags == 0, "flags 0x%x\n", attr->wLibFlags);
+ ITypeLib_ReleaseTLibAttr(typelib, attr);
+
hr = ICreateTypeLib2_SetLcid(tl, lcid);
ok(hr == S_OK, "got %08x\n", hr);
hr = ICreateTypeLib2_SaveAllChanges(tl);
ok(hr == S_OK, "got %08x\n", hr);
+ hr = ITypeLib_GetLibAttr(typelib, &attr);
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(attr->wLibFlags == 0, "flags 0x%x\n", attr->wLibFlags);
+ ITypeLib_ReleaseTLibAttr(typelib, attr);
+
+ ITypeLib_Release(typelib);
ICreateTypeLib2_Release(tl);
file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0 );
ok(msft_header[3] == (lcid ? lcid : 0x409), "got %08x (lcid %08x)\n", msft_header[3], lcid);
ok(msft_header[4] == lcid, "got %08x (lcid %08x)\n", msft_header[4], lcid);
ok(msft_header[6] == 0x00040003, "got %08x\n", msft_header[6]);
+ ok(msft_header[7] == 0, "got %08x\n", msft_header[7]);
+
+ /* check flags after loading */
+ hr = LoadTypeLib(name, &typelib);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ITypeLib_GetLibAttr(typelib, &attr);
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(attr->wLibFlags == LIBFLAG_FHASDISKIMAGE, "flags 0x%x\n", attr->wLibFlags);
+ ITypeLib_ReleaseTLibAttr(typelib, attr);
+ ITypeLib_Release(typelib);
DeleteFileA(filename);
}
{
ITypeInfo *typeinfo;
TYPEATTR *attr;
+ REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY);
hr = ITypeLib_GetTypeInfo(typelib, i, &typeinfo);
ok(hr == S_OK, "got %08x\n", hr);
ok(ret == expect_ret, "%d: got %d\n", i, ret);
if(ret == ERROR_SUCCESS) RegCloseKey(hkey);
+ /* 32-bit typelibs should be registered into both registry bit modes */
+ ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, key_name, 0, KEY_READ | opposite, &hkey);
+ ok(ret == expect_ret, "%d: got %d\n", i, ret);
+ if(ret == ERROR_SUCCESS) RegCloseKey(hkey);
+
ITypeInfo_ReleaseTypeAttr(typeinfo, attr);
ITypeInfo_Release(typeinfo);
}
ok(pdesc->memid == 0x40000000, "got wrong memid: %x\n", pdesc->memid);
ok(pdesc->elemdescVar.tdesc.vt == VT_INT, "got wrong vardesc type: %u\n", pdesc->elemdescVar.tdesc.vt);
ok(pdesc->varkind == VAR_CONST, "got wrong varkind: %u\n", pdesc->varkind);
- ok(V_VT(U(pdesc)->lpvarValue) == VT_INT, "got wrong value type: %u\n", V_VT(U(pdesc)->lpvarValue));
- ok(V_INT(U(pdesc)->lpvarValue) == 1, "got wrong value: 0x%x\n", V_INT(U(pdesc)->lpvarValue));
+ ok(V_VT(U(*pdesc).lpvarValue) == VT_INT, "got wrong value type: %u\n", V_VT(U(*pdesc).lpvarValue));
+ ok(V_INT(U(*pdesc).lpvarValue) == 1, "got wrong value: 0x%x\n", V_INT(U(*pdesc).lpvarValue));
hr = ITypeInfo_GetDocumentation(ti, pdesc->memid, NULL, NULL, &ctx, NULL);
ok(hr == S_OK, "got %08x\n", hr);
static void test_SetFuncAndParamNames(void)
{
static OLECHAR nameW[] = {'n','a','m','e',0};
+ static OLECHAR name2W[] = {'n','a','m','e','2',0};
static OLECHAR prop[] = {'p','r','o','p',0};
static OLECHAR *propW[] = {prop};
+ static OLECHAR func[] = {'f','u','n','c',0};
+ static OLECHAR *funcW[] = {func, NULL};
CHAR filenameA[MAX_PATH];
WCHAR filenameW[MAX_PATH];
ICreateTypeLib2 *ctl;
ICreateTypeInfo *cti;
+ ITypeLib *tl;
+ ITypeInfo *infos[3];
+ MEMBERID memids[3];
FUNCDESC funcdesc;
ELEMDESC edesc;
HRESULT hr;
+ USHORT found;
GetTempFileNameA(".", "tlb", 0, filenameA);
MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filenameW, MAX_PATH);
hr = ICreateTypeInfo_SetFuncAndParamNames(cti, 3, propW, 1);
ok(hr == TYPE_E_AMBIGUOUSNAME, "got 0x%08x\n", hr);
+ /* regular function */
+ funcdesc.invkind = INVOKE_FUNC;
+ funcdesc.cParams = 1;
+ hr = ICreateTypeInfo_AddFuncDesc(cti, 4, &funcdesc);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = ICreateTypeInfo_SetFuncAndParamNames(cti, 4, funcW, 2);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ ICreateTypeInfo_Release(cti);
+
+ hr = ICreateTypeLib2_CreateTypeInfo(ctl, name2W, TKIND_INTERFACE, &cti);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ funcdesc.funckind = FUNC_PUREVIRTUAL;
+ funcdesc.invkind = INVOKE_FUNC;
+ funcdesc.cParams = 0;
+ funcdesc.lprgelemdescParam = NULL;
+ hr = ICreateTypeInfo_AddFuncDesc(cti, 0, &funcdesc);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = ICreateTypeInfo_SetFuncAndParamNames(cti, 0, funcW, 1);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
ICreateTypeInfo_Release(cti);
+
+ hr = ICreateTypeLib2_QueryInterface(ctl, &IID_ITypeLib, (void**)&tl);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ found = 1;
+ memset(infos, 0, sizeof(infos));
+ memids[0] = 0xdeadbeef;
+ memids[1] = 0xdeadbeef;
+ memids[2] = 0xdeadbeef;
+ hr = ITypeLib_FindName(tl, func, 0, infos, memids, &found);
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(found == 1, "got wrong count: %u\n", found);
+ ok(infos[0] && !infos[1] && !infos[2], "got wrong typeinfo\n");
+ ok(memids[0] == 0, "got wrong memid[0]\n");
+ ok(memids[1] == 0xdeadbeef && memids[2] == 0xdeadbeef, "got wrong memids\n");
+
+ found = 3;
+ memset(infos, 0, sizeof(infos));
+ memids[0] = 0xdeadbeef;
+ memids[1] = 0xdeadbeef;
+ memids[2] = 0xdeadbeef;
+ hr = ITypeLib_FindName(tl, func, 0, infos, memids, &found);
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(found == 2, "got wrong count: %u\n", found);
+ ok(infos[0] && infos[1] && infos[0] != infos[1], "got same typeinfo\n");
+ ok(memids[0] == 0, "got wrong memid[0]\n");
+ ok(memids[1] == 0, "got wrong memid[1]\n");
+
+ ITypeLib_Release(tl);
ICreateTypeLib2_Release(ctl);
DeleteFileA(filenameA);
}
-static void test_SetVarDocString(void)
+static void test_SetDocString(void)
{
static OLECHAR nameW[] = {'n','a','m','e',0};
+ static OLECHAR name2W[] = {'n','a','m','e','2',0};
static OLECHAR doc1W[] = {'d','o','c','1',0};
static OLECHAR doc2W[] = {'d','o','c','2',0};
+ static OLECHAR var_nameW[] = {'v','a','r','n','a','m','e',0};
CHAR filenameA[MAX_PATH];
WCHAR filenameW[MAX_PATH];
ICreateTypeLib2 *ctl;
ICreateTypeInfo *cti;
ITypeLib *tl;
ITypeInfo *ti;
- BSTR docstr;
+ BSTR namestr, docstr;
VARDESC desc, *pdesc;
+ FUNCDESC funcdesc, *pfuncdesc;
HRESULT hr;
VARIANT v;
hr = ICreateTypeInfo_AddVarDesc(cti, 0, &desc);
ok(hr == S_OK, "got %08x\n", hr);
+ hr = ICreateTypeInfo_SetVarName(cti, 0, NULL);
+ ok(hr == E_INVALIDARG, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetVarName(cti, 1, var_nameW);
+ ok(hr == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetVarName(cti, 0, var_nameW);
+ ok(hr == S_OK, "got %08x\n", hr);
+
hr = ICreateTypeInfo_SetVarDocString(cti, 0, NULL);
ok(hr == E_INVALIDARG, "got %08x\n", hr);
ICreateTypeInfo_Release(cti);
+ hr = ICreateTypeLib2_CreateTypeInfo(ctl, name2W, TKIND_INTERFACE, &cti);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetFuncDocString(cti, 0, doc1W);
+ ok(hr == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetFuncDocString(cti, 0, NULL);
+ ok(hr == E_INVALIDARG, "got %08x\n", hr);
+
+ memset(&funcdesc, 0, sizeof(funcdesc));
+ funcdesc.memid = MEMBERID_NIL;
+ funcdesc.funckind = FUNC_PUREVIRTUAL;
+ funcdesc.invkind = INVOKE_FUNC;
+ funcdesc.callconv = CC_STDCALL;
+
+ hr = ICreateTypeInfo_AddFuncDesc(cti, 0, &funcdesc);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetFuncDocString(cti, 0, doc1W);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ ICreateTypeInfo_Release(cti);
+
hr = ICreateTypeLib2_SaveAllChanges(ctl);
ok(hr == S_OK, "got: %08x\n", hr);
ok(pdesc->memid == 0x40000000, "got wrong memid: %x\n", pdesc->memid);
ok(pdesc->elemdescVar.tdesc.vt == VT_INT, "got wrong vardesc type: %u\n", pdesc->elemdescVar.tdesc.vt);
ok(pdesc->varkind == VAR_CONST, "got wrong varkind: %u\n", pdesc->varkind);
- ok(V_VT(U(pdesc)->lpvarValue) == VT_INT, "got wrong value type: %u\n", V_VT(U(pdesc)->lpvarValue));
- ok(V_INT(U(pdesc)->lpvarValue) == 1, "got wrong value: 0x%x\n", V_INT(U(pdesc)->lpvarValue));
+ ok(V_VT(U(*pdesc).lpvarValue) == VT_INT, "got wrong value type: %u\n", V_VT(U(*pdesc).lpvarValue));
+ ok(V_INT(U(*pdesc).lpvarValue) == 1, "got wrong value: 0x%x\n", V_INT(U(*pdesc).lpvarValue));
- hr = ITypeInfo_GetDocumentation(ti, pdesc->memid, NULL, &docstr, NULL, NULL);
+ hr = ITypeInfo_GetDocumentation(ti, pdesc->memid, &namestr, &docstr, NULL, NULL);
ok(hr == S_OK, "got %08x\n", hr);
+ ok(memcmp(namestr, var_nameW, sizeof(var_nameW)) == 0, "got wrong name: %s\n", wine_dbgstr_w(namestr));
ok(memcmp(docstr, doc2W, sizeof(doc2W)) == 0, "got wrong docstring: %s\n", wine_dbgstr_w(docstr));
+ SysFreeString(namestr);
SysFreeString(docstr);
ITypeInfo_ReleaseVarDesc(ti, pdesc);
ITypeInfo_Release(ti);
+
+ hr = ITypeLib_GetTypeInfo(tl, 1, &ti);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ITypeInfo_GetFuncDesc(ti, 0, &pfuncdesc);
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(pfuncdesc->memid == 0x60000000, "got wrong memid: %x\n", pfuncdesc->memid);
+ ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got wrong funckind: %x\n", pfuncdesc->funckind);
+ ok(pfuncdesc->invkind == INVOKE_FUNC, "got wrong invkind: %x\n", pfuncdesc->invkind);
+ ok(pfuncdesc->callconv == CC_STDCALL, "got wrong callconv: %x\n", pfuncdesc->callconv);
+
+ hr = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &namestr, &docstr, NULL, NULL);
+ ok(hr == S_OK, "got %08x\n", hr);
+ ok(namestr == NULL, "got wrong name: %s\n", wine_dbgstr_w(namestr));
+ ok(memcmp(docstr, doc1W, sizeof(doc1W)) == 0, "got wrong docstring: %s\n", wine_dbgstr_w(docstr));
+
+ SysFreeString(docstr);
+
+ ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+ ITypeInfo_Release(ti);
+
ITypeLib_Release(tl);
DeleteFileA(filenameA);
ti = (void*)0xdeadbeef;
hr = ITypeLib_FindName(tl, buffW, 0, &ti, &memid, &c);
ok(hr == S_OK, "got 0x%08x\n", hr);
-todo_wine
- ok(memid == -1, "got %d\n", memid);
+ ok(memid == MEMBERID_NIL, "got %d\n", memid);
ok(!lstrcmpW(buffW, wszGUID), "got %s\n", wine_dbgstr_w(buffW));
ok(c == 1, "got %d\n", c);
ITypeInfo_Release(ti);
hr = ITypeLib_FindName(tl, buffW, 0, &ti, &memid, &c);
ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine {
- ok(memid == -1, "got %d\n", memid);
+ ok(memid == MEMBERID_NIL, "got %d\n", memid);
ok(!lstrcmpW(buffW, wszGUID), "got %s\n", wine_dbgstr_w(buffW));
ok(c == 1, "got %d\n", c);
}
ti = (void*)0xdeadbeef;
hr = ITypeLib_FindName(tl, buffW, 0, &ti, &memid, &c);
ok(hr == S_OK, "got 0x%08x\n", hr);
- ok(memid == -1, "got %d\n", memid);
+ ok(memid == MEMBERID_NIL, "got %d\n", memid);
ok(!lstrcmpW(buffW, invalidW), "got %s\n", wine_dbgstr_w(buffW));
ok(c == 0, "got %d\n", c);
ok(ti == (void*)0xdeadbeef, "got %p\n", ti);
"<assemblyIdentity version=\"1.2.3.4\" name=\"testdep\" type=\"win32\" processorArchitecture=\"" ARCH "\"/>"
"<file name=\"test_actctx_tlb.tlb\">"
" <typelib tlbid=\"{d96d8a3e-78b6-4c8d-8f27-059db959be8a}\" version=\"2.7\" helpdir=\"\" resourceid=\"409\""
-" flags=\"RESTRICTED,CONTROL\""
+" flags=\"Restricted,cONTROL\""
" />"
"</file>"
"<file name=\"test_actctx_tlb2.tlb\">"
path = NULL;
hr = QueryPathOfRegTypeLib(&LIBID_TestTypelib, 2, 0, LOCALE_NEUTRAL, &path);
-todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
SysFreeString(path);
path = NULL;
hr = QueryPathOfRegTypeLib(&LIBID_TestTypelib, 2, 0, lcid_en, &path);
-todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
SysFreeString(path);
path = NULL;
hr = QueryPathOfRegTypeLib(&LIBID_TestTypelib, 2, 0, lcid_ru, &path);
-todo_wine
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ SysFreeString(path);
+
+ hr = QueryPathOfRegTypeLib(&LIBID_TestTypelib, 2, 8, LOCALE_NEUTRAL, &path);
+ ok(hr == TYPE_E_LIBNOTREGISTERED || broken(hr == S_OK) /* winxp */, "got 0x%08x\n", hr);
+
+ path = NULL;
+ hr = QueryPathOfRegTypeLib(&LIBID_TestTypelib, 2, 7, LOCALE_NEUTRAL, &path);
ok(hr == S_OK, "got 0x%08x\n", hr);
SysFreeString(path);
/* manifest version is 2.7, actual is 2.5 */
hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 0, LOCALE_NEUTRAL, &tl);
-todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) ITypeLib_Release(tl);
hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 1, LOCALE_NEUTRAL, &tl);
-todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) ITypeLib_Release(tl);
hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 0, lcid_en, &tl);
-todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) ITypeLib_Release(tl);
hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 0, lcid_ru, &tl);
-todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) ITypeLib_Release(tl);
ok(hr == TYPE_E_LIBNOTREGISTERED, "got 0x%08x\n", hr);
hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &tl);
-todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr);
-if (hr == S_OK)
-{
hr = ITypeLib_GetLibAttr(tl, &attr);
ok(hr == S_OK, "got 0x%08x\n", hr);
ITypeLib_ReleaseTLibAttr(tl, attr);
ITypeLib_Release(tl);
-}
hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 7, LOCALE_NEUTRAL, &tl);
ok(hr == TYPE_E_LIBNOTREGISTERED, "got 0x%08x\n", hr);
DeleteFileA(filenameA);
}
+static void test_GetLibAttr(void)
+{
+ ULONG ref1, ref2;
+ TLIBATTR *attr;
+ ITypeLib *tl;
+ HRESULT hr;
+
+ hr = LoadTypeLib(wszStdOle2, &tl);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ ref1 = ITypeLib_AddRef(tl);
+ ITypeLib_Release(tl);
+
+ hr = ITypeLib_GetLibAttr(tl, &attr);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ ref2 = ITypeLib_AddRef(tl);
+ ITypeLib_Release(tl);
+ ok(ref2 == ref1, "got %d, %d\n", ref2, ref1);
+
+ ITypeLib_ReleaseTLibAttr(tl, attr);
+ ITypeLib_Release(tl);
+}
+
+static HRESULT WINAPI uk_QueryInterface(IUnknown *obj, REFIID iid, void **out)
+{
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI uk_AddRef(IUnknown *obj)
+{
+ return 2;
+}
+
+static ULONG WINAPI uk_Release(IUnknown *obj)
+{
+ return 1;
+}
+
+IUnknownVtbl vt = {
+ uk_QueryInterface,
+ uk_AddRef,
+ uk_Release,
+};
+
+IUnknown uk = {&vt};
+
+static void test_stub(void)
+{
+ HRESULT hr;
+ CLSID clsid;
+ IPSFactoryBuffer *factory;
+ IRpcStubBuffer *base_stub;
+ ITypeLib *stdole;
+ ICreateTypeLib2 *ctl;
+ ICreateTypeInfo *cti;
+ ITypeLib *tl;
+ ITypeInfo *unk, *ti;
+ HREFTYPE href;
+ char filenameA[MAX_PATH];
+ WCHAR filenameW[MAX_PATH];
+ HKEY hkey;
+ LONG lr;
+
+ static const GUID libguid = {0x3b9ff02e,0x9675,0x4861,{0xb7,0x81,0xce,0xae,0xa4,0x78,0x2a,0xcc}};
+ static const GUID interfaceguid = {0x3b9ff02f,0x9675,0x4861,{0xb7,0x81,0xce,0xae,0xa4,0x78,0x2a,0xcc}};
+ static const GUID coclassguid = {0x3b9ff030,0x9675,0x4861,{0xb7,0x81,0xce,0xae,0xa4,0x78,0x2a,0xcc}};
+ static OLECHAR interfaceW[] = {'i','n','t','e','r','f','a','c','e',0};
+ static OLECHAR classW[] = {'c','l','a','s','s',0};
+
+ CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
+ hr = LoadTypeLib(wszStdOle2, &stdole);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IUnknown, &unk);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ GetTempFileNameA(".", "tlb", 0, filenameA);
+ MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filenameW, MAX_PATH);
+
+ hr = CreateTypeLib2(SYS_WIN32, filenameW, &ctl);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeLib2_SetGuid(ctl, &libguid);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeLib2_SetLcid(ctl, LOCALE_NEUTRAL);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeLib2_CreateTypeInfo(ctl, interfaceW, TKIND_INTERFACE, &cti);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetGuid(cti, &interfaceguid);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetTypeFlags(cti, TYPEFLAG_FOLEAUTOMATION);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_AddRefTypeInfo(cti, unk, &href);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_AddImplType(cti, 0, href);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_QueryInterface(cti, &IID_ITypeInfo, (void**)&ti);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ ICreateTypeInfo_Release(cti);
+ ITypeInfo_Release(unk);
+ ITypeLib_Release(stdole);
+
+ hr = ICreateTypeLib2_CreateTypeInfo(ctl, classW, TKIND_COCLASS, &cti);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_SetGuid(cti, &coclassguid);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_AddRefTypeInfo(cti, ti, &href);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeInfo_AddImplType(cti, 0, href);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ ITypeInfo_Release(ti);
+ ICreateTypeInfo_Release(cti);
+
+ hr = ICreateTypeLib2_SaveAllChanges(ctl);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = ICreateTypeLib2_QueryInterface(ctl, &IID_ITypeLib, (void**)&tl);
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ hr = RegisterTypeLib(tl, filenameW, NULL);
+ if (hr == TYPE_E_REGISTRYACCESS)
+ {
+ win_skip("Insufficient privileges to register typelib in the registry\n");
+ ITypeLib_Release(tl);
+ DeleteFileW(filenameW);
+ CoUninitialize();
+ return;
+ }
+ ok(hr == S_OK, "got %08x\n", hr);
+
+ ITypeLib_Release(tl);
+ ok(0 == ICreateTypeLib2_Release(ctl), "Typelib still has references\n");
+
+ /* SYS_WIN32 typelibs should be registered only as 32-bit */
+ lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "TypeLib\\{3b9ff02e-9675-4861-b781-ceaea4782acc}\\0.0\\0\\win64", 0, KEY_READ, &hkey);
+ ok(lr == ERROR_FILE_NOT_FOUND, "got wrong return code: %u\n", lr);
+
+ lr = RegOpenKeyExA(HKEY_CLASSES_ROOT, "TypeLib\\{3b9ff02e-9675-4861-b781-ceaea4782acc}\\0.0\\0\\win32", 0, KEY_READ, &hkey);
+ ok(lr == ERROR_SUCCESS, "got wrong return code: %u\n", lr);
+ RegCloseKey(hkey);
+
+ hr = CoGetPSClsid(&interfaceguid, &clsid);
+ ok(hr == S_OK, "got: %x\n", hr);
+
+ hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL,
+ &IID_IPSFactoryBuffer, (void **)&factory);
+ ok(hr == S_OK, "got: %x\n", hr);
+
+ hr = IPSFactoryBuffer_CreateStub(factory, &interfaceguid, &uk, &base_stub);
+ ok(hr == S_OK, "got: %x\n", hr);
+
+ IPSFactoryBuffer_Release(factory);
+
+ UnRegisterTypeLib(&libguid, 0, 0, 0, SYS_WIN32);
+ DeleteFileW(filenameW);
+
+ CoUninitialize();
+}
+
START_TEST(typelib)
{
const char *filename;
test_inheritance();
test_SetVarHelpContext();
test_SetFuncAndParamNames();
- test_SetVarDocString();
+ test_SetDocString();
test_FindName();
if ((filename = create_test_typelib(2)))
{
test_dump_typelib( filename );
- DeleteFile( filename );
+ DeleteFileA( filename );
}
test_register_typelib(TRUE);
test_LoadTypeLib();
test_TypeInfo2_GetContainingTypeLib();
test_LoadRegTypeLib();
+ test_GetLibAttr();
+ test_stub();
}
#include <math.h>
#include <float.h>
+#define COBJMACROS
#define CONST_VTABLE
//#include "windef.h"
#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;
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");
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;
}
}
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 */
};
/* 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) &&
(!(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;
}
static void test_VariantClear(void)
{
+ struct __tagBRECORD *rec;
+ IRecordInfoImpl *recinfo;
HRESULT hres;
VARIANTARG v;
VARIANT v2;
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;
}
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;
}
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 */
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
{
- HRESULT bFail = TRUE;
+ BOOL bFail = TRUE;
SKIPTESTS(vt);
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
{
- HRESULT bFail = TRUE;
+ BOOL bFail = TRUE;
SKIPTESTS(vt);
for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
{
- HRESULT bFail = TRUE;
+ BOOL bFail = TRUE;
SKIPTESTS(vt);
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;
/* 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);
"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);
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++)
{
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++)
{
#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
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*);
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*);
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_GetTypeInfoCount(IDispatch *iface, UINT *pctinfo)
+{
+ ok(0, "Unexpected call\n");
+ return E_NOTIMPL;
}
-static HRESULT WINAPI DummyDispatch_Invoke(LPDISPATCH iface,
- DISPID dispIdMember, REFIID riid,
+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 *pDispParams,
- VARIANT *pVarResult,
- EXCEPINFO *pExcepInfo,
- UINT *puArgErr)
+ DISPPARAMS *params,
+ VARIANT *res,
+ EXCEPINFO *ei,
+ UINT *arg_err)
{
- trace("Invoke(%p)\n", iface);
+ 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(pDispParams->cArgs == 0, "Property get has args\n");
- if (dispatch.bFailInvoke)
+ 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;
}
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
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);
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);
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 */
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 */
static void test_VarUI1FromDisp(void)
{
+ DummyDispatch dispatch;
CONVVARS(LCID);
VARIANTARG vSrc, vDst;
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)
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 */
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 */
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 */
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 */
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);
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);
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;
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
*/
{
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;
{
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);
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);
{
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 */
{
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 */
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);
/* 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)
- {
- hExpected = DISP_E_TYPEMISMATCH;
- }
- else if (vt == VT_VARIANT || vt == VT_DISPATCH ||
- vt == VT_UNKNOWN || vt == VT_ERROR)
- {
+ 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_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;
+ }
- hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
+ VariantInit(&vSrc);
+ V_VT(&vSrc) = VT_EMPTY;
+ memset(&vDst, 0, sizeof(vDst));
+ V_VT(&vDst) = VT_NULL;
- 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);
+ hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
+ 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;
- VariantInit(&vSrc);
- V_VT(&vSrc) = VT_NULL;
- 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)
{
- if (has_i8)
+ 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;
}
- 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);
+ VariantInit(&vSrc);
+ V_VT(&vSrc) = VT_NULL;
+ memset(&vDst, 0, sizeof(vDst));
+ V_VT(&vDst) = VT_EMPTY;
- ok(hres == hExpected && (hres != S_OK || V_VT(&vDst) == vt),
- "change null: vt %d expected 0x%08x, got 0x%08x, vt %d\n",
+ hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
+ 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));
}
}
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");
test_VarDecCmpR8();
test_VarDecMul();
test_VarDecDiv();
+ test_VarDecRound();
test_VarBoolFromI1();
test_VarBoolFromUI1();
test_NullByRef();
test_ChangeType_keep_dst();
+
+ test_recinfo();
}