[OLE32_WINETEST] Sync with Wine Staging 4.18. CORE-16441

This commit is contained in:
Amine Khaldi 2019-11-10 14:11:19 +01:00
parent 0f5d91b750
commit fc6e4ed576
5 changed files with 264 additions and 88 deletions

View file

@ -46,7 +46,7 @@ static inline char *dump_fmtetc(FORMATETC *fmt)
{ {
static char buf[100]; static char buf[100];
snprintf(buf, sizeof(buf), "cf %04x ptd %p aspect %x lindex %d tymed %x", sprintf(buf, "cf %04x ptd %p aspect %x lindex %d tymed %x",
fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed); fmt->cfFormat, fmt->ptd, fmt->dwAspect, fmt->lindex, fmt->tymed);
return buf; return buf;
} }

View file

@ -39,7 +39,7 @@
#include "initguid.h" #include "initguid.h"
#define DEFINE_EXPECT(func) \ #define DEFINE_EXPECT(func) \
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE static BOOL expect_ ## func = FALSE; static unsigned int called_ ## func = 0
#define SET_EXPECT(func) \ #define SET_EXPECT(func) \
expect_ ## func = TRUE expect_ ## func = TRUE
@ -47,7 +47,7 @@
#define CHECK_EXPECT2(func) \ #define CHECK_EXPECT2(func) \
do { \ do { \
ok(expect_ ##func, "unexpected call " #func "\n"); \ ok(expect_ ##func, "unexpected call " #func "\n"); \
called_ ## func = TRUE; \ called_ ## func++; \
}while(0) }while(0)
#define CHECK_EXPECT(func) \ #define CHECK_EXPECT(func) \
@ -56,13 +56,18 @@
expect_ ## func = FALSE; \ expect_ ## func = FALSE; \
}while(0) }while(0)
#define CHECK_CALLED(func) \ #define CHECK_CALLED(func, n) \
do { \ do { \
ok(called_ ## func, "expected " #func "\n"); \ ok(called_ ## func == n, "expected " #func " called %u times, got %u\n", n, called_ ## func); \
expect_ ## func = called_ ## func = FALSE; \ expect_ ## func = FALSE; \
called_ ## func = 0; \
}while(0) }while(0)
DEFINE_EXPECT(CreateStub); DEFINE_EXPECT(CreateStub);
DEFINE_EXPECT(PreInitialize);
DEFINE_EXPECT(PostInitialize);
DEFINE_EXPECT(PreUninitialize);
DEFINE_EXPECT(PostUninitialize);
/* functions that are not present on all versions of Windows */ /* functions that are not present on all versions of Windows */
static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit); static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
@ -788,7 +793,7 @@ static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID
if (ppvObj == NULL) return E_POINTER; if (ppvObj == NULL) return E_POINTER;
if (IsEqualGUID(riid, &IID_IUnknown) || if (IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IClassFactory)) IsEqualGUID(riid, &IID_IMessageFilter))
{ {
*ppvObj = iface; *ppvObj = iface;
IMessageFilter_AddRef(iface); IMessageFilter_AddRef(iface);
@ -1031,7 +1036,7 @@ static HRESULT WINAPI PSFactoryBuffer_CreateStub(
{ {
CHECK_EXPECT(CreateStub); CHECK_EXPECT(CreateStub);
ok(pUnkServer == (IUnknown*)&Test_Unknown, "unexpected pUnkServer %p\n", pUnkServer); ok(pUnkServer == &Test_Unknown, "unexpected pUnkServer %p\n", pUnkServer);
if(!ps_factory_buffer) if(!ps_factory_buffer)
return E_NOTIMPL; return E_NOTIMPL;
@ -1120,7 +1125,7 @@ static void test_CoRegisterPSClsid(void)
SET_EXPECT(CreateStub); SET_EXPECT(CreateStub);
hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); hr = CoMarshalInterface(stream, &IID_IWineTest, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr); ok(hr == E_NOTIMPL, "CoMarshalInterface should have returned E_NOTIMPL instead of 0x%08x\n", hr);
CHECK_CALLED(CreateStub); CHECK_CALLED(CreateStub, 1);
hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid); hr = CoGetPSClsid(&IID_IEnumOLEVERB, &clsid);
ok_ole_success(hr, "CoGetPSClsid"); ok_ole_success(hr, "CoGetPSClsid");
@ -1134,7 +1139,7 @@ static void test_CoRegisterPSClsid(void)
SET_EXPECT(CreateStub); SET_EXPECT(CreateStub);
hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, (IUnknown*)&EnumOLEVERB, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr); ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
CHECK_CALLED(CreateStub); CHECK_CALLED(CreateStub, 1);
hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); hr = CoMarshalInterface(stream, &IID_IEnumOLEVERB, &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr); ok(hr == S_OK, "CoMarshalInterface should have returned S_OK instead of 0x%08x\n", hr);
@ -3306,27 +3311,47 @@ static ULONG WINAPI testinitialize_Release(IInitializeSpy *iface)
return 1; return 1;
} }
static DWORD expected_coinit_flags;
static ULARGE_INTEGER init_cookies[3];
static BOOL revoke_spies_on_uninit;
static HRESULT WINAPI testinitialize_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs) static HRESULT WINAPI testinitialize_PreInitialize(IInitializeSpy *iface, DWORD coinit, DWORD aptrefs)
{ {
ok(0, "unexpected call\n"); CHECK_EXPECT2(PreInitialize);
return E_NOTIMPL; ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags);
return S_OK;
} }
static HRESULT WINAPI testinitialize_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs) static HRESULT WINAPI testinitialize_PostInitialize(IInitializeSpy *iface, HRESULT hr, DWORD coinit, DWORD aptrefs)
{ {
ok(0, "unexpected call\n"); CHECK_EXPECT2(PostInitialize);
return E_NOTIMPL; ok(coinit == expected_coinit_flags, "Unexpected init flags %#x, expected %#x.\n", coinit, expected_coinit_flags);
return hr;
} }
static HRESULT WINAPI testinitialize_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs) static HRESULT WINAPI testinitialize_PreUninitialize(IInitializeSpy *iface, DWORD aptrefs)
{ {
ok(0, "unexpected call\n"); HRESULT hr;
return E_NOTIMPL; CHECK_EXPECT2(PreUninitialize);
if (revoke_spies_on_uninit)
{
hr = CoRevokeInitializeSpy(init_cookies[0]);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = CoRevokeInitializeSpy(init_cookies[1]);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = CoRevokeInitializeSpy(init_cookies[2]);
ok(hr == S_OK, "got 0x%08x\n", hr);
revoke_spies_on_uninit = FALSE;
}
return S_OK;
} }
static HRESULT WINAPI testinitialize_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs) static HRESULT WINAPI testinitialize_PostUninitialize(IInitializeSpy *iface, DWORD aptrefs)
{ {
ok(0, "unexpected call\n"); CHECK_EXPECT2(PostUninitialize);
return E_NOTIMPL; return E_NOTIMPL;
} }
@ -3343,76 +3368,134 @@ static const IInitializeSpyVtbl testinitializevtbl =
static IInitializeSpy testinitialize = { &testinitializevtbl }; static IInitializeSpy testinitialize = { &testinitializevtbl };
static void test_IInitializeSpy(void) static DWORD WINAPI test_init_spies_proc(void *arg)
{ {
ULARGE_INTEGER cookie, cookie1, cookie2;
HRESULT hr; HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
hr = CoRevokeInitializeSpy(init_cookies[2]);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
CoUninitialize();
return 0;
}
static void test_IInitializeSpy(BOOL mt)
{
HRESULT hr;
if (mt)
{
hr = pCoInitializeEx(NULL, COINIT_MULTITHREADED);
ok(hr == S_OK, "CoInitializeEx failed: %#x\n", hr);
}
hr = CoRegisterInitializeSpy(NULL, NULL); hr = CoRegisterInitializeSpy(NULL, NULL);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
cookie.QuadPart = 1; init_cookies[0].QuadPart = 1;
hr = CoRegisterInitializeSpy(NULL, &cookie); hr = CoRegisterInitializeSpy(NULL, &init_cookies[0]);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
ok(cookie.QuadPart == 1, "got wrong cookie\n"); ok(init_cookies[0].QuadPart == 1, "got wrong cookie\n");
hr = CoRegisterInitializeSpy(&testinitialize, NULL); hr = CoRegisterInitializeSpy(&testinitialize, NULL);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
cookie.HighPart = 0; init_cookies[0].HighPart = 0;
cookie.LowPart = 1; init_cookies[0].LowPart = 1;
hr = CoRegisterInitializeSpy(&testinitialize, &cookie); hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[0]);
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine { ok(init_cookies[0].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[0].HighPart,
ok(cookie.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie.HighPart,
GetCurrentThreadId()); GetCurrentThreadId());
ok(cookie.LowPart == 0, "got wrong low part 0x%x\n", cookie.LowPart); if (!mt) ok(init_cookies[0].LowPart == 0, "got wrong low part 0x%x\n", init_cookies[0].LowPart);
}
/* register same instance one more time */ /* register same instance one more time */
cookie1.HighPart = 0; init_cookies[1].HighPart = 0;
cookie1.LowPart = 0; init_cookies[1].LowPart = 0;
hr = CoRegisterInitializeSpy(&testinitialize, &cookie1); hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]);
todo_wine {
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
ok(cookie1.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie1.HighPart, ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart,
GetCurrentThreadId()); GetCurrentThreadId());
ok(cookie1.LowPart == 1, "got wrong low part 0x%x\n", cookie1.LowPart); if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart);
}
cookie2.HighPart = 0; init_cookies[2].HighPart = 0;
cookie2.LowPart = 0; init_cookies[2].LowPart = 0;
hr = CoRegisterInitializeSpy(&testinitialize, &cookie2); hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[2]);
todo_wine {
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
ok(cookie2.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie2.HighPart, ok(init_cookies[2].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[2].HighPart,
GetCurrentThreadId()); GetCurrentThreadId());
ok(cookie2.LowPart == 2, "got wrong low part 0x%x\n", cookie2.LowPart); if (!mt) ok(init_cookies[2].LowPart == 2, "got wrong low part 0x%x\n", init_cookies[2].LowPart);
}
hr = CoRevokeInitializeSpy(cookie1); hr = CoRevokeInitializeSpy(init_cookies[1]);
todo_wine
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
hr = CoRevokeInitializeSpy(cookie1); hr = CoRevokeInitializeSpy(init_cookies[1]);
ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
cookie1.HighPart = 0; init_cookies[1].HighPart = 0;
cookie1.LowPart = 0; init_cookies[1].LowPart = 0;
hr = CoRegisterInitializeSpy(&testinitialize, &cookie1); hr = CoRegisterInitializeSpy(&testinitialize, &init_cookies[1]);
todo_wine {
ok(hr == S_OK, "got 0x%08x\n", hr); ok(hr == S_OK, "got 0x%08x\n", hr);
ok(cookie1.HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", cookie1.HighPart, ok(init_cookies[1].HighPart == GetCurrentThreadId(), "got high part 0x%08x, expected 0x%08x\n", init_cookies[1].HighPart,
GetCurrentThreadId()); GetCurrentThreadId());
ok(cookie1.LowPart == 1, "got wrong low part 0x%x\n", cookie1.LowPart); if (!mt) ok(init_cookies[1].LowPart == 1, "got wrong low part 0x%x\n", init_cookies[1].LowPart);
}
hr = CoRevokeInitializeSpy(cookie);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = CoRevokeInitializeSpy(cookie1); SET_EXPECT(PreInitialize);
todo_wine SET_EXPECT(PostInitialize);
ok(hr == S_OK, "got 0x%08x\n", hr); hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
ok(hr == (mt ? S_FALSE : S_OK), "Failed to initialize COM, hr %#x.\n", hr);
CHECK_CALLED(PreInitialize, 3);
CHECK_CALLED(PostInitialize, 3);
hr = CoRevokeInitializeSpy(cookie2); if (mt)
todo_wine {
ok(hr == S_OK, "got 0x%08x\n", hr); HANDLE thread;
thread = CreateThread(NULL, 0, test_init_spies_proc, NULL, 0, NULL);
ok(thread != NULL, "CreateThread failed: %u\n", GetLastError());
ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
}
SET_EXPECT(PreInitialize);
SET_EXPECT(PostInitialize);
hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
ok(hr == S_FALSE, "Failed to initialize COM, hr %#x.\n", hr);
CHECK_CALLED(PreInitialize, 3);
CHECK_CALLED(PostInitialize, 3);
SET_EXPECT(PreUninitialize);
SET_EXPECT(PostUninitialize);
CoUninitialize();
CHECK_CALLED(PreUninitialize, 3);
CHECK_CALLED(PostUninitialize, 3);
SET_EXPECT(PreUninitialize);
SET_EXPECT(PostUninitialize);
CoUninitialize();
CHECK_CALLED(PreUninitialize, 3);
CHECK_CALLED(PostUninitialize, 3);
if (mt)
{
SET_EXPECT(PreUninitialize);
SET_EXPECT(PostUninitialize);
CoUninitialize();
CHECK_CALLED(PreUninitialize, 3);
CHECK_CALLED(PostUninitialize, 3);
}
SET_EXPECT(PreInitialize);
SET_EXPECT(PostInitialize);
hr = CoInitializeEx(NULL, expected_coinit_flags = ((mt ? COINIT_MULTITHREADED : COINIT_APARTMENTTHREADED) | COINIT_DISABLE_OLE1DDE));
ok(hr == S_OK, "Failed to initialize COM, hr %#x.\n", hr);
CHECK_CALLED(PreInitialize, 3);
CHECK_CALLED(PostInitialize, 3);
SET_EXPECT(PreUninitialize);
revoke_spies_on_uninit = TRUE;
CoUninitialize();
CHECK_CALLED(PreUninitialize, 1);
} }
static HRESULT g_persistfile_qi_ret; static HRESULT g_persistfile_qi_ret;
@ -3755,10 +3838,10 @@ static DWORD CALLBACK implicit_mta_proc(void *param)
hr = CoRegisterMessageFilter(NULL, NULL); hr = CoRegisterMessageFilter(NULL, NULL);
ok(hr == CO_E_NOT_SUPPORTED, "got %#x\n", hr); ok(hr == CO_E_NOT_SUPPORTED, "got %#x\n", hr);
hr = CoLockObjectExternal((IUnknown *)&Test_Unknown, TRUE, TRUE); hr = CoLockObjectExternal(&Test_Unknown, TRUE, TRUE);
ok_ole_success(hr, "CoLockObjectExternal"); ok_ole_success(hr, "CoLockObjectExternal");
hr = CoDisconnectObject((IUnknown *)&Test_Unknown, 0); hr = CoDisconnectObject(&Test_Unknown, 0);
ok_ole_success(hr, "CoDisconnectObject"); ok_ole_success(hr, "CoDisconnectObject");
return 0; return 0;
@ -3824,7 +3907,8 @@ START_TEST(compobj)
test_CoGetApartmentType(); test_CoGetApartmentType();
test_IMallocSpy(); test_IMallocSpy();
test_CoGetCurrentLogicalThreadId(); test_CoGetCurrentLogicalThreadId();
test_IInitializeSpy(); test_IInitializeSpy(FALSE);
test_IInitializeSpy(TRUE);
test_CoGetInstanceFromFile(); test_CoGetInstanceFromFile();
test_GlobalOptions(); test_GlobalOptions();
test_implicit_mta(); test_implicit_mta();

