rpcrt4/tests: Add some tests for marshalling interface pointers.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
76a665a1c6
commit
b7cc627c6e
|
@ -21,6 +21,7 @@
|
||||||
#define _WIN32_WINNT 0x0500
|
#define _WIN32_WINNT 0x0500
|
||||||
#define NTDDI_WIN2K 0x05000000
|
#define NTDDI_WIN2K 0x05000000
|
||||||
#define NTDDI_VERSION NTDDI_WIN2K /* for some MIDL_STUB_MESSAGE fields */
|
#define NTDDI_VERSION NTDDI_WIN2K /* for some MIDL_STUB_MESSAGE fields */
|
||||||
|
#define COBJMACROS
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
@ -1173,6 +1174,280 @@ static void test_simple_struct(void)
|
||||||
test_pointer_marshal(fmtstr_pointer_struct, &ps1, 17, wiredata, 21, ps1_cmp, 2, "pointer_struct");
|
test_pointer_marshal(fmtstr_pointer_struct, &ps1, 17, wiredata, 21, ps1_cmp, 2, "pointer_struct");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct testiface
|
||||||
|
{
|
||||||
|
IPersist IPersist_iface;
|
||||||
|
LONG ref;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct testiface *impl_from_IPersist(IPersist *iface)
|
||||||
|
{
|
||||||
|
return CONTAINING_RECORD(iface, struct testiface, IPersist_iface);
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI test_persist_QueryInterface(IPersist *iface, REFIID iid, void **out)
|
||||||
|
{
|
||||||
|
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IPersist))
|
||||||
|
{
|
||||||
|
*out = iface;
|
||||||
|
IPersist_AddRef(iface);
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out = NULL;
|
||||||
|
return E_NOINTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI test_persist_AddRef(IPersist *iface)
|
||||||
|
{
|
||||||
|
struct testiface *unk = impl_from_IPersist(iface);
|
||||||
|
return ++unk->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ULONG WINAPI test_persist_Release(IPersist *iface)
|
||||||
|
{
|
||||||
|
struct testiface *unk = impl_from_IPersist(iface);
|
||||||
|
return --unk->ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT WINAPI test_persist_GetClassId(IPersist *iface, GUID *clsid)
|
||||||
|
{
|
||||||
|
*clsid = IID_IPersist;
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static IPersistVtbl testiface_vtbl = {
|
||||||
|
test_persist_QueryInterface,
|
||||||
|
test_persist_AddRef,
|
||||||
|
test_persist_Release,
|
||||||
|
test_persist_GetClassId,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void test_iface_ptr(void)
|
||||||
|
{
|
||||||
|
struct testiface server_obj = {{&testiface_vtbl}, 1};
|
||||||
|
struct testiface client_obj = {{&testiface_vtbl}, 1};
|
||||||
|
|
||||||
|
MIDL_STUB_MESSAGE StubMsg;
|
||||||
|
MIDL_STUB_DESC StubDesc;
|
||||||
|
RPC_MESSAGE RpcMessage;
|
||||||
|
IPersist *proxy;
|
||||||
|
HRESULT hr;
|
||||||
|
GUID clsid;
|
||||||
|
void *ptr;
|
||||||
|
LONG ref;
|
||||||
|
|
||||||
|
static const unsigned char fmtstr_ip[] =
|
||||||
|
{
|
||||||
|
FC_IP,
|
||||||
|
FC_CONSTANT_IID,
|
||||||
|
NdrFcLong(0x0000010c),
|
||||||
|
NdrFcShort(0x0000),
|
||||||
|
NdrFcShort(0x0000),
|
||||||
|
0xc0,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x00,
|
||||||
|
0x46,
|
||||||
|
};
|
||||||
|
|
||||||
|
CoInitialize(NULL);
|
||||||
|
|
||||||
|
StubDesc = Object_StubDesc;
|
||||||
|
StubDesc.pFormatTypes = fmtstr_ip;
|
||||||
|
|
||||||
|
NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0);
|
||||||
|
StubMsg.BufferLength = 0;
|
||||||
|
NdrInterfacePointerBufferSize(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
|
||||||
|
StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength);
|
||||||
|
StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength;
|
||||||
|
|
||||||
|
/* server -> client */
|
||||||
|
|
||||||
|
StubMsg.IsClient = 0;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
IPersist_AddRef(&server_obj.IPersist_iface);
|
||||||
|
ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(server_obj.ref > 2, "got %d references\n", server_obj.ref);
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
|
||||||
|
NdrInterfacePointerFree(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
ok(server_obj.ref > 1, "got %d references\n", server_obj.ref);
|
||||||
|
|
||||||
|
StubMsg.IsClient = 1;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
proxy = NULL;
|
||||||
|
ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(!!proxy, "mem not alloced\n");
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
ok(server_obj.ref > 1, "got %d references\n", server_obj.ref);
|
||||||
|
|
||||||
|
hr = IPersist_GetClassID(proxy, &clsid);
|
||||||
|
ok(hr == S_OK, "got hr %#x\n", hr);
|
||||||
|
ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
|
||||||
|
|
||||||
|
ref = IPersist_Release(proxy);
|
||||||
|
ok(ref == 1, "got %d references\n", ref);
|
||||||
|
ok(server_obj.ref == 1, "got %d references\n", server_obj.ref);
|
||||||
|
|
||||||
|
/* An existing interface pointer is released; this is necessary so that an
|
||||||
|
* [in, out] pointer which changes does not leak references. */
|
||||||
|
|
||||||
|
StubMsg.IsClient = 0;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
IPersist_AddRef(&server_obj.IPersist_iface);
|
||||||
|
ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(server_obj.ref > 2, "got %d references\n", server_obj.ref);
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
|
||||||
|
NdrInterfacePointerFree(&StubMsg, (unsigned char *)&server_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
ok(server_obj.ref > 1, "got %d references\n", server_obj.ref);
|
||||||
|
|
||||||
|
StubMsg.IsClient = 1;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
proxy = &client_obj.IPersist_iface;
|
||||||
|
IPersist_AddRef(proxy);
|
||||||
|
ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(!!proxy && proxy != &client_obj.IPersist_iface, "mem not alloced\n");
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
ok(server_obj.ref > 1, "got %d references\n", server_obj.ref);
|
||||||
|
todo_wine
|
||||||
|
ok(client_obj.ref == 1, "got %d references\n", client_obj.ref);
|
||||||
|
client_obj.ref = 1;
|
||||||
|
|
||||||
|
hr = IPersist_GetClassID(proxy, &clsid);
|
||||||
|
ok(hr == S_OK, "got hr %#x\n", hr);
|
||||||
|
ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
|
||||||
|
|
||||||
|
ref = IPersist_Release(proxy);
|
||||||
|
ok(ref == 1, "got %d references\n", ref);
|
||||||
|
ok(server_obj.ref == 1, "got %d references\n", server_obj.ref);
|
||||||
|
|
||||||
|
/* client -> server */
|
||||||
|
|
||||||
|
StubMsg.IsClient = 1;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
IPersist_AddRef(&client_obj.IPersist_iface);
|
||||||
|
ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(client_obj.ref > 2, "got %d references\n", client_obj.ref);
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
|
||||||
|
StubMsg.IsClient = 0;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
proxy = NULL;
|
||||||
|
ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(!!proxy, "mem not alloced\n");
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
ok(client_obj.ref > 2, "got %d references\n", client_obj.ref);
|
||||||
|
|
||||||
|
hr = IPersist_GetClassID(proxy, &clsid);
|
||||||
|
ok(hr == S_OK, "got hr %#x\n", hr);
|
||||||
|
ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
|
||||||
|
|
||||||
|
ref = IPersist_Release(proxy);
|
||||||
|
ok(client_obj.ref > 1, "got %d references\n", client_obj.ref);
|
||||||
|
ok(ref == client_obj.ref, "expected %d references, got %d\n", client_obj.ref, ref);
|
||||||
|
|
||||||
|
NdrInterfacePointerFree(&StubMsg, (unsigned char *)proxy, fmtstr_ip);
|
||||||
|
ok(client_obj.ref == 1, "got %d references\n", client_obj.ref);
|
||||||
|
|
||||||
|
/* same, but free the interface after calling NdrInterfacePointerFree */
|
||||||
|
|
||||||
|
StubMsg.IsClient = 1;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
IPersist_AddRef(&client_obj.IPersist_iface);
|
||||||
|
ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(client_obj.ref > 2, "got %d references\n", client_obj.ref);
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
|
||||||
|
StubMsg.IsClient = 0;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
proxy = NULL;
|
||||||
|
ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(!!proxy, "mem not alloced\n");
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
ok(client_obj.ref > 2, "got %d references\n", client_obj.ref);
|
||||||
|
|
||||||
|
NdrInterfacePointerFree(&StubMsg, (unsigned char *)proxy, fmtstr_ip);
|
||||||
|
ok(client_obj.ref > 1, "got %d references\n", client_obj.ref);
|
||||||
|
|
||||||
|
hr = IPersist_GetClassID(proxy, &clsid);
|
||||||
|
ok(hr == S_OK, "got hr %#x\n", hr);
|
||||||
|
ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
|
||||||
|
|
||||||
|
ref = IPersist_Release(proxy);
|
||||||
|
ok(ref == 1, "got %d references\n", ref);
|
||||||
|
ok(client_obj.ref == 1, "got %d references\n", client_obj.ref);
|
||||||
|
|
||||||
|
/* An existing interface pointer is *not* released (in fact, it is ignored
|
||||||
|
* and may be invalid). In practice it will always be NULL anyway. */
|
||||||
|
|
||||||
|
StubMsg.IsClient = 1;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
IPersist_AddRef(&client_obj.IPersist_iface);
|
||||||
|
ptr = NdrInterfacePointerMarshall(&StubMsg, (unsigned char *)&client_obj.IPersist_iface, fmtstr_ip);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(client_obj.ref > 2, "got %d references\n", client_obj.ref);
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
|
||||||
|
StubMsg.IsClient = 0;
|
||||||
|
my_alloc_called = my_free_called = 0;
|
||||||
|
StubMsg.Buffer = StubMsg.BufferStart;
|
||||||
|
proxy = &server_obj.IPersist_iface;
|
||||||
|
IPersist_AddRef(proxy);
|
||||||
|
ptr = NdrInterfacePointerUnmarshall(&StubMsg, (unsigned char **)&proxy, fmtstr_ip, 0);
|
||||||
|
ok(!ptr, "ret %p\n", ptr);
|
||||||
|
ok(!!proxy && proxy != &server_obj.IPersist_iface, "mem not alloced\n");
|
||||||
|
ok(!my_alloc_called, "alloc called %d\n", my_alloc_called);
|
||||||
|
ok(!my_free_called, "free called %d\n", my_free_called);
|
||||||
|
ok(client_obj.ref > 2, "got %d references\n", client_obj.ref);
|
||||||
|
ok(server_obj.ref == 2, "got %d references\n", server_obj.ref);
|
||||||
|
IPersist_Release(&server_obj.IPersist_iface);
|
||||||
|
|
||||||
|
hr = IPersist_GetClassID(proxy, &clsid);
|
||||||
|
ok(hr == S_OK, "got hr %#x\n", hr);
|
||||||
|
ok(IsEqualGUID(&clsid, &IID_IPersist), "wrong clsid %s\n", wine_dbgstr_guid(&clsid));
|
||||||
|
|
||||||
|
ref = IPersist_Release(proxy);
|
||||||
|
ok(client_obj.ref > 1, "got %d references\n", client_obj.ref);
|
||||||
|
ok(ref == client_obj.ref, "expected %d references, got %d\n", client_obj.ref, ref);
|
||||||
|
|
||||||
|
NdrInterfacePointerFree(&StubMsg, (unsigned char *)proxy, fmtstr_ip);
|
||||||
|
ok(client_obj.ref == 1, "got %d references\n", client_obj.ref);
|
||||||
|
|
||||||
|
CoUninitialize();
|
||||||
|
}
|
||||||
|
|
||||||
static void test_fullpointer_xlat(void)
|
static void test_fullpointer_xlat(void)
|
||||||
{
|
{
|
||||||
PFULL_PTR_XLAT_TABLES pXlatTables;
|
PFULL_PTR_XLAT_TABLES pXlatTables;
|
||||||
|
@ -2635,6 +2910,7 @@ START_TEST( ndr_marshall )
|
||||||
test_simple_types();
|
test_simple_types();
|
||||||
test_nontrivial_pointer_types();
|
test_nontrivial_pointer_types();
|
||||||
test_simple_struct();
|
test_simple_struct();
|
||||||
|
test_iface_ptr();
|
||||||
test_fullpointer_xlat();
|
test_fullpointer_xlat();
|
||||||
test_client_init();
|
test_client_init();
|
||||||
test_server_init();
|
test_server_init();
|
||||||
|
|
Loading…
Reference in New Issue