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
37 #include "wine/debug.h"
39 #include "rpc_binding.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
44 /***********************************************************************
45 * I_RpcGetBuffer [RPCRT4.@]
47 RPC_STATUS WINAPI
I_RpcGetBuffer(PRPC_MESSAGE pMsg
)
51 TRACE("(%p): BufferLength=%d\n", pMsg
, pMsg
->BufferLength
);
52 /* FIXME: pfnAllocate? */
53 buf
= HeapReAlloc(GetProcessHeap(), 0, pMsg
->Buffer
, pMsg
->BufferLength
);
54 TRACE("Buffer=%p\n", buf
);
55 if (buf
) pMsg
->Buffer
= buf
;
56 /* FIXME: which errors to return? */
57 return buf
? S_OK
: E_OUTOFMEMORY
;
60 /***********************************************************************
61 * I_RpcFreeBuffer [RPCRT4.@]
63 RPC_STATUS WINAPI
I_RpcFreeBuffer(PRPC_MESSAGE pMsg
)
65 TRACE("(%p)\n", pMsg
);
67 HeapFree(GetProcessHeap(), 0, pMsg
->Buffer
);
72 /***********************************************************************
73 * I_RpcSend [RPCRT4.@]
75 RPC_STATUS WINAPI
I_RpcSend(PRPC_MESSAGE pMsg
)
77 RpcBinding
* bind
= (RpcBinding
*)pMsg
->Handle
;
79 RPC_CLIENT_INTERFACE
* cif
= NULL
;
80 RPC_SERVER_INTERFACE
* sif
= NULL
;
86 TRACE("(%p)\n", pMsg
);
87 if (!bind
) return RPC_S_INVALID_BINDING
;
89 status
= RPCRT4_OpenBinding(bind
, &conn
);
90 if (status
!= RPC_S_OK
) return status
;
92 obj
= &bind
->ObjectUuid
;
93 act
= &bind
->ActiveUuid
;
96 sif
= pMsg
->RpcInterfaceInformation
;
97 if (!sif
) return RPC_S_INTERFACE_NOT_FOUND
; /* ? */
99 cif
= pMsg
->RpcInterfaceInformation
;
100 if (!cif
) return RPC_S_INTERFACE_NOT_FOUND
; /* ? */
103 /* initialize packet header */
104 memset(&hdr
, 0, sizeof(hdr
));
106 hdr
.ptype
= bind
->server
? PKT_RESPONSE
: PKT_REQUEST
;
107 hdr
.object
= *obj
; /* FIXME: IIRC iff no object, the header structure excludes this elt */
108 hdr
.if_id
= (bind
->server
) ? sif
->InterfaceId
.SyntaxGUID
: cif
->InterfaceId
.SyntaxGUID
;
111 MAKELONG(sif
->InterfaceId
.SyntaxVersion
.MinorVersion
, sif
->InterfaceId
.SyntaxVersion
.MajorVersion
) :
112 MAKELONG(cif
->InterfaceId
.SyntaxVersion
.MinorVersion
, cif
->InterfaceId
.SyntaxVersion
.MajorVersion
);
114 hdr
.opnum
= pMsg
->ProcNum
;
115 /* only the low-order 3 octets of the DataRepresentation go in the header */
116 hdr
.drep
[0] = LOBYTE(LOWORD(pMsg
->DataRepresentation
));
117 hdr
.drep
[1] = HIBYTE(LOWORD(pMsg
->DataRepresentation
));
118 hdr
.drep
[2] = LOBYTE(HIWORD(pMsg
->DataRepresentation
));
119 hdr
.len
= pMsg
->BufferLength
;
121 /* transmit packet */
122 if (!WriteFile(conn
->conn
, &hdr
, sizeof(hdr
), NULL
, NULL
)) {
123 status
= GetLastError();
126 if (pMsg
->BufferLength
&& !WriteFile(conn
->conn
, pMsg
->Buffer
, pMsg
->BufferLength
, NULL
, NULL
)) {
127 status
= GetLastError();
133 /* save the connection, so the response can be read from it */
134 pMsg
->ReservedForRuntime
= conn
;
137 RPCRT4_CloseBinding(bind
, conn
);
144 /***********************************************************************
145 * I_RpcReceive [RPCRT4.@]
147 RPC_STATUS WINAPI
I_RpcReceive(PRPC_MESSAGE pMsg
)
149 RpcBinding
* bind
= (RpcBinding
*)pMsg
->Handle
;
156 TRACE("(%p)\n", pMsg
);
157 if (!bind
) return RPC_S_INVALID_BINDING
;
159 if (pMsg
->ReservedForRuntime
) {
160 conn
= pMsg
->ReservedForRuntime
;
161 pMsg
->ReservedForRuntime
= NULL
;
163 status
= RPCRT4_OpenBinding(bind
, &conn
);
164 if (status
!= RPC_S_OK
) return status
;
167 act
= &bind
->ActiveUuid
;
170 /* read packet header */
171 #ifdef OVERLAPPED_WORKS
172 if (!ReadFile(conn
->conn
, &hdr
, sizeof(hdr
), &dwRead
, &conn
->ovl
)) {
173 DWORD err
= GetLastError();
174 if (err
!= ERROR_IO_PENDING
) {
178 if (!GetOverlappedResult(conn
->conn
, &conn
->ovl
, &dwRead
, TRUE
)) {
179 status
= GetLastError();
184 if (!ReadFile(conn
->conn
, &hdr
, sizeof(hdr
), &dwRead
, NULL
)) {
185 status
= GetLastError();
189 if (dwRead
!= sizeof(hdr
)) {
190 status
= RPC_S_PROTOCOL_ERROR
;
194 /* read packet body */
195 pMsg
->BufferLength
= hdr
.len
;
196 status
= I_RpcGetBuffer(pMsg
);
197 if (status
!= RPC_S_OK
) goto fail
;
198 if (!pMsg
->BufferLength
) dwRead
= 0; else
199 #ifdef OVERLAPPED_WORKS
200 if (!ReadFile(conn
->conn
, pMsg
->Buffer
, hdr
.len
, &dwRead
, &conn
->ovl
)) {
201 DWORD err
= GetLastError();
202 if (err
!= ERROR_IO_PENDING
) {
206 if (!GetOverlappedResult(conn
->conn
, &conn
->ovl
, &dwRead
, TRUE
)) {
207 status
= GetLastError();
212 if (!ReadFile(conn
->conn
, pMsg
->Buffer
, hdr
.len
, &dwRead
, NULL
)) {
213 status
= GetLastError();
217 if (dwRead
!= hdr
.len
) {
218 status
= RPC_S_PROTOCOL_ERROR
;
225 /* FIXME: check packet type, destination, etc? */
229 RPCRT4_CloseBinding(bind
, conn
);
233 /***********************************************************************
234 * I_RpcSendReceive [RPCRT4.@]
236 RPC_STATUS WINAPI
I_RpcSendReceive(PRPC_MESSAGE pMsg
)
240 TRACE("(%p)\n", pMsg
);
241 status
= I_RpcSend(pMsg
);
242 if (status
== RPC_S_OK
)
243 status
= I_RpcReceive(pMsg
);