[PATCH 4/5] rpcrt4: Handle exceptions in a larger portion of NdrClientCall().

Zebediah Figura z.figura12 at gmail.com
Mon May 20 23:30:55 CDT 2019


Most notably in NdrProxyInitialize().

This patch and the next bring the scope of exception handling roughly in line
with -Os stubs.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=36981
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/rpcrt4/ndr_stubless.c | 445 +++++++++++++++++--------------------
 1 file changed, 199 insertions(+), 246 deletions(-)

diff --git a/dlls/rpcrt4/ndr_stubless.c b/dlls/rpcrt4/ndr_stubless.c
index 816af4b39a..c0f026076e 100644
--- a/dlls/rpcrt4/ndr_stubless.c
+++ b/dlls/rpcrt4/ndr_stubless.c
@@ -657,13 +657,170 @@ PFORMAT_STRING convert_old_args( PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFo
     return (PFORMAT_STRING)args;
 }
 
+/* Helper for ndr_client_call, to factor out the part that may or may not be
+ * guarded by a try/except block. */
+static LONG_PTR do_ndr_client_call( const MIDL_STUB_DESC *stub_desc, const PFORMAT_STRING format,
+        const PFORMAT_STRING handle_format, void **stack_top, void **fpu_stack, MIDL_STUB_MESSAGE *stub_msg,
+        unsigned short procedure_number, unsigned short stack_size, unsigned int number_of_params,
+        INTERPRETER_OPT_FLAGS Oif_flags, INTERPRETER_OPT_FLAGS2 ext_flags, const NDR_PROC_HEADER *proc_header )
+{
+    RPC_MESSAGE rpc_msg;
+    handle_t hbinding = NULL;
+    /* the value to return to the client from the remote procedure */
+    LONG_PTR retval = 0;
+    /* the pointer to the object when in OLE mode */
+    void *This = NULL;
+    /* correlation cache */
+    ULONG_PTR NdrCorrCache[256];
+
+    /* create the full pointer translation tables, if requested */
+    if (proc_header->Oi_flags & Oi_FULL_PTR_USED)
+        stub_msg->FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
+
+    if (proc_header->Oi_flags & Oi_OBJECT_PROC)
+    {
+        /* object is always the first argument */
+        This = stack_top[0];
+        NdrProxyInitialize(This, &rpc_msg, stub_msg, stub_desc, procedure_number);
+    }
+    else
+        NdrClientInitializeNew(&rpc_msg, stub_msg, stub_desc, procedure_number);
+
+    stub_msg->StackTop = (unsigned char *)stack_top;
+
+    /* we only need a handle if this isn't an object method */
+    if (!(proc_header->Oi_flags & Oi_OBJECT_PROC))
+    {
+        hbinding = client_get_handle(stub_msg, proc_header, handle_format);
+        if (!hbinding) return 0;
+    }
+
+    stub_msg->BufferLength = 0;
+
+    /* store the RPC flags away */
+    if (proc_header->Oi_flags & Oi_HAS_RPCFLAGS)
+        rpc_msg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)proc_header)->rpc_flags;
+
+    /* use alternate memory allocation routines */
+    if (proc_header->Oi_flags & Oi_RPCSS_ALLOC_USED)
+        NdrRpcSmSetClientToOsf(stub_msg);
+
+    if (Oif_flags.HasPipes)
+    {
+        FIXME("pipes not supported yet\n");
+        RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
+        /* init pipes package */
+        /* NdrPipesInitialize(...) */
+    }
+    if (ext_flags.HasNewCorrDesc)
+    {
+        /* initialize extra correlation package */
+        NdrCorrelationInitialize(stub_msg, NdrCorrCache, sizeof(NdrCorrCache), 0);
+        if (ext_flags.Unused & 0x2) /* has range on conformance */
+            stub_msg->CorrDespIncrement = 12;
+    }
+
+    /* order of phases:
+     * 1. INITOUT - zero [out] parameters (proxies only)
+     * 2. CALCSIZE - calculate the buffer size
+     * 3. GETBUFFER - allocate the buffer
+     * 4. MARSHAL - marshal [in] params into the buffer
+     * 5. SENDRECEIVE - send/receive buffer
+     * 6. UNMARSHAL - unmarshal [out] params from buffer
+     * 7. FREE - clear [out] parameters (for proxies, and only on error)
+     */
+
+    /* 1. INITOUT */
+    if (proc_header->Oi_flags & Oi_OBJECT_PROC)
+    {
+        TRACE( "INITOUT\n" );
+        client_do_args(stub_msg, format, STUBLESS_INITOUT, fpu_stack,
+                       number_of_params, (unsigned char *)&retval);
+    }
+
+    /* 2. CALCSIZE */
+    TRACE( "CALCSIZE\n" );
+    client_do_args(stub_msg, format, STUBLESS_CALCSIZE, fpu_stack,
+                   number_of_params, (unsigned char *)&retval);
+
+    /* 3. GETBUFFER */
+    TRACE( "GETBUFFER\n" );
+    if (proc_header->Oi_flags & Oi_OBJECT_PROC)
+        NdrProxyGetBuffer(This, stub_msg);
+    else if (Oif_flags.HasPipes)
+        FIXME("pipes not supported yet\n");
+    else if (proc_header->handle_type == FC_AUTO_HANDLE)
+#if 0
+        NdrNsGetBuffer(stub_msg, stub_msg->BufferLength, hBinding);
+#else
+        FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
+#endif
+    else
+        NdrGetBuffer(stub_msg, stub_msg->BufferLength, hbinding);
+
+    /* 4. MARSHAL */
+    TRACE( "MARSHAL\n" );
+    client_do_args(stub_msg, format, STUBLESS_MARSHAL, fpu_stack,
+                   number_of_params, (unsigned char *)&retval);
+
+    /* 5. SENDRECEIVE */
+    TRACE( "SENDRECEIVE\n" );
+    if (proc_header->Oi_flags & Oi_OBJECT_PROC)
+        NdrProxySendReceive(This, stub_msg);
+    else if (Oif_flags.HasPipes)
+        /* NdrPipesSendReceive(...) */
+        FIXME("pipes not supported yet\n");
+    else if (proc_header->handle_type == FC_AUTO_HANDLE)
+#if 0
+        NdrNsSendReceive(stub_msg, stub_msg->Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
+#else
+        FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
+#endif
+    else
+        NdrSendReceive(stub_msg, stub_msg->Buffer);
+
+    /* convert strings, floating point values and endianness into our
+     * preferred format */
+    if ((rpc_msg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
+        NdrConvert(stub_msg, format);
+
+    /* 6. UNMARSHAL */
+    TRACE( "UNMARSHAL\n" );
+    client_do_args(stub_msg, format, STUBLESS_UNMARSHAL, fpu_stack,
+                   number_of_params, (unsigned char *)&retval);
+
+    if (ext_flags.HasNewCorrDesc)
+    {
+        /* free extra correlation package */
+        NdrCorrelationFree(stub_msg);
+    }
+
+    if (Oif_flags.HasPipes)
+    {
+        /* NdrPipesDone(...) */
+    }
+
+    /* free the full pointer translation tables */
+    if (proc_header->Oi_flags & Oi_FULL_PTR_USED)
+        NdrFullPointerXlatFree(stub_msg->FullPtrXlatTables);
+
+    /* free marshalling buffer */
+    if (proc_header->Oi_flags & Oi_OBJECT_PROC)
+        NdrProxyFreeBuffer(This, stub_msg);
+    else
+    {
+        NdrFreeBuffer(stub_msg);
+        client_free_handle(stub_msg, proc_header, handle_format, hbinding);
+    }
+
+    return retval;
+}
+
 LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORMAT_STRING pFormat,
                                                 void **stack_top, void **fpu_stack )
 {
     /* pointer to start of stack where arguments start */
-    RPC_MESSAGE rpcMsg;
     MIDL_STUB_MESSAGE stubMsg;
-    handle_t hBinding = NULL;
     /* procedure number */
     unsigned short procedure_number;
     /* size of stack */
@@ -678,11 +835,8 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORM
     const NDR_PROC_HEADER * pProcHeader = (const NDR_PROC_HEADER *)&pFormat[0];
     /* the value to return to the client from the remote procedure */
     LONG_PTR RetVal = 0;
-    /* the pointer to the object when in OLE mode */
-    void * This = NULL;
     PFORMAT_STRING pHandleFormat;
-    /* correlation cache */
-    ULONG_PTR NdrCorrCache[256];
+    NDR_PARAM_OIF old_args[256];
 
     TRACE("pStubDesc %p, pFormat %p, ...\n", pStubDesc, pFormat);
 
@@ -703,33 +857,14 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORM
     }
     TRACE("stack size: 0x%x\n", stack_size);
     TRACE("proc num: %d\n", procedure_number);
-
-    /* create the full pointer translation tables, if requested */
-    if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
-        stubMsg.FullPtrXlatTables = NdrFullPointerXlatInit(0,XLAT_CLIENT);
-
-    if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
-    {
-        /* object is always the first argument */
-        This = stack_top[0];
-        NdrProxyInitialize(This, &rpcMsg, &stubMsg, pStubDesc, procedure_number);
-    }
-    else
-        NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDesc, procedure_number);
-
     TRACE("Oi_flags = 0x%02x\n", pProcHeader->Oi_flags);
     TRACE("MIDL stub version = 0x%x\n", pStubDesc->MIDLVersion);
 
