If explicit_handle is defined in the *.idl file, c/s are uses explicit handles, then an explicit handle must be passed in to the server-side interface
Add a test for explicit_handle.
v3.
From: Haoyang Chen chenhaoyang@kylinos.cn
If explicit_handle is defined in the *.idl file, c/s are uses explicit handles, then an explicit handle must be passed in to the server-side interface --- dlls/rpcrt4/ndr_stubless.c | 63 +++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 28 deletions(-)
diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c index 80cd0bbcb89..7aa2f79d10b 100644 --- a/dlls/rpcrt4/ndr_stubless.c +++ b/dlls/rpcrt4/ndr_stubless.c @@ -1365,6 +1365,32 @@ LONG WINAPI NdrStubCall2(
TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
+ if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) + NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); + else + NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); + + /* create the full pointer translation tables, if requested */ + if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) + stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); + + /* store the RPC flags away */ + if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) + pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; + + /* use alternate memory allocation routines */ + if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) +#if 0 + NdrRpcSsEnableAllocate(&stubMsg); +#else + FIXME("Set RPCSS memory allocation routines\n"); +#endif + + TRACE("allocating memory for stack of size %x\n", stack_size); + + args = calloc(1, stack_size); + stubMsg.StackTop = args; /* used by conformance of top-level objects */ + /* binding */ switch (pProcHeader->handle_type) { @@ -1373,8 +1399,15 @@ LONG WINAPI NdrStubCall2( switch (*pFormat) /* handle_type */ { case FC_BIND_PRIMITIVE: /* explicit primitive */ - pFormat += sizeof(NDR_EHD_PRIMITIVE); - break; + { + const NDR_EHD_PRIMITIVE *pDesc = (const NDR_EHD_PRIMITIVE *)pFormat; + if (pDesc->flag) + **(handle_t **)ARG_FROM_OFFSET(stubMsg.StackTop, pDesc->offset) = pRpcMsg->Handle; + else + *(handle_t *)ARG_FROM_OFFSET(stubMsg.StackTop, pDesc->offset) = pRpcMsg->Handle; + pFormat += sizeof(NDR_EHD_PRIMITIVE); + break; + } case FC_BIND_GENERIC: /* explicit generic */ pFormat += sizeof(NDR_EHD_GENERIC); break; @@ -1396,32 +1429,6 @@ LONG WINAPI NdrStubCall2( RpcRaiseException(RPC_X_BAD_STUB_DATA); }
- if (pProcHeader->Oi_flags & Oi_OBJECT_PROC) - NdrStubInitialize(pRpcMsg, &stubMsg, pStubDesc, pChannel); - else - NdrServerInitializeNew(pRpcMsg, &stubMsg, pStubDesc); - - /* create the full pointer translation tables, if requested */ - if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED) - stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_SERVER); - - /* store the RPC flags away */ - if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS) - pRpcMsg->RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags; - - /* use alternate memory allocation routines */ - if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED) -#if 0 - NdrRpcSsEnableAllocate(&stubMsg); -#else - FIXME("Set RPCSS memory allocation routines\n"); -#endif - - TRACE("allocating memory for stack of size %x\n", stack_size); - - args = calloc(1, stack_size); - stubMsg.StackTop = args; /* used by conformance of top-level objects */ - /* add the implicit This pointer as the first arg to the function if we * are calling an object method */ if (pThis)
From: Haoyang Chen chenhaoyang@kylinos.cn
--- dlls/rpcrt4/tests/Makefile.in | 1 + dlls/rpcrt4/tests/explicit_handle.idl | 32 ++++++++++ dlls/rpcrt4/tests/server.c | 87 +++++++++++++++++++++++++++ 3 files changed, 120 insertions(+) create mode 100644 dlls/rpcrt4/tests/explicit_handle.idl
diff --git a/dlls/rpcrt4/tests/Makefile.in b/dlls/rpcrt4/tests/Makefile.in index f46ff49219a..0e888069783 100644 --- a/dlls/rpcrt4/tests/Makefile.in +++ b/dlls/rpcrt4/tests/Makefile.in @@ -9,6 +9,7 @@ server_interp_EXTRAIDLFLAGS = -Oicf --prefix-client=interp_ SOURCES = \ cstub.c \ cstub.idl \ + explicit_handle.idl \ generated.c \ ndr_marshall.c \ rpc.c \ diff --git a/dlls/rpcrt4/tests/explicit_handle.idl b/dlls/rpcrt4/tests/explicit_handle.idl new file mode 100644 index 00000000000..ab41f771fe7 --- /dev/null +++ b/dlls/rpcrt4/tests/explicit_handle.idl @@ -0,0 +1,32 @@ +/* + * Copyright 2023 Haoyang Chen + * + * 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 + */ + +#pragma makedep client +#pragma makedep server + +[ + uuid(00000000-4114-0704-2301-000000000002), + explicit_handle +] + +interface RPCExplicitHandle +{ + int add([in] handle_t hBinding, [in] int a, [in] int b); + int getNum([in] int a, [in] handle_t hBinding); + void Shutdown([in] handle_t hBinding); +} diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c index 8e87a468f86..93934da8097 100644 --- a/dlls/rpcrt4/tests/server.c +++ b/dlls/rpcrt4/tests/server.c @@ -30,6 +30,7 @@ #define SKIP_TYPE_DECLS #include "server_interp.h" #include "server_defines.h" +#include "explicit_handle.h"
#include <stddef.h> #include <stdio.h> @@ -1202,6 +1203,30 @@ void __cdecl s_test_I_RpcBindingInqLocalClientPID(unsigned int protseq, RPC_BIND winetest_pop_context(); }
+int __cdecl s_add(handle_t binding, int a, int b) +{ + ok(binding != NULL, "explicit handle is NULL\n"); + return a + b; +} + +int __cdecl s_getNum(int a, handle_t binding) +{ + ok(binding != NULL, "explicit handle is NULL\n"); + return a + 2; +} + +void __cdecl s_Shutdown(handle_t binding) +{ + RPC_STATUS status; + ULONG pid = 0; + ok(binding != NULL, "explicit handle is NULL\n"); + + status = I_RpcBindingInqLocalClientPID(binding, &pid); + ok(status == RPC_S_OK, "Got unexpected %ld.\n", status); + ok(pid == client_info.dwProcessId, "Got unexpected pid: %ld client pid: %ld.\n", pid, client_info.dwProcessId); + ok(SetEvent(stop_event), "SetEvent\n"); +} + void __RPC_USER ctx_handle_t_rundown(ctx_handle_t ctx_handle) { ok(ctx_handle == (ctx_handle_t)0xdeadbeef, "Unexpected ctx_handle %p\n", ctx_handle); @@ -2034,6 +2059,7 @@ client(const char *test) static unsigned char port[] = PORT; static unsigned char pipe[] = PIPE; static unsigned char guid[] = "00000000-4114-0704-2301-000000000000"; + static unsigned char explicit_handle_guid[] = "00000000-4114-0704-2301-000000000002";
unsigned char *binding;
@@ -2138,6 +2164,21 @@ client(const char *test) ok(RPC_S_OK == RpcStringFreeA(&binding), "RpcStringFree\n"); ok(RPC_S_OK == RpcBindingFree(&IInterpServer_IfHandle), "RpcBindingFree\n"); } + else if (strcmp(test, "explicit_handle") == 0) + { + IMixedServer_IfHandle = NULL; + ok(RPC_S_OK == RpcStringBindingComposeA(NULL, ncalrpc, NULL, explicit_handle_guid, NULL, &binding), "RpcStringBindingCompose\n"); + ok(RPC_S_OK == RpcBindingFromStringBindingA(binding, &IMixedServer_IfHandle), "RpcBindingFromStringBinding\n"); + + test_is_server_listening(IMixedServer_IfHandle, RPC_S_OK); + + ok(add(IMixedServer_IfHandle, 2, 3) == 5, "RPC add\n"); + ok(getNum(7, IMixedServer_IfHandle) == 9, "RPC getNum\n"); + Shutdown(IMixedServer_IfHandle); + + ok(RPC_S_OK == RpcStringFreeA(&binding), "RpcStringFree\n"); + ok(RPC_S_OK == RpcBindingFree(&IMixedServer_IfHandle), "RpcBindingFree\n"); + } }
static void @@ -2149,6 +2190,7 @@ server(void) static unsigned char pipe[] = PIPE; static unsigned char ncalrpc[] = "ncalrpc"; static unsigned char guid[] = "00000000-4114-0704-2301-000000000000"; + static unsigned char explicit_handle_guid[] = "00000000-4114-0704-2301-000000000002"; RPC_STATUS status, iptcp_status, np_status, ncalrpc_status; DWORD ret;
@@ -2247,6 +2289,51 @@ server(void) ok(status == RPC_S_OK, "RpcServerUnregisterIf() failed: %lu\n", status); }
+ /* explicit handle */ + stop_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(stop_event != NULL, "CreateEvent failed with error %ld\n", GetLastError()); + + ncalrpc_status = RpcServerUseProtseqEpA(ncalrpc, 0, explicit_handle_guid, NULL); + if (ncalrpc_status == RPC_S_PROTSEQ_NOT_SUPPORTED) + skip("Protocol sequence ncacn_np is not supported\n"); + else + ok(ncalrpc_status == RPC_S_OK, "RpcServerUseProtseqEp(ncacn_np) failed with status %ld\n", ncalrpc_status); + + if (pRpcServerRegisterIfEx) + { + trace("Using RpcServerRegisterIfEx\n"); + status = pRpcServerRegisterIfEx(s_RPCExplicitHandle_v0_0_s_ifspec, NULL, NULL, + RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH, + RPC_C_LISTEN_MAX_CALLS_DEFAULT, NULL); + ok(status == RPC_S_OK, "RpcServerRegisterIfEx failed with status %ld\n", status); + test_is_server_listening(NULL, RPC_S_NOT_LISTENING); + status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); + ok(status == RPC_S_OK, "RpcServerListen failed with status %ld\n", status); + } + else + { + status = RpcServerRegisterIf(s_RPCExplicitHandle_v0_0_s_ifspec, NULL, NULL); + ok(status == RPC_S_OK, "RpcServerRegisterIf failed with status %ld\n", status); + status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); + ok(status == RPC_S_OK, "RpcServerListen failed with status %ld\n", status); + } + + test_is_server_listening(NULL, RPC_S_OK); + + run_client("explicit_handle"); + + ret = WaitForSingleObject(stop_event, 1000); + ok(WAIT_OBJECT_0 == ret, "WaitForSingleObject\n"); + + if (pRpcServerRegisterIfEx) + { + status = RpcServerUnregisterIf(s_RPCExplicitHandle_v0_0_s_ifspec, NULL, TRUE); + ok(status == RPC_S_OK, "RpcServerUnregisterIf() failed: %lu\n", status); + } + + CloseHandle(stop_event); + stop_event = NULL; + CoUninitialize(); }
Hi,
Is there any reason to create a new MR instead of pushing the newser version of the patchset to an existing MR (MR !4386 and MR !4451)? If there isn't any special issue, I think we would prefer to try to maintain all the discussions about it in a single thread, so that we can track its context.
On Wed Nov 22 07:05:57 2023 +0000, Jactry Zeng wrote:
Hi, Is there any reason to create a new MR instead of pushing the newser version of the patchset to an existing MR (MR !4386 and MR !4451)? If there isn't any special issue, I think we would prefer to try to maintain all the discussions about it in a single thread, so that we can track its context.
Sorry, I just switched to gitlab. I wasn't aware of the need to save a MR thread. I will check it out.
This merge request was approved by Zebediah Figura.
This merge request was approved by Huw Davies.