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:
parent
7f53bb8f8c
commit
c707e23675
|
@ -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);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 */
|
|
@ -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 */
|
||||
__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);
|
||||
|
|
Loading…
Reference in New Issue