-    stubMsg.StackTop = (unsigned char *)stack_top;
     pHandleFormat = pFormat;
 
     /* we only need a handle if this isn't an object method */
     if (!(pProcHeader->Oi_flags & Oi_OBJECT_PROC))
-    {
         pFormat += get_handle_desc_size(pProcHeader, pFormat);
-        hBinding = client_get_handle(&stubMsg, pProcHeader, pHandleFormat);
-        if (!hBinding) goto done;
-    }
 
     if (is_oicf_stubdesc(pStubDesc))  /* -Oicf format */
     {
@@ -767,251 +902,69 @@ LONG_PTR CDECL DECLSPEC_HIDDEN ndr_client_call( PMIDL_STUB_DESC pStubDesc, PFORM
     {
         pFormat = convert_old_args( &stubMsg, pFormat, stack_size,
                                     pProcHeader->Oi_flags & Oi_OBJECT_PROC,
-                                    /* reuse the correlation cache, it's not needed for v1 format */
-                                    NdrCorrCache, sizeof(NdrCorrCache), &number_of_params );
-    }
-
-    stubMsg.BufferLength = 0;
-
-    /* store the RPC flags away */
-    if (pProcHeader->Oi_flags & Oi_HAS_RPCFLAGS)
-        rpcMsg.RpcFlags = ((const NDR_PROC_HEADER_RPC *)pProcHeader)->rpc_flags;
-
-    /* use alternate memory allocation routines */
-    if (pProcHeader->Oi_flags & Oi_RPCSS_ALLOC_USED)
-        NdrRpcSmSetClientToOsf(&stubMsg);
-
-    if (Oif_flags.HasPipes)
-    {
-        FIXME("pipes not supported yet\n");
-        RpcRaiseException(RPC_X_WRONG_STUB_VERSION); /* FIXME: remove when implemented */
-        /* init pipes package */
-        /* NdrPipesInitialize(...) */
-    }
-    if (ext_flags.HasNewCorrDesc)
-    {
-        /* initialize extra correlation package */
-        NdrCorrelationInitialize(&stubMsg, NdrCorrCache, sizeof(NdrCorrCache), 0);
-        if (ext_flags.Unused & 0x2) /* has range on conformance */
-            stubMsg.CorrDespIncrement = 12;
+                                    old_args, sizeof(old_args), &number_of_params );
     }
 
-    /* order of phases:
-     * 1. INITOUT - zero [out] parameters (proxies only)
-     * 2. CALCSIZE - calculate the buffer size
-     * 3. GETBUFFER - allocate the buffer
-     * 4. MARSHAL - marshal [in] params into the buffer
-     * 5. SENDRECEIVE - send/receive buffer
-     * 6. UNMARSHAL - unmarshal [out] params from buffer
-     * 7. FREE - clear [out] parameters (for proxies, and only on error)
-     */
-    if ((pProcHeader->Oi_flags & Oi_OBJECT_PROC) ||
-        (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT))
+    if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
     {
-        /* 1. INITOUT */
-        if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
-        {
-            TRACE( "INITOUT\n" );
-            client_do_args(&stubMsg, pFormat, STUBLESS_INITOUT, fpu_stack,
-                           number_of_params, (unsigned char *)&RetVal);
-        }
-
         __TRY
         {
-            /* 2. CALCSIZE */
-            TRACE( "CALCSIZE\n" );
-            client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack,
-                           number_of_params, (unsigned char *)&RetVal);
-
-            /* 3. GETBUFFER */
-            TRACE( "GETBUFFER\n" );
-            if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
-            {
-                /* allocate the buffer */
-                NdrProxyGetBuffer(This, &stubMsg);
-            }
-            else
-            {
-                /* allocate the buffer */
-                if (Oif_flags.HasPipes)
-                    /* NdrGetPipeBuffer(...) */
-                    FIXME("pipes not supported yet\n");
-                else
-                {
-                    if (pProcHeader->handle_type == FC_AUTO_HANDLE)
-#if 0
-                        NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
-#else
-                    FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
-#endif
-                    else
-                        NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
-                }
-            }
-
-            /* 4. MARSHAL */
-            TRACE( "MARSHAL\n" );
-            client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack,
-                           number_of_params, (unsigned char *)&RetVal);
-
-            /* 5. SENDRECEIVE */
-            TRACE( "SENDRECEIVE\n" );
-            if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
-            {
-                /* send the [in] params and receive the [out] and [retval]
-                 * params */
-                NdrProxySendReceive(This, &stubMsg);
-            }
-            else
-            {
-                /* send the [in] params and receive the [out] and [retval]
-                 * params */
-                if (Oif_flags.HasPipes)
-                    /* NdrPipesSendReceive(...) */
-                    FIXME("pipes not supported yet\n");
-                else
-                {
-                    if (pProcHeader->handle_type == FC_AUTO_HANDLE)
-#if 0
-                        NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
-#else
-                    FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
-#endif
-                    else
-                        NdrSendReceive(&stubMsg, stubMsg.Buffer);
-                }
-            }
-
-            /* convert strings, floating point values and endianness into our
-             * preferred format */
-            if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
-                NdrConvert(&stubMsg, pFormat);
-
-            /* 6. UNMARSHAL */
-            TRACE( "UNMARSHAL\n" );
-            client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack,
-                           number_of_params, (unsigned char *)&RetVal);
+            RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat,
+                    stack_top, fpu_stack, &stubMsg, procedure_number, stack_size,
+                    number_of_params, Oif_flags, ext_flags, pProcHeader);
         }
         __EXCEPT_ALL
         {
-            if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
-            {
-                /* 7. FREE */
-                TRACE( "FREE\n" );
-                client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack,
-                               number_of_params, (unsigned char *)&RetVal);
-                RetVal = NdrProxyErrorHandler(GetExceptionCode());
-            }
-            else
-            {
-                const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number];
-                ULONG *comm_status;
-                ULONG *fault_status;
-
-                TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset);
-
-                if (comm_fault_offsets->CommOffset == -1)
-                    comm_status = (ULONG *)&RetVal;
-                else if (comm_fault_offsets->CommOffset >= 0)
-                    comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
-                else
-                    comm_status = NULL;
-
-                if (comm_fault_offsets->FaultOffset == -1)
-                    fault_status = (ULONG *)&RetVal;
-                else if (comm_fault_offsets->FaultOffset >= 0)
-                    fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->FaultOffset);
-                else
-                    fault_status = NULL;
-
-                NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status,
-                                         GetExceptionCode());
-            }
+            /* 7. FREE */
+            TRACE( "FREE\n" );
+            client_do_args(&stubMsg, pFormat, STUBLESS_FREE, fpu_stack,
+                           number_of_params, (unsigned char *)&RetVal);
+            RetVal = NdrProxyErrorHandler(GetExceptionCode());
         }
         __ENDTRY
     }
