[OLEAUT32_WINETEST]
authorAmine Khaldi <amine.khaldi@reactos.org>
Thu, 26 Sep 2013 14:00:56 +0000 (14:00 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Thu, 26 Sep 2013 14:00:56 +0000 (14:00 +0000)
* Sync with Wine 1.7.1.
CORE-7469

svn path=/trunk/; revision=60357

rostests/winetests/oleaut32/CMakeLists.txt
rostests/winetests/oleaut32/safearray.c
rostests/winetests/oleaut32/tmarshal.c
rostests/winetests/oleaut32/tmarshal.idl
rostests/winetests/oleaut32/typelib.c
rostests/winetests/oleaut32/varformat.c
rostests/winetests/oleaut32/vartest.c
rostests/winetests/oleaut32/vartype.c

index c563581..9aee355 100644 (file)
@@ -1,5 +1,4 @@
 
-add_definitions(-D__ROS_LONG64__)
 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)
@@ -20,17 +19,16 @@ list(APPEND SOURCE
     ${CMAKE_CURRENT_BINARY_DIR}/test_reg_i.c
     ${CMAKE_CURRENT_BINARY_DIR}/tmarshal_i.c)
 
-add_executable(oleaut32_winetest ${SOURCE} tmarshal.rc)
-target_link_libraries(oleaut32_winetest uuid wine)
-set_module_type(oleaut32_winetest win32cui)
-add_importlibs(oleaut32_winetest oleaut32 ole32 rpcrt4 user32 gdi32 advapi32 msvcrt kernel32 ntdll)
+set(tmarshal.rc_DEPS
+    ${CMAKE_CURRENT_BINARY_DIR}/test_reg.tlb
+    ${CMAKE_CURRENT_BINARY_DIR}/test_tlb.tlb
+    ${CMAKE_CURRENT_BINARY_DIR}/tmarshal.tlb)
 
-SET(tmarshal.rc_DEPS
-${REACTOS_BINARY_DIR}/include/psdk/stdole2.tlb
-${CMAKE_CURRENT_BINARY_DIR}/test_reg.tlb
-${CMAKE_CURRENT_BINARY_DIR}/test_tlb.tlb
-${CMAKE_CURRENT_BINARY_DIR}/tmarshal.tlb)
 set_source_files_properties(tmarshal.rc PROPERTIES OBJECT_DEPENDS "${tmarshal.rc_DEPS}")
 
-add_dependencies(oleaut32_winetest stdole2 oleaut32_typelibs oleaut32_idlheaders )
+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_dependencies(oleaut32_winetest stdole2 oleaut32_typelibs oleaut32_idlheaders)
 add_cd_file(TARGET oleaut32_winetest DESTINATION reactos/bin FOR all)
index 1d634f9..859deb3 100644 (file)
@@ -56,22 +56,10 @@ static SAFEARRAY* (WINAPI *pSafeArrayCreateVector)(VARTYPE,LONG,ULONG);
 
 #define GETPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func)
 
-/* Is a given function exported from oleaut32? */
-#define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
-
-/* Have IRecordInfo data type? */
-#define HAVE_OLEAUT32_RECORD  HAVE_FUNC(SafeArraySetRecordInfo)
-/* Have R8 data type? */
-#define HAVE_OLEAUT32_R8      HAVE_FUNC(VarR8FromI1)
-/* Have I8/UI8 data type? */
-#define HAVE_OLEAUT32_I8      HAVE_FUNC(VarI8FromI1)
-/* Have the decimal type? */
-#define HAVE_OLEAUT32_DECIMAL HAVE_FUNC(VarDecAdd)
-/* Have INT_PTR/UINT_PTR type? */
-static BOOL HAVE_OLEAUT32_INT_PTR;
-
-/* very old version? */
-#define IS_ANCIENT (!HAVE_FUNC(VarI1FromI2))
+/* Has I8/UI8 data type? */
+static BOOL has_i8;
+/* Has INT_PTR/UINT_PTR type? */
+static BOOL has_int_ptr;
 
 #define START_REF_COUNT 1
 #define RECORD_SIZE 64
@@ -189,19 +177,17 @@ static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
     case VT_UI4:
     case VT_R4:
     case VT_ERROR:    return sizeof(LONG);
-    case VT_R8:
-      if (HAVE_OLEAUT32_R8)
-        return sizeof(LONG64);
+    case VT_R8:       return sizeof(LONG64);
     case VT_I8:
     case VT_UI8:
-      if (HAVE_OLEAUT32_I8)
+      if (has_i8)
         return sizeof(LONG64);
       break;
     case VT_INT:
     case VT_UINT:     return sizeof(INT);
     case VT_INT_PTR:
     case VT_UINT_PTR: 
-      if (HAVE_OLEAUT32_INT_PTR)
+      if (has_int_ptr)
         return sizeof(UINT_PTR);
       break;
     case VT_CY:       return sizeof(CY);
@@ -210,10 +196,7 @@ static DWORD SAFEARRAY_GetVTSize(VARTYPE vt)
     case VT_DISPATCH: return sizeof(LPDISPATCH);
     case VT_VARIANT:  return sizeof(VARIANT);
     case VT_UNKNOWN:  return sizeof(LPUNKNOWN);
-    case VT_DECIMAL:
-      if (HAVE_OLEAUT32_DECIMAL)
-        return sizeof(DECIMAL);
-      break;
+    case VT_DECIMAL:  return sizeof(DECIMAL);
   }
   return 0;
 }
@@ -230,13 +213,13 @@ static void check_for_VT_INT_PTR(void)
     if (a) {
         HRESULT hres;
         trace("VT_INT_PTR is supported\n");
-        HAVE_OLEAUT32_INT_PTR = TRUE;
+        has_int_ptr = TRUE;
         hres = SafeArrayDestroy(a);
         ok(hres == S_OK, "got 0x%08x\n", hres);
     }
     else {
         trace("VT_INT_PTR is not supported\n");
-        HAVE_OLEAUT32_INT_PTR = FALSE;
+        has_int_ptr = FALSE;
     }        
 }
 
@@ -345,7 +328,8 @@ static void test_safearray(void)
         a->rgsabound[1].cElements = 4;
         a->rgsabound[1].lLbound = 1;
         a->cbElements = 2;
-        SafeArrayAllocData(a);
+        hres = SafeArrayAllocData(a);
+        ok(hres == S_OK, "SafeArrayAllocData failed with hres %x\n", hres);
 
         indices[0] = 4;
         indices[1] = 2;
@@ -477,7 +461,7 @@ static void test_safearray(void)
        ok(hres == S_OK,"SAD failed with hres %x\n", hres);
 
        for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
-       if ((i == VT_I8 || i == VT_UI8) && HAVE_OLEAUT32_I8)
+       if ((i == VT_I8 || i == VT_UI8) && has_i8)
        {
          vttypes[i].elemsize = sizeof(LONG64);
        }
@@ -485,17 +469,12 @@ static void test_safearray(void)
        a = SafeArrayCreate(vttypes[i].vt, 1, &bound);
 
        ok((!a && !vttypes[i].elemsize) ||
-          (a && vttypes[i].elemsize == a->cbElements) ||
-          (IS_ANCIENT && (vttypes[i].vt == VT_DECIMAL || vttypes[i].vt == VT_I1 ||
-           vttypes[i].vt == VT_UI2 || vttypes[i].vt == VT_UI4 || vttypes[i].vt == VT_INT ||
-           vttypes[i].vt == VT_UINT)),
+          (a && vttypes[i].elemsize == a->cbElements),
           "SAC(%d,1,[1,0]), %p result %d, expected %d\n",
           vttypes[i].vt,a,(a?a->cbElements:0),vttypes[i].elemsize);
 
        if (a)
        {
-         if (!HAVE_OLEAUT32_RECORD)
-           vttypes[i].expflags = 0;
          ok(a->fFeatures == (vttypes[i].expflags | vttypes[i].addflags),
             "SAC of %d returned feature flags %x, expected %x\n",
          vttypes[i].vt, a->fFeatures,
@@ -688,8 +667,7 @@ static void test_SafeArrayAllocDestroyDescriptor(void)
   ok(hres == E_INVALIDARG, "0 dimensions gave hres 0x%x\n", hres);
 
   hres = SafeArrayAllocDescriptor(65536, &sa);
-  ok(IS_ANCIENT || hres == E_INVALIDARG,
-     "65536 dimensions gave hres 0x%x\n", hres);
+  ok(hres == E_INVALIDARG, "65536 dimensions gave hres 0x%x\n", hres);
 
   if (0)
   {
@@ -761,7 +739,7 @@ static void test_SafeArrayCreateLockDestroy(void)
   ok(sa == NULL, "NULL bounds didn't fail\n");
 */
   sa = SafeArrayCreate(VT_UI1, 65536, sab);
-  ok(IS_ANCIENT || !sa, "Max bounds didn't fail\n");
+  ok(!sa, "Max bounds didn't fail\n");
 
   memset(sab, 0, sizeof(sab));
 
@@ -780,9 +758,7 @@ static void test_SafeArrayCreateLockDestroy(void)
       sa = SafeArrayCreate(vt, dimension, sab);
 
       if (dwLen)
-        ok(sa || (IS_ANCIENT && (vt == VT_DECIMAL || vt == VT_I1 || vt == VT_UI2 ||
-           vt == VT_UI4 || vt == VT_INT || vt == VT_UINT)),
-           "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
+        ok(sa != NULL, "VARTYPE %d (@%d dimensions) failed\n", vt, dimension);
       else
         ok(sa == NULL || vt == VT_R8,
            "VARTYPE %d (@%d dimensions) succeeded!\n", vt, dimension);
@@ -810,7 +786,7 @@ static void test_SafeArrayCreateLockDestroy(void)
           {
             VARTYPE aVt;
 
-            ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEVARTYPE,
+            ok(sa->fFeatures & FADF_HAVEVARTYPE,
                "Non interface type should have FADF_HAVEVARTYPE\n");
             if (pSafeArrayGetVartype)
             {
@@ -822,8 +798,7 @@ static void test_SafeArrayCreateLockDestroy(void)
         }
         else
         {
-          ok(IS_ANCIENT || sa->fFeatures & FADF_HAVEIID,
-             "Interface type should have FADF_HAVEIID\n");
+          ok(sa->fFeatures & FADF_HAVEIID, "Interface type should have FADF_HAVEIID\n");
           if (pSafeArraySetIID)
           {
             hres = pSafeArraySetIID(sa, &IID_IUnknown);
@@ -1813,6 +1788,8 @@ START_TEST(safearray)
 {
     hOleaut32 = GetModuleHandleA("oleaut32.dll");
 
+    has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
+
     GETPTR(SafeArrayAllocDescriptorEx);
     GETPTR(SafeArrayCopyData);
     GETPTR(SafeArrayGetIID);
index 245ae71..68361c6 100644 (file)
@@ -160,6 +160,58 @@ static void end_host_object(DWORD tid, HANDLE thread)
     CloseHandle(thread);
 }
 
+static int external_connections;
+static BOOL expect_last_release_closes;
+
+static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
+{
+    ok(0, "unxpected call\n");
+    *ppv = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
+{
+    return 1;
+}
+
+static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
+{
+    trace("add connection\n");
+
+    ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
+    ok(!reserved, "reserved = %x\n", reserved);
+    return ++external_connections;
+}
+
+static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
+        DWORD reserved, BOOL fLastReleaseCloses)
+{
+    trace("release connection\n");
+
+    ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
+    ok(!reserved, "reserved = %x\n", reserved);
+
+    ok(fLastReleaseCloses == expect_last_release_closes, "fLastReleaseCloses = %x, expected %x\n",
+       fLastReleaseCloses, expect_last_release_closes);
+    return --external_connections;
+}
+
+static const IExternalConnectionVtbl ExternalConnectionVtbl = {
+    ExternalConnection_QueryInterface,
+    ExternalConnection_AddRef,
+    ExternalConnection_Release,
+    ExternalConnection_AddConnection,
+    ExternalConnection_ReleaseConnection
+};
+
+static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
+
 static ItestDual TestDual, TestDualDisp;
 
 static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
@@ -191,6 +243,67 @@ static const ITestSecondIfaceVtbl TestSecondIfaceVtbl = {
 
 static ITestSecondIface TestSecondIface = { &TestSecondIfaceVtbl };
 
+static HRESULT WINAPI TestSecondDisp_QueryInterface(ITestSecondDisp *iface, REFIID riid, void **ppv)
+{
+    return ItestDual_QueryInterface(&TestDual, riid, ppv);
+}
+
+static ULONG WINAPI TestSecondDisp_AddRef(ITestSecondDisp *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI TestSecondDisp_Release(ITestSecondDisp *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI TestSecondDisp_GetTypeInfoCount(ITestSecondDisp *iface, UINT *pctinfo)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TestSecondDisp_GetTypeInfo(ITestSecondDisp *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TestSecondDisp_GetIDsOfNames(ITestSecondDisp *iface, REFIID riid, LPOLESTR *rgszNames,
+        UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TestSecondDisp_Invoke(ITestSecondDisp *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
+        WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
+        UINT *puArgErr)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TestSecondDisp_test(ITestSecondDisp *iface)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static ITestSecondDispVtbl TestSecondDispVtbl = {
+    TestSecondDisp_QueryInterface,
+    TestSecondDisp_AddRef,
+    TestSecondDisp_Release,
+    TestSecondDisp_GetTypeInfoCount,
+    TestSecondDisp_GetTypeInfo,
+    TestSecondDisp_GetIDsOfNames,
+    TestSecondDisp_Invoke,
+    TestSecondDisp_test
+};
+
+static ITestSecondDisp TestSecondDisp = { &TestSecondDispVtbl };
+
 static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, void **ppvObject)
 {
     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) {
@@ -202,6 +315,13 @@ static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, voi
     }else if(IsEqualGUID(riid, &IID_ITestSecondIface)) {
         *ppvObject = &TestSecondIface;
         return S_OK;
+    }else if(IsEqualGUID(riid, &IID_ITestSecondDisp)) {
+        *ppvObject = &TestSecondDisp;
+        return S_OK;
+    }else if (IsEqualGUID(riid, &IID_IExternalConnection)) {
+        trace("QI external connection\n");
+        *ppvObject = &ExternalConnection;
+        return S_OK;
     }
 
     *ppvObject = NULL;
@@ -884,7 +1004,7 @@ static ITypeInfo *get_type_info(REFIID riid)
     ITypeLib *pTypeLib;
     HRESULT hr;
 
-    hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &pTypeLib);
+    hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
     ok_ole_success(hr, LoadRegTypeLib);
     if (FAILED(hr))
         return NULL;
@@ -1067,7 +1187,7 @@ static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
 {
     ITypeLib *pTypeLib;
-    HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &pTypeLib);
+    HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
     ok_ole_success(hr, LoadRegTypeLib);
     if (SUCCEEDED(hr))
     {
@@ -1696,7 +1816,7 @@ static void test_libattr(void)
     HRESULT hr;
     TLIBATTR *pattr;
 
-    hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &pTypeLib);
+    hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
     ok_ole_success(hr, LoadRegTypeLib);
     if (FAILED(hr))
         return;
@@ -1713,6 +1833,112 @@ static void test_libattr(void)
     ITypeLib_Release(pTypeLib);
 }
 
+static void test_external_connection(void)
+{
+    IStream *stream, *stream2;
+    ITestSecondDisp *second;
+    ItestDual *iface;
+    HANDLE thread;
+    DWORD tid;
+    HRESULT hres;
+
+    static const LARGE_INTEGER zero;
+
+    trace("Testing IExternalConnection...\n");
+
+    external_connections = 0;
+
+    /* Marshaling an interface increases external connection count. */
+    expect_last_release_closes = FALSE;
+    hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
+    tid = start_host_object(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHLFLAGS_NORMAL, &thread);
+    ok(external_connections == 1, "external_connections = %d\n", external_connections);
+
+    IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
+    hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
+    ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
+    ok(external_connections == 1, "external_connections = %d\n", external_connections);
+
+    IStream_Release(stream);
+    ok(external_connections == 1, "external_connections = %d\n", external_connections);
+
+    /* Creating a stub for new iface causes new external connection. */
+    hres = ItestDual_QueryInterface(iface, &IID_ITestSecondDisp, (void**)&second);
+    ok(hres == S_OK, "Could not get ITestSecondDisp iface: %08x\n", hres);
+    todo_wine
+    ok(external_connections == 2, "external_connections = %d\n", external_connections);
+
+    ITestSecondDisp_Release(second);
+    todo_wine
+    ok(external_connections == 2, "external_connections = %d\n", external_connections);
+
+    expect_last_release_closes = TRUE;
+    ItestDual_Release(iface);
+    ok(external_connections == 0, "external_connections = %d\n", external_connections);
+
+    end_host_object(tid, thread);
+
+    /* A test with direct CoMarshalInterface call. */
+    hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
+
+    expect_last_release_closes = FALSE;
+    hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+    ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
+    ok(external_connections == 1, "external_connections = %d\n", external_connections);
+
+    expect_last_release_closes = TRUE;
+    IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
+    hres = CoReleaseMarshalData(stream);
+    ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
+    ok(external_connections == 0, "external_connections = %d\n", external_connections);
+
+    /* Two separated marshal data are still one external connection. */
+    hres = CreateStreamOnHGlobal(NULL, TRUE, &stream2);
+    ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
+
+    expect_last_release_closes = FALSE;
+    IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
+    hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+    ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
+    ok(external_connections == 1, "external_connections = %d\n", external_connections);
+
+    hres = CoMarshalInterface(stream2, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
+    ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
+    ok(external_connections == 1, "external_connections = %d\n", external_connections);
+
+    IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
+    hres = CoReleaseMarshalData(stream);
+    ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
+    ok(external_connections == 1, "external_connections = %d\n", external_connections);
+
+    expect_last_release_closes = TRUE;
+    IStream_Seek(stream2, zero, STREAM_SEEK_SET, NULL);
+    hres = CoReleaseMarshalData(stream2);
+    ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
+    ok(external_connections == 0, "external_connections = %d\n", external_connections);
+
+    /* Weak table marshaling does not increment external connections */
+    hres = CreateStreamOnHGlobal(NULL, TRUE, &stream);
+    ok(hres == S_OK, "CreateStreamOnHGlobal failed: %08x\n", hres);
+
+    hres = CoMarshalInterface(stream, &IID_ItestDual, (IUnknown*)&TestDual, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
+    ok(hres == S_OK, "CoMarshalInterface failed: %08x\n", hres);
+    ok(external_connections == 0, "external_connections = %d\n", external_connections);
+
+    IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
+    hres = CoUnmarshalInterface(stream, &IID_ItestDual, (void**)&iface);
+    ok(hres == S_OK, "CoUnmarshalInterface failed: %08x\n", hres);
+    ok(external_connections == 0, "external_connections = %d\n", external_connections);
+    ItestDual_Release(iface);
+
+    IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
+    hres = CoReleaseMarshalData(stream);
+    ok(hres == S_OK, "CoReleaseMarshalData failed: %08x\n", hres);
+    ok(external_connections == 0, "external_connections = %d\n", external_connections);
+}
+
 START_TEST(tmarshal)
 {
     HRESULT hr;
@@ -1733,8 +1959,9 @@ START_TEST(tmarshal)
     test_DispCallFunc();
     test_StaticWidget();
     test_libattr();
+    test_external_connection();
 
-    hr = UnRegisterTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL,
+    hr = UnRegisterTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL,
                            sizeof(void*) == 8 ? SYS_WIN64 : SYS_WIN32);
     ok_ole_success(hr, UnRegisterTypeLib);
 
index a421011..92b5435 100644 (file)
@@ -22,7 +22,7 @@ import "ocidl.idl";
 
 [
   uuid(d96d8a3e-78b6-4c8d-8f27-059db959be8a),
-  version(1.0),
+  version(2.5),
   helpstring("Test Typelib")
 ]
 library TestTypelib
@@ -73,6 +73,17 @@ library TestTypelib
         HRESULT test();
     }
 
+    [
+        odl,
+        oleautomation,
+        dual,
+        uuid(3f7e06fe-0bce-46f0-8b7d-3a68393c7969)
+    ]
+    interface ITestSecondDisp : IDispatch
+    {
+        HRESULT test();
+    }
+
     [
         odl,
         uuid(a1f8cae3-c947-4c5f-b57d-c87b9b5f3586),
index 6129ae6..bb99aa6 100644 (file)
 
 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
 
+#ifdef __i386__
+#define ARCH "x86"
+#elif defined __x86_64__
+#define ARCH "amd64"
+#else
+#define ARCH "none"
+#endif
+
 static HRESULT (WINAPI *pRegisterTypeLibForUser)(ITypeLib*,OLECHAR*,OLECHAR*);
 static HRESULT (WINAPI *pUnRegisterTypeLibForUser)(REFGUID,WORD,WORD,LCID,SYSKIND);
 
+static BOOL   (WINAPI *pActivateActCtx)(HANDLE,ULONG_PTR*);
+static HANDLE (WINAPI *pCreateActCtxW)(PCACTCTXW);
+static BOOL   (WINAPI *pDeactivateActCtx)(DWORD,ULONG_PTR);
+static VOID   (WINAPI *pReleaseActCtx)(HANDLE);
+
 static const WCHAR wszStdOle2[] = {'s','t','d','o','l','e','2','.','t','l','b',0};
 static WCHAR wszGUID[] = {'G','U','I','D',0};
 static WCHAR wszguid[] = {'g','u','i','d',0};
@@ -143,9 +156,14 @@ static IInvokeTest invoketest = { &invoketestvtbl };
 static void init_function_pointers(void)
 {
     HMODULE hmod = GetModuleHandleA("oleaut32.dll");
+    HMODULE hk32 = GetModuleHandleA("kernel32.dll");
 
     pRegisterTypeLibForUser = (void *)GetProcAddress(hmod, "RegisterTypeLibForUser");
     pUnRegisterTypeLibForUser = (void *)GetProcAddress(hmod, "UnRegisterTypeLibForUser");
+    pActivateActCtx = (void *)GetProcAddress(hk32, "ActivateActCtx");
+    pCreateActCtxW = (void *)GetProcAddress(hk32, "CreateActCtxW");
+    pDeactivateActCtx = (void *)GetProcAddress(hk32, "DeactivateActCtx");
+    pReleaseActCtx = (void *)GetProcAddress(hk32, "ReleaseActCtx");
 }
 
 static void ref_count_test(LPCWSTR type_lib)
@@ -610,24 +628,30 @@ static void test_CreateDispTypeInfo(void)
     SysFreeString(methdata[3].szName);
 }
 
-static const char *create_test_typelib(int res_no)
+static void write_typelib(int res_no, const char *filename)
 {
-    static char filename[MAX_PATH];
+    DWORD written;
     HANDLE file;
     HRSRC res;
     void *ptr;
-    DWORD written;
 
-    GetTempFileNameA( ".", "tlb", 0, filename );
     file = CreateFile( 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 NULL;
+    if (file == INVALID_HANDLE_VALUE) return;
     res = FindResource( GetModuleHandle(0), 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" );
     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;
 }
 
@@ -1217,7 +1241,7 @@ static void test_QueryPathOfRegTypeLib(DWORD arch)
 
     for (i = 0; i < sizeof(td)/sizeof(td[0]); i++)
     {
-        ret = QueryPathOfRegTypeLib(&uid, td[i].maj, td[i].min, 0, &path);
+        ret = QueryPathOfRegTypeLib(&uid, td[i].maj, td[i].min, LOCALE_NEUTRAL, &path);
         ok(ret == td[i].ret, "QueryPathOfRegTypeLib(%u.%u) returned %08x\n", td[i].maj, td[i].min, ret);
         if (ret == S_OK)
         {
@@ -1504,7 +1528,7 @@ if(use_midl_tlb) {
     return;
 }
 
-static void test_CreateTypeLib(void) {
+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};
@@ -1521,11 +1545,14 @@ static void test_CreateTypeLib(void) {
     static OLECHAR param1W[] = {'p','a','r','a','m','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 *names1[] = {func1W, param1W, param2W};
     static OLECHAR *names2[] = {func2W, param1W, param2W};
     static OLECHAR *propname[] = {prop1W, param1W};
     static const GUID custguid = {0xbf611abe,0x5b38,0x11df,{0x91,0x5c,0x08,0x02,0x79,0x79,0x94,0x70}};
     static const GUID bogusguid = {0xbf611abe,0x5b38,0x11df,{0x91,0x5c,0x08,0x02,0x79,0x79,0x94,0x71}};
+    static const GUID interfaceguid = {0x3b9ff02f,0x9675,0x4861,{0xb7,0x81,0xce,0xae,0xa4,0x78,0x2a,0xcc}};
+    static const GUID interface2guid = {0x3b9ff02f,0x9675,0x4861,{0xb7,0x81,0xce,0xae,0xa4,0x78,0x2a,0xcd}};
 
     char filename[MAX_PATH];
     WCHAR filenameW[MAX_PATH];
@@ -1542,13 +1569,29 @@ static void test_CreateTypeLib(void) {
     TYPEATTR *typeattr;
     TLIBATTR *libattr;
     HREFTYPE hreftype;
-    BSTR name, docstring, helpfile;
-    DWORD helpcontext;
+    BSTR name, docstring, helpfile, names[3];
+    DWORD helpcontext, ptr_size, alignment;
     int impltypeflags;
+    unsigned int cnames;
     VARIANT cust_data;
     HRESULT hres;
     TYPEKIND kind;
 
+    switch(sys){
+    case SYS_WIN32:
+        trace("testing SYS_WIN32\n");
+        ptr_size = 4;
+        alignment = sizeof(void*);
+        break;
+    case SYS_WIN64:
+        trace("testing SYS_WIN64\n");
+        ptr_size = 8;
+        alignment = 4;
+        break;
+    default:
+        return;
+    }
+
     trace("CreateTypeLib tests\n");
 
     hres = LoadTypeLib(stdoleW, &stdole);
@@ -1557,13 +1600,18 @@ static void test_CreateTypeLib(void) {
     hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IUnknown, &unknown);
     ok(hres == S_OK, "got %08x\n", hres);
 
+    hres = ITypeInfo_GetTypeAttr(unknown, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeVft == 3 * sizeof(void*), "Got wrong cbSizeVft: %u\n", typeattr->cbSizeVft);
+    ITypeInfo_ReleaseTypeAttr(unknown, typeattr);
+
     hres = ITypeLib_GetTypeInfoOfGuid(stdole, &IID_IDispatch, &dispatch);
     ok(hres == S_OK, "got %08x\n", hres);
 
     GetTempFileNameA(".", "tlb", 0, filename);
     MultiByteToWideChar(CP_ACP, 0, filename, -1, filenameW, MAX_PATH);
 
-    hres = CreateTypeLib2(SYS_WIN32, filenameW, &createtl);
+    hres = CreateTypeLib2(sys, filenameW, &createtl);
     ok(hres == S_OK, "got %08x\n", hres);
 
     hres = ICreateTypeLib2_QueryInterface(createtl, &IID_ITypeLib, (void**)&tl);
@@ -1587,7 +1635,7 @@ static void test_CreateTypeLib(void) {
     hres = ITypeLib_GetLibAttr(tl, &libattr);
     ok(hres == S_OK, "got %08x\n", hres);
 
-    ok(libattr->syskind == SYS_WIN32, "syskind = %d\n", libattr->syskind);
+    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);
     ok(libattr->wLibFlags == 0, "wLibFlags = %d\n", libattr->wLibFlags);
@@ -1668,6 +1716,9 @@ static void test_CreateTypeLib(void) {
     hres = ICreateTypeInfo_LayOut(createti);
     ok(hres == S_OK, "got %08x\n", hres);
 
+    hres = ICreateTypeInfo_SetGuid(createti, &interfaceguid);
+    ok(hres == S_OK, "got %08x\n", hres);
+
     hres = ICreateTypeInfo_AddRefTypeInfo(createti, NULL, &hreftype);
     ok(hres == E_INVALIDARG, "got %08x\n", hres);
 
@@ -1691,6 +1742,17 @@ static void test_CreateTypeLib(void) {
     ok(hres == S_OK, "got %08x\n", hres);
     ok(hreftype == 3, "hreftype = %d\n", hreftype);
 
+    hres = ITypeInfo_GetRefTypeInfo(interface1, hreftype, &ti);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeVft == 3 * ptr_size || broken(sys == SYS_WIN32 && typeattr->cbSizeVft == 24) /* xp64 */,
+            "retrieved IUnknown gave wrong cbSizeVft: %u\n", typeattr->cbSizeVft);
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+    ITypeInfo_Release(ti);
+
     hres = ITypeInfo_GetRefTypeOfImplType(interface1, -1, &hreftype);
     ok(hres == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hres);
 
@@ -1729,8 +1791,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 0, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 12 ||
-            broken(pfuncdesc->oVft == 24) /* xp64 */,
+    ok(pfuncdesc->oVft == 3 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 24) /* xp64 */,
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_BSTR, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -1790,8 +1851,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 16 ||
-            broken(pfuncdesc->oVft == 28) /* xp64 */,
+    ok(pfuncdesc->oVft == 4 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 28) /* xp64 */,
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -1832,8 +1892,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 0, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 16 ||
-            broken(pfuncdesc->oVft == 28), /* xp64 */
+    ok(pfuncdesc->oVft == 4 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 28), /* xp64 */
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -1864,8 +1923,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 28 ||
-            broken(pfuncdesc->oVft == 40) /* xp64 */,
+    ok(pfuncdesc->oVft == 7 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 40) /* xp64 */,
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -1897,8 +1955,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 28 ||
-            broken(pfuncdesc->oVft == 40) /* xp64 */,
+    ok(pfuncdesc->oVft == 7 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 40) /* xp64 */,
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -1934,8 +1991,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 24 ||
-            broken(pfuncdesc->oVft == 36) /* xp64 */,
+    ok(pfuncdesc->oVft == 6 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 36) /* xp64 */,
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -1976,8 +2032,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 2, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 24 ||
-            broken(pfuncdesc->oVft == 36) /* xp64 */,
+    ok(pfuncdesc->oVft == 6 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 36) /* xp64 */,
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -2028,8 +2083,7 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 2, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 24 ||
-            broken(pfuncdesc->oVft == 36) /* xp64 */,
+    ok(pfuncdesc->oVft == 6 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 36) /* xp64 */,
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
@@ -2063,8 +2117,10 @@ static void test_CreateTypeLib(void) {
 
     elemdesc[0].tdesc.vt = VT_USERDEFINED;
     U(elemdesc[0].tdesc).hreftype = hreftype;
-    U(elemdesc[0]).paramdesc.pparamdescex = NULL;
-    U(elemdesc[0]).paramdesc.wParamFlags = 0;
+    U(elemdesc[0]).paramdesc.pparamdescex = &paramdescex;
+    U(elemdesc[0]).paramdesc.wParamFlags = PARAMFLAG_FHASDEFAULT;
+    V_VT(&paramdescex.varDefaultValue) = VT_INT;
+    V_INT(&paramdescex.varDefaultValue) = 0x789;
 
     funcdesc.lprgelemdescParam = elemdesc;
     funcdesc.invkind = INVOKE_FUNC;
@@ -2085,18 +2141,65 @@ static void test_CreateTypeLib(void) {
     ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
     ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
     ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
-    todo_wine ok(pfuncdesc->oVft == 32 ||
-            broken(pfuncdesc->oVft == 44), /* xp64 */
+    ok(pfuncdesc->oVft == 8 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 44), /* xp64 */
             "got %d\n", pfuncdesc->oVft);
     ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
     ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
     ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
 
     edesc = pfuncdesc->lprgelemdescParam;
-    ok(U(*edesc).paramdesc.pparamdescex == NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
-    ok(U(*edesc).paramdesc.wParamFlags == 0, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
     ok(edesc->tdesc.vt == VT_USERDEFINED, "got: %d\n", edesc->tdesc.vt);
     ok(U(edesc->tdesc).hreftype == hreftype, "got: 0x%x\n", U(edesc->tdesc).hreftype);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_INT, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_INT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0x789, "got: %d\n",
+            V_INT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+
+    ITypeInfo2_ReleaseFuncDesc(ti2, pfuncdesc);
+
+    elemdesc[0].tdesc.vt = VT_VARIANT;
+    U(elemdesc[0]).paramdesc.pparamdescex = &paramdescex;
+    U(elemdesc[0]).paramdesc.wParamFlags = PARAMFLAG_FHASDEFAULT;
+    V_VT(&paramdescex.varDefaultValue) = VT_INT;
+    V_INT(&paramdescex.varDefaultValue) = 3;
+
+    funcdesc.lprgelemdescParam = elemdesc;
+    funcdesc.invkind = INVOKE_FUNC;
+    funcdesc.cParams = 1;
+    funcdesc.elemdescFunc.tdesc.vt = VT_VARIANT;
+
+    hres = ICreateTypeInfo_AddFuncDesc(createti, 6, &funcdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo2_GetFuncDesc(ti2, 6, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    ok(pfuncdesc->memid == 0x60010006, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+    ok(pfuncdesc->oVft == 9 * ptr_size || broken(sys == SYS_WIN32 && pfuncdesc->oVft == 48), /* xp64 */
+            "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VARIANT, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(edesc->tdesc.vt == VT_VARIANT, "got: %d\n", edesc->tdesc.vt);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_INT, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_INT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 3, "got: %d\n",
+            V_INT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
 
     ITypeInfo2_ReleaseFuncDesc(ti2, pfuncdesc);
 
@@ -2145,6 +2248,9 @@ static void test_CreateTypeLib(void) {
     hres = ICreateTypeLib2_CreateTypeInfo(createtl, interface2W, TKIND_INTERFACE, &createti);
     ok(hres == S_OK, "got %08x\n", hres);
 
+    hres = ICreateTypeInfo_SetGuid(createti, &interface2guid);
+    ok(hres == S_OK, "got %08x\n", hres);
+
     hres = ICreateTypeInfo_QueryInterface(createti, &IID_ITypeInfo, (void**)&interface2);
     ok(hres == S_OK, "got %08x\n", hres);
 
@@ -2180,12 +2286,41 @@ static void test_CreateTypeLib(void) {
     hres = ITypeInfo_GetImplTypeFlags(interface2, 1, &impltypeflags);
     ok(hres == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hres);
 
+    funcdesc.elemdescFunc.tdesc.vt = VT_VOID;
     funcdesc.oVft = 0xaaac;
     hres = ICreateTypeInfo_AddFuncDesc(createti, 0, &funcdesc);
+    if(sys == SYS_WIN64){
+        ok(hres == E_INVALIDARG, "got %08x\n", hres);
+        funcdesc.oVft = 0xaab0;
+        hres = ICreateTypeInfo_AddFuncDesc(createti, 0, &funcdesc);
+    }
     ok(hres == S_OK, "got %08x\n", hres);
     funcdesc.oVft = 0xaaa8;
     hres = ICreateTypeInfo_AddFuncDesc(createti, 0, &funcdesc);
     ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ICreateTypeInfo_QueryInterface(createti, &IID_ITypeInfo, (void**)&ti2);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo2_GetFuncDesc(ti2, 0, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    ok(pfuncdesc->memid == 0x60020000, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+    ok(pfuncdesc->oVft == (short)0xaaa8, "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    ITypeInfo2_ReleaseFuncDesc(ti2, pfuncdesc);
+    ITypeInfo2_Release(ti2);
+
     funcdesc.oVft = 0;
 
     ICreateTypeInfo_Release(createti);
@@ -2365,12 +2500,12 @@ static void test_CreateTypeLib(void) {
 
     hres = ITypeInfo_GetTypeAttr(dual, &typeattr);
     ok(hres == S_OK, "got %08x\n", hres);
-    ok(typeattr->cbSizeInstance == 4, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->cbSizeInstance == ptr_size, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
     ok(typeattr->typekind == 3, "typekind = %d\n", typeattr->typekind);
     ok(typeattr->cFuncs == 1, "cFuncs = %d\n", typeattr->cFuncs);
     ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
     ok(typeattr->cImplTypes == 1, "cImplTypes = %d\n", typeattr->cImplTypes);
-    ok(typeattr->cbSizeVft == 32 || broken(typeattr->cbSizeVft == 7 * sizeof(void *) + 4), /* xp64 */
+    ok(typeattr->cbSizeVft == 8 * ptr_size || broken(sys == SYS_WIN32 && typeattr->cbSizeVft == 7 * sizeof(void *) + 4), /* xp64 */
        "cbSizeVft = %d\n", typeattr->cbSizeVft);
     ok(typeattr->cbAlignment == 4, "cbAlignment = %d\n", typeattr->cbAlignment);
     ok(typeattr->wTypeFlags == (TYPEFLAG_FDISPATCHABLE|TYPEFLAG_FDUAL), "wTypeFlags = %d\n", typeattr->wTypeFlags);
@@ -2388,7 +2523,7 @@ static void test_CreateTypeLib(void) {
 
     hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
     ok(hres == S_OK, "got %08x\n", hres);
-    ok(typeattr->cbSizeInstance == 4, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->cbSizeInstance == ptr_size, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
     ok(typeattr->typekind == 4, "typekind = %d\n", typeattr->typekind);
     ok(typeattr->cFuncs == 8, "cFuncs = %d\n", typeattr->cFuncs);
     ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
@@ -2403,16 +2538,19 @@ static void test_CreateTypeLib(void) {
 
     ITypeInfo_Release(ti);
 
+    hres = ICreateTypeInfo_SetTypeDescAlias(createti, &typedesc1);
+    ok(hres == TYPE_E_BADMODULEKIND, "got %08x\n", hres);
+
     ICreateTypeInfo_Release(createti);
 
     hres = ITypeInfo_GetTypeAttr(interface1, &typeattr);
     ok(hres == S_OK, "got %08x\n", hres);
-    ok(typeattr->cbSizeInstance == 4, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->cbSizeInstance == ptr_size, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
     ok(typeattr->typekind == 3, "typekind = %d\n", typeattr->typekind);
-    ok(typeattr->cFuncs == 12, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cFuncs == 13, "cFuncs = %d\n", typeattr->cFuncs);
     ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
     ok(typeattr->cImplTypes == 1, "cImplTypes = %d\n", typeattr->cImplTypes);
-    ok(typeattr->cbSizeVft == 60 || broken(typeattr->cbSizeVft == 3 * sizeof(void *) + 48), /* xp64 */
+    ok(typeattr->cbSizeVft == 16 * ptr_size || broken(sys == SYS_WIN32 && typeattr->cbSizeVft == 3 * sizeof(void *) + 52), /* xp64 */
        "cbSizeVft = %d\n", typeattr->cbSizeVft);
     ok(typeattr->cbAlignment == 4, "cbAlignment = %d\n", typeattr->cbAlignment);
     ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
@@ -2423,12 +2561,14 @@ static void test_CreateTypeLib(void) {
 
     hres = ITypeInfo_GetTypeAttr(interface2, &typeattr);
     ok(hres == S_OK, "got %08x\n", hres);
-    ok(typeattr->cbSizeInstance == 4, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->cbSizeInstance == ptr_size, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
     ok(typeattr->typekind == 3, "typekind = %d\n", typeattr->typekind);
     ok(typeattr->cFuncs == 2, "cFuncs = %d\n", typeattr->cFuncs);
     ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
     ok(typeattr->cImplTypes == 1, "cImplTypes = %d\n", typeattr->cImplTypes);
-    ok(typeattr->cbSizeVft == 43696, "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok((sys == SYS_WIN32 && typeattr->cbSizeVft == 0xaab0) ||
+            (sys == SYS_WIN64 && typeattr->cbSizeVft == 0xaab8),
+            "cbSizeVft = 0x%x\n", typeattr->cbSizeVft);
     ok(typeattr->cbAlignment == 4, "cbAlignment = %d\n", typeattr->cbAlignment);
     ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
     ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
@@ -2436,12 +2576,82 @@ static void test_CreateTypeLib(void) {
 
     ITypeInfo_ReleaseTypeAttr(interface2, typeattr);
 
-    hres = ICreateTypeLib2_SaveAllChanges(createtl);
-    ok(hres == S_OK, "got %08x\n", hres);
-
     ok(ITypeInfo_Release(interface2)==0, "Object should be freed\n");
     ok(ITypeInfo_Release(interface1)==0, "Object should be freed\n");
     ok(ITypeInfo_Release(dual)==0, "Object should be freed\n");
+
+    hres = ICreateTypeLib2_CreateTypeInfo(createtl, aliasW, TKIND_ALIAS, &createti);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ICreateTypeInfo_QueryInterface(createti, &IID_ITypeInfo, (void**)&interface1);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    if(0){
+        /* windows gives invalid values here, and even breaks the typeinfo permanently
+         * on winxp. only call GetTypeAttr() on a TKIND_ALIAS after SetTypeDescAlias. */
+        hres = ITypeInfo_GetTypeAttr(interface1, &typeattr);
+        ok(hres == S_OK, "got %08x\n", hres);
+        ok(typeattr->cbSizeInstance == 0xffffffb4, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+        ok(typeattr->typekind == TKIND_ALIAS, "typekind = %d\n", typeattr->typekind);
+        ok(typeattr->cFuncs == 0, "cFuncs = %d\n", typeattr->cFuncs);
+        ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+        ok(typeattr->cImplTypes == 0, "cImplTypes = %d\n", typeattr->cImplTypes);
+        ok(typeattr->cbSizeVft == 0, "cbSizeVft = %d\n", typeattr->cbSizeVft);
+        ok(typeattr->cbAlignment == 0, "cbAlignment = %d\n", typeattr->cbAlignment);
+        ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
+        ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+        ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+        ok(typeattr->tdescAlias.vt == VT_EMPTY, "Got wrong tdescAlias.vt: %u\n", typeattr->tdescAlias.vt);
+        ITypeInfo_ReleaseTypeAttr(interface1, typeattr);
+    }
+
+    hres = ICreateTypeInfo_SetTypeDescAlias(createti, NULL);
+    ok(hres == E_INVALIDARG, "got %08x\n", hres);
+
+    typedesc1.vt = VT_I1;
+    hres = ICreateTypeInfo_SetTypeDescAlias(createti, &typedesc1);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(interface1, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == 1, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_ALIAS, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 0, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 0, "cImplTypes = %d\n", typeattr->cImplTypes);
+    ok(typeattr->cbSizeVft == 0, "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == 1, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ok(typeattr->tdescAlias.vt == VT_I1, "Got wrong tdescAlias.vt: %u\n", typeattr->tdescAlias.vt);
+    ITypeInfo_ReleaseTypeAttr(interface1, typeattr);
+
+    typedesc1.vt = VT_R8;
+    hres = ICreateTypeInfo_SetTypeDescAlias(createti, &typedesc1);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(interface1, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == 8, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_ALIAS, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 0, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 0, "cImplTypes = %d\n", typeattr->cImplTypes);
+    ok(typeattr->cbSizeVft == 0, "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == 4, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ok(typeattr->tdescAlias.vt == VT_R8, "Got wrong tdescAlias.vt: %u\n", typeattr->tdescAlias.vt);
+    ITypeInfo_ReleaseTypeAttr(interface1, typeattr);
+
+    ITypeInfo_Release(interface1);
+    ICreateTypeInfo_Release(createti);
+
+    hres = ICreateTypeLib2_SaveAllChanges(createtl);
+    ok(hres == S_OK, "got %08x\n", hres);
+
     ok(ICreateTypeLib2_Release(createtl)==0, "Object should be freed\n");
 
     ok(ITypeInfo_Release(dispatch)==0, "Object should be freed\n");
@@ -2450,102 +2660,942 @@ static void test_CreateTypeLib(void) {
 
     hres = LoadTypeLibEx(filenameW, REGKIND_NONE, &tl);
     ok(hres == S_OK, "got %08x\n", hres);
-    ok(ITypeLib_Release(tl)==0, "Object should be freed\n");
 
-    DeleteFileA(filename);
-}
+    hres = ITypeLib_GetLibAttr(tl, &libattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    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);
+    ITypeLib_ReleaseTLibAttr(tl, libattr);
 
-#if 0       /* use this to generate more tests */
+    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",
+            wine_dbgstr_w(name));
+    ok(docstring == NULL, "got wrong docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got wrong helpcontext: 0x%x\n", helpcontext);
+    ok(memcmp(helpfileW, helpfile, sizeof(helpfileW)) == 0,
+            "got wrong helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(name);
+    SysFreeString(helpfile);
 
-#define OLE_CHECK(x) { HRESULT hr = x; if (FAILED(hr)) { printf(#x "failed - %x\n", hr); return; } }
+    hres = ITypeLib_GetDocumentation(tl, 0, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(memcmp(interface1W, name, sizeof(interface1W)) == 0, "got wrong typeinfo name: %s\n",
+            wine_dbgstr_w(name));
+    ok(docstring == NULL, "got wrong docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got wrong helpcontext: 0x%x\n", helpcontext);
+    ok(memcmp(helpfileW, helpfile, sizeof(helpfileW)) == 0,
+            "got wrong helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(name);
+    SysFreeString(helpfile);
 
-static char *dump_string(LPWSTR wstr)
-{
-    int size = lstrlenW(wstr)+3;
-    char *out = CoTaskMemAlloc(size);
-    WideCharToMultiByte(20127, 0, wstr, -1, out+1, size, NULL, NULL);
-    out[0] = '\"';
-    strcat(out, "\"");
-    return out;
-}
+    hres = ITypeLib_GetTypeInfo(tl, 0, &ti);
+    ok(hres == S_OK, "got %08x\n", hres);
 
-struct map_entry
-{
-    DWORD value;
-    const char *name;
-};
+    hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == sizeof(void*), "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_INTERFACE, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 13, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 1, "cImplTypes = %d\n", typeattr->cImplTypes);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(typeattr->cbSizeVft == 16 * sizeof(void*), "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    else
+#endif
+        ok(typeattr->cbSizeVft == 16 * sizeof(void*), "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == alignment, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
 
-#define MAP_ENTRY(x) { x, #x }
-static const struct map_entry tkind_map[] = {
-    MAP_ENTRY(TKIND_ENUM),
-    MAP_ENTRY(TKIND_RECORD),
-    MAP_ENTRY(TKIND_MODULE),
-    MAP_ENTRY(TKIND_INTERFACE),
-    MAP_ENTRY(TKIND_DISPATCH),
-    MAP_ENTRY(TKIND_COCLASS),
-    MAP_ENTRY(TKIND_ALIAS),
-    MAP_ENTRY(TKIND_UNION),
-    MAP_ENTRY(TKIND_MAX),
-    {0, NULL}
-};
+    hres = ITypeInfo_GetRefTypeOfImplType(ti, 0, &hreftype);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(hreftype == 3, "hreftype = %d\n", hreftype);
 
-static const struct map_entry funckind_map[] = {
-    MAP_ENTRY(FUNC_VIRTUAL),
-    MAP_ENTRY(FUNC_PUREVIRTUAL),
-    MAP_ENTRY(FUNC_NONVIRTUAL),
-    MAP_ENTRY(FUNC_STATIC),
-    MAP_ENTRY(FUNC_DISPATCH),
-    {0, NULL}
-};
+    hres = ITypeInfo_GetRefTypeInfo(ti, hreftype, &unknown);
+    ok(hres == S_OK, "got %08x\n", hres);
 
-static const struct map_entry invkind_map[] = {
-    MAP_ENTRY(INVOKE_FUNC),
-    MAP_ENTRY(INVOKE_PROPERTYGET),
-    MAP_ENTRY(INVOKE_PROPERTYPUT),
-    MAP_ENTRY(INVOKE_PROPERTYPUTREF),
-    {0, NULL}
-};
+    hres = ITypeInfo_GetTypeAttr(unknown, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(IsEqualGUID(&typeattr->guid, &IID_IUnknown), "got wrong reftypeinfo\n");
+    ITypeInfo_ReleaseTypeAttr(unknown, typeattr);
 
-#undef MAP_ENTRY
+    ITypeInfo_Release(unknown);
 
-static const char *map_value(DWORD val, const struct map_entry *map)
-{
-    static int map_id;
-    static char bufs[16][256];
-    char *buf;
+    hres = ITypeInfo_GetFuncDesc(ti, 0, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_PROPERTYPUTREF, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_BSTR, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).idldesc.wIDLFlags == IDLFLAG_FIN, "got: %x\n", U(*edesc).idldesc.wIDLFlags);
 
-    while (map->name)
-    {
-        if (map->value == val)
-            return map->name;
-        map++;
-    }
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(!memcmp(name, func1W, sizeof(func1W)), "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0x201, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(name);
+    SysFreeString(helpfile);
 
-    buf = bufs[(map_id++)%16];
-    sprintf(buf, "0x%x", val);
-    return buf;
-}
+    hres = ITypeInfo_GetNames(ti, pfuncdesc->memid, NULL, 0, &cnames);
+    ok(hres == E_INVALIDARG, "got: %08x\n", hres);
 
-static void test_dump_typelib(const char *name)
-{
-    WCHAR wszString[260];
-    ITypeInfo *info;
-    ITypeLib *lib;
-    int count;
-    int i;
+    cnames = 8;
+    hres = ITypeInfo_GetNames(ti, pfuncdesc->memid, names, 0, &cnames);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(cnames == 0, "got: %u\n", cnames);
 
-    MultiByteToWideChar(CP_ACP, 0, name, -1, wszString, 260);
-    OLE_CHECK(LoadTypeLib(wszString, &lib));
-    count = ITypeLib_GetTypeInfoCount(lib);
-    printf("/* interfaces count: %d */\n", count);
-    for (i = 0; i < count; i++)
-    {
-        TYPEATTR *attr;
-        BSTR name;
-        int f = 0;
+    hres = ITypeInfo_GetNames(ti, pfuncdesc->memid, names, sizeof(names) / sizeof(*names), &cnames);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(cnames == 1, "got: %u\n", cnames);
+    ok(!memcmp(names[0], func1W, sizeof(func1W)), "got names[0]: %s\n", wine_dbgstr_w(names[0]));
+    SysFreeString(names[0]);
 
-        OLE_CHECK(ITypeLib_GetDocumentation(lib, i, &name, NULL, NULL, NULL));
-        printf("{\n"
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 1, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60010001, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam == NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 0, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 4 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 4 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 2, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x1, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam == NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 0, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 5 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 5 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 3, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x6001000b, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 2, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 6 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 6 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_BSTR, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_BSTR, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(!lstrcmpW(V_BSTR(&U(*edesc).paramdesc.pparamdescex->varDefaultValue), defaultQW),
+            "got: %s\n",
+            wine_dbgstr_w(V_BSTR(&U(*edesc).paramdesc.pparamdescex->varDefaultValue)));
+
+    edesc = pfuncdesc->lprgelemdescParam + 1;
+    ok(edesc->tdesc.vt == VT_BSTR, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_BSTR, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(!lstrcmpW(V_BSTR(&U(*edesc).paramdesc.pparamdescex->varDefaultValue), defaultQW),
+            "got: %s\n",
+            wine_dbgstr_w(V_BSTR(&U(*edesc).paramdesc.pparamdescex->varDefaultValue)));
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(!memcmp(name, func2W, sizeof(func2W)), "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(name);
+    SysFreeString(helpfile);
+
+    hres = ITypeInfo_GetNames(ti, pfuncdesc->memid, names, sizeof(names) / sizeof(*names), &cnames);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(cnames == 3, "got: %u\n", cnames);
+    ok(!memcmp(names[0], func2W, sizeof(func2W)), "got names[0]: %s\n", wine_dbgstr_w(names[0]));
+    ok(!memcmp(names[1], param1W, sizeof(func2W)), "got names[1]: %s\n", wine_dbgstr_w(names[1]));
+    ok(!memcmp(names[2], param2W, sizeof(func2W)), "got names[2]: %s\n", wine_dbgstr_w(names[2]));
+    SysFreeString(names[0]);
+    SysFreeString(names[1]);
+    SysFreeString(names[2]);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 4, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x6001000c, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 2, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 7 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 7 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_INT, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_I4, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_I4(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0xFFFFFFFF,
+            "got: 0x%x\n", V_I4(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+
+    edesc = pfuncdesc->lprgelemdescParam + 1;
+    ok(edesc->tdesc.vt == VT_INT, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_I4, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_I4(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0xFFFFFFFF,
+            "got: 0x%x\n", V_I4(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 5, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60010005, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 8 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 8 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_INT, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0x789, "got: 0x%x\n",
+            V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(edesc->tdesc.vt == VT_USERDEFINED, "got: %d\n", edesc->tdesc.vt);
+    ok(U(edesc->tdesc).hreftype == hreftype, "got: 0x%x\n", U(edesc->tdesc).hreftype);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 6, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60010006, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 9 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 9 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VARIANT, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_INT, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0x3, "got: 0x%x\n",
+            V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(edesc->tdesc.vt == VT_VARIANT, "got: %d\n", edesc->tdesc.vt);
+    ok(U(edesc->tdesc).hreftype == 0, "got: 0x%x\n", U(edesc->tdesc).hreftype);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 7, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60010009, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 2, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 10 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 10 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_INT, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FIN, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex == NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+
+    edesc = pfuncdesc->lprgelemdescParam + 1;
+    ok(edesc->tdesc.vt == VT_UI2, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_UI2, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0xFFFF, "got: 0x%x\n",
+            V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 8, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60010003, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 11 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 11 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_INT, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_I4, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_I4(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0x123, "got: 0x%x\n",
+            V_I4(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 9, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam == NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_PROPERTYGET, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 0, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 12 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 12 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_BSTR, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(!memcmp(name, func1W, sizeof(func1W)), "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0x201, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(name);
+    SysFreeString(helpfile);
+
+    hres = ITypeInfo_GetNames(ti, pfuncdesc->memid, names, sizeof(names) / sizeof(*names), &cnames);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(cnames == 1, "got: %u\n", cnames);
+    ok(!memcmp(names[0], func1W, sizeof(func1W)), "got names[0]: %s\n", wine_dbgstr_w(names[0]));
+    SysFreeString(names[0]);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 10, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60010007, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 13 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 13 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_PTR, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FIN, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex == NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(edesc->tdesc).lptdesc != NULL, "got: %p\n", U(edesc->tdesc).lptdesc);
+    ok(U(edesc->tdesc).lptdesc->vt == VT_PTR, "got: %d\n", U(edesc->tdesc).lptdesc->vt);
+    ok(U(*U(edesc->tdesc).lptdesc).lptdesc != NULL, "got: %p\n", U(*U(edesc->tdesc).lptdesc).lptdesc);
+    ok(U(*U(edesc->tdesc).lptdesc).lptdesc->vt == VT_BSTR, "got: %d\n", U(*U(edesc->tdesc).lptdesc).lptdesc->vt);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 11, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60010004, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 14 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 14 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_PTR, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FIN, "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex == NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(edesc->tdesc).lptdesc != NULL, "got: %p\n", U(edesc->tdesc).lptdesc);
+    ok(U(edesc->tdesc).lptdesc->vt == VT_BSTR, "got: %d\n", U(edesc->tdesc).lptdesc->vt);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(name == NULL, "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(helpfile);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 12, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_PROPERTYPUT, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(pfuncdesc->oVft == 15 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    else
+#endif
+        ok(pfuncdesc->oVft == 15 * sizeof(void*), "got %d\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_BSTR, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).idldesc.wIDLFlags == IDLFLAG_FIN, "got: %x\n", U(*edesc).idldesc.wIDLFlags);
+
+    hres = ITypeInfo_GetDocumentation(ti, pfuncdesc->memid, &name, &docstring, &helpcontext, &helpfile);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(!memcmp(name, func1W, sizeof(func1W)), "got name: %s\n", wine_dbgstr_w(name));
+    ok(docstring == NULL, "got docstring: %s\n", wine_dbgstr_w(docstring));
+    ok(helpcontext == 0x201, "got helpcontext: 0x%x\n", helpcontext);
+    ok(!memcmp(helpfile, helpfileW, sizeof(helpfileW)), "got helpfile: %s\n", wine_dbgstr_w(helpfile));
+    SysFreeString(name);
+    SysFreeString(helpfile);
+
+    hres = ITypeInfo_GetNames(ti, pfuncdesc->memid, names, sizeof(names) / sizeof(*names), &cnames);
+    ok(hres == S_OK, "got: %08x\n", hres);
+    ok(cnames == 1, "got: %u\n", cnames);
+    ok(!memcmp(names[0], func1W, sizeof(func1W)), "got names[0]: %s\n", wine_dbgstr_w(names[0]));
+    SysFreeString(names[0]);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 13, &pfuncdesc);
+    ok(hres == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hres);
+
+    ok(ITypeInfo_Release(ti) == 0, "Object should be freed\n");
+
+    hres = ITypeLib_GetTypeInfo(tl, 1, &ti);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == sizeof(void*), "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_INTERFACE, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 2, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 1, "cImplTypes = %d\n", typeattr->cImplTypes);
+    ok(typeattr->cbSizeVft == 0xaab8 || typeattr->cbSizeVft == 0xaab0 ||
+            typeattr->cbSizeVft == 0x5560, "cbSizeVft = 0x%x\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == alignment, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+    hres = ITypeInfo_GetRefTypeOfImplType(ti, 0, &hreftype);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 0, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60020000, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+    ok(pfuncdesc->oVft == 0xffffaaa8 ||
+            pfuncdesc->oVft == 0x5550, "got %x\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_VARIANT, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_INT, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0x3, "got: 0x%x\n",
+            V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(edesc->tdesc).lptdesc == NULL, "got: %p\n", U(edesc->tdesc).lptdesc);
+    ok(U(edesc->tdesc).hreftype == 0, "got: %d\n", U(edesc->tdesc).hreftype);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    hres = ITypeInfo_GetFuncDesc(ti, 1, &pfuncdesc);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(pfuncdesc->memid == 0x60020001, "got %x\n", pfuncdesc->memid);
+    ok(pfuncdesc->lprgscode == NULL, "got %p\n", pfuncdesc->lprgscode);
+    ok(pfuncdesc->lprgelemdescParam != NULL, "got %p\n", pfuncdesc->lprgelemdescParam);
+    ok(pfuncdesc->funckind == FUNC_PUREVIRTUAL, "got 0x%x\n", pfuncdesc->funckind);
+    ok(pfuncdesc->invkind == INVOKE_FUNC, "got 0x%x\n", pfuncdesc->invkind);
+    ok(pfuncdesc->callconv == CC_STDCALL, "got 0x%x\n", pfuncdesc->callconv);
+    ok(pfuncdesc->cParams == 1, "got %d\n", pfuncdesc->cParams);
+    ok(pfuncdesc->cParamsOpt == 0, "got %d\n", pfuncdesc->cParamsOpt);
+    ok(pfuncdesc->oVft == 0xffffaaac ||
+            pfuncdesc->oVft == 0xffffaab0 ||
+            pfuncdesc->oVft == 0x5558, "got %x\n", pfuncdesc->oVft);
+    ok(pfuncdesc->cScodes == 0, "got %d\n", pfuncdesc->cScodes);
+    ok(pfuncdesc->elemdescFunc.tdesc.vt == VT_VOID, "got %d\n", pfuncdesc->elemdescFunc.tdesc.vt);
+    ok(pfuncdesc->wFuncFlags == 0, "got 0x%x\n", pfuncdesc->wFuncFlags);
+
+    edesc = pfuncdesc->lprgelemdescParam;
+    ok(edesc->tdesc.vt == VT_VARIANT, "got: %d\n", edesc->tdesc.vt);
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(*edesc).paramdesc.pparamdescex != NULL, "got: %p\n", U(*edesc).paramdesc.pparamdescex);
+    ok(U(*edesc).paramdesc.pparamdescex->cBytes == sizeof(PARAMDESCEX), "got: %d\n",
+            U(*edesc).paramdesc.pparamdescex->cBytes);
+    ok(V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == VT_INT, "got: %d\n",
+            V_VT(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue) == 0x3, "got: 0x%x\n",
+            V_UI2(&U(*edesc).paramdesc.pparamdescex->varDefaultValue));
+    ok(U(*edesc).paramdesc.wParamFlags == PARAMFLAG_FHASDEFAULT,
+            "got: 0x%x\n", U(*edesc).paramdesc.wParamFlags);
+    ok(U(edesc->tdesc).lptdesc == NULL, "got: %p\n", U(edesc->tdesc).lptdesc);
+    ok(U(edesc->tdesc).hreftype == 0, "got: %d\n", U(edesc->tdesc).hreftype);
+    ITypeInfo_ReleaseFuncDesc(ti, pfuncdesc);
+
+    ok(ITypeInfo_Release(ti) == 0, "Object should be freed\n");
+
+    hres = ITypeLib_GetTypeInfo(tl, 2, &ti);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_QueryInterface(ti, &IID_ITypeInfo2, (void**)&ti2);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == sizeof(void*), "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_INTERFACE, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 0, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 0, "cImplTypes = %d\n", typeattr->cImplTypes);
+    ok(typeattr->cbSizeVft == 0, "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == alignment, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+    VariantClear(&cust_data);
+    hres = ITypeInfo2_GetCustData(ti2, &custguid, &cust_data);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(V_VT(&cust_data) == VT_BSTR, "got wrong custdata type: %u\n", V_VT(&cust_data));
+    ok(!lstrcmpW(V_BSTR(&cust_data), asdfW), "got wrong custdata value: %s\n", wine_dbgstr_w(V_BSTR(&cust_data)));
+    SysFreeString(V_BSTR(&cust_data));
+
+    ITypeInfo2_Release(ti2);
+    ok(ITypeInfo_Release(ti) == 0, "Object should be freed\n");
+
+    hres = ITypeLib_GetTypeInfo(tl, 3, &ti);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == sizeof(void*), "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_COCLASS, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 0, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 3, "cImplTypes = %d\n", typeattr->cImplTypes);
+    ok(typeattr->cbSizeVft == 0, "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == alignment, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == 0, "wTypeFlags = %d\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+    hres = ITypeInfo_GetRefTypeOfImplType(ti, 0, &hreftype);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(hreftype == 0, "got wrong hreftype: %x\n", hreftype);
+
+    hres = ITypeInfo_GetImplTypeFlags(ti, 0, &impltypeflags);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(impltypeflags == IMPLTYPEFLAG_FDEFAULT, "got wrong flag: %x\n", impltypeflags);
+
+    hres = ITypeInfo_GetRefTypeOfImplType(ti, 1, &hreftype);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(hreftype == 1, "got wrong hreftype: %x\n", hreftype);
+
+    hres = ITypeInfo_GetImplTypeFlags(ti, 1, &impltypeflags);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(impltypeflags == IMPLTYPEFLAG_FRESTRICTED, "got wrong flag: %x\n", impltypeflags);
+
+    hres = ITypeInfo_GetRefTypeOfImplType(ti, 2, &hreftype);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(hreftype == 1, "got wrong hreftype: %x\n", hreftype);
+
+    hres = ITypeInfo_GetImplTypeFlags(ti, 2, &impltypeflags);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(impltypeflags == 0, "got wrong flag: %x\n", impltypeflags);
+
+    hres = ITypeInfo_GetRefTypeOfImplType(ti, 3, &hreftype);
+    ok(hres == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hres);
+
+    ok(ITypeInfo_Release(ti) == 0, "Object should be freed\n");
+
+    hres = ITypeLib_GetTypeInfo(tl, 4, &ti);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == sizeof(void*), "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_DISPATCH, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 8, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 1, "cImplTypes = %d\n", typeattr->cImplTypes);
+    ok(typeattr->cbSizeVft == 7 * sizeof(void*), "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == alignment, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == (TYPEFLAG_FDISPATCHABLE | TYPEFLAG_FDUAL), "wTypeFlags = 0x%x\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+    hres = ITypeInfo_GetRefTypeOfImplType(ti, -1, &hreftype);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(hreftype == -2, "got wrong hreftype: %x\n", hreftype);
+
+    hres = ITypeInfo_GetRefTypeInfo(ti, hreftype, &interface1);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(interface1, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == sizeof(void*), "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_INTERFACE, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 1, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 1, "cImplTypes = %d\n", typeattr->cImplTypes);
+#ifdef _WIN64
+    if(sys == SYS_WIN32)
+        todo_wine ok(typeattr->cbSizeVft == 8 * sizeof(void*), "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    else
+#endif
+        ok(typeattr->cbSizeVft == 8 * sizeof(void*), "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == alignment, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == (TYPEFLAG_FDISPATCHABLE | TYPEFLAG_FDUAL), "wTypeFlags = 0x%x\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ITypeInfo_ReleaseTypeAttr(interface1, typeattr);
+
+    ITypeInfo_Release(interface1);
+
+    ok(ITypeInfo_Release(ti) == 0, "Object should be freed\n");
+
+    hres = ITypeLib_GetTypeInfo(tl, 5, &ti);
+    ok(hres == S_OK, "got %08x\n", hres);
+
+    hres = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hres == S_OK, "got %08x\n", hres);
+    ok(typeattr->cbSizeInstance == 8, "cbSizeInstance = %d\n", typeattr->cbSizeInstance);
+    ok(typeattr->typekind == TKIND_ALIAS, "typekind = %d\n", typeattr->typekind);
+    ok(typeattr->cFuncs == 0, "cFuncs = %d\n", typeattr->cFuncs);
+    ok(typeattr->cVars == 0, "cVars = %d\n", typeattr->cVars);
+    ok(typeattr->cImplTypes == 0, "cImplTypes = %d\n", typeattr->cImplTypes);
+    ok(typeattr->cbSizeVft == 0, "cbSizeVft = %d\n", typeattr->cbSizeVft);
+    ok(typeattr->cbAlignment == alignment, "cbAlignment = %d\n", typeattr->cbAlignment);
+    ok(typeattr->wTypeFlags == 0, "wTypeFlags = 0x%x\n", typeattr->wTypeFlags);
+    ok(typeattr->wMajorVerNum == 0, "wMajorVerNum = %d\n", typeattr->wMajorVerNum);
+    ok(typeattr->wMinorVerNum == 0, "wMinorVerNum = %d\n", typeattr->wMinorVerNum);
+    ok(typeattr->tdescAlias.vt == VT_R8, "Got wrong tdescAlias.vt: %u\n", typeattr->tdescAlias.vt);
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+    ok(ITypeInfo_Release(ti) == 0, "Object should be freed\n");
+
+    ok(ITypeLib_Release(tl)==0, "Object should be freed\n");
+
+    DeleteFileA(filename);
+}
+
+#if 0       /* use this to generate more tests */
+
+#define OLE_CHECK(x) { HRESULT hr = x; if (FAILED(hr)) { printf(#x "failed - %x\n", hr); return; } }
+
+static char *dump_string(LPWSTR wstr)
+{
+    int size = lstrlenW(wstr)+3;
+    char *out = CoTaskMemAlloc(size);
+    WideCharToMultiByte(20127, 0, wstr, -1, out+1, size, NULL, NULL);
+    out[0] = '\"';
+    strcat(out, "\"");
+    return out;
+}
+
+struct map_entry
+{
+    DWORD value;
+    const char *name;
+};
+
+#define MAP_ENTRY(x) { x, #x }
+static const struct map_entry tkind_map[] = {
+    MAP_ENTRY(TKIND_ENUM),
+    MAP_ENTRY(TKIND_RECORD),
+    MAP_ENTRY(TKIND_MODULE),
+    MAP_ENTRY(TKIND_INTERFACE),
+    MAP_ENTRY(TKIND_DISPATCH),
+    MAP_ENTRY(TKIND_COCLASS),
+    MAP_ENTRY(TKIND_ALIAS),
+    MAP_ENTRY(TKIND_UNION),
+    MAP_ENTRY(TKIND_MAX),
+    {0, NULL}
+};
+
+static const struct map_entry funckind_map[] = {
+    MAP_ENTRY(FUNC_VIRTUAL),
+    MAP_ENTRY(FUNC_PUREVIRTUAL),
+    MAP_ENTRY(FUNC_NONVIRTUAL),
+    MAP_ENTRY(FUNC_STATIC),
+    MAP_ENTRY(FUNC_DISPATCH),
+    {0, NULL}
+};
+
+static const struct map_entry invkind_map[] = {
+    MAP_ENTRY(INVOKE_FUNC),
+    MAP_ENTRY(INVOKE_PROPERTYGET),
+    MAP_ENTRY(INVOKE_PROPERTYPUT),
+    MAP_ENTRY(INVOKE_PROPERTYPUTREF),
+    {0, NULL}
+};
+
+#undef MAP_ENTRY
+
+static const char *map_value(DWORD val, const struct map_entry *map)
+{
+    static int map_id;
+    static char bufs[16][256];
+    char *buf;
+
+    while (map->name)
+    {
+        if (map->value == val)
+            return map->name;
+        map++;
+    }
+
+    buf = bufs[(map_id++)%16];
+    sprintf(buf, "0x%x", val);
+    return buf;
+}
+
+static void test_dump_typelib(const char *name)
+{
+    WCHAR wszString[260];
+    ITypeInfo *info;
+    ITypeLib *lib;
+    int count;
+    int i;
+
+    MultiByteToWideChar(CP_ACP, 0, name, -1, wszString, 260);
+    OLE_CHECK(LoadTypeLib(wszString, &lib));
+    count = ITypeLib_GetTypeInfoCount(lib);
+    printf("/* interfaces count: %d */\n", count);
+    for (i = 0; i < count; i++)
+    {
+        TYPEATTR *attr;
+        BSTR name;
+        int f = 0;
+
+        OLE_CHECK(ITypeLib_GetDocumentation(lib, i, &name, NULL, NULL, NULL));
+        printf("{\n"
                "  %s,\n", dump_string(name));
         SysFreeString(name);
 
@@ -2891,7 +3941,7 @@ static void test_create_typelib_lcid(LCID lcid)
     HRESULT hr;
     ICreateTypeLib2 *tl;
     HANDLE file;
-    DWORD msft_header[5]; /* five is enough for now */
+    DWORD msft_header[7];
     DWORD read;
 
     GetTempFileNameA( ".", "tlb", 0, filename );
@@ -2903,6 +3953,9 @@ static void test_create_typelib_lcid(LCID lcid)
     hr = ICreateTypeLib2_SetLcid(tl, lcid);
     ok(hr == S_OK, "got %08x\n", hr);
 
+    hr = ICreateTypeLib2_SetVersion(tl, 3, 4);
+    ok(hr == S_OK, "got %08x\n", hr);
+
     hr = ICreateTypeLib2_SaveAllChanges(tl);
     ok(hr == S_OK, "got %08x\n", hr);
 
@@ -2920,6 +3973,7 @@ static void test_create_typelib_lcid(LCID lcid)
     ok(msft_header[2] == 0xffffffff, "got %08x\n", msft_header[2]);
     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]);
 
     DeleteFileA(filename);
 }
@@ -3086,8 +4140,11 @@ static void test_SetVarHelpContext(void)
     WCHAR filenameW[MAX_PATH];
     ICreateTypeLib2 *ctl;
     ICreateTypeInfo *cti;
-    VARDESC desc;
+    ITypeLib *tl;
+    ITypeInfo *ti;
+    VARDESC desc, *pdesc;
     HRESULT hr;
+    DWORD ctx;
     VARIANT v;
 
     GetTempFileNameA(".", "tlb", 0, filenameA);
@@ -3103,6 +4160,7 @@ static void test_SetVarHelpContext(void)
     ok(hr == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hr);
 
     memset(&desc, 0, sizeof(desc));
+    desc.memid = MEMBERID_NIL;
     desc.elemdescVar.tdesc.vt = VT_INT;
     desc.varkind = VAR_CONST;
 
@@ -3124,7 +4182,34 @@ static void test_SetVarHelpContext(void)
     ok(hr == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hr);
 
     ICreateTypeInfo_Release(cti);
+
+    hr = ICreateTypeLib2_SaveAllChanges(ctl);
+    ok(hr == S_OK, "got: %08x\n", hr);
+
     ICreateTypeLib2_Release(ctl);
+
+    hr = LoadTypeLib(filenameW, &tl);
+    ok(hr == S_OK, "got: %08x\n", hr);
+
+    hr = ITypeLib_GetTypeInfo(tl, 0, &ti);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    hr = ITypeInfo_GetVarDesc(ti, 0, &pdesc);
+    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));
+
+    hr = ITypeInfo_GetDocumentation(ti, pdesc->memid, NULL, NULL, &ctx, NULL);
+    ok(hr == S_OK, "got %08x\n", hr);
+    ok(ctx == 1, "got wrong help context: 0x%x\n", ctx);
+
+    ITypeInfo_ReleaseVarDesc(ti, pdesc);
+    ITypeInfo_Release(ti);
+    ITypeLib_Release(tl);
+
     DeleteFileA(filenameA);
 }
 
@@ -3192,6 +4277,13 @@ static void test_SetFuncAndParamNames(void)
     hr = ICreateTypeInfo_SetFuncAndParamNames(cti, 2, propW, 1);
     ok(hr == S_OK, "got 0x%08x\n", hr);
 
+    hr = ICreateTypeInfo_AddFuncDesc(cti, 3, &funcdesc);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    /* getter name again */
+    hr = ICreateTypeInfo_SetFuncAndParamNames(cti, 3, propW, 1);
+    ok(hr == TYPE_E_AMBIGUOUSNAME, "got 0x%08x\n", hr);
+
     ICreateTypeInfo_Release(cti);
     ICreateTypeLib2_Release(ctl);
     DeleteFileA(filenameA);
@@ -3206,7 +4298,10 @@ static void test_SetVarDocString(void)
     WCHAR filenameW[MAX_PATH];
     ICreateTypeLib2 *ctl;
     ICreateTypeInfo *cti;
-    VARDESC desc;
+    ITypeLib *tl;
+    ITypeInfo *ti;
+    BSTR docstr;
+    VARDESC desc, *pdesc;
     HRESULT hr;
     VARIANT v;
 
@@ -3226,6 +4321,7 @@ static void test_SetVarDocString(void)
     ok(hr == E_INVALIDARG, "got %08x\n", hr);
 
     memset(&desc, 0, sizeof(desc));
+    desc.memid = MEMBERID_NIL;
     desc.elemdescVar.tdesc.vt = VT_INT;
     desc.varkind = VAR_CONST;
 
@@ -3250,7 +4346,36 @@ static void test_SetVarDocString(void)
     ok(hr == TYPE_E_ELEMENTNOTFOUND, "got %08x\n", hr);
 
     ICreateTypeInfo_Release(cti);
+
+    hr = ICreateTypeLib2_SaveAllChanges(ctl);
+    ok(hr == S_OK, "got: %08x\n", hr);
+
     ICreateTypeLib2_Release(ctl);
+
+    hr = LoadTypeLib(filenameW, &tl);
+    ok(hr == S_OK, "got: %08x\n", hr);
+
+    hr = ITypeLib_GetTypeInfo(tl, 0, &ti);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    hr = ITypeInfo_GetVarDesc(ti, 0, &pdesc);
+    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));
+
+    hr = ITypeInfo_GetDocumentation(ti, pdesc->memid, NULL, &docstr, NULL, NULL);
+    ok(hr == S_OK, "got %08x\n", hr);
+    ok(memcmp(docstr, doc2W, sizeof(doc2W)) == 0, "got wrong docstring: %s\n", wine_dbgstr_w(docstr));
+
+    SysFreeString(docstr);
+
+    ITypeInfo_ReleaseVarDesc(ti, pdesc);
+    ITypeInfo_Release(ti);
+    ITypeLib_Release(tl);
+
     DeleteFileA(filenameA);
 }
 
@@ -3327,6 +4452,485 @@ todo_wine {
     ITypeLib_Release(tl);
 }
 
+static void test_TypeInfo2_GetContainingTypeLib(void)
+{
+    static const WCHAR test[] = {'t','e','s','t','.','t','l','b',0};
+    static OLECHAR testTI[] = {'t','e','s','t','T','y','p','e','I','n','f','o',0};
+
+    ICreateTypeLib2 *ctl2;
+    ICreateTypeInfo *cti;
+    ITypeInfo2 *ti2;
+    ITypeLib *tl;
+    UINT Index;
+    HRESULT hr;
+
+    hr = CreateTypeLib2(SYS_WIN32, test, &ctl2);
+    ok_ole_success(hr, CreateTypeLib2);
+
+    hr = ICreateTypeLib2_CreateTypeInfo(ctl2, testTI, TKIND_DISPATCH, &cti);
+    ok_ole_success(hr, ICreateTypeLib2_CreateTypeInfo);
+
+    hr = ICreateTypeInfo_QueryInterface(cti, &IID_ITypeInfo2, (void**)&ti2);
+    ok_ole_success(hr, ICreateTypeInfo2_QueryInterface);
+
+    tl = NULL;
+    Index = 888;
+    hr = ITypeInfo2_GetContainingTypeLib(ti2, &tl, &Index);
+    ok_ole_success(hr, ITypeInfo2_GetContainingTypeLib);
+    ok(tl != NULL, "ITypeInfo2_GetContainingTypeLib returned empty TypeLib\n");
+    ok(Index == 0, "ITypeInfo2_GetContainingTypeLib returned Index = %u, expected 0\n", Index);
+    if(tl) ITypeLib_Release(tl);
+
+    tl = NULL;
+    hr = ITypeInfo2_GetContainingTypeLib(ti2, &tl, NULL);
+    ok_ole_success(hr, ITypeInfo2_GetContainingTypeLib);
+    ok(tl != NULL, "ITypeInfo2_GetContainingTypeLib returned empty TypeLib\n");
+    if(tl) ITypeLib_Release(tl);
+
+    Index = 888;
+    hr = ITypeInfo2_GetContainingTypeLib(ti2, NULL, &Index);
+    ok_ole_success(hr, ITypeInfo2_GetContainingTypeLib);
+    ok(Index == 0, "ITypeInfo2_GetContainingTypeLib returned Index = %u, expected 0\n", Index);
+
+    hr = ITypeInfo2_GetContainingTypeLib(ti2, NULL, NULL);
+    ok_ole_success(hr, ITypeInfo2_GetContainingTypeLib);
+
+    ITypeInfo2_Release(ti2);
+    ICreateTypeInfo_Release(cti);
+    ICreateTypeLib2_Release(ctl2);
+}
+
+static void create_manifest_file(const char *filename, const char *manifest)
+{
+    HANDLE file;
+    DWORD size;
+
+    file = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
+                       FILE_ATTRIBUTE_NORMAL, NULL);
+    ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %u\n", GetLastError());
+    WriteFile(file, manifest, strlen(manifest), &size, NULL);
+    CloseHandle(file);
+}
+
+static HANDLE create_actctx(const char *file)
+{
+    WCHAR path[MAX_PATH];
+    ACTCTXW actctx;
+    HANDLE handle;
+
+    MultiByteToWideChar(CP_ACP, 0, file, -1, path, MAX_PATH);
+    memset(&actctx, 0, sizeof(ACTCTXW));
+    actctx.cbSize = sizeof(ACTCTXW);
+    actctx.lpSource = path;
+
+    handle = pCreateActCtxW(&actctx);
+    ok(handle != INVALID_HANDLE_VALUE, "handle == INVALID_HANDLE_VALUE, error %u\n", GetLastError());
+
+    ok(actctx.cbSize == sizeof(actctx), "actctx.cbSize=%d\n", actctx.cbSize);
+    ok(actctx.dwFlags == 0, "actctx.dwFlags=%d\n", actctx.dwFlags);
+    ok(actctx.lpSource == path, "actctx.lpSource=%p\n", actctx.lpSource);
+    ok(actctx.wProcessorArchitecture == 0, "actctx.wProcessorArchitecture=%d\n", actctx.wProcessorArchitecture);
+    ok(actctx.wLangId == 0, "actctx.wLangId=%d\n", actctx.wLangId);
+    ok(actctx.lpAssemblyDirectory == NULL, "actctx.lpAssemblyDirectory=%p\n", actctx.lpAssemblyDirectory);
+    ok(actctx.lpResourceName == NULL, "actctx.lpResourceName=%p\n", actctx.lpResourceName);
+    ok(actctx.lpApplicationName == NULL, "actctx.lpApplicationName=%p\n",
+       actctx.lpApplicationName);
+    ok(actctx.hModule == NULL, "actctx.hModule=%p\n", actctx.hModule);
+
+    return handle;
+}
+
+static const char manifest_dep[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<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\""
+" />"
+"</file>"
+"<file name=\"test_actctx_tlb2.tlb\">"
+" <typelib tlbid=\"{a2cfdbd3-2bbf-4b1c-a414-5a5904e634c9}\" version=\"2.0\" helpdir=\"\" resourceid=\"409\""
+"          flags=\"RESTRICTED,CONTROL\""
+" />"
+"</file>"
+"</assembly>";
+
+static const char manifest_main[] =
+"<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
+"<assemblyIdentity version=\"1.2.3.4\" name=\"Wine.Test\" type=\"win32\" />"
+"<dependency>"
+" <dependentAssembly>"
+"  <assemblyIdentity type=\"win32\" name=\"testdep\" version=\"1.2.3.4\" processorArchitecture=\"" ARCH "\" />"
+" </dependentAssembly>"
+"</dependency>"
+"</assembly>";
+
+static void test_LoadRegTypeLib(void)
+{
+    LCID lcid_en = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
+    LCID lcid_ru = MAKELCID(MAKELANGID(LANG_RUSSIAN, SUBLANG_NEUTRAL), SORT_DEFAULT);
+    ULONG_PTR cookie;
+    TLIBATTR *attr;
+    HANDLE handle;
+    ITypeLib *tl;
+    HRESULT hr;
+    BSTR path;
+    BOOL ret;
+
+    if (!pActivateActCtx)
+    {
+        win_skip("Activation contexts not supported, skipping LoadRegTypeLib tests\n");
+        return;
+    }
+
+    create_manifest_file("testdep.manifest", manifest_dep);
+    create_manifest_file("main.manifest", manifest_main);
+
+    handle = create_actctx("main.manifest");
+    DeleteFileA("testdep.manifest");
+    DeleteFileA("main.manifest");
+
+    /* create typelib file */
+    write_typelib(1, "test_actctx_tlb.tlb");
+    write_typelib(3, "test_actctx_tlb2.tlb");
+
+    hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &tl);
+    ok(hr == TYPE_E_LIBNOTREGISTERED, "got 0x%08x\n", hr);
+
+    hr = LoadRegTypeLib(&LIBID_register_test, 1, 0, LOCALE_NEUTRAL, &tl);
+    ok(hr == TYPE_E_LIBNOTREGISTERED, "got 0x%08x\n", hr);
+
+    hr = QueryPathOfRegTypeLib(&LIBID_TestTypelib, 2, 0, LOCALE_NEUTRAL, &path);
+    ok(hr == TYPE_E_LIBNOTREGISTERED, "got 0x%08x\n", hr);
+
+    ret = pActivateActCtx(handle, &cookie);
+    ok(ret, "ActivateActCtx failed: %u\n", GetLastError());
+
+    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);
+
+    path = NULL;
+    hr = QueryPathOfRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &path);
+    ok(hr == TYPE_E_LIBNOTREGISTERED || broken(hr == S_OK) /* winxp */, "got 0x%08x\n", hr);
+    SysFreeString(path);
+
+    /* manifest version is 2.0, actual is 1.0 */
+    hr = LoadRegTypeLib(&LIBID_register_test, 1, 0, LOCALE_NEUTRAL, &tl);
+    ok(hr == TYPE_E_LIBNOTREGISTERED || broken(hr == S_OK) /* winxp */, "got 0x%08x\n", hr);
+    if (hr == S_OK) ITypeLib_Release(tl);
+
+    hr = LoadRegTypeLib(&LIBID_register_test, 2, 0, LOCALE_NEUTRAL, &tl);
+    ok(hr == TYPE_E_LIBNOTREGISTERED, "got 0x%08x\n", hr);
+
+    /* 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);
+
+    hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 7, LOCALE_NEUTRAL, &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);
+
+    ok(attr->lcid == 0, "got %x\n", attr->lcid);
+    ok(attr->wMajorVerNum == 2, "got %d\n", attr->wMajorVerNum);
+    ok(attr->wMinorVerNum == 5, "got %d\n", attr->wMinorVerNum);
+    ok(attr->wLibFlags == LIBFLAG_FHASDISKIMAGE, "got %x\n", attr->wLibFlags);
+
+    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("test_actctx_tlb.tlb");
+    DeleteFileA("test_actctx_tlb2.tlb");
+
+    ret = pDeactivateActCtx(0, cookie);
+    ok(ret, "DeactivateActCtx failed: %u\n", GetLastError());
+
+    pReleaseActCtx(handle);
+}
+
+#define AUX_HREF 1
+#define AUX_TDESC 2
+#define AUX_ADESC 3
+static struct _TDATest {
+    VARTYPE vt;
+    ULONG size; /* -1 == typelib ptr size */
+    WORD align;
+    WORD align3264; /* for 32-bit typelibs loaded in 64-bit mode */
+    DWORD aux;
+    TYPEDESC tdesc;
+    ARRAYDESC adesc;
+} TDATests[] = {
+    { VT_I2, 2, 2, 2 },
+    { VT_I4, 4, 4, 4 },
+    { VT_R4, 4, 4, 4 },
+    { VT_R8, 8, 4, 8 },
+    { VT_CY, 8, 4, 8 },
+    { VT_DATE, 8, 4, 8 },
+    { VT_BSTR, -1, 4, 8 },
+    { VT_DISPATCH, -1, 4, 8 },
+    { VT_ERROR, 4, 4, 4 },
+    { VT_BOOL, 2, 2, 2 },
+    { VT_VARIANT, 0 /* see code below */, 4, 8 },
+    { VT_UNKNOWN, -1, 4, 8 },
+    { VT_DECIMAL, 16, 4, 8 },
+    { VT_I1, 1, 1, 1 },
+    { VT_UI1, 1, 1, 1 },
+    { VT_UI2, 2, 2, 2 },
+    { VT_UI4, 4, 4, 4 },
+    { VT_I8, 8, 4, 8 },
+    { VT_UI8, 8, 4, 8 },
+    { VT_INT, 4, 4, 4 },
+    { VT_UINT, 4, 4, 4 },
+    { VT_VOID, 0, 0, 0 },
+    { VT_HRESULT, 4, 4, 4 },
+    { VT_PTR, -1, 4, 8, AUX_TDESC, { { 0 }, VT_INT } },
+    { VT_SAFEARRAY, -1, 4, 8, AUX_TDESC, { { 0 }, VT_INT } },
+    { VT_CARRAY, 16 /* == 4 * sizeof(int) */, 4, 4, AUX_ADESC, { { 0 } }, { { { 0 }, VT_INT }, 1, { { 4, 0 } } } },
+    { VT_USERDEFINED, 0, 0, 0, AUX_HREF },
+    { VT_LPSTR, -1, 4, 8 },
+    { VT_LPWSTR, -1, 4, 8 },
+    { 0 }
+};
+
+static void testTDA(ITypeLib *tl, struct _TDATest *TDATest,
+        ULONG ptr_size, HREFTYPE hreftype, ULONG href_cbSizeInstance,
+        WORD href_cbAlignment, BOOL create)
+{
+    TYPEDESC tdesc;
+    WCHAR nameW[32];
+    ITypeInfo *ti;
+    ICreateTypeInfo *cti;
+    ICreateTypeLib2 *ctl;
+    ULONG size;
+    WORD alignment;
+    TYPEATTR *typeattr;
+    HRESULT hr;
+
+    static const WCHAR name_fmtW[] = {'a','l','i','a','s','%','0','2','u',0};
+
+    wsprintfW(nameW, name_fmtW, TDATest->vt);
+
+    if(create){
+        hr = ITypeLib_QueryInterface(tl, &IID_ICreateTypeLib2, (void**)&ctl);
+        ok(hr == S_OK, "got %08x\n", hr);
+
+        hr = ICreateTypeLib2_CreateTypeInfo(ctl, nameW, TKIND_ALIAS, &cti);
+        ok(hr == S_OK, "got %08x\n", hr);
+
+        tdesc.vt = TDATest->vt;
+        if(TDATest->aux == AUX_TDESC)
+            U(tdesc).lptdesc = &TDATest->tdesc;
+        else if(TDATest->aux == AUX_ADESC)
+            U(tdesc).lpadesc = &TDATest->adesc;
+        else if(TDATest->aux == AUX_HREF)
+            U(tdesc).hreftype = hreftype;
+
+        hr = ICreateTypeInfo_SetTypeDescAlias(cti, &tdesc);
+        ok(hr == S_OK, "for VT %u, got %08x\n", TDATest->vt, hr);
+
+        hr = ICreateTypeInfo_QueryInterface(cti, &IID_ITypeInfo, (void**)&ti);
+        ok(hr == S_OK, "got %08x\n", hr);
+
+        ICreateTypeInfo_Release(cti);
+        ICreateTypeLib2_Release(ctl);
+    }else{
+        USHORT found = 1;
+        MEMBERID memid;
+
+        hr = ITypeLib_FindName(tl, nameW, 0, &ti, &memid, &found);
+        ok(hr == S_OK, "for VT %u, got %08x\n", TDATest->vt, hr);
+    }
+
+    hr = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    if(TDATest->aux == AUX_HREF){
+        size = href_cbSizeInstance;
+        alignment = href_cbAlignment;
+    }else{
+        size = TDATest->size;
+        if(size == -1){
+            if(create)
+                size = ptr_size;
+            else
+                size = sizeof(void*);
+        }else if(TDATest->vt == VT_VARIANT){
+            if(create){
+                size = sizeof(VARIANT);
+#ifdef _WIN64
+                if(ptr_size != sizeof(void*))
+                    size -= 8; /* 32-bit variant is 4 bytes smaller than 64-bit variant */
+#endif
+            }else
+                size = sizeof(VARIANT);
+        }
+        alignment = TDATest->align;
+#ifdef _WIN64
+        if(!create && ptr_size != sizeof(void*))
+            alignment = TDATest->align3264;
+#endif
+    }
+
+    ok(typeattr->cbSizeInstance == size ||
+            broken(TDATest->vt == VT_VARIANT && ptr_size != sizeof(void*) && typeattr->cbSizeInstance == sizeof(VARIANT)) /* winxp64 */,
+            "got wrong size for VT %u: 0x%x\n", TDATest->vt, typeattr->cbSizeInstance);
+    ok(typeattr->cbAlignment == alignment, "got wrong alignment for VT %u: 0x%x\n", TDATest->vt, typeattr->cbAlignment);
+    ok(typeattr->tdescAlias.vt == TDATest->vt, "got wrong VT for VT %u: 0x%x\n", TDATest->vt, typeattr->tdescAlias.vt);
+
+    switch(TDATest->aux){
+    case AUX_HREF:
+        ok(U(typeattr->tdescAlias).hreftype == hreftype, "got wrong hreftype for VT %u: 0x%x\n", TDATest->vt, U(typeattr->tdescAlias).hreftype);
+        break;
+    case AUX_TDESC:
+        ok(U(typeattr->tdescAlias).lptdesc->vt == TDATest->tdesc.vt, "got wrong typedesc VT for VT %u: 0x%x\n", TDATest->vt, U(typeattr->tdescAlias).lptdesc->vt);
+        break;
+    case AUX_ADESC:
+        ok(U(typeattr->tdescAlias).lpadesc->tdescElem.vt == TDATest->adesc.tdescElem.vt, "got wrong arraydesc element VT for VT %u: 0x%x\n", TDATest->vt, U(typeattr->tdescAlias).lpadesc->tdescElem.vt);
+        ok(U(typeattr->tdescAlias).lpadesc->cDims == TDATest->adesc.cDims, "got wrong arraydesc dimension count for VT %u: 0x%x\n", TDATest->vt, U(typeattr->tdescAlias).lpadesc->cDims);
+        ok(U(typeattr->tdescAlias).lpadesc->rgbounds[0].cElements == TDATest->adesc.rgbounds[0].cElements, "got wrong arraydesc element count for VT %u: 0x%x\n", TDATest->vt, U(typeattr->tdescAlias).lpadesc->rgbounds[0].cElements);
+        ok(U(typeattr->tdescAlias).lpadesc->rgbounds[0].lLbound == TDATest->adesc.rgbounds[0].lLbound, "got wrong arraydesc lower bound for VT %u: 0x%x\n", TDATest->vt, U(typeattr->tdescAlias).lpadesc->rgbounds[0].lLbound);
+        break;
+    }
+
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+    ITypeInfo_Release(ti);
+}
+
+static void test_SetTypeDescAlias(SYSKIND kind)
+{
+    CHAR filenameA[MAX_PATH];
+    WCHAR filenameW[MAX_PATH];
+    ITypeLib *tl;
+    ICreateTypeLib2 *ctl;
+    ITypeInfo *ti;
+    ICreateTypeInfo *cti;
+    HREFTYPE hreftype;
+    TYPEATTR *typeattr;
+    ULONG href_cbSizeInstance, i;
+    WORD href_cbAlignment, ptr_size;
+    HRESULT hr;
+
+    static OLECHAR interfaceW[] = {'i','n','t','e','r','f','a','c','e',0};
+
+    switch(kind){
+    case SYS_WIN32:
+        trace("testing SYS_WIN32\n");
+        ptr_size = 4;
+        break;
+    case SYS_WIN64:
+        trace("testing SYS_WIN64\n");
+        ptr_size = 8;
+        break;
+    default:
+        return;
+    }
+
+    GetTempFileNameA(".", "tlb", 0, filenameA);
+    MultiByteToWideChar(CP_ACP, 0, filenameA, -1, filenameW, MAX_PATH);
+
+    hr = CreateTypeLib2(kind, filenameW, &ctl);
+    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_QueryInterface(cti, &IID_ITypeInfo, (void**)&ti);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    hr = ICreateTypeInfo_AddRefTypeInfo(cti, ti, &hreftype);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    hr = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    href_cbSizeInstance = typeattr->cbSizeInstance;
+    href_cbAlignment = typeattr->cbAlignment;
+
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+
+    ITypeInfo_Release(ti);
+    ICreateTypeInfo_Release(cti);
+
+    hr = ICreateTypeLib2_QueryInterface(ctl, &IID_ITypeLib, (void**)&tl);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    for(i = 0; TDATests[i].vt; ++i)
+        testTDA(tl, &TDATests[i], ptr_size, hreftype, href_cbSizeInstance, href_cbAlignment, TRUE);
+
+    hr = ICreateTypeLib2_SaveAllChanges(ctl);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    ITypeLib_Release(tl);
+    ok(0 == ICreateTypeLib2_Release(ctl), "typelib should have been released\n");
+
+    trace("after save...\n");
+
+    hr = LoadTypeLibEx(filenameW, REGKIND_NONE, &tl);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    hr = ITypeLib_GetTypeInfo(tl, 0, &ti);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    hr = ITypeInfo_GetTypeAttr(ti, &typeattr);
+    ok(hr == S_OK, "got %08x\n", hr);
+
+    href_cbSizeInstance = typeattr->cbSizeInstance;
+    href_cbAlignment = typeattr->cbAlignment;
+
+    ITypeInfo_ReleaseTypeAttr(ti, typeattr);
+    ITypeInfo_Release(ti);
+
+    for(i = 0; TDATests[i].vt; ++i)
+        testTDA(tl, &TDATests[i], ptr_size, hreftype, href_cbSizeInstance, href_cbAlignment, FALSE);
+
+    ok(0 == ITypeLib_Release(tl), "typelib should have been released\n");
+
+    DeleteFileA(filenameA);
+}
+
 START_TEST(typelib)
 {
     const char *filename;
@@ -3339,10 +4943,14 @@ START_TEST(typelib)
     test_TypeInfo();
     test_DispCallFunc();
     test_QueryPathOfRegTypeLib(32);
-    if(sizeof(void*) == 8)
+    if(sizeof(void*) == 8){
         test_QueryPathOfRegTypeLib(64);
+        test_CreateTypeLib(SYS_WIN64);
+        test_SetTypeDescAlias(SYS_WIN64);
+    }
+    test_CreateTypeLib(SYS_WIN32);
+    test_SetTypeDescAlias(SYS_WIN32);
     test_inheritance();
-    test_CreateTypeLib();
     test_SetVarHelpContext();
     test_SetFuncAndParamNames();
     test_SetVarDocString();
@@ -3358,4 +4966,6 @@ START_TEST(typelib)
     test_register_typelib(FALSE);
     test_create_typelibs();
     test_LoadTypeLib();
+    test_TypeInfo2_GetContainingTypeLib();
+    test_LoadRegTypeLib();
 }
index 5f1ea51..436e293 100644 (file)
@@ -48,11 +48,8 @@ static HRESULT (WINAPI *pVarFormatNumber)(LPVARIANT,int,int,int,int,ULONG,BSTR*)
 static HRESULT (WINAPI *pVarFormat)(LPVARIANT,LPOLESTR,int,int,ULONG,BSTR*);
 static HRESULT (WINAPI *pVarWeekdayName)(int,int,int,ULONG,BSTR*);
 
-/* Have I8/UI8 data type? */
-#define HAVE_OLEAUT32_I8      HAVE_FUNC(VarI8FromI1)
-
-/* Is a given function exported from oleaut32? */
-#define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
+/* Has I8/UI8 data type? */
+static BOOL has_i8;
 
 /* Get a conversion function ptr, return if function not available */
 #define CHECKPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func); \
@@ -100,7 +97,7 @@ static void test_VarFormatNumber(void)
   FMT_NUMBER(VT_UI2, V_UI2);
   FMT_NUMBER(VT_I4, V_I4);
   FMT_NUMBER(VT_UI4, V_UI4);
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     FMT_NUMBER(VT_I8, V_I8);
     FMT_NUMBER(VT_UI8, V_UI8);
@@ -282,7 +279,7 @@ static void test_VarFormat(void)
   VNUMFMT(VT_I1,V_I1);
   VNUMFMT(VT_I2,V_I2);
   VNUMFMT(VT_I4,V_I4);
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     VNUMFMT(VT_I8,V_I8);
   }
@@ -290,7 +287,7 @@ static void test_VarFormat(void)
   VNUMFMT(VT_UI1,V_UI1);
   VNUMFMT(VT_UI2,V_UI2);
   VNUMFMT(VT_UI4,V_UI4);
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     VNUMFMT(VT_UI8,V_UI8);
   }
@@ -569,6 +566,8 @@ START_TEST(varformat)
 {
   hOleaut32 = GetModuleHandleA("oleaut32.dll");
 
+  has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
+
   test_VarFormatNumber();
   test_VarFormat();
   test_VarWeekdayName();
index 429ff24..b78e871 100644 (file)
@@ -61,12 +61,8 @@ static WCHAR sz12_true[32];
 #define CHECKPTR(func) p##func = (void*)GetProcAddress(hOleaut32, #func); \
   if (!p##func) { win_skip("function " # func " not available, not testing it\n"); return; }
 
-/* Have IRecordInfo data type? */
-static int HAVE_OLEAUT32_RECORD = 0;
-/* Have I8/UI8 data type? */
-static int HAVE_OLEAUT32_I8 = 0;
-/* Is this an ancient version with support for only I2/I4/R4/R8/DATE? */
-static int IS_ANCIENT = 0;
+/* Has I8/UI8 data type? */
+static BOOL has_i8;
 
 /* When comparing floating point values we cannot expect an exact match
  * because the rounding errors depend on the exact algorithm.
@@ -125,18 +121,9 @@ static void init(void)
     SysFreeString(bstr);
 
     hOleaut32 = GetModuleHandle("oleaut32.dll");
-
-  /* Is a given function exported from oleaut32? */
-#define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
-
-  HAVE_OLEAUT32_I8 = HAVE_FUNC(VarI8FromI1);
-  if (!HAVE_OLEAUT32_I8)
-      skip("No support for I8 and UI8 data types\n");
-
-  HAVE_OLEAUT32_RECORD = HAVE_FUNC(SafeArraySetRecordInfo);
-  IS_ANCIENT = (!HAVE_FUNC(VarI1FromI2));
-
-#undef HAVE_FUNC
+    has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
+    if (!has_i8)
+        skip("No support for I8 and UI8 data types\n");
 }
 
 /* Functions to set a DECIMAL */
@@ -411,8 +398,7 @@ static int IsValidVariantClearVT(VARTYPE vt, VARTYPE extraFlags)
        extraFlags == (VT_ARRAY|VT_BYREF)))
     ret = 1; /* ok */
 
-  if ((vt == VT_RECORD && !HAVE_OLEAUT32_RECORD) ||
-      ((vt == VT_I8 || vt == VT_UI8) && !HAVE_OLEAUT32_I8))
+  if (!has_i8 && (vt == VT_I8 || vt == VT_UI8))
     ret = 0; /* Old versions of oleaut32 */
   return ret;
 }
@@ -474,8 +460,7 @@ static void test_VariantClear(void)
   V_VT(&v) = VT_UI4;
   V_UI4(&v) = ~0u;
   hres = VariantClear(&v);
-  ok((hres == S_OK && V_VT(&v) == VT_EMPTY) ||
-     (IS_ANCIENT && hres == DISP_E_BADVARTYPE && V_VT(&v) == VT_UI4),
+  ok((hres == S_OK && V_VT(&v) == VT_EMPTY),
      "VariantClear: Type set to %d, res %08x\n", V_VT(&v), hres);
   ok(V_UI4(&v) == ~0u, "VariantClear: Overwrote value\n");
 
@@ -483,7 +468,7 @@ static void test_VariantClear(void)
    * Also demonstrates that null pointers in 'v' are not dereferenced.
    * Individual variant tests should test VariantClear() with non-NULL values.
    */
-  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]) && !IS_ANCIENT; i++)
+  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
   {
     VARTYPE vt;
 
@@ -593,7 +578,7 @@ static void test_VariantCopy(void)
    */
 
   /* vSrc == vDst */
-  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]) && !IS_ANCIENT; i++)
+  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
   {
     for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
     {
@@ -621,7 +606,7 @@ static void test_VariantCopy(void)
   memset(&vSrc, 0, sizeof(vSrc));
   V_VT(&vSrc) = VT_UI1;
 
-  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]) && !IS_ANCIENT; i++)
+  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
   {
     for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
     {
@@ -647,7 +632,7 @@ static void test_VariantCopy(void)
   }
 
   /* Test that VariantClear() checks vSrc for validity before copying */
-  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]) && !IS_ANCIENT; i++)
+  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
   {
     for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
     {
@@ -724,7 +709,7 @@ static void test_VariantCopyInd(void)
   memset(buffer, 0, sizeof(buffer));
 
   /* vSrc == vDst */
-  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]) && !IS_ANCIENT; i++)
+  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
   {
     if (ExtraFlags[i] & VT_ARRAY)
       continue; /* Native crashes on NULL safearray */
@@ -755,7 +740,7 @@ static void test_VariantCopyInd(void)
         if ((vt == VT_I8 || vt == VT_UI8) &&
             ExtraFlags[i] == VT_BYREF)
         {
-          if (HAVE_OLEAUT32_I8)
+          if (has_i8)
             hExpected = S_OK; /* Only valid if I8 is a known type */
         }
         else if (IsValidVariantCopyIndVT(vt, ExtraFlags[i]))
@@ -775,7 +760,7 @@ static void test_VariantCopyInd(void)
   V_VT(&vSrc) = VT_UI1|VT_BYREF;
   V_BYREF(&vSrc) = &buffer;
 
-  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]) && !IS_ANCIENT; i++)
+  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
   {
     for (vt = 0; vt <= VT_BSTR_BLOB; vt++)
     {
@@ -801,7 +786,7 @@ static void test_VariantCopyInd(void)
   }
 
   /* bad src */
-  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]) && !IS_ANCIENT; i++)
+  for (i = 0; i < sizeof(ExtraFlags)/sizeof(ExtraFlags[0]); i++)
   {
     if (ExtraFlags[i] & VT_ARRAY)
       continue; /* Native crashes on NULL safearray */
@@ -836,7 +821,7 @@ static void test_VariantCopyInd(void)
         if ((vt == VT_I8 || vt == VT_UI8) &&
             ExtraFlags[i] == VT_BYREF)
         {
-          if (HAVE_OLEAUT32_I8)
+          if (has_i8)
             hExpected = S_OK; /* Only valid if I8 is a known type */
         }
         else if (IsValidVariantCopyIndVT(vt, ExtraFlags[i]))
@@ -1503,7 +1488,7 @@ static void test_VarNumFromParseNum(void)
   SETRGB(4, 0xf); SETRGB(5, 0xf); SETRGB(6, 0xf); SETRGB(7, 0xf);
   SETRGB(8, 0xf); SETRGB(9, 0xf); SETRGB(10, 0xf); SETRGB(11, 0xf);
   SETRGB(12, 0xf); SETRGB(13, 0xf); SETRGB(14, 0xf); SETRGB(15, 0xf);
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     /* We cannot use INTEGER_VTBITS as WinXP and Win2003 are broken(?). They
        truncate the number to the smallest integer size requested:
@@ -1529,7 +1514,7 @@ static void test_VarNumFromParseNum(void)
   SETRGB(4, 0); SETRGB(5, 0); SETRGB(6, 0); SETRGB(7, 0);
   SETRGB(8, 0); SETRGB(9, 0); SETRGB(10, 0); SETRGB(11, 0);
   SETRGB(12, 0); SETRGB(13, 0); SETRGB(14, 0); SETRGB(15, 2);
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     /* We cannot use INTEGER_VTBITS as WinXP and Win2003 are broken(?). They
        truncate the number to the smallest integer size requested:
@@ -1556,7 +1541,7 @@ static void test_VarNumFromParseNum(void)
   SETRGB(4, 0); SETRGB(5, 0); SETRGB(6, 0); SETRGB(7, 0);
   SETRGB(8, 0); SETRGB(9, 0); SETRGB(10, 0); SETRGB(11, 0);
   SETRGB(12, 0); SETRGB(13, 0); SETRGB(14, 0); SETRGB(15, 2);
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     CONVERT(16,0,0,16,4,0, VTBIT_I8); EXPECT_I8(0x80000000,0x00000002);
   }
@@ -2046,12 +2031,11 @@ static void test_VarNot(void)
                 hExpected = S_OK;
                 break;
             case VT_I8: case VT_UI8:
-                if (HAVE_OLEAUT32_I8)
+                if (has_i8)
                     hExpected = S_OK;
                 break;
             case VT_RECORD:
-                if (HAVE_OLEAUT32_RECORD)
-                    hExpected = DISP_E_TYPEMISMATCH;
+                hExpected = DISP_E_TYPEMISMATCH;
                 break;
             case VT_UNKNOWN: case VT_BSTR: case VT_DISPATCH: case VT_ERROR:
                 hExpected = DISP_E_TYPEMISMATCH;
@@ -2091,7 +2075,7 @@ static void test_VarNot(void)
     VARNOT(INT,1,I4,-2);
     VARNOT(UINT,0,I4,-1);
     VARNOT(UINT,1,I4,-2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARNOT(I8,1,I8,-2);
         VARNOT(I8,0,I8,-1);
@@ -2215,7 +2199,7 @@ static void test_VarSub(void)
                 {
                     if (leftvt == VT_RECORD && rightvt == VT_I8)
                     {
-                        if (HAVE_OLEAUT32_I8)
+                        if (has_i8)
                             expectedhres = DISP_E_TYPEMISMATCH;
                         else
                             expectedhres = DISP_E_BADVARTYPE;
@@ -2504,7 +2488,7 @@ static void test_VarMod(void)
   VARMOD(BSTR,R8,strNum0,10,I4,5);
   VARMOD(I4,BSTR,125,strNum1,I4,5);
 
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     VARMOD(BOOL,I8,100,10,I8,0);
     VARMOD(I1,I8,100,10,I8,0);
@@ -2735,7 +2719,7 @@ static void test_VarMod(void)
       else
        V_I4(&v2) = 10000;
 
-      if ((l != VT_I8 && l != VT_UI8 && r != VT_I8 && r != VT_UI8) || HAVE_OLEAUT32_I8)
+      if ((l != VT_I8 && l != VT_UI8 && r != VT_I8 && r != VT_UI8) || has_i8)
       {
         hres = pVarMod(&v1,&v2,&vDst);
         ok(hres == hexpected,
@@ -2828,7 +2812,7 @@ static void test_VarMod(void)
 
   /* test some invalid types */
   /*TODO: not testing VT_DISPATCH */
-  if (HAVE_OLEAUT32_I8)
+  if (has_i8)
   {
     VARMOD2(I8,INT,100,10,EMPTY,0,DISP_E_TYPEMISMATCH);
   }
@@ -2911,7 +2895,7 @@ static void test_VarFix(void)
                 bFail = FALSE;
                 break;
               case VT_I8:
-                if (HAVE_OLEAUT32_I8)
+                if (has_i8)
                   bFail = FALSE;
                 break;
             }
@@ -2933,7 +2917,7 @@ static void test_VarFix(void)
     VARFIX(UI1,1,UI1,1);
     VARFIX(I2,-1,I2,-1);
     VARFIX(I4,-1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARFIX(I8,-1,I8,-1);
     }
@@ -3026,7 +3010,7 @@ static void test_VarInt(void)
                 bFail = FALSE;
                 break;
               case VT_I8:
-                if (HAVE_OLEAUT32_I8)
+                if (has_i8)
                   bFail = FALSE;
                 break;
             }
@@ -3048,7 +3032,7 @@ static void test_VarInt(void)
     VARINT(UI1,1,UI1,1);
     VARINT(I2,-1,I2,-1);
     VARINT(I4,-1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARINT(I8,-1,I8,-1);
     }
@@ -3148,7 +3132,7 @@ static void test_VarNeg(void)
                 bFail = FALSE;
                 break;
             case VT_I8:
-                if (HAVE_OLEAUT32_I8)
+                if (has_i8)
                     bFail = FALSE;
             }
 
@@ -3174,7 +3158,7 @@ static void test_VarNeg(void)
     VARNEG(I4,-((int)(~0u >> 1)) - 1,R8,-2147483648u);
     VARNEG(I4,-1,I4,1);
     VARNEG(I4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARNEG(I8,1,I8,-1);
         VARNEG(I8,-1,I8,1);
@@ -3539,7 +3523,7 @@ static void test_VarXor(void)
     VARXOR(EMPTY,0,I4,1,I4,1);
     VARXOR(EMPTY,0,UI4,0,I4,0);
     VARXOR(EMPTY,0,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(EMPTY,0,I8,0,I8,0);
         VARXOR(EMPTY,0,I8,1,I8,1);
@@ -3579,7 +3563,7 @@ static void test_VarXor(void)
     VARXOR(NULL,0,I4,1,NULL,0);
     VARXOR(NULL,0,UI4,0,NULL,0);
     VARXOR(NULL,0,UI4,1,NULL,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(NULL,0,I8,0,NULL,0);
         VARXOR(NULL,0,I8,1,NULL,0);
@@ -3637,7 +3621,7 @@ static void test_VarXor(void)
     VARXOR(BOOL,VARIANT_TRUE,DATE,-1,I4,0);
     VARXOR(BOOL,VARIANT_TRUE,DATE,0,I4,-1);
     VARXOR(BOOL,VARIANT_FALSE,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(BOOL,VARIANT_TRUE,I8,-1,I8,0);
         VARXOR(BOOL,VARIANT_TRUE,I8,0,I8,-1);
@@ -3694,7 +3678,7 @@ static void test_VarXor(void)
     VARXOR(I1,-1,DATE,-1,I4,0);
     VARXOR(I1,-1,DATE,0,I4,-1);
     VARXOR(I1,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(I1,-1,I8,-1,I8,0);
         VARXOR(I1,-1,I8,0,I8,-1);
@@ -3744,7 +3728,7 @@ static void test_VarXor(void)
     VARXOR(UI1,255,DATE,-1,I4,-256);
     VARXOR(UI1,255,DATE,0,I4,255);
     VARXOR(UI1,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(UI1,255,I8,-1,I8,-256);
         VARXOR(UI1,255,I8,0,I8,255);
@@ -3791,7 +3775,7 @@ static void test_VarXor(void)
     VARXOR(I2,-1,DATE,-1,I4,0);
     VARXOR(I2,-1,DATE,0,I4,-1);
     VARXOR(I2,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(I2,-1,I8,-1,I8,0);
         VARXOR(I2,-1,I8,0,I8,-1);
@@ -3835,7 +3819,7 @@ static void test_VarXor(void)
     VARXOR(UI2,65535,DATE,-1,I4,-65536);
     VARXOR(UI2,65535,DATE,0,I4,65535);
     VARXOR(UI2,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(UI2,65535,I8,-1,I8,-65536);
         VARXOR(UI2,65535,I8,0,I8,65535);
@@ -3876,7 +3860,7 @@ static void test_VarXor(void)
     VARXOR(I4,-1,DATE,-1,I4,0);
     VARXOR(I4,-1,DATE,0,I4,-1);
     VARXOR(I4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(I4,-1,I8,-1,I8,0);
         VARXOR(I4,-1,I8,0,I8,-1);
@@ -3914,7 +3898,7 @@ static void test_VarXor(void)
     VARXOR(UI4,0xffffffff,DATE,-1,I4,0);
     VARXOR(UI4,0xffffffff,DATE,0,I4,-1);
     VARXOR(UI4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(UI4,0xffffffff,I8,0,I8,0xffffffff);
         VARXOR(UI4,VARIANT_FALSE,I8,VARIANT_FALSE,I8,0);
@@ -3949,7 +3933,7 @@ static void test_VarXor(void)
     VARXOR(R4,-1,DATE,-1,I4,0);
     VARXOR(R4,-1,DATE,0,I4,-1);
     VARXOR(R4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(R4,-1,I8,-1,I8,0);
         VARXOR(R4,-1,I8,0,I8,-1);
@@ -3981,7 +3965,7 @@ static void test_VarXor(void)
     VARXOR(R8,-1,DATE,-1,I4,0);
     VARXOR(R8,-1,DATE,0,I4,-1);
     VARXOR(R8,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(R8,-1,I8,-1,I8,0);
         VARXOR(R8,-1,I8,0,I8,-1);
@@ -4010,7 +3994,7 @@ static void test_VarXor(void)
     VARXOR(DATE,-1,DATE,-1,I4,0);
     VARXOR(DATE,-1,DATE,0,I4,-1);
     VARXOR(DATE,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(DATE,-1,I8,-1,I8,0);
         VARXOR(DATE,-1,I8,0,I8,-1);
@@ -4036,7 +4020,7 @@ static void test_VarXor(void)
     VARXORCY(DATE,-1,0,I4,-1);
     VARXORCY(DATE,0,0,I4,0);
 
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARXOR(I8,-1,I8,-1,I8,0);
         VARXOR(I8,-1,I8,0,I8,-1);
@@ -4275,7 +4259,7 @@ static void test_VarOr(void)
     VAROR(EMPTY,0,I4,1,I4,1);
     VAROR(EMPTY,0,UI4,0,I4,0);
     VAROR(EMPTY,0,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(EMPTY,0,I8,0,I8,0);
         VAROR(EMPTY,0,I8,1,I8,1);
@@ -4315,7 +4299,7 @@ static void test_VarOr(void)
     VAROR(NULL,0,I4,1,I4,1);
     VAROR(NULL,0,UI4,0,NULL,0);
     VAROR(NULL,0,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(NULL,0,I8,0,NULL,0);
         VAROR(NULL,0,I8,1,I8,1);
@@ -4373,7 +4357,7 @@ static void test_VarOr(void)
     VAROR(BOOL,VARIANT_TRUE,DATE,-1,I4,-1);
     VAROR(BOOL,VARIANT_TRUE,DATE,0,I4,-1);
     VAROR(BOOL,VARIANT_FALSE,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(BOOL,VARIANT_TRUE,I8,-1,I8,-1);
         VAROR(BOOL,VARIANT_TRUE,I8,0,I8,-1);
@@ -4430,7 +4414,7 @@ static void test_VarOr(void)
     VAROR(I1,-1,DATE,-1,I4,-1);
     VAROR(I1,-1,DATE,0,I4,-1);
     VAROR(I1,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(I1,-1,I8,-1,I8,-1);
         VAROR(I1,-1,I8,0,I8,-1);
@@ -4480,7 +4464,7 @@ static void test_VarOr(void)
     VAROR(UI1,255,DATE,-1,I4,-1);
     VAROR(UI1,255,DATE,0,I4,255);
     VAROR(UI1,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(UI1,255,I8,-1,I8,-1);
         VAROR(UI1,255,I8,0,I8,255);
@@ -4527,7 +4511,7 @@ static void test_VarOr(void)
     VAROR(I2,-1,DATE,-1,I4,-1);
     VAROR(I2,-1,DATE,0,I4,-1);
     VAROR(I2,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(I2,-1,I8,-1,I8,-1);
         VAROR(I2,-1,I8,0,I8,-1);
@@ -4571,7 +4555,7 @@ static void test_VarOr(void)
     VAROR(UI2,65535,DATE,-1,I4,-1);
     VAROR(UI2,65535,DATE,0,I4,65535);
     VAROR(UI2,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(UI2,65535,I8,-1,I8,-1);
         VAROR(UI2,65535,I8,0,I8,65535);
@@ -4612,7 +4596,7 @@ static void test_VarOr(void)
     VAROR(I4,-1,DATE,-1,I4,-1);
     VAROR(I4,-1,DATE,0,I4,-1);
     VAROR(I4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(I4,-1,I8,-1,I8,-1);
         VAROR(I4,-1,I8,0,I8,-1);
@@ -4650,7 +4634,7 @@ static void test_VarOr(void)
     VAROR(UI4,0xffffffff,DATE,-1,I4,-1);
     VAROR(UI4,0xffffffff,DATE,0,I4,-1);
     VAROR(UI4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(UI4,0xffffffff,I8,-1,I8,-1);
         VAROR(UI4,0xffffffff,I8,0,I8,0xffffffff);
@@ -4685,7 +4669,7 @@ static void test_VarOr(void)
     VAROR(R4,-1,DATE,-1,I4,-1);
     VAROR(R4,-1,DATE,0,I4,-1);
     VAROR(R4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(R4,-1,I8,-1,I8,-1);
         VAROR(R4,-1,I8,0,I8,-1);
@@ -4717,7 +4701,7 @@ static void test_VarOr(void)
     VAROR(R8,-1,DATE,-1,I4,-1);
     VAROR(R8,-1,DATE,0,I4,-1);
     VAROR(R8,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(R8,-1,I8,-1,I8,-1);
         VAROR(R8,-1,I8,0,I8,-1);
@@ -4746,7 +4730,7 @@ static void test_VarOr(void)
     VAROR(DATE,-1,DATE,-1,I4,-1);
     VAROR(DATE,-1,DATE,0,I4,-1);
     VAROR(DATE,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(DATE,-1,I8,-1,I8,-1);
         VAROR(DATE,-1,I8,0,I8,-1);
@@ -4772,7 +4756,7 @@ static void test_VarOr(void)
     VARORCY(DATE,-1,0,I4,-1);
     VARORCY(DATE,0,0,I4,0);
 
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAROR(I8,-1,I8,-1,I8,-1);
         VAROR(I8,-1,I8,0,I8,-1);
@@ -5001,7 +4985,7 @@ static void test_VarEqv(void)
     VAREQV(UI1,1,UI1,1,UI1,255);
     VAREQV(UI1,1,UI1,0,UI1,254);
     VAREQV(UI1,0,UI1,1,UI1,254);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VAREQV(UI4,VARIANT_FALSE,I8,VARIANT_FALSE,I8,-1);
         VAREQV(UI4,5,I8,19,I8,-23);
@@ -5410,7 +5394,7 @@ static void test_VarCat(void)
         SKIPTESTS(leftvt);
 
         /* Check if we need/have support for I8 and/or UI8 */
-        if ((leftvt == VT_I8 || leftvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+        if ((leftvt == VT_I8 || leftvt == VT_UI8) && !has_i8)
             continue;
 
         for (rightvt = 0; rightvt <= VT_BSTR_BLOB; rightvt++)
@@ -5427,7 +5411,7 @@ static void test_VarCat(void)
                 continue;
 
             /* Check if we need/have support for I8 and/or UI8 */
-            if ((rightvt == VT_I8 || rightvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+            if ((rightvt == VT_I8 || rightvt == VT_UI8) && !has_i8)
                 continue;
 
             if (leftvt == VT_NULL && rightvt == VT_NULL)
@@ -5514,7 +5498,7 @@ static void test_VarCat(void)
             /* Determine the error code for the vt combination */
             ok(hres == expected_error_num,
                 "VarCat: %d, %d returned error, 0x%X expected 0x%X.\n",
-                leftvt, rightvt, expected_error_num, hres);
+                leftvt, rightvt, hres, expected_error_num);
 
             /* Check types are correct */
             ok(V_VT(&result) == resultvt,
@@ -5794,7 +5778,7 @@ static void test_VarAnd(void)
             SKIPTESTAND(leftvt);
 
             /* Check if we need/have support for I8 and/or UI8 */
-            if ((leftvt == VT_I8 || leftvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+            if ((leftvt == VT_I8 || leftvt == VT_UI8) && !has_i8)
                 continue;
 
             for (rightvt = 0; rightvt <= VT_BSTR_BLOB; rightvt++)
@@ -5803,7 +5787,7 @@ static void test_VarAnd(void)
                 SKIPTESTAND(rightvt);
 
                 /* Check if we need/have support for I8 and/or UI8 */
-                if ((rightvt == VT_I8 || rightvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+                if ((rightvt == VT_I8 || rightvt == VT_UI8) && !has_i8)
                     continue;
 
                 memset(&left, 0, sizeof(left));
@@ -5907,7 +5891,7 @@ static void test_VarAnd(void)
     VARAND(EMPTY,0,UI4,0,I4,0);
     VARAND(EMPTY,0,UI4,1,I4,0);
     VARAND(EMPTY,1,UI4,1,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(EMPTY,0,I8,0,I8,0);
         VARAND(EMPTY,0,I8,1,I8,0);
@@ -5950,7 +5934,7 @@ static void test_VarAnd(void)
     VARAND(NULL,0,I4,1,NULL,0);
     VARAND(NULL,0,UI4,0,I4,0);
     VARAND(NULL,0,UI4,1,NULL,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(NULL,0,I8,0,I8,0);
         VARAND(NULL,0,I8,1,NULL,0);
@@ -6004,7 +5988,7 @@ static void test_VarAnd(void)
     VARAND(BOOL,VARIANT_TRUE,DATE,-1,I4,-1);
     VARAND(BOOL,VARIANT_TRUE,DATE,0,I4,0);
     VARAND(BOOL,VARIANT_FALSE,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(BOOL,VARIANT_TRUE,I8,-1,I8,-1);
         VARAND(BOOL,VARIANT_TRUE,I8,0,I8,0);
@@ -6052,7 +6036,7 @@ static void test_VarAnd(void)
     VARAND(I1,-1,DATE,-1,I4,-1);
     VARAND(I1,-1,DATE,0,I4,0);
     VARAND(I1,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(I1,-1,I8,-1,I8,-1);
         VARAND(I1,-1,I8,0,I8,0);
@@ -6098,7 +6082,7 @@ static void test_VarAnd(void)
     VARAND(UI1,255,DATE,-1,I4,255);
     VARAND(UI1,255,DATE,0,I4,0);
     VARAND(UI1,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(UI1,255,I8,-1,I8,255);
         VARAND(UI1,255,I8,0,I8,0);
@@ -6141,7 +6125,7 @@ static void test_VarAnd(void)
     VARAND(I2,-1,DATE,-1,I4,-1);
     VARAND(I2,-1,DATE,0,I4,0);
     VARAND(I2,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(I2,-1,I8,-1,I8,-1);
         VARAND(I2,-1,I8,0,I8,0);
@@ -6181,7 +6165,7 @@ static void test_VarAnd(void)
     VARAND(UI2,65535,DATE,-1,I4,65535);
     VARAND(UI2,65535,DATE,0,I4,0);
     VARAND(UI2,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(UI2,65535,I8,-1,I8,65535);
         VARAND(UI2,65535,I8,0,I8,0);
@@ -6218,7 +6202,7 @@ static void test_VarAnd(void)
     VARAND(I4,-1,DATE,-1,I4,-1);
     VARAND(I4,-1,DATE,0,I4,0);
     VARAND(I4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(I4,-1,I8,-1,I8,-1);
         VARAND(I4,-1,I8,0,I8,0);
@@ -6252,7 +6236,7 @@ static void test_VarAnd(void)
     VARAND(UI4,0xffffffff,DATE,-1,I4,-1);
     VARAND(UI4,0xffffffff,DATE,0,I4,0);
     VARAND(UI4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(UI4,0xffffffff,I8,0,I8,0);
         VARAND(UI4,0,I8,0,I8,0);
@@ -6282,7 +6266,7 @@ static void test_VarAnd(void)
     VARAND(R4,-1,DATE,-1,I4,-1);
     VARAND(R4,-1,DATE,0,I4,0);
     VARAND(R4,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(R4,-1,I8,-1,I8,-1);
         VARAND(R4,-1,I8,0,I8,0);
@@ -6310,7 +6294,7 @@ static void test_VarAnd(void)
     VARAND(R8,-1,DATE,-1,I4,-1);
     VARAND(R8,-1,DATE,0,I4,0);
     VARAND(R8,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(R8,-1,I8,-1,I8,-1);
         VARAND(R8,-1,I8,0,I8,0);
@@ -6335,7 +6319,7 @@ static void test_VarAnd(void)
     VARAND(DATE,-1,DATE,-1,I4,-1);
     VARAND(DATE,-1,DATE,0,I4,0);
     VARAND(DATE,0,DATE,0,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(DATE,-1,I8,-1,I8,-1);
         VARAND(DATE,-1,I8,0,I8,0);
@@ -6357,7 +6341,7 @@ static void test_VarAnd(void)
     VARANDCY(DATE,-1,0,I4,0);
     VARANDCY(DATE,0,0,I4,0);
 
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARAND(I8,-1,I8,-1,I8,-1);
         VARAND(I8,-1,I8,0,I8,0);
@@ -6774,7 +6758,7 @@ static void test_VarPow(void)
                 /* Determine return type */
                 else if ((leftvt == VT_NULL || rightvt == VT_NULL) &&
                          ((leftvt != VT_I8 && leftvt != VT_UI8 &&
-                           rightvt != VT_I8 && rightvt != VT_UI8) || HAVE_OLEAUT32_I8))
+                           rightvt != VT_I8 && rightvt != VT_UI8) || has_i8))
                     resvt = VT_NULL;
                 else if ((leftvt == VT_EMPTY || leftvt == VT_I2 ||
                     leftvt == VT_I4 || leftvt == VT_R4 ||
@@ -6782,7 +6766,7 @@ static void test_VarPow(void)
                     leftvt == VT_DATE || leftvt == VT_BSTR ||
                     leftvt == VT_BOOL || leftvt == VT_DECIMAL ||
                     (leftvt >= VT_I1 && leftvt <= VT_UI4) ||
-                    (HAVE_OLEAUT32_I8 && (leftvt == VT_I8 || leftvt == VT_UI8)) ||
+                    (has_i8 && (leftvt == VT_I8 || leftvt == VT_UI8)) ||
                     leftvt == VT_INT || leftvt == VT_UINT) &&
                     (rightvt == VT_EMPTY || rightvt == VT_I2 ||
                     rightvt == VT_I4 || rightvt == VT_R4 ||
@@ -6790,7 +6774,7 @@ static void test_VarPow(void)
                     rightvt == VT_DATE || rightvt == VT_BSTR ||
                     rightvt == VT_BOOL || rightvt == VT_DECIMAL ||
                     (rightvt >= VT_I1 && rightvt <= VT_UI4) ||
-                    (HAVE_OLEAUT32_I8 && (rightvt == VT_I8 || rightvt == VT_UI8)) ||
+                    (has_i8 && (rightvt == VT_I8 || rightvt == VT_UI8)) ||
                     rightvt == VT_INT || rightvt == VT_UINT))
                     resvt = VT_R8;
                 else
@@ -6827,7 +6811,7 @@ static void test_VarPow(void)
     VARPOW(EMPTY,0,UI1,3,R8,0.0);
     VARPOW(EMPTY,0,UI2,3,R8,0.0);
     VARPOW(EMPTY,0,UI4,3,R8,0.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(EMPTY,0,I8,3,R8,0.0);
         VARPOW(EMPTY,0,UI8,3,R8,0.0);
@@ -6847,7 +6831,7 @@ static void test_VarPow(void)
     VARPOW(NULL,0,UI1,3,NULL,0);
     VARPOW(NULL,0,UI2,3,NULL,0);
     VARPOW(NULL,0,UI4,3,NULL,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(NULL,0,I8,3,NULL,0);
         VARPOW(NULL,0,UI8,3,NULL,0);
@@ -6867,7 +6851,7 @@ static void test_VarPow(void)
     VARPOW(I2,2,UI1,3,R8,8.0);
     VARPOW(I2,2,UI2,3,R8,8.0);
     VARPOW(I2,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(I2,2,I8,3,R8,8.0);
         VARPOW(I2,2,UI8,3,R8,8.0);
@@ -6887,7 +6871,7 @@ static void test_VarPow(void)
     VARPOW(I4,2,UI1,3,R8,8.0);
     VARPOW(I4,2,UI2,3,R8,8.0);
     VARPOW(I4,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(I4,2,I8,3,R8,8.0);
         VARPOW(I4,2,UI8,3,R8,8.0);
@@ -6907,7 +6891,7 @@ static void test_VarPow(void)
     VARPOW(R4,2,UI1,3,R8,8.0);
     VARPOW(R4,2,UI2,3,R8,8.0);
     VARPOW(R4,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(R4,2,I8,3,R8,8.0);
         VARPOW(R4,2,UI8,3,R8,8.0);
@@ -6927,7 +6911,7 @@ static void test_VarPow(void)
     VARPOW(R8,2,UI1,3,R8,8.0);
     VARPOW(R8,2,UI2,3,R8,8.0);
     VARPOW(R8,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(R8,2,I8,3,R8,8.0);
         VARPOW(R8,2,UI8,3,R8,8.0);
@@ -6947,7 +6931,7 @@ static void test_VarPow(void)
     VARPOW(DATE,2,UI1,3,R8,8.0);
     VARPOW(DATE,2,UI2,3,R8,8.0);
     VARPOW(DATE,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(DATE,2,I8,3,R8,8.0);
         VARPOW(DATE,2,UI8,3,R8,8.0);
@@ -6967,7 +6951,7 @@ static void test_VarPow(void)
     VARPOW(BSTR,num2_str,UI1,3,R8,8.0);
     VARPOW(BSTR,num2_str,UI2,3,R8,8.0);
     VARPOW(BSTR,num2_str,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(BSTR,num2_str,I8,3,R8,8.0);
         VARPOW(BSTR,num2_str,UI8,3,R8,8.0);
@@ -6987,7 +6971,7 @@ static void test_VarPow(void)
     VARPOW(BOOL,VARIANT_TRUE,UI1,3,R8,-1.0);
     VARPOW(BOOL,VARIANT_TRUE,UI2,3,R8,-1.0);
     VARPOW(BOOL,VARIANT_TRUE,UI4,3,R8,-1.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(BOOL,VARIANT_TRUE,I8,3,R8,-1.0);
         VARPOW(BOOL,VARIANT_TRUE,UI8,3,R8,-1.0);
@@ -7007,7 +6991,7 @@ static void test_VarPow(void)
     VARPOW(I1,2,UI1,3,R8,8.0);
     VARPOW(I1,2,UI2,3,R8,8.0);
     VARPOW(I1,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(I1,2,I8,3,R8,8.0);
         VARPOW(I1,2,UI8,3,R8,8.0);
@@ -7027,7 +7011,7 @@ static void test_VarPow(void)
     VARPOW(UI1,2,UI1,3,R8,8.0);
     VARPOW(UI1,2,UI2,3,R8,8.0);
     VARPOW(UI1,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(UI1,2,I8,3,R8,8.0);
         VARPOW(UI1,2,UI8,3,R8,8.0);
@@ -7047,7 +7031,7 @@ static void test_VarPow(void)
     VARPOW(UI2,2,UI1,3,R8,8.0);
     VARPOW(UI2,2,UI2,3,R8,8.0);
     VARPOW(UI2,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(UI2,2,I8,3,R8,8.0);
         VARPOW(UI2,2,UI8,3,R8,8.0);
@@ -7067,14 +7051,14 @@ static void test_VarPow(void)
     VARPOW(UI4,2,UI1,3,R8,8.0);
     VARPOW(UI4,2,UI2,3,R8,8.0);
     VARPOW(UI4,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(UI4,2,I8,3,R8,8.0);
         VARPOW(UI4,2,UI8,3,R8,8.0);
     }
     VARPOW(UI4,2,INT,3,R8,8.0);
     VARPOW(UI4,2,UINT,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(I8,2,EMPTY,0,R8,1.0);
         VARPOW(I8,2,NULL,0,NULL,0);
@@ -7123,7 +7107,7 @@ static void test_VarPow(void)
     VARPOW(INT,2,UI1,3,R8,8.0);
     VARPOW(INT,2,UI2,3,R8,8.0);
     VARPOW(INT,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(INT,2,I8,3,R8,8.0);
         VARPOW(INT,2,UI8,3,R8,8.0);
@@ -7143,7 +7127,7 @@ static void test_VarPow(void)
     VARPOW(UINT,2,UI1,3,R8,8.0);
     VARPOW(UINT,2,UI2,3,R8,8.0);
     VARPOW(UINT,2,UI4,3,R8,8.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARPOW(UINT,2,I8,3,R8,8.0);
         VARPOW(UINT,2,UI8,3,R8,8.0);
@@ -7273,7 +7257,7 @@ static void test_VarDiv(void)
             SKIPTESTDIV(leftvt);
 
             /* Check if we need/have support for I8 */
-            if (leftvt == VT_I8 && !HAVE_OLEAUT32_I8)
+            if (leftvt == VT_I8 && !has_i8)
                 continue;
 
             for (rightvt = 0; rightvt <= VT_BSTR_BLOB; rightvt++)
@@ -7282,7 +7266,7 @@ static void test_VarDiv(void)
                 SKIPTESTDIV(rightvt);
 
                 /* Check if we need/have support for I8 */
-                if (rightvt == VT_I8 && !HAVE_OLEAUT32_I8)
+                if (rightvt == VT_I8 && !has_i8)
                     continue;
 
                 /* Native crashes with VT_BYREF */
@@ -7395,7 +7379,7 @@ static void test_VarDiv(void)
     VARDIV(EMPTY,0,BSTR,num2_str,R8,0.0);
     VARDIV(EMPTY,0,BOOL,VARIANT_TRUE,R8,0.0);
     VARDIV(EMPTY,0,UI1,2,R8,0.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(EMPTY,0,I8,2,R8,0.0);
     }
@@ -7409,7 +7393,7 @@ static void test_VarDiv(void)
     VARDIV(NULL,0,BSTR,num2_str,NULL,0);
     VARDIV(NULL,0,BOOL,VARIANT_TRUE,NULL,0);
     VARDIV(NULL,0,UI1,2,NULL,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(NULL,0,I8,2,NULL,0);
     }
@@ -7421,7 +7405,7 @@ static void test_VarDiv(void)
     VARDIV(I2,1,DATE,2,R8,0.5);
     VARDIV(I2,1,BOOL,VARIANT_TRUE,R8,-1.0);
     VARDIV(I2,1,UI1,2,R8,0.5);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(I2,1,I8,2,R8,0.5);
     }
@@ -7434,7 +7418,7 @@ static void test_VarDiv(void)
     VARDIV(I4,1,BSTR,num2_str,R8,0.5);
     VARDIV(I4,1,BOOL,VARIANT_TRUE,R8,-1.0);
     VARDIV(I4,1,UI1,2,R8,0.5);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(I4,1,I8,2,R8,0.5);
     }
@@ -7447,7 +7431,7 @@ static void test_VarDiv(void)
     VARDIV(R4,1.0f,BSTR,num2_str,R8,0.5);
     VARDIV(R4,1.0f,BOOL,VARIANT_TRUE,R4,-1);
     VARDIV(R4,1.0f,UI1,2,R4,0.5f);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(R4,1.0f,I8,2,R8,0.5);
     }
@@ -7460,7 +7444,7 @@ static void test_VarDiv(void)
     VARDIV(R8,1.0,BSTR,num2_str,R8,0.5);
     VARDIV(R8,1.0,BOOL,VARIANT_TRUE,R8,-1.0);
     VARDIV(R8,1.0,UI1,2,R8,0.5);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(R8,1.0,I8,2,R8,0.5);
     }
@@ -7473,7 +7457,7 @@ static void test_VarDiv(void)
     VARDIV(DATE,1,BSTR,num2_str,R8,0.5);
     VARDIV(DATE,1,BOOL,VARIANT_TRUE,R8,-1.0);
     VARDIV(DATE,1,UI1,2,R8,0.5);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(DATE,1,I8,2,R8,0.5);
     }
@@ -7486,7 +7470,7 @@ static void test_VarDiv(void)
     VARDIV(BSTR,num1_str,BSTR,num2_str,R8,0.5);
     VARDIV(BSTR,num1_str,BOOL,VARIANT_TRUE,R8,-1);
     VARDIV(BSTR,num1_str,UI1,2,R8,0.5);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(BSTR,num1_str,I8,2,R8,0.5);
     }
@@ -7504,7 +7488,7 @@ static void test_VarDiv(void)
     VARDIV(BOOL,VARIANT_TRUE,BOOL,VARIANT_TRUE,R8,1.0);
     VARDIV(BOOL,VARIANT_FALSE,BOOL,VARIANT_TRUE,R8,0.0);
     VARDIV(BOOL,VARIANT_TRUE,UI1,1,R8,-1.0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(BOOL,VARIANT_TRUE,I8,1,R8,-1.0);
     }
@@ -7517,7 +7501,7 @@ static void test_VarDiv(void)
     VARDIV(UI1,1,BSTR,num2_str,R8,0.5);
     VARDIV(UI1,1,BOOL,VARIANT_TRUE,R8,-1);
     VARDIV(UI1,1,UI1,2,R8,0.5);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARDIV(UI1,1,I8,2,R8,0.5);
         VARDIV(I8,1,NULL,0,NULL,0);
@@ -7646,7 +7630,7 @@ static void test_VarIdiv(void)
             SKIPTESTIDIV(leftvt);
 
             /* Check if we need/have support for I8 and/or UI8 */
-            if ((leftvt == VT_I8 || leftvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+            if ((leftvt == VT_I8 || leftvt == VT_UI8) && !has_i8)
                 continue;
 
             for (rightvt = 0; rightvt <= VT_BSTR_BLOB; rightvt++)
@@ -7659,7 +7643,7 @@ static void test_VarIdiv(void)
                     continue;
 
                 /* Check if we need/have support for I8 and/or UI8 */
-                if ((rightvt == VT_I8 || rightvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+                if ((rightvt == VT_I8 || rightvt == VT_UI8) && !has_i8)
                     continue;
 
                 memset(&left, 0, sizeof(left));
@@ -7778,7 +7762,7 @@ static void test_VarIdiv(void)
     VARIDIV(EMPTY,0,UI1,1,I2,0);
     VARIDIV(EMPTY,0,UI2,1,I4,0);
     VARIDIV(EMPTY,0,UI4,1,I4,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(EMPTY,0,I8,1,I8,0);
         VARIDIV(EMPTY,0,UI8,1,I4,0);
@@ -7798,7 +7782,7 @@ static void test_VarIdiv(void)
     VARIDIV(NULL,0,UI1,1,NULL,0);
     VARIDIV(NULL,0,UI2,1,NULL,0);
     VARIDIV(NULL,0,UI4,1,NULL,0);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(NULL,0,I8,1,NULL,0);
         VARIDIV(NULL,0,UI8,1,NULL,0);
@@ -7817,7 +7801,7 @@ static void test_VarIdiv(void)
     VARIDIV(I2,2,UI1,1,I2,2);
     VARIDIV(I2,2,UI2,1,I4,2);
     VARIDIV(I2,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(I2,2,I8,1,I8,2);
         VARIDIV(I2,2,UI8,1,I4,2);
@@ -7836,7 +7820,7 @@ static void test_VarIdiv(void)
     VARIDIV(I4,2,UI1,1,I4,2);
     VARIDIV(I4,2,UI2,1,I4,2);
     VARIDIV(I4,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(I4,2,I8,1,I8,2);
         VARIDIV(I4,2,UI8,1,I4,2);
@@ -7855,7 +7839,7 @@ static void test_VarIdiv(void)
     VARIDIV(R4,2.0f,UI1,1,I4,2);
     VARIDIV(R4,2.0f,UI2,1,I4,2);
     VARIDIV(R4,2.0f,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(R4,2.0f,I8,1,I8,2);
         VARIDIV(R4,2.0f,UI8,1,I4,2);
@@ -7874,7 +7858,7 @@ static void test_VarIdiv(void)
     VARIDIV(R8,2.0,UI1,1,I4,2);
     VARIDIV(R8,2.0,UI2,1,I4,2);
     VARIDIV(R8,2.0,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(R8,2.0,I8,1,I8,2);
         VARIDIV(R8,2.0,UI8,1,I4,2);
@@ -7893,7 +7877,7 @@ static void test_VarIdiv(void)
     VARIDIV(DATE,2,UI1,1,I4,2);
     VARIDIV(DATE,2,UI2,1,I4,2);
     VARIDIV(DATE,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(DATE,2,I8,1,I8,2);
         VARIDIV(DATE,2,UI8,1,I4,2);
@@ -7912,7 +7896,7 @@ static void test_VarIdiv(void)
     VARIDIV(BSTR,num2_str,UI1,1,I4,2);
     VARIDIV(BSTR,num2_str,UI2,1,I4,2);
     VARIDIV(BSTR,num2_str,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(BSTR,num2_str,I8,1,I8,2);
         VARIDIV(BSTR,num2_str,UI8,1,I4,2);
@@ -7931,7 +7915,7 @@ static void test_VarIdiv(void)
     VARIDIV(BOOL,VARIANT_TRUE,UI1,1,I2,-1);
     VARIDIV(BOOL,VARIANT_TRUE,UI2,1,I4,-1);
     VARIDIV(BOOL,VARIANT_TRUE,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(BOOL,VARIANT_TRUE,I8,1,I8,-1);
         VARIDIV(BOOL,VARIANT_TRUE,UI8,1,I4,-1);
@@ -7950,7 +7934,7 @@ static void test_VarIdiv(void)
     VARIDIV(I1,2,UI1,1,I4,2);
     VARIDIV(I1,2,UI2,1,I4,2);
     VARIDIV(I1,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(I1,2,I8,1,I8,2);
         VARIDIV(I1,2,UI8,1,I4,2);
@@ -7969,7 +7953,7 @@ static void test_VarIdiv(void)
     VARIDIV(UI1,2,UI1,1,UI1,2);
     VARIDIV(UI1,2,UI2,1,I4,2);
     VARIDIV(UI1,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(UI1,2,I8,1,I8,2);
         VARIDIV(UI1,2,UI8,1,I4,2);
@@ -7988,7 +7972,7 @@ static void test_VarIdiv(void)
     VARIDIV(UI2,2,UI1,1,I4,2);
     VARIDIV(UI2,2,UI2,1,I4,2);
     VARIDIV(UI2,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(UI2,2,I8,1,I8,2);
         VARIDIV(UI2,2,UI8,1,I4,2);
@@ -8007,14 +7991,14 @@ static void test_VarIdiv(void)
     VARIDIV(UI4,2,UI1,1,I4,2);
     VARIDIV(UI4,2,UI2,1,I4,2);
     VARIDIV(UI4,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(UI4,2,I8,1,I8,2);
         VARIDIV(UI4,2,UI8,1,I4,2);
     }
     VARIDIV(UI4,2,INT,1,I4,2);
     VARIDIV(UI4,2,UINT,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(I8,2,NULL,0,NULL,0);
         VARIDIV(I8,2,I2,1,I8,2);
@@ -8060,7 +8044,7 @@ static void test_VarIdiv(void)
     VARIDIV(INT,2,UI1,1,I4,2);
     VARIDIV(INT,2,UI2,1,I4,2);
     VARIDIV(INT,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(INT,2,UI8,1,I4,2);
     }
@@ -8078,7 +8062,7 @@ static void test_VarIdiv(void)
     VARIDIV(UINT,2,UI1,1,I4,2);
     VARIDIV(UINT,2,UI2,1,I4,2);
     VARIDIV(UINT,2,UI4,1,I4,2);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIDIV(UINT,2,I8,1,I8,2);
         VARIDIV(UINT,2,UI8,1,I4,2);
@@ -8107,7 +8091,7 @@ static void test_VarIdiv(void)
     ok(hres == S_OK && V_I4(&result) == 1,
         "VARIDIV: CY value %d, expected %d\n", V_I4(&result), 1);
 
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         hres = pVarIdiv(&cy, &right, &result);
         ok(hres == S_OK && V_VT(&result) == VT_I8,
@@ -8139,7 +8123,7 @@ static void test_VarIdiv(void)
     ok(hres == S_OK && V_I4(&result) == 1,
         "VARIDIV: DECIMAL value %d, expected %d\n", V_I4(&result), 1);
 
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         hres = pVarIdiv(&dec, &right, &result);
         ok(hres == S_OK && V_VT(&result) == VT_I8,
@@ -8212,7 +8196,7 @@ static void test_VarImp(void)
             SKIPTESTIMP(leftvt);
 
             /* Check if we need/have support for I8 and/or UI8 */
-            if ((leftvt == VT_I8 || leftvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+            if ((leftvt == VT_I8 || leftvt == VT_UI8) && !has_i8)
                 continue;
 
             for (rightvt = 0; rightvt <= VT_BSTR_BLOB; rightvt++)
@@ -8229,7 +8213,7 @@ static void test_VarImp(void)
                     continue;
 
                 /* Check if we need/have support for I8 and/or UI8 */
-                if ((rightvt == VT_I8 || rightvt == VT_UI8) && !HAVE_OLEAUT32_I8)
+                if ((rightvt == VT_I8 || rightvt == VT_UI8) && !has_i8)
                     continue;
 
                 memset(&left, 0, sizeof(left));
@@ -8343,7 +8327,7 @@ static void test_VarImp(void)
     VARIMP(EMPTY,0,UI1,1,I2,-1);
     VARIMP(EMPTY,0,UI2,1,I4,-1);
     VARIMP(EMPTY,0,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(EMPTY,0,I8,1,I8,-1);
         VARIMP(EMPTY,0,UI8,1,I4,-1);
@@ -8363,7 +8347,7 @@ static void test_VarImp(void)
     VARIMP(NULL,0,UI1,1,UI1,1);
     VARIMP(NULL,0,UI2,1,I4,1);
     VARIMP(NULL,0,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(NULL,0,I8,1,I8,1);
         VARIMP(NULL,0,UI8,1,I4,1);
@@ -8382,7 +8366,7 @@ static void test_VarImp(void)
     VARIMP(I2,-1,UI1,1,I2,1);
     VARIMP(I2,-1,UI2,1,I4,1);
     VARIMP(I2,-1,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(I2,-1,I8,1,I8,1);
         VARIMP(I2,-1,UI8,1,I4,1);
@@ -8402,7 +8386,7 @@ static void test_VarImp(void)
     VARIMP(I4,2,UI1,1,I4,-3);
     VARIMP(I4,2,UI2,1,I4,-3);
     VARIMP(I4,2,UI4,1,I4,-3);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(I4,2,I8,1,I8,-3);
         VARIMP(I4,2,UI8,1,I4,-3);
@@ -8422,7 +8406,7 @@ static void test_VarImp(void)
     VARIMP(R4,-1.0f,UI1,1,I4,1);
     VARIMP(R4,-1.0f,UI2,1,I4,1);
     VARIMP(R4,-1.0f,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(R4,-1.0f,I8,1,I8,1);
         VARIMP(R4,-1.0f,UI8,1,I4,1);
@@ -8442,7 +8426,7 @@ static void test_VarImp(void)
     VARIMP(R8,1.0,UI1,1,I4,-1);
     VARIMP(R8,1.0,UI2,1,I4,-1);
     VARIMP(R8,1.0,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(R8,1.0,I8,1,I8,-1);
         VARIMP(R8,1.0,UI8,1,I4,-1);
@@ -8462,7 +8446,7 @@ static void test_VarImp(void)
     VARIMP(DATE,0,UI1,1,I4,-1);
     VARIMP(DATE,0,UI2,1,I4,-1);
     VARIMP(DATE,0,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(DATE,0,I8,1,I8,-1);
         VARIMP(DATE,0,UI8,1,I4,-1);
@@ -8482,7 +8466,7 @@ static void test_VarImp(void)
     VARIMP(BSTR,false_str,UI1,1,I2,-1);
     VARIMP(BSTR,false_str,UI2,1,I4,-1);
     VARIMP(BSTR,false_str,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(BSTR,false_str,I8,1,I8,-1);
         VARIMP(BSTR,false_str,UI8,1,I4,-1);
@@ -8502,7 +8486,7 @@ static void test_VarImp(void)
     VARIMP(BOOL,VARIANT_TRUE,UI1,1,I2,1);
     VARIMP(BOOL,VARIANT_TRUE,UI2,1,I4,1);
     VARIMP(BOOL,VARIANT_TRUE,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(BOOL,VARIANT_TRUE,I8,1,I8,1);
         VARIMP(BOOL,VARIANT_TRUE,UI8,1,I4,1);
@@ -8522,7 +8506,7 @@ static void test_VarImp(void)
     VARIMP(I1,-1,UI1,1,I4,1);
     VARIMP(I1,-1,UI2,1,I4,1);
     VARIMP(I1,-1,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(I1,-1,I8,1,I8,1);
         VARIMP(I1,-1,UI8,1,I4,1);
@@ -8542,7 +8526,7 @@ static void test_VarImp(void)
     VARIMP(UI1,0,UI1,1,UI1,255);
     VARIMP(UI1,0,UI2,1,I4,-1);
     VARIMP(UI1,0,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(UI1,0,I8,1,I8,-1);
         VARIMP(UI1,0,UI8,1,I4,-1);
@@ -8562,7 +8546,7 @@ static void test_VarImp(void)
     VARIMP(UI2,0,UI1,1,I4,-1);
     VARIMP(UI2,0,UI2,1,I4,-1);
     VARIMP(UI2,0,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(UI2,0,I8,1,I8,-1);
         VARIMP(UI2,0,UI8,1,I4,-1);
@@ -8582,14 +8566,14 @@ static void test_VarImp(void)
     VARIMP(UI4,0,UI1,1,I4,-1);
     VARIMP(UI4,0,UI2,1,I4,-1);
     VARIMP(UI4,0,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(UI4,0,I8,1,I8,-1);
         VARIMP(UI4,0,UI8,1,I4,-1);
     }
     VARIMP(UI4,0,INT,-1,I4,-1);
     VARIMP(UI4,0,UINT,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(I8,-1,EMPTY,0,I8,0);
         VARIMP(I8,-1,NULL,0,NULL,0);
@@ -8638,7 +8622,7 @@ static void test_VarImp(void)
     VARIMP(INT,-1,UI1,1,I4,1);
     VARIMP(INT,-1,UI2,1,I4,1);
     VARIMP(INT,-1,UI4,1,I4,1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(INT,-1,I8,1,I8,1);
         VARIMP(INT,-1,UI8,1,I4,1);
@@ -8658,7 +8642,7 @@ static void test_VarImp(void)
     VARIMP(UINT,1,UI1,1,I4,-1);
     VARIMP(UINT,1,UI2,1,I4,-1);
     VARIMP(UINT,1,UI4,1,I4,-1);
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         VARIMP(UINT,1,I8,1,I8,-1);
         VARIMP(UINT,1,UI8,1,I4,-1);
@@ -8687,7 +8671,7 @@ static void test_VarImp(void)
     ok(hres == S_OK && V_I4(&result) == -1,
         "VARIMP: CY value %d, expected %d\n", V_I4(&result), -1);
 
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         hres = pVarImp(&cy, &right, &result);
         ok(hres == S_OK && V_VT(&result) == VT_I8,
@@ -8719,7 +8703,7 @@ static void test_VarImp(void)
     ok(hres == S_OK && V_I4(&result) == -1,
         "VARIMP: DECIMAL value %d, expected %d\n", V_I4(&result), -1);
 
-    if (HAVE_OLEAUT32_I8)
+    if (has_i8)
     {
         hres = pVarImp(&dec, &right, &result);
         ok(hres == S_OK && V_VT(&result) == VT_I8,
index 9fda4e6..dda443d 100644 (file)
@@ -56,21 +56,11 @@ static HMODULE hOleaut32;
   if (!p##func) { \
     win_skip("function " # func " not available, not testing it\n"); return; }
 
-/* Is a given function exported from oleaut32? */
-#define HAVE_FUNC(func) ((void*)GetProcAddress(hOleaut32, #func) != NULL)
-
-/* Have IRecordInfo data type? */
-#define HAVE_OLEAUT32_RECORD  HAVE_FUNC(SafeArraySetRecordInfo)
-/* Have DECIMAL data type with new error checking? */
-#define HAVE_OLEAUT32_DECIMAL HAVE_FUNC(VarDecAdd)
-/* Have CY data type? */
-#define HAVE_OLEAUT32_CY      HAVE_FUNC(VarCyAdd)
-/* Have I8/UI8 data type? */
-#define HAVE_OLEAUT32_I8      HAVE_FUNC(VarI8FromI1)
-/* Have proper locale conversions? */
-#define HAVE_OLEAUT32_LOCALES (HAVE_FUNC(GetVarConversionLocaleSetting) && HAVE_OLEAUT32_I8)
-/* Is this an ancient version with support for only I2/I4/R4/R8/DATE? */
-#define IS_ANCIENT (!HAVE_FUNC(VarI1FromI2))
+/* Has I8/UI8 data type? */
+static BOOL has_i8;
+/* Has proper locale conversions? */
+static BOOL has_locales;
+
 /* Is vt a type unavailable to ancient versions? */
 #define IS_MODERN_VTYPE(vt) (vt==VT_VARIANT||vt==VT_DECIMAL|| \
     vt==VT_I1||vt==VT_UI2||vt==VT_UI4||vt == VT_INT||vt == VT_UINT)
@@ -119,13 +109,10 @@ static HMODULE hOleaut32;
 #define CONVERT_DEC64(func,scl,sgn,hi,mid,lo) SETDEC64(in,scl,sgn,hi,mid,lo); hres = p##func(&in, &out)
 
 #define CONVERT_BADDEC(func) \
-  if (HAVE_OLEAUT32_DECIMAL) \
-  { \
-    CONVERT_DEC(func,29,0,0,0);   EXPECT_INVALID; \
-    CONVERT_DEC(func,0,0x1,0,0);  EXPECT_INVALID; \
-    CONVERT_DEC(func,0,0x40,0,0); EXPECT_INVALID; \
-    CONVERT_DEC(func,0,0x7f,0,0); EXPECT_INVALID; \
-  }
+  CONVERT_DEC(func,29,0,0,0);   EXPECT_INVALID; \
+  CONVERT_DEC(func,0,0x1,0,0);  EXPECT_INVALID; \
+  CONVERT_DEC(func,0,0x40,0,0); EXPECT_INVALID; \
+  CONVERT_DEC(func,0,0x7f,0,0); EXPECT_INVALID;
 
 #define CONVERT_STR(func,str,flags) \
   SetLastError(0); \
@@ -166,23 +153,18 @@ static HMODULE hOleaut32;
   VariantInit(&vDst); \
   V_VT(&vSrc) = vt; \
   (val(&vSrc)) = in; \
-  if (!IS_ANCIENT) { \
-    TYPETEST(VT_I1, V_I1(&vDst), fs); \
-    TYPETEST(VT_UI2, V_UI2(&vDst), fs); \
-    TYPETEST(VT_UI4, V_UI4(&vDst), fs); \
-    TYPETEST(VT_INT, V_INT(&vDst), fs); \
-    TYPETEST(VT_UINT, V_UINT(&vDst), fs); \
-  } else {  \
-    BADVAR(VT_I1); BADVAR(VT_UI2); BADVAR(VT_UI4); \
-    BADVAR(VT_INT); BADVAR(VT_UINT); \
-  } \
+  TYPETEST(VT_I1, V_I1(&vDst), fs); \
+  TYPETEST(VT_UI2, V_UI2(&vDst), fs); \
+  TYPETEST(VT_UI4, V_UI4(&vDst), fs); \
+  TYPETEST(VT_INT, V_INT(&vDst), fs); \
+  TYPETEST(VT_UINT, V_UINT(&vDst), fs); \
   TYPETEST(VT_UI1, V_UI1(&vDst), fs); \
   TYPETEST(VT_I2, V_I2(&vDst), fs); \
   TYPETEST(VT_I4, V_I4(&vDst), fs); \
   TYPETEST(VT_R4, V_R4(&vDst), fs); \
   TYPETEST(VT_R8, V_R8(&vDst), fs); \
   TYPETEST(VT_DATE, V_DATE(&vDst), fs); \
-  if (HAVE_OLEAUT32_I8) \
+  if (has_i8) \
   { \
     TYPETEST(VT_I8, V_I8(&vDst), fs); \
     TYPETEST(VT_UI8, V_UI8(&vDst), fs); \
@@ -193,9 +175,7 @@ static HMODULE hOleaut32;
   VariantInit(&vDst); \
   V_VT(&vSrc) = vt; \
   (val(&vSrc)) = in; \
-  if (!IS_ANCIENT) { \
-    TYPETEST(vtneg, valneg(&vDst), fs); \
-  }
+  TYPETEST(vtneg, valneg(&vDst), fs);
 
 #define INITIAL_TYPETESTI8(vt, val) \
   VariantInit(&vSrc); \
@@ -222,13 +202,10 @@ static HMODULE hOleaut32;
      (V_BOOL(&vDst) == VARIANT_TRUE || (V_VT(&vSrc) == VT_BOOL && V_BOOL(&vDst) == 1)), \
      "->VT_BOOL hres=0x%X, type=%d (should be VT_BOOL), value %d (should be VARIANT_TRUE)\n", \
      hres, V_VT(&vDst), V_BOOL(&vDst)); \
-  if (HAVE_OLEAUT32_CY) \
-  { \
-    hres = VariantChangeTypeEx(&vDst, &vSrc, 0, 0, VT_CY); \
-    ok(hres == S_OK && V_VT(&vDst) == VT_CY && V_CY(&vDst).int64 == CY_MULTIPLIER, \
-       "->VT_CY hres=0x%X, type=%d (should be VT_CY), value (%08x,%08x) (should be CY_MULTIPLIER)\n", \
-       hres, V_VT(&vDst), S(V_CY(&vDst)).Hi, S(V_CY(&vDst)).Lo); \
-  } \
+  hres = VariantChangeTypeEx(&vDst, &vSrc, 0, 0, VT_CY); \
+  ok(hres == S_OK && V_VT(&vDst) == VT_CY && V_CY(&vDst).int64 == CY_MULTIPLIER, \
+     "->VT_CY hres=0x%X, type=%d (should be VT_CY), value (%08x,%08x) (should be CY_MULTIPLIER)\n", \
+     hres, V_VT(&vDst), S(V_CY(&vDst)).Hi, S(V_CY(&vDst)).Lo); \
   if (V_VT(&vSrc) != VT_DATE) \
   { \
     hres = VariantChangeTypeEx(&vDst, &vSrc, 0, 0, VT_BSTR); \
@@ -237,16 +214,13 @@ static HMODULE hOleaut32;
        "->VT_BSTR hres=0x%X, type=%d (should be VT_BSTR), *bstr='%c'\n", \
        hres, V_VT(&vDst), V_BSTR(&vDst) ? *V_BSTR(&vDst) : '?'); \
   } \
-  if (HAVE_OLEAUT32_DECIMAL) \
-  { \
-    hres = VariantChangeTypeEx(&vDst, &vSrc, 0, 0, VT_DECIMAL); \
-    ok(hres == S_OK && V_VT(&vDst) == VT_DECIMAL && \
-       S(U(V_DECIMAL(&vDst))).sign == 0 && S(U(V_DECIMAL(&vDst))).scale == 0 && \
-       V_DECIMAL(&vDst).Hi32 == 0 && U1(V_DECIMAL(&vDst)).Lo64 == (ULONGLONG)in, \
-       "->VT_DECIMAL hres=0x%X, type=%d (should be VT_DECIMAL), sign=%d, scale=%d, hi=%u, lo=(%8x %8x),\n", \
-       hres, V_VT(&vDst), S(U(V_DECIMAL(&vDst))).sign, S(U(V_DECIMAL(&vDst))).scale, \
-       V_DECIMAL(&vDst).Hi32, S1(U1(V_DECIMAL(&vDst))).Mid32, S1(U1(V_DECIMAL(&vDst))).Lo32); \
-  } \
+  hres = VariantChangeTypeEx(&vDst, &vSrc, 0, 0, VT_DECIMAL); \
+  ok(hres == S_OK && V_VT(&vDst) == VT_DECIMAL && \
+     S(U(V_DECIMAL(&vDst))).sign == 0 && S(U(V_DECIMAL(&vDst))).scale == 0 && \
+     V_DECIMAL(&vDst).Hi32 == 0 && U1(V_DECIMAL(&vDst)).Lo64 == (ULONGLONG)in, \
+     "->VT_DECIMAL hres=0x%X, type=%d (should be VT_DECIMAL), sign=%d, scale=%d, hi=%u, lo=(%8x %8x),\n", \
+     hres, V_VT(&vDst), S(U(V_DECIMAL(&vDst))).sign, S(U(V_DECIMAL(&vDst))).scale, \
+     V_DECIMAL(&vDst).Hi32, S1(U1(V_DECIMAL(&vDst))).Mid32, S1(U1(V_DECIMAL(&vDst))).Lo32); \
   hres = VariantChangeTypeEx(&vDst, &vSrc, 0, 0, VT_EMPTY); \
   ok(hres == S_OK && V_VT(&vDst) == VT_EMPTY, "->VT_EMPTY hres=0x%X, type=%d (should be VT_EMPTY)\n", hres, V_VT(&vDst)); \
   hres = VariantChangeTypeEx(&vDst, &vSrc, 0, 0, VT_NULL); \
@@ -254,11 +228,8 @@ static HMODULE hOleaut32;
   MISMATCH(VT_DISPATCH); \
   MISMATCH(VT_ERROR); \
   MISMATCH(VT_UNKNOWN); \
-  if (!IS_ANCIENT) { MISMATCH(VT_VARIANT); } else { BADVAR(VT_VARIANT); } \
-  if (HAVE_OLEAUT32_RECORD) \
-  { \
-    MISMATCH(VT_RECORD); \
-  } \
+  MISMATCH(VT_VARIANT); \
+  MISMATCH(VT_RECORD); \
   BADVAR(VT_VOID); \
   BADVAR(VT_HRESULT); \
   BADVAR(VT_SAFEARRAY); \
@@ -488,6 +459,7 @@ static HRESULT (WINAPI *pVarDecSub)(const DECIMAL*,const DECIMAL*,DECIMAL*);
 static HRESULT (WINAPI *pVarDecMul)(const DECIMAL*,const DECIMAL*,DECIMAL*);
 static HRESULT (WINAPI *pVarDecDiv)(const DECIMAL*,const DECIMAL*,DECIMAL*);
 static HRESULT (WINAPI *pVarDecCmp)(const DECIMAL*,const DECIMAL*);
+static HRESULT (WINAPI *pVarDecCmpR8)(const DECIMAL*,double);
 static HRESULT (WINAPI *pVarDecNeg)(const DECIMAL*,DECIMAL*);
 
 static HRESULT (WINAPI *pVarBoolFromUI1)(BYTE,VARIANT_BOOL*);
@@ -847,10 +819,7 @@ static void test_VarI1FromStr(void)
 
 static void test_VarI1Copy(void)
 {
-  if (!IS_ANCIENT)
-  {
-      COPYTEST(1, VT_I1, V_I1(&vSrc), V_I1(&vDst), V_I1REF(&vSrc), V_I1REF(&vDst), "%d");
-  }
+  COPYTEST(1, VT_I1, V_I1(&vSrc), V_I1(&vDst), V_I1REF(&vSrc), V_I1REF(&vDst), "%d");
 }
 
 static void test_VarI1ChangeTypeEx(void)
@@ -861,12 +830,9 @@ static void test_VarI1ChangeTypeEx(void)
 
   in = 1;
 
-  if (!IS_ANCIENT)
-  {
-      INITIAL_TYPETEST(VT_I1, V_I1, "%d");
-      COMMON_TYPETEST;
-      NEGATIVE_TYPETEST(VT_I1, V_I1, "%d", VT_UI1, V_UI1);
-  }
+  INITIAL_TYPETEST(VT_I1, V_I1, "%d");
+  COMMON_TYPETEST;
+  NEGATIVE_TYPETEST(VT_I1, V_I1, "%d", VT_UI1, V_UI1);
 }
 
 #undef CONV_TYPE
@@ -1620,10 +1586,7 @@ static void test_VarUI2FromStr(void)
 
 static void test_VarUI2Copy(void)
 {
-  if (!IS_ANCIENT)
-  {
-      COPYTEST(1, VT_UI2, V_UI2(&vSrc), V_UI2(&vDst), V_UI2REF(&vSrc), V_UI2REF(&vDst), "%d");
-  }
+  COPYTEST(1, VT_UI2, V_UI2(&vSrc), V_UI2(&vDst), V_UI2REF(&vSrc), V_UI2REF(&vDst), "%d");
 }
 
 static void test_VarUI2ChangeTypeEx(void)
@@ -1634,12 +1597,9 @@ static void test_VarUI2ChangeTypeEx(void)
 
   in = 1;
 
-  if (!IS_ANCIENT)
-  {
-    INITIAL_TYPETEST(VT_UI2, V_UI2, "%d");
-    COMMON_TYPETEST;
-    NEGATIVE_TYPETEST(VT_UI2, V_UI2, "%d", VT_I2, V_I2);
-  }
+  INITIAL_TYPETEST(VT_UI2, V_UI2, "%d");
+  COMMON_TYPETEST;
+  NEGATIVE_TYPETEST(VT_UI2, V_UI2, "%d", VT_I2, V_I2);
 }
 
 /*
@@ -2108,10 +2068,7 @@ static void test_VarUI4FromStr(void)
 
 static void test_VarUI4Copy(void)
 {
-  if (!IS_ANCIENT)
-  {
-      COPYTEST(1u, VT_UI4, V_UI4(&vSrc), V_UI4(&vDst), V_UI4REF(&vSrc), V_UI4REF(&vDst), "%u");
-  }
+  COPYTEST(1u, VT_UI4, V_UI4(&vSrc), V_UI4(&vDst), V_UI4REF(&vSrc), V_UI4REF(&vDst), "%u");
 }
 
 static void test_VarUI4ChangeTypeEx(void)
@@ -2122,12 +2079,9 @@ static void test_VarUI4ChangeTypeEx(void)
 
   in = 1;
 
-  if (!IS_ANCIENT)
-  {
-    INITIAL_TYPETEST(VT_UI4, V_UI4, "%u");
-    COMMON_TYPETEST;
-    NEGATIVE_TYPETEST(VT_UI4, V_UI4, "%u", VT_I4, V_I4);
-  }
+  INITIAL_TYPETEST(VT_UI4, V_UI4, "%u");
+  COMMON_TYPETEST;
+  NEGATIVE_TYPETEST(VT_UI4, V_UI4, "%u", VT_I4, V_I4);
 }
 
 /*
@@ -2363,7 +2317,7 @@ static void test_VarI8Copy(void)
   VARIANTARG vSrc, vDst;
   LONGLONG in = 1;
 
-  if (!HAVE_OLEAUT32_I8)
+  if (!has_i8)
   {
     win_skip("I8 and UI8 data types are not available\n");
     return;
@@ -2394,7 +2348,7 @@ static void test_VarI8ChangeTypeEx(void)
   LONG64 in;
   VARIANTARG vSrc, vDst;
 
-  if (!HAVE_OLEAUT32_I8)
+  if (!has_i8)
   {
     win_skip("I8 and UI8 data types are not available\n");
     return;
@@ -2632,7 +2586,7 @@ static void test_VarUI8Copy(void)
   VARIANTARG vSrc, vDst;
   ULONGLONG in = 1;
 
-  if (!HAVE_OLEAUT32_I8)
+  if (!has_i8)
   {
     win_skip("I8 and UI8 data types are not available\n");
     return;
@@ -2663,7 +2617,7 @@ static void test_VarUI8ChangeTypeEx(void)
   ULONG64 in;
   VARIANTARG vSrc, vDst;
 
-  if (!HAVE_OLEAUT32_I8)
+  if (!has_i8)
   {
     win_skip("I8 and UI8 data types are not available\n");
     return;
@@ -3523,7 +3477,7 @@ static void test_VarDateChangeTypeEx(void)
   VariantClear(&vDst);
 
   lcid = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
-  if (HAVE_OLEAUT32_LOCALES)
+  if (has_locales)
   {
     hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, VARIANT_NOUSEROVERRIDE|VARIANT_USE_NLS, VT_BSTR);
     ok(hres == S_OK && V_VT(&vDst) == VT_BSTR && V_BSTR(&vDst) && !lstrcmpW(V_BSTR(&vDst), sz25570Nls), 
@@ -4264,6 +4218,8 @@ static void test_VarDecFromCy(void)
 #define MATH1(func) hres = p##func(&l, &out)
 #undef MATH2
 #define MATH2(func) hres = p##func(&l, &r, &out)
+#undef MATH3
+#define MATH3(func) hres = p##func(&l, r)
 
 static void test_VarDecAbs(void)
 {
@@ -4338,6 +4294,9 @@ static void test_VarDecAdd(void)
   ok(hres == DISP_E_OVERFLOW,"Expected overflow, got (%d,%d,%d,(%8x,%8x)x) hres 0x%08x\n",
      S(U(out)).scale, S(U(out)).sign, out.Hi32, S1(U1(out)).Mid32, S1(U1(out)).Lo32, hres);
 
+  SETDEC(l,3,128,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF);
+  MATH2(VarDecAdd); todo_wine EXPECTDEC64(0,0,-1,0xFFFFFFFF,0xFFFFFF84);
+
   /* Promotes to the highest scale, so here the results are in the scale of 2 */
   SETDEC(l,2,0,0,0);   SETDEC(r,0,0,0,0); MATH2(VarDecAdd); EXPECTDEC(2,0,0,0);
   SETDEC(l,2,0,0,100); SETDEC(r,0,0,0,1); MATH2(VarDecAdd); EXPECTDEC(2,0,0,200);
@@ -4558,6 +4517,38 @@ static void test_VarDecCmp(void)
   SETDEC(out,0,DECIMAL_NEG,-1,-1); SETDEC(l,0,DECIMAL_NEG,0,0); MATH1(VarDecCmp); EXPECT_GT;
   SETDEC(out,0,DECIMAL_NEG,-1,-1); SETDEC(l,0,DECIMAL_NEG,-1,-1); MATH1(VarDecCmp); EXPECT_EQ;
 
+  SETDEC(l,3,0,0,123456); SETDEC64(out,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF);
+  MATH1(VarDecCmp); todo_wine EXPECT_LT;
+}
+
+static void test_VarDecCmpR8(void)
+{
+  HRESULT hres;
+  DECIMAL l;
+  double r;
+
+  CHECKPTR(VarDecCmpR8);
+
+  SETDEC(l,0,0,0,1); r = 0.0;  MATH3(VarDecCmpR8); EXPECT_GT;
+  SETDEC(l,0,0,0,1); r = 0.1;  MATH3(VarDecCmpR8); EXPECT_GT;
+  SETDEC(l,0,0,0,1); r = -0.1; MATH3(VarDecCmpR8); EXPECT_GT;
+
+  SETDEC(l,0,DECIMAL_NEG,0,1); r = 0.0;  MATH3(VarDecCmpR8); EXPECT_LT;
+  SETDEC(l,0,DECIMAL_NEG,0,1); r = 0.1;  MATH3(VarDecCmpR8); EXPECT_LT;
+  SETDEC(l,0,DECIMAL_NEG,0,1); r = -0.1; MATH3(VarDecCmpR8); EXPECT_LT;
+
+  SETDEC(l,0,0,0,0); r = 0.0;  MATH3(VarDecCmpR8); EXPECT_EQ;
+  SETDEC(l,0,0,0,0); r = 0.1;  MATH3(VarDecCmpR8); EXPECT_LT;
+  SETDEC(l,0,0,0,0); r = -0.1; MATH3(VarDecCmpR8); EXPECT_GT;
+
+  SETDEC(l,0,DECIMAL_NEG,0,0); r = 0.0;  MATH3(VarDecCmpR8); EXPECT_EQ;
+  SETDEC(l,0,DECIMAL_NEG,0,0); r = 0.1;  MATH3(VarDecCmpR8); EXPECT_LT;
+  SETDEC(l,0,DECIMAL_NEG,0,0); r = -0.1; MATH3(VarDecCmpR8); EXPECT_GT;
+
+  SETDEC(l,0,0,0,1);             r = DECIMAL_NEG; MATH3(VarDecCmpR8); EXPECT_LT;
+  SETDEC(l,0,DECIMAL_NEG,0,0);   r = DECIMAL_NEG; MATH3(VarDecCmpR8); EXPECT_LT;
+  SETDEC(l,0,0,-1,-1);           r = DECIMAL_NEG; MATH3(VarDecCmpR8); EXPECT_GT;
+  SETDEC(l,0,DECIMAL_NEG,-1,-1); r = DECIMAL_NEG; MATH3(VarDecCmpR8); EXPECT_LT;
 }
 
 /*
@@ -4704,14 +4695,10 @@ static void test_VarBoolFromDec(void)
   CHECKPTR(VarBoolFromDec);
   CONVERT_BADDEC(VarBoolFromDec);
 
-  if (HAVE_OLEAUT32_DECIMAL)
-  {
-    /* Early versions of oleaut32 don't catch these errors */
-    CONVERT_DEC(VarBoolFromDec,29,0,0,0);   EXPECT_INVALID;
-    CONVERT_DEC(VarBoolFromDec,0,0x1,0,0);  EXPECT_INVALID;
-    CONVERT_DEC(VarBoolFromDec,0,0x40,0,0); EXPECT_INVALID;
-    CONVERT_DEC(VarBoolFromDec,0,0x7f,0,0); EXPECT_INVALID;
-  }
+  CONVERT_DEC(VarBoolFromDec,29,0,0,0);   EXPECT_INVALID;
+  CONVERT_DEC(VarBoolFromDec,0,0x1,0,0);  EXPECT_INVALID;
+  CONVERT_DEC(VarBoolFromDec,0,0x40,0,0); EXPECT_INVALID;
+  CONVERT_DEC(VarBoolFromDec,0,0x7f,0,0); EXPECT_INVALID;
 
   CONVERT_DEC(VarBoolFromDec,0,0x80,0,1); EXPECT(VARIANT_TRUE);
   CONVERT_DEC(VarBoolFromDec,0,0,0,0);    EXPECT(VARIANT_FALSE);
@@ -4773,7 +4760,7 @@ static void test_VarBoolFromStr(void)
   /* And is still not case sensitive */
   CONVERT_STR(VarBoolFromStr,"False",0); EXPECT(VARIANT_FALSE);
 
-  if (HAVE_OLEAUT32_LOCALES)
+  if (has_locales)
   {
     /* French is rejected without VARIANT_LOCALBOOL */
     CONVERT_STR(VarBoolFromStr,"faux",0); EXPECT_MISMATCH;
@@ -4793,7 +4780,7 @@ static void test_VarBoolFromStr(void)
   CONVERT_STR(VarBoolFromStr,"-1",0); EXPECT(VARIANT_TRUE);
   CONVERT_STR(VarBoolFromStr,"+1",0); EXPECT(VARIANT_TRUE);
 
-  if (HAVE_OLEAUT32_LOCALES)
+  if (has_locales)
   {
     /* Numeric strings are read as floating point numbers. The line below fails
      * because '.' is not a valid decimal separator for Polish numbers */
@@ -4838,14 +4825,11 @@ static void test_VarBoolChangeTypeEx(void)
   V_VT(&vSrc) = VT_BOOL;
   V_BOOL(&vSrc) = 1;
 
-  if (!IS_ANCIENT)
-  {
-      BOOL_STR(VARIANT_ALPHABOOL, szTrue);
-      V_BOOL(&vSrc) = 0;
-      BOOL_STR(VARIANT_ALPHABOOL, szFalse);
-  }
+  BOOL_STR(VARIANT_ALPHABOOL, szTrue);
+  V_BOOL(&vSrc) = 0;
+  BOOL_STR(VARIANT_ALPHABOOL, szFalse);
 
-  if (HAVE_OLEAUT32_LOCALES)
+  if (has_locales)
   {
     lcid = MAKELCID(MAKELANGID(LANG_FRENCH, SUBLANG_DEFAULT), SORT_DEFAULT);
 
@@ -5719,19 +5703,16 @@ static void test_IUnknownChangeTypeEx(void)
     {
       if (vt == VT_I8 || vt == VT_UI8)
       {
-        if (HAVE_OLEAUT32_I8)
+        if (has_i8)
           hExpected = DISP_E_TYPEMISMATCH;
       }
       else if (vt == VT_RECORD)
       {
-        if (HAVE_OLEAUT32_RECORD)
-          hExpected = DISP_E_TYPEMISMATCH;
+        hExpected = DISP_E_TYPEMISMATCH;
       }
       else if (vt  >= VT_I2 && vt <= VT_UINT && vt != (VARTYPE)15)
         hExpected = DISP_E_TYPEMISMATCH;
     }
-    if (IS_ANCIENT && IS_MODERN_VTYPE(vt))
-        hExpected = DISP_E_BADVARTYPE;
 
     hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
     ok(hres == hExpected,
@@ -5872,19 +5853,16 @@ static void test_ErrorChangeTypeEx(void)
     {
       if (vt == VT_I8 || vt == VT_UI8)
       {
-        if (HAVE_OLEAUT32_I8)
+        if (has_i8)
           hExpected = DISP_E_TYPEMISMATCH;
       }
       else if (vt == VT_RECORD)
       {
-        if (HAVE_OLEAUT32_RECORD)
-          hExpected = DISP_E_TYPEMISMATCH;
+        hExpected = DISP_E_TYPEMISMATCH;
       }
       else if (vt <= VT_UINT && vt != (VARTYPE)15)
         hExpected = DISP_E_TYPEMISMATCH;
     }
-    if (IS_ANCIENT && IS_MODERN_VTYPE(vt))
-        hExpected = DISP_E_BADVARTYPE;
 
     ok(hres == hExpected,
      "change err: vt %d expected 0x%08x, got 0x%08x\n", vt, hExpected, hres);
@@ -5911,13 +5889,12 @@ static void test_EmptyChangeTypeEx(void)
 
     if (vt == VT_I8 || vt == VT_UI8)
     {
-      if (HAVE_OLEAUT32_I8)
+      if (has_i8)
         hExpected = S_OK;
     }
     else if (vt == VT_RECORD)
     {
-      if (HAVE_OLEAUT32_RECORD)
-        hExpected = DISP_E_TYPEMISMATCH;
+      hExpected = DISP_E_TYPEMISMATCH;
     }
     else if (vt == VT_VARIANT || vt == VT_DISPATCH ||
               vt == VT_UNKNOWN || vt == VT_ERROR)
@@ -5927,9 +5904,6 @@ static void test_EmptyChangeTypeEx(void)
     else if (vt <= VT_UINT && vt != (VARTYPE)15)
       hExpected = S_OK;
 
-    if (IS_ANCIENT && IS_MODERN_VTYPE(vt))
-        hExpected = DISP_E_BADVARTYPE;
-
     hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
 
     ok(hres == hExpected && (hres != S_OK || V_VT(&vDst) == vt),
@@ -5960,13 +5934,12 @@ static void test_NullChangeTypeEx(void)
 
     if (vt == VT_I8 || vt == VT_UI8)
     {
-      if (HAVE_OLEAUT32_I8)
+      if (has_i8)
         hExpected = DISP_E_TYPEMISMATCH;
     }
     else if (vt == VT_RECORD)
     {
-      if (HAVE_OLEAUT32_RECORD)
-        hExpected = DISP_E_TYPEMISMATCH;
+      hExpected = DISP_E_TYPEMISMATCH;
     }
     else if (vt == VT_NULL)
     {
@@ -5977,9 +5950,6 @@ static void test_NullChangeTypeEx(void)
               (vt <= VT_UINT && vt != (VARTYPE)15))
       hExpected = DISP_E_TYPEMISMATCH;
 
-    if (IS_ANCIENT && IS_MODERN_VTYPE(vt))
-        hExpected = DISP_E_BADVARTYPE;
-
     hres = VariantChangeTypeEx(&vDst, &vSrc, lcid, 0, vt);
 
     ok(hres == hExpected && (hres != S_OK || V_VT(&vDst) == vt),
@@ -6124,6 +6094,9 @@ START_TEST(vartype)
 {
   hOleaut32 = GetModuleHandleA("oleaut32.dll");
 
+  has_i8 = GetProcAddress(hOleaut32, "VarI8FromI1") != NULL;
+  has_locales = has_i8 && GetProcAddress(hOleaut32, "GetVarConversionLocaleSetting") != NULL;
+
   trace("LCIDs: System=0x%08x, User=0x%08x\n", GetSystemDefaultLCID(),
         GetUserDefaultLCID());
 
@@ -6364,6 +6337,7 @@ START_TEST(vartype)
   test_VarDecAdd();
   test_VarDecSub();
   test_VarDecCmp();
+  test_VarDecCmpR8();
   test_VarDecMul();
   test_VarDecDiv();