rpc exception patch

Ove Kaaven ovek at arcticnet.no
Wed May 21 15:07:49 CDT 2003


I've encountered an installer that needed this...

This is the last rpcrt4 update for now, I guess it's finally time to
start looking at chopping up my ole32 work for submission.

Log:
Ove Kaaven <ovek at transgaming.com>
Initial support for RPC call failures, by catching RPC server exceptions
and returning simple failure packets, and throwing exceptions on the
client side when unmarshalling the failure packet.

? dlls/rpcrt4/rpc_misc.h
Index: dlls/rpcrt4/ndr_midl.c
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/ndr_midl.c,v
retrieving revision 1.13
diff -u -r1.13 ndr_midl.c
--- dlls/rpcrt4/ndr_midl.c	21 May 2003 18:22:49 -0000	1.13
+++ dlls/rpcrt4/ndr_midl.c	21 May 2003 19:56:57 -0000
@@ -106,6 +106,10 @@
   pStubMsg->BufferStart = pStubMsg->RpcMsg->Buffer;
   pStubMsg->BufferEnd = pStubMsg->BufferStart + pStubMsg->BufferLength;
   pStubMsg->Buffer = pStubMsg->BufferStart;
+
+  /* raise exception if call failed */
+  if (hr == RPC_S_CALL_FAILED) RpcRaiseException(*(DWORD*)pStubMsg->Buffer);
+  else if (FAILED(hr)) RpcRaiseException(hr);
 }
 
 /***********************************************************************
Index: dlls/rpcrt4/rpc_message.c
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpc_message.c,v
retrieving revision 1.6
diff -u -r1.6 rpc_message.c
--- dlls/rpcrt4/rpc_message.c	21 May 2003 18:23:06 -0000	1.6
+++ dlls/rpcrt4/rpc_message.c	21 May 2003 19:56:57 -0000
@@ -37,6 +37,7 @@
 #include "wine/debug.h"
 
 #include "rpc_binding.h"
+#include "rpc_misc.h"
 #include "rpc_defs.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(ole);
@@ -111,7 +112,9 @@
   /* initialize packet header */
   memset(&hdr, 0, sizeof(hdr));
   hdr.rpc_ver = 4;
-  hdr.ptype = bind->server ? PKT_RESPONSE : PKT_REQUEST;
+  hdr.ptype = bind->server
+              ? ((pMsg->RpcFlags & WINE_RPCFLAG_EXCEPTION) ? PKT_FAULT : PKT_RESPONSE)
+              : PKT_REQUEST;
   hdr.object = *obj; /* FIXME: IIRC iff no object, the header structure excludes this elt */
   hdr.if_id = (bind->server) ? sif->InterfaceId.SyntaxGUID : cif->InterfaceId.SyntaxGUID;
   hdr.if_vers = 
@@ -227,10 +230,27 @@
       goto fail;
     }
 
+    status = RPC_S_PROTOCOL_ERROR;
+
+    switch (hdr.ptype) {
+    case PKT_RESPONSE:
+      if (bind->server) goto fail;
+      break;
+    case PKT_REQUEST:
+      if (!bind->server) goto fail;
+      break;
+    case PKT_FAULT:
+      pMsg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;
+      status = RPC_S_CALL_FAILED; /* ? */
+      goto fail;
+    default:
+      goto fail;
+    }
+
     /* success */
     status = RPC_S_OK;
 
-    /* FIXME: check packet type, destination, etc? */
+    /* FIXME: check destination, etc? */
     break;
   }
 fail:
Index: dlls/rpcrt4/rpc_server.c
===================================================================
RCS file: /home/wine/wine/dlls/rpcrt4/rpc_server.c,v
retrieving revision 1.16
diff -u -r1.16 rpc_server.c
--- dlls/rpcrt4/rpc_server.c	21 May 2003 18:23:06 -0000	1.16
+++ dlls/rpcrt4/rpc_server.c	21 May 2003 19:56:58 -0000
@@ -33,8 +33,11 @@
 #include "rpc.h"
 
 #include "wine/debug.h"
+#include "wine/exception.h"
+#include "msvcrt/excpt.h"
 
 #include "rpc_server.h"
+#include "rpc_misc.h"
 #include "rpc_defs.h"
 
 #define MAX_THREADS 128
@@ -63,7 +66,7 @@
 static RpcPacket* spacket_tail;
 static HANDLE server_sem;
 
-static DWORD worker_count, worker_free;
+static DWORD worker_count, worker_free, worker_tls;
 
 static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
 {
@@ -110,6 +113,18 @@
   return packet;
 }
 
+static WINE_EXCEPTION_FILTER(rpc_filter)
+{
+  PRPC_MESSAGE msg;
+  msg = TlsGetValue(worker_tls);
+  I_RpcFreeBuffer(msg);
+  msg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;
+  msg->BufferLength = sizeof(DWORD);
+  I_RpcGetBuffer(msg);
+  *(DWORD*)msg->Buffer = GetExceptionCode();
+  return EXCEPTION_EXECUTE_HANDLER;
+}
+
 static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf)
 {
   RpcBinding* pbind;
@@ -117,6 +132,7 @@
   RpcServerInterface* sif;
   RPC_DISPATCH_FUNCTION func;
 
+  TlsSetValue(worker_tls, &msg);
   memset(&msg, 0, sizeof(msg));
   msg.BufferLength = hdr->len;
   msg.Buffer = buf;
@@ -152,7 +168,12 @@
                   MAKEWORD(hdr->drep[2], 0));
 
       /* dispatch */
-      if (func) func(&msg);
+      __TRY {
+        if (func) func(&msg);
+      } __EXCEPT(rpc_filter) {
+        /* failure packet was created in rpc_filter */
+        TRACE("exception caught, returning failure packet\n");
+      } __ENDTRY
 
       /* send response packet */
       I_RpcSend(&msg);
@@ -176,6 +197,7 @@
   HeapFree(GetProcessHeap(), 0, buf);
   I_RpcFreeBuffer(&msg);
   msg.Buffer = NULL;
+  TlsSetValue(worker_tls, NULL);
 }
 
 static DWORD CALLBACK RPCRT4_worker_thread(LPVOID the_arg)
@@ -411,6 +433,7 @@
   if (! ++listen_count) {
     if (!mgr_event) mgr_event = CreateEventA(NULL, TRUE, FALSE, NULL);
     if (!server_sem) server_sem = CreateSemaphoreA(NULL, 0, MAX_THREADS, NULL);
+    if (!worker_tls) worker_tls = TlsAlloc();
     std_listen = TRUE;
     server_thread = CreateThread(NULL, 0, RPCRT4_server_thread, NULL, 0, NULL);
     LeaveCriticalSection(&listen_cs);
--- /dev/null	2003-01-10 01:23:22.000000000 +0100
+++ dlls/rpcrt4/rpc_misc.h	2003-05-21 21:55:52.000000000 +0200
@@ -0,0 +1,13 @@
+/*
+ * RPC definitions
+ *
+ * Copyright 2003 Ove Kåven, TransGaming Technologies
+ */
+
+#ifndef __WINE_RPC_MISC_H
+#define __WINE_RPC_MISC_H
+
+/* flags for RPC_MESSAGE.RpcFlags */
+#define WINE_RPCFLAG_EXCEPTION 0x0001
+
+#endif  /* __WINE_RPC_MISC_H */






More information about the wine-patches mailing list