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
;
96 TRACE("(%p)\n", pMsg
);
97 if (!bind
) return RPC_S_INVALID_BINDING
;
99 status
= RPCRT4_OpenBinding(bind
, &conn
);
100 if (status
!= RPC_S_OK
) return status
;
102 obj
= &bind
->ObjectUuid
;
103 act
= &bind
->ActiveUuid
;
106 sif
= pMsg
->RpcInterfaceInformation
;
107 if (!sif
) return RPC_S_INTERFACE_NOT_FOUND
; /* ? */
109 cif
= pMsg
->RpcInterfaceInformation
;
110 if (!cif
) return RPC_S_INTERFACE_NOT_FOUND
; /* ? */
113 /* initialize packet header */
114 memset(&hdr
, 0, sizeof(hdr
));
116 hdr
.ptype
= bind
->server
117 ? ((pMsg
->RpcFlags
& WINE_RPCFLAG_EXCEPTION
) ? PKT_FAULT
: PKT_RESPONSE
)
119 hdr
.object
= *obj
; /* FIXME: IIRC iff no object, the header structure excludes this elt */
120 hdr
.if_id
= (bind
->server
) ? sif
->InterfaceId
.SyntaxGUID
: cif
->InterfaceId
.SyntaxGUID
;
123 MAKELONG(sif
->InterfaceId
.SyntaxVersion
.MinorVersion
, sif
->InterfaceId
.SyntaxVersion
.MajorVersion
) :
124 MAKELONG(cif
->InterfaceId
.SyntaxVersion
.MinorVersion
, cif
->InterfaceId
.SyntaxVersion
.MajorVersion
);
126 hdr
.opnum
= pMsg
->ProcNum
;
127 /* only the low-order 3 octets of the DataRepresentation go in the header */
128 hdr
.drep
[0] = LOBYTE(LOWORD(pMsg
->DataRepresentation
));
129 hdr
.drep
[1] = HIBYTE(LOWORD(pMsg
->DataRepresentation
));
130 hdr
.drep
[2] = LOBYTE(HIWORD(pMsg
->DataRepresentation
));
131 hdr
.len
= pMsg
->BufferLength
;
133 /* transmit packet */
134 if (!WriteFile(conn
->conn
, &hdr
, sizeof(hdr
), NULL
, NULL
)) {
135 WARN("WriteFile failed with error %ld\n", GetLastError());
136 status
= RPC_S_PROTOCOL_ERROR
;
140 if (!pMsg
->BufferLength
)
146 if (!WriteFile(conn
->conn
, pMsg
->Buffer
, pMsg
->BufferLength
, NULL
, NULL
)) {
147 WARN("WriteFile failed with error %ld\n", GetLastError());
148 status
= RPC_S_PROTOCOL_ERROR
;
154 /* save the connection, so the response can be read from it */
155 pMsg
->ReservedForRuntime
= conn
;
158 RPCRT4_CloseBinding(bind
, conn
);
165 /***********************************************************************
166 * I_RpcReceive [RPCRT4.@]
168 RPC_STATUS WINAPI
I_RpcReceive(PRPC_MESSAGE pMsg
)
170 RpcBinding
* bind
= (RpcBinding
*)pMsg
->Handle
;
177 TRACE("(%p)\n", pMsg
);
178 if (!bind
) return RPC_S_INVALID_BINDING
;
180 if (pMsg
->ReservedForRuntime
) {
181 conn
= pMsg
->ReservedForRuntime
;
182 pMsg
->ReservedForRuntime
= NULL
;
184 status
= RPCRT4_OpenBinding(bind
, &conn
);
185 if (status
!= RPC_S_OK
) return status
;
188 act
= &bind
->ActiveUuid
;
191 /* read packet header */
192 #ifdef OVERLAPPED_WORKS
193 if (!ReadFile(conn
->conn
, &hdr
, sizeof(hdr
), &dwRead
, &conn
->ovl
)) {
194 DWORD err
= GetLastError();
195 if (err
!= ERROR_IO_PENDING
) {
196 WARN("ReadFile failed with error %ld\n", err
);
197 status
= RPC_S_PROTOCOL_ERROR
;
200 if (!GetOverlappedResult(conn
->conn
, &conn
->ovl
, &dwRead
, TRUE
)) {
201 WARN("ReadFile failed with error %ld\n", GetLastError());
202 status
= RPC_S_PROTOCOL_ERROR
;
207 if (!ReadFile(conn
->conn
, &hdr
, sizeof(hdr
), &dwRead
, NULL
)) {
208 WARN("ReadFile failed with error %ld\n", GetLastError());
209 status
= RPC_S_PROTOCOL_ERROR
;
213 if (dwRead
!= sizeof(hdr
)) {
214 status
= RPC_S_PROTOCOL_ERROR
;
218 /* read packet body */
219 pMsg
->BufferLength
= hdr
.len
;
220 status
= I_RpcGetBuffer(pMsg
);
221 if (status
!= RPC_S_OK
) goto fail
;
222 if (!pMsg
->BufferLength
) dwRead
= 0; else
223 #ifdef OVERLAPPED_WORKS
224 if (!ReadFile(conn
->conn
, pMsg
->Buffer
, hdr
.len
, &dwRead
, &conn
->ovl
)) {
225 if (GetLastError() != ERROR_IO_PENDING
) {
226 WARN("ReadFile failed with error %ld\n", GetLastError());
227 status
= RPC_S_PROTOCOL_ERROR
;
230 if (!GetOverlappedResult(conn
->conn
, &conn
->ovl
, &dwRead
, TRUE
)) {
231 WARN("ReadFile failed with error %ld\n", GetLastError());
232 status
= RPC_S_PROTOCOL_ERROR
;
237 if (!ReadFile(conn
->conn
, pMsg
->Buffer
, hdr
.len
, &dwRead
, NULL
)) {
238 WARN("ReadFile failed with error %ld\n", GetLastError());
239 status
= RPC_S_PROTOCOL_ERROR
;
243 if (dwRead
!= hdr
.len
) {
244 status
= RPC_S_PROTOCOL_ERROR
;
248 status
= RPC_S_PROTOCOL_ERROR
;
252 if (bind
->server
) goto fail
;
255 if (!bind
->server
) goto fail
;
258 pMsg
->RpcFlags
|= WINE_RPCFLAG_EXCEPTION
;
259 status
= RPC_S_CALL_FAILED
; /* ? */
268 /* FIXME: check destination, etc? */
272 RPCRT4_CloseBinding(bind
, conn
);
276 /***********************************************************************
277 * I_RpcSendReceive [RPCRT4.@]
279 RPC_STATUS WINAPI
I_RpcSendReceive(PRPC_MESSAGE pMsg
)
283 TRACE("(%p)\n", pMsg
);
284 status
= I_RpcSend(pMsg
);
285 if (status
== RPC_S_OK
)
286 status
= I_RpcReceive(pMsg
);