static HRESULT (WINAPI *pVarAdd)(LPVARIANT,LPVARIANT,LPVARIANT);
-#define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", (unsigned long int)hr)
+#define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
/* ULL suffix is not portable */
#define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
ok_ole_success(hr, CoMarshalInterface);
/* force the message queue to be created before signaling parent thread */
- PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
+ PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
SetEvent(data->marshal_event);
- while (GetMessage(&msg, NULL, 0, 0))
+ while (GetMessageA(&msg, NULL, 0, 0))
{
if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
{
SetEvent((HANDLE)msg.lParam);
}
else
- DispatchMessage(&msg);
+ DispatchMessageA(&msg);
}
HeapFree(GetProcessHeap(), 0, data);
static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
{
DWORD tid = 0;
- HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
data->stream = stream;
* same thread that marshaled the interface in the first place. */
static void release_host_object(DWORD tid)
{
- HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
- PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
+ HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
+ PostThreadMessageA(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
WaitForSingleObject(event, INFINITE);
CloseHandle(event);
}
static void end_host_object(DWORD tid, HANDLE thread)
{
- BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
+ BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
/* be careful of races - don't return until hosting thread has terminated */
WaitForSingleObject(thread, INFINITE);
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)
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)) {
}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;
int i;
for (i = 0; i < sizeof(mystruct->uarr)/sizeof(mystruct->uarr[0]); i++)
if (mystruct->uarr[i] != i)
- return 0;
-
- return 1;
+ return FALSE;
+ return TRUE;
}
static HRESULT WINAPI Widget_StructArgs(
return S_OK;
}
-static HRESULT WINAPI Widget_do_restrict(IWidget* iface, INT *i)
+static HRESULT WINAPI Widget__restrict(IWidget* iface, INT *i)
{
trace("restrict\n");
*i = DISPID_TM_RESTRICTED;
Widget_ByRefUInt,
Widget_put_prop_opt_arg,
Widget_put_prop_req_arg,
- Widget_do_restrict,
+ Widget__restrict,
Widget_neg_restrict
};
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;
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))
{
{
static const WCHAR szCat[] = { 'C','a','t',0 };
static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
- static WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
+ static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
HRESULT hr;
IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
IWidget *pWidget;
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;
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;
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);