Commit c707e236 authored by Ove Kaaven's avatar Ove Kaaven Committed by Alexandre Julliard

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.
parent 7f53bb8f
......@@ -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:
......
/*
* 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 */
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment