1 /**
2 * Copyright © 2011 Red Hat, Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #ifdef HAVE_DIX_CONFIG_H
25 #include <dix-config.h>
26 #endif
27
28 /*
29 * Protocol testing for XIPassiveGrab request.
30 */
31 #include <stdint.h>
32 #include <X11/X.h>
33 #include <X11/Xproto.h>
34 #include <X11/extensions/XI2proto.h>
35 #include "inputstr.h"
36 #include "windowstr.h"
37 #include "scrnintstr.h"
38 #include "xipassivegrab.h"
39 #include "exevents.h"
40 #include "exglobals.h"
41
42 #include "protocol-common.h"
43
44 extern ClientRec client_window;
45 static ClientRec client_request;
46
47 #define N_MODS 7
48 static uint32_t modifiers[N_MODS] = { 1, 2, 3, 4, 5, 6, 7 };
49
50 static struct test_data {
51 int num_modifiers;
52 } testdata;
53
54 int __wrap_GrabButton(ClientPtr client, DeviceIntPtr dev,
55 DeviceIntPtr modifier_device, int button,
56 GrabParameters *param, enum InputLevel grabtype,
57 GrabMask *mask);
58 int __real_GrabButton(ClientPtr client, DeviceIntPtr dev,
59 DeviceIntPtr modifier_device, int button,
60 GrabParameters *param, enum InputLevel grabtype,
61 GrabMask *mask);
62 static void reply_XIPassiveGrabDevice_data(ClientPtr client, int len,
63 char *data, void *closure);
64
65 int
__wrap_GrabButton(ClientPtr client,DeviceIntPtr dev,DeviceIntPtr modifier_device,int button,GrabParameters * param,enum InputLevel grabtype,GrabMask * mask)66 __wrap_GrabButton(ClientPtr client, DeviceIntPtr dev,
67 DeviceIntPtr modifier_device, int button,
68 GrabParameters *param, enum InputLevel grabtype,
69 GrabMask *mask)
70 {
71 if (!enable_GrabButton_wrap)
72 __real_GrabButton(client, dev, modifier_device, button, param, grabtype, mask);
73
74 /* Fail every odd modifier */
75 if (param->modifiers % 2)
76 return BadAccess;
77
78 return Success;
79 }
80
81 static void
reply_XIPassiveGrabDevice(ClientPtr client,int len,char * data,void * closure)82 reply_XIPassiveGrabDevice(ClientPtr client, int len, char *data, void *closure)
83 {
84 xXIPassiveGrabDeviceReply *rep = (xXIPassiveGrabDeviceReply *) data;
85
86 if (client->swapped) {
87 swaps(&rep->sequenceNumber);
88 swapl(&rep->length);
89 swaps(&rep->num_modifiers);
90
91 testdata.num_modifiers = rep->num_modifiers;
92 }
93
94 reply_check_defaults(rep, len, XIPassiveGrabDevice);
95
96 /* ProcXIPassiveGrabDevice sends the data in two batches, let the second
97 * handler handle the modifier data */
98 if (rep->num_modifiers > 0)
99 reply_handler = reply_XIPassiveGrabDevice_data;
100 }
101
102 static void
reply_XIPassiveGrabDevice_data(ClientPtr client,int len,char * data,void * closure)103 reply_XIPassiveGrabDevice_data(ClientPtr client, int len, char *data,
104 void *closure)
105 {
106 int i;
107
108 xXIGrabModifierInfo *mods = (xXIGrabModifierInfo *) data;
109
110 for (i = 0; i < testdata.num_modifiers; i++, mods++) {
111 if (client->swapped)
112 swapl(&mods->modifiers);
113
114 /* 1 - 7 is the range we use for the global modifiers array
115 * above */
116 assert(mods->modifiers > 0);
117 assert(mods->modifiers <= 7);
118 assert(mods->modifiers % 2 == 1); /* because we fail odd ones */
119 assert(mods->status != Success);
120 assert(mods->pad0 == 0);
121 assert(mods->pad1 == 0);
122 }
123
124 reply_handler = reply_XIPassiveGrabDevice;
125 }
126
127 static void
request_XIPassiveGrabDevice(ClientPtr client,xXIPassiveGrabDeviceReq * req,int error,int errval)128 request_XIPassiveGrabDevice(ClientPtr client, xXIPassiveGrabDeviceReq * req,
129 int error, int errval)
130 {
131 int rc;
132 int local_modifiers;
133 int mask_len;
134
135 client_request.req_len = req->length;
136 rc = ProcXIPassiveGrabDevice(&client_request);
137 assert(rc == error);
138
139 if (rc != Success)
140 assert(client_request.errorValue == errval);
141
142 client_request.swapped = TRUE;
143 swaps(&req->length);
144 swapl(&req->time);
145 swapl(&req->grab_window);
146 swapl(&req->cursor);
147 swapl(&req->detail);
148 swaps(&req->deviceid);
149 local_modifiers = req->num_modifiers;
150 swaps(&req->num_modifiers);
151 mask_len = req->mask_len;
152 swaps(&req->mask_len);
153
154 while (local_modifiers--) {
155 CARD32 *mod = (CARD32 *) (req + 1) + mask_len + local_modifiers;
156
157 swapl(mod);
158 }
159
160 rc = SProcXIPassiveGrabDevice(&client_request);
161 assert(rc == error);
162
163 if (rc != Success)
164 assert(client_request.errorValue == errval);
165 }
166
167 static unsigned char *data[4096]; /* the request buffer */
168 static void
test_XIPassiveGrabDevice(void)169 test_XIPassiveGrabDevice(void)
170 {
171 int i;
172 xXIPassiveGrabDeviceReq *request = (xXIPassiveGrabDeviceReq *) data;
173 unsigned char *mask;
174
175 request_init(request, XIPassiveGrabDevice);
176
177 request->grab_window = CLIENT_WINDOW_ID;
178
179 reply_handler = reply_XIPassiveGrabDevice;
180 client_request = init_client(request->length, request);
181
182 printf("Testing invalid device\n");
183 request->deviceid = 12;
184 request_XIPassiveGrabDevice(&client_request, request, BadDevice,
185 request->deviceid);
186
187 printf("Testing invalid length\n");
188 request->length -= 2;
189 request_XIPassiveGrabDevice(&client_request, request, BadLength,
190 client_request.errorValue);
191 /* re-init request since swapped length test leaves some values swapped */
192 request_init(request, XIPassiveGrabDevice);
193 request->grab_window = CLIENT_WINDOW_ID;
194 request->deviceid = XIAllMasterDevices;
195
196 printf("Testing invalid grab types\n");
197 for (i = XIGrabtypeTouchBegin + 1; i < 0xFF; i++) {
198 request->grab_type = i;
199 request_XIPassiveGrabDevice(&client_request, request, BadValue,
200 request->grab_type);
201 }
202
203 printf("Testing invalid grab type + detail combinations\n");
204 request->grab_type = XIGrabtypeEnter;
205 request->detail = 1;
206 request_XIPassiveGrabDevice(&client_request, request, BadValue,
207 request->detail);
208
209 request->grab_type = XIGrabtypeFocusIn;
210 request_XIPassiveGrabDevice(&client_request, request, BadValue,
211 request->detail);
212
213 request->detail = 0;
214
215 printf("Testing invalid masks\n");
216 mask = (unsigned char *) &request[1];
217
218 request->mask_len = bytes_to_int32(XI2LASTEVENT + 1);
219 request->length += request->mask_len;
220 SetBit(mask, XI2LASTEVENT + 1);
221 request_XIPassiveGrabDevice(&client_request, request, BadValue,
222 XI2LASTEVENT + 1);
223
224 ClearBit(mask, XI2LASTEVENT + 1);
225
226 /* tested all special cases now, test a few valid cases */
227
228 /* no modifiers */
229 request->deviceid = XIAllDevices;
230 request->grab_type = XIGrabtypeButton;
231 request->detail = XIAnyButton;
232 request_XIPassiveGrabDevice(&client_request, request, Success, 0);
233
234 /* Set a few random masks to make sure we handle modifiers correctly */
235 SetBit(mask, XI_ButtonPress);
236 SetBit(mask, XI_KeyPress);
237 SetBit(mask, XI_Enter);
238
239 /* some modifiers */
240 request->num_modifiers = N_MODS;
241 request->length += N_MODS;
242 memcpy((uint32_t *) (request + 1) + request->mask_len, modifiers,
243 sizeof(modifiers));
244 request_XIPassiveGrabDevice(&client_request, request, Success, 0);
245 }
246
247 int
protocol_xipassivegrabdevice_test(void)248 protocol_xipassivegrabdevice_test(void)
249 {
250 init_simple();
251
252 test_XIPassiveGrabDevice();
253
254 return 0;
255 }
256