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/* Test relies on assert() */ 25#undef NDEBUG 26 27#ifdef HAVE_DIX_CONFIG_H 28#include <dix-config.h> 29#endif 30 31/* 32 * Protocol testing for XIPassiveGrab request. 33 */ 34#include <stdint.h> 35#include <X11/X.h> 36#include <X11/Xproto.h> 37#include <X11/extensions/XI2proto.h> 38#include "inputstr.h" 39#include "windowstr.h" 40#include "scrnintstr.h" 41#include "xipassivegrab.h" 42#include "exevents.h" 43#include "exglobals.h" 44 45#include "protocol-common.h" 46 47extern ClientRec client_window; 48static ClientRec client_request; 49 50#define N_MODS 7 51static uint32_t modifiers[N_MODS] = { 1, 2, 3, 4, 5, 6, 7 }; 52 53static struct test_data { 54 int num_modifiers; 55} testdata; 56 57int __wrap_GrabButton(ClientPtr client, DeviceIntPtr dev, 58 DeviceIntPtr modifier_device, int button, 59 GrabParameters *param, enum InputLevel grabtype, 60 GrabMask *mask); 61int __real_GrabButton(ClientPtr client, DeviceIntPtr dev, 62 DeviceIntPtr modifier_device, int button, 63 GrabParameters *param, enum InputLevel grabtype, 64 GrabMask *mask); 65static void reply_XIPassiveGrabDevice_data(ClientPtr client, int len, 66 char *data, void *closure); 67 68int 69__wrap_GrabButton(ClientPtr client, DeviceIntPtr dev, 70 DeviceIntPtr modifier_device, int button, 71 GrabParameters *param, enum InputLevel grabtype, 72 GrabMask *mask) 73{ 74 if (!enable_GrabButton_wrap) 75 __real_GrabButton(client, dev, modifier_device, button, param, grabtype, mask); 76 77 /* Fail every odd modifier */ 78 if (param->modifiers % 2) 79 return BadAccess; 80 81 return Success; 82} 83 84static void 85reply_XIPassiveGrabDevice(ClientPtr client, int len, char *data, void *closure) 86{ 87 xXIPassiveGrabDeviceReply *rep = (xXIPassiveGrabDeviceReply *) data; 88 89 if (client->swapped) { 90 swaps(&rep->sequenceNumber); 91 swapl(&rep->length); 92 swaps(&rep->num_modifiers); 93 94 testdata.num_modifiers = rep->num_modifiers; 95 } 96 97 reply_check_defaults(rep, len, XIPassiveGrabDevice); 98 99 /* ProcXIPassiveGrabDevice sends the data in two batches, let the second 100 * handler handle the modifier data */ 101 if (rep->num_modifiers > 0) 102 reply_handler = reply_XIPassiveGrabDevice_data; 103} 104 105static void 106reply_XIPassiveGrabDevice_data(ClientPtr client, int len, char *data, 107 void *closure) 108{ 109 int i; 110 111 xXIGrabModifierInfo *mods = (xXIGrabModifierInfo *) data; 112 113 for (i = 0; i < testdata.num_modifiers; i++, mods++) { 114 if (client->swapped) 115 swapl(&mods->modifiers); 116 117 /* 1 - 7 is the range we use for the global modifiers array 118 * above */ 119 assert(mods->modifiers > 0); 120 assert(mods->modifiers <= 7); 121 assert(mods->modifiers % 2 == 1); /* because we fail odd ones */ 122 assert(mods->status != Success); 123 assert(mods->pad0 == 0); 124 assert(mods->pad1 == 0); 125 } 126 127 reply_handler = reply_XIPassiveGrabDevice; 128} 129 130static void 131request_XIPassiveGrabDevice(ClientPtr client, xXIPassiveGrabDeviceReq * req, 132 int error, int errval) 133{ 134 int rc; 135 int local_modifiers; 136 int mask_len; 137 138 client_request.req_len = req->length; 139 rc = ProcXIPassiveGrabDevice(&client_request); 140 assert(rc == error); 141 142 if (rc != Success) 143 assert(client_request.errorValue == errval); 144 145 client_request.swapped = TRUE; 146 swaps(&req->length); 147 swapl(&req->time); 148 swapl(&req->grab_window); 149 swapl(&req->cursor); 150 swapl(&req->detail); 151 swaps(&req->deviceid); 152 local_modifiers = req->num_modifiers; 153 swaps(&req->num_modifiers); 154 mask_len = req->mask_len; 155 swaps(&req->mask_len); 156 157 while (local_modifiers--) { 158 CARD32 *mod = (CARD32 *) (req + 1) + mask_len + local_modifiers; 159 160 swapl(mod); 161 } 162 163 rc = SProcXIPassiveGrabDevice(&client_request); 164 assert(rc == error); 165 166 if (rc != Success) 167 assert(client_request.errorValue == errval); 168} 169 170static unsigned char *data[4096]; /* the request buffer */ 171static void 172test_XIPassiveGrabDevice(void) 173{ 174 int i; 175 xXIPassiveGrabDeviceReq *request = (xXIPassiveGrabDeviceReq *) data; 176 unsigned char *mask; 177 178 request_init(request, XIPassiveGrabDevice); 179 180 request->grab_window = CLIENT_WINDOW_ID; 181 182 reply_handler = reply_XIPassiveGrabDevice; 183 client_request = init_client(request->length, request); 184 185 printf("Testing invalid device\n"); 186 request->deviceid = 12; 187 request_XIPassiveGrabDevice(&client_request, request, BadDevice, 188 request->deviceid); 189 190 printf("Testing invalid length\n"); 191 request->length -= 2; 192 request_XIPassiveGrabDevice(&client_request, request, BadLength, 193 client_request.errorValue); 194 /* re-init request since swapped length test leaves some values swapped */ 195 request_init(request, XIPassiveGrabDevice); 196 request->grab_window = CLIENT_WINDOW_ID; 197 request->deviceid = XIAllMasterDevices; 198 199 printf("Testing invalid grab types\n"); 200 for (i = XIGrabtypeGestureSwipeBegin + 1; i < 0xFF; i++) { 201 request->grab_type = i; 202 request_XIPassiveGrabDevice(&client_request, request, BadValue, 203 request->grab_type); 204 } 205 206 printf("Testing invalid grab type + detail combinations\n"); 207 request->grab_type = XIGrabtypeEnter; 208 request->detail = 1; 209 request_XIPassiveGrabDevice(&client_request, request, BadValue, 210 request->detail); 211 212 request->grab_type = XIGrabtypeFocusIn; 213 request_XIPassiveGrabDevice(&client_request, request, BadValue, 214 request->detail); 215 216 request->detail = 0; 217 218 printf("Testing invalid masks\n"); 219 mask = (unsigned char *) &request[1]; 220 221 request->mask_len = bytes_to_int32(XI2LASTEVENT + 1); 222 request->length += request->mask_len; 223 SetBit(mask, XI2LASTEVENT + 1); 224 request_XIPassiveGrabDevice(&client_request, request, BadValue, 225 XI2LASTEVENT + 1); 226 227 ClearBit(mask, XI2LASTEVENT + 1); 228 229 /* tested all special cases now, test a few valid cases */ 230 231 /* no modifiers */ 232 request->deviceid = XIAllDevices; 233 request->grab_type = XIGrabtypeButton; 234 request->detail = XIAnyButton; 235 request_XIPassiveGrabDevice(&client_request, request, Success, 0); 236 237 /* Set a few random masks to make sure we handle modifiers correctly */ 238 SetBit(mask, XI_ButtonPress); 239 SetBit(mask, XI_KeyPress); 240 SetBit(mask, XI_Enter); 241 242 /* some modifiers */ 243 request->num_modifiers = N_MODS; 244 request->length += N_MODS; 245 memcpy((uint32_t *) (request + 1) + request->mask_len, modifiers, 246 sizeof(modifiers)); 247 request_XIPassiveGrabDevice(&client_request, request, Success, 0); 248} 249 250int 251protocol_xipassivegrabdevice_test(void) 252{ 253 init_simple(); 254 255 test_XIPassiveGrabDevice(); 256 257 return 0; 258} 259