Add RtlDowncaseUnicodeChar(), RtlEqualComputerName(),
[wine] / dlls / rpcrt4 / rpc_message.c
1 /*
2  * RPC messages
3  *
4  * Copyright 2001-2002 Ove Kåven, TransGaming Technologies
5  *
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.
10  *
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.
15  *
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
19  *
20  * TODO:
21  *  - figure out whether we *really* got this right
22  *  - check for errors and throw exceptions
23  *  - decide if OVERLAPPED_WORKS
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winerror.h"
32 #include "winreg.h"
33
34 #include "rpc.h"
35 #include "rpcdcep.h"
36
37 #include "wine/debug.h"
38
39 #include "rpc_binding.h"
40 #include "rpc_defs.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(ole);
43
44 /***********************************************************************
45  *           I_RpcGetBuffer [RPCRT4.@]
46  */
47 RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
48 {
49   void* buf;
50
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;
58 }
59
60 /***********************************************************************
61  *           I_RpcFreeBuffer [RPCRT4.@]
62  */
63 RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
64 {
65   TRACE("(%p)\n", pMsg);
66   /* FIXME: pfnFree? */
67   HeapFree(GetProcessHeap(), 0, pMsg->Buffer);
68   pMsg->Buffer = NULL;
69   return S_OK;
70 }
71
72 /***********************************************************************
73  *           I_RpcSend [RPCRT4.@]
74  */
75 RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
76 {
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;
85
86   TRACE("(%p)\n", pMsg);
87   if (!bind) return RPC_S_INVALID_BINDING;
88
89   status = RPCRT4_OpenBinding(bind, &conn);
90   if (status != RPC_S_OK) return status;
91
92   obj = &bind->ObjectUuid;
93   act = &bind->ActiveUuid;
94
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; /* ? */
101   }
102
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;
120
121   /* transmit packet */
122   if (!WriteFile(conn->conn, &hdr, sizeof(hdr), NULL, NULL)) {
123     status = GetLastError();
124     goto fail;
125   }
126   if (pMsg->BufferLength && !WriteFile(conn->conn, pMsg->Buffer, pMsg->BufferLength, NULL, NULL)) {
127     status = GetLastError();
128     goto fail;
129   }
130
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;
136   }
137   RPCRT4_CloseBinding(bind, conn);
138   status = RPC_S_OK;
139 fail:
140
141   return status;
142 }
143
144 /***********************************************************************
145  *           I_RpcReceive [RPCRT4.@]
146  */
147 RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
148 {
149   RpcBinding* bind = (RpcBinding*)pMsg->Handle;
150   RpcConnection* conn;
151   UUID* act;
152   RPC_STATUS status;
153   RpcPktHdr hdr;
154   DWORD dwRead;
155
156   TRACE("(%p)\n", pMsg);
157   if (!bind) return RPC_S_INVALID_BINDING;
158
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;
165   }
166
167   act = &bind->ActiveUuid;
168
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;
177       }
178       if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
179         status = GetLastError();
180         goto fail;
181       }
182     }
183 #else
184     if (!ReadFile(conn->conn, &hdr, sizeof(hdr), &dwRead, NULL)) {
185       status = GetLastError();
186       goto fail;
187     }
188 #endif
189     if (dwRead != sizeof(hdr)) {
190       status = RPC_S_PROTOCOL_ERROR;
191       goto fail;
192     }
193
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;
205       }
206       if (!GetOverlappedResult(conn->conn, &conn->ovl, &dwRead, TRUE)) {
207         status = GetLastError();
208         goto fail;
209       }
210     }
211 #else
212     if (!ReadFile(conn->conn, pMsg->Buffer, hdr.len, &dwRead, NULL)) {
213       status = GetLastError();
214       goto fail;
215     }
216 #endif
217     if (dwRead != hdr.len) {
218       status = RPC_S_PROTOCOL_ERROR;
219       goto fail;
220     }
221
222     /* success */
223     status = RPC_S_OK;
224
225     /* FIXME: check packet type, destination, etc? */
226     break;
227   }
228 fail:
229   RPCRT4_CloseBinding(bind, conn);
230   return status;
231 }
232
233 /***********************************************************************
234  *           I_RpcSendReceive [RPCRT4.@]
235  */
236 RPC_STATUS WINAPI I_RpcSendReceive(PRPC_MESSAGE pMsg)
237 {
238   RPC_STATUS status;
239
240   TRACE("(%p)\n", pMsg);
241   status = I_RpcSend(pMsg);
242   if (status == RPC_S_OK)
243     status = I_RpcReceive(pMsg);
244   return status;
245 }