Split Win16/32 printer dialogs.
[wine/wine64.git] / dlls / rpcrt4 / rpc_message.c
blobd2e7e1d45885332b8ac19122db3b336fcca8a96b
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_misc.h"
41 #include "rpc_defs.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(ole);
45 /***********************************************************************
46 * I_RpcGetBuffer [RPCRT4.@]
48 RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
50 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
51 void* buf;
53 TRACE("(%p): BufferLength=%d\n", pMsg, pMsg->BufferLength);
54 /* FIXME: pfnAllocate? */
55 if (bind->server) {
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 buf = HeapAlloc(GetProcessHeap(), 0, pMsg->BufferLength);
60 } else {
61 buf = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength);
63 TRACE("Buffer=%p\n", buf);
64 if (buf) pMsg->Buffer = buf;
65 /* FIXME: which errors to return? */
66 return buf ? S_OK : E_OUTOFMEMORY;
69 /***********************************************************************
70 * I_RpcFreeBuffer [RPCRT4.@]
72 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
74 TRACE("(%p) Buffer=%p\n", pMsg, pMsg->Buffer);
75 /* FIXME: pfnFree? */
76 HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
77 pMsg->Buffer = NULL;
78 return S_OK;
81 /***********************************************************************
82 * I_RpcSend [RPCRT4.@]
84 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
86 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
87 RpcConnection* conn;
88 RPC_CLIENT_INTERFACE* cif = NULL;
89 RPC_SERVER_INTERFACE* sif = NULL;
90 UUID* obj;
91 UUID* act;
92 RPC_STATUS status;
93 RpcPktHdr hdr;
95 TRACE("(%p)\n", pMsg);
96 if (!bind) return RPC_S_INVALID_BINDING;
98 status = RPCRT4_OpenBinding(bind, &conn);
99 if (status != RPC_S_OK) return status;
101 obj = &bind->ObjectUuid;
102 act = &bind->ActiveUuid;
104 if (bind->server) {
105 sif = pMsg->RpcInterfaceInformation;
106 if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
107 } else {
108 cif = pMsg->RpcInterfaceInformation;
109 if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
112 /* initialize packet header */
113 memset(&hdr, 0, sizeof(hdr));
114 hdr.rpc_ver = 4;
115 hdr.ptype = bind->server
116 ? ((pMsg->RpcFlags & WINE_RPCFLAG_EXCEPTION) ? PKT_FAULT : PKT_RESPONSE)
117 : PKT_REQUEST;
118 hdr.object = *obj; /* FIXME: IIRC iff no object, the header structure excludes this elt */
119 hdr.if_id = (bind->server) ? sif->InterfaceId.SyntaxGUID : cif->InterfaceId.SyntaxGUID;
120 hdr.if_vers =
121 (bind->server) ?
122 MAKELONG(sif->InterfaceId.SyntaxVersion.MinorVersion, sif->InterfaceId.SyntaxVersion.MajorVersion) :
123 MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion, cif->InterfaceId.SyntaxVersion.MajorVersion);
124 hdr.act_id = *act;
125 hdr.opnum = pMsg->ProcNum;
126 /* only the low-order 3 octets of the DataRepresentation go in the header */
127 hdr.drep[0] = LOBYTE(LOWORD(pMsg->DataRepresentation));
128 hdr.drep[1] = HIBYTE(LOWORD(pMsg->DataRepresentation));
129 hdr.drep[2] = LOBYTE(HIWORD(pMsg->DataRepresentation));
130 hdr.len = pMsg->BufferLength;
132 /* transmit packet */
133 if (!WriteFile(conn->conn, &hdr, sizeof(hdr), NULL, NULL)) {
134 status = GetLastError();
135 goto fail;
137 if (pMsg->BufferLength && !WriteFile(conn->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL)) {
138 status = GetLastError();
139 goto fail;
142 /* success */
143 if (!bind->server) {
144 /* save the connection, so the response can be read from it */
145 pMsg->ReservedForRuntime = conn;
146 return RPC_S_OK;
148 RPCRT4_CloseBinding(bind, conn);
149 status = RPC_S_OK;
150 fail:
152 return status;
155 /***********************************************************************
156 * I_RpcReceive [RPCRT4.@]
158 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
160 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
161 RpcConnection* conn;
162 UUID* act;
163 RPC_STATUS status;
164 RpcPktHdr hdr;
165 DWORD dwRead;
167 TRACE("(%p)\n", pMsg);
168 if (!bind) return RPC_S_INVALID_BINDING;
170 if (pMsg->ReservedForRuntime) {
171 conn = pMsg->ReservedForRuntime;
172 pMsg->ReservedForRuntime = NULL;
173 } else {
174 status = RPCRT4_OpenBinding(bind, &conn);
175 if (status != RPC_S_OK) return status;
178 act = &bind->ActiveUuid;
180 for (;;) {
181 /* read packet header */
182 #ifdef OVERLAPPED_WORKS
183 if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, &conn->ovl)) {
184 DWORD err = GetLastError();
185 if (err != ERROR_IO_PENDING) {
186 status = err;
187 goto fail;
189 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
190 status = GetLastError();
191 goto fail;
194 #else
195 if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
196 status = GetLastError();
197 goto fail;
199 #endif
200 if (dwRead != sizeof(hdr)) {
201 status = RPC_S_PROTOCOL_ERROR;
202 goto fail;
205 /* read packet body */
206 pMsg->BufferLength = hdr.len;
207 status = I_RpcGetBuffer(pMsg);
208 if (status != RPC_S_OK) goto fail;
209 if (!pMsg->BufferLength) dwRead = 0; else
210 #ifdef OVERLAPPED_WORKS
211 if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, &conn->ovl)) {
212 DWORD err = GetLastError();
213 if (err != ERROR_IO_PENDING) {
214 status = err;
215 goto fail;
217 if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
218 status = GetLastError();
219 goto fail;
222 #else
223 if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) {
224 status = GetLastError();
225 goto fail;
227 #endif
228 if (dwRead != hdr.len) {
229 status = RPC_S_PROTOCOL_ERROR;
230 goto fail;
233 status = RPC_S_PROTOCOL_ERROR;
235 switch (hdr.ptype) {
236 case PKT_RESPONSE:
237 if (bind->server) goto fail;
238 break;
239 case PKT_REQUEST:
240 if (!bind->server) goto fail;
241 break;
242 case PKT_FAULT:
243 pMsg->RpcFlags |= WINE_RPCFLAG_EXCEPTION;
244 status = RPC_S_CALL_FAILED; /* ? */
245 goto fail;
246 default:
247 goto fail;
250 /* success */
251 status = RPC_S_OK;
253 /* FIXME: check destination, etc? */
254 break;
256 fail:
257 RPCRT4_CloseBinding(bind, conn);
258 return status;
261 /***********************************************************************
262 * I_RpcSendReceive [RPCRT4.@]
264 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
266 RPC_STATUS status;
268 TRACE("(%p)\n", pMsg);
269 status = I_RpcSend(pMsg);
270 if (status == RPC_S_OK)
271 status = I_RpcReceive(pMsg);
272 return status;