Implemented Rtl*ByteSwap() functions, based on a patch by Jon
[wine/multimedia.git] / dlls / rpcrt4 / rpc_message.c
blob8ba3996ecb986b4a912702d546da65a222feb233
1 /*
2 * RPC messages
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
20 * TODO:
21 * - figure out whether we *really* got this right
22 * - check for errors and throw exceptions
23 * - decide if OVERLAPPED_WORKS
26 #include <stdio.h>
27 #include <string.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winreg.h"
34 #include "rpc.h"
35 #include "rpcdcep.h"
37 #include "wine/debug.h"
39 #include "rpc_binding.h"
40 #include "rpc_defs.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(ole);
44 /***********************************************************************
45 * I_RpcGetBuffer [RPCRT4.@]
47 RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
49 void* buf;
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);
66 /* FIXME: pfnFree? */
67 HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
68 pMsg->Buffer = NULL;
69 return S_OK;
72 /***********************************************************************
73 * I_RpcSend [RPCRT4.@]
75 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
77 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
78 RpcConnection* conn;
79 RPC_CLIENT_INTERFACE* cif = NULL;
80 RPC_SERVER_INTERFACE* sif = NULL;
81 UUID* obj;
82 UUID* act;
83 RPC_STATUS status;
84 RpcPktHdr hdr;
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;
95 if (bind->server) {
96 sif = pMsg->RpcInterfaceInformation;
97 if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
98 } else {
99 cif = pMsg->RpcInterfaceInformation;
100 if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
103 /* initialize packet header */
104 memset(&hdr, 0, sizeof(hdr));
105 hdr.rpc_ver = 4;
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;
109 hdr.if_vers =
110 (bind->server) ?
111 MAKELONG(sif->InterfaceId.SyntaxVersion.MinorVersion, sif->InterfaceId.SyntaxVersion.MajorVersion) :
112 MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion, cif->InterfaceId.SyntaxVersion.MajorVersion);
113 hdr.act_id = *act;
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();
124 goto fail;
126 if (pMsg->BufferLength && !WriteFile(conn->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL)) {
127 status = GetLastError();
128 goto fail;
131 /* success */
132 if (!bind->server) {
133 /* save the connection, so the response can be read from it */
134 pMsg->ReservedForRuntime = conn;
135 return RPC_S_OK;
137 RPCRT4_CloseBinding(bind, conn);
138 status = RPC_S_OK;
139 fail:
141 return status;
144 /***********************************************************************
145 * I_RpcReceive [RPCRT4.@]
147 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
149 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
150 RpcConnection* conn;
151 UUID* act;
152 RPC_STATUS status;
153 RpcPktHdr hdr;
154 DWORD dwRead;
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;
162 } else {
163 status = RPCRT4_OpenBinding(bind, &conn);
164 if (status != RPC_S_OK) return status;
167 act = &bind->ActiveUuid;
169 for (;;) {
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) {
175 status = err;
176 goto fail;
178 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
179 status = GetLastError();
180 goto fail;
183 #else
184 if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
185 status = GetLastError();
186 goto fail;
188 #endif
189 if (dwRead != sizeof(hdr)) {
190 status = RPC_S_PROTOCOL_ERROR;
191 goto fail;
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) {
203 status = err;
204 goto fail;
206 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
207 status = GetLastError();
208 goto fail;
211 #else
212 if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) {
213 status = GetLastError();
214 goto fail;
216 #endif
217 if (dwRead != hdr.len) {
218 status = RPC_S_PROTOCOL_ERROR;
219 goto fail;
222 /* success */
223 status = RPC_S_OK;
225 /* FIXME: check packet type, destination, etc? */
226 break;
228 fail:
229 RPCRT4_CloseBinding(bind, conn);
230 return status;
233 /***********************************************************************
234 * I_RpcSendReceive [RPCRT4.@]
236 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
238 RPC_STATUS status;
240 TRACE("(%p)\n", pMsg);
241 status = I_RpcSend(pMsg);
242 if (status == RPC_S_OK)
243 status = I_RpcReceive(pMsg);
244 return status;