All MCI functions are now cleanly separated.
[wine/hacks.git] / dlls / rpcrt4 / rpc_message.c
blobb35b1143eb877d2c2ab831be30b7fe1a696f08c8
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)\n", pMsg);
52 /* FIXME: pfnAllocate? */
53 buf = HeapReAlloc(GetProcessHeap(), 0, pMsg->Buffer, pMsg->BufferLength);
54 if (buf) pMsg->Buffer = buf;
55 /* FIXME: which errors to return? */
56 return buf ? S_OK : E_OUTOFMEMORY;
59 /***********************************************************************
60 * I_RpcFreeBuffer [RPCRT4.@]
62 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
64 TRACE("(%p)\n", pMsg);
65 /* FIXME: pfnFree? */
66 HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
67 pMsg->Buffer = NULL;
68 return S_OK;
71 /***********************************************************************
72 * I_RpcSend [RPCRT4.@]
74 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
76 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
77 RPC_CLIENT_INTERFACE* cif = NULL;
78 RPC_SERVER_INTERFACE* sif = NULL;
79 RPC_STATUS status;
80 RpcPktHdr hdr;
82 TRACE("(%p)\n", pMsg);
83 if (!bind) return RPC_S_INVALID_BINDING;
85 if (bind->server) {
86 sif = pMsg->RpcInterfaceInformation;
87 if (!sif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
88 } else {
89 cif = pMsg->RpcInterfaceInformation;
90 if (!cif) return RPC_S_INTERFACE_NOT_FOUND; /* ? */
93 status = RPCRT4_OpenBinding(bind);
94 if (status != RPC_S_OK) return status;
96 /* initialize packet header */
97 memset(&hdr, 0, sizeof(hdr));
98 hdr.rpc_ver = 4;
99 hdr.ptype = PKT_REQUEST;
100 hdr.object = bind->ObjectUuid; /* FIXME: IIRC iff no object, the header structure excludes this elt */
101 hdr.if_id = (bind->server) ? sif->InterfaceId.SyntaxGUID : cif->InterfaceId.SyntaxGUID;
102 hdr.if_vers =
103 (bind->server) ?
104 MAKELONG(sif->InterfaceId.SyntaxVersion.MinorVersion, sif->InterfaceId.SyntaxVersion.MajorVersion) :
105 MAKELONG(cif->InterfaceId.SyntaxVersion.MinorVersion, cif->InterfaceId.SyntaxVersion.MajorVersion);
106 hdr.opnum = pMsg->ProcNum;
107 /* only the low-order 3 octets of the DataRepresentation go in the header */
108 hdr.drep[0] = LOBYTE(LOWORD(pMsg->DataRepresentation));
109 hdr.drep[1] = HIBYTE(LOWORD(pMsg->DataRepresentation));
110 hdr.drep[2] = LOBYTE(HIWORD(pMsg->DataRepresentation));
111 hdr.len = pMsg->BufferLength;
113 /* transmit packet */
114 if (!WriteFile(bind->conn, &hdr, sizeof(hdr), NULL, NULL))
115 return GetLastError();
116 if (!WriteFile(bind->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL))
117 return GetLastError();
119 /* success */
120 return RPC_S_OK;
123 /***********************************************************************
124 * I_RpcReceive [RPCRT4.@]
126 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
128 RpcBinding* bind = (RpcBinding*)pMsg->Handle;
129 RPC_STATUS status;
130 RpcPktHdr hdr;
131 DWORD dwRead;
133 TRACE("(%p)\n", pMsg);
134 if (!bind) return RPC_S_INVALID_BINDING;
136 status = RPCRT4_OpenBinding(bind);
137 if (status != RPC_S_OK) return status;
139 /* read packet header */
140 #ifdef OVERLAPPED_WORKS
141 if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, &bind->ovl)) {
142 DWORD err = GetLastError();
143 if (err != ERROR_IO_PENDING) {
144 return err;
146 if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
148 #else
149 if (!ReadFile(bind->conn, &hdr, sizeof(hdr), &dwRead, NULL))
150 return GetLastError();
151 #endif
152 if (dwRead != sizeof(hdr)) return RPC_S_PROTOCOL_ERROR;
154 /* read packet body */
155 pMsg->BufferLength = hdr.len;
156 status = I_RpcGetBuffer(pMsg);
157 if (status != RPC_S_OK) return status;
158 #ifdef OVERLAPPED_WORKS
159 if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, &bind->ovl)) {
160 DWORD err = GetLastError();
161 if (err != ERROR_IO_PENDING) {
162 return err;
164 if (!GetOverlappedResult(bind->conn, &bind->ovl, &dwRead, TRUE)) return GetLastError();
166 #else
167 if (!ReadFile(bind->conn, pMsg->Buffer, hdr.len, &dwRead, NULL))
168 return GetLastError();
169 #endif
170 if (dwRead != hdr.len) return RPC_S_PROTOCOL_ERROR;
172 /* success */
173 return RPC_S_OK;
176 /***********************************************************************
177 * I_RpcSendReceive [RPCRT4.@]
179 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
181 RPC_STATUS status;
183 TRACE("(%p)\n", pMsg);
184 status = I_RpcSend(pMsg);
185 if (status == RPC_S_OK)
186 status = I_RpcReceive(pMsg);
187 return status;