blob: 6256d3bf27da7efd920cee36df4c9847ddc43dc3 [file] [log] [blame]
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18#include <stdio.h>
Pierre Ossman8a044ee2015-03-03 16:44:30 +010019#include <stdint.h>
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +000020
21#define NEED_REPLIES
22#include <X11/Xlib.h>
23#include <X11/Xlibint.h>
24#define _VNCEXT_PROTO_
25#include "vncExt.h"
26
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +000027static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
28 xEvent* w);
29
30static Bool extensionInited = False;
31static XExtCodes* codes = 0;
32
33static Bool checkExtension(Display* dpy)
34{
35 if (!extensionInited) {
36 extensionInited = True;
37 codes = XInitExtension(dpy, VNCEXTNAME);
38 if (!codes) return False;
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +000039 XESetWireToEvent(dpy, codes->first_event + VncExtQueryConnectNotify,
40 XVncExtQueryConnectNotifyWireToEvent);
41 }
42 return codes != 0;
43}
44
45Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep)
46{
47 if (!checkExtension(dpy)) return False;
48 *event_basep = codes->first_event;
49 *error_basep = codes->first_error;
50 return True;
51}
52
53Bool XVncExtSetParam(Display* dpy, const char* param)
54{
55 xVncExtSetParamReq* req;
56 xVncExtSetParamReply rep;
57
58 int paramLen = strlen(param);
59 if (paramLen > 255) return False;
60 if (!checkExtension(dpy)) return False;
61
62 LockDisplay(dpy);
63 GetReq(VncExtSetParam, req);
64 req->reqType = codes->major_opcode;
65 req->vncExtReqType = X_VncExtSetParam;
66 req->length += (paramLen + 3) >> 2;
67 req->paramLen = paramLen;
68 Data(dpy, param, paramLen);
69 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
70 UnlockDisplay(dpy);
71 SyncHandle();
72 return False;
73 }
74 UnlockDisplay(dpy);
75 SyncHandle();
76 return rep.success;
77}
78
79Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len)
80{
81 xVncExtGetParamReq* req;
82 xVncExtGetParamReply rep;
83
84 int paramLen = strlen(param);
85 *value = 0;
86 *len = 0;
87 if (paramLen > 255) return False;
88 if (!checkExtension(dpy)) return False;
89
90 LockDisplay(dpy);
91 GetReq(VncExtGetParam, req);
92 req->reqType = codes->major_opcode;
93 req->vncExtReqType = X_VncExtGetParam;
94 req->length += (paramLen + 3) >> 2;
95 req->paramLen = paramLen;
96 Data(dpy, param, paramLen);
97 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
98 UnlockDisplay(dpy);
99 SyncHandle();
100 return False;
101 }
102 if (rep.success) {
103 *len = rep.valueLen;
104 *value = (char*) Xmalloc (*len+1);
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200105 if (!*value) {
106 _XEatData(dpy, (*len+1)&~1);
107 return False;
108 }
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000109 _XReadPad(dpy, *value, *len);
110 (*value)[*len] = 0;
111 }
112 UnlockDisplay(dpy);
113 SyncHandle();
114 return rep.success;
115}
116
117char* XVncExtGetParamDesc(Display* dpy, const char* param)
118{
119 xVncExtGetParamDescReq* req;
120 xVncExtGetParamDescReply rep;
121 char* desc = 0;
122
123 int paramLen = strlen(param);
124 if (paramLen > 255) return False;
125 if (!checkExtension(dpy)) return False;
126
127 LockDisplay(dpy);
128 GetReq(VncExtGetParamDesc, req);
129 req->reqType = codes->major_opcode;
130 req->vncExtReqType = X_VncExtGetParamDesc;
131 req->length += (paramLen + 3) >> 2;
132 req->paramLen = paramLen;
133 Data(dpy, param, paramLen);
134 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
135 UnlockDisplay(dpy);
136 SyncHandle();
137 return False;
138 }
139 if (rep.success) {
140 desc = (char*)Xmalloc(rep.descLen+1);
uglym8d01de972016-05-11 19:04:02 +0300141 if (!desc) {
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200142 _XEatData(dpy, (rep.descLen+1)&~1);
143 return False;
144 }
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000145 _XReadPad(dpy, desc, rep.descLen);
146 desc[rep.descLen] = 0;
147 }
148 UnlockDisplay(dpy);
149 SyncHandle();
150 return desc;
151}
152
153char** XVncExtListParams(Display* dpy, int* nParams)
154{
155 xVncExtListParamsReq* req;
156 xVncExtListParamsReply rep;
157 char** list = 0;
158 char* ch;
159 int rlen, paramLen, i;
160
161 if (!checkExtension(dpy)) return False;
162
163 LockDisplay(dpy);
164 GetReq(VncExtListParams, req);
165 req->reqType = codes->major_opcode;
166 req->vncExtReqType = X_VncExtListParams;
167 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
168 UnlockDisplay(dpy);
169 SyncHandle();
170 return False;
171 }
172 UnlockDisplay(dpy);
173 SyncHandle();
174 if (rep.nParams) {
175 list = (char**)Xmalloc(rep.nParams * sizeof(char*));
176 rlen = rep.length << 2;
177 ch = (char*)Xmalloc(rlen + 1);
178 if (!list || !ch) {
179 if (list) Xfree((char*)list);
180 if (ch) Xfree(ch);
181 _XEatData(dpy, rlen);
182 UnlockDisplay(dpy);
183 SyncHandle();
184 return 0;
185 }
186 _XReadPad(dpy, ch, rlen);
187 paramLen = *ch++;
188 for (i = 0; i < rep.nParams; i++) {
189 list[i] = ch;
190 ch += paramLen;
191 paramLen = *ch;
192 *ch++ = 0;
193 }
194 }
195 *nParams = rep.nParams;
196 UnlockDisplay(dpy);
197 SyncHandle();
198 return list;
199}
200
201void XVncExtFreeParamList(char** list)
202{
203 if (list) {
204 Xfree(list[0]-1);
205 Xfree((char*)list);
206 }
207}
208
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000209Bool XVncExtSelectInput(Display* dpy, Window w, int mask)
210{
211 xVncExtSelectInputReq* req;
212
213 if (!checkExtension(dpy)) return False;
214
215 LockDisplay(dpy);
216 GetReq(VncExtSelectInput, req);
217 req->reqType = codes->major_opcode;
218 req->vncExtReqType = X_VncExtSelectInput;
219 req->window = w;
220 req->mask = mask;
221 UnlockDisplay(dpy);
222 SyncHandle();
223 return True;
224}
225
Pierre Ossman8f308112015-03-03 16:45:02 +0100226Bool XVncExtConnect(Display* dpy, const char* hostAndPort)
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000227{
228 xVncExtConnectReq* req;
229 xVncExtConnectReply rep;
230
231 int strLen = strlen(hostAndPort);
232 if (strLen > 255) return False;
233 if (!checkExtension(dpy)) return False;
234
235 LockDisplay(dpy);
236 GetReq(VncExtConnect, req);
237 req->reqType = codes->major_opcode;
238 req->vncExtReqType = X_VncExtConnect;
239 req->length += (strLen + 3) >> 2;
240 req->strLen = strLen;
241 Data(dpy, hostAndPort, strLen);
242 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
243 UnlockDisplay(dpy);
244 SyncHandle();
245 return False;
246 }
247 UnlockDisplay(dpy);
248 SyncHandle();
249 return rep.success;
250}
251
252Bool XVncExtGetQueryConnect(Display* dpy, char** addr, char** user,
253 int* timeout, void** opaqueId)
254{
255 xVncExtGetQueryConnectReq* req;
256 xVncExtGetQueryConnectReply rep;
257
258 if (!checkExtension(dpy)) return False;
259
260 LockDisplay(dpy);
261 GetReq(VncExtGetQueryConnect, req);
262 req->reqType = codes->major_opcode;
263 req->vncExtReqType = X_VncExtGetQueryConnect;
264 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
265 UnlockDisplay(dpy);
266 SyncHandle();
267 return False;
268 }
269 UnlockDisplay(dpy);
270 SyncHandle();
271
272 *addr = Xmalloc(rep.addrLen+1);
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200273 *user = Xmalloc(rep.userLen+1);
274 if (!*addr || !*user) {
275 Xfree(*addr);
276 Xfree(*user);
Pierre Ossman7728be22015-03-03 16:39:37 +0100277 _XEatData(dpy, ((rep.addrLen+1)&~1) + ((rep.userLen+1)&~1));
Pierre Ossmane83b14a2014-10-10 13:32:31 +0200278 return False;
279 }
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000280 _XReadPad(dpy, *addr, rep.addrLen);
281 (*addr)[rep.addrLen] = 0;
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000282 _XReadPad(dpy, *user, rep.userLen);
283 (*user)[rep.userLen] = 0;
284 *timeout = rep.timeout;
Pierre Ossman8a044ee2015-03-03 16:44:30 +0100285 *opaqueId = (void*)(intptr_t)rep.opaqueId;
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000286 return True;
287}
288
289Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve)
290{
291 xVncExtApproveConnectReq* req;
292
293 if (!checkExtension(dpy)) return False;
294
295 LockDisplay(dpy);
296 GetReq(VncExtApproveConnect, req);
297 req->reqType = codes->major_opcode;
298 req->vncExtReqType = X_VncExtApproveConnect;
299 req->approve = approve;
Pierre Ossman8a044ee2015-03-03 16:44:30 +0100300 req->opaqueId = (CARD32)(intptr_t)opaqueId;
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000301 UnlockDisplay(dpy);
302 SyncHandle();
303 return True;
304}
305
306
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +0000307static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
308 xEvent* w)
309{
310 XVncExtQueryConnectEvent* ev = (XVncExtQueryConnectEvent*)e;
311 xVncExtQueryConnectNotifyEvent* wire
312 = (xVncExtQueryConnectNotifyEvent*)w;
313 ev->type = wire->type & 0x7f;
314 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
315 ev->send_event = (wire->type & 0x80) != 0;
316 ev->display = dpy;
317 ev->window = wire->window;
318 return True;
319}