-    else
+    else if (pProcHeader->Oi_flags & Oi_HAS_COMM_OR_FAULT)
     {
-        /* 2. CALCSIZE */
-        TRACE( "CALCSIZE\n" );
-        client_do_args(&stubMsg, pFormat, STUBLESS_CALCSIZE, fpu_stack,
-                       number_of_params, (unsigned char *)&RetVal);
-
-        /* 3. GETBUFFER */
-        TRACE( "GETBUFFER\n" );
-        if (Oif_flags.HasPipes)
-            /* NdrGetPipeBuffer(...) */
-            FIXME("pipes not supported yet\n");
-        else
+        __TRY
         {
-            if (pProcHeader->handle_type == FC_AUTO_HANDLE)
-#if 0
-                NdrNsGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
-#else
-            FIXME("using auto handle - call NdrNsGetBuffer when it gets implemented\n");
-#endif
-            else
-                NdrGetBuffer(&stubMsg, stubMsg.BufferLength, hBinding);
+            RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat,
+                    stack_top, fpu_stack, &stubMsg, procedure_number, stack_size,
+                    number_of_params, Oif_flags, ext_flags, pProcHeader);
         }
-
-        /* 4. MARSHAL */
-        TRACE( "MARSHAL\n" );
-        client_do_args(&stubMsg, pFormat, STUBLESS_MARSHAL, fpu_stack,
-                       number_of_params, (unsigned char *)&RetVal);
-
-        /* 5. SENDRECEIVE */
-        TRACE( "SENDRECEIVE\n" );
-        if (Oif_flags.HasPipes)
-            /* NdrPipesSendReceive(...) */
-            FIXME("pipes not supported yet\n");
-        else
+        __EXCEPT_ALL
         {
-            if (pProcHeader->handle_type == FC_AUTO_HANDLE)
-#if 0
-                NdrNsSendReceive(&stubMsg, stubMsg.Buffer, pStubDesc->IMPLICIT_HANDLE_INFO.pAutoHandle);
-#else
-            FIXME("using auto handle - call NdrNsSendReceive when it gets implemented\n");
-#endif
-            else
-                NdrSendReceive(&stubMsg, stubMsg.Buffer);
-        }
+            const COMM_FAULT_OFFSETS *comm_fault_offsets = &pStubDesc->CommFaultOffsets[procedure_number];
+            ULONG *comm_status;
+            ULONG *fault_status;
 
