4 * Copyright 2001-2002 Ove Kåven, TransGaming Technologies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 * - figure out whether we *really* got this right
22 * - check for errors and throw exceptions
23 * - decide if OVERLAPPED_WORKS
38 #include "wine/debug.h"
40 #include "rpc_binding.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ole);
46 /***********************************************************************
47 * I_RpcGetBuffer [RPCRT4.@]
49 RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
51 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
53 TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
54 /* FIXME: pfnAllocate? */
56 /* it turns out that the original buffer data must still be available
57 * while the RPC server is marshalling a reply, so we should not deallocate
58 * it, we'll leave deallocating the original buffer to the RPC server */
59 pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);
62 HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
63 pMsg->Buffer = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);
65 TRACE("Buffer=%p\n", pMsg->Buffer);
66 /* FIXME: which errors to return? */
67 return pMsg->Buffer ? S_OK : E_OUTOFMEMORY;
70 /***********************************************************************
71 * I_RpcFreeBuffer [RPCRT4.@]
73 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
75 TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);
77 HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
82 /***********************************************************************
83 * I_RpcSend [RPCRT4.@]
85 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
87 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
89 RPC_CLIENT_INTERFACE* cif = NULL;
90 RPC_SERVER_INTERFACE* sif = NULL;
97 TRACE("(%p)\n", pMsg);
98 if (!bind) return RPC_S_INVALID_BINDING;
100 status = RPCRT4_OpenBinding(bind, &conn);
101 if (status != RPC_S_OK) return status;
103 obj = &bind->ObjectUuid;
104 act = &bind->ActiveUuid;
107 sif = pMsg->RpcInterfaceInformation;
108 if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
110 cif = pMsg->RpcInterfaceInformation;
111 if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
114 /* initialize packet header */
115 memset(&hdr, 0, sizeof(hdr));
117 hdr.ptype = bind->server
118 ? ((pMsg->RpcFlags & WINE_RPCFLAG_EXCEPTION) ? PKT_FAULT : PKT_RESPONSE)
120 hdr.object = *obj; /* FIXME: IIRC iff no object, the header structure excludes this elt */
121 hdr.if_id = (bind->server) ? sif->InterfaceId.SyntaxGUID : cif->InterfaceId.SyntaxGUID;
124 MAKELONG(sif->InterfaceId.SyntaxVersion.MinorVersion, sif->InterfaceId.SyntaxVersion.MajorVersion) :
125 MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion, cif->InterfaceId.SyntaxVersion.MajorVersion);
127 hdr.opnum = pMsg->ProcNum;
128 /* only the low-order 3 octets of the DataRepresentation go in the header */
129 hdr.drep[0] = LOBYTE(LOWORD(pMsg->DataRepresentation));
130 hdr.drep[1] = HIBYTE(LOWORD(pMsg->DataRepresentation));
131 hdr.drep[2] = LOBYTE(HIWORD(pMsg->DataRepresentation));
132 hdr.len = pMsg->BufferLength;
134 /* transmit packet */
135 if (!WriteFile(conn->conn, &hdr, sizeof(hdr), &count, NULL)) {
136 WARN("WriteFile failed with error %ld\n", GetLastError());
137 status = RPC_S_PROTOCOL_ERROR;
141 if (!pMsg->BufferLength)
147 if (!WriteFile(conn->conn, pMsg->Buffer, pMsg->BufferLength, &count, NULL)) {
148 WARN("WriteFile failed with error %ld\n", GetLastError());
149 status = RPC_S_PROTOCOL_ERROR;
155 /* save the connection, so the response can be read from it */
156 pMsg->ReservedForRuntime = conn;
159 RPCRT4_CloseBinding(bind, conn);
166 /***********************************************************************
167 * I_RpcReceive [RPCRT4.@]
169 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
171 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
178 TRACE("(%p)\n", pMsg);
179 if (!bind) return RPC_S_INVALID_BINDING;
181 if (pMsg->ReservedForRuntime) {
182 conn = pMsg->ReservedForRuntime;
183 pMsg->ReservedForRuntime = NULL;
185 status = RPCRT4_OpenBinding(bind, &conn);
186 if (status != RPC_S_OK) return status;
189 act = &bind->ActiveUuid;
192 /* read packet header */
193 #ifdef OVERLAPPED_WORKS
194 if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) {
195 DWORD err = GetLastError();
196 if (err != ERROR_IO_PENDING) {
197 WARN("ReadFile failed with error %ld\n", err);
198 status = RPC_S_PROTOCOL_ERROR;
201 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
202 WARN("ReadFile failed with error %ld\n", GetLastError());
203 status = RPC_S_PROTOCOL_ERROR;
208 if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
209 WARN("ReadFile failed with error %ld\n", GetLastError());
210 status = RPC_S_PROTOCOL_ERROR;
214 if (dwRead != sizeof(hdr)) {
215 status = RPC_S_PROTOCOL_ERROR;
219 /* read packet body */
220 pMsg->BufferLength = hdr.len;
221 status = I_RpcGetBuffer(pMsg);
222 if (status != RPC_S_OK) goto fail;
223 if (!pMsg->BufferLength) dwRead = 0; else
224 #ifdef OVERLAPPED_WORKS
225 if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, &conn->ovl)) {
226 if (GetLastError() != ERROR_IO_PENDING) {
227 WARN("ReadFile failed with error %ld\n", GetLastError());
228 status = RPC_S_PROTOCOL_ERROR;
231 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
232 WARN("ReadFile failed with error %ld\n", GetLastError());
233 status = RPC_S_PROTOCOL_ERROR;
238 if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) {
239 WARN("ReadFile failed with error %ld\n", GetLastError());
240 status = RPC_S_PROTOCOL_ERROR;
244 if (dwRead != hdr.len) {
245 status = RPC_S_PROTOCOL_ERROR;
249 status = RPC_S_PROTOCOL_ERROR;
253 if (bind->server) goto fail;
256 if (!bind->server) goto fail;
259 pMsg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;
260 status = RPC_S_CALL_FAILED; /* ? */
269 /* FIXME: check destination, etc? */
273 RPCRT4_CloseBinding(bind, conn);
277 /***********************************************************************
278 * I_RpcSendReceive [RPCRT4.@]
280 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
284 TRACE("(%p)\n", pMsg);
285 status = I_RpcSend(pMsg);
286 if (status == RPC_S_OK)
287 status = I_RpcReceive(pMsg);