View file

@ -329,7 +329,7 @@ static HRESULT WINAPI Test_IClassFactory_CreateInstance(
LPVOID *ppvObj) LPVOID *ppvObj)
{ {
if (pUnkOuter) return CLASS_E_NOAGGREGATION; if (pUnkOuter) return CLASS_E_NOAGGREGATION;
return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj); return IUnknown_QueryInterface(&Test_Unknown, riid, ppvObj);
} }
static HRESULT WINAPI Test_IClassFactory_LockServer( static HRESULT WINAPI Test_IClassFactory_LockServer(
@ -1205,7 +1205,9 @@ static void test_marshal_proxy_apartment_shutdown(void)
{ {
HRESULT hr; HRESULT hr;
IStream *pStream = NULL; IStream *pStream = NULL;
IUnknown *pProxy = NULL; IClassFactory *proxy;
IUnknown *unk;
ULONG ref;
DWORD tid; DWORD tid;
HANDLE thread; HANDLE thread;
@ -1220,7 +1222,7 @@ static void test_marshal_proxy_apartment_shutdown(void)
ok_non_zero_external_conn(); ok_non_zero_external_conn();
IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
ok_ole_success(hr, CoUnmarshalInterface); ok_ole_success(hr, CoUnmarshalInterface);
IStream_Release(pStream); IStream_Release(pStream);
@ -1233,7 +1235,11 @@ static void test_marshal_proxy_apartment_shutdown(void)
ok_zero_external_conn(); ok_zero_external_conn();
ok_last_release_closes(TRUE); ok_last_release_closes(TRUE);
IUnknown_Release(pProxy); hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&unk);
ok(hr == CO_E_OBJNOTCONNECTED, "got %#x\n", hr);
ref = IClassFactory_Release(proxy);
ok(!ref, "got %d refs\n", ref);
ok_no_locks(); ok_no_locks();

View file

@ -244,7 +244,7 @@ static void ole_server(void)
if (hr == S_OK) if (hr == S_OK)
{ {
trace("server: registering class object\n"); trace("server: registering class object\n");
hr = CoRegisterClassObject(&CLSID_WineTestObject, (IUnknown *)&factory, hr = CoRegisterClassObject(&CLSID_WineTestObject, (IUnknown *)&factory.IClassFactory_iface,
CLSCTX_SERVER, REGCLS_MULTIPLEUSE, &key); CLSCTX_SERVER, REGCLS_MULTIPLEUSE, &key);
if (hr == S_OK) if (hr == S_OK)
{ {

View file

@ -18,6 +18,11 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#define COBJMACROS
#ifdef __REACTOS__
#define CONST_VTABLE
#endif
#include "windows.h" #include "windows.h"
#include "wtypes.h" #include "wtypes.h"
#include "ddeml.h" #include "ddeml.h"
@ -44,28 +49,28 @@ static const struct valid_mapping
{ {
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_EMPTY */ { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_EMPTY */
{ PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_NULL */ { PROP_V0 , PROP_INV, PROP_INV, PROP_INV }, /* VT_NULL */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I2 */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I2 */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I4 */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_I4 */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R4 */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R4 */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R8 */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_R8 */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_CY */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_CY */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_DATE */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_DATE */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BSTR */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BSTR */
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DISPATCH */ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DISPATCH */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_ERROR */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_ERROR */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BOOL */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_BOOL */
{ PROP_V1 | PROP_TODO , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_VARIANT */ { PROP_V1 | PROP_TODO , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_VARIANT */
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UNKNOWN */ { PROP_V1 , PROP_V1, PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UNKNOWN */
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DECIMAL */ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_DECIMAL */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 15 */ { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* 15 */
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_V1 , PROP_V1 | PROP_TODO }, /* VT_I1 */ { PROP_V1 , PROP_V1 , PROP_V1 , PROP_V1 | PROP_TODO }, /* VT_I1 */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI1 */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI1 */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI2 */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI2 */
{ PROP_V0 , PROP_V1 | PROP_TODO , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI4 */ { PROP_V0 , PROP_V1 , PROP_V0 , PROP_V1 | PROP_TODO }, /* VT_UI4 */
{ PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_I8 */ { PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_I8 */
{ PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_UI8 */ { PROP_V0 , PROP_V1A | PROP_TODO, PROP_V0 , PROP_V1A | PROP_TODO }, /* VT_UI8 */
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_INT */ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_INT */
{ PROP_V1 , PROP_V1 | PROP_TODO , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UINT */ { PROP_V1 , PROP_V1 , PROP_INV, PROP_V1 | PROP_TODO }, /* VT_UINT */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_VOID */ { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_VOID */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_HRESULT */ { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_HRESULT */
{ PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_PTR */ { PROP_INV, PROP_INV, PROP_INV, PROP_INV }, /* VT_PTR */
@ -298,12 +303,60 @@ static void test_validtypes(void)
} }
} }
struct unk_impl
{
IUnknown IUnknown_iface;
LONG ref;
};
static inline struct unk_impl *impl_from_IUnknown(IUnknown *iface)
{
return CONTAINING_RECORD(iface, struct unk_impl, IUnknown_iface);
}
static HRESULT WINAPI unk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
struct unk_impl *This = impl_from_IUnknown(iface);
if(winetest_debug > 1)
trace("Call to unk_QueryInterface()\n");
*ppv = &This->IUnknown_iface;
IUnknown_AddRef(iface);
return S_OK;
}
static ULONG WINAPI unk_AddRef(IUnknown *iface)
{
struct unk_impl *This = impl_from_IUnknown(iface);
if(winetest_debug > 1)
trace("Call to unk_AddRef()\n");
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI unk_Release(IUnknown *iface)
{
struct unk_impl *This = impl_from_IUnknown(iface);
if(winetest_debug > 1)
trace("Call to unk_Release()\n");
return InterlockedDecrement(&This->ref);
}
static const IUnknownVtbl unk_vtbl =
{
unk_QueryInterface,
unk_AddRef,
unk_Release
};
static void test_copy(void) static void test_copy(void)
{ {
static char szTestString[] = "Test String"; static char szTestString[] = "Test String";
static WCHAR wszTestString[] = {'T','e','s','t',' ','S','t','r','i','n','g',0}; static WCHAR wszTestString[] = {'T','e','s','t',' ','S','t','r','i','n','g',0};
struct unk_impl unk_obj = {{&unk_vtbl}, 1};
PROPVARIANT propvarSrc; PROPVARIANT propvarSrc;
PROPVARIANT propvarDst; PROPVARIANT propvarDst;
SAFEARRAY *sa;
SAFEARRAYBOUND sabound;
LONG saindex;
HRESULT hr; HRESULT hr;
propvarSrc.vt = VT_BSTR; propvarSrc.vt = VT_BSTR;
@ -334,6 +387,39 @@ static void test_copy(void)
hr = PropVariantClear(&propvarDst); hr = PropVariantClear(&propvarDst);
ok(hr == S_OK, "PropVariantClear(...VT_LPSTR...) failed\n"); ok(hr == S_OK, "PropVariantClear(...VT_LPSTR...) failed\n");
memset(&propvarSrc, 0, sizeof(propvarSrc)); memset(&propvarSrc, 0, sizeof(propvarSrc));
propvarSrc.vt = VT_UNKNOWN;
U(propvarSrc).punkVal = &unk_obj.IUnknown_iface;
hr = PropVariantCopy(&propvarDst, &propvarSrc);
ok(hr == S_OK, "PropVariantCopy(...VT_UNKNOWN...) failed: 0x%08x.\n", hr);
ok(U(propvarDst).punkVal == &unk_obj.IUnknown_iface, "Got wrong IUnknown pointer\n");
ok(unk_obj.ref == 2, "got wrong refcount: %d.\n", unk_obj.ref);
hr = PropVariantClear(&propvarDst);
ok(hr == S_OK, "PropVariantClear(...VT_UNKNOWN...) failed: 0x%08x.\n", hr);
ok(unk_obj.ref == 1, "got wrong refcount: %d.\n", unk_obj.ref);
memset(&propvarSrc, 0, sizeof(propvarSrc));
sabound.lLbound = 0;
sabound.cElements = 2;
sa = SafeArrayCreate(VT_UNKNOWN, 1, &sabound);
saindex = 0;
SafeArrayPutElement(sa, &saindex, &unk_obj.IUnknown_iface);
saindex = 1;
SafeArrayPutElement(sa, &saindex, &unk_obj.IUnknown_iface);
ok(unk_obj.ref == 3, "got wrong refcount: %d.\n", unk_obj.ref);
propvarSrc.vt = VT_ARRAY | VT_UNKNOWN;
U(propvarSrc).parray = sa;
hr = PropVariantCopy(&propvarDst, &propvarSrc);
ok(hr == S_OK, "PropVariantCopy(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
ok(unk_obj.ref == 5, "got wrong refcount: %d.\n", unk_obj.ref);
hr = PropVariantClear(&propvarDst);
ok(hr == S_OK, "PropVariantClear(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
ok(unk_obj.ref == 3, "got wrong refcount: %d.\n", unk_obj.ref);
hr = PropVariantClear(&propvarSrc);
ok(hr == S_OK, "PropVariantClear(...VT_ARRAY|VT_UNKNOWN...) failed: 0x%08x.\n", hr);
ok(unk_obj.ref == 1, "got wrong refcount: %d.\n", unk_obj.ref);
memset(&propvarSrc, 0, sizeof(propvarSrc));
} }
struct _PMemoryAllocator_vtable { struct _PMemoryAllocator_vtable {