-        /* convert strings, floating point values and endianness into our
-         * preferred format */
-        if ((rpcMsg.DataRepresentation & 0x0000FFFFUL) != NDR_LOCAL_DATA_REPRESENTATION)
-            NdrConvert(&stubMsg, pFormat);
+            TRACE("comm_fault_offsets = {0x%hx, 0x%hx}\n", comm_fault_offsets->CommOffset, comm_fault_offsets->FaultOffset);
 
-        /* 6. UNMARSHAL */
-        TRACE( "UNMARSHAL\n" );
-        client_do_args(&stubMsg, pFormat, STUBLESS_UNMARSHAL, fpu_stack,
-                       number_of_params, (unsigned char *)&RetVal);
-    }
+            if (comm_fault_offsets->CommOffset == -1)
+                comm_status = (ULONG *)&RetVal;
+            else if (comm_fault_offsets->CommOffset >= 0)
+                comm_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->CommOffset);
+            else
+                comm_status = NULL;
 
-    if (ext_flags.HasNewCorrDesc)
-    {
-        /* free extra correlation package */
-        NdrCorrelationFree(&stubMsg);
-    }
+            if (comm_fault_offsets->FaultOffset == -1)
+                fault_status = (ULONG *)&RetVal;
+            else if (comm_fault_offsets->FaultOffset >= 0)
+                fault_status = *(ULONG **)ARG_FROM_OFFSET(stubMsg.StackTop, comm_fault_offsets->FaultOffset);
+            else
+                fault_status = NULL;
 
-    if (Oif_flags.HasPipes)
-    {
-        /* NdrPipesDone(...) */
+            NdrMapCommAndFaultStatus(&stubMsg, comm_status, fault_status,
+                                     GetExceptionCode());
+        }
+        __ENDTRY
     }
-
-    /* free the full pointer translation tables */
-    if (pProcHeader->Oi_flags & Oi_FULL_PTR_USED)
-        NdrFullPointerXlatFree(stubMsg.FullPtrXlatTables);
-
-    /* free marshalling buffer */
-    if (pProcHeader->Oi_flags & Oi_OBJECT_PROC)
-        NdrProxyFreeBuffer(This, &stubMsg);
     else
     {
-        NdrFreeBuffer(&stubMsg);
-        client_free_handle(&stubMsg, pProcHeader, pHandleFormat, hBinding);
+        RetVal = do_ndr_client_call(pStubDesc, pFormat, pHandleFormat,
+                stack_top, fpu_stack, &stubMsg, procedure_number, stack_size,
+                number_of_params, Oif_flags, ext_flags, pProcHeader);
     }
 
-done:
     TRACE("RetVal = 0x%lx\n", RetVal);
     return RetVal;
 }
-- 
2.21.0




More information about the wine-devel mailing list