📄 rpc_message.c
字号:
WARN("ReadFile failed with error %ld\n", GetLastError());
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
if (!GetOverlappedResult(Connection->conn, &Connection->ovl[0], &dwRead, TRUE)) {
if (GetLastError() != ERROR_MORE_DATA) {
WARN("GetOverlappedResult failed with error %ld\n", GetLastError());
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
}
if (dwRead != sizeof(common_hdr)) {
WARN("Short read of header, %ld/%d bytes\n", dwRead, sizeof(common_hdr));
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
/* verify if the header really makes sense */
if (common_hdr.rpc_ver != RPC_VER_MAJOR ||
common_hdr.rpc_ver_minor != RPC_VER_MINOR) {
WARN("unhandled packet version\n");
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
hdr_length = RPCRT4_GetHeaderSize((RpcPktHdr*)&common_hdr);
if (hdr_length == 0) {
WARN("header length == 0\n");
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
*Header = HeapAlloc(GetProcessHeap(), 0, hdr_length);
memcpy(*Header, &common_hdr, sizeof(common_hdr));
/* read the rest of packet header */
if (!ReadFile(Connection->conn, &(*Header)->common + 1,
hdr_length - sizeof(common_hdr), &dwRead, &Connection->ovl[0]) &&
ERROR_IO_PENDING != GetLastError()) {
WARN("ReadFile failed with error %ld\n", GetLastError());
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
if (!GetOverlappedResult(Connection->conn, &Connection->ovl[0], &dwRead, TRUE)) {
if (GetLastError() != ERROR_MORE_DATA) {
WARN("GetOverlappedResult failed with error %ld\n", GetLastError());
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
}
if (dwRead != hdr_length - sizeof(common_hdr)) {
WARN("bad header length, %ld/%ld bytes\n", dwRead, hdr_length - sizeof(common_hdr));
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
/* read packet body */
switch (common_hdr.ptype) {
case PKT_RESPONSE:
pMsg->BufferLength = (*Header)->response.alloc_hint;
break;
case PKT_REQUEST:
pMsg->BufferLength = (*Header)->request.alloc_hint;
break;
default:
pMsg->BufferLength = common_hdr.frag_len - hdr_length;
}
TRACE("buffer length = %u\n", pMsg->BufferLength);
status = I_RpcGetBuffer(pMsg);
if (status != RPC_S_OK) goto fail;
first_flag = RPC_FLG_FIRST;
buffer_length = 0;
buffer_ptr = pMsg->Buffer;
while (buffer_length < pMsg->BufferLength)
{
data_length = (*Header)->common.frag_len - hdr_length;
if (((*Header)->common.flags & RPC_FLG_FIRST) != first_flag ||
data_length + buffer_length > pMsg->BufferLength) {
TRACE("invalid packet flags or buffer length\n");
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
if (data_length == 0) dwRead = 0; else {
if (!ReadFile(Connection->conn, buffer_ptr, data_length, &dwRead, &Connection->ovl[0]) &&
ERROR_IO_PENDING != GetLastError()) {
WARN("ReadFile failed with error %ld\n", GetLastError());
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
if (!GetOverlappedResult(Connection->conn, &Connection->ovl[0], &dwRead, TRUE)) {
if (GetLastError() != ERROR_MORE_DATA) {
WARN("GetOverlappedResult failed with error %ld\n", GetLastError());
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
}
}
if (dwRead != data_length) {
WARN("bad data length, %ld/%ld\n", dwRead, data_length);
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
/* when there is no more data left, it should be the last packet */
if (buffer_length == pMsg->BufferLength &&
((*Header)->common.flags & RPC_FLG_LAST) == 0) {
WARN("no more data left, but not last packet\n");
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
buffer_length += data_length;
if (buffer_length < pMsg->BufferLength) {
TRACE("next header\n");
/* read the header of next packet */
if (!ReadFile(Connection->conn, *Header, hdr_length, &dwRead, &Connection->ovl[0]) &&
ERROR_IO_PENDING != GetLastError()) {
WARN("ReadFile failed with error %ld\n", GetLastError());
status = GetLastError();
goto fail;
}
if (!GetOverlappedResult(Connection->conn, &Connection->ovl[0], &dwRead, TRUE)) {
if (GetLastError() != ERROR_MORE_DATA) {
WARN("GetOverlappedResult failed with error %ld\n", GetLastError());
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
}
if (dwRead != hdr_length) {
WARN("invalid packet header size (%ld)\n", dwRead);
status = RPC_S_PROTOCOL_ERROR;
goto fail;
}
buffer_ptr += data_length;
first_flag = 0;
}
}
/* success */
status = RPC_S_OK;
fail:
if (status != RPC_S_OK && *Header) {
RPCRT4_FreeHeader(*Header);
*Header = NULL;
}
return status;
}
/***********************************************************************
* I_RpcGetBuffer [RPCRT4.@]
*/
RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
{
TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
/* FIXME: pfnAllocate? */
pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);
TRACE("Buffer=%p\n", pMsg->Buffer);
/* FIXME: which errors to return? */
return pMsg->Buffer ? S_OK : E_OUTOFMEMORY;
}
/***********************************************************************
* I_RpcFreeBuffer [RPCRT4.@]
*/
RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
{
TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);
/* FIXME: pfnFree? */
HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
pMsg->Buffer = NULL;
return S_OK;
}
/***********************************************************************
* I_RpcSend [RPCRT4.@]
*/
RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
{
RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RpcConnection* conn;
RPC_CLIENT_INTERFACE* cif = NULL;
RPC_SERVER_INTERFACE* sif = NULL;
RPC_STATUS status;
RpcPktHdr *hdr;
TRACE("(%p)\n", pMsg);
if (!bind) return RPC_S_INVALID_BINDING;
if (bind->server) {
sif = pMsg->RpcInterfaceInformation;
if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax,
&sif->InterfaceId);
} else {
cif = pMsg->RpcInterfaceInformation;
if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,
&cif->InterfaceId);
}
if (status != RPC_S_OK) return status;
if (bind->server) {
if (pMsg->RpcFlags & WINE_RPCFLAG_EXCEPTION) {
hdr = RPCRT4_BuildFaultHeader(pMsg->DataRepresentation,
RPC_S_CALL_FAILED);
} else {
hdr = RPCRT4_BuildResponseHeader(pMsg->DataRepresentation,
pMsg->BufferLength);
}
} else {
hdr = RPCRT4_BuildRequestHeader(pMsg->DataRepresentation,
pMsg->BufferLength, pMsg->ProcNum,
&bind->ObjectUuid);
}
status = RPCRT4_Send(conn, hdr, pMsg->Buffer, pMsg->BufferLength);
RPCRT4_FreeHeader(hdr);
/* success */
if (!bind->server) {
/* save the connection, so the response can be read from it */
pMsg->ReservedForRuntime = conn;
return RPC_S_OK;
}
RPCRT4_CloseBinding(bind, conn);
status = RPC_S_OK;
return status;
}
/***********************************************************************
* I_RpcReceive [RPCRT4.@]
*/
RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
{
RpcBinding* bind = (RpcBinding*)pMsg->Handle;
RpcConnection* conn;
RPC_CLIENT_INTERFACE* cif = NULL;
RPC_SERVER_INTERFACE* sif = NULL;
RPC_STATUS status;
RpcPktHdr *hdr = NULL;
TRACE("(%p)\n", pMsg);
if (!bind) return RPC_S_INVALID_BINDING;
if (pMsg->ReservedForRuntime) {
conn = pMsg->ReservedForRuntime;
pMsg->ReservedForRuntime = NULL;
} else {
if (bind->server) {
sif = pMsg->RpcInterfaceInformation;
if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
status = RPCRT4_OpenBinding(bind, &conn, &sif->TransferSyntax,
&sif->InterfaceId);
} else {
cif = pMsg->RpcInterfaceInformation;
if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
status = RPCRT4_OpenBinding(bind, &conn, &cif->TransferSyntax,
&cif->InterfaceId);
}
if (status != RPC_S_OK) return status;
}
status = RPCRT4_Receive(conn, &hdr, pMsg);
if (status != RPC_S_OK) {
WARN("receive failed with error %lx\n", status);
goto fail;
}
status = RPC_S_PROTOCOL_ERROR;
switch (hdr->common.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;
ERR ("we got fault packet with status %lx\n", hdr->fault.status);
status = RPC_S_CALL_FAILED; /* ? */
goto fail;
default:
WARN("bad packet type %d\n", hdr->common.ptype);
goto fail;
}
/* success */
status = RPC_S_OK;
fail:
if (hdr) {
RPCRT4_FreeHeader(hdr);
}
RPCRT4_CloseBinding(bind, conn);
return status;
}
/***********************************************************************
* I_RpcSendReceive [RPCRT4.@]
*/
RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
{
RPC_STATUS status;
TRACE("(%p)\n", pMsg);
status = I_RpcSend(pMsg);
if (status == RPC_S_OK)
status = I_RpcReceive(pMsg);
return status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -