rpcrt4: Split RPCRT4_process_packet out into separate functions.
This commit is contained in:
parent
4dc91b7ba1
commit
a04641c15b
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright 2001 Ove Kåven, TransGaming Technologies
|
||||
* Copyright 2004 Filip Navara
|
||||
* Copyright 2006-2008 Robert Shearman (for CodeWeavers)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -160,16 +161,179 @@ static WINE_EXCEPTION_FILTER(rpc_filter)
|
|||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg)
|
||||
static RPC_STATUS process_bind_packet(RpcConnection *conn, RpcPktBindHdr *hdr, RPC_MESSAGE *msg)
|
||||
{
|
||||
RPC_STATUS status;
|
||||
RpcServerInterface* sif;
|
||||
RpcPktHdr *response = NULL;
|
||||
|
||||
/* FIXME: do more checks! */
|
||||
if (hdr->max_tsize < RPC_MIN_PACKET_SIZE ||
|
||||
!UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) ||
|
||||
conn->server_binding) {
|
||||
TRACE("packet size less than min size, or active interface syntax guid non-null\n");
|
||||
sif = NULL;
|
||||
} else {
|
||||
/* create temporary binding */
|
||||
if (RPCRT4_MakeBinding(&conn->server_binding, conn) == RPC_S_OK &&
|
||||
RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn),
|
||||
conn->NetworkAddr, conn->Endpoint,
|
||||
conn->NetworkOptions,
|
||||
hdr->assoc_gid,
|
||||
&conn->server_binding->Assoc) == RPC_S_OK)
|
||||
sif = RPCRT4_find_interface(NULL, &hdr->abstract, FALSE);
|
||||
else
|
||||
sif = NULL;
|
||||
}
|
||||
if (sif == NULL) {
|
||||
TRACE("rejecting bind request on connection %p\n", conn);
|
||||
/* Report failure to client. */
|
||||
response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
RPC_VER_MAJOR, RPC_VER_MINOR);
|
||||
} else {
|
||||
TRACE("accepting bind request on connection %p for %s\n", conn,
|
||||
debugstr_guid(&hdr->abstract.SyntaxGUID));
|
||||
|
||||
/* accept. */
|
||||
response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
RPC_MAX_PACKET_SIZE,
|
||||
RPC_MAX_PACKET_SIZE,
|
||||
conn->server_binding->Assoc->assoc_group_id,
|
||||
conn->Endpoint,
|
||||
RESULT_ACCEPT, REASON_NONE,
|
||||
&sif->If->TransferSyntax);
|
||||
|
||||
/* save the interface for later use */
|
||||
conn->ActiveInterface = hdr->abstract;
|
||||
conn->MaxTransmissionSize = hdr->max_tsize;
|
||||
|
||||
RPCRT4_release_server_interface(sif);
|
||||
}
|
||||
|
||||
if (response)
|
||||
status = RPCRT4_Send(conn, response, NULL, 0);
|
||||
else
|
||||
status = ERROR_OUTOFMEMORY;
|
||||
RPCRT4_FreeHeader(response);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static RPC_STATUS process_request_packet(RpcConnection *conn, RpcPktRequestHdr *hdr, RPC_MESSAGE *msg)
|
||||
{
|
||||
RPC_STATUS status;
|
||||
RpcPktHdr *response = NULL;
|
||||
RpcServerInterface* sif;
|
||||
RPC_DISPATCH_FUNCTION func;
|
||||
UUID *object_uuid;
|
||||
RpcPktHdr *response = NULL;
|
||||
void *buf = msg->Buffer;
|
||||
RPC_STATUS status;
|
||||
BOOL exception;
|
||||
UUID *object_uuid;
|
||||
NDR_SCONTEXT context_handle;
|
||||
void *buf = msg->Buffer;
|
||||
|
||||
/* fail if the connection isn't bound with an interface */
|
||||
if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) {
|
||||
/* FIXME: should send BindNack instead */
|
||||
response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
status);
|
||||
|
||||
RPCRT4_Send(conn, response, NULL, 0);
|
||||
RPCRT4_FreeHeader(response);
|
||||
return RPC_S_OK;
|
||||
}
|
||||
|
||||
if (hdr->common.flags & RPC_FLG_OBJECT_UUID) {
|
||||
object_uuid = (UUID*)(hdr + 1);
|
||||
} else {
|
||||
object_uuid = NULL;
|
||||
}
|
||||
|
||||
sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, TRUE);
|
||||
if (!sif) {
|
||||
WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID));
|
||||
response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
NCA_S_UNK_IF);
|
||||
|
||||
RPCRT4_Send(conn, response, NULL, 0);
|
||||
RPCRT4_FreeHeader(response);
|
||||
return RPC_S_OK;
|
||||
}
|
||||
msg->RpcInterfaceInformation = sif->If;
|
||||
/* copy the endpoint vector from sif to msg so that midl-generated code will use it */
|
||||
msg->ManagerEpv = sif->MgrEpv;
|
||||
if (object_uuid != NULL) {
|
||||
RPCRT4_SetBindingObject(msg->Handle, object_uuid);
|
||||
}
|
||||
|
||||
/* find dispatch function */
|
||||
msg->ProcNum = hdr->opnum;
|
||||
if (sif->Flags & RPC_IF_OLE) {
|
||||
/* native ole32 always gives us a dispatch table with a single entry
|
||||
* (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
|
||||
func = *sif->If->DispatchTable->DispatchTable;
|
||||
} else {
|
||||
if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
|
||||
WARN("invalid procnum (%d/%d)\n", msg->ProcNum, sif->If->DispatchTable->DispatchTableCount);
|
||||
response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
NCA_S_OP_RNG_ERROR);
|
||||
|
||||
RPCRT4_Send(conn, response, NULL, 0);
|
||||
RPCRT4_FreeHeader(response);
|
||||
}
|
||||
func = sif->If->DispatchTable->DispatchTable[msg->ProcNum];
|
||||
}
|
||||
|
||||
/* put in the drep. FIXME: is this more universally applicable?
|
||||
perhaps we should move this outward... */
|
||||
msg->DataRepresentation =
|
||||
MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]),
|
||||
MAKEWORD(hdr->common.drep[2], hdr->common.drep[3]));
|
||||
|
||||
exception = FALSE;
|
||||
|
||||
/* dispatch */
|
||||
RPCRT4_SetThreadCurrentCallHandle(msg->Handle);
|
||||
__TRY {
|
||||
if (func) func(msg);
|
||||
} __EXCEPT(rpc_filter) {
|
||||
exception = TRUE;
|
||||
if (GetExceptionCode() == STATUS_ACCESS_VIOLATION)
|
||||
status = ERROR_NOACCESS;
|
||||
else
|
||||
status = GetExceptionCode();
|
||||
response = RPCRT4_BuildFaultHeader(msg->DataRepresentation,
|
||||
RPC2NCA_STATUS(status));
|
||||
} __ENDTRY
|
||||
RPCRT4_SetThreadCurrentCallHandle(NULL);
|
||||
|
||||
/* release any unmarshalled context handles */
|
||||
while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL)
|
||||
RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE);
|
||||
|
||||
if (!exception)
|
||||
response = RPCRT4_BuildResponseHeader(msg->DataRepresentation,
|
||||
msg->BufferLength);
|
||||
|
||||
/* send response packet */
|
||||
if (response) {
|
||||
status = RPCRT4_Send(conn, response, exception ? NULL : msg->Buffer,
|
||||
exception ? 0 : msg->BufferLength);
|
||||
RPCRT4_FreeHeader(response);
|
||||
} else
|
||||
ERR("out of memory\n");
|
||||
|
||||
msg->RpcInterfaceInformation = NULL;
|
||||
RPCRT4_release_server_interface(sif);
|
||||
|
||||
if (msg->Buffer == buf) buf = NULL;
|
||||
TRACE("freeing Buffer=%p\n", buf);
|
||||
I_RpcFree(buf);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSAGE* msg)
|
||||
{
|
||||
RPC_STATUS status;
|
||||
|
||||
msg->Handle = (RPC_BINDING_HANDLE)conn->server_binding;
|
||||
|
||||
|
@ -177,153 +341,13 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
|
|||
case PKT_BIND:
|
||||
TRACE("got bind packet\n");
|
||||
|
||||
/* FIXME: do more checks! */
|
||||
if (hdr->bind.max_tsize < RPC_MIN_PACKET_SIZE ||
|
||||
!UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status) ||
|
||||
conn->server_binding) {
|
||||
TRACE("packet size less than min size, or active interface syntax guid non-null\n");
|
||||
sif = NULL;
|
||||
} else {
|
||||
/* create temporary binding */
|
||||
if (RPCRT4_MakeBinding(&conn->server_binding, conn) == RPC_S_OK &&
|
||||
RpcServerAssoc_GetAssociation(rpcrt4_conn_get_name(conn),
|
||||
conn->NetworkAddr, conn->Endpoint,
|
||||
conn->NetworkOptions,
|
||||
hdr->bind.assoc_gid,
|
||||
&conn->server_binding->Assoc) == RPC_S_OK)
|
||||
sif = RPCRT4_find_interface(NULL, &hdr->bind.abstract, FALSE);
|
||||
else
|
||||
sif = NULL;
|
||||
}
|
||||
if (sif == NULL) {
|
||||
TRACE("rejecting bind request on connection %p\n", conn);
|
||||
/* Report failure to client. */
|
||||
response = RPCRT4_BuildBindNackHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
RPC_VER_MAJOR, RPC_VER_MINOR);
|
||||
} else {
|
||||
TRACE("accepting bind request on connection %p for %s\n", conn,
|
||||
debugstr_guid(&hdr->bind.abstract.SyntaxGUID));
|
||||
|
||||
/* accept. */
|
||||
response = RPCRT4_BuildBindAckHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
RPC_MAX_PACKET_SIZE,
|
||||
RPC_MAX_PACKET_SIZE,
|
||||
conn->server_binding->Assoc->assoc_group_id,
|
||||
conn->Endpoint,
|
||||
RESULT_ACCEPT, REASON_NONE,
|
||||
&sif->If->TransferSyntax);
|
||||
|
||||
/* save the interface for later use */
|
||||
conn->ActiveInterface = hdr->bind.abstract;
|
||||
conn->MaxTransmissionSize = hdr->bind.max_tsize;
|
||||
|
||||
RPCRT4_release_server_interface(sif);
|
||||
}
|
||||
|
||||
status = RPCRT4_Send(conn, response, NULL, 0);
|
||||
RPCRT4_FreeHeader(response);
|
||||
if (status != RPC_S_OK)
|
||||
goto fail;
|
||||
|
||||
status = process_bind_packet(conn, &hdr->bind, msg);
|
||||
break;
|
||||
|
||||
case PKT_REQUEST:
|
||||
TRACE("got request packet\n");
|
||||
|
||||
/* fail if the connection isn't bound with an interface */
|
||||
if (UuidIsNil(&conn->ActiveInterface.SyntaxGUID, &status)) {
|
||||
/* FIXME: should send BindNack instead */
|
||||
response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
status);
|
||||
|
||||
RPCRT4_Send(conn, response, NULL, 0);
|
||||
RPCRT4_FreeHeader(response);
|
||||
break;
|
||||
}
|
||||
|
||||
if (hdr->common.flags & RPC_FLG_OBJECT_UUID) {
|
||||
object_uuid = (UUID*)(&hdr->request + 1);
|
||||
} else {
|
||||
object_uuid = NULL;
|
||||
}
|
||||
|
||||
sif = RPCRT4_find_interface(object_uuid, &conn->ActiveInterface, TRUE);
|
||||
if (!sif) {
|
||||
WARN("interface %s no longer registered, returning fault packet\n", debugstr_guid(&conn->ActiveInterface.SyntaxGUID));
|
||||
response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
NCA_S_UNK_IF);
|
||||
|
||||
RPCRT4_Send(conn, response, NULL, 0);
|
||||
RPCRT4_FreeHeader(response);
|
||||
break;
|
||||
}
|
||||
msg->RpcInterfaceInformation = sif->If;
|
||||
/* copy the endpoint vector from sif to msg so that midl-generated code will use it */
|
||||
msg->ManagerEpv = sif->MgrEpv;
|
||||
if (object_uuid != NULL) {
|
||||
RPCRT4_SetBindingObject(msg->Handle, object_uuid);
|
||||
}
|
||||
|
||||
/* find dispatch function */
|
||||
msg->ProcNum = hdr->request.opnum;
|
||||
if (sif->Flags & RPC_IF_OLE) {
|
||||
/* native ole32 always gives us a dispatch table with a single entry
|
||||
* (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
|
||||
func = *sif->If->DispatchTable->DispatchTable;
|
||||
} else {
|
||||
if (msg->ProcNum >= sif->If->DispatchTable->DispatchTableCount) {
|
||||
WARN("invalid procnum (%d/%d)\n", msg->ProcNum, sif->If->DispatchTable->DispatchTableCount);
|
||||
response = RPCRT4_BuildFaultHeader(NDR_LOCAL_DATA_REPRESENTATION,
|
||||
NCA_S_OP_RNG_ERROR);
|
||||
|
||||
RPCRT4_Send(conn, response, NULL, 0);
|
||||
RPCRT4_FreeHeader(response);
|
||||
}
|
||||
func = sif->If->DispatchTable->DispatchTable[msg->ProcNum];
|
||||
}
|
||||
|
||||
/* put in the drep. FIXME: is this more universally applicable?
|
||||
perhaps we should move this outward... */
|
||||
msg->DataRepresentation =
|
||||
MAKELONG( MAKEWORD(hdr->common.drep[0], hdr->common.drep[1]),
|
||||
MAKEWORD(hdr->common.drep[2], hdr->common.drep[3]));
|
||||
|
||||
exception = FALSE;
|
||||
|
||||
/* dispatch */
|
||||
RPCRT4_SetThreadCurrentCallHandle(msg->Handle);
|
||||
__TRY {
|
||||
if (func) func(msg);
|
||||
} __EXCEPT(rpc_filter) {
|
||||
exception = TRUE;
|
||||
if (GetExceptionCode() == STATUS_ACCESS_VIOLATION)
|
||||
status = ERROR_NOACCESS;
|
||||
else
|
||||
status = GetExceptionCode();
|
||||
response = RPCRT4_BuildFaultHeader(msg->DataRepresentation,
|
||||
RPC2NCA_STATUS(status));
|
||||
} __ENDTRY
|
||||
RPCRT4_SetThreadCurrentCallHandle(NULL);
|
||||
|
||||
/* release any unmarshalled context handles */
|
||||
while ((context_handle = RPCRT4_PopThreadContextHandle()) != NULL)
|
||||
RpcServerAssoc_ReleaseContextHandle(conn->server_binding->Assoc, context_handle, TRUE);
|
||||
|
||||
if (!exception)
|
||||
response = RPCRT4_BuildResponseHeader(msg->DataRepresentation,
|
||||
msg->BufferLength);
|
||||
|
||||
/* send response packet */
|
||||
if (response) {
|
||||
status = RPCRT4_Send(conn, response, exception ? NULL : msg->Buffer,
|
||||
exception ? 0 : msg->BufferLength);
|
||||
RPCRT4_FreeHeader(response);
|
||||
} else
|
||||
ERR("out of memory\n");
|
||||
|
||||
msg->RpcInterfaceInformation = NULL;
|
||||
RPCRT4_release_server_interface(sif);
|
||||
|
||||
status = process_request_packet(conn, &hdr->request, msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -331,11 +355,7 @@ static void RPCRT4_process_packet(RpcConnection* conn, RpcPktHdr* hdr, RPC_MESSA
|
|||
break;
|
||||
}
|
||||
|
||||
fail:
|
||||
/* clean up */
|
||||
if (msg->Buffer == buf) msg->Buffer = NULL;
|
||||
TRACE("freeing Buffer=%p\n", buf);
|
||||
I_RpcFree(buf);
|
||||
I_RpcFreeBuffer(msg);
|
||||
RPCRT4_FreeHeader(hdr);
|
||||
HeapFree(GetProcessHeap(), 0, msg);
|
||||
|
|
Loading…
Reference in New Issue