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 }
+};