From f1df2b6693f9c07a3cc854820a9570bc6bee7d61 Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Fri, 11 Jan 2008 10:57:59 +0000 Subject: [PATCH] - Import rpcrt4 tests from Wine-20080105. - There is an ugly hack applied, which defines the relative path to the server_*.h files inside obj-i386 directory, thus being dependent on its name. svn path=/trunk/; revision=31710 --- rostests/winetests/directory.rbuild | 3 + rostests/winetests/rpcrt4/cstub.c | 945 ++++++++++++ rostests/winetests/rpcrt4/generated.c | 709 +++++++++ rostests/winetests/rpcrt4/ndr_marshall.c | 1524 ++++++++++++++++++++ rostests/winetests/rpcrt4/rpc.c | 385 +++++ rostests/winetests/rpcrt4/rpcrt4.rbuild | 25 + rostests/winetests/rpcrt4/server.c | 1244 ++++++++++++++++ rostests/winetests/rpcrt4/server.idl | 308 ++++ rostests/winetests/rpcrt4/server_defines.h | 33 + rostests/winetests/rpcrt4/testlist.c | 23 + 10 files changed, 5199 insertions(+) create mode 100644 rostests/winetests/rpcrt4/cstub.c create mode 100644 rostests/winetests/rpcrt4/generated.c create mode 100644 rostests/winetests/rpcrt4/ndr_marshall.c create mode 100644 rostests/winetests/rpcrt4/rpc.c create mode 100644 rostests/winetests/rpcrt4/rpcrt4.rbuild create mode 100644 rostests/winetests/rpcrt4/server.c create mode 100644 rostests/winetests/rpcrt4/server.idl create mode 100644 rostests/winetests/rpcrt4/server_defines.h create mode 100644 rostests/winetests/rpcrt4/testlist.c diff --git a/rostests/winetests/directory.rbuild b/rostests/winetests/directory.rbuild index 686d51c5fa0..f2fb0f4c500 100644 --- a/rostests/winetests/directory.rbuild +++ b/rostests/winetests/directory.rbuild @@ -62,6 +62,9 @@ + + + diff --git a/rostests/winetests/rpcrt4/cstub.c b/rostests/winetests/rpcrt4/cstub.c new file mode 100644 index 00000000000..6a38397f679 --- /dev/null +++ b/rostests/winetests/rpcrt4/cstub.c @@ -0,0 +1,945 @@ +/* + * Unit test suite for cstubs + * + * Copyright 2006 Huw Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define PROXY_DELEGATION +#define COBJMACROS + +#include "wine/test.h" +#include +#include +#include +#include + + +#include "rpc.h" +#include "rpcdce.h" +#include "rpcproxy.h" + +static CStdPSFactoryBuffer PSFactoryBuffer; + +CSTDSTUBBUFFERRELEASE(&PSFactoryBuffer) +CSTDSTUBBUFFER2RELEASE(&PSFactoryBuffer) + +static GUID IID_if1 = {0x12345678, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; +static GUID IID_if2 = {0x12345679, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; +static GUID IID_if3 = {0x1234567a, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; +static GUID IID_if4 = {0x1234567b, 1234, 5678, {12,34,56,78,90,0xab,0xcd,0xef}}; + +static int my_alloc_called; +static int my_free_called; + +static void * CALLBACK my_alloc(size_t size) +{ + my_alloc_called++; + return NdrOleAllocate(size); +} + +static void CALLBACK my_free(void *ptr) +{ + my_free_called++; + NdrOleFree(ptr); +} + +typedef struct _MIDL_PROC_FORMAT_STRING +{ + short Pad; + unsigned char Format[ 2 ]; +} MIDL_PROC_FORMAT_STRING; + +typedef struct _MIDL_TYPE_FORMAT_STRING +{ + short Pad; + unsigned char Format[ 2 ]; +} MIDL_TYPE_FORMAT_STRING; + + +static const MIDL_PROC_FORMAT_STRING __MIDL_ProcFormatString = +{ + 0, + { + 0, 0 + } +}; + +static const MIDL_TYPE_FORMAT_STRING __MIDL_TypeFormatString = +{ + 0, + { + 0, 0 + } +}; + +static const MIDL_STUB_DESC Object_StubDesc = + { + NULL, + my_alloc, + my_free, + { 0 }, + 0, + 0, + 0, + 0, + __MIDL_TypeFormatString.Format, + 1, /* -error bounds_check flag */ + 0x20000, /* Ndr library version */ + 0, + 0x50100a4, /* MIDL Version 5.1.164 */ + 0, + NULL, + 0, /* notify & notify_flag routine table */ + 1, /* Flags */ + 0, /* Reserved3 */ + 0, /* Reserved4 */ + 0 /* Reserved5 */ + }; + +static HRESULT WINAPI if1_fn1_Proxy(void *This) +{ + return S_OK; +} + +static void __RPC_STUB if1_fn1_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase) +{ + trace("fn1 stub\n"); +} + +static HRESULT WINAPI if1_fn2_Proxy(void *This) +{ + return S_OK; +} + +static void __RPC_STUB if1_fn2_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase) +{ + trace("fn2 stub\n"); +} + +static CINTERFACE_PROXY_VTABLE(5) if1_proxy_vtbl = +{ + { &IID_if1 }, + { IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + if1_fn1_Proxy, + if1_fn2_Proxy + } +}; + + +static const unsigned short if1_FormatStringOffsetTable[] = + { + 0, + 0 + }; + +static const MIDL_SERVER_INFO if1_server_info = + { + &Object_StubDesc, + 0, + __MIDL_ProcFormatString.Format, + &if1_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; + + +static const PRPC_STUB_FUNCTION if1_table[] = +{ + if1_fn1_Stub, + if1_fn2_Stub +}; + +static CInterfaceStubVtbl if1_stub_vtbl = +{ + { + &IID_if1, + &if1_server_info, + 5, + &if1_table[-3] + }, + { CStdStubBuffer_METHODS } +}; + +static CINTERFACE_PROXY_VTABLE(13) if2_proxy_vtbl = +{ + { &IID_if2 }, + { IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + } +}; + +static const unsigned short if2_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 0 + }; + +static const MIDL_SERVER_INFO if2_server_info = + { + &Object_StubDesc, + 0, + __MIDL_ProcFormatString.Format, + &if2_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; + + +static const PRPC_STUB_FUNCTION if2_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION +}; + +static CInterfaceStubVtbl if2_stub_vtbl = +{ + { + &IID_if2, + &if2_server_info, + 13, + &if2_table[-3] + }, + { CStdStubBuffer_DELEGATING_METHODS } +}; + +static CINTERFACE_PROXY_VTABLE(4) if3_proxy_vtbl = +{ + { &IID_if3 }, + { IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + if1_fn1_Proxy + } +}; + + +static const unsigned short if3_FormatStringOffsetTable[] = + { + 0, + 0 + }; + +static const MIDL_SERVER_INFO if3_server_info = + { + &Object_StubDesc, + 0, + __MIDL_ProcFormatString.Format, + &if3_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; + + +static const PRPC_STUB_FUNCTION if3_table[] = +{ + if1_fn1_Stub +}; + +static CInterfaceStubVtbl if3_stub_vtbl = +{ + { + &IID_if3, + &if3_server_info, + 4, + &if1_table[-3] + }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +static CINTERFACE_PROXY_VTABLE(7) if4_proxy_vtbl = +{ + { &IID_if4 }, + { IUnknown_QueryInterface_Proxy, + IUnknown_AddRef_Proxy, + IUnknown_Release_Proxy , + 0, + 0, + 0, + 0 + } +}; + +static const unsigned short if4_FormatStringOffsetTable[] = + { + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + (unsigned short) -1, + 0 + }; + +static const MIDL_SERVER_INFO if4_server_info = + { + &Object_StubDesc, + 0, + __MIDL_ProcFormatString.Format, + &if4_FormatStringOffsetTable[-3], + 0, + 0, + 0, + 0}; + + +static const PRPC_STUB_FUNCTION if4_table[] = +{ + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, + STUB_FORWARDING_FUNCTION, +}; + +static CInterfaceStubVtbl if4_stub_vtbl = +{ + { + &IID_if4, + &if4_server_info, + 7, + &if2_table[-3] + }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +static const CInterfaceProxyVtbl *cstub_ProxyVtblList[] = +{ + (const CInterfaceProxyVtbl *) &if1_proxy_vtbl, + (const CInterfaceProxyVtbl *) &if2_proxy_vtbl, + (const CInterfaceProxyVtbl *) &if3_proxy_vtbl, + (const CInterfaceProxyVtbl *) &if4_proxy_vtbl, + NULL +}; + +static const CInterfaceStubVtbl *cstub_StubVtblList[] = +{ + (const CInterfaceStubVtbl *) &if1_stub_vtbl, + (const CInterfaceStubVtbl *) &if2_stub_vtbl, + (const CInterfaceStubVtbl *) &if3_stub_vtbl, + (const CInterfaceStubVtbl *) &if4_stub_vtbl, + NULL +}; + +static PCInterfaceName const if_name_list[] = +{ + "if1", + "if2", + "if3", + "if4", + NULL +}; + +static const IID *base_iid_list[] = +{ + NULL, + &IID_ITypeLib, + NULL, + &IID_IDispatch, + NULL +}; + +#define cstub_CHECK_IID(n) IID_GENERIC_CHECK_IID( cstub, pIID, n) + +static int __stdcall iid_lookup( const IID * pIID, int * pIndex ) +{ + IID_BS_LOOKUP_SETUP + + IID_BS_LOOKUP_INITIAL_TEST( cstub, 4, 4 ) + IID_BS_LOOKUP_NEXT_TEST( cstub, 2 ) + IID_BS_LOOKUP_NEXT_TEST( cstub, 1 ) + IID_BS_LOOKUP_RETURN_RESULT( cstub, 4, *pIndex ) + +} + + +static const ExtendedProxyFileInfo my_proxy_file_info = +{ + (const PCInterfaceProxyVtblList *) &cstub_ProxyVtblList, + (const PCInterfaceStubVtblList *) &cstub_StubVtblList, + (const PCInterfaceName *) &if_name_list, + (const IID **) &base_iid_list, + &iid_lookup, + 4, + 1, + NULL, + 0, + 0, + 0 +}; + +static const ProxyFileInfo *proxy_file_list[] = { + &my_proxy_file_info, + NULL +}; + + +static IPSFactoryBuffer *test_NdrDllGetClassObject(void) +{ + IPSFactoryBuffer *ppsf = NULL; + const CLSID PSDispatch = {0x20420, 0, 0, {0xc0, 0, 0, 0, 0, 0, 0, 0x46}}; + HRESULT r; + HMODULE hmod = LoadLibraryA("rpcrt4.dll"); + void *CStd_QueryInterface = GetProcAddress(hmod, "CStdStubBuffer_QueryInterface"); + void *CStd_AddRef = GetProcAddress(hmod, "CStdStubBuffer_AddRef"); + void *CStd_Release = GetProcAddress(hmod, "NdrCStdStubBuffer_Release"); + void *CStd_Connect = GetProcAddress(hmod, "CStdStubBuffer_Connect"); + void *CStd_Disconnect = GetProcAddress(hmod, "CStdStubBuffer_Disconnect"); + void *CStd_Invoke = GetProcAddress(hmod, "CStdStubBuffer_Invoke"); + void *CStd_IsIIDSupported = GetProcAddress(hmod, "CStdStubBuffer_IsIIDSupported"); + void *CStd_CountRefs = GetProcAddress(hmod, "CStdStubBuffer_CountRefs"); + void *CStd_DebugServerQueryInterface = GetProcAddress(hmod, "CStdStubBuffer_DebugServerQueryInterface"); + void *CStd_DebugServerRelease = GetProcAddress(hmod, "CStdStubBuffer_DebugServerRelease"); + + r = NdrDllGetClassObject(&PSDispatch, &IID_IPSFactoryBuffer, (void**)&ppsf, proxy_file_list, + &PSDispatch, &PSFactoryBuffer); + + ok(r == S_OK, "ret %08x\n", r); + ok(ppsf != NULL, "ppsf == NULL\n"); + + ok(PSFactoryBuffer.pProxyFileList == proxy_file_list, "pfl not the same\n"); + ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList == (PCInterfaceStubVtblList *) &cstub_StubVtblList, "stub vtbllist not the same\n"); + + /* if1 is non-delegating, if2 is delegating, if3 is non-delegating + but I've zero'ed the vtbl entries, similarly if4 is delegating + with zero'ed vtbl entries */ + +#define VTBL_TEST_NOT_CHANGE_TO(name, i) \ + ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name != CStd_##name, #name "vtbl %d updated %p %p\n", \ + i, PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name, CStd_##name ); +#define VTBL_TEST_CHANGE_TO(name, i) \ + ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name == CStd_##name, #name "vtbl %d not updated %p %p\n", \ + i, PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name, CStd_##name ); +#define VTBL_TEST_ZERO(name, i) \ + ok(PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name == NULL, #name "vtbl %d not null %p\n", \ + i, PSFactoryBuffer.pProxyFileList[0]->pStubVtblList[i]->Vtbl.name ); + VTBL_TEST_NOT_CHANGE_TO(QueryInterface, 0); + VTBL_TEST_NOT_CHANGE_TO(AddRef, 0); + VTBL_TEST_NOT_CHANGE_TO(Release, 0); + VTBL_TEST_NOT_CHANGE_TO(Connect, 0); + VTBL_TEST_NOT_CHANGE_TO(Disconnect, 0); + VTBL_TEST_NOT_CHANGE_TO(Invoke, 0); + VTBL_TEST_NOT_CHANGE_TO(IsIIDSupported, 0); + VTBL_TEST_NOT_CHANGE_TO(CountRefs, 0); + VTBL_TEST_NOT_CHANGE_TO(DebugServerQueryInterface, 0); + VTBL_TEST_NOT_CHANGE_TO(DebugServerRelease, 0); + + VTBL_TEST_CHANGE_TO(QueryInterface, 1); + VTBL_TEST_CHANGE_TO(AddRef, 1); + VTBL_TEST_NOT_CHANGE_TO(Release, 1); + VTBL_TEST_NOT_CHANGE_TO(Connect, 1); + VTBL_TEST_NOT_CHANGE_TO(Disconnect, 1); + VTBL_TEST_CHANGE_TO(Invoke, 1); + VTBL_TEST_CHANGE_TO(IsIIDSupported, 1); + VTBL_TEST_NOT_CHANGE_TO(CountRefs, 1); + VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 1); + VTBL_TEST_CHANGE_TO(DebugServerRelease, 1); + + VTBL_TEST_CHANGE_TO(QueryInterface, 2); + VTBL_TEST_CHANGE_TO(AddRef, 2); + VTBL_TEST_ZERO(Release, 2); + VTBL_TEST_CHANGE_TO(Connect, 2); + VTBL_TEST_CHANGE_TO(Disconnect, 2); + VTBL_TEST_CHANGE_TO(Invoke, 2); + VTBL_TEST_CHANGE_TO(IsIIDSupported, 2); + VTBL_TEST_CHANGE_TO(CountRefs, 2); + VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 2); + VTBL_TEST_CHANGE_TO(DebugServerRelease, 2); + + VTBL_TEST_CHANGE_TO(QueryInterface, 3); + VTBL_TEST_CHANGE_TO(AddRef, 3); + VTBL_TEST_ZERO(Release, 3); + VTBL_TEST_NOT_CHANGE_TO(Connect, 3); + VTBL_TEST_NOT_CHANGE_TO(Disconnect, 3); + VTBL_TEST_CHANGE_TO(Invoke, 3); + VTBL_TEST_CHANGE_TO(IsIIDSupported, 3); + VTBL_TEST_NOT_CHANGE_TO(CountRefs, 3); + VTBL_TEST_CHANGE_TO(DebugServerQueryInterface, 3); + VTBL_TEST_CHANGE_TO(DebugServerRelease, 3); + + + +#undef VTBL_TEST_NOT_CHANGE_TO +#undef VTBL_TEST_CHANGE_TO +#undef VTBL_TEST_ZERO + + ok(PSFactoryBuffer.RefCount == 1, "ref count %d\n", PSFactoryBuffer.RefCount); + return ppsf; +} + +static int base_buffer_invoke_called; +static HRESULT WINAPI base_buffer_Invoke(IRpcStubBuffer *This, RPCOLEMESSAGE *msg, IRpcChannelBuffer *channel) +{ + base_buffer_invoke_called++; + ok(msg == (RPCOLEMESSAGE*)0xcafebabe, "msg ptr changed\n"); + ok(channel == (IRpcChannelBuffer*)0xdeadbeef, "channel ptr changed\n"); + return S_OK; /* returning any failure here results in an exception */ +} + +static IRpcStubBufferVtbl base_buffer_vtbl = { + (void*)0xcafebab0, + (void*)0xcafebab1, + (void*)0xcafebab2, + (void*)0xcafebab3, + (void*)0xcafebab4, + base_buffer_Invoke, + (void*)0xcafebab6, + (void*)0xcafebab7, + (void*)0xcafebab8, + (void*)0xcafebab9 +}; + +static void test_NdrStubForwardingFunction(void) +{ + void *This[5]; + void *real_this; + IRpcChannelBuffer *channel = (IRpcChannelBuffer*)0xdeadbeef; + RPC_MESSAGE *msg = (RPC_MESSAGE*)0xcafebabe; + DWORD *phase = (DWORD*)0x12345678; + IRpcStubBufferVtbl *base_buffer_vtbl_ptr = &base_buffer_vtbl; + IRpcStubBuffer *base_stub_buffer = (IRpcStubBuffer*)&base_buffer_vtbl_ptr; + + memset(This, 0xcc, sizeof(This)); + This[0] = base_stub_buffer; + real_this = &This[1]; + + NdrStubForwardingFunction( real_this, channel, msg, phase ); + ok(base_buffer_invoke_called == 1, "base_buffer_invoke called %d times\n", base_buffer_invoke_called); + +} + +static IRpcStubBuffer *create_stub(IPSFactoryBuffer *ppsf, REFIID iid, IUnknown *obj, HRESULT expected_result) +{ + IRpcStubBuffer *pstub = NULL; + HRESULT r; + + r = IPSFactoryBuffer_CreateStub(ppsf, iid, obj, &pstub); + ok(r == expected_result, "CreateStub returned %08x expected %08x\n", r, expected_result); + return pstub; +} + +static HRESULT WINAPI create_stub_test_QI(IUnknown *This, REFIID iid, void **ppv) +{ + ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n"); + *ppv = (void*)0xdeadbeef; + return S_OK; +} + +static IUnknownVtbl create_stub_test_vtbl = +{ + create_stub_test_QI, + NULL, + NULL +}; + +static HRESULT WINAPI create_stub_test_fail_QI(IUnknown *This, REFIID iid, void **ppv) +{ + ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n"); + *ppv = NULL; + return E_NOINTERFACE; +} + +static IUnknownVtbl create_stub_test_fail_vtbl = +{ + create_stub_test_fail_QI, + NULL, + NULL +}; + +static void test_CreateStub(IPSFactoryBuffer *ppsf) +{ + IUnknownVtbl *vtbl = &create_stub_test_vtbl; + IUnknown *obj = (IUnknown*)&vtbl; + IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); + CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; + const CInterfaceStubHeader *header = ((const CInterfaceStubHeader *)cstd_stub->lpVtbl) - 1; + + ok(IsEqualIID(header->piid, &IID_if1), "header iid differs\n"); + ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount); + /* 0xdeadbeef returned from create_stub_test_QI */ + ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject); + ok(cstd_stub->pPSFactory == ppsf, "pPSFactory %p\n", cstd_stub->pPSFactory); + + vtbl = &create_stub_test_fail_vtbl; + pstub = create_stub(ppsf, &IID_if1, obj, E_NOINTERFACE); + +} + +static HRESULT WINAPI connect_test_orig_QI(IUnknown *This, REFIID iid, void **ppv) +{ + ok(IsEqualIID(iid, &IID_if1) || + IsEqualIID(iid, &IID_if2), "incorrect iid\n"); + *ppv = (void*)This; + return S_OK; +} + +static int connect_test_orig_release_called; +static ULONG WINAPI connect_test_orig_release(IUnknown *This) +{ + connect_test_orig_release_called++; + return 0; +} + +static IUnknownVtbl connect_test_orig_vtbl = +{ + connect_test_orig_QI, + NULL, + connect_test_orig_release +}; + +static HRESULT WINAPI connect_test_new_QI(IUnknown *This, REFIID iid, void **ppv) +{ + ok(IsEqualIID(iid, &IID_if1) || + IsEqualIID(iid, &IID_if2), "incorrect iid\n"); + *ppv = (void*)0xcafebabe; + return S_OK; +} + +static IUnknownVtbl connect_test_new_vtbl = +{ + connect_test_new_QI, + NULL, + NULL +}; + +static HRESULT WINAPI connect_test_new_fail_QI(IUnknown *This, REFIID iid, void **ppv) +{ + ok(IsEqualIID(iid, &IID_if1), "incorrect iid\n"); + *ppv = (void*)0xdeadbeef; + return E_NOINTERFACE; +} + +static IUnknownVtbl connect_test_new_fail_vtbl = +{ + connect_test_new_fail_QI, + NULL, + NULL +}; + +static int connect_test_base_Connect_called; +static HRESULT WINAPI connect_test_base_Connect(IRpcStubBuffer *pstub, IUnknown *obj) +{ + connect_test_base_Connect_called++; + ok(*(void**)obj == (void*)0xbeefcafe, "unexpected obj %p\n", obj); + return S_OK; +} + +static IRpcStubBufferVtbl connect_test_base_stub_buffer_vtbl = +{ + (void*)0xcafebab0, + (void*)0xcafebab1, + (void*)0xcafebab2, + connect_test_base_Connect, + (void*)0xcafebab4, + (void*)0xcafebab5, + (void*)0xcafebab6, + (void*)0xcafebab7, + (void*)0xcafebab8, + (void*)0xcafebab9 +}; + +static void test_Connect(IPSFactoryBuffer *ppsf) +{ + IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl; + IUnknownVtbl *new_vtbl = &connect_test_new_vtbl; + IUnknownVtbl *new_fail_vtbl = &connect_test_new_fail_vtbl; + IUnknown *obj = (IUnknown*)&orig_vtbl; + IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); + CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; + IRpcStubBufferVtbl *base_stub_buf_vtbl = &connect_test_base_stub_buffer_vtbl; + HRESULT r; + + obj = (IUnknown*)&new_vtbl; + r = IRpcStubBuffer_Connect(pstub, obj); + ok(r == S_OK, "r %08x\n", r); + ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called); + ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject); + + cstd_stub->pvServerObject = (IUnknown*)&orig_vtbl; + obj = (IUnknown*)&new_fail_vtbl; + r = IRpcStubBuffer_Connect(pstub, obj); + ok(r == E_NOINTERFACE, "r %08x\n", r); + ok(cstd_stub->pvServerObject == (void*)0xdeadbeef, "pvServerObject %p\n", cstd_stub->pvServerObject); + ok(connect_test_orig_release_called == 2, "release called %d\n", connect_test_orig_release_called); + + /* Now use a delegated stub. + + We know from the NdrStubForwardFunction test that + (void**)pstub-1 is the base interface stub buffer. This shows + that (void**)pstub-2 contains the address of a vtable that gets + passed to the base interface's Connect method. Note that + (void**)pstub-2 itself gets passed to Connect and not + *((void**)pstub-2), so it should contain the vtable ptr and not + an interface ptr. */ + + obj = (IUnknown*)&orig_vtbl; + pstub = create_stub(ppsf, &IID_if2, obj, S_OK); + *((void**)pstub-1) = &base_stub_buf_vtbl; + *((void**)pstub-2) = (void*)0xbeefcafe; + + obj = (IUnknown*)&new_vtbl; + r = IRpcStubBuffer_Connect(pstub, obj); + ok(connect_test_base_Connect_called == 1, "connect_test_bsae_Connect called %d times\n", + connect_test_base_Connect_called); + ok(connect_test_orig_release_called == 3, "release called %d\n", connect_test_orig_release_called); + cstd_stub = (CStdStubBuffer*)pstub; + ok(cstd_stub->pvServerObject == (void*)0xcafebabe, "pvServerObject %p\n", cstd_stub->pvServerObject); +} + +static void test_Disconnect(IPSFactoryBuffer *ppsf) +{ + IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl; + IUnknown *obj = (IUnknown*)&orig_vtbl; + IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); + CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; + + connect_test_orig_release_called = 0; + IRpcStubBuffer_Disconnect(pstub); + ok(connect_test_orig_release_called == 1, "release called %d\n", connect_test_orig_release_called); + ok(cstd_stub->pvServerObject == NULL, "pvServerObject %p\n", cstd_stub->pvServerObject); +} + + +static int release_test_psfacbuf_release_called; +static ULONG WINAPI release_test_pretend_psfacbuf_release(IUnknown *pUnk) +{ + release_test_psfacbuf_release_called++; + return 1; +} + +static IUnknownVtbl release_test_pretend_psfacbuf_vtbl = +{ + NULL, + NULL, + release_test_pretend_psfacbuf_release +}; + +static void test_Release(IPSFactoryBuffer *ppsf) +{ + LONG facbuf_refs; + IUnknownVtbl *orig_vtbl = &connect_test_orig_vtbl; + IUnknown *obj = (IUnknown*)&orig_vtbl; + IUnknownVtbl *pretend_psfacbuf_vtbl = &release_test_pretend_psfacbuf_vtbl; + IUnknown *pretend_psfacbuf = (IUnknown *)&pretend_psfacbuf_vtbl; + IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if1, obj, S_OK); + CStdStubBuffer *cstd_stub = (CStdStubBuffer*)pstub; + + facbuf_refs = PSFactoryBuffer.RefCount; + + /* This shows that NdrCStdStubBuffer_Release doesn't call Disconnect */ + ok(cstd_stub->RefCount == 1, "ref count %d\n", cstd_stub->RefCount); + connect_test_orig_release_called = 0; + IRpcStubBuffer_Release(pstub); +todo_wine { + ok(connect_test_orig_release_called == 0, "release called %d\n", connect_test_orig_release_called); +} + ok(PSFactoryBuffer.RefCount == facbuf_refs - 1, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs); + + /* This shows that NdrCStdStubBuffer_Release calls Release on its 2nd arg, rather than on This->pPSFactory + (which are usually the same and indeed it's odd that _Release requires this 2nd arg). */ + pstub = create_stub(ppsf, &IID_if1, obj, S_OK); + ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs); + NdrCStdStubBuffer_Release(pstub, (IPSFactoryBuffer*)pretend_psfacbuf); + ok(release_test_psfacbuf_release_called == 1, "pretend_psfacbuf_release called %d\n", release_test_psfacbuf_release_called); + ok(PSFactoryBuffer.RefCount == facbuf_refs, "factory buffer refs %d orig %d\n", PSFactoryBuffer.RefCount, facbuf_refs); +} + +static HRESULT WINAPI delegating_invoke_test_QI(ITypeLib *pUnk, REFIID iid, void** ppv) +{ + + *ppv = pUnk; + return S_OK; +} + +static ULONG WINAPI delegating_invoke_test_addref(ITypeLib *pUnk) +{ + return 1; +} + +static ULONG WINAPI delegating_invoke_test_release(ITypeLib *pUnk) +{ + return 1; +} + +static UINT WINAPI delegating_invoke_test_get_type_info_count(ITypeLib *pUnk) +{ + return 0xabcdef; +} + +static ITypeLibVtbl delegating_invoke_test_obj_vtbl = +{ + delegating_invoke_test_QI, + delegating_invoke_test_addref, + delegating_invoke_test_release, + delegating_invoke_test_get_type_info_count, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + +static HRESULT WINAPI delegating_invoke_chan_query_interface(IRpcChannelBuffer *pchan, + REFIID iid, + void **ppv) +{ + ok(0, "call to QueryInterface not expected\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI delegating_invoke_chan_add_ref(IRpcChannelBuffer *pchan) +{ + return 2; +} + +static ULONG WINAPI delegating_invoke_chan_release(IRpcChannelBuffer *pchan) +{ + return 1; +} + +static HRESULT WINAPI delegating_invoke_chan_get_buffer(IRpcChannelBuffer *pchan, + RPCOLEMESSAGE *msg, + REFIID iid) +{ + msg->Buffer = HeapAlloc(GetProcessHeap(), 0, msg->cbBuffer); + return S_OK; +} + +static HRESULT WINAPI delegating_invoke_chan_send_receive(IRpcChannelBuffer *pchan, + RPCOLEMESSAGE *pMessage, + ULONG *pStatus) +{ + ok(0, "call to SendReceive not expected\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI delegating_invoke_chan_free_buffer(IRpcChannelBuffer *pchan, + RPCOLEMESSAGE *pMessage) +{ + ok(0, "call to FreeBuffer not expected\n"); + return E_NOTIMPL; +} + +static HRESULT WINAPI delegating_invoke_chan_get_dest_ctx(IRpcChannelBuffer *pchan, + DWORD *pdwDestContext, + void **ppvDestContext) +{ + *pdwDestContext = MSHCTX_LOCAL; + *ppvDestContext = NULL; + return S_OK; +} + +static HRESULT WINAPI delegating_invoke_chan_is_connected(IRpcChannelBuffer *pchan) +{ + ok(0, "call to IsConnected not expected\n"); + return E_NOTIMPL; +} + +static IRpcChannelBufferVtbl delegating_invoke_test_rpc_chan_vtbl = +{ + delegating_invoke_chan_query_interface, + delegating_invoke_chan_add_ref, + delegating_invoke_chan_release, + delegating_invoke_chan_get_buffer, + delegating_invoke_chan_send_receive, + delegating_invoke_chan_free_buffer, + delegating_invoke_chan_get_dest_ctx, + delegating_invoke_chan_is_connected +}; + +static void test_delegating_Invoke(IPSFactoryBuffer *ppsf) +{ + ITypeLibVtbl *obj_vtbl = &delegating_invoke_test_obj_vtbl; + IUnknown *obj = (IUnknown*)&obj_vtbl; + IRpcStubBuffer *pstub = create_stub(ppsf, &IID_if2, obj, S_OK); + IRpcChannelBufferVtbl *pchan_vtbl = &delegating_invoke_test_rpc_chan_vtbl; + IRpcChannelBuffer *pchan = (IRpcChannelBuffer *)&pchan_vtbl; + HRESULT r = E_FAIL; + RPCOLEMESSAGE msg; + + memset(&msg, 0, sizeof(msg)); + msg.dataRepresentation = NDR_LOCAL_DATA_REPRESENTATION; + msg.iMethod = 3; + r = IRpcStubBuffer_Invoke(pstub, &msg, pchan); + ok(r == S_OK, "ret %08x\n", r); + if(r == S_OK) + { + ok(*(DWORD*)msg.Buffer == 0xabcdef, "buf[0] %08x\n", *(DWORD*)msg.Buffer); + ok(*((DWORD*)msg.Buffer + 1) == S_OK, "buf[1] %08x\n", *((DWORD*)msg.Buffer + 1)); + } + IRpcStubBuffer_Release(pstub); +} + +START_TEST( cstub ) +{ + IPSFactoryBuffer *ppsf; + + OleInitialize(NULL); + + ppsf = test_NdrDllGetClassObject(); + test_NdrStubForwardingFunction(); + test_CreateStub(ppsf); + test_Connect(ppsf); + test_Disconnect(ppsf); + test_Release(ppsf); + test_delegating_Invoke(ppsf); + + OleUninitialize(); +} diff --git a/rostests/winetests/rpcrt4/generated.c b/rostests/winetests/rpcrt4/generated.c new file mode 100644 index 00000000000..fb7d7cca108 --- /dev/null +++ b/rostests/winetests/rpcrt4/generated.c @@ -0,0 +1,709 @@ +/* File generated automatically from tools/winapi/test.dat; do not edit! */ +/* This file can be copied, modified and distributed without restriction. */ + +/* + * Unit tests for data structure packing + */ + +#define WINVER 0x0501 +#define _WIN32_IE 0x0501 +#define _WIN32_WINNT 0x0501 + +#define WINE_NOWINSOCK + +#include +#include "windef.h" +#include "winbase.h" +#include "rpc.h" +#include "rpcndr.h" +#include "rpcproxy.h" + +#include "wine/test.h" + +/*********************************************************************** + * Compability macros + */ + +#define DWORD_PTR UINT_PTR +#define LONG_PTR INT_PTR +#define ULONG_PTR UINT_PTR + +/*********************************************************************** + * Windows API extension + */ + +#if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus) +# define FIELD_ALIGNMENT(type, field) __alignof(((type*)0)->field) +#elif defined(__GNUC__) +# define FIELD_ALIGNMENT(type, field) __alignof__(((type*)0)->field) +#else +/* FIXME: Not sure if is possible to do without compiler extension */ +#endif + +#if defined(_MSC_VER) && (_MSC_VER >= 1300) && defined(__cplusplus) +# define _TYPE_ALIGNMENT(type) __alignof(type) +#elif defined(__GNUC__) +# define _TYPE_ALIGNMENT(type) __alignof__(type) +#else +/* + * FIXME: Not sure if is possible to do without compiler extension + * (if type is not just a name that is, if so the normal) + * TYPE_ALIGNMENT can be used) + */ +#endif + +#if defined(TYPE_ALIGNMENT) && defined(_MSC_VER) && _MSC_VER >= 800 && !defined(__cplusplus) +#pragma warning(disable:4116) +#endif + +#if !defined(TYPE_ALIGNMENT) && defined(_TYPE_ALIGNMENT) +# define TYPE_ALIGNMENT _TYPE_ALIGNMENT +#endif + +/*********************************************************************** + * Test helper macros + */ + +#ifdef FIELD_ALIGNMENT +# define TEST_FIELD_ALIGNMENT(type, field, align) \ + ok(FIELD_ALIGNMENT(type, field) == align, \ + "FIELD_ALIGNMENT(" #type ", " #field ") == %d (expected " #align ")\n", \ + (int)FIELD_ALIGNMENT(type, field)) +#else +# define TEST_FIELD_ALIGNMENT(type, field, align) do { } while (0) +#endif + +#define TEST_FIELD_OFFSET(type, field, offset) \ + ok(FIELD_OFFSET(type, field) == offset, \ + "FIELD_OFFSET(" #type ", " #field ") == %ld (expected " #offset ")\n", \ + (long int)FIELD_OFFSET(type, field)) + +#ifdef _TYPE_ALIGNMENT +#define TEST__TYPE_ALIGNMENT(type, align) \ + ok(_TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)_TYPE_ALIGNMENT(type)) +#else +# define TEST__TYPE_ALIGNMENT(type, align) do { } while (0) +#endif + +#ifdef TYPE_ALIGNMENT +#define TEST_TYPE_ALIGNMENT(type, align) \ + ok(TYPE_ALIGNMENT(type) == align, "TYPE_ALIGNMENT(" #type ") == %d (expected " #align ")\n", (int)TYPE_ALIGNMENT(type)) +#else +# define TEST_TYPE_ALIGNMENT(type, align) do { } while (0) +#endif + +#define TEST_TYPE_SIZE(type, size) \ + ok(sizeof(type) == size, "sizeof(" #type ") == %d (expected " #size ")\n", ((int) sizeof(type))) + +/*********************************************************************** + * Test macros + */ + +#define TEST_FIELD(type, field_type, field_name, field_offset, field_size, field_align) \ + TEST_TYPE_SIZE(field_type, field_size); \ + TEST_FIELD_ALIGNMENT(type, field_name, field_align); \ + TEST_FIELD_OFFSET(type, field_name, field_offset); \ + +#define TEST_TYPE(type, size, align) \ + TEST_TYPE_ALIGNMENT(type, align); \ + TEST_TYPE_SIZE(type, size) + +#define TEST_TYPE_POINTER(type, size, align) \ + TEST__TYPE_ALIGNMENT(*(type)0, align); \ + TEST_TYPE_SIZE(*(type)0, size) + +#define TEST_TYPE_SIGNED(type) \ + ok((type) -1 < 0, "(" #type ") -1 < 0\n"); + +#define TEST_TYPE_UNSIGNED(type) \ + ok((type) -1 > 0, "(" #type ") -1 > 0\n"); + +static void test_pack_I_RPC_HANDLE(void) +{ + /* I_RPC_HANDLE */ + TEST_TYPE(I_RPC_HANDLE, 4, 4); +} + +static void test_pack_RPC_STATUS(void) +{ + /* RPC_STATUS */ + TEST_TYPE(RPC_STATUS, 4, 4); + TEST_TYPE_SIGNED(RPC_STATUS); +} + +static void test_pack_PRPC_POLICY(void) +{ + /* PRPC_POLICY */ + TEST_TYPE(PRPC_POLICY, 4, 4); + TEST_TYPE_POINTER(PRPC_POLICY, 12, 4); +} + +static void test_pack_RPC_AUTH_IDENTITY_HANDLE(void) +{ + /* RPC_AUTH_IDENTITY_HANDLE */ + TEST_TYPE(RPC_AUTH_IDENTITY_HANDLE, 4, 4); +} + +static void test_pack_RPC_AUTH_KEY_RETRIEVAL_FN(void) +{ + /* RPC_AUTH_KEY_RETRIEVAL_FN */ +} + +static void test_pack_RPC_AUTHZ_HANDLE(void) +{ + /* RPC_AUTHZ_HANDLE */ + TEST_TYPE(RPC_AUTHZ_HANDLE, 4, 4); +} + +static void test_pack_RPC_BINDING_HANDLE(void) +{ + /* RPC_BINDING_HANDLE */ + TEST_TYPE(RPC_BINDING_HANDLE, 4, 4); +} + +static void test_pack_RPC_BINDING_VECTOR(void) +{ + /* RPC_BINDING_VECTOR (pack 4) */ + TEST_TYPE(RPC_BINDING_VECTOR, 8, 4); + TEST_FIELD(RPC_BINDING_VECTOR, unsigned long, Count, 0, 4, 4); + TEST_FIELD(RPC_BINDING_VECTOR, RPC_BINDING_HANDLE[1], BindingH, 4, 4, 4); +} + +static void test_pack_RPC_IF_HANDLE(void) +{ + /* RPC_IF_HANDLE */ + TEST_TYPE(RPC_IF_HANDLE, 4, 4); +} + +static void test_pack_RPC_IF_ID(void) +{ + /* RPC_IF_ID (pack 4) */ +} + +static void test_pack_RPC_POLICY(void) +{ + /* RPC_POLICY (pack 4) */ + TEST_TYPE(RPC_POLICY, 12, 4); + TEST_FIELD(RPC_POLICY, unsigned int, Length, 0, 4, 4); + TEST_FIELD(RPC_POLICY, unsigned long, EndpointFlags, 4, 4, 4); + TEST_FIELD(RPC_POLICY, unsigned long, NICFlags, 8, 4, 4); +} + +static void test_pack_UUID_VECTOR(void) +{ + /* UUID_VECTOR (pack 4) */ + TEST_TYPE(UUID_VECTOR, 8, 4); + TEST_FIELD(UUID_VECTOR, unsigned long, Count, 0, 4, 4); + TEST_FIELD(UUID_VECTOR, UUID *[1], Uuid, 4, 4, 4); +} + +static void test_pack_PRPC_CLIENT_INTERFACE(void) +{ + /* PRPC_CLIENT_INTERFACE */ + TEST_TYPE(PRPC_CLIENT_INTERFACE, 4, 4); +} + +static void test_pack_PRPC_DISPATCH_TABLE(void) +{ + /* PRPC_DISPATCH_TABLE */ + TEST_TYPE(PRPC_DISPATCH_TABLE, 4, 4); + TEST_TYPE_POINTER(PRPC_DISPATCH_TABLE, 12, 4); +} + +static void test_pack_PRPC_MESSAGE(void) +{ + /* PRPC_MESSAGE */ + TEST_TYPE(PRPC_MESSAGE, 4, 4); + TEST_TYPE_POINTER(PRPC_MESSAGE, 44, 4); +} + +static void test_pack_PRPC_PROTSEQ_ENDPOINT(void) +{ + /* PRPC_PROTSEQ_ENDPOINT */ + TEST_TYPE(PRPC_PROTSEQ_ENDPOINT, 4, 4); + TEST_TYPE_POINTER(PRPC_PROTSEQ_ENDPOINT, 8, 4); +} + +static void test_pack_PRPC_SERVER_INTERFACE(void) +{ + /* PRPC_SERVER_INTERFACE */ + TEST_TYPE(PRPC_SERVER_INTERFACE, 4, 4); +} + +static void test_pack_PRPC_SYNTAX_IDENTIFIER(void) +{ + /* PRPC_SYNTAX_IDENTIFIER */ + TEST_TYPE(PRPC_SYNTAX_IDENTIFIER, 4, 4); + TEST_TYPE_POINTER(PRPC_SYNTAX_IDENTIFIER, 20, 4); +} + +static void test_pack_RPC_CLIENT_INTERFACE(void) +{ + /* RPC_CLIENT_INTERFACE (pack 4) */ + TEST_FIELD(RPC_CLIENT_INTERFACE, unsigned int, Length, 0, 4, 4); +} + +static void test_pack_RPC_DISPATCH_FUNCTION(void) +{ + /* RPC_DISPATCH_FUNCTION */ +} + +static void test_pack_RPC_DISPATCH_TABLE(void) +{ + /* RPC_DISPATCH_TABLE (pack 4) */ + TEST_TYPE(RPC_DISPATCH_TABLE, 12, 4); + TEST_FIELD(RPC_DISPATCH_TABLE, unsigned int, DispatchTableCount, 0, 4, 4); + TEST_FIELD(RPC_DISPATCH_TABLE, RPC_DISPATCH_FUNCTION*, DispatchTable, 4, 4, 4); + TEST_FIELD(RPC_DISPATCH_TABLE, LONG_PTR, Reserved, 8, 4, 4); +} + +static void test_pack_RPC_MESSAGE(void) +{ + /* RPC_MESSAGE (pack 4) */ + TEST_TYPE(RPC_MESSAGE, 44, 4); + TEST_FIELD(RPC_MESSAGE, RPC_BINDING_HANDLE, Handle, 0, 4, 4); + TEST_FIELD(RPC_MESSAGE, unsigned long, DataRepresentation, 4, 4, 4); + TEST_FIELD(RPC_MESSAGE, void*, Buffer, 8, 4, 4); + TEST_FIELD(RPC_MESSAGE, unsigned int, BufferLength, 12, 4, 4); + TEST_FIELD(RPC_MESSAGE, unsigned int, ProcNum, 16, 4, 4); + TEST_FIELD(RPC_MESSAGE, PRPC_SYNTAX_IDENTIFIER, TransferSyntax, 20, 4, 4); + TEST_FIELD(RPC_MESSAGE, void*, RpcInterfaceInformation, 24, 4, 4); + TEST_FIELD(RPC_MESSAGE, void*, ReservedForRuntime, 28, 4, 4); + TEST_FIELD(RPC_MESSAGE, RPC_MGR_EPV*, ManagerEpv, 32, 4, 4); + TEST_FIELD(RPC_MESSAGE, void*, ImportContext, 36, 4, 4); + TEST_FIELD(RPC_MESSAGE, unsigned long, RpcFlags, 40, 4, 4); +} + +static void test_pack_RPC_PROTSEQ_ENDPOINT(void) +{ + /* RPC_PROTSEQ_ENDPOINT (pack 4) */ + TEST_TYPE(RPC_PROTSEQ_ENDPOINT, 8, 4); + TEST_FIELD(RPC_PROTSEQ_ENDPOINT, unsigned char*, RpcProtocolSequence, 0, 4, 4); + TEST_FIELD(RPC_PROTSEQ_ENDPOINT, unsigned char*, Endpoint, 4, 4, 4); +} + +static void test_pack_RPC_SERVER_INTERFACE(void) +{ + /* RPC_SERVER_INTERFACE (pack 4) */ + TEST_FIELD(RPC_SERVER_INTERFACE, unsigned int, Length, 0, 4, 4); +} + +static void test_pack_RPC_SYNTAX_IDENTIFIER(void) +{ + /* RPC_SYNTAX_IDENTIFIER (pack 4) */ + TEST_TYPE(RPC_SYNTAX_IDENTIFIER, 20, 4); + TEST_FIELD(RPC_SYNTAX_IDENTIFIER, GUID, SyntaxGUID, 0, 16, 4); + TEST_FIELD(RPC_SYNTAX_IDENTIFIER, RPC_VERSION, SyntaxVersion, 16, 4, 2); +} + +static void test_pack_RPC_VERSION(void) +{ + /* RPC_VERSION (pack 4) */ + TEST_TYPE(RPC_VERSION, 4, 2); + TEST_FIELD(RPC_VERSION, unsigned short, MajorVersion, 0, 2, 2); + TEST_FIELD(RPC_VERSION, unsigned short, MinorVersion, 2, 2, 2); +} + +static void test_pack_ARRAY_INFO(void) +{ + /* ARRAY_INFO (pack 4) */ + TEST_TYPE(ARRAY_INFO, 24, 4); + TEST_FIELD(ARRAY_INFO, long, Dimension, 0, 4, 4); + TEST_FIELD(ARRAY_INFO, unsigned long *, BufferConformanceMark, 4, 4, 4); + TEST_FIELD(ARRAY_INFO, unsigned long *, BufferVarianceMark, 8, 4, 4); + TEST_FIELD(ARRAY_INFO, unsigned long *, MaxCountArray, 12, 4, 4); + TEST_FIELD(ARRAY_INFO, unsigned long *, OffsetArray, 16, 4, 4); + TEST_FIELD(ARRAY_INFO, unsigned long *, ActualCountArray, 20, 4, 4); +} + +static void test_pack_COMM_FAULT_OFFSETS(void) +{ + /* COMM_FAULT_OFFSETS (pack 4) */ + TEST_TYPE(COMM_FAULT_OFFSETS, 4, 2); + TEST_FIELD(COMM_FAULT_OFFSETS, short, CommOffset, 0, 2, 2); + TEST_FIELD(COMM_FAULT_OFFSETS, short, FaultOffset, 2, 2, 2); +} + +static void test_pack_CS_STUB_INFO(void) +{ + /* CS_STUB_INFO (pack 4) */ + TEST_TYPE(CS_STUB_INFO, 12, 4); + TEST_FIELD(CS_STUB_INFO, unsigned long, WireCodeset, 0, 4, 4); + TEST_FIELD(CS_STUB_INFO, unsigned long, DesiredReceivingCodeset, 4, 4, 4); + TEST_FIELD(CS_STUB_INFO, void *, CSArrayInfo, 8, 4, 4); +} + +static void test_pack_EXPR_EVAL(void) +{ + /* EXPR_EVAL */ +} + +static void test_pack_FULL_PTR_TO_REFID_ELEMENT(void) +{ + /* FULL_PTR_TO_REFID_ELEMENT (pack 4) */ + TEST_TYPE(FULL_PTR_TO_REFID_ELEMENT, 16, 4); + TEST_FIELD(FULL_PTR_TO_REFID_ELEMENT, struct _FULL_PTR_TO_REFID_ELEMENT *, Next, 0, 4, 4); + TEST_FIELD(FULL_PTR_TO_REFID_ELEMENT, void *, Pointer, 4, 4, 4); + TEST_FIELD(FULL_PTR_TO_REFID_ELEMENT, unsigned long, RefId, 8, 4, 4); + TEST_FIELD(FULL_PTR_TO_REFID_ELEMENT, unsigned char, State, 12, 1, 1); +} + +static void test_pack_FULL_PTR_XLAT_TABLES(void) +{ + /* FULL_PTR_XLAT_TABLES (pack 4) */ +} + +static void test_pack_GENERIC_BINDING_INFO(void) +{ + /* GENERIC_BINDING_INFO (pack 4) */ + TEST_FIELD(GENERIC_BINDING_INFO, void *, pObj, 0, 4, 4); + TEST_FIELD(GENERIC_BINDING_INFO, unsigned int, Size, 4, 4, 4); +} + +static void test_pack_GENERIC_BINDING_ROUTINE_PAIR(void) +{ + /* GENERIC_BINDING_ROUTINE_PAIR (pack 4) */ +} + +static void test_pack_MALLOC_FREE_STRUCT(void) +{ + /* MALLOC_FREE_STRUCT (pack 4) */ +} + +static void test_pack_MIDL_FORMAT_STRING(void) +{ + /* MIDL_FORMAT_STRING (pack 4) */ + TEST_FIELD(MIDL_FORMAT_STRING, short, Pad, 0, 2, 2); +} + +static void test_pack_MIDL_SERVER_INFO(void) +{ + /* MIDL_SERVER_INFO (pack 4) */ + TEST_TYPE(MIDL_SERVER_INFO, 32, 4); + TEST_FIELD(MIDL_SERVER_INFO, PMIDL_STUB_DESC, pStubDesc, 0, 4, 4); + TEST_FIELD(MIDL_SERVER_INFO, SERVER_ROUTINE *, DispatchTable, 4, 4, 4); + TEST_FIELD(MIDL_SERVER_INFO, PFORMAT_STRING, ProcString, 8, 4, 4); + TEST_FIELD(MIDL_SERVER_INFO, unsigned short *, FmtStringOffset, 12, 4, 4); + TEST_FIELD(MIDL_SERVER_INFO, STUB_THUNK *, ThunkTable, 16, 4, 4); + TEST_FIELD(MIDL_SERVER_INFO, PRPC_SYNTAX_IDENTIFIER, pTransferSyntax, 20, 4, 4); + TEST_FIELD(MIDL_SERVER_INFO, ULONG_PTR, nCount, 24, 4, 4); + TEST_FIELD(MIDL_SERVER_INFO, PMIDL_SYNTAX_INFO, pSyntaxInfo, 28, 4, 4); +} + +static void test_pack_MIDL_STUB_DESC(void) +{ + /* MIDL_STUB_DESC (pack 4) */ + TEST_FIELD(MIDL_STUB_DESC, void *, RpcInterfaceInformation, 0, 4, 4); +} + +static void test_pack_MIDL_STUB_MESSAGE(void) +{ + /* MIDL_STUB_MESSAGE (pack 4) */ + TEST_FIELD(MIDL_STUB_MESSAGE, PRPC_MESSAGE, RpcMsg, 0, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char *, Buffer, 4, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char *, BufferStart, 8, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char *, BufferEnd, 12, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char *, BufferMark, 16, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned long, BufferLength, 20, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned long, MemorySize, 24, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char *, Memory, 28, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, int, IsClient, 32, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, int, ReuseBuffer, 36, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, struct NDR_ALLOC_ALL_NODES_CONTEXT *, pAllocAllNodesContext, 40, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, struct NDR_POINTER_QUEUE_STATE *, pPointerQueueState, 44, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, int, IgnoreEmbeddedPointers, 48, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char *, PointerBufferMark, 52, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char, fBufferValid, 56, 1, 1); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned char, uFlags, 57, 1, 1); + TEST_FIELD(MIDL_STUB_MESSAGE, ULONG_PTR, MaxCount, 60, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned long, Offset, 64, 4, 4); + TEST_FIELD(MIDL_STUB_MESSAGE, unsigned long, ActualCount, 68, 4, 4); +} + +static void test_pack_MIDL_STUBLESS_PROXY_INFO(void) +{ + /* MIDL_STUBLESS_PROXY_INFO (pack 4) */ + TEST_TYPE(MIDL_STUBLESS_PROXY_INFO, 24, 4); + TEST_FIELD(MIDL_STUBLESS_PROXY_INFO, PMIDL_STUB_DESC, pStubDesc, 0, 4, 4); + TEST_FIELD(MIDL_STUBLESS_PROXY_INFO, PFORMAT_STRING, ProcFormatString, 4, 4, 4); + TEST_FIELD(MIDL_STUBLESS_PROXY_INFO, unsigned short *, FormatStringOffset, 8, 4, 4); + TEST_FIELD(MIDL_STUBLESS_PROXY_INFO, PRPC_SYNTAX_IDENTIFIER, pTransferSyntax, 12, 4, 4); + TEST_FIELD(MIDL_STUBLESS_PROXY_INFO, ULONG_PTR, nCount, 16, 4, 4); + TEST_FIELD(MIDL_STUBLESS_PROXY_INFO, PMIDL_SYNTAX_INFO, pSyntaxInfo, 20, 4, 4); +} + +static void test_pack_MIDL_SYNTAX_INFO(void) +{ + /* MIDL_SYNTAX_INFO (pack 4) */ +} + +static void test_pack_NDR_CCONTEXT(void) +{ + /* NDR_CCONTEXT */ + TEST_TYPE(NDR_CCONTEXT, 4, 4); +} + +static void test_pack_NDR_NOTIFY_ROUTINE(void) +{ + /* NDR_NOTIFY_ROUTINE */ +} + +static void test_pack_NDR_NOTIFY2_ROUTINE(void) +{ + /* NDR_NOTIFY2_ROUTINE */ +} + +static void test_pack_NDR_RUNDOWN(void) +{ + /* NDR_RUNDOWN */ +} + +static void test_pack_NDR_SCONTEXT(void) +{ + /* NDR_SCONTEXT */ + TEST_TYPE(NDR_SCONTEXT, 4, 4); +} + +static void test_pack_PARRAY_INFO(void) +{ + /* PARRAY_INFO */ + TEST_TYPE(PARRAY_INFO, 4, 4); + TEST_TYPE_POINTER(PARRAY_INFO, 24, 4); +} + +static void test_pack_PFORMAT_STRING(void) +{ + /* PFORMAT_STRING */ + TEST_TYPE(PFORMAT_STRING, 4, 4); +} + +static void test_pack_PFULL_PTR_TO_REFID_ELEMENT(void) +{ + /* PFULL_PTR_TO_REFID_ELEMENT */ + TEST_TYPE(PFULL_PTR_TO_REFID_ELEMENT, 4, 4); + TEST_TYPE_POINTER(PFULL_PTR_TO_REFID_ELEMENT, 16, 4); +} + +static void test_pack_PFULL_PTR_XLAT_TABLES(void) +{ + /* PFULL_PTR_XLAT_TABLES */ + TEST_TYPE(PFULL_PTR_XLAT_TABLES, 4, 4); +} + +static void test_pack_PGENERIC_BINDING_INFO(void) +{ + /* PGENERIC_BINDING_INFO */ + TEST_TYPE(PGENERIC_BINDING_INFO, 4, 4); +} + +static void test_pack_PGENERIC_BINDING_ROUTINE_PAIR(void) +{ + /* PGENERIC_BINDING_ROUTINE_PAIR */ + TEST_TYPE(PGENERIC_BINDING_ROUTINE_PAIR, 4, 4); +} + +static void test_pack_PMIDL_SERVER_INFO(void) +{ + /* PMIDL_SERVER_INFO */ + TEST_TYPE(PMIDL_SERVER_INFO, 4, 4); + TEST_TYPE_POINTER(PMIDL_SERVER_INFO, 32, 4); +} + +static void test_pack_PMIDL_STUB_DESC(void) +{ + /* PMIDL_STUB_DESC */ + TEST_TYPE(PMIDL_STUB_DESC, 4, 4); +} + +static void test_pack_PMIDL_STUB_MESSAGE(void) +{ + /* PMIDL_STUB_MESSAGE */ + TEST_TYPE(PMIDL_STUB_MESSAGE, 4, 4); +} + +static void test_pack_PMIDL_STUBLESS_PROXY_INFO(void) +{ + /* PMIDL_STUBLESS_PROXY_INFO */ + TEST_TYPE(PMIDL_STUBLESS_PROXY_INFO, 4, 4); + TEST_TYPE_POINTER(PMIDL_STUBLESS_PROXY_INFO, 24, 4); +} + +static void test_pack_PMIDL_SYNTAX_INFO(void) +{ + /* PMIDL_SYNTAX_INFO */ + TEST_TYPE(PMIDL_SYNTAX_INFO, 4, 4); +} + +static void test_pack_PNDR_ASYNC_MESSAGE(void) +{ + /* PNDR_ASYNC_MESSAGE */ + TEST_TYPE(PNDR_ASYNC_MESSAGE, 4, 4); +} + +static void test_pack_PNDR_CORRELATION_INFO(void) +{ + /* PNDR_CORRELATION_INFO */ + TEST_TYPE(PNDR_CORRELATION_INFO, 4, 4); +} + +static void test_pack_PSCONTEXT_QUEUE(void) +{ + /* PSCONTEXT_QUEUE */ + TEST_TYPE(PSCONTEXT_QUEUE, 4, 4); + TEST_TYPE_POINTER(PSCONTEXT_QUEUE, 8, 4); +} + +static void test_pack_PXMIT_ROUTINE_QUINTUPLE(void) +{ + /* PXMIT_ROUTINE_QUINTUPLE */ + TEST_TYPE(PXMIT_ROUTINE_QUINTUPLE, 4, 4); +} + +static void test_pack_SCONTEXT_QUEUE(void) +{ + /* SCONTEXT_QUEUE (pack 4) */ + TEST_TYPE(SCONTEXT_QUEUE, 8, 4); + TEST_FIELD(SCONTEXT_QUEUE, unsigned long, NumberOfObjects, 0, 4, 4); + TEST_FIELD(SCONTEXT_QUEUE, NDR_SCONTEXT *, ArrayOfObjects, 4, 4, 4); +} + +static void test_pack_SERVER_ROUTINE(void) +{ + /* SERVER_ROUTINE */ +} + +static void test_pack_STUB_THUNK(void) +{ + /* STUB_THUNK */ +} + +static void test_pack_USER_MARSHAL_CB(void) +{ + /* USER_MARSHAL_CB (pack 4) */ + TEST_FIELD(USER_MARSHAL_CB, unsigned long, Flags, 0, 4, 4); + TEST_FIELD(USER_MARSHAL_CB, PMIDL_STUB_MESSAGE, pStubMsg, 4, 4, 4); + TEST_FIELD(USER_MARSHAL_CB, PFORMAT_STRING, pReserve, 8, 4, 4); + TEST_FIELD(USER_MARSHAL_CB, unsigned long, Signature, 12, 4, 4); +} + +static void test_pack_USER_MARSHAL_FREEING_ROUTINE(void) +{ + /* USER_MARSHAL_FREEING_ROUTINE */ +} + +static void test_pack_USER_MARSHAL_MARSHALLING_ROUTINE(void) +{ + /* USER_MARSHAL_MARSHALLING_ROUTINE */ +} + +static void test_pack_USER_MARSHAL_ROUTINE_QUADRUPLE(void) +{ + /* USER_MARSHAL_ROUTINE_QUADRUPLE (pack 4) */ +} + +static void test_pack_USER_MARSHAL_SIZING_ROUTINE(void) +{ + /* USER_MARSHAL_SIZING_ROUTINE */ +} + +static void test_pack_USER_MARSHAL_UNMARSHALLING_ROUTINE(void) +{ + /* USER_MARSHAL_UNMARSHALLING_ROUTINE */ +} + +static void test_pack_XMIT_HELPER_ROUTINE(void) +{ + /* XMIT_HELPER_ROUTINE */ +} + +static void test_pack_XMIT_ROUTINE_QUINTUPLE(void) +{ + /* XMIT_ROUTINE_QUINTUPLE (pack 4) */ +} + +static void test_pack_PRPC_STUB_FUNCTION(void) +{ + /* PRPC_STUB_FUNCTION */ +} + +static void test_pack(void) +{ + test_pack_ARRAY_INFO(); + test_pack_COMM_FAULT_OFFSETS(); + test_pack_CS_STUB_INFO(); + test_pack_EXPR_EVAL(); + test_pack_FULL_PTR_TO_REFID_ELEMENT(); + test_pack_FULL_PTR_XLAT_TABLES(); + test_pack_GENERIC_BINDING_INFO(); + test_pack_GENERIC_BINDING_ROUTINE_PAIR(); + test_pack_I_RPC_HANDLE(); + test_pack_MALLOC_FREE_STRUCT(); + test_pack_MIDL_FORMAT_STRING(); + test_pack_MIDL_SERVER_INFO(); + test_pack_MIDL_STUBLESS_PROXY_INFO(); + test_pack_MIDL_STUB_DESC(); + test_pack_MIDL_STUB_MESSAGE(); + test_pack_MIDL_SYNTAX_INFO(); + test_pack_NDR_CCONTEXT(); + test_pack_NDR_NOTIFY2_ROUTINE(); + test_pack_NDR_NOTIFY_ROUTINE(); + test_pack_NDR_RUNDOWN(); + test_pack_NDR_SCONTEXT(); + test_pack_PARRAY_INFO(); + test_pack_PFORMAT_STRING(); + test_pack_PFULL_PTR_TO_REFID_ELEMENT(); + test_pack_PFULL_PTR_XLAT_TABLES(); + test_pack_PGENERIC_BINDING_INFO(); + test_pack_PGENERIC_BINDING_ROUTINE_PAIR(); + test_pack_PMIDL_SERVER_INFO(); + test_pack_PMIDL_STUBLESS_PROXY_INFO(); + test_pack_PMIDL_STUB_DESC(); + test_pack_PMIDL_STUB_MESSAGE(); + test_pack_PMIDL_SYNTAX_INFO(); + test_pack_PNDR_ASYNC_MESSAGE(); + test_pack_PNDR_CORRELATION_INFO(); + test_pack_PRPC_CLIENT_INTERFACE(); + test_pack_PRPC_DISPATCH_TABLE(); + test_pack_PRPC_MESSAGE(); + test_pack_PRPC_POLICY(); + test_pack_PRPC_PROTSEQ_ENDPOINT(); + test_pack_PRPC_SERVER_INTERFACE(); + test_pack_PRPC_STUB_FUNCTION(); + test_pack_PRPC_SYNTAX_IDENTIFIER(); + test_pack_PSCONTEXT_QUEUE(); + test_pack_PXMIT_ROUTINE_QUINTUPLE(); + test_pack_RPC_AUTHZ_HANDLE(); + test_pack_RPC_AUTH_IDENTITY_HANDLE(); + test_pack_RPC_AUTH_KEY_RETRIEVAL_FN(); + test_pack_RPC_BINDING_HANDLE(); + test_pack_RPC_BINDING_VECTOR(); + test_pack_RPC_CLIENT_INTERFACE(); + test_pack_RPC_DISPATCH_FUNCTION(); + test_pack_RPC_DISPATCH_TABLE(); + test_pack_RPC_IF_HANDLE(); + test_pack_RPC_IF_ID(); + test_pack_RPC_MESSAGE(); + test_pack_RPC_POLICY(); + test_pack_RPC_PROTSEQ_ENDPOINT(); + test_pack_RPC_SERVER_INTERFACE(); + test_pack_RPC_STATUS(); + test_pack_RPC_SYNTAX_IDENTIFIER(); + test_pack_RPC_VERSION(); + test_pack_SCONTEXT_QUEUE(); + test_pack_SERVER_ROUTINE(); + test_pack_STUB_THUNK(); + test_pack_USER_MARSHAL_CB(); + test_pack_USER_MARSHAL_FREEING_ROUTINE(); + test_pack_USER_MARSHAL_MARSHALLING_ROUTINE(); + test_pack_USER_MARSHAL_ROUTINE_QUADRUPLE(); + test_pack_USER_MARSHAL_SIZING_ROUTINE(); + test_pack_USER_MARSHAL_UNMARSHALLING_ROUTINE(); + test_pack_UUID_VECTOR(); + test_pack_XMIT_HELPER_ROUTINE(); + test_pack_XMIT_ROUTINE_QUINTUPLE(); +} + +START_TEST(generated) +{ + test_pack(); +} diff --git a/rostests/winetests/rpcrt4/ndr_marshall.c b/rostests/winetests/rpcrt4/ndr_marshall.c new file mode 100644 index 00000000000..eadb9c7395b --- /dev/null +++ b/rostests/winetests/rpcrt4/ndr_marshall.c @@ -0,0 +1,1524 @@ +/* + * Unit test suite for ndr marshalling functions + * + * Copyright 2006 Huw Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define NTDDI_WIN2K 0x05000000 +#define NTDDI_VERSION NTDDI_WIN2K /* for some MIDL_STUB_MESSAGE fields */ + +#include "wine/test.h" +#include +#include +#include +#include + +#include "rpc.h" +#include "rpcdce.h" +#include "rpcproxy.h" + + +static int my_alloc_called; +static int my_free_called; +static void * CALLBACK my_alloc(size_t size) +{ + my_alloc_called++; + return NdrOleAllocate(size); +} + +static void CALLBACK my_free(void *ptr) +{ + my_free_called++; + NdrOleFree(ptr); +} + +static const MIDL_STUB_DESC Object_StubDesc = + { + NULL, + my_alloc, + my_free, + { 0 }, + 0, + 0, + 0, + 0, + NULL, /* format string, filled in by tests */ + 1, /* -error bounds_check flag */ + 0x20000, /* Ndr library version */ + 0, + 0x50100a4, /* MIDL Version 5.1.164 */ + 0, + NULL, + 0, /* notify & notify_flag routine table */ + 1, /* Flags */ + 0, /* Reserved3 */ + 0, /* Reserved4 */ + 0 /* Reserved5 */ + }; + + +static void test_ndr_simple_type(void) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + long l, l2 = 0; + + StubDesc = Object_StubDesc; + StubDesc.pFormatTypes = NULL; + + NdrClientInitializeNew( + &RpcMessage, + &StubMsg, + &StubDesc, + 0); + + StubMsg.BufferLength = 16; + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + l = 0xcafebabe; + NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, 8 /* FC_LONG */); + ok(StubMsg.Buffer == StubMsg.BufferStart + 4, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart); + ok(*(long*)StubMsg.BufferStart == l, "%ld\n", *(long*)StubMsg.BufferStart); + + StubMsg.Buffer = StubMsg.BufferStart + 1; + NdrSimpleTypeMarshall(&StubMsg, (unsigned char*)&l, 8 /* FC_LONG */); + ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart); + ok(*(long*)(StubMsg.BufferStart + 4) == l, "%ld\n", *(long*)StubMsg.BufferStart); + + StubMsg.Buffer = StubMsg.BufferStart + 1; + NdrSimpleTypeUnmarshall(&StubMsg, (unsigned char*)&l2, 8 /* FC_LONG */); + ok(StubMsg.Buffer == StubMsg.BufferStart + 8, "%p %p\n", StubMsg.Buffer, StubMsg.BufferStart); + ok(l2 == l, "%ld\n", l2); + + HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); +} + +static void test_pointer_marshal(const unsigned char *formattypes, + void *memsrc, + long srcsize, + const void *wiredata, + ULONG wiredatalen, + int(*cmp)(const void*,const void*,size_t), + long num_additional_allocs, + const char *msgpfx) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + DWORD size; + void *ptr; + unsigned char *mem, *mem_orig; + + my_alloc_called = my_free_called = 0; + if(!cmp) + cmp = memcmp; + + StubDesc = Object_StubDesc; + StubDesc.pFormatTypes = formattypes; + + NdrClientInitializeNew( + &RpcMessage, + &StubMsg, + &StubDesc, + 0); + + StubMsg.BufferLength = 0; + NdrPointerBufferSize( &StubMsg, + memsrc, + formattypes ); + ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength); + + /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; + + memset(StubMsg.BufferStart, 0x0, StubMsg.BufferLength); /* This is a hack to clear the padding between the ptr and longlong/double */ + + ptr = NdrPointerMarshall( &StubMsg, memsrc, formattypes ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled\n", msgpfx); + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + + if (0) + { + /* NdrPointerMemorySize crashes under Wine */ + size = NdrPointerMemorySize( &StubMsg, formattypes ); + ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) + ok(size == srcsize + 4, "%s: mem size %u\n", msgpfx, size); + else + ok(size == srcsize, "%s: mem size %u\n", msgpfx, size); + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 16; + size = NdrPointerMemorySize( &StubMsg, formattypes ); + ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) + ok(size == srcsize + 4 + 16, "%s: mem size %u\n", msgpfx, size); + else + ok(size == srcsize + 16, "%s: mem size %u\n", msgpfx, size); + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 1; + size = NdrPointerMemorySize( &StubMsg, formattypes ); + ok(size == StubMsg.MemorySize, "%s: mem size %u size %u\n", msgpfx, StubMsg.MemorySize, size); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) + ok(size == srcsize + 4 + (srcsize == 8 ? 8 : 4), "%s: mem size %u\n", msgpfx, size); + else + ok(size == srcsize + (srcsize == 8 ? 8 : 4), "%s: mem size %u\n", msgpfx, size); + } + + size = srcsize; + if(formattypes[1] & 0x10) size += 4; + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + mem_orig = mem = HeapAlloc(GetProcessHeap(), 0, size); + + if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) + *(void**)mem = NULL; + ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); + ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); + ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + + /* reset the buffer and call with must alloc */ + StubMsg.Buffer = StubMsg.BufferStart; + if(formattypes[1] & 0x10 /* FC_POINTER_DEREF */) + *(void**)mem = NULL; + ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 1 ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + /* doesn't allocate mem in this case */ +todo_wine { + ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); + } + ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); + +todo_wine { + ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); +} + my_alloc_called = 0; + if(formattypes[0] != 0x11 /* FC_RP */) + { + /* now pass the address of a NULL ptr */ + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart); + ok(!cmp(mem, memsrc, size), "%s: incorrectly unmarshaled\n", msgpfx); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); + ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + NdrPointerFree(&StubMsg, mem, formattypes); + + /* again pass address of NULL ptr, but pretend we're a server */ + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.IsClient = 0; + ptr = NdrPointerUnmarshall( &StubMsg, &mem, formattypes, 0 ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + if (formattypes[2] == 0xd /* FC_ENUM16 */) + ok(mem != StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem points to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart); + else + ok(mem == StubMsg.BufferStart + wiredatalen - srcsize, "%s: mem doesn't point to buffer %p %p\n", msgpfx, mem, StubMsg.BufferStart); + ok(!cmp(mem, memsrc, size), "%s: incorrecly unmarshaled\n", msgpfx); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p len %d\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart, wiredatalen); + ok(StubMsg.MemorySize == 0, "%s: memorysize %d\n", msgpfx, StubMsg.MemorySize); + if (formattypes[2] != 0xd /* FC_ENUM16 */) { + ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + } + } + HeapFree(GetProcessHeap(), 0, mem_orig); + HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); +} + +static int deref_cmp(const void *s1, const void *s2, size_t num) +{ + return memcmp(*(const void *const *)s1, *(const void *const *)s2, num); +} + + +static void test_simple_types(void) +{ + unsigned char wiredata[16]; + unsigned char ch; + unsigned char *ch_ptr; + unsigned short s; + unsigned int i; + unsigned long l; + ULONGLONG ll; + float f; + double d; + + static const unsigned char fmtstr_up_char[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x2, /* FC_CHAR */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_byte[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x1, /* FC_BYTE */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_small[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x3, /* FC_SMALL */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_usmall[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x4, /* FC_USMALL */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_rp_char[] = + { + 0x11, 0x8, /* FC_RP [simple_pointer] */ + 0x2, /* FC_CHAR */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_rpup_char[] = + { + 0x11, 0x14, /* FC_RP [alloced_on_stack] */ + NdrFcShort( 0x2 ), /* Offset= 2 (4) */ + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x2, /* FC_CHAR */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_rpup_char2[] = + { + 0x11, 0x04, /* FC_RP [alloced_on_stack] */ + NdrFcShort( 0x2 ), /* Offset= 2 (4) */ + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x2, /* FC_CHAR */ + 0x5c, /* FC_PAD */ + }; + + static const unsigned char fmtstr_up_wchar[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x5, /* FC_WCHAR */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_short[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x6, /* FC_SHORT */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_ushort[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x7, /* FC_USHORT */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_enum16[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0xd, /* FC_ENUM16 */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_long[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x8, /* FC_LONG */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_ulong[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x9, /* FC_ULONG */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_enum32[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0xe, /* FC_ENUM32 */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_errorstatus[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0x10, /* FC_ERROR_STATUS_T */ + 0x5c, /* FC_PAD */ + }; + + static const unsigned char fmtstr_up_longlong[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0xb, /* FC_HYPER */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_float[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0xa, /* FC_FLOAT */ + 0x5c, /* FC_PAD */ + }; + static const unsigned char fmtstr_up_double[] = + { + 0x12, 0x8, /* FC_UP [simple_pointer] */ + 0xc, /* FC_DOUBLE */ + 0x5c, /* FC_PAD */ + }; + + ch = 0xa5; + ch_ptr = &ch; + *(void**)wiredata = ch_ptr; + wiredata[sizeof(void*)] = ch; + + test_pointer_marshal(fmtstr_up_char, ch_ptr, 1, wiredata, 5, NULL, 0, "up_char"); + test_pointer_marshal(fmtstr_up_byte, ch_ptr, 1, wiredata, 5, NULL, 0, "up_byte"); + test_pointer_marshal(fmtstr_up_small, ch_ptr, 1, wiredata, 5, NULL, 0, "up_small"); + test_pointer_marshal(fmtstr_up_usmall, ch_ptr, 1, wiredata, 5, NULL, 0, "up_usmall"); + + test_pointer_marshal(fmtstr_rp_char, ch_ptr, 1, &ch, 1, NULL, 0, "rp_char"); + + test_pointer_marshal(fmtstr_rpup_char, &ch_ptr, 1, wiredata, 5, deref_cmp, 1, "rpup_char"); + test_pointer_marshal(fmtstr_rpup_char2, ch_ptr, 1, wiredata, 5, NULL, 0, "rpup_char2"); + + s = 0xa597; + *(void**)wiredata = &s; + *(unsigned short*)(wiredata + sizeof(void*)) = s; + + test_pointer_marshal(fmtstr_up_wchar, &s, 2, wiredata, 6, NULL, 0, "up_wchar"); + test_pointer_marshal(fmtstr_up_short, &s, 2, wiredata, 6, NULL, 0, "up_short"); + test_pointer_marshal(fmtstr_up_ushort, &s, 2, wiredata, 6, NULL, 0, "up_ushort"); + + i = 0x7fff; + *(void**)wiredata = &i; + *(unsigned short*)(wiredata + sizeof(void*)) = i; + test_pointer_marshal(fmtstr_up_enum16, &i, 2, wiredata, 6, NULL, 0, "up_enum16"); + + l = 0xcafebabe; + *(void**)wiredata = &l; + *(unsigned long*)(wiredata + sizeof(void*)) = l; + + test_pointer_marshal(fmtstr_up_long, &l, 4, wiredata, 8, NULL, 0, "up_long"); + test_pointer_marshal(fmtstr_up_ulong, &l, 4, wiredata, 8, NULL, 0, "up_ulong"); + test_pointer_marshal(fmtstr_up_enum32, &l, 4, wiredata, 8, NULL, 0, "up_emun32"); + test_pointer_marshal(fmtstr_up_errorstatus, &l, 4, wiredata, 8, NULL, 0, "up_errorstatus"); + + ll = ((ULONGLONG)0xcafebabe) << 32 | 0xdeadbeef; + *(void**)wiredata = ≪ + *(void**)(wiredata + sizeof(void*)) = NULL; + *(ULONGLONG*)(wiredata + 2 * sizeof(void*)) = ll; + test_pointer_marshal(fmtstr_up_longlong, &ll, 8, wiredata, 16, NULL, 0, "up_longlong"); + + f = 3.1415f; + *(void**)wiredata = &f; + *(float*)(wiredata + sizeof(void*)) = f; + test_pointer_marshal(fmtstr_up_float, &f, 4, wiredata, 8, NULL, 0, "up_float"); + + d = 3.1415; + *(void**)wiredata = &d; + *(void**)(wiredata + sizeof(void*)) = NULL; + *(double*)(wiredata + 2 * sizeof(void*)) = d; + test_pointer_marshal(fmtstr_up_double, &d, 8, wiredata, 16, NULL, 0, "up_double"); + +} + +static void test_simple_struct_marshal(const unsigned char *formattypes, + void *memsrc, + long srcsize, + const void *wiredata, + ULONG wiredatalen, + int(*cmp)(const void*,const void*,size_t), + long num_additional_allocs, + const char *msgpfx) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + DWORD size; + void *ptr; + unsigned char *mem, *mem_orig; + + my_alloc_called = my_free_called = 0; + if(!cmp) + cmp = memcmp; + + StubDesc = Object_StubDesc; + StubDesc.pFormatTypes = formattypes; + + NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0); + + StubMsg.BufferLength = 0; + NdrSimpleStructBufferSize( &StubMsg, (unsigned char *)memsrc, formattypes ); + ok(StubMsg.BufferLength >= wiredatalen, "%s: length %d\n", msgpfx, StubMsg.BufferLength); + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; + ptr = NdrSimpleStructMarshall( &StubMsg, (unsigned char*)memsrc, formattypes ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); + ok(!memcmp(StubMsg.BufferStart, wiredata, wiredatalen), "%s: incorrectly marshaled %08x %08x %08x\n", msgpfx, *(DWORD*)StubMsg.BufferStart,*((DWORD*)StubMsg.BufferStart+1),*((DWORD*)StubMsg.BufferStart+2)); + + if (0) + { + /* FIXME: Causes Wine to crash */ + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + size = NdrSimpleStructMemorySize( &StubMsg, formattypes ); + ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx); + ok(size == srcsize, "%s: mem size %u\n", msgpfx, size); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); + + StubMsg.Buffer = StubMsg.BufferStart; + size = NdrSimpleStructMemorySize( &StubMsg, formattypes ); +todo_wine { + ok(size == StubMsg.MemorySize, "%s: size != MemorySize\n", msgpfx); +} + ok(StubMsg.MemorySize == ((srcsize + 3) & ~3) + srcsize, "%s: mem size %u\n", msgpfx, size); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); + } + size = srcsize; + /*** Unmarshalling first with must_alloc false ***/ + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + mem_orig = mem = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, srcsize); + ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + ok(StubMsg.Buffer - StubMsg.BufferStart == wiredatalen, "%s: Buffer %p Start %p\n", msgpfx, StubMsg.Buffer, StubMsg.BufferStart); + ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); + ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); + ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx); + + /* if we're a server we still use the suppiled memory */ + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.IsClient = 0; + ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + ok(mem == mem_orig, "%s: mem has changed %p %p\n", msgpfx, mem, mem_orig); + ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); + ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx); + + /* ...unless we pass a NULL ptr, then the buffer is used. + Passing a NULL ptr while we're a client && !must_alloc + crashes on Windows, so we won't do that. */ + + mem = NULL; + StubMsg.IsClient = 0; + StubMsg.Buffer = StubMsg.BufferStart; + ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 0 ); + ok(ptr == NULL, "%s: ret %p\n", msgpfx, ptr); + ok(mem == StubMsg.BufferStart, "%s: mem not equal buffer\n", msgpfx); + ok(!cmp(mem, memsrc, srcsize), "%s: incorrectly unmarshaled\n", msgpfx); + ok(my_alloc_called == num_additional_allocs, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + ok(StubMsg.MemorySize == 0, "%s: memorysize touched in unmarshal\n", msgpfx); + + /*** now must_alloc is true ***/ + + /* with must_alloc set we always allocate new memory whether or not we're + a server and also when passing NULL */ + mem = mem_orig; + StubMsg.IsClient = 1; + StubMsg.Buffer = StubMsg.BufferStart; + ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig); + ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); + ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); + + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig); + ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); + ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); + + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.IsClient = 0; + StubMsg.ReuseBuffer = 1; + ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(mem != mem_orig, "mem not changed %p %p\n", mem, mem_orig); + ok(mem != StubMsg.BufferStart, "mem is buffer mem\n"); + ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); + ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); + + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.IsClient = 0; + StubMsg.ReuseBuffer = 1; + ptr = NdrSimpleStructUnmarshall( &StubMsg, &mem, formattypes, 1 ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(mem != StubMsg.BufferStart, "mem is buffer mem\n"); + ok(!cmp(mem, memsrc, srcsize), "incorrectly unmarshaled\n"); + ok(my_alloc_called == num_additional_allocs + 1, "%s: my_alloc got called %d times\n", msgpfx, my_alloc_called); + my_alloc_called = 0; + ok(StubMsg.MemorySize == 0, "memorysize touched in unmarshal\n"); + + HeapFree(GetProcessHeap(), 0, mem_orig); + HeapFree(GetProcessHeap(), 0, StubMsg.BufferStart); +} + +typedef struct +{ + long l1; + long *pl1; + char *pc1; +} ps1_t; + +static int ps1_cmp(const void *s1, const void *s2, size_t num) +{ + const ps1_t *p1, *p2; + + p1 = s1; + p2 = s2; + + if(p1->l1 != p2->l1) + return 1; + + if(p1->pl1 && p2->pl1) + { + if(*p1->pl1 != *p2->pl1) + return 1; + } + else if(p1->pl1 || p1->pl1) + return 1; + + if(p1->pc1 && p2->pc1) + { + if(*p1->pc1 != *p2->pc1) + return 1; + } + else if(p1->pc1 || p1->pc1) + return 1; + + return 0; +} + +static void test_simple_struct(void) +{ + unsigned char wiredata[28]; + unsigned long wiredatalen; + long l; + char c; + ps1_t ps1; + + static const unsigned char fmtstr_simple_struct[] = + { + 0x12, 0x0, /* FC_UP */ + NdrFcShort( 0x2 ), /* Offset=2 */ + 0x15, 0x3, /* FC_STRUCT [align 4] */ + NdrFcShort( 0x18 ), /* [size 24] */ + 0x6, /* FC_SHORT */ + 0x2, /* FC_CHAR */ + 0x38, /* FC_ALIGNM4 */ + 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ + 0x39, /* FC_ALIGNM8 */ + 0xb, /* FC_HYPER */ + 0x5b, /* FC_END */ + }; + struct { + short s; + char c; + long l1, l2; + LONGLONG ll; + } s1; + + static const unsigned char fmtstr_pointer_struct[] = + { + 0x12, 0x0, /* FC_UP */ + NdrFcShort( 0x2 ), /* Offset=2 */ + 0x16, 0x3, /* FC_PSTRUCT [align 4] */ + NdrFcShort( 0xc ), /* [size 12] */ + 0x4b, /* FC_PP */ + 0x5c, /* FC_PAD */ + 0x46, /* FC_NO_REPEAT */ + 0x5c, /* FC_PAD */ + NdrFcShort( 0x4 ), /* 4 */ + NdrFcShort( 0x4 ), /* 4 */ + 0x13, 0x8, /* FC_OP [simple_pointer] */ + 0x8, /* FC_LONG */ + 0x5c, /* FC_PAD */ + 0x46, /* FC_NO_REPEAT */ + 0x5c, /* FC_PAD */ + NdrFcShort( 0x8 ), /* 8 */ + NdrFcShort( 0x8 ), /* 8 */ + 0x13, 0x8, /* FC_OP [simple_pointer] */ + 0x2, /* FC_CHAR */ + 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ + 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ + 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ + + }; + + /* FC_STRUCT */ + s1.s = 0x1234; + s1.c = 0xa5; + s1.l1 = 0xdeadbeef; + s1.l2 = 0xcafebabe; + s1.ll = ((LONGLONG) 0xbadefeed << 32) | 0x2468ace0; + + wiredatalen = 24; + memcpy(wiredata, &s1, wiredatalen); + test_simple_struct_marshal(fmtstr_simple_struct + 4, &s1, 24, wiredata, 24, NULL, 0, "struct"); + + *(void**)wiredata = &s1; + memcpy(wiredata + 4, &s1, wiredatalen); + if (0) + { + /* one of the unmarshallings crashes Wine */ + test_pointer_marshal(fmtstr_simple_struct, &s1, 24, wiredata, 28, NULL, 0, "struct"); + } + + /* FC_PSTRUCT */ + ps1.l1 = 0xdeadbeef; + l = 0xcafebabe; + ps1.pl1 = &l; + c = 'a'; + ps1.pc1 = &c; + memcpy(wiredata + 4, &ps1, 12); + memcpy(wiredata + 16, &l, 4); + memcpy(wiredata + 20, &c, 1); + + test_simple_struct_marshal(fmtstr_pointer_struct + 4, &ps1, 17, wiredata + 4, 17, ps1_cmp, 2, "pointer_struct"); + *(void**)wiredata = &ps1; + if (0) + { + /* one of the unmarshallings crashes Wine */ + test_pointer_marshal(fmtstr_pointer_struct, &ps1, 17, wiredata, 21, ps1_cmp, 2, "pointer_struct"); + } +} + +static void test_fullpointer_xlat(void) +{ + PFULL_PTR_XLAT_TABLES pXlatTables; + ULONG RefId; + int ret; + void *Pointer; + + pXlatTables = NdrFullPointerXlatInit(2, XLAT_CLIENT); + + /* "marshaling" phase */ + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x1, "RefId should be 0x1 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, NULL, 0, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(RefId == 0, "RefId should be 0 instead of 0x%x\n", RefId); + + /* "unmarshaling" phase */ + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(Pointer == (void *)0xcafebabe, "Pointer should be 0xcafebabe instead of %p\n", Pointer); + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 0, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer); + + NdrFullPointerInsertRefId(pXlatTables, 0x4, (void *)0xdeadbabe); + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x4, 1, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(Pointer == (void *)0xdeadbabe, "Pointer should be (void *)0xdeadbabe instead of %p\n", Pointer); + + NdrFullPointerXlatFree(pXlatTables); + + pXlatTables = NdrFullPointerXlatInit(2, XLAT_SERVER); + + /* "unmarshaling" phase */ + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(Pointer == NULL, "Pointer should be NULL instead of %p\n", Pointer); + + NdrFullPointerInsertRefId(pXlatTables, 0x2, (void *)0xcafebabe); + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 0, &Pointer); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer); + + ret = NdrFullPointerQueryRefId(pXlatTables, 0x2, 1, &Pointer); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(Pointer == (void *)0xcafebabe, "Pointer should be (void *)0xcafebabe instead of %p\n", Pointer); + + /* "marshaling" phase */ + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebabe, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x2, "RefId should be 0x2 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); + + /* "freeing" phase */ + + ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebeef); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 0x20, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xcafebeef, 1, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(RefId == 0x3, "RefId should be 0x3 instead of 0x%x\n", RefId); + + ret = NdrFullPointerFree(pXlatTables, (void *)0xcafebabe); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + + ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 0x20, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); + + ret = NdrFullPointerQueryPointer(pXlatTables, (void *)0xdeadbeef, 1, &RefId); + ok(ret == 1, "ret should be 1 instead of 0x%x\n", ret); + ok(RefId == 0x4, "RefId should be 0x4 instead of 0x%x\n", RefId); + + ret = NdrFullPointerFree(pXlatTables, (void *)0xdeadbeef); + ok(ret == 0, "ret should be 0 instead of 0x%x\n", ret); + + NdrFullPointerXlatFree(pXlatTables); +} + +static void test_client_init(void) +{ + MIDL_STUB_MESSAGE stubMsg; + RPC_MESSAGE rpcMsg; + + memset(&rpcMsg, 0, sizeof(rpcMsg)); + memset(&stubMsg, 0xcc, sizeof(stubMsg)); + + NdrClientInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc, 1); + +#define TEST_ZERO(field, fmt) ok(stubMsg.field == 0, #field " should have been set to zero instead of " fmt "\n", stubMsg.field) +#define TEST_POINTER_UNSET(field) ok(stubMsg.field == (void *)0xcccccccc, #field " should have been unset instead of %p\n", stubMsg.field) +#define TEST_ULONG_UNSET(field) ok(stubMsg.field == 0xcccccccc, #field " should have been unset instead of 0x%x\n", stubMsg.field) +#define TEST_ULONG_PTR_UNSET(field) ok(stubMsg.field == 0xcccccccc, #field " should have been unset instead of 0x%lx\n", stubMsg.field) + + ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg); + TEST_POINTER_UNSET(Buffer); + TEST_ZERO(BufferStart, "%p"); + TEST_ZERO(BufferEnd, "%p"); + TEST_POINTER_UNSET(BufferMark); + TEST_ZERO(BufferLength, "%d"); + TEST_ULONG_UNSET(MemorySize); + TEST_POINTER_UNSET(Memory); + ok(stubMsg.IsClient == 1, "stubMsg.IsClient should have been 1 instead of %u\n", stubMsg.IsClient); + TEST_ZERO(ReuseBuffer, "%d"); + TEST_ZERO(pAllocAllNodesContext, "%p"); + TEST_ZERO(pPointerQueueState, "%p"); + TEST_ZERO(IgnoreEmbeddedPointers, "%d"); + TEST_ZERO(PointerBufferMark, "%p"); + TEST_ZERO(fBufferValid, "%d"); + TEST_ZERO(uFlags, "%d"); + /* FIXME: UniquePtrCount */ + TEST_ULONG_PTR_UNSET(MaxCount); + TEST_ULONG_UNSET(Offset); + TEST_ULONG_UNSET(ActualCount); + ok(stubMsg.pfnAllocate == my_alloc, "stubMsg.pfnAllocate should have been %p instead of %p\n", my_alloc, stubMsg.pfnAllocate); + ok(stubMsg.pfnFree == my_free, "stubMsg.pfnFree should have been %p instead of %p\n", my_free, stubMsg.pfnFree); + TEST_ZERO(StackTop, "%p"); + TEST_POINTER_UNSET(pPresentedType); + TEST_POINTER_UNSET(pTransmitType); + TEST_POINTER_UNSET(SavedHandle); + ok(stubMsg.StubDesc == &Object_StubDesc, "stubMsg.StubDesc should have been %p instead of %p\n", &Object_StubDesc, stubMsg.StubDesc); + TEST_POINTER_UNSET(FullPtrXlatTables); + TEST_ZERO(FullPtrRefId, "%d"); + TEST_ZERO(PointerLength, "%d"); + TEST_ZERO(fInDontFree, "%d"); + TEST_ZERO(fDontCallFreeInst, "%d"); + TEST_ZERO(fInOnlyParam, "%d"); + TEST_ZERO(fHasReturn, "%d"); + TEST_ZERO(fHasExtensions, "%d"); + TEST_ZERO(fHasNewCorrDesc, "%d"); + TEST_ZERO(fUnused, "%d"); + ok(stubMsg.fUnused2 == 0xffffcccc, "stubMsg.fUnused2 should have been 0xcccc instead of 0x%x\n", stubMsg.fUnused2); + ok(stubMsg.dwDestContext == MSHCTX_DIFFERENTMACHINE, "stubMsg.dwDestContext should have been MSHCTX_DIFFERENTMACHINE instead of %d\n", stubMsg.dwDestContext); + TEST_ZERO(pvDestContext, "%p"); + TEST_POINTER_UNSET(SavedContextHandles); + TEST_ULONG_UNSET(ParamNumber); + TEST_ZERO(pRpcChannelBuffer, "%p"); + TEST_ZERO(pArrayInfo, "%p"); + TEST_POINTER_UNSET(SizePtrCountArray); + TEST_POINTER_UNSET(SizePtrOffsetArray); + TEST_POINTER_UNSET(SizePtrLengthArray); + TEST_POINTER_UNSET(pArgQueue); + TEST_ZERO(dwStubPhase, "%d"); + /* FIXME: where does this value come from? */ + trace("LowStackMark is %p\n", stubMsg.LowStackMark); + TEST_ZERO(pAsyncMsg, "%p"); + TEST_ZERO(pCorrInfo, "%p"); + TEST_ZERO(pCorrMemory, "%p"); + TEST_ZERO(pMemoryList, "%p"); + TEST_POINTER_UNSET(pCSInfo); + TEST_POINTER_UNSET(ConformanceMark); + TEST_POINTER_UNSET(VarianceMark); + ok(stubMsg.Unused == 0xcccccccc, "Unused should have be unset instead of 0x%lx\n", stubMsg.Unused); + TEST_POINTER_UNSET(pContext); + TEST_POINTER_UNSET(ContextHandleHash); + TEST_POINTER_UNSET(pUserMarshalList); + TEST_ULONG_PTR_UNSET(Reserved51_3); + TEST_ULONG_PTR_UNSET(Reserved51_4); + TEST_ULONG_PTR_UNSET(Reserved51_5); +#undef TEST_ULONG_UNSET +#undef TEST_POINTER_UNSET +#undef TEST_ZERO + +} + +static void test_server_init(void) +{ + MIDL_STUB_MESSAGE stubMsg; + RPC_MESSAGE rpcMsg; + unsigned char *ret; + unsigned char buffer[256]; + + memset(&rpcMsg, 0, sizeof(rpcMsg)); + rpcMsg.Buffer = buffer; + rpcMsg.BufferLength = sizeof(buffer); + rpcMsg.RpcFlags = RPC_BUFFER_COMPLETE; + + memset(&stubMsg, 0xcc, sizeof(stubMsg)); + + ret = NdrServerInitializeNew(&rpcMsg, &stubMsg, &Object_StubDesc); + ok(ret == NULL, "NdrServerInitializeNew should have returned NULL instead of %p\n", ret); + +#define TEST_ZERO(field, fmt) ok(stubMsg.field == 0, #field " should have been set to zero instead of " fmt "\n", stubMsg.field) +#define TEST_POINTER_UNSET(field) ok(stubMsg.field == (void *)0xcccccccc, #field " should have been unset instead of %p\n", stubMsg.field) +#define TEST_ULONG_UNSET(field) ok(stubMsg.field == 0xcccccccc, #field " should have been unset instead of 0x%x\n", stubMsg.field) +#define TEST_ULONG_PTR_UNSET(field) ok(stubMsg.field == 0xcccccccc, #field " should have been unset instead of 0x%lx\n", stubMsg.field) + + ok(stubMsg.RpcMsg == &rpcMsg, "stubMsg.RpcMsg should have been %p instead of %p\n", &rpcMsg, stubMsg.RpcMsg); + ok(stubMsg.Buffer == buffer, "stubMsg.Buffer should have been %p instead of %p\n", buffer, stubMsg.Buffer); + ok(stubMsg.BufferStart == buffer, "stubMsg.BufferStart should have been %p instead of %p\n", buffer, stubMsg.BufferStart); + ok(stubMsg.BufferEnd == buffer + sizeof(buffer), "stubMsg.BufferEnd should have been %p instead of %p\n", buffer + sizeof(buffer), stubMsg.BufferEnd); + TEST_POINTER_UNSET(BufferMark); +todo_wine + TEST_ZERO(BufferLength, "%d"); + TEST_ULONG_UNSET(MemorySize); + TEST_POINTER_UNSET(Memory); + ok(stubMsg.IsClient == 0, "stubMsg.IsClient should have been 0 instead of %u\n", stubMsg.IsClient); + TEST_ZERO(ReuseBuffer, "%d"); + TEST_ZERO(pAllocAllNodesContext, "%p"); + TEST_ZERO(pPointerQueueState, "%p"); + TEST_ZERO(IgnoreEmbeddedPointers, "%d"); + TEST_ZERO(PointerBufferMark, "%p"); + ok(stubMsg.fBufferValid == 0xcc, "fBufferValid should have been unset instead of 0x%x\n", stubMsg.fBufferValid); + TEST_ZERO(uFlags, "%d"); + /* FIXME: UniquePtrCount */ + TEST_ULONG_PTR_UNSET(MaxCount); + TEST_ULONG_UNSET(Offset); + TEST_ULONG_UNSET(ActualCount); + ok(stubMsg.pfnAllocate == my_alloc, "stubMsg.pfnAllocate should have been %p instead of %p\n", my_alloc, stubMsg.pfnAllocate); + ok(stubMsg.pfnFree == my_free, "stubMsg.pfnFree should have been %p instead of %p\n", my_free, stubMsg.pfnFree); + TEST_ZERO(StackTop, "%p"); + TEST_POINTER_UNSET(pPresentedType); + TEST_POINTER_UNSET(pTransmitType); + TEST_POINTER_UNSET(SavedHandle); + ok(stubMsg.StubDesc == &Object_StubDesc, "stubMsg.StubDesc should have been %p instead of %p\n", &Object_StubDesc, stubMsg.StubDesc); + TEST_ZERO(FullPtrXlatTables, "%p"); + TEST_ZERO(FullPtrRefId, "%d"); + TEST_ZERO(PointerLength, "%d"); + TEST_ZERO(fInDontFree, "%d"); + TEST_ZERO(fDontCallFreeInst, "%d"); + TEST_ZERO(fInOnlyParam, "%d"); + TEST_ZERO(fHasReturn, "%d"); + TEST_ZERO(fHasExtensions, "%d"); + TEST_ZERO(fHasNewCorrDesc, "%d"); + TEST_ZERO(fUnused, "%d"); + ok(stubMsg.fUnused2 == 0xffffcccc, "stubMsg.fUnused2 should have been 0xcccc instead of 0x%x\n", stubMsg.fUnused2); + ok(stubMsg.dwDestContext == MSHCTX_DIFFERENTMACHINE, "stubMsg.dwDestContext should have been MSHCTX_DIFFERENTMACHINE instead of %d\n", stubMsg.dwDestContext); + TEST_ZERO(pvDestContext, "%p"); + TEST_POINTER_UNSET(SavedContextHandles); + TEST_ULONG_UNSET(ParamNumber); + TEST_ZERO(pRpcChannelBuffer, "%p"); + TEST_ZERO(pArrayInfo, "%p"); + TEST_POINTER_UNSET(SizePtrCountArray); + TEST_POINTER_UNSET(SizePtrOffsetArray); + TEST_POINTER_UNSET(SizePtrLengthArray); + TEST_POINTER_UNSET(pArgQueue); + TEST_ZERO(dwStubPhase, "%d"); + /* FIXME: where does this value come from? */ + trace("LowStackMark is %p\n", stubMsg.LowStackMark); + TEST_ZERO(pAsyncMsg, "%p"); + TEST_ZERO(pCorrInfo, "%p"); + TEST_ZERO(pCorrMemory, "%p"); + TEST_ZERO(pMemoryList, "%p"); + TEST_POINTER_UNSET(pCSInfo); + TEST_POINTER_UNSET(ConformanceMark); + TEST_POINTER_UNSET(VarianceMark); + ok(stubMsg.Unused == 0xcccccccc, "Unused should have be unset instead of 0x%lx\n", stubMsg.Unused); + TEST_POINTER_UNSET(pContext); + TEST_POINTER_UNSET(ContextHandleHash); + TEST_POINTER_UNSET(pUserMarshalList); + TEST_ULONG_PTR_UNSET(Reserved51_3); + TEST_ULONG_PTR_UNSET(Reserved51_4); + TEST_ULONG_PTR_UNSET(Reserved51_5); +#undef TEST_ULONG_UNSET +#undef TEST_POINTER_UNSET +#undef TEST_ZERO + +} + +static void test_ndr_allocate(void) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + void *p1, *p2; + struct tag_mem_list_v1_t + { + DWORD magic; + void *ptr; + struct tag_mem_list_v1_t *next; + } *mem_list_v1; + struct tag_mem_list_v2_t + { + DWORD magic; + DWORD size; + DWORD unknown; + struct tag_mem_list_v2_t *next; + } *mem_list_v2; + const DWORD magic_MEML = 'M' << 24 | 'E' << 16 | 'M' << 8 | 'L'; + + StubDesc = Object_StubDesc; + NdrClientInitializeNew(&RpcMessage, &StubMsg, &StubDesc, 0); + + ok(StubMsg.pMemoryList == NULL, "memlist %p\n", StubMsg.pMemoryList); + my_alloc_called = my_free_called = 0; + p1 = NdrAllocate(&StubMsg, 10); + p2 = NdrAllocate(&StubMsg, 24); + ok(my_alloc_called == 2, "alloc called %d\n", my_alloc_called); + ok(StubMsg.pMemoryList != NULL, "StubMsg.pMemoryList NULL\n"); + if(StubMsg.pMemoryList) + { + mem_list_v2 = StubMsg.pMemoryList; + if (mem_list_v2->size == 24) + { + trace("v2 mem list format\n"); + ok((char *)mem_list_v2 == (char *)p2 + 24, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p2 + 24, mem_list_v2); + ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic); + ok(mem_list_v2->size == 24, "wrong size for p2 %d\n", mem_list_v2->size); + ok(mem_list_v2->unknown == 0, "wrong unknown for p2 0x%x\n", mem_list_v2->unknown); + ok(mem_list_v2->next != NULL, "next NULL\n"); + mem_list_v2 = mem_list_v2->next; + if(mem_list_v2) + { + ok((char *)mem_list_v2 == (char *)p1 + 16, "expected mem_list_v2 pointer %p, but got %p\n", (char *)p1 + 16, mem_list_v2); + ok(mem_list_v2->magic == magic_MEML, "magic %08x\n", mem_list_v2->magic); + ok(mem_list_v2->size == 16, "wrong size for p1 %d\n", mem_list_v2->size); + ok(mem_list_v2->unknown == 0, "wrong unknown for p1 0x%x\n", mem_list_v2->unknown); + ok(mem_list_v2->next == NULL, "next %p\n", mem_list_v2->next); + } + } + else + { + trace("v1 mem list format\n"); + mem_list_v1 = StubMsg.pMemoryList; + ok(mem_list_v1->magic == magic_MEML, "magic %08x\n", mem_list_v1->magic); + ok(mem_list_v1->ptr == p2, "ptr != p2\n"); + ok(mem_list_v1->next != NULL, "next NULL\n"); + mem_list_v1 = mem_list_v1->next; + if(mem_list_v1) + { + ok(mem_list_v1->magic == magic_MEML, "magic %08x\n", mem_list_v1->magic); + ok(mem_list_v1->ptr == p1, "ptr != p1\n"); + ok(mem_list_v1->next == NULL, "next %p\n", mem_list_v1->next); + } + } + } + /* NdrFree isn't exported so we can't test free'ing */ +} + +static void test_conformant_array(void) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + void *ptr; + unsigned char *mem, *mem_orig; + unsigned char memsrc[20]; + + static const unsigned char fmtstr_conf_array[] = + { + 0x1b, /* FC_CARRAY */ + 0x0, /* align */ + NdrFcShort( 0x1 ), /* elem size */ + 0x40, /* Corr desc: const */ + 0x0, + NdrFcShort(0x10), /* const = 0x10 */ + 0x1, /* FC_BYTE */ + 0x5b /* FC_END */ + }; + + StubDesc = Object_StubDesc; + StubDesc.pFormatTypes = fmtstr_conf_array; + + NdrClientInitializeNew( + &RpcMessage, + &StubMsg, + &StubDesc, + 0); + + StubMsg.BufferLength = 0; + NdrConformantArrayBufferSize( &StubMsg, + memsrc, + fmtstr_conf_array ); + ok(StubMsg.BufferLength >= 20, "length %d\n", StubMsg.BufferLength); + + /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; + + ptr = NdrConformantArrayMarshall( &StubMsg, memsrc, fmtstr_conf_array ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(StubMsg.Buffer - StubMsg.BufferStart == 20, "Buffer %p Start %p len %d\n", StubMsg.Buffer, StubMsg.BufferStart, 20); + ok(!memcmp(StubMsg.BufferStart + 4, memsrc, 16), "incorrectly marshaled\n"); + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + mem = NULL; + + /* Client */ + my_alloc_called = 0; + /* passing mem == NULL with must_alloc == 0 crashes under Windows */ + NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); + ok(mem != NULL, "mem not alloced\n"); + ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); + ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + mem_orig = mem; + NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0); + ok(mem == mem_orig, "mem alloced\n"); + ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); + ok(mem != mem_orig, "mem not alloced\n"); + ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); + ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); + + my_free_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrConformantArrayFree( &StubMsg, mem, fmtstr_conf_array ); + ok(my_free_called == 0, "free called %d\n", my_free_called); + StubMsg.pfnFree(mem); + + /* Server */ + my_alloc_called = 0; + StubMsg.IsClient = 0; + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0); + ok(mem == StubMsg.BufferStart + 4, "mem not pointing at buffer\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + my_alloc_called = 0; + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); + ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); + ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); + StubMsg.pfnFree(mem); + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 0); + ok(mem == mem_orig, "mem alloced\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrConformantArrayUnmarshall( &StubMsg, &mem, fmtstr_conf_array, 1); + ok(mem != StubMsg.BufferStart + 4, "mem pointing at buffer\n"); + ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); + StubMsg.pfnFree(mem); + StubMsg.pfnFree(mem_orig); + + HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); +} + +static void test_conformant_string(void) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + void *ptr; + unsigned char *mem, *mem_orig; + char memsrc[] = "This is a test string"; + + static const unsigned char fmtstr_conf_str[] = + { + 0x11, 0x8, /* FC_RP [simple_pointer] */ + 0x22, /* FC_C_CSTRING */ + 0x5c, /* FC_PAD */ + }; + + StubDesc = Object_StubDesc; + StubDesc.pFormatTypes = fmtstr_conf_str; + + NdrClientInitializeNew( + &RpcMessage, + &StubMsg, + &StubDesc, + 0); + + StubMsg.BufferLength = 0; + NdrPointerBufferSize( &StubMsg, + (unsigned char *)memsrc, + fmtstr_conf_str ); + ok(StubMsg.BufferLength >= sizeof(memsrc) + 12, "length %d\n", StubMsg.BufferLength); + + /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; + + ptr = NdrPointerMarshall( &StubMsg, (unsigned char *)memsrc, fmtstr_conf_str ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(StubMsg.Buffer - StubMsg.BufferStart == sizeof(memsrc) + 12, "Buffer %p Start %p len %d\n", + StubMsg.Buffer, StubMsg.BufferStart, StubMsg.Buffer - StubMsg.BufferStart); + ok(!memcmp(StubMsg.BufferStart + 12, memsrc, sizeof(memsrc)), "incorrectly marshaled\n"); + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + mem = NULL; + + /* Client */ + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); + NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0); + ok(mem == mem_orig, "mem not alloced\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1); +todo_wine { + ok(mem == mem_orig, "mem not alloced\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); +} + + my_free_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerFree( &StubMsg, mem, fmtstr_conf_str ); + ok(my_free_called == 1, "free called %d\n", my_free_called); + + mem = my_alloc(10); + my_free_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerFree( &StubMsg, mem, fmtstr_conf_str ); + ok(my_free_called == 1, "free called %d\n", my_free_called); + + /* Server */ + my_alloc_called = 0; + StubMsg.IsClient = 0; + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0); + ok(mem == StubMsg.BufferStart + 12, "mem not pointing at buffer\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1); +todo_wine { + ok(mem == StubMsg.BufferStart + 12, "mem not pointing at buffer\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); +} + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 0); + ok(mem == StubMsg.BufferStart + 12, "mem not pointing at buffer\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerUnmarshall( &StubMsg, &mem, fmtstr_conf_str, 1); +todo_wine { + ok(mem == StubMsg.BufferStart + 12, "mem not pointing at buffer\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); +} + + mem = my_alloc(10); + my_free_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrPointerFree( &StubMsg, mem, fmtstr_conf_str ); + ok(my_free_called == 1, "free called %d\n", my_free_called); + + HeapFree(GetProcessHeap(), 0, mem_orig); + HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); +} + +static void test_nonconformant_string(void) +{ + RPC_MESSAGE RpcMessage; + MIDL_STUB_MESSAGE StubMsg; + MIDL_STUB_DESC StubDesc; + void *ptr; + unsigned char *mem, *mem_orig; + unsigned char memsrc[10] = "This is"; + unsigned char memsrc2[10] = "This is a"; + + static const unsigned char fmtstr_nonconf_str[] = + { + 0x26, /* FC_CSTRING */ + 0x5c, /* FC_PAD */ + NdrFcShort( 0xa ), /* 10 */ + }; + + StubDesc = Object_StubDesc; + StubDesc.pFormatTypes = fmtstr_nonconf_str; + + /* length < size */ + NdrClientInitializeNew( + &RpcMessage, + &StubMsg, + &StubDesc, + 0); + + StubMsg.BufferLength = 0; + + NdrNonConformantStringBufferSize( &StubMsg, + (unsigned char *)memsrc, + fmtstr_nonconf_str ); + ok(StubMsg.BufferLength >= strlen((char *)memsrc) + 1 + 8, "length %d\n", StubMsg.BufferLength); + + /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; + + ptr = NdrNonConformantStringMarshall( &StubMsg, (unsigned char *)memsrc, fmtstr_nonconf_str ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(StubMsg.Buffer - StubMsg.BufferStart == strlen((char *)memsrc) + 1 + 8, "Buffer %p Start %p len %d\n", + StubMsg.Buffer, StubMsg.BufferStart, StubMsg.Buffer - StubMsg.BufferStart); + ok(!memcmp(StubMsg.BufferStart + 8, memsrc, strlen((char *)memsrc) + 1), "incorrectly marshaled\n"); + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + mem = NULL; + + /* Client */ + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); + ok(mem == mem_orig, "mem alloced\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); + todo_wine + ok(mem == mem_orig, "mem alloced\n"); + todo_wine + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + /* Server */ + my_alloc_called = 0; + StubMsg.IsClient = 0; + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); + ok(mem != mem_orig, "mem not alloced\n"); + ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n"); + ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); + NdrOleFree(mem); + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); + ok(mem == mem_orig, "mem alloced\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); + todo_wine + ok(mem == mem_orig, "mem alloced\n"); + todo_wine + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + HeapFree(GetProcessHeap(), 0, mem_orig); + HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); + + /* length = size */ + NdrClientInitializeNew( + &RpcMessage, + &StubMsg, + &StubDesc, + 0); + + StubMsg.BufferLength = 0; + + NdrNonConformantStringBufferSize( &StubMsg, + (unsigned char *)memsrc2, + fmtstr_nonconf_str ); + ok(StubMsg.BufferLength >= strlen((char *)memsrc2) + 1 + 8, "length %d\n", StubMsg.BufferLength); + + /*NdrGetBuffer(&_StubMsg, _StubMsg.BufferLength, NULL);*/ + StubMsg.RpcMsg->Buffer = StubMsg.BufferStart = StubMsg.Buffer = HeapAlloc(GetProcessHeap(), 0, StubMsg.BufferLength); + StubMsg.BufferEnd = StubMsg.BufferStart + StubMsg.BufferLength; + + ptr = NdrNonConformantStringMarshall( &StubMsg, (unsigned char *)memsrc2, fmtstr_nonconf_str ); + ok(ptr == NULL, "ret %p\n", ptr); + ok(StubMsg.Buffer - StubMsg.BufferStart == strlen((char *)memsrc2) + 1 + 8, "Buffer %p Start %p len %d\n", + StubMsg.Buffer, StubMsg.BufferStart, StubMsg.Buffer - StubMsg.BufferStart); + ok(!memcmp(StubMsg.BufferStart + 8, memsrc2, strlen((char *)memsrc2) + 1), "incorrectly marshaled\n"); + + StubMsg.Buffer = StubMsg.BufferStart; + StubMsg.MemorySize = 0; + mem = NULL; + + /* Client */ + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + mem = mem_orig = HeapAlloc(GetProcessHeap(), 0, sizeof(memsrc)); + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); + ok(mem == mem_orig, "mem alloced\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); + todo_wine + ok(mem == mem_orig, "mem alloced\n"); + todo_wine + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + /* Server */ + my_alloc_called = 0; + StubMsg.IsClient = 0; + mem = NULL; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); + ok(mem != mem_orig, "mem not alloced\n"); + ok(mem != StubMsg.BufferStart + 8, "mem pointing at buffer\n"); + ok(my_alloc_called == 1, "alloc called %d\n", my_alloc_called); + NdrOleFree(mem); + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 0); + ok(mem == mem_orig, "mem alloced\n"); + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + my_alloc_called = 0; + mem = mem_orig; + StubMsg.Buffer = StubMsg.BufferStart; + NdrNonConformantStringUnmarshall( &StubMsg, &mem, fmtstr_nonconf_str, 1); + todo_wine + ok(mem == mem_orig, "mem alloced\n"); + todo_wine + ok(my_alloc_called == 0, "alloc called %d\n", my_alloc_called); + + HeapFree(GetProcessHeap(), 0, mem_orig); + HeapFree(GetProcessHeap(), 0, StubMsg.RpcMsg->Buffer); +} + +START_TEST( ndr_marshall ) +{ + test_ndr_simple_type(); + test_simple_types(); + test_simple_struct(); + test_fullpointer_xlat(); + test_client_init(); + test_server_init(); + test_ndr_allocate(); + test_conformant_array(); + test_conformant_string(); + test_nonconformant_string(); +} diff --git a/rostests/winetests/rpcrt4/rpc.c b/rostests/winetests/rpcrt4/rpc.c new file mode 100644 index 00000000000..a72037012be --- /dev/null +++ b/rostests/winetests/rpcrt4/rpc.c @@ -0,0 +1,385 @@ +/* + * Unit test suite for rpc functions + * + * Copyright 2002 Greg Turner + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "wine/test.h" +#include +#include +#include +#include + +#include "rpc.h" +#include "rpcdce.h" + +typedef unsigned int unsigned32; +typedef struct twr_t + { + unsigned32 tower_length; + /* [size_is] */ byte tower_octet_string[ 1 ]; + } twr_t; + +RPC_STATUS WINAPI TowerExplode(const twr_t *tower, RPC_SYNTAX_IDENTIFIER *object, RPC_SYNTAX_IDENTIFIER *syntax, char **protseq, char **endpoint, char **address); +RPC_STATUS WINAPI TowerConstruct(const RPC_SYNTAX_IDENTIFIER *object, const RPC_SYNTAX_IDENTIFIER *syntax, const char *protseq, const char *endpoint, const char *address, twr_t **tower); + +static UUID Uuid_Table[10] = { + { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, /* 0 (null) */ + { 0xdeadbeef, 0xdead, 0xbeef, {0x10, 0x21, 0x35, 0x56, 0x89, 0xa0, 0xf4, 0x8a} }, /* 1 */ + { 0xabadfeed, 0x49ff, 0xbead, {0x8a, 0xf4, 0xa0, 0x89, 0x56, 0x35, 0x21, 0x10} }, /* 2 */ + { 0x93da375c, 0x1324, 0x1355, {0x87, 0xff, 0x49, 0x44, 0x34, 0x44, 0x22, 0x19} }, /* 3 */ + { 0xdeadbeef, 0xdead, 0xbeef, {0x10, 0x21, 0x35, 0x56, 0x89, 0xa0, 0xf4, 0x8b} }, /* 4 (~1) */ + { 0x9badfeed, 0x49ff, 0xbead, {0x8a, 0xf4, 0xa0, 0x89, 0x56, 0x35, 0x21, 0x10} }, /* 5 (~2) */ + { 0x00000000, 0x0001, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, /* 6 (~0) */ + { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01} }, /* 7 (~0) */ + { 0x12312312, 0x1231, 0x1231, {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xff} }, /* 8 */ + { 0x11111111, 0x1111, 0x1111, {0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11} } /* 9 */ +}; + +/* index of "10" means "NULL" */ +static BOOL Uuid_Comparison_Grid[11][11] = { + { TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE }, + { FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE }, + { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE }, + { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE }, + { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE }, + { FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE }, + { TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE } +}; + +static void UuidConversionAndComparison(void) { + CHAR strx[100], x; + LPSTR str = strx; + WCHAR wstrx[100], wx; + LPWSTR wstr = wstrx; + + UUID Uuid1, Uuid2, *PUuid1, *PUuid2; + RPC_STATUS rslt; + + int i1,i2; + + /* Uuid Equality */ + for (i1 = 0; i1 < 11; i1++) + for (i2 = 0; i2 < 11; i2++) { + if (i1 < 10) { + Uuid1 = Uuid_Table[i1]; + PUuid1 = &Uuid1; + } else { + PUuid1 = NULL; + } + if (i2 < 10) { + Uuid2 = Uuid_Table[i2]; + PUuid2 = &Uuid2; + } else { + PUuid2 = NULL; + } + ok( (UuidEqual(PUuid1, PUuid2, &rslt) == Uuid_Comparison_Grid[i1][i2]), "UUID Equality\n" ); + } + + /* Uuid to String to Uuid (char) */ + for (i1 = 0; i1 < 10; i1++) { + Uuid1 = Uuid_Table[i1]; + ok( (UuidToStringA(&Uuid1, (unsigned char**)&str) == RPC_S_OK), "Simple UUID->String copy\n" ); + ok( (UuidFromStringA((unsigned char*)str, &Uuid2) == RPC_S_OK), "Simple String->UUID copy from generated UUID String\n" ); + ok( UuidEqual(&Uuid1, &Uuid2, &rslt), "Uuid -> String -> Uuid transform\n" ); + /* invalid uuid tests -- size of valid UUID string=36 */ + for (i2 = 0; i2 < 36; i2++) { + x = str[i2]; + str[i2] = 'g'; /* whatever, but "g" is a good boundary condition */ + ok( (UuidFromStringA((unsigned char*)str, &Uuid1) == RPC_S_INVALID_STRING_UUID), "Invalid UUID String\n" ); + str[i2] = x; /* change it back so remaining tests are interesting. */ + } + } + + /* Uuid to String to Uuid (wchar) */ + for (i1 = 0; i1 < 10; i1++) { + Uuid1 = Uuid_Table[i1]; + rslt=UuidToStringW(&Uuid1, &wstr); + if (rslt==RPC_S_CANNOT_SUPPORT) { + /* Must be Win9x (no Unicode support), skip the tests */ + break; + } + ok( (rslt == RPC_S_OK), "Simple UUID->WString copy\n" ); + ok( (UuidFromStringW(wstr, &Uuid2) == RPC_S_OK), "Simple WString->UUID copy from generated UUID String\n" ); + ok( UuidEqual(&Uuid1, &Uuid2, &rslt), "Uuid -> WString -> Uuid transform\n" ); + /* invalid uuid tests -- size of valid UUID string=36 */ + for (i2 = 0; i2 < 36; i2++) { + wx = wstr[i2]; + wstr[i2] = 'g'; /* whatever, but "g" is a good boundary condition */ + ok( (UuidFromStringW(wstr, &Uuid1) == RPC_S_INVALID_STRING_UUID), "Invalid UUID WString\n" ); + wstr[i2] = wx; /* change it back so remaining tests are interesting. */ + } + } +} + +static void TestDceErrorInqText (void) +{ + char bufferInvalid [1024]; + char buffer [1024]; /* The required size is not documented but would + * appear to be 256. + */ + DWORD dwCount; + + dwCount = FormatMessageA (FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, RPC_S_NOT_RPC_ERROR, 0, bufferInvalid, + sizeof(bufferInvalid)/sizeof(bufferInvalid[0]), NULL); + + /* A random sample of DceErrorInqText */ + /* 0 is success */ + ok ((DceErrorInqTextA (0, (unsigned char*)buffer) == RPC_S_OK), + "DceErrorInqTextA(0...)\n"); + /* A real RPC_S error */ + ok ((DceErrorInqTextA (RPC_S_INVALID_STRING_UUID, (unsigned char*)buffer) == RPC_S_OK), + "DceErrorInqTextA(valid...)\n"); + + if (dwCount) + { + /* A message for which FormatMessage should fail + * which should return RPC_S_OK and the + * fixed "not valid" message + */ + ok ((DceErrorInqTextA (35, (unsigned char*)buffer) == RPC_S_OK && + strcmp (buffer, bufferInvalid) == 0), + "DceErrorInqTextA(unformattable...)\n"); + /* One for which FormatMessage should succeed but + * DceErrorInqText should "fail" + * 3814 is generally quite a long message + */ + ok ((DceErrorInqTextA (3814, (unsigned char*)buffer) == RPC_S_OK && + strcmp (buffer, bufferInvalid) == 0), + "DceErrorInqTextA(deviation...)\n"); + } + else + ok (0, "Cannot set up for DceErrorInqText\n"); +} + +static RPC_DISPATCH_FUNCTION IFoo_table[] = +{ + 0 +}; + +static RPC_DISPATCH_TABLE IFoo_v0_0_DispatchTable = +{ + 0, + IFoo_table +}; + +static const RPC_SERVER_INTERFACE IFoo___RpcServerInterface = +{ + sizeof(RPC_SERVER_INTERFACE), + {{0x00000000,0x0000,0x0000,{0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x34}},{0,0}}, + {{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}}, + &IFoo_v0_0_DispatchTable, + 0, + 0, + 0, + 0, + 0, +}; + +static RPC_IF_HANDLE IFoo_v0_0_s_ifspec = (RPC_IF_HANDLE)& IFoo___RpcServerInterface; + +static void test_rpc_ncacn_ip_tcp(void) +{ + RPC_STATUS status; + unsigned char *binding; + handle_t IFoo_IfHandle; + static unsigned char foo[] = "foo"; + static unsigned char ncacn_ip_tcp[] = "ncacn_ip_tcp"; + static unsigned char address[] = "127.0.0.1"; + static unsigned char endpoint[] = "4114"; + + status = RpcNetworkIsProtseqValid(foo); + ok(status == RPC_S_INVALID_RPC_PROTSEQ, "return wrong\n"); + + status = RpcNetworkIsProtseqValid(ncacn_ip_tcp); + ok(status == RPC_S_OK, "return wrong\n"); + + status = RpcMgmtStopServerListening(NULL); +todo_wine { + ok(status == RPC_S_NOT_LISTENING, + "wrong RpcMgmtStopServerListening error (%lu)\n", status); +} + + status = RpcMgmtWaitServerListen(); + ok(status == RPC_S_NOT_LISTENING, + "wrong RpcMgmtWaitServerListen error status (%lu)\n", status); + + status = RpcServerListen(1, 20, FALSE); + ok(status == RPC_S_NO_PROTSEQS_REGISTERED, + "wrong RpcServerListen error (%lu)\n", status); + + status = RpcServerUseProtseqEp(ncacn_ip_tcp, 20, endpoint, NULL); + ok(status == RPC_S_OK, "RpcServerUseProtseqEp failed (%lu)\n", status); + + status = RpcServerRegisterIf(IFoo_v0_0_s_ifspec, NULL, NULL); + ok(status == RPC_S_OK, "RpcServerRegisterIf failed (%lu)\n", status); + + status = RpcServerListen(1, 20, TRUE); +todo_wine { + ok(status == RPC_S_OK, "RpcServerListen failed (%lu)\n", status); +} + + status = RpcServerListen(1, 20, TRUE); +todo_wine { + ok(status == RPC_S_ALREADY_LISTENING, + "wrong RpcServerListen error (%lu)\n", status); +} + + status = RpcStringBindingCompose(NULL, ncacn_ip_tcp, address, + endpoint, NULL, &binding); + ok(status == RPC_S_OK, "RpcStringBindingCompose failed (%lu)\n", status); + + status = RpcBindingFromStringBinding(binding, &IFoo_IfHandle); + ok(status == RPC_S_OK, "RpcBindingFromStringBinding failed (%lu)\n", + status); + + status = RpcMgmtStopServerListening(NULL); + ok(status == RPC_S_OK, "RpcMgmtStopServerListening failed (%lu)\n", + status); + + status = RpcMgmtStopServerListening(NULL); + ok(status == RPC_S_OK, "RpcMgmtStopServerListening failed (%lu)\n", + status); + + status = RpcServerUnregisterIf(NULL, NULL, FALSE); + ok(status == RPC_S_OK, "RpcServerUnregisterIf failed (%lu)\n", status); + + status = RpcMgmtWaitServerListen(); +todo_wine { + ok(status == RPC_S_OK, "RpcMgmtWaitServerListen failed (%lu)\n", status); +} + + status = RpcStringFree(&binding); + ok(status == RPC_S_OK, "RpcStringFree failed (%lu)\n", status); + + status = RpcBindingFree(&IFoo_IfHandle); + ok(status == RPC_S_OK, "RpcBindingFree failed (%lu)\n", status); +} + +/* this is what's generated with MS/RPC - it includes an extra 2 + * bytes in the protocol floor */ +static const unsigned char tower_data_tcp_ip1[] = +{ + 0x05,0x00,0x13,0x00,0x0d,0x00,0xdb,0xf1, + 0xa4,0x47,0xca,0x67,0x10,0xb3,0x1f,0x00, + 0xdd,0x01,0x06,0x62,0xda,0x00,0x00,0x02, + 0x00,0x00,0x00,0x13,0x00,0x0d,0x04,0x5d, + 0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8, + 0x08,0x00,0x2b,0x10,0x48,0x60,0x02,0x00, + 0x02,0x00,0x00,0x00,0x01,0x00,0x0b,0x02, + 0x00,0x00,0x00,0x01,0x00,0x07,0x02,0x00, + 0x00,0x87,0x01,0x00,0x09,0x04,0x00,0x0a, + 0x00,0x00,0x01, +}; +/* this is the optimal data that i think should be generated */ +static const unsigned char tower_data_tcp_ip2[] = +{ + 0x05,0x00,0x13,0x00,0x0d,0x00,0xdb,0xf1, + 0xa4,0x47,0xca,0x67,0x10,0xb3,0x1f,0x00, + 0xdd,0x01,0x06,0x62,0xda,0x00,0x00,0x02, + 0x00,0x00,0x00,0x13,0x00,0x0d,0x04,0x5d, + 0x88,0x8a,0xeb,0x1c,0xc9,0x11,0x9f,0xe8, + 0x08,0x00,0x2b,0x10,0x48,0x60,0x02,0x00, + 0x02,0x00,0x00,0x00,0x01,0x00,0x0b,0x00, + 0x00,0x01,0x00,0x07,0x02,0x00,0x00,0x87, + 0x01,0x00,0x09,0x04,0x00,0x0a,0x00,0x00, + 0x01, +}; + +static void test_towers(void) +{ + RPC_STATUS ret; + twr_t *tower; + static const RPC_SYNTAX_IDENTIFIER mapi_if_id = { { 0xa4f1db00, 0xca47, 0x1067, { 0xb3, 0x1f, 0x00, 0xdd, 0x01, 0x06, 0x62, 0xda } }, { 0, 0 } }; + static const RPC_SYNTAX_IDENTIFIER ndr_syntax = { { 0x8a885d04, 0x1ceb, 0x11c9, { 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60 } }, { 2, 0 } }; + RPC_SYNTAX_IDENTIFIER object, syntax; + char *protseq, *endpoint, *address; + BOOL same; + + ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_ip_tcp", "135", "10.0.0.1", &tower); + ok(ret == RPC_S_OK, "TowerConstruct failed with error %ld\n", ret); + + /* first check we have the right amount of data */ + ok(tower->tower_length == sizeof(tower_data_tcp_ip1) || + tower->tower_length == sizeof(tower_data_tcp_ip2), + "Wrong size of tower %d\n", tower->tower_length); + + /* then do a byte-by-byte comparison */ + same = ((tower->tower_length == sizeof(tower_data_tcp_ip1)) && + !memcmp(&tower->tower_octet_string, tower_data_tcp_ip1, sizeof(tower_data_tcp_ip1))) || + ((tower->tower_length == sizeof(tower_data_tcp_ip2)) && + !memcmp(&tower->tower_octet_string, tower_data_tcp_ip2, sizeof(tower_data_tcp_ip2))); + + ok(same, "Tower data differs\n"); + if (!same) + { + unsigned32 i; + for (i = 0; i < tower->tower_length; i++) + { + if (i % 8 == 0) printf(" "); + printf("0x%02x,", tower->tower_octet_string[i]); + if (i % 8 == 7) printf("\n"); + } + printf("\n"); + } + + ret = TowerExplode(tower, &object, &syntax, &protseq, &endpoint, &address); + ok(ret == RPC_S_OK, "TowerExplode failed with error %ld\n", ret); + ok(!memcmp(&object, &mapi_if_id, sizeof(mapi_if_id)), "object id didn't match\n"); + ok(!memcmp(&syntax, &ndr_syntax, sizeof(syntax)), "syntax id didn't match\n"); + ok(!strcmp(protseq, "ncacn_ip_tcp"), "protseq was \"%s\" instead of \"ncacn_ip_tcp\"\n", protseq); + ok(!strcmp(endpoint, "135"), "endpoint was \"%s\" instead of \"135\"\n", endpoint); + ok(!strcmp(address, "10.0.0.1"), "address was \"%s\" instead of \"10.0.0.1\"\n", address); + + I_RpcFree(protseq); + I_RpcFree(endpoint); + I_RpcFree(address); + + ret = TowerExplode(tower, NULL, NULL, NULL, NULL, NULL); + ok(ret == RPC_S_OK, "TowerExplode failed with error %ld\n", ret); + + I_RpcFree(tower); + + /* test the behaviour for ip_tcp with name instead of dotted IP notation */ + ret = TowerConstruct(&mapi_if_id, &ndr_syntax, "ncacn_ip_tcp", "135", "localhost", &tower); + ok(ret == RPC_S_OK, "TowerConstruct failed with error %ld\n", ret); + ret = TowerExplode(tower, NULL, NULL, NULL, NULL, &address); + ok(ret == RPC_S_OK, "TowerExplode failed with error %ld\n", ret); + ok(!strcmp(address, "0.0.0.0"), "address was \"%s\" instead of \"0.0.0.0\"\n", address); + + I_RpcFree(address); + I_RpcFree(tower); +} + +START_TEST( rpc ) +{ + trace ( " ** Uuid Conversion and Comparison Tests **\n" ); + UuidConversionAndComparison(); + trace ( " ** DceErrorInqText **\n"); + TestDceErrorInqText(); + test_rpc_ncacn_ip_tcp(); + test_towers(); +} diff --git a/rostests/winetests/rpcrt4/rpcrt4.rbuild b/rostests/winetests/rpcrt4/rpcrt4.rbuild new file mode 100644 index 00000000000..cb14a820f90 --- /dev/null +++ b/rostests/winetests/rpcrt4/rpcrt4.rbuild @@ -0,0 +1,25 @@ + + server.idl + + + server.idl + + + . + + wine + pseh + ole32 + uuid + rpcrt4_winetest_server + rpcrt4_winetest_client + rpcrt4 + kernel32 + ntdll + cstub.c + generated.c + ndr_marshall.c + rpc.c + server.c + testlist.c + \ No newline at end of file diff --git a/rostests/winetests/rpcrt4/server.c b/rostests/winetests/rpcrt4/server.c new file mode 100644 index 00000000000..8269dfa3f6d --- /dev/null +++ b/rostests/winetests/rpcrt4/server.c @@ -0,0 +1,1244 @@ +/* + * Tests for WIDL and RPC server/clients. + * + * Copyright (C) Google 2007 (Dan Hipschman) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include "wine/test.h" +#include "obj-i386/modules/rostests/winetests/rpcrt4/server.h" +#include "server_defines.h" + +#include +#include +#include + +#define PORT "4114" +#define PIPE "\\pipe\\wine_rpcrt4_test" + +#define INT_CODE 4198 + +static const char *progname; + +static HANDLE stop_event; + +void __RPC_FAR *__RPC_USER +midl_user_allocate(size_t n) +{ + return malloc(n); +} + +void __RPC_USER +midl_user_free(void __RPC_FAR *p) +{ + free(p); +} + +static char * +xstrdup(const char *s) +{ + char *d = HeapAlloc(GetProcessHeap(), 0, strlen(s) + 1); + strcpy(d, s); + return d; +} + +int +s_int_return(void) +{ + return INT_CODE; +} + +int +s_square(int x) +{ + return x * x; +} + +int +s_sum(int x, int y) +{ + return x + y; +} + +void +s_square_out(int x, int *y) +{ + *y = s_square(x); +} + +void +s_square_ref(int *x) +{ + *x = s_square(*x); +} + +int +s_str_length(const char *s) +{ + return strlen(s); +} + +int +s_cstr_length(const char *s, int n) +{ + int len = 0; + while (0 < n-- && *s++) + ++len; + return len; +} + +int +s_dot_self(vector_t *v) +{ + return s_square(v->x) + s_square(v->y) + s_square(v->z); +} + +double +s_square_half(double x, double *y) +{ + *y = x / 2.0; + return x * x; +} + +float +s_square_half_float(float x, float *y) +{ + *y = x / 2.0f; + return x * x; +} + +long +s_square_half_long(long x, long *y) +{ + *y = x / 2; + return x * x; +} + +int +s_sum_fixed_array(int a[5]) +{ + return a[0] + a[1] + a[2] + a[3] + a[4]; +} + +int +s_pints_sum(pints_t *pints) +{ + return *pints->pi + **pints->ppi + ***pints->pppi; +} + +double +s_ptypes_sum(ptypes_t *pt) +{ + return *pt->pc + *pt->ps + *pt->pl + *pt->pf + *pt->pd; +} + +int +s_dot_pvectors(pvectors_t *p) +{ + return p->pu->x * (*p->pv)->x + p->pu->y * (*p->pv)->y + p->pu->z * (*p->pv)->z; +} + +int +s_sum_sp(sp_t *sp) +{ + return sp->x + sp->s->x; +} + +double +s_square_sun(sun_t *su) +{ + switch (su->s) + { + case SUN_I: return su->u.i * su->u.i; + case SUN_F1: + case SUN_F2: return su->u.f * su->u.f; + case SUN_PI: return (*su->u.pi) * (*su->u.pi); + default: + return 0.0; + } +} + +int +s_test_list_length(test_list_t *list) +{ + return (list->t == TL_LIST + ? 1 + s_test_list_length(list->u.tail) + : 0); +} + +int +s_sum_fixed_int_3d(int m[2][3][4]) +{ + int i, j, k; + int sum = 0; + + for (i = 0; i < 2; ++i) + for (j = 0; j < 3; ++j) + for (k = 0; k < 4; ++k) + sum += m[i][j][k]; + + return sum; +} + +int +s_sum_conf_array(int x[], int n) +{ + int *p = x, *end = p + n; + int sum = 0; + + while (p < end) + sum += *p++; + + return sum; +} + +int +s_sum_unique_conf_array(int x[], int n) +{ + return s_sum_conf_array(x, n); +} + +int +s_sum_unique_conf_ptr(int *x, int n) +{ + return x ? s_sum_conf_array(x, n) : 0; +} + +int +s_sum_var_array(int x[20], int n) +{ + ok(0 <= n, "RPC sum_var_array\n"); + ok(n <= 20, "RPC sum_var_array\n"); + + return s_sum_conf_array(x, n); +} + +int +s_dot_two_vectors(vector_t vs[2]) +{ + return vs[0].x * vs[1].x + vs[0].y * vs[1].y + vs[0].z * vs[1].z; +} + +int +s_sum_cs(cs_t *cs) +{ + return s_sum_conf_array(cs->ca, cs->n); +} + +int +s_sum_cps(cps_t *cps) +{ + int sum = 0; + int i; + + for (i = 0; i < *cps->pn; ++i) + sum += cps->ca1[i]; + + for (i = 0; i < 2 * cps->n; ++i) + sum += cps->ca2[i]; + + return sum; +} + +int +s_sum_cpsc(cpsc_t *cpsc) +{ + int sum = 0; + int i; + for (i = 0; i < (cpsc->c ? cpsc->a : cpsc->b); ++i) + sum += cpsc->ca[i]; + return sum; +} + +int +s_square_puint(puint_t p) +{ + int n = atoi(p); + return n * n; +} + +int +s_sum_puints(puints_t *p) +{ + int sum = 0; + int i; + for (i = 0; i < p->n; ++i) + sum += atoi(p->ps[i]); + return sum; +} + +int +s_sum_cpuints(cpuints_t *p) +{ + int sum = 0; + int i; + for (i = 0; i < p->n; ++i) + sum += atoi(p->ps[i]); + return sum; +} + +int +s_dot_copy_vectors(vector_t u, vector_t v) +{ + return u.x * v.x + u.y * v.y + u.z * v.z; +} + +int +s_square_test_us(test_us_t *tus) +{ + int n = atoi(tus->us.x); + return n * n; +} + +double +s_square_encu(encu_t *eu) +{ + switch (eu->t) + { + case ENCU_I: return eu->tagged_union.i * eu->tagged_union.i; + case ENCU_F: return eu->tagged_union.f * eu->tagged_union.f; + default: + return 0.0; + } +} + +int +s_sum_parr(int *a[3]) +{ + return s_sum_pcarr(a, 3); +} + +int +s_sum_pcarr(int *a[], int n) +{ + int i, s = 0; + for (i = 0; i < n; ++i) + s += *a[i]; + return s; +} + +int +s_enum_ord(e_t e) +{ + switch (e) + { + case E1: return 1; + case E2: return 2; + case E3: return 3; + case E4: return 4; + default: + return 0; + } +} + +double +s_square_encue(encue_t *eue) +{ + switch (eue->t) + { + case E1: return eue->tagged_union.i1 * eue->tagged_union.i1; + case E2: return eue->tagged_union.f2 * eue->tagged_union.f2; + default: + return 0.0; + } +} + +int +s_sum_toplev_conf_2n(int *x, int n) +{ + int sum = 0; + int i; + for (i = 0; i < 2 * n; ++i) + sum += x[i]; + return sum; +} + +int +s_sum_toplev_conf_cond(int *x, int a, int b, int c) +{ + int sum = 0; + int n = c ? a : b; + int i; + for (i = 0; i < n; ++i) + sum += x[i]; + return sum; +} + +double +s_sum_aligns(aligns_t *a) +{ + return a->c + a->i + a->s + a->d; +} + +int +s_sum_padded(padded_t *p) +{ + return p->i + p->c; +} + +int +s_sum_padded2(padded_t ps[2]) +{ + return s_sum_padded(&ps[0]) + s_sum_padded(&ps[1]); +} + +int +s_sum_padded_conf(padded_t *ps, int n) +{ + int sum = 0; + int i; + for (i = 0; i < n; ++i) + sum += s_sum_padded(&ps[i]); + return sum; +} + +int +s_sum_bogus(bogus_t *b) +{ + return *b->h.p1 + *b->p2 + *b->p3 + b->c; +} + +void +s_check_null(int *null) +{ + ok(!null, "RPC check_null\n"); +} + +int +s_str_struct_len(str_struct_t *s) +{ + return lstrlenA(s->s); +} + +int +s_wstr_struct_len(wstr_struct_t *s) +{ + return lstrlenW(s->s); +} + +int +s_sum_doub_carr(doub_carr_t *dc) +{ + int i, j; + int sum = 0; + for (i = 0; i < dc->n; ++i) + for (j = 0; j < dc->a[i]->n; ++j) + sum += dc->a[i]->a[j]; + return sum; +} + +void +s_make_pyramid_doub_carr(unsigned char n, doub_carr_t **dc) +{ + doub_carr_t *t; + int i, j; + t = MIDL_user_allocate(FIELD_OFFSET(doub_carr_t, a[n])); + t->n = n; + for (i = 0; i < n; ++i) + { + int v = i + 1; + t->a[i] = MIDL_user_allocate(FIELD_OFFSET(doub_carr_1_t, a[v])); + t->a[i]->n = v; + for (j = 0; j < v; ++j) + t->a[i]->a[j] = j + 1; + } + *dc = t; +} + +unsigned +s_hash_bstr(bstr_t b) +{ + short n = b[-1]; + short *s = b; + unsigned hash = 0; + short i; + for (i = 0; i < n; ++i) + hash = 5 * hash + (unsigned) s[i]; + return hash; +} + +void +s_get_name(name_t *name) +{ + const char bossman[] = "Jeremy White"; + memcpy(name->name, bossman, min(name->size, sizeof(bossman))); + /* ensure nul-termination */ + if (name->size < sizeof(bossman)) + name->name[name->size - 1] = 0; +} + +int +s_sum_pcarr2(int n, int **pa) +{ + return s_sum_conf_array(*pa, n); +} + +int +s_sum_L1_norms(int n, vector_t *vs) +{ + int i; + int sum = 0; + for (i = 0; i < n; ++i) + sum += abs(vs[i].x) + abs(vs[i].y) + abs(vs[i].z); + return sum; +} + +str_t +s_get_filename(void) +{ + return (char *)__FILE__; +} + +void +s_context_handle_test(void) +{ + NDR_SCONTEXT h; + RPC_BINDING_HANDLE binding; + RPC_STATUS status; + unsigned char buf[20]; + static RPC_SERVER_INTERFACE server_if = + { + sizeof(RPC_SERVER_INTERFACE), + {{0x00000000,0x4114,0x0704,{0x23,0x01,0x00,0x00,0x00,0x00,0x00,0x00}},{1,0}}, + {{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}}, + NULL, + 0, + 0, + 0, + 0, + 0, + }; + + binding = I_RpcGetCurrentCallHandle(); + ok(binding != NULL, "I_RpcGetCurrentCallHandle returned NULL\n"); + + h = NDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0); + ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n"); + + /* marshal a context handle with NULL userContext */ + memset(buf, 0xcc, sizeof(buf)); + NDRSContextMarshall2(binding, h, buf, NULL, NULL, 0); + ok(*(ULONG *)buf == 0, "attributes should have been set to 0 instead of 0x%x\n", *(ULONG *)buf); + ok(UuidIsNil((UUID *)&buf[4], &status), "uuid should have been nil\n"); + + h = NDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0); + ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n"); + + /* marshal a context handle with non-NULL userContext */ + memset(buf, 0xcc, sizeof(buf)); + h->userContext = (void *)0xdeadbeef; + NDRSContextMarshall2(binding, h, buf, NULL, NULL, 0); + ok(*(ULONG *)buf == 0, "attributes should have been set to 0 instead of 0x%x\n", *(ULONG *)buf); + ok(!UuidIsNil((UUID *)&buf[4], &status), "uuid should not have been nil\n"); + + h = NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, NULL, 0); + ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n"); + ok(h->userContext == (void *)0xdeadbeef, "userContext of interface didn't unmarshal properly: %p\n", h->userContext); + + /* marshal a context handle with an interface specified */ + h = NDRSContextUnmarshall2(binding, NULL, NDR_LOCAL_DATA_REPRESENTATION, &server_if.InterfaceId, 0); + ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n"); + + memset(buf, 0xcc, sizeof(buf)); + h->userContext = (void *)0xcafebabe; + NDRSContextMarshall2(binding, h, buf, NULL, &server_if.InterfaceId, 0); + ok(*(ULONG *)buf == 0, "attributes should have been set to 0 instead of 0x%x\n", *(ULONG *)buf); + ok(!UuidIsNil((UUID *)&buf[4], &status), "uuid should not have been nil\n"); + + h = NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if.InterfaceId, 0); + ok(h != NULL, "NDRSContextUnmarshall2 returned NULL\n"); + ok(h->userContext == (void *)0xcafebabe, "userContext of interface didn't unmarshal properly: %p\n", h->userContext); + + /* test same interface data, but different pointer */ + /* raises ERROR_INVALID_HANDLE exception */ + if (0) + { + RPC_SERVER_INTERFACE server_if_clone = server_if; + + NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if_clone.InterfaceId, 0); + } + + /* test different interface data, but different pointer */ + /* raises ERROR_INVALID_HANDLE exception */ + if (0) + { + static RPC_SERVER_INTERFACE server_if2 = + { + sizeof(RPC_SERVER_INTERFACE), + {{0x00000000,0x4114,0x0704,{0x23,0x01,0x00,0x00,0x00,0x00,0x00,0x00}},{1,0}}, + {{0x8a885d04,0x1ceb,0x11c9,{0x9f,0xe8,0x08,0x00,0x2b,0x10,0x48,0x60}},{2,0}}, + NULL, + 0, + 0, + 0, + 0, + 0, + }; + NDRSContextMarshall2(binding, h, buf, NULL, &server_if.InterfaceId, 0); + + NDRSContextUnmarshall2(binding, buf, NDR_LOCAL_DATA_REPRESENTATION, &server_if2.InterfaceId, 0); + } +} + +void +s_get_5numbers(int count, pints_t n[5]) +{ + int i; + for (i = 0; i < count; i++) + { + n[i].pi = midl_user_allocate(sizeof(*n[i].pi)); + *n[i].pi = i; + n[i].ppi = NULL; + n[i].pppi = NULL; + } +} + +void +s_get_numbers(int length, int size, pints_t n[]) +{ + int i; + for (i = 0; i < length; i++) + { + n[i].pi = midl_user_allocate(sizeof(*n[i].pi)); + *n[i].pi = i; + n[i].ppi = NULL; + n[i].pppi = NULL; + } +} + +void +s_stop(void) +{ + ok(RPC_S_OK == RpcMgmtStopServerListening(NULL), "RpcMgmtStopServerListening\n"); + ok(RPC_S_OK == RpcServerUnregisterIf(NULL, NULL, FALSE), "RpcServerUnregisterIf\n"); + ok(SetEvent(stop_event), "SetEvent\n"); +} + +static void +make_cmdline(char buffer[MAX_PATH], const char *test) +{ + sprintf(buffer, "%s server %s", progname, test); +} + +static int +run_client(const char *test) +{ + char cmdline[MAX_PATH]; + PROCESS_INFORMATION info; + STARTUPINFOA startup; + DWORD exitcode; + + memset(&startup, 0, sizeof startup); + startup.cb = sizeof startup; + + make_cmdline(cmdline, test); + ok(CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess\n"); + ok(WaitForSingleObject(info.hProcess, 30000) == WAIT_OBJECT_0, "Child process termination\n"); + ok(GetExitCodeProcess(info.hProcess, &exitcode), "GetExitCodeProcess\n"); + ok(CloseHandle(info.hProcess), "CloseHandle\n"); + ok(CloseHandle(info.hThread), "CloseHandle\n"); + + return exitcode == 0; +} + +static void +basic_tests(void) +{ + char string[] = "I am a string"; + WCHAR wstring[] = {'I',' ','a','m',' ','a',' ','w','s','t','r','i','n','g', 0}; + int f[5] = {1, 3, 0, -2, -4}; + vector_t a = {1, 3, 7}; + vector_t vec1 = {4, -2, 1}, vec2 = {-5, 2, 3}, *pvec2 = &vec2; + pvectors_t pvecs = {&vec1, &pvec2}; + sp_inner_t spi = {42}; + sp_t sp = {-13, &spi}; + aligns_t aligns; + pints_t pints; + ptypes_t ptypes; + padded_t padded; + padded_t padded2[2]; + bogus_t bogus; + int i1, i2, i3, *pi2, *pi3, **ppi3; + double u, v; + float s, t; + long q, r; + short h; + char c; + int x; + str_struct_t ss = {string}; + wstr_struct_t ws = {wstring}; + str_t str; + + ok(int_return() == INT_CODE, "RPC int_return\n"); + + ok(square(7) == 49, "RPC square\n"); + ok(sum(23, -4) == 19, "RPC sum\n"); + + x = 0; + square_out(11, &x); + ok(x == 121, "RPC square_out\n"); + + x = 5; + square_ref(&x); + ok(x == 25, "RPC square_ref\n"); + + ok(str_length(string) == strlen(string), "RPC str_length\n"); + ok(dot_self(&a) == 59, "RPC dot_self\n"); + + ok(str_struct_len(&ss) == lstrlenA(string), "RPC str_struct_len\n"); + ok(wstr_struct_len(&ws) == lstrlenW(wstring), "RPC str_struct_len\n"); + + v = 0.0; + u = square_half(3.0, &v); + ok(u == 9.0, "RPC square_half\n"); + ok(v == 1.5, "RPC square_half\n"); + + t = 0.0f; + s = square_half_float(3.0f, &t); + ok(s == 9.0f, "RPC square_half_float\n"); + ok(t == 1.5f, "RPC square_half_float\n"); + + r = 0; + q = square_half_long(3, &r); + ok(q == 9, "RPC square_half_long\n"); + ok(r == 1, "RPC square_half_long\n"); + + i1 = 19; + i2 = -3; + i3 = -29; + pi2 = &i2; + pi3 = &i3; + ppi3 = &pi3; + pints.pi = &i1; + pints.ppi = &pi2; + pints.pppi = &ppi3; + ok(pints_sum(&pints) == -13, "RPC pints_sum\n"); + + c = 10; + h = 3; + q = 14; + s = -5.0f; + u = 11.0; + ptypes.pc = &c; + ptypes.ps = &h; + ptypes.pl = &q; + ptypes.pf = &s; + ptypes.pd = &u; + ok(ptypes_sum(&ptypes) == 33.0, "RPC ptypes_sum\n"); + + ok(dot_pvectors(&pvecs) == -21, "RPC dot_pvectors\n"); + ok(dot_copy_vectors(vec1, vec2) == -21, "RPC dot_copy_vectors\n"); + ok(sum_fixed_array(f) == -2, "RPC sum_fixed_array\n"); + ok(sum_sp(&sp) == 29, "RPC sum_sp\n"); + + ok(enum_ord(E1) == 1, "RPC enum_ord\n"); + ok(enum_ord(E2) == 2, "RPC enum_ord\n"); + ok(enum_ord(E3) == 3, "RPC enum_ord\n"); + ok(enum_ord(E4) == 4, "RPC enum_ord\n"); + + memset(&aligns, 0, sizeof(aligns)); + aligns.c = 3; + aligns.i = 4; + aligns.s = 5; + aligns.d = 6.0; + ok(sum_aligns(&aligns) == 18.0, "RPC sum_aligns\n"); + + padded.i = -3; + padded.c = 8; + ok(sum_padded(&padded) == 5, "RPC sum_padded\n"); + padded2[0].i = -5; + padded2[0].c = 1; + padded2[1].i = 3; + padded2[1].c = 7; + ok(sum_padded2(padded2) == 6, "RPC sum_padded2\n"); + padded2[0].i = -5; + padded2[0].c = 1; + padded2[1].i = 3; + padded2[1].c = 7; + ok(sum_padded_conf(padded2, 2) == 6, "RPC sum_padded_conf\n"); + + i1 = 14; + i2 = -7; + i3 = -4; + bogus.h.p1 = &i1; + bogus.p2 = &i2; + bogus.p3 = &i3; + bogus.c = 9; + ok(sum_bogus(&bogus) == 12, "RPC sum_bogus\n"); + + check_null(NULL); + + str = get_filename(); + ok(!strcmp(str, __FILE__), "get_filename() returned %s instead of %s\n", str, __FILE__); + midl_user_free(str); +} + +static void +union_tests(void) +{ + encue_t eue; + encu_t eu; + sun_t su; + int i; + + su.s = SUN_I; + su.u.i = 9; + ok(square_sun(&su) == 81.0, "RPC square_sun\n"); + + su.s = SUN_F1; + su.u.f = 5.0; + ok(square_sun(&su) == 25.0, "RPC square_sun\n"); + + su.s = SUN_F2; + su.u.f = -2.0; + ok(square_sun(&su) == 4.0, "RPC square_sun\n"); + + su.s = SUN_PI; + su.u.pi = &i; + i = 11; + ok(square_sun(&su) == 121.0, "RPC square_sun\n"); + + eu.t = ENCU_I; + eu.tagged_union.i = 7; + ok(square_encu(&eu) == 49.0, "RPC square_encu\n"); + + eu.t = ENCU_F; + eu.tagged_union.f = 3.0; + ok(square_encu(&eu) == 9.0, "RPC square_encu\n"); + + eue.t = E1; + eue.tagged_union.i1 = 8; + ok(square_encue(&eue) == 64.0, "RPC square_encue\n"); + + eue.t = E2; + eue.tagged_union.f2 = 10.0; + ok(square_encue(&eue) == 100.0, "RPC square_encue\n"); +} + +static test_list_t * +null_list(void) +{ + test_list_t *n = HeapAlloc(GetProcessHeap(), 0, sizeof *n); + n->t = TL_NULL; + n->u.x = 0; + return n; +} + +static test_list_t * +make_list(test_list_t *tail) +{ + test_list_t *n = HeapAlloc(GetProcessHeap(), 0, sizeof *n); + n->t = TL_LIST; + n->u.tail = tail; + return n; +} + +static void +free_list(test_list_t *list) +{ + if (list->t == TL_LIST) + free_list(list->u.tail); + HeapFree(GetProcessHeap(), 0, list); +} + +ULONG __RPC_USER +puint_t_UserSize(ULONG *flags, ULONG start, puint_t *p) +{ + return start + sizeof(int); +} + +unsigned char * __RPC_USER +puint_t_UserMarshal(ULONG *flags, unsigned char *buffer, puint_t *p) +{ + int n = atoi(*p); + memcpy(buffer, &n, sizeof n); + return buffer + sizeof n; +} + +unsigned char * __RPC_USER +puint_t_UserUnmarshal(ULONG *flags, unsigned char *buffer, puint_t *p) +{ + int n; + memcpy(&n, buffer, sizeof n); + *p = HeapAlloc(GetProcessHeap(), 0, 10); + sprintf(*p, "%d", n); + return buffer + sizeof n; +} + +void __RPC_USER +puint_t_UserFree(ULONG *flags, puint_t *p) +{ + HeapFree(GetProcessHeap(), 0, *p); +} + +ULONG __RPC_USER +us_t_UserSize(ULONG *flags, ULONG start, us_t *pus) +{ + return start + sizeof(struct wire_us); +} + +unsigned char * __RPC_USER +us_t_UserMarshal(ULONG *flags, unsigned char *buffer, us_t *pus) +{ + struct wire_us wus; + wus.x = atoi(pus->x); + memcpy(buffer, &wus, sizeof wus); + return buffer + sizeof wus; +} + +unsigned char * __RPC_USER +us_t_UserUnmarshal(ULONG *flags, unsigned char *buffer, us_t *pus) +{ + struct wire_us wus; + memcpy(&wus, buffer, sizeof wus); + pus->x = HeapAlloc(GetProcessHeap(), 0, 10); + sprintf(pus->x, "%d", wus.x); + return buffer + sizeof wus; +} + +void __RPC_USER +us_t_UserFree(ULONG *flags, us_t *pus) +{ + HeapFree(GetProcessHeap(), 0, pus->x); +} + +ULONG __RPC_USER +bstr_t_UserSize(ULONG *flags, ULONG start, bstr_t *b) +{ + return start + FIELD_OFFSET(wire_bstr_t, data[(*b)[-1]]); +} + +unsigned char * __RPC_USER +bstr_t_UserMarshal(ULONG *flags, unsigned char *buffer, bstr_t *b) +{ + wire_bstr_t *wb = (wire_bstr_t *) buffer; + wb->n = (*b)[-1]; + memcpy(&wb->data, *b, wb->n * sizeof wb->data[0]); + return buffer + FIELD_OFFSET(wire_bstr_t, data[wb->n]); +} + +unsigned char * __RPC_USER +bstr_t_UserUnmarshal(ULONG *flags, unsigned char *buffer, bstr_t *b) +{ + wire_bstr_t *wb = (wire_bstr_t *) buffer; + short *data = HeapAlloc(GetProcessHeap(), 0, (wb->n + 1) * sizeof *data); + data[0] = wb->n; + memcpy(&data[1], wb->data, wb->n * sizeof data[1]); + *b = &data[1]; + return buffer + FIELD_OFFSET(wire_bstr_t, data[wb->n]); +} + +void __RPC_USER +bstr_t_UserFree(ULONG *flags, bstr_t *b) +{ + HeapFree(GetProcessHeap(), 0, &((*b)[-1])); +} + +static void +pointer_tests(void) +{ + int a[] = {1, 2, 3, 4}; + char p1[] = "11"; + test_list_t *list = make_list(make_list(make_list(null_list()))); + test_us_t tus = {{p1}}; + int *pa[4]; + puints_t pus; + cpuints_t cpus; + short bstr_data[] = { 5, 'H', 'e', 'l', 'l', 'o' }; + bstr_t bstr = &bstr_data[1]; + name_t name; + void *buffer; + int *pa2; + + ok(test_list_length(list) == 3, "RPC test_list_length\n"); + ok(square_puint(p1) == 121, "RPC square_puint\n"); + pus.n = 4; + pus.ps = HeapAlloc(GetProcessHeap(), 0, pus.n * sizeof pus.ps[0]); + pus.ps[0] = xstrdup("5"); + pus.ps[1] = xstrdup("6"); + pus.ps[2] = xstrdup("7"); + pus.ps[3] = xstrdup("8"); + ok(sum_puints(&pus) == 26, "RPC sum_puints\n"); + HeapFree(GetProcessHeap(), 0, pus.ps[0]); + HeapFree(GetProcessHeap(), 0, pus.ps[1]); + HeapFree(GetProcessHeap(), 0, pus.ps[2]); + HeapFree(GetProcessHeap(), 0, pus.ps[3]); + HeapFree(GetProcessHeap(), 0, pus.ps); + cpus.n = 4; + cpus.ps = HeapAlloc(GetProcessHeap(), 0, cpus.n * sizeof cpus.ps[0]); + cpus.ps[0] = xstrdup("5"); + cpus.ps[1] = xstrdup("6"); + cpus.ps[2] = xstrdup("7"); + cpus.ps[3] = xstrdup("8"); + ok(sum_cpuints(&cpus) == 26, "RPC sum_puints\n"); + HeapFree(GetProcessHeap(), 0, cpus.ps[0]); + HeapFree(GetProcessHeap(), 0, cpus.ps[1]); + HeapFree(GetProcessHeap(), 0, cpus.ps[2]); + HeapFree(GetProcessHeap(), 0, cpus.ps[3]); + HeapFree(GetProcessHeap(), 0, cpus.ps); + ok(square_test_us(&tus) == 121, "RPC square_test_us\n"); + + pa[0] = &a[0]; + pa[1] = &a[1]; + pa[2] = &a[2]; + ok(sum_parr(pa) == 6, "RPC sum_parr\n"); + + pa[0] = &a[0]; + pa[1] = &a[1]; + pa[2] = &a[2]; + pa[3] = &a[3]; + ok(sum_pcarr(pa, 4) == 10, "RPC sum_pcarr\n"); + + ok(hash_bstr(bstr) == s_hash_bstr(bstr), "RPC hash_bstr_data\n"); + + free_list(list); + + name.size = 10; + name.name = buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, name.size); + get_name(&name); + ok(name.name == buffer, "[in,out] pointer should have stayed as %p but instead changed to %p\n", name.name, buffer); + ok(!strcmp(name.name, "Jeremy Wh"), "name didn't unmarshall properly, expected \"Jeremy Wh\", but got \"%s\"\n", name.name); + HeapFree(GetProcessHeap(), 0, name.name); + + pa2 = a; + ok(sum_pcarr2(4, &pa2) == 10, "RPC sum_pcarr2\n"); +} + +static int +check_pyramid_doub_carr(doub_carr_t *dc) +{ + int i, j; + for (i = 0; i < dc->n; ++i) + for (j = 0; j < dc->a[i]->n; ++j) + if (dc->a[i]->a[j] != j + 1) + return FALSE; + return TRUE; +} + +static void +free_pyramid_doub_carr(doub_carr_t *dc) +{ + int i; + for (i = 0; i < dc->n; ++i) + MIDL_user_free(dc->a[i]); + MIDL_user_free(dc); +} + +static void +array_tests(void) +{ + const char str1[25] = "Hello"; + int m[2][3][4] = + { + {{1, 2, 3, 4}, {-1, -3, -5, -7}, {0, 2, 4, 6}}, + {{1, -2, 3, -4}, {2, 3, 5, 7}, {-4, -1, -14, 4114}} + }; + int c[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + vector_t vs[2] = {{1, -2, 3}, {4, -5, -6}}; + cps_t cps; + cpsc_t cpsc; + cs_t *cs; + int n; + int ca[5] = {1, -2, 3, -4, 5}; + doub_carr_t *dc; + int *pi; + pints_t api[5]; + + ok(cstr_length(str1, sizeof str1) == strlen(str1), "RPC cstr_length\n"); + + ok(sum_fixed_int_3d(m) == 4116, "RPC sum_fixed_int_3d\n"); + + ok(sum_conf_array(c, 10) == 45, "RPC sum_conf_array\n"); + ok(sum_conf_array(&c[5], 2) == 11, "RPC sum_conf_array\n"); + ok(sum_conf_array(&c[7], 1) == 7, "RPC sum_conf_array\n"); + ok(sum_conf_array(&c[2], 0) == 0, "RPC sum_conf_array\n"); + + ok(sum_unique_conf_array(ca, 4) == -2, "RPC sum_unique_conf_array\n"); + ok(sum_unique_conf_ptr(ca, 5) == 3, "RPC sum_unique_conf_array\n"); + ok(sum_unique_conf_ptr(NULL, 10) == 0, "RPC sum_unique_conf_array\n"); + + ok(sum_var_array(c, 10) == 45, "RPC sum_conf_array\n"); + ok(sum_var_array(&c[5], 2) == 11, "RPC sum_conf_array\n"); + ok(sum_var_array(&c[7], 1) == 7, "RPC sum_conf_array\n"); + ok(sum_var_array(&c[2], 0) == 0, "RPC sum_conf_array\n"); + + ok(dot_two_vectors(vs) == -4, "RPC dot_two_vectors\n"); + cs = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET(cs_t, ca[5])); + cs->n = 5; + cs->ca[0] = 3; + cs->ca[1] = 5; + cs->ca[2] = -2; + cs->ca[3] = -1; + cs->ca[4] = -4; + ok(sum_cs(cs) == 1, "RPC sum_cs\n"); + HeapFree(GetProcessHeap(), 0, cs); + + n = 5; + cps.pn = &n; + cps.ca1 = &c[2]; + cps.n = 3; + cps.ca2 = &c[3]; + ok(sum_cps(&cps) == 53, "RPC sum_cps\n"); + + cpsc.a = 4; + cpsc.b = 5; + cpsc.c = 1; + cpsc.ca = c; + ok(sum_cpsc(&cpsc) == 6, "RPC sum_cpsc\n"); + cpsc.a = 4; + cpsc.b = 5; + cpsc.c = 0; + cpsc.ca = c; + ok(sum_cpsc(&cpsc) == 10, "RPC sum_cpsc\n"); + + ok(sum_toplev_conf_2n(c, 3) == 15, "RPC sum_toplev_conf_2n\n"); + ok(sum_toplev_conf_cond(c, 5, 6, 1) == 10, "RPC sum_toplev_conf_cond\n"); + ok(sum_toplev_conf_cond(c, 5, 6, 0) == 15, "RPC sum_toplev_conf_cond\n"); + + dc = malloc(FIELD_OFFSET(doub_carr_t, a[2])); + dc->n = 2; + dc->a[0] = malloc(FIELD_OFFSET(doub_carr_1_t, a[3])); + dc->a[0]->n = 3; + dc->a[0]->a[0] = 5; + dc->a[0]->a[1] = 1; + dc->a[0]->a[2] = 8; + dc->a[1] = malloc(FIELD_OFFSET(doub_carr_1_t, a[2])); + dc->a[1]->n = 2; + dc->a[1]->a[0] = 2; + dc->a[1]->a[1] = 3; + ok(sum_doub_carr(dc) == 19, "RPC sum_doub_carr\n"); + free(dc->a[0]); + free(dc->a[1]); + free(dc); + + dc = NULL; + make_pyramid_doub_carr(4, &dc); + ok(check_pyramid_doub_carr(dc), "RPC make_pyramid_doub_carr\n"); + free_pyramid_doub_carr(dc); + + ok(sum_L1_norms(2, vs) == 21, "RPC sum_L1_norms\n"); + + memset(api, 0, sizeof(api)); + pi = HeapAlloc(GetProcessHeap(), 0, sizeof(*pi)); + *pi = -1; + api[0].pi = pi; + get_5numbers(1, api); + ok(api[0].pi == pi, "RPC varying array [out] pointer changed from %p to %p\n", pi, api[0].pi); + ok(*api[0].pi == 0, "pi unmarshalled incorrectly %d\n", *pi); + + api[0].pi = pi; + get_numbers(1, 1, api); + ok(api[0].pi == pi, "RPC conformant varying array [out] pointer changed from %p to %p\n", pi, api[0].pi); + ok(*api[0].pi == 0, "pi unmarshalled incorrectly %d\n", *pi); + HeapFree(GetProcessHeap(), 0, pi); +} + +static void +run_tests(void) +{ + basic_tests(); + union_tests(); + pointer_tests(); + array_tests(); + context_handle_test(); +} + +static void +client(const char *test) +{ + if (strcmp(test, "tcp_basic") == 0) + { + static unsigned char iptcp[] = "ncacn_ip_tcp"; + static unsigned char address[] = "127.0.0.1"; + static unsigned char port[] = PORT; + unsigned char *binding; + + ok(RPC_S_OK == RpcStringBindingCompose(NULL, iptcp, address, port, NULL, &binding), "RpcStringBindingCompose\n"); + ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n"); + + run_tests(); + + ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n"); + ok(RPC_S_OK == RpcBindingFree(&IServer_IfHandle), "RpcBindingFree\n"); + } + else if (strcmp(test, "np_basic") == 0) + { + static unsigned char np[] = "ncacn_np"; + static unsigned char address[] = "\\\\."; + static unsigned char pipe[] = PIPE; + unsigned char *binding; + + ok(RPC_S_OK == RpcStringBindingCompose(NULL, np, address, pipe, NULL, &binding), "RpcStringBindingCompose\n"); + ok(RPC_S_OK == RpcBindingFromStringBinding(binding, &IServer_IfHandle), "RpcBindingFromStringBinding\n"); + + run_tests(); + stop(); + + ok(RPC_S_OK == RpcStringFree(&binding), "RpcStringFree\n"); + ok(RPC_S_OK == RpcBindingFree(&IServer_IfHandle), "RpcBindingFree\n"); + } +} + +static void +server(void) +{ + static unsigned char iptcp[] = "ncacn_ip_tcp"; + static unsigned char port[] = PORT; + static unsigned char np[] = "ncacn_np"; + static unsigned char pipe[] = PIPE; + + ok(RPC_S_OK == RpcServerUseProtseqEp(iptcp, 20, port, NULL), "RpcServerUseProtseqEp\n"); + //ok(RPC_S_OK == RpcServerRegisterIf(s_IServer_v0_0_s_ifspec, NULL, NULL), "RpcServerRegisterIf\n"); + ok(RPC_S_OK == RpcServerListen(1, 20, TRUE), "RpcServerListen\n"); + + stop_event = CreateEvent(NULL, FALSE, FALSE, NULL); + ok(stop_event != NULL, "CreateEvent failed\n"); + + ok(run_client("tcp_basic"), "tcp_basic client test failed\n"); + + ok(RPC_S_OK == RpcServerUseProtseqEp(np, 0, pipe, NULL), "RpcServerUseProtseqEp\n"); + ok(run_client("np_basic"), "np_basic client test failed\n"); + + ok(WAIT_OBJECT_0 == WaitForSingleObject(stop_event, 60000), "WaitForSingleObject\n"); + todo_wine { + ok(RPC_S_OK == RpcMgmtWaitServerListen(), "RpcMgmtWaitServerListening\n"); + } +} + +START_TEST(server) +{ + int argc; + char **argv; + + argc = winetest_get_mainargs(&argv); + progname = argv[0]; + + if (argc == 3) + { + RpcTryExcept + { + client(argv[2]); + } + RpcExcept(TRUE) + { + trace("Exception %d\n", RpcExceptionCode()); + } + RpcEndExcept + } + else + server(); +} diff --git a/rostests/winetests/rpcrt4/server.idl b/rostests/winetests/rpcrt4/server.idl new file mode 100644 index 00000000000..ec517572dc3 --- /dev/null +++ b/rostests/winetests/rpcrt4/server.idl @@ -0,0 +1,308 @@ +/* + * A simple interface to test the RPC server. + * + * Copyright (C) Google 2007 (Dan Hipschman) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "server_defines.h" + +typedef struct tag_vector +{ + int x; + int y; + int z; +} vector_t; + +[ + uuid(00000000-4114-0704-2301-000000000000), +#ifndef __midl + implicit_handle(handle_t IServer_IfHandle) +#endif +] +interface IServer +{ +cpp_quote("#if 0") + typedef wchar_t WCHAR; +cpp_quote("#endif") + + typedef [string] char *str_t; + typedef [string] WCHAR *wstr_t; + + typedef struct + { + int *pi; + int **ppi; + int ***pppi; + } pints_t; + + typedef struct + { + char *pc; + short *ps; + long *pl; + float *pf; + double *pd; + } ptypes_t; + + typedef struct + { + vector_t *pu; + vector_t **pv; + } pvectors_t; + + typedef struct + { + [switch_is(s)] union + { + [case(SUN_I)] int i; + [case(SUN_F1, SUN_F2)] float f; + [case(SUN_PI)] int *pi; + } u; + + int s; + } sun_t; + + int int_return(void); + int square(int x); + int sum(int x, int y); + void square_out(int x, [out] int *y); + void square_ref([in, out] int *x); + int str_length([string] const char *s); + int cstr_length([string, size_is(n)] const char *s, int n); + int dot_self(vector_t *v); + double square_half(double x, [out] double *y); + float square_half_float(float x, [out] float *y); + long square_half_long(long x, [out] long *y); + int sum_fixed_array(int a[5]); + int pints_sum(pints_t *pints); + double ptypes_sum(ptypes_t *ptypes); + int dot_pvectors(pvectors_t *pvectors); + + /* don't use this anywhere except in sp_t */ + typedef struct + { + int x; + } sp_inner_t; + + typedef struct + { + int x; + sp_inner_t *s; + } sp_t; + + int sum_sp(sp_t *sp); + double square_sun(sun_t *su); + + typedef struct test_list + { + int t; + [switch_is(t)] union + { + [case(TL_NULL)] char x; /* end of list */ + [case(TL_LIST)] struct test_list *tail; + } u; + } test_list_t; + + int test_list_length(test_list_t *ls); + int sum_fixed_int_3d(int m[2][3][4]); + int sum_conf_array([size_is(n)] int x[], int n); + int sum_unique_conf_array([size_is(n), unique] int x[], int n); + int sum_unique_conf_ptr([size_is(n), unique] int *x, int n); + int sum_var_array([length_is(n)] int x[20], int n); + int dot_two_vectors(vector_t vs[2]); + + typedef struct + { + int n; + [size_is(n)] int ca[]; + } cs_t; + + typedef struct + { + int *pn; + [size_is(*pn)] int *ca1; + [size_is(n * 2)] int *ca2; + int n; + } cps_t; + + typedef struct + { + [size_is(c ? a : b)] int *ca; + int a; + int b; + int c; + } cpsc_t; + + int sum_cs(cs_t *cs); + int sum_cps(cps_t *cps); + int sum_cpsc(cpsc_t *cpsc); + + typedef [wire_marshal(int)] void *puint_t; + int square_puint(puint_t p); + + typedef struct + { + [size_is(n)] puint_t *ps; + int n; + } puints_t; + + /* Same thing as puints_t, but make it complex (needs padding). */ + typedef struct + { + [size_is(n)] puint_t *ps; + char n; + } cpuints_t; + + int sum_puints(puints_t *p); + int sum_cpuints(cpuints_t *p); + int dot_copy_vectors(vector_t u, vector_t v); + + typedef struct wire_us *wire_us_t; + typedef [wire_marshal(wire_us_t)] struct us us_t; + struct us + { + void *x; + }; + struct wire_us + { + int x; + }; + typedef struct + { + us_t us; + } test_us_t; + + int square_test_us(test_us_t *tus); + + typedef union encu switch (int t) + { + case ENCU_I: int i; + case ENCU_F: float f; + } encu_t; + + typedef enum + { + E1 = 23, + E2 = 4, + E3 = 0, + E4 = 64 + } e_t; + + typedef union encue switch (e_t t) + { + case E1: int i1; + case E2: float f2; + } encue_t; + + double square_encu(encu_t *eu); + int sum_parr(int *a[3]); + int sum_pcarr([size_is(n)] int *a[], int n); + int enum_ord(e_t e); + double square_encue(encue_t *eue); + + int sum_toplev_conf_2n([size_is(n * 2)] int *x, int n); + int sum_toplev_conf_cond([size_is(c ? a : b)] int *x, int a, int b, int c); + + typedef struct + { + char c; + int i; + short s; + double d; + } aligns_t; + + double sum_aligns(aligns_t *a); + + typedef struct + { + int i; + char c; + } padded_t; + + int sum_padded(padded_t *p); + int sum_padded2(padded_t ps[2]); + int sum_padded_conf([size_is(n)] padded_t *ps, int n); + + typedef struct + { + int *p1; + } bogus_helper_t; + + typedef struct + { + bogus_helper_t h; + int *p2; + int *p3; + char c; + } bogus_t; + + int sum_bogus(bogus_t *b); + void check_null([unique] int *null); + + typedef struct + { + str_t s; + } str_struct_t; + + typedef struct + { + wstr_t s; + } wstr_struct_t; + + int str_struct_len(str_struct_t *s); + int wstr_struct_len(wstr_struct_t *s); + + typedef struct + { + unsigned int n; + [size_is(n)] byte a[]; + } doub_carr_1_t; + + typedef struct + { + int n; + [size_is(n)] doub_carr_1_t *a[]; + } doub_carr_t; + + int sum_doub_carr(doub_carr_t *dc); + void make_pyramid_doub_carr(unsigned char n, [out] doub_carr_t **dc); + + typedef struct + { + short n; + [size_is(n)] short data[]; + } wire_bstr_t; + + typedef [wire_marshal(wire_bstr_t)] short *bstr_t; + unsigned hash_bstr(bstr_t s); + + typedef struct + { + [string, size_is(size)] char *name; + unsigned int size; + } name_t; + void get_name([in,out] name_t *name); + + int sum_pcarr2(int n, [size_is(, n)] int **pa); + int sum_L1_norms(int n, [size_is(n)] vector_t *vs); + + void get_5numbers([in] int count, [out, length_is(count)] pints_t pn[5]); + void get_numbers([in] int length, [in] int size, [out, length_is(length), size_is(size)] pints_t pn[]); + str_t get_filename(void); + void context_handle_test(void); + void stop(void); +} diff --git a/rostests/winetests/rpcrt4/server_defines.h b/rostests/winetests/rpcrt4/server_defines.h new file mode 100644 index 00000000000..51f934f2488 --- /dev/null +++ b/rostests/winetests/rpcrt4/server_defines.h @@ -0,0 +1,33 @@ +/* + * Constants shared between server.c and server.idl + * + * Copyright (C) Google 2007 (Dan Hipschman) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* sun_t case values */ +#define SUN_I 10 +#define SUN_F1 -2 +#define SUN_F2 7 +#define SUN_PI 399 + +/* test_list_t case values */ +#define TL_NULL 0 +#define TL_LIST 1 + +/* encu_t case values */ +#define ENCU_I 27 +#define ENCU_F 0 diff --git a/rostests/winetests/rpcrt4/testlist.c b/rostests/winetests/rpcrt4/testlist.c new file mode 100644 index 00000000000..3a7fecf1fdc --- /dev/null +++ b/rostests/winetests/rpcrt4/testlist.c @@ -0,0 +1,23 @@ +/* Automatically generated file; DO NOT EDIT!! */ + +#define WIN32_LEAN_AND_MEAN +#include + +#define STANDALONE +#include "wine/test.h" + +extern void func_cstub(void); +extern void func_generated(void); +extern void func_ndr_marshall(void); +extern void func_rpc(void); +extern void func_server(void); + +const struct test winetest_testlist[] = +{ + { "cstub", func_cstub }, + { "generated", func_generated }, + { "ndr_marshall", func_ndr_marshall }, + { "rpc", func_rpc }, + { "server", func_server }, + { 0, 0 } +};