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.
This commit is contained in:
Ove Kaaven 2003-05-22 03:36:00 +00:00 committed by Alexandre Julliard
parent 7f53bb8f8c
commit c707e23675
4 changed files with 79 additions and 4 deletions

View File

@ -106,6 +106,10 @@ void WINAPI NdrProxySendReceive(void *This,
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);
}
/***********************************************************************

View File

@ -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 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
/* 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 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
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:

28
dlls/rpcrt4/rpc_misc.h Normal file
View File

@ -0,0 +1,28 @@
/*
* RPC definitions
*
* Copyright 2003 Ove Kåven, TransGaming Technologies
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#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 */

View File

@ -31,10 +31,13 @@
#include "winreg.h"
#include "rpc.h"
#include "excpt.h"
#include "wine/debug.h"
#include "wine/exception.h"
#include "rpc_server.h"
#include "rpc_misc.h"
#include "rpc_defs.h"
#define MAX_THREADS 128
@ -63,7 +66,7 @@ static RpcPacket* spacket_head;
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 @@ static RpcPacket* RPCRT4_pop_packet(void)
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 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf
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 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf
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 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, void* buf
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 @@ static void RPCRT4_start_listen(void)
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);