1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3 
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
15 
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 
25 ********************************************************/
26 
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
29 #endif
30 
31 #include <stdio.h>
32 #include <X11/X.h>
33 #include <X11/Xproto.h>
34 #include "misc.h"
35 #include "inputstr.h"
36 #define	XKBSRV_NEED_FILE_FUNCS
37 #include <xkbsrv.h>
38 #include "extnsionst.h"
39 #include "extinit.h"
40 #include "xace.h"
41 #include "xkb.h"
42 #include "protocol-versions.h"
43 
44 #include <X11/extensions/XI.h>
45 #include <X11/extensions/XKMformat.h>
46 
47 int XkbEventBase;
48 static int XkbErrorBase;
49 int XkbReqCode;
50 int XkbKeyboardErrorCode;
51 CARD32 xkbDebugFlags = 0;
52 static CARD32 xkbDebugCtrls = 0;
53 
54 static RESTYPE RT_XKBCLIENT;
55 
56 /***====================================================================***/
57 
58 #define	CHK_DEVICE(dev, id, client, access_mode, lf) {\
59     int why;\
60     int tmprc = lf(&(dev), id, client, access_mode, &why);\
61     if (tmprc != Success) {\
62 	client->errorValue = _XkbErrCode2(why, id);\
63 	return tmprc;\
64     }\
65 }
66 
67 #define	CHK_KBD_DEVICE(dev, id, client, mode) \
68     CHK_DEVICE(dev, id, client, mode, _XkbLookupKeyboard)
69 #define	CHK_LED_DEVICE(dev, id, client, mode) \
70     CHK_DEVICE(dev, id, client, mode, _XkbLookupLedDevice)
71 #define	CHK_BELL_DEVICE(dev, id, client, mode) \
72     CHK_DEVICE(dev, id, client, mode, _XkbLookupBellDevice)
73 #define	CHK_ANY_DEVICE(dev, id, client, mode) \
74     CHK_DEVICE(dev, id, client, mode, _XkbLookupAnyDevice)
75 
76 #define	CHK_ATOM_ONLY2(a,ev,er) {\
77 	if (((a)==None)||(!ValidAtom((a)))) {\
78 	    (ev)= (XID)(a);\
79 	    return er;\
80 	}\
81 }
82 #define	CHK_ATOM_ONLY(a) \
83 	CHK_ATOM_ONLY2(a,client->errorValue,BadAtom)
84 
85 #define	CHK_ATOM_OR_NONE3(a,ev,er,ret) {\
86 	if (((a)!=None)&&(!ValidAtom((a)))) {\
87 	    (ev)= (XID)(a);\
88 	    (er)= BadAtom;\
89 	    return ret;\
90 	}\
91 }
92 #define	CHK_ATOM_OR_NONE2(a,ev,er) {\
93 	if (((a)!=None)&&(!ValidAtom((a)))) {\
94 	    (ev)= (XID)(a);\
95 	    return er;\
96 	}\
97 }
98 #define	CHK_ATOM_OR_NONE(a) \
99 	CHK_ATOM_OR_NONE2(a,client->errorValue,BadAtom)
100 
101 #define	CHK_MASK_LEGAL3(err,mask,legal,ev,er,ret)	{\
102 	if ((mask)&(~(legal))) { \
103 	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
104 	    (er)= BadValue;\
105 	    return ret;\
106 	}\
107 }
108 #define	CHK_MASK_LEGAL2(err,mask,legal,ev,er)	{\
109 	if ((mask)&(~(legal))) { \
110 	    (ev)= _XkbErrCode2((err),((mask)&(~(legal))));\
111 	    return er;\
112 	}\
113 }
114 #define	CHK_MASK_LEGAL(err,mask,legal) \
115 	CHK_MASK_LEGAL2(err,mask,legal,client->errorValue,BadValue)
116 
117 #define	CHK_MASK_MATCH(err,affect,value) {\
118 	if ((value)&(~(affect))) { \
119 	    client->errorValue= _XkbErrCode2((err),((value)&(~(affect))));\
120 	    return BadMatch;\
121 	}\
122 }
123 #define	CHK_MASK_OVERLAP(err,m1,m2) {\
124 	if ((m1)&(m2)) { \
125 	    client->errorValue= _XkbErrCode2((err),((m1)&(m2)));\
126 	    return BadMatch;\
127 	}\
128 }
129 #define	CHK_KEY_RANGE2(err,first,num,x,ev,er) {\
130 	if (((unsigned)(first)+(num)-1)>(x)->max_key_code) {\
131 	    (ev)=_XkbErrCode4(err,(first),(num),(x)->max_key_code);\
132 	    return er;\
133 	}\
134 	else if ( (first)<(x)->min_key_code ) {\
135 	    (ev)=_XkbErrCode3(err+1,(first),xkb->min_key_code);\
136 	    return er;\
137 	}\
138 }
139 #define	CHK_KEY_RANGE(err,first,num,x)  \
140 	CHK_KEY_RANGE2(err,first,num,x,client->errorValue,BadValue)
141 
142 #define	CHK_REQ_KEY_RANGE2(err,first,num,r,ev,er) {\
143 	if (((unsigned)(first)+(num)-1)>(r)->maxKeyCode) {\
144 	    (ev)=_XkbErrCode4(err,(first),(num),(r)->maxKeyCode);\
145 	    return er;\
146 	}\
147 	else if ( (first)<(r)->minKeyCode ) {\
148 	    (ev)=_XkbErrCode3(err+1,(first),(r)->minKeyCode);\
149 	    return er;\
150 	}\
151 }
152 #define	CHK_REQ_KEY_RANGE(err,first,num,r)  \
153 	CHK_REQ_KEY_RANGE2(err,first,num,r,client->errorValue,BadValue)
154 
155 static Bool
_XkbCheckRequestBounds(ClientPtr client,void * stuff,void * from,void * to)156 _XkbCheckRequestBounds(ClientPtr client, void *stuff, void *from, void *to) {
157     char *cstuff = (char *)stuff;
158     char *cfrom = (char *)from;
159     char *cto = (char *)to;
160 
161     return cfrom < cto &&
162            cfrom >= cstuff &&
163            cfrom < cstuff + ((size_t)client->req_len << 2) &&
164            cto >= cstuff &&
165            cto <= cstuff + ((size_t)client->req_len << 2);
166 }
167 
168 /***====================================================================***/
169 
170 int
ProcXkbUseExtension(ClientPtr client)171 ProcXkbUseExtension(ClientPtr client)
172 {
173     REQUEST(xkbUseExtensionReq);
174     xkbUseExtensionReply rep;
175     int supported;
176 
177     REQUEST_SIZE_MATCH(xkbUseExtensionReq);
178     if (stuff->wantedMajor != SERVER_XKB_MAJOR_VERSION) {
179         /* pre-release version 0.65 is compatible with 1.00 */
180         supported = ((SERVER_XKB_MAJOR_VERSION == 1) &&
181                      (stuff->wantedMajor == 0) && (stuff->wantedMinor == 65));
182     }
183     else
184         supported = 1;
185 
186     if ((supported) && (!(client->xkbClientFlags & _XkbClientInitialized))) {
187         client->xkbClientFlags = _XkbClientInitialized;
188         if (stuff->wantedMajor == 0)
189             client->xkbClientFlags |= _XkbClientIsAncient;
190     }
191     else if (xkbDebugFlags & 0x1) {
192         ErrorF
193             ("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n",
194              client->index, (long) client->clientAsMask, stuff->wantedMajor,
195              stuff->wantedMinor, SERVER_XKB_MAJOR_VERSION,
196              SERVER_XKB_MINOR_VERSION);
197     }
198     rep = (xkbUseExtensionReply) {
199         .type = X_Reply,
200         .supported = supported,
201         .sequenceNumber = client->sequence,
202         .length = 0,
203         .serverMajor = SERVER_XKB_MAJOR_VERSION,
204         .serverMinor = SERVER_XKB_MINOR_VERSION
205     };
206     if (client->swapped) {
207         swaps(&rep.sequenceNumber);
208         swaps(&rep.serverMajor);
209         swaps(&rep.serverMinor);
210     }
211     WriteToClient(client, SIZEOF(xkbUseExtensionReply), &rep);
212     return Success;
213 }
214 
215 /***====================================================================***/
216 
217 int
ProcXkbSelectEvents(ClientPtr client)218 ProcXkbSelectEvents(ClientPtr client)
219 {
220     unsigned legal;
221     DeviceIntPtr dev;
222     XkbInterestPtr masks;
223 
224     REQUEST(xkbSelectEventsReq);
225 
226     REQUEST_AT_LEAST_SIZE(xkbSelectEventsReq);
227 
228     if (!(client->xkbClientFlags & _XkbClientInitialized))
229         return BadAccess;
230 
231     CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixUseAccess);
232 
233     if (((stuff->affectWhich & XkbMapNotifyMask) != 0) && (stuff->affectMap)) {
234         client->mapNotifyMask &= ~stuff->affectMap;
235         client->mapNotifyMask |= (stuff->affectMap & stuff->map);
236     }
237     if ((stuff->affectWhich & (~XkbMapNotifyMask)) == 0)
238         return Success;
239 
240     masks = XkbFindClientResource((DevicePtr) dev, client);
241     if (!masks) {
242         XID id = FakeClientID(client->index);
243 
244         if (!AddResource(id, RT_XKBCLIENT, dev))
245             return BadAlloc;
246         masks = XkbAddClientResource((DevicePtr) dev, client, id);
247     }
248     if (masks) {
249         union {
250             CARD8 *c8;
251             CARD16 *c16;
252             CARD32 *c32;
253         } from, to;
254         register unsigned bit, ndx, maskLeft, dataLeft, size;
255 
256         from.c8 = (CARD8 *) &stuff[1];
257         dataLeft = (stuff->length * 4) - SIZEOF(xkbSelectEventsReq);
258         maskLeft = (stuff->affectWhich & (~XkbMapNotifyMask));
259         for (ndx = 0, bit = 1; (maskLeft != 0); ndx++, bit <<= 1) {
260             if ((bit & maskLeft) == 0)
261                 continue;
262             maskLeft &= ~bit;
263             switch (ndx) {
264             case XkbNewKeyboardNotify:
265                 to.c16 = &client->newKeyboardNotifyMask;
266                 legal = XkbAllNewKeyboardEventsMask;
267                 size = 2;
268                 break;
269             case XkbStateNotify:
270                 to.c16 = &masks->stateNotifyMask;
271                 legal = XkbAllStateEventsMask;
272                 size = 2;
273                 break;
274             case XkbControlsNotify:
275                 to.c32 = &masks->ctrlsNotifyMask;
276                 legal = XkbAllControlEventsMask;
277                 size = 4;
278                 break;
279             case XkbIndicatorStateNotify:
280                 to.c32 = &masks->iStateNotifyMask;
281                 legal = XkbAllIndicatorEventsMask;
282                 size = 4;
283                 break;
284             case XkbIndicatorMapNotify:
285                 to.c32 = &masks->iMapNotifyMask;
286                 legal = XkbAllIndicatorEventsMask;
287                 size = 4;
288                 break;
289             case XkbNamesNotify:
290                 to.c16 = &masks->namesNotifyMask;
291                 legal = XkbAllNameEventsMask;
292                 size = 2;
293                 break;
294             case XkbCompatMapNotify:
295                 to.c8 = &masks->compatNotifyMask;
296                 legal = XkbAllCompatMapEventsMask;
297                 size = 1;
298                 break;
299             case XkbBellNotify:
300                 to.c8 = &masks->bellNotifyMask;
301                 legal = XkbAllBellEventsMask;
302                 size = 1;
303                 break;
304             case XkbActionMessage:
305                 to.c8 = &masks->actionMessageMask;
306                 legal = XkbAllActionMessagesMask;
307                 size = 1;
308                 break;
309             case XkbAccessXNotify:
310                 to.c16 = &masks->accessXNotifyMask;
311                 legal = XkbAllAccessXEventsMask;
312                 size = 2;
313                 break;
314             case XkbExtensionDeviceNotify:
315                 to.c16 = &masks->extDevNotifyMask;
316                 legal = XkbAllExtensionDeviceEventsMask;
317                 size = 2;
318                 break;
319             default:
320                 client->errorValue = _XkbErrCode2(33, bit);
321                 return BadValue;
322             }
323 
324             if (stuff->clear & bit) {
325                 if (size == 2)
326                     to.c16[0] = 0;
327                 else if (size == 4)
328                     to.c32[0] = 0;
329                 else
330                     to.c8[0] = 0;
331             }
332             else if (stuff->selectAll & bit) {
333                 if (size == 2)
334                     to.c16[0] = ~0;
335                 else if (size == 4)
336                     to.c32[0] = ~0;
337                 else
338                     to.c8[0] = ~0;
339             }
340             else {
341                 if (dataLeft < (size * 2))
342                     return BadLength;
343                 if (size == 2) {
344                     CHK_MASK_MATCH(ndx, from.c16[0], from.c16[1]);
345                     CHK_MASK_LEGAL(ndx, from.c16[0], legal);
346                     to.c16[0] &= ~from.c16[0];
347                     to.c16[0] |= (from.c16[0] & from.c16[1]);
348                 }
349                 else if (size == 4) {
350                     CHK_MASK_MATCH(ndx, from.c32[0], from.c32[1]);
351                     CHK_MASK_LEGAL(ndx, from.c32[0], legal);
352                     to.c32[0] &= ~from.c32[0];
353                     to.c32[0] |= (from.c32[0] & from.c32[1]);
354                 }
355                 else {
356                     CHK_MASK_MATCH(ndx, from.c8[0], from.c8[1]);
357                     CHK_MASK_LEGAL(ndx, from.c8[0], legal);
358                     to.c8[0] &= ~from.c8[0];
359                     to.c8[0] |= (from.c8[0] & from.c8[1]);
360                     size = 2;
361                 }
362                 from.c8 += (size * 2);
363                 dataLeft -= (size * 2);
364             }
365         }
366         if (dataLeft > 2) {
367             ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",
368                    dataLeft);
369             return BadLength;
370         }
371         return Success;
372     }
373     return BadAlloc;
374 }
375 
376 /***====================================================================***/
377 /**
378  * Ring a bell on the given device for the given client.
379  */
380 static int
_XkbBell(ClientPtr client,DeviceIntPtr dev,WindowPtr pWin,int bellClass,int bellID,int pitch,int duration,int percent,int forceSound,int eventOnly,Atom name)381 _XkbBell(ClientPtr client, DeviceIntPtr dev, WindowPtr pWin,
382          int bellClass, int bellID, int pitch, int duration,
383          int percent, int forceSound, int eventOnly, Atom name)
384 {
385     int base;
386     void *ctrl;
387     int oldPitch, oldDuration;
388     int newPercent;
389 
390     if (bellClass == KbdFeedbackClass) {
391         KbdFeedbackPtr k;
392 
393         if (bellID == XkbDfltXIId)
394             k = dev->kbdfeed;
395         else {
396             for (k = dev->kbdfeed; k; k = k->next) {
397                 if (k->ctrl.id == bellID)
398                     break;
399             }
400         }
401         if (!k) {
402             client->errorValue = _XkbErrCode2(0x5, bellID);
403             return BadValue;
404         }
405         base = k->ctrl.bell;
406         ctrl = (void *) &(k->ctrl);
407         oldPitch = k->ctrl.bell_pitch;
408         oldDuration = k->ctrl.bell_duration;
409         if (pitch != 0) {
410             if (pitch == -1)
411                 k->ctrl.bell_pitch = defaultKeyboardControl.bell_pitch;
412             else
413                 k->ctrl.bell_pitch = pitch;
414         }
415         if (duration != 0) {
416             if (duration == -1)
417                 k->ctrl.bell_duration = defaultKeyboardControl.bell_duration;
418             else
419                 k->ctrl.bell_duration = duration;
420         }
421     }
422     else if (bellClass == BellFeedbackClass) {
423         BellFeedbackPtr b;
424 
425         if (bellID == XkbDfltXIId)
426             b = dev->bell;
427         else {
428             for (b = dev->bell; b; b = b->next) {
429                 if (b->ctrl.id == bellID)
430                     break;
431             }
432         }
433         if (!b) {
434             client->errorValue = _XkbErrCode2(0x6, bellID);
435             return BadValue;
436         }
437         base = b->ctrl.percent;
438         ctrl = (void *) &(b->ctrl);
439         oldPitch = b->ctrl.pitch;
440         oldDuration = b->ctrl.duration;
441         if (pitch != 0) {
442             if (pitch == -1)
443                 b->ctrl.pitch = defaultKeyboardControl.bell_pitch;
444             else
445                 b->ctrl.pitch = pitch;
446         }
447         if (duration != 0) {
448             if (duration == -1)
449                 b->ctrl.duration = defaultKeyboardControl.bell_duration;
450             else
451                 b->ctrl.duration = duration;
452         }
453     }
454     else {
455         client->errorValue = _XkbErrCode2(0x7, bellClass);
456         return BadValue;
457     }
458 
459     newPercent = (base * percent) / 100;
460     if (percent < 0)
461         newPercent = base + newPercent;
462     else
463         newPercent = base - newPercent + percent;
464 
465     XkbHandleBell(forceSound, eventOnly,
466                   dev, newPercent, ctrl, bellClass, name, pWin, client);
467     if ((pitch != 0) || (duration != 0)) {
468         if (bellClass == KbdFeedbackClass) {
469             KbdFeedbackPtr k;
470 
471             k = (KbdFeedbackPtr) ctrl;
472             if (pitch != 0)
473                 k->ctrl.bell_pitch = oldPitch;
474             if (duration != 0)
475                 k->ctrl.bell_duration = oldDuration;
476         }
477         else {
478             BellFeedbackPtr b;
479 
480             b = (BellFeedbackPtr) ctrl;
481             if (pitch != 0)
482                 b->ctrl.pitch = oldPitch;
483             if (duration != 0)
484                 b->ctrl.duration = oldDuration;
485         }
486     }
487 
488     return Success;
489 }
490 
491 int
ProcXkbBell(ClientPtr client)492 ProcXkbBell(ClientPtr client)
493 {
494     REQUEST(xkbBellReq);
495     DeviceIntPtr dev;
496     WindowPtr pWin;
497     int rc;
498 
499     REQUEST_SIZE_MATCH(xkbBellReq);
500 
501     if (!(client->xkbClientFlags & _XkbClientInitialized))
502         return BadAccess;
503 
504     CHK_BELL_DEVICE(dev, stuff->deviceSpec, client, DixBellAccess);
505     CHK_ATOM_OR_NONE(stuff->name);
506 
507     /* device-independent checks request for sane values */
508     if ((stuff->forceSound) && (stuff->eventOnly)) {
509         client->errorValue =
510             _XkbErrCode3(0x1, stuff->forceSound, stuff->eventOnly);
511         return BadMatch;
512     }
513     if (stuff->percent < -100 || stuff->percent > 100) {
514         client->errorValue = _XkbErrCode2(0x2, stuff->percent);
515         return BadValue;
516     }
517     if (stuff->duration < -1) {
518         client->errorValue = _XkbErrCode2(0x3, stuff->duration);
519         return BadValue;
520     }
521     if (stuff->pitch < -1) {
522         client->errorValue = _XkbErrCode2(0x4, stuff->pitch);
523         return BadValue;
524     }
525 
526     if (stuff->bellClass == XkbDfltXIClass) {
527         if (dev->kbdfeed != NULL)
528             stuff->bellClass = KbdFeedbackClass;
529         else
530             stuff->bellClass = BellFeedbackClass;
531     }
532 
533     if (stuff->window != None) {
534         rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
535         if (rc != Success) {
536             client->errorValue = stuff->window;
537             return rc;
538         }
539     }
540     else
541         pWin = NULL;
542 
543     /* Client wants to ring a bell on the core keyboard?
544        Ring the bell on the core keyboard (which does nothing, but if that
545        fails the client is screwed anyway), and then on all extension devices.
546        Fail if the core keyboard fails but not the extension devices.  this
547        may cause some keyboards to ding and others to stay silent. Fix
548        your client to use explicit keyboards to avoid this.
549 
550        dev is the device the client requested.
551      */
552     rc = _XkbBell(client, dev, pWin, stuff->bellClass, stuff->bellID,
553                   stuff->pitch, stuff->duration, stuff->percent,
554                   stuff->forceSound, stuff->eventOnly, stuff->name);
555 
556     if ((rc == Success) && ((stuff->deviceSpec == XkbUseCoreKbd) ||
557                             (stuff->deviceSpec == XkbUseCorePtr))) {
558         DeviceIntPtr other;
559 
560         for (other = inputInfo.devices; other; other = other->next) {
561             if ((other != dev) && other->key && !IsMaster(other) &&
562                 GetMaster(other, MASTER_KEYBOARD) == dev) {
563                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other, DixBellAccess);
564                 if (rc == Success)
565                     _XkbBell(client, other, pWin, stuff->bellClass,
566                              stuff->bellID, stuff->pitch, stuff->duration,
567                              stuff->percent, stuff->forceSound,
568                              stuff->eventOnly, stuff->name);
569             }
570         }
571         rc = Success;           /* reset to success, that's what we got for the VCK */
572     }
573 
574     return rc;
575 }
576 
577 /***====================================================================***/
578 
579 int
ProcXkbGetState(ClientPtr client)580 ProcXkbGetState(ClientPtr client)
581 {
582     REQUEST(xkbGetStateReq);
583     DeviceIntPtr dev;
584     xkbGetStateReply rep;
585     XkbStateRec *xkb;
586 
587     REQUEST_SIZE_MATCH(xkbGetStateReq);
588 
589     if (!(client->xkbClientFlags & _XkbClientInitialized))
590         return BadAccess;
591 
592     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
593 
594     xkb = &dev->key->xkbInfo->state;
595     rep = (xkbGetStateReply) {
596         .type = X_Reply,
597         .deviceID = dev->id,
598         .sequenceNumber = client->sequence,
599         .length = 0,
600         .mods = XkbStateFieldFromRec(xkb) & 0xff,
601         .baseMods = xkb->base_mods,
602         .latchedMods = xkb->latched_mods,
603         .lockedMods = xkb->locked_mods,
604         .group = xkb->group,
605         .lockedGroup = xkb->locked_group,
606         .baseGroup = xkb->base_group,
607         .latchedGroup = xkb->latched_group,
608         .compatState = xkb->compat_state,
609         .ptrBtnState = xkb->ptr_buttons
610     };
611     if (client->swapped) {
612         swaps(&rep.sequenceNumber);
613         swaps(&rep.ptrBtnState);
614     }
615     WriteToClient(client, SIZEOF(xkbGetStateReply), &rep);
616     return Success;
617 }
618 
619 /***====================================================================***/
620 
621 int
ProcXkbLatchLockState(ClientPtr client)622 ProcXkbLatchLockState(ClientPtr client)
623 {
624     int status;
625     DeviceIntPtr dev, tmpd;
626     XkbStateRec oldState, *newState;
627     CARD16 changed;
628     xkbStateNotify sn;
629     XkbEventCauseRec cause;
630 
631     REQUEST(xkbLatchLockStateReq);
632     REQUEST_SIZE_MATCH(xkbLatchLockStateReq);
633 
634     if (!(client->xkbClientFlags & _XkbClientInitialized))
635         return BadAccess;
636 
637     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
638     CHK_MASK_MATCH(0x01, stuff->affectModLocks, stuff->modLocks);
639     CHK_MASK_MATCH(0x01, stuff->affectModLatches, stuff->modLatches);
640 
641     status = Success;
642 
643     for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
644         if ((tmpd == dev) ||
645             (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
646             if (!tmpd->key || !tmpd->key->xkbInfo)
647                 continue;
648 
649             oldState = tmpd->key->xkbInfo->state;
650             newState = &tmpd->key->xkbInfo->state;
651             if (stuff->affectModLocks) {
652                 newState->locked_mods &= ~stuff->affectModLocks;
653                 newState->locked_mods |=
654                     (stuff->affectModLocks & stuff->modLocks);
655             }
656             if (status == Success && stuff->lockGroup)
657                 newState->locked_group = stuff->groupLock;
658             if (status == Success && stuff->affectModLatches)
659                 status = XkbLatchModifiers(tmpd, stuff->affectModLatches,
660                                            stuff->modLatches);
661             if (status == Success && stuff->latchGroup)
662                 status = XkbLatchGroup(tmpd, stuff->groupLatch);
663 
664             if (status != Success)
665                 return status;
666 
667             XkbComputeDerivedState(tmpd->key->xkbInfo);
668 
669             changed = XkbStateChangedFlags(&oldState, newState);
670             if (changed) {
671                 sn.keycode = 0;
672                 sn.eventType = 0;
673                 sn.requestMajor = XkbReqCode;
674                 sn.requestMinor = X_kbLatchLockState;
675                 sn.changed = changed;
676                 XkbSendStateNotify(tmpd, &sn);
677                 changed = XkbIndicatorsToUpdate(tmpd, changed, FALSE);
678                 if (changed) {
679                     XkbSetCauseXkbReq(&cause, X_kbLatchLockState, client);
680                     XkbUpdateIndicators(tmpd, changed, TRUE, NULL, &cause);
681                 }
682             }
683         }
684     }
685 
686     return Success;
687 }
688 
689 /***====================================================================***/
690 
691 int
ProcXkbGetControls(ClientPtr client)692 ProcXkbGetControls(ClientPtr client)
693 {
694     xkbGetControlsReply rep;
695     XkbControlsPtr xkb;
696     DeviceIntPtr dev;
697 
698     REQUEST(xkbGetControlsReq);
699     REQUEST_SIZE_MATCH(xkbGetControlsReq);
700 
701     if (!(client->xkbClientFlags & _XkbClientInitialized))
702         return BadAccess;
703 
704     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
705 
706     xkb = dev->key->xkbInfo->desc->ctrls;
707     rep = (xkbGetControlsReply) {
708         .type = X_Reply,
709         .deviceID = ((DeviceIntPtr) dev)->id,
710         .sequenceNumber = client->sequence,
711         .length = bytes_to_int32(SIZEOF(xkbGetControlsReply) -
712                                  SIZEOF(xGenericReply)),
713         .mkDfltBtn = xkb->mk_dflt_btn,
714         .numGroups = xkb->num_groups,
715         .groupsWrap = xkb->groups_wrap,
716         .internalMods = xkb->internal.mask,
717         .ignoreLockMods = xkb->ignore_lock.mask,
718         .internalRealMods = xkb->internal.real_mods,
719         .ignoreLockRealMods = xkb->ignore_lock.real_mods,
720         .internalVMods = xkb->internal.vmods,
721         .ignoreLockVMods = xkb->ignore_lock.vmods,
722         .repeatDelay = xkb->repeat_delay,
723         .repeatInterval = xkb->repeat_interval,
724         .slowKeysDelay = xkb->slow_keys_delay,
725         .debounceDelay = xkb->debounce_delay,
726         .mkDelay = xkb->mk_delay,
727         .mkInterval = xkb->mk_interval,
728         .mkTimeToMax = xkb->mk_time_to_max,
729         .mkMaxSpeed = xkb->mk_max_speed,
730         .mkCurve = xkb->mk_curve,
731         .axOptions = xkb->ax_options,
732         .axTimeout = xkb->ax_timeout,
733         .axtOptsMask = xkb->axt_opts_mask,
734         .axtOptsValues = xkb->axt_opts_values,
735         .axtCtrlsMask = xkb->axt_ctrls_mask,
736         .axtCtrlsValues = xkb->axt_ctrls_values,
737         .enabledCtrls = xkb->enabled_ctrls,
738     };
739     memcpy(rep.perKeyRepeat, xkb->per_key_repeat, XkbPerKeyBitArraySize);
740     if (client->swapped) {
741         swaps(&rep.sequenceNumber);
742         swapl(&rep.length);
743         swaps(&rep.internalVMods);
744         swaps(&rep.ignoreLockVMods);
745         swapl(&rep.enabledCtrls);
746         swaps(&rep.repeatDelay);
747         swaps(&rep.repeatInterval);
748         swaps(&rep.slowKeysDelay);
749         swaps(&rep.debounceDelay);
750         swaps(&rep.mkDelay);
751         swaps(&rep.mkInterval);
752         swaps(&rep.mkTimeToMax);
753         swaps(&rep.mkMaxSpeed);
754         swaps(&rep.mkCurve);
755         swaps(&rep.axTimeout);
756         swapl(&rep.axtCtrlsMask);
757         swapl(&rep.axtCtrlsValues);
758         swaps(&rep.axtOptsMask);
759         swaps(&rep.axtOptsValues);
760         swaps(&rep.axOptions);
761     }
762     WriteToClient(client, SIZEOF(xkbGetControlsReply), &rep);
763     return Success;
764 }
765 
766 int
ProcXkbSetControls(ClientPtr client)767 ProcXkbSetControls(ClientPtr client)
768 {
769     DeviceIntPtr dev, tmpd;
770     XkbSrvInfoPtr xkbi;
771     XkbControlsPtr ctrl;
772     XkbControlsRec new, old;
773     xkbControlsNotify cn;
774     XkbEventCauseRec cause;
775     XkbSrvLedInfoPtr sli;
776 
777     REQUEST(xkbSetControlsReq);
778     REQUEST_SIZE_MATCH(xkbSetControlsReq);
779 
780     if (!(client->xkbClientFlags & _XkbClientInitialized))
781         return BadAccess;
782 
783     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
784     CHK_MASK_LEGAL(0x01, stuff->changeCtrls, XkbAllControlsMask);
785 
786     for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
787         if (!tmpd->key || !tmpd->key->xkbInfo)
788             continue;
789         if ((tmpd == dev) ||
790             (!IsMaster(tmpd) && GetMaster(tmpd, MASTER_KEYBOARD) == dev)) {
791             xkbi = tmpd->key->xkbInfo;
792             ctrl = xkbi->desc->ctrls;
793             new = *ctrl;
794             XkbSetCauseXkbReq(&cause, X_kbSetControls, client);
795 
796             if (stuff->changeCtrls & XkbInternalModsMask) {
797                 CHK_MASK_MATCH(0x02, stuff->affectInternalMods,
798                                stuff->internalMods);
799                 CHK_MASK_MATCH(0x03, stuff->affectInternalVMods,
800                                stuff->internalVMods);
801 
802                 new.internal.real_mods &= ~(stuff->affectInternalMods);
803                 new.internal.real_mods |= (stuff->affectInternalMods &
804                                            stuff->internalMods);
805                 new.internal.vmods &= ~(stuff->affectInternalVMods);
806                 new.internal.vmods |= (stuff->affectInternalVMods &
807                                        stuff->internalVMods);
808                 new.internal.mask = new.internal.real_mods |
809                     XkbMaskForVMask(xkbi->desc, new.internal.vmods);
810             }
811 
812             if (stuff->changeCtrls & XkbIgnoreLockModsMask) {
813                 CHK_MASK_MATCH(0x4, stuff->affectIgnoreLockMods,
814                                stuff->ignoreLockMods);
815                 CHK_MASK_MATCH(0x5, stuff->affectIgnoreLockVMods,
816                                stuff->ignoreLockVMods);
817 
818                 new.ignore_lock.real_mods &= ~(stuff->affectIgnoreLockMods);
819                 new.ignore_lock.real_mods |= (stuff->affectIgnoreLockMods &
820                                               stuff->ignoreLockMods);
821                 new.ignore_lock.vmods &= ~(stuff->affectIgnoreLockVMods);
822                 new.ignore_lock.vmods |= (stuff->affectIgnoreLockVMods &
823                                           stuff->ignoreLockVMods);
824                 new.ignore_lock.mask = new.ignore_lock.real_mods |
825                     XkbMaskForVMask(xkbi->desc, new.ignore_lock.vmods);
826             }
827 
828             CHK_MASK_MATCH(0x06, stuff->affectEnabledCtrls,
829                            stuff->enabledCtrls);
830             if (stuff->affectEnabledCtrls) {
831                 CHK_MASK_LEGAL(0x07, stuff->affectEnabledCtrls,
832                                XkbAllBooleanCtrlsMask);
833 
834                 new.enabled_ctrls &= ~(stuff->affectEnabledCtrls);
835                 new.enabled_ctrls |= (stuff->affectEnabledCtrls &
836                                       stuff->enabledCtrls);
837             }
838 
839             if (stuff->changeCtrls & XkbRepeatKeysMask) {
840                 if (stuff->repeatDelay < 1 || stuff->repeatInterval < 1) {
841                     client->errorValue = _XkbErrCode3(0x08, stuff->repeatDelay,
842                                                       stuff->repeatInterval);
843                     return BadValue;
844                 }
845 
846                 new.repeat_delay = stuff->repeatDelay;
847                 new.repeat_interval = stuff->repeatInterval;
848             }
849 
850             if (stuff->changeCtrls & XkbSlowKeysMask) {
851                 if (stuff->slowKeysDelay < 1) {
852                     client->errorValue = _XkbErrCode2(0x09,
853                                                       stuff->slowKeysDelay);
854                     return BadValue;
855                 }
856 
857                 new.slow_keys_delay = stuff->slowKeysDelay;
858             }
859 
860             if (stuff->changeCtrls & XkbBounceKeysMask) {
861                 if (stuff->debounceDelay < 1) {
862                     client->errorValue = _XkbErrCode2(0x0A,
863                                                       stuff->debounceDelay);
864                     return BadValue;
865                 }
866 
867                 new.debounce_delay = stuff->debounceDelay;
868             }
869 
870             if (stuff->changeCtrls & XkbMouseKeysMask) {
871                 if (stuff->mkDfltBtn > XkbMaxMouseKeysBtn) {
872                     client->errorValue = _XkbErrCode2(0x0B, stuff->mkDfltBtn);
873                     return BadValue;
874                 }
875 
876                 new.mk_dflt_btn = stuff->mkDfltBtn;
877             }
878 
879             if (stuff->changeCtrls & XkbMouseKeysAccelMask) {
880                 if (stuff->mkDelay < 1 || stuff->mkInterval < 1 ||
881                     stuff->mkTimeToMax < 1 || stuff->mkMaxSpeed < 1 ||
882                     stuff->mkCurve < -1000) {
883                     client->errorValue = _XkbErrCode2(0x0C, 0);
884                     return BadValue;
885                 }
886 
887                 new.mk_delay = stuff->mkDelay;
888                 new.mk_interval = stuff->mkInterval;
889                 new.mk_time_to_max = stuff->mkTimeToMax;
890                 new.mk_max_speed = stuff->mkMaxSpeed;
891                 new.mk_curve = stuff->mkCurve;
892                 AccessXComputeCurveFactor(xkbi, &new);
893             }
894 
895             if (stuff->changeCtrls & XkbGroupsWrapMask) {
896                 unsigned act, num;
897 
898                 act = XkbOutOfRangeGroupAction(stuff->groupsWrap);
899                 switch (act) {
900                 case XkbRedirectIntoRange:
901                     num = XkbOutOfRangeGroupNumber(stuff->groupsWrap);
902                     if (num >= new.num_groups) {
903                         client->errorValue = _XkbErrCode3(0x0D, new.num_groups,
904                                                           num);
905                         return BadValue;
906                     }
907                 case XkbWrapIntoRange:
908                 case XkbClampIntoRange:
909                     break;
910                 default:
911                     client->errorValue = _XkbErrCode2(0x0E, act);
912                     return BadValue;
913                 }
914 
915                 new.groups_wrap = stuff->groupsWrap;
916             }
917 
918             CHK_MASK_LEGAL(0x0F, stuff->axOptions, XkbAX_AllOptionsMask);
919             if (stuff->changeCtrls & XkbAccessXKeysMask) {
920                 new.ax_options = stuff->axOptions & XkbAX_AllOptionsMask;
921             }
922             else {
923                 if (stuff->changeCtrls & XkbStickyKeysMask) {
924                     new.ax_options &= ~(XkbAX_SKOptionsMask);
925                     new.ax_options |= (stuff->axOptions & XkbAX_SKOptionsMask);
926                 }
927 
928                 if (stuff->changeCtrls & XkbAccessXFeedbackMask) {
929                     new.ax_options &= ~(XkbAX_FBOptionsMask);
930                     new.ax_options |= (stuff->axOptions & XkbAX_FBOptionsMask);
931                 }
932             }
933 
934             if (stuff->changeCtrls & XkbAccessXTimeoutMask) {
935                 if (stuff->axTimeout < 1) {
936                     client->errorValue = _XkbErrCode2(0x10, stuff->axTimeout);
937                     return BadValue;
938                 }
939                 CHK_MASK_MATCH(0x11, stuff->axtCtrlsMask,
940                                stuff->axtCtrlsValues);
941                 CHK_MASK_LEGAL(0x12, stuff->axtCtrlsMask,
942                                XkbAllBooleanCtrlsMask);
943                 CHK_MASK_MATCH(0x13, stuff->axtOptsMask, stuff->axtOptsValues);
944                 CHK_MASK_LEGAL(0x14, stuff->axtOptsMask, XkbAX_AllOptionsMask);
945                 new.ax_timeout = stuff->axTimeout;
946                 new.axt_ctrls_mask = stuff->axtCtrlsMask;
947                 new.axt_ctrls_values = (stuff->axtCtrlsValues &
948                                         stuff->axtCtrlsMask);
949                 new.axt_opts_mask = stuff->axtOptsMask;
950                 new.axt_opts_values = (stuff->axtOptsValues &
951                                        stuff->axtOptsMask);
952             }
953 
954             if (stuff->changeCtrls & XkbPerKeyRepeatMask) {
955                 memcpy(new.per_key_repeat, stuff->perKeyRepeat,
956                        XkbPerKeyBitArraySize);
957                 if (xkbi->repeatKey &&
958                     !BitIsOn(new.per_key_repeat, xkbi->repeatKey)) {
959                     AccessXCancelRepeatKey(xkbi, xkbi->repeatKey);
960                 }
961             }
962 
963             old = *ctrl;
964             *ctrl = new;
965             XkbDDXChangeControls(tmpd, &old, ctrl);
966 
967             if (XkbComputeControlsNotify(tmpd, &old, ctrl, &cn, FALSE)) {
968                 cn.keycode = 0;
969                 cn.eventType = 0;
970                 cn.requestMajor = XkbReqCode;
971                 cn.requestMinor = X_kbSetControls;
972                 XkbSendControlsNotify(tmpd, &cn);
973             }
974 
975             sli = XkbFindSrvLedInfo(tmpd, XkbDfltXIClass, XkbDfltXIId, 0);
976             if (sli)
977                 XkbUpdateIndicators(tmpd, sli->usesControls, TRUE, NULL,
978                                     &cause);
979 
980             /* If sticky keys were disabled, clear all locks and latches */
981             if ((old.enabled_ctrls & XkbStickyKeysMask) &&
982                 !(ctrl->enabled_ctrls & XkbStickyKeysMask))
983                 XkbClearAllLatchesAndLocks(tmpd, xkbi, TRUE, &cause);
984         }
985     }
986 
987     return Success;
988 }
989 
990 /***====================================================================***/
991 
992 static int
XkbSizeKeyTypes(XkbDescPtr xkb,xkbGetMapReply * rep)993 XkbSizeKeyTypes(XkbDescPtr xkb, xkbGetMapReply * rep)
994 {
995     XkbKeyTypeRec *type;
996     unsigned i, len;
997 
998     len = 0;
999     if (((rep->present & XkbKeyTypesMask) == 0) || (rep->nTypes < 1) ||
1000         (!xkb) || (!xkb->map) || (!xkb->map->types)) {
1001         rep->present &= ~XkbKeyTypesMask;
1002         rep->firstType = rep->nTypes = 0;
1003         return 0;
1004     }
1005     type = &xkb->map->types[rep->firstType];
1006     for (i = 0; i < rep->nTypes; i++, type++) {
1007         len += SIZEOF(xkbKeyTypeWireDesc);
1008         if (type->map_count > 0) {
1009             len += (type->map_count * SIZEOF(xkbKTMapEntryWireDesc));
1010             if (type->preserve)
1011                 len += (type->map_count * SIZEOF(xkbModsWireDesc));
1012         }
1013     }
1014     return len;
1015 }
1016 
1017 static char *
XkbWriteKeyTypes(XkbDescPtr xkb,xkbGetMapReply * rep,char * buf,ClientPtr client)1018 XkbWriteKeyTypes(XkbDescPtr xkb,
1019                  xkbGetMapReply * rep, char *buf, ClientPtr client)
1020 {
1021     XkbKeyTypePtr type;
1022     unsigned i;
1023     xkbKeyTypeWireDesc *wire;
1024 
1025     type = &xkb->map->types[rep->firstType];
1026     for (i = 0; i < rep->nTypes; i++, type++) {
1027         register unsigned n;
1028 
1029         wire = (xkbKeyTypeWireDesc *) buf;
1030         wire->mask = type->mods.mask;
1031         wire->realMods = type->mods.real_mods;
1032         wire->virtualMods = type->mods.vmods;
1033         wire->numLevels = type->num_levels;
1034         wire->nMapEntries = type->map_count;
1035         wire->preserve = (type->preserve != NULL);
1036         if (client->swapped) {
1037             swaps(&wire->virtualMods);
1038         }
1039 
1040         buf = (char *) &wire[1];
1041         if (wire->nMapEntries > 0) {
1042             xkbKTMapEntryWireDesc *ewire;
1043             XkbKTMapEntryPtr entry;
1044 
1045             ewire = (xkbKTMapEntryWireDesc *) buf;
1046             entry = type->map;
1047             for (n = 0; n < type->map_count; n++, ewire++, entry++) {
1048                 ewire->active = entry->active;
1049                 ewire->mask = entry->mods.mask;
1050                 ewire->level = entry->level;
1051                 ewire->realMods = entry->mods.real_mods;
1052                 ewire->virtualMods = entry->mods.vmods;
1053                 if (client->swapped) {
1054                     swaps(&ewire->virtualMods);
1055                 }
1056             }
1057             buf = (char *) ewire;
1058             if (type->preserve != NULL) {
1059                 xkbModsWireDesc *pwire;
1060                 XkbModsPtr preserve;
1061 
1062                 pwire = (xkbModsWireDesc *) buf;
1063                 preserve = type->preserve;
1064                 for (n = 0; n < type->map_count; n++, pwire++, preserve++) {
1065                     pwire->mask = preserve->mask;
1066                     pwire->realMods = preserve->real_mods;
1067                     pwire->virtualMods = preserve->vmods;
1068                     if (client->swapped) {
1069                         swaps(&pwire->virtualMods);
1070                     }
1071                 }
1072                 buf = (char *) pwire;
1073             }
1074         }
1075     }
1076     return buf;
1077 }
1078 
1079 static int
XkbSizeKeySyms(XkbDescPtr xkb,xkbGetMapReply * rep)1080 XkbSizeKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep)
1081 {
1082     XkbSymMapPtr symMap;
1083     unsigned i, len;
1084     unsigned nSyms, nSymsThisKey;
1085 
1086     if (((rep->present & XkbKeySymsMask) == 0) || (rep->nKeySyms < 1) ||
1087         (!xkb) || (!xkb->map) || (!xkb->map->key_sym_map)) {
1088         rep->present &= ~XkbKeySymsMask;
1089         rep->firstKeySym = rep->nKeySyms = 0;
1090         rep->totalSyms = 0;
1091         return 0;
1092     }
1093     len = rep->nKeySyms * SIZEOF(xkbSymMapWireDesc);
1094     symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1095     for (i = nSyms = 0; i < rep->nKeySyms; i++, symMap++) {
1096         if (symMap->offset != 0) {
1097             nSymsThisKey = XkbNumGroups(symMap->group_info) * symMap->width;
1098             nSyms += nSymsThisKey;
1099         }
1100     }
1101     len += nSyms * 4;
1102     rep->totalSyms = nSyms;
1103     return len;
1104 }
1105 
1106 static int
XkbSizeVirtualMods(XkbDescPtr xkb,xkbGetMapReply * rep)1107 XkbSizeVirtualMods(XkbDescPtr xkb, xkbGetMapReply * rep)
1108 {
1109     register unsigned i, nMods, bit;
1110 
1111     if (((rep->present & XkbVirtualModsMask) == 0) || (rep->virtualMods == 0) ||
1112         (!xkb) || (!xkb->server)) {
1113         rep->present &= ~XkbVirtualModsMask;
1114         rep->virtualMods = 0;
1115         return 0;
1116     }
1117     for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1118         if (rep->virtualMods & bit)
1119             nMods++;
1120     }
1121     return XkbPaddedSize(nMods);
1122 }
1123 
1124 static char *
XkbWriteKeySyms(XkbDescPtr xkb,xkbGetMapReply * rep,char * buf,ClientPtr client)1125 XkbWriteKeySyms(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1126                 ClientPtr client)
1127 {
1128     register KeySym *pSym;
1129     XkbSymMapPtr symMap;
1130     xkbSymMapWireDesc *outMap;
1131     register unsigned i;
1132 
1133     symMap = &xkb->map->key_sym_map[rep->firstKeySym];
1134     for (i = 0; i < rep->nKeySyms; i++, symMap++) {
1135         outMap = (xkbSymMapWireDesc *) buf;
1136         outMap->ktIndex[0] = symMap->kt_index[0];
1137         outMap->ktIndex[1] = symMap->kt_index[1];
1138         outMap->ktIndex[2] = symMap->kt_index[2];
1139         outMap->ktIndex[3] = symMap->kt_index[3];
1140         outMap->groupInfo = symMap->group_info;
1141         outMap->width = symMap->width;
1142         outMap->nSyms = symMap->width * XkbNumGroups(symMap->group_info);
1143         buf = (char *) &outMap[1];
1144         if (outMap->nSyms == 0)
1145             continue;
1146 
1147         pSym = &xkb->map->syms[symMap->offset];
1148         memcpy((char *) buf, (char *) pSym, outMap->nSyms * 4);
1149         if (client->swapped) {
1150             register int nSyms = outMap->nSyms;
1151 
1152             swaps(&outMap->nSyms);
1153             while (nSyms-- > 0) {
1154                 swapl((int *) buf);
1155                 buf += 4;
1156             }
1157         }
1158         else
1159             buf += outMap->nSyms * 4;
1160     }
1161     return buf;
1162 }
1163 
1164 static int
XkbSizeKeyActions(XkbDescPtr xkb,xkbGetMapReply * rep)1165 XkbSizeKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep)
1166 {
1167     unsigned i, len, nActs;
1168     register KeyCode firstKey;
1169 
1170     if (((rep->present & XkbKeyActionsMask) == 0) || (rep->nKeyActs < 1) ||
1171         (!xkb) || (!xkb->server) || (!xkb->server->key_acts)) {
1172         rep->present &= ~XkbKeyActionsMask;
1173         rep->firstKeyAct = rep->nKeyActs = 0;
1174         rep->totalActs = 0;
1175         return 0;
1176     }
1177     firstKey = rep->firstKeyAct;
1178     for (nActs = i = 0; i < rep->nKeyActs; i++) {
1179         if (xkb->server->key_acts[i + firstKey] != 0)
1180             nActs += XkbKeyNumActions(xkb, i + firstKey);
1181     }
1182     len = XkbPaddedSize(rep->nKeyActs) + (nActs * SIZEOF(xkbActionWireDesc));
1183     rep->totalActs = nActs;
1184     return len;
1185 }
1186 
1187 static char *
XkbWriteKeyActions(XkbDescPtr xkb,xkbGetMapReply * rep,char * buf,ClientPtr client)1188 XkbWriteKeyActions(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1189                    ClientPtr client)
1190 {
1191     unsigned i;
1192     CARD8 *numDesc;
1193     XkbAnyAction *actDesc;
1194 
1195     numDesc = (CARD8 *) buf;
1196     for (i = 0; i < rep->nKeyActs; i++) {
1197         if (xkb->server->key_acts[i + rep->firstKeyAct] == 0)
1198             numDesc[i] = 0;
1199         else
1200             numDesc[i] = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1201     }
1202     buf += XkbPaddedSize(rep->nKeyActs);
1203 
1204     actDesc = (XkbAnyAction *) buf;
1205     for (i = 0; i < rep->nKeyActs; i++) {
1206         if (xkb->server->key_acts[i + rep->firstKeyAct] != 0) {
1207             unsigned int num;
1208 
1209             num = XkbKeyNumActions(xkb, (i + rep->firstKeyAct));
1210             memcpy((char *) actDesc,
1211                    (char *) XkbKeyActionsPtr(xkb, (i + rep->firstKeyAct)),
1212                    num * SIZEOF(xkbActionWireDesc));
1213             actDesc += num;
1214         }
1215     }
1216     buf = (char *) actDesc;
1217     return buf;
1218 }
1219 
1220 static int
XkbSizeKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply * rep)1221 XkbSizeKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep)
1222 {
1223     unsigned i, len, nBhvr;
1224     XkbBehavior *bhv;
1225 
1226     if (((rep->present & XkbKeyBehaviorsMask) == 0) || (rep->nKeyBehaviors < 1)
1227         || (!xkb) || (!xkb->server) || (!xkb->server->behaviors)) {
1228         rep->present &= ~XkbKeyBehaviorsMask;
1229         rep->firstKeyBehavior = rep->nKeyBehaviors = 0;
1230         rep->totalKeyBehaviors = 0;
1231         return 0;
1232     }
1233     bhv = &xkb->server->behaviors[rep->firstKeyBehavior];
1234     for (nBhvr = i = 0; i < rep->nKeyBehaviors; i++, bhv++) {
1235         if (bhv->type != XkbKB_Default)
1236             nBhvr++;
1237     }
1238     len = nBhvr * SIZEOF(xkbBehaviorWireDesc);
1239     rep->totalKeyBehaviors = nBhvr;
1240     return len;
1241 }
1242 
1243 static char *
XkbWriteKeyBehaviors(XkbDescPtr xkb,xkbGetMapReply * rep,char * buf,ClientPtr client)1244 XkbWriteKeyBehaviors(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1245                      ClientPtr client)
1246 {
1247     unsigned i;
1248     xkbBehaviorWireDesc *wire;
1249     XkbBehavior *pBhvr;
1250 
1251     wire = (xkbBehaviorWireDesc *) buf;
1252     pBhvr = &xkb->server->behaviors[rep->firstKeyBehavior];
1253     for (i = 0; i < rep->nKeyBehaviors; i++, pBhvr++) {
1254         if (pBhvr->type != XkbKB_Default) {
1255             wire->key = i + rep->firstKeyBehavior;
1256             wire->type = pBhvr->type;
1257             wire->data = pBhvr->data;
1258             wire++;
1259         }
1260     }
1261     buf = (char *) wire;
1262     return buf;
1263 }
1264 
1265 static int
XkbSizeExplicit(XkbDescPtr xkb,xkbGetMapReply * rep)1266 XkbSizeExplicit(XkbDescPtr xkb, xkbGetMapReply * rep)
1267 {
1268     unsigned i, len, nRtrn;
1269 
1270     if (((rep->present & XkbExplicitComponentsMask) == 0) ||
1271         (rep->nKeyExplicit < 1) || (!xkb) || (!xkb->server) ||
1272         (!xkb->server->explicit)) {
1273         rep->present &= ~XkbExplicitComponentsMask;
1274         rep->firstKeyExplicit = rep->nKeyExplicit = 0;
1275         rep->totalKeyExplicit = 0;
1276         return 0;
1277     }
1278     for (nRtrn = i = 0; i < rep->nKeyExplicit; i++) {
1279         if (xkb->server->explicit[i + rep->firstKeyExplicit] != 0)
1280             nRtrn++;
1281     }
1282     rep->totalKeyExplicit = nRtrn;
1283     len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero explicit component */
1284     return len;
1285 }
1286 
1287 static char *
XkbWriteExplicit(XkbDescPtr xkb,xkbGetMapReply * rep,char * buf,ClientPtr client)1288 XkbWriteExplicit(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1289                  ClientPtr client)
1290 {
1291     unsigned i;
1292     char *start;
1293     unsigned char *pExp;
1294 
1295     start = buf;
1296     pExp = &xkb->server->explicit[rep->firstKeyExplicit];
1297     for (i = 0; i < rep->nKeyExplicit; i++, pExp++) {
1298         if (*pExp != 0) {
1299             *buf++ = i + rep->firstKeyExplicit;
1300             *buf++ = *pExp;
1301         }
1302     }
1303     i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1304     return buf + i;
1305 }
1306 
1307 static int
XkbSizeModifierMap(XkbDescPtr xkb,xkbGetMapReply * rep)1308 XkbSizeModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep)
1309 {
1310     unsigned i, len, nRtrn;
1311 
1312     if (((rep->present & XkbModifierMapMask) == 0) || (rep->nModMapKeys < 1) ||
1313         (!xkb) || (!xkb->map) || (!xkb->map->modmap)) {
1314         rep->present &= ~XkbModifierMapMask;
1315         rep->firstModMapKey = rep->nModMapKeys = 0;
1316         rep->totalModMapKeys = 0;
1317         return 0;
1318     }
1319     for (nRtrn = i = 0; i < rep->nModMapKeys; i++) {
1320         if (xkb->map->modmap[i + rep->firstModMapKey] != 0)
1321             nRtrn++;
1322     }
1323     rep->totalModMapKeys = nRtrn;
1324     len = XkbPaddedSize(nRtrn * 2);     /* two bytes per non-zero modmap component */
1325     return len;
1326 }
1327 
1328 static char *
XkbWriteModifierMap(XkbDescPtr xkb,xkbGetMapReply * rep,char * buf,ClientPtr client)1329 XkbWriteModifierMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1330                     ClientPtr client)
1331 {
1332     unsigned i;
1333     char *start;
1334     unsigned char *pMap;
1335 
1336     start = buf;
1337     pMap = &xkb->map->modmap[rep->firstModMapKey];
1338     for (i = 0; i < rep->nModMapKeys; i++, pMap++) {
1339         if (*pMap != 0) {
1340             *buf++ = i + rep->firstModMapKey;
1341             *buf++ = *pMap;
1342         }
1343     }
1344     i = XkbPaddedSize(buf - start) - (buf - start);     /* pad to word boundary */
1345     return buf + i;
1346 }
1347 
1348 static int
XkbSizeVirtualModMap(XkbDescPtr xkb,xkbGetMapReply * rep)1349 XkbSizeVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep)
1350 {
1351     unsigned i, len, nRtrn;
1352 
1353     if (((rep->present & XkbVirtualModMapMask) == 0) || (rep->nVModMapKeys < 1)
1354         || (!xkb) || (!xkb->server) || (!xkb->server->vmodmap)) {
1355         rep->present &= ~XkbVirtualModMapMask;
1356         rep->firstVModMapKey = rep->nVModMapKeys = 0;
1357         rep->totalVModMapKeys = 0;
1358         return 0;
1359     }
1360     for (nRtrn = i = 0; i < rep->nVModMapKeys; i++) {
1361         if (xkb->server->vmodmap[i + rep->firstVModMapKey] != 0)
1362             nRtrn++;
1363     }
1364     rep->totalVModMapKeys = nRtrn;
1365     len = nRtrn * SIZEOF(xkbVModMapWireDesc);
1366     return len;
1367 }
1368 
1369 static char *
XkbWriteVirtualModMap(XkbDescPtr xkb,xkbGetMapReply * rep,char * buf,ClientPtr client)1370 XkbWriteVirtualModMap(XkbDescPtr xkb, xkbGetMapReply * rep, char *buf,
1371                       ClientPtr client)
1372 {
1373     unsigned i;
1374     xkbVModMapWireDesc *wire;
1375     unsigned short *pMap;
1376 
1377     wire = (xkbVModMapWireDesc *) buf;
1378     pMap = &xkb->server->vmodmap[rep->firstVModMapKey];
1379     for (i = 0; i < rep->nVModMapKeys; i++, pMap++) {
1380         if (*pMap != 0) {
1381             wire->key = i + rep->firstVModMapKey;
1382             wire->vmods = *pMap;
1383             wire++;
1384         }
1385     }
1386     return (char *) wire;
1387 }
1388 
1389 static Status
XkbComputeGetMapReplySize(XkbDescPtr xkb,xkbGetMapReply * rep)1390 XkbComputeGetMapReplySize(XkbDescPtr xkb, xkbGetMapReply * rep)
1391 {
1392     int len;
1393 
1394     rep->minKeyCode = xkb->min_key_code;
1395     rep->maxKeyCode = xkb->max_key_code;
1396     len = XkbSizeKeyTypes(xkb, rep);
1397     len += XkbSizeKeySyms(xkb, rep);
1398     len += XkbSizeKeyActions(xkb, rep);
1399     len += XkbSizeKeyBehaviors(xkb, rep);
1400     len += XkbSizeVirtualMods(xkb, rep);
1401     len += XkbSizeExplicit(xkb, rep);
1402     len += XkbSizeModifierMap(xkb, rep);
1403     len += XkbSizeVirtualModMap(xkb, rep);
1404     rep->length += (len / 4);
1405     return Success;
1406 }
1407 
1408 static int
XkbSendMap(ClientPtr client,XkbDescPtr xkb,xkbGetMapReply * rep)1409 XkbSendMap(ClientPtr client, XkbDescPtr xkb, xkbGetMapReply * rep)
1410 {
1411     unsigned i, len;
1412     char *desc, *start;
1413 
1414     len = (rep->length * 4) - (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply));
1415     start = desc = calloc(1, len);
1416     if (!start)
1417         return BadAlloc;
1418     if (rep->nTypes > 0)
1419         desc = XkbWriteKeyTypes(xkb, rep, desc, client);
1420     if (rep->nKeySyms > 0)
1421         desc = XkbWriteKeySyms(xkb, rep, desc, client);
1422     if (rep->nKeyActs > 0)
1423         desc = XkbWriteKeyActions(xkb, rep, desc, client);
1424     if (rep->totalKeyBehaviors > 0)
1425         desc = XkbWriteKeyBehaviors(xkb, rep, desc, client);
1426     if (rep->virtualMods) {
1427         register int sz, bit;
1428 
1429         for (i = sz = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1430             if (rep->virtualMods & bit) {
1431                 desc[sz++] = xkb->server->vmods[i];
1432             }
1433         }
1434         desc += XkbPaddedSize(sz);
1435     }
1436     if (rep->totalKeyExplicit > 0)
1437         desc = XkbWriteExplicit(xkb, rep, desc, client);
1438     if (rep->totalModMapKeys > 0)
1439         desc = XkbWriteModifierMap(xkb, rep, desc, client);
1440     if (rep->totalVModMapKeys > 0)
1441         desc = XkbWriteVirtualModMap(xkb, rep, desc, client);
1442     if ((desc - start) != (len)) {
1443         ErrorF
1444             ("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n",
1445              len, (unsigned long) (desc - start));
1446     }
1447     if (client->swapped) {
1448         swaps(&rep->sequenceNumber);
1449         swapl(&rep->length);
1450         swaps(&rep->present);
1451         swaps(&rep->totalSyms);
1452         swaps(&rep->totalActs);
1453     }
1454     WriteToClient(client, (i = SIZEOF(xkbGetMapReply)), rep);
1455     WriteToClient(client, len, start);
1456     free((char *) start);
1457     return Success;
1458 }
1459 
1460 int
ProcXkbGetMap(ClientPtr client)1461 ProcXkbGetMap(ClientPtr client)
1462 {
1463     DeviceIntPtr dev;
1464     xkbGetMapReply rep;
1465     XkbDescRec *xkb;
1466     int n, status;
1467 
1468     REQUEST(xkbGetMapReq);
1469     REQUEST_SIZE_MATCH(xkbGetMapReq);
1470 
1471     if (!(client->xkbClientFlags & _XkbClientInitialized))
1472         return BadAccess;
1473 
1474     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
1475     CHK_MASK_OVERLAP(0x01, stuff->full, stuff->partial);
1476     CHK_MASK_LEGAL(0x02, stuff->full, XkbAllMapComponentsMask);
1477     CHK_MASK_LEGAL(0x03, stuff->partial, XkbAllMapComponentsMask);
1478 
1479     xkb = dev->key->xkbInfo->desc;
1480     rep = (xkbGetMapReply) {
1481         .type = X_Reply,
1482         .deviceID = dev->id,
1483         .sequenceNumber = client->sequence,
1484         .length = (SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2,
1485         .present = stuff->partial | stuff->full,
1486         .minKeyCode = xkb->min_key_code,
1487         .maxKeyCode = xkb->max_key_code
1488     };
1489 
1490     if (stuff->full & XkbKeyTypesMask) {
1491         rep.firstType = 0;
1492         rep.nTypes = xkb->map->num_types;
1493     }
1494     else if (stuff->partial & XkbKeyTypesMask) {
1495         if (((unsigned) stuff->firstType + stuff->nTypes) > xkb->map->num_types) {
1496             client->errorValue = _XkbErrCode4(0x04, xkb->map->num_types,
1497                                               stuff->firstType, stuff->nTypes);
1498             return BadValue;
1499         }
1500         rep.firstType = stuff->firstType;
1501         rep.nTypes = stuff->nTypes;
1502     }
1503     else
1504         rep.nTypes = 0;
1505     rep.totalTypes = xkb->map->num_types;
1506 
1507     n = XkbNumKeys(xkb);
1508     if (stuff->full & XkbKeySymsMask) {
1509         rep.firstKeySym = xkb->min_key_code;
1510         rep.nKeySyms = n;
1511     }
1512     else if (stuff->partial & XkbKeySymsMask) {
1513         CHK_KEY_RANGE(0x05, stuff->firstKeySym, stuff->nKeySyms, xkb);
1514         rep.firstKeySym = stuff->firstKeySym;
1515         rep.nKeySyms = stuff->nKeySyms;
1516     }
1517     else
1518         rep.nKeySyms = 0;
1519     rep.totalSyms = 0;
1520 
1521     if (stuff->full & XkbKeyActionsMask) {
1522         rep.firstKeyAct = xkb->min_key_code;
1523         rep.nKeyActs = n;
1524     }
1525     else if (stuff->partial & XkbKeyActionsMask) {
1526         CHK_KEY_RANGE(0x07, stuff->firstKeyAct, stuff->nKeyActs, xkb);
1527         rep.firstKeyAct = stuff->firstKeyAct;
1528         rep.nKeyActs = stuff->nKeyActs;
1529     }
1530     else
1531         rep.nKeyActs = 0;
1532     rep.totalActs = 0;
1533 
1534     if (stuff->full & XkbKeyBehaviorsMask) {
1535         rep.firstKeyBehavior = xkb->min_key_code;
1536         rep.nKeyBehaviors = n;
1537     }
1538     else if (stuff->partial & XkbKeyBehaviorsMask) {
1539         CHK_KEY_RANGE(0x09, stuff->firstKeyBehavior, stuff->nKeyBehaviors, xkb);
1540         rep.firstKeyBehavior = stuff->firstKeyBehavior;
1541         rep.nKeyBehaviors = stuff->nKeyBehaviors;
1542     }
1543     else
1544         rep.nKeyBehaviors = 0;
1545     rep.totalKeyBehaviors = 0;
1546 
1547     if (stuff->full & XkbVirtualModsMask)
1548         rep.virtualMods = ~0;
1549     else if (stuff->partial & XkbVirtualModsMask)
1550         rep.virtualMods = stuff->virtualMods;
1551 
1552     if (stuff->full & XkbExplicitComponentsMask) {
1553         rep.firstKeyExplicit = xkb->min_key_code;
1554         rep.nKeyExplicit = n;
1555     }
1556     else if (stuff->partial & XkbExplicitComponentsMask) {
1557         CHK_KEY_RANGE(0x0B, stuff->firstKeyExplicit, stuff->nKeyExplicit, xkb);
1558         rep.firstKeyExplicit = stuff->firstKeyExplicit;
1559         rep.nKeyExplicit = stuff->nKeyExplicit;
1560     }
1561     else
1562         rep.nKeyExplicit = 0;
1563     rep.totalKeyExplicit = 0;
1564 
1565     if (stuff->full & XkbModifierMapMask) {
1566         rep.firstModMapKey = xkb->min_key_code;
1567         rep.nModMapKeys = n;
1568     }
1569     else if (stuff->partial & XkbModifierMapMask) {
1570         CHK_KEY_RANGE(0x0D, stuff->firstModMapKey, stuff->nModMapKeys, xkb);
1571         rep.firstModMapKey = stuff->firstModMapKey;
1572         rep.nModMapKeys = stuff->nModMapKeys;
1573     }
1574     else
1575         rep.nModMapKeys = 0;
1576     rep.totalModMapKeys = 0;
1577 
1578     if (stuff->full & XkbVirtualModMapMask) {
1579         rep.firstVModMapKey = xkb->min_key_code;
1580         rep.nVModMapKeys = n;
1581     }
1582     else if (stuff->partial & XkbVirtualModMapMask) {
1583         CHK_KEY_RANGE(0x0F, stuff->firstVModMapKey, stuff->nVModMapKeys, xkb);
1584         rep.firstVModMapKey = stuff->firstVModMapKey;
1585         rep.nVModMapKeys = stuff->nVModMapKeys;
1586     }
1587     else
1588         rep.nVModMapKeys = 0;
1589     rep.totalVModMapKeys = 0;
1590 
1591     if ((status = XkbComputeGetMapReplySize(xkb, &rep)) != Success)
1592         return status;
1593     return XkbSendMap(client, xkb, &rep);
1594 }
1595 
1596 /***====================================================================***/
1597 
1598 static int
CheckKeyTypes(ClientPtr client,XkbDescPtr xkb,xkbSetMapReq * req,xkbKeyTypeWireDesc ** wireRtrn,int * nMapsRtrn,CARD8 * mapWidthRtrn,Bool doswap)1599 CheckKeyTypes(ClientPtr client,
1600               XkbDescPtr xkb,
1601               xkbSetMapReq * req,
1602               xkbKeyTypeWireDesc ** wireRtrn,
1603               int *nMapsRtrn, CARD8 *mapWidthRtrn, Bool doswap)
1604 {
1605     unsigned nMaps;
1606     register unsigned i, n;
1607     register CARD8 *map;
1608     register xkbKeyTypeWireDesc *wire = *wireRtrn;
1609 
1610     if (req->firstType > ((unsigned) xkb->map->num_types)) {
1611         *nMapsRtrn = _XkbErrCode3(0x01, req->firstType, xkb->map->num_types);
1612         return 0;
1613     }
1614     if (req->flags & XkbSetMapResizeTypes) {
1615         nMaps = req->firstType + req->nTypes;
1616         if (nMaps < XkbNumRequiredTypes) {      /* canonical types must be there */
1617             *nMapsRtrn = _XkbErrCode4(0x02, req->firstType, req->nTypes, 4);
1618             return 0;
1619         }
1620     }
1621     else if (req->present & XkbKeyTypesMask) {
1622         nMaps = xkb->map->num_types;
1623         if ((req->firstType + req->nTypes) > nMaps) {
1624             *nMapsRtrn = req->firstType + req->nTypes;
1625             return 0;
1626         }
1627     }
1628     else {
1629         *nMapsRtrn = xkb->map->num_types;
1630         for (i = 0; i < xkb->map->num_types; i++) {
1631             mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1632         }
1633         return 1;
1634     }
1635 
1636     for (i = 0; i < req->firstType; i++) {
1637         mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1638     }
1639     for (i = 0; i < req->nTypes; i++) {
1640         unsigned width;
1641 
1642         if (client->swapped && doswap) {
1643             swaps(&wire->virtualMods);
1644         }
1645         n = i + req->firstType;
1646         width = wire->numLevels;
1647         if (width < 1) {
1648             *nMapsRtrn = _XkbErrCode3(0x04, n, width);
1649             return 0;
1650         }
1651         else if ((n == XkbOneLevelIndex) && (width != 1)) {     /* must be width 1 */
1652             *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1653             return 0;
1654         }
1655         else if ((width != 2) &&
1656                  ((n == XkbTwoLevelIndex) || (n == XkbKeypadIndex) ||
1657                   (n == XkbAlphabeticIndex))) {
1658             /* TWO_LEVEL, ALPHABETIC and KEYPAD must be width 2 */
1659             *nMapsRtrn = _XkbErrCode3(0x05, n, width);
1660             return 0;
1661         }
1662         if (wire->nMapEntries > 0) {
1663             xkbKTSetMapEntryWireDesc *mapWire;
1664             xkbModsWireDesc *preWire;
1665 
1666             mapWire = (xkbKTSetMapEntryWireDesc *) &wire[1];
1667             preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
1668             for (n = 0; n < wire->nMapEntries; n++) {
1669                 if (client->swapped && doswap) {
1670                     swaps(&mapWire[n].virtualMods);
1671                 }
1672                 if (mapWire[n].realMods & (~wire->realMods)) {
1673                     *nMapsRtrn = _XkbErrCode4(0x06, n, mapWire[n].realMods,
1674                                               wire->realMods);
1675                     return 0;
1676                 }
1677                 if (mapWire[n].virtualMods & (~wire->virtualMods)) {
1678                     *nMapsRtrn = _XkbErrCode3(0x07, n, mapWire[n].virtualMods);
1679                     return 0;
1680                 }
1681                 if (mapWire[n].level >= wire->numLevels) {
1682                     *nMapsRtrn = _XkbErrCode4(0x08, n, wire->numLevels,
1683                                               mapWire[n].level);
1684                     return 0;
1685                 }
1686                 if (wire->preserve) {
1687                     if (client->swapped && doswap) {
1688                         swaps(&preWire[n].virtualMods);
1689                     }
1690                     if (preWire[n].realMods & (~mapWire[n].realMods)) {
1691                         *nMapsRtrn = _XkbErrCode4(0x09, n, preWire[n].realMods,
1692                                                   mapWire[n].realMods);
1693                         return 0;
1694                     }
1695                     if (preWire[n].virtualMods & (~mapWire[n].virtualMods)) {
1696                         *nMapsRtrn =
1697                             _XkbErrCode3(0x0a, n, preWire[n].virtualMods);
1698                         return 0;
1699                     }
1700                 }
1701             }
1702             if (wire->preserve)
1703                 map = (CARD8 *) &preWire[wire->nMapEntries];
1704             else
1705                 map = (CARD8 *) &mapWire[wire->nMapEntries];
1706         }
1707         else
1708             map = (CARD8 *) &wire[1];
1709         mapWidthRtrn[i + req->firstType] = wire->numLevels;
1710         wire = (xkbKeyTypeWireDesc *) map;
1711     }
1712     for (i = req->firstType + req->nTypes; i < nMaps; i++) {
1713         mapWidthRtrn[i] = xkb->map->types[i].num_levels;
1714     }
1715     *nMapsRtrn = nMaps;
1716     *wireRtrn = wire;
1717     return 1;
1718 }
1719 
1720 static int
CheckKeySyms(ClientPtr client,XkbDescPtr xkb,xkbSetMapReq * req,int nTypes,CARD8 * mapWidths,CARD16 * symsPerKey,xkbSymMapWireDesc ** wireRtrn,int * errorRtrn,Bool doswap)1721 CheckKeySyms(ClientPtr client,
1722              XkbDescPtr xkb,
1723              xkbSetMapReq * req,
1724              int nTypes,
1725              CARD8 *mapWidths,
1726              CARD16 *symsPerKey, xkbSymMapWireDesc ** wireRtrn, int *errorRtrn, Bool doswap)
1727 {
1728     register unsigned i;
1729     XkbSymMapPtr map;
1730     xkbSymMapWireDesc *wire = *wireRtrn;
1731 
1732     if (!(XkbKeySymsMask & req->present))
1733         return 1;
1734     CHK_REQ_KEY_RANGE2(0x11, req->firstKeySym, req->nKeySyms, req, (*errorRtrn),
1735                        0);
1736     for (i = 0; i < req->nKeySyms; i++) {
1737         KeySym *pSyms;
1738         register unsigned nG;
1739 
1740         if (client->swapped && doswap) {
1741             swaps(&wire->nSyms);
1742         }
1743         nG = XkbNumGroups(wire->groupInfo);
1744         if (nG > XkbNumKbdGroups) {
1745             *errorRtrn = _XkbErrCode3(0x14, i + req->firstKeySym, nG);
1746             return 0;
1747         }
1748         if (nG > 0) {
1749             register int g, w;
1750 
1751             for (g = w = 0; g < nG; g++) {
1752                 if (wire->ktIndex[g] >= (unsigned) nTypes) {
1753                     *errorRtrn = _XkbErrCode4(0x15, i + req->firstKeySym, g,
1754                                               wire->ktIndex[g]);
1755                     return 0;
1756                 }
1757                 if (mapWidths[wire->ktIndex[g]] > w)
1758                     w = mapWidths[wire->ktIndex[g]];
1759             }
1760             if (wire->width != w) {
1761                 *errorRtrn =
1762                     _XkbErrCode3(0x16, i + req->firstKeySym, wire->width);
1763                 return 0;
1764             }
1765             w *= nG;
1766             symsPerKey[i + req->firstKeySym] = w;
1767             if (w != wire->nSyms) {
1768                 *errorRtrn =
1769                     _XkbErrCode4(0x16, i + req->firstKeySym, wire->nSyms, w);
1770                 return 0;
1771             }
1772         }
1773         else if (wire->nSyms != 0) {
1774             *errorRtrn = _XkbErrCode3(0x17, i + req->firstKeySym, wire->nSyms);
1775             return 0;
1776         }
1777         pSyms = (KeySym *) &wire[1];
1778         wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
1779     }
1780 
1781     map = &xkb->map->key_sym_map[i];
1782     for (; i <= (unsigned) xkb->max_key_code; i++, map++) {
1783         register int g, nG, w;
1784 
1785         nG = XkbKeyNumGroups(xkb, i);
1786         for (w = g = 0; g < nG; g++) {
1787             if (map->kt_index[g] >= (unsigned) nTypes) {
1788                 *errorRtrn = _XkbErrCode4(0x18, i, g, map->kt_index[g]);
1789                 return 0;
1790             }
1791             if (mapWidths[map->kt_index[g]] > w)
1792                 w = mapWidths[map->kt_index[g]];
1793         }
1794         symsPerKey[i] = w * nG;
1795     }
1796     *wireRtrn = wire;
1797     return 1;
1798 }
1799 
1800 static int
CheckKeyActions(XkbDescPtr xkb,xkbSetMapReq * req,int nTypes,CARD8 * mapWidths,CARD16 * symsPerKey,CARD8 ** wireRtrn,int * nActsRtrn)1801 CheckKeyActions(XkbDescPtr xkb,
1802                 xkbSetMapReq * req,
1803                 int nTypes,
1804                 CARD8 *mapWidths,
1805                 CARD16 *symsPerKey, CARD8 **wireRtrn, int *nActsRtrn)
1806 {
1807     int nActs;
1808     CARD8 *wire = *wireRtrn;
1809     register unsigned i;
1810 
1811     if (!(XkbKeyActionsMask & req->present))
1812         return 1;
1813     CHK_REQ_KEY_RANGE2(0x21, req->firstKeyAct, req->nKeyActs, req, (*nActsRtrn),
1814                        0);
1815     for (nActs = i = 0; i < req->nKeyActs; i++) {
1816         if (wire[0] != 0) {
1817             if (wire[0] == symsPerKey[i + req->firstKeyAct])
1818                 nActs += wire[0];
1819             else {
1820                 *nActsRtrn = _XkbErrCode3(0x23, i + req->firstKeyAct, wire[0]);
1821                 return 0;
1822             }
1823         }
1824         wire++;
1825     }
1826     if (req->nKeyActs % 4)
1827         wire += 4 - (req->nKeyActs % 4);
1828     *wireRtrn = (CARD8 *) (((XkbAnyAction *) wire) + nActs);
1829     *nActsRtrn = nActs;
1830     return 1;
1831 }
1832 
1833 static int
CheckKeyBehaviors(XkbDescPtr xkb,xkbSetMapReq * req,xkbBehaviorWireDesc ** wireRtrn,int * errorRtrn)1834 CheckKeyBehaviors(XkbDescPtr xkb,
1835                   xkbSetMapReq * req,
1836                   xkbBehaviorWireDesc ** wireRtrn, int *errorRtrn)
1837 {
1838     register xkbBehaviorWireDesc *wire = *wireRtrn;
1839     register XkbServerMapPtr server = xkb->server;
1840     register unsigned i;
1841     unsigned first, last;
1842 
1843     if (((req->present & XkbKeyBehaviorsMask) == 0) || (req->nKeyBehaviors < 1)) {
1844         req->present &= ~XkbKeyBehaviorsMask;
1845         req->nKeyBehaviors = 0;
1846         return 1;
1847     }
1848     first = req->firstKeyBehavior;
1849     last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
1850     if (first < req->minKeyCode) {
1851         *errorRtrn = _XkbErrCode3(0x31, first, req->minKeyCode);
1852         return 0;
1853     }
1854     if (last > req->maxKeyCode) {
1855         *errorRtrn = _XkbErrCode3(0x32, last, req->maxKeyCode);
1856         return 0;
1857     }
1858 
1859     for (i = 0; i < req->totalKeyBehaviors; i++, wire++) {
1860         if ((wire->key < first) || (wire->key > last)) {
1861             *errorRtrn = _XkbErrCode4(0x33, first, last, wire->key);
1862             return 0;
1863         }
1864         if ((wire->type & XkbKB_Permanent) &&
1865             ((server->behaviors[wire->key].type != wire->type) ||
1866              (server->behaviors[wire->key].data != wire->data))) {
1867             *errorRtrn = _XkbErrCode3(0x33, wire->key, wire->type);
1868             return 0;
1869         }
1870         if ((wire->type == XkbKB_RadioGroup) &&
1871             ((wire->data & (~XkbKB_RGAllowNone)) > XkbMaxRadioGroups)) {
1872             *errorRtrn = _XkbErrCode4(0x34, wire->key, wire->data,
1873                                       XkbMaxRadioGroups);
1874             return 0;
1875         }
1876         if ((wire->type == XkbKB_Overlay1) || (wire->type == XkbKB_Overlay2)) {
1877             CHK_KEY_RANGE2(0x35, wire->key, 1, xkb, *errorRtrn, 0);
1878         }
1879     }
1880     *wireRtrn = wire;
1881     return 1;
1882 }
1883 
1884 static int
CheckVirtualMods(XkbDescRec * xkb,xkbSetMapReq * req,CARD8 ** wireRtrn,int * errorRtrn)1885 CheckVirtualMods(XkbDescRec * xkb,
1886                  xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
1887 {
1888     register CARD8 *wire = *wireRtrn;
1889     register unsigned i, nMods, bit;
1890 
1891     if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
1892         return 1;
1893     for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
1894         if (req->virtualMods & bit)
1895             nMods++;
1896     }
1897     *wireRtrn = (wire + XkbPaddedSize(nMods));
1898     return 1;
1899 }
1900 
1901 static int
CheckKeyExplicit(XkbDescPtr xkb,xkbSetMapReq * req,CARD8 ** wireRtrn,int * errorRtrn)1902 CheckKeyExplicit(XkbDescPtr xkb,
1903                  xkbSetMapReq * req, CARD8 **wireRtrn, int *errorRtrn)
1904 {
1905     register CARD8 *wire = *wireRtrn;
1906     CARD8 *start;
1907     register unsigned i;
1908     int first, last;
1909 
1910     if (((req->present & XkbExplicitComponentsMask) == 0) ||
1911         (req->nKeyExplicit < 1)) {
1912         req->present &= ~XkbExplicitComponentsMask;
1913         req->nKeyExplicit = 0;
1914         return 1;
1915     }
1916     first = req->firstKeyExplicit;
1917     last = first + req->nKeyExplicit - 1;
1918     if (first < req->minKeyCode) {
1919         *errorRtrn = _XkbErrCode3(0x51, first, req->minKeyCode);
1920         return 0;
1921     }
1922     if (last > req->maxKeyCode) {
1923         *errorRtrn = _XkbErrCode3(0x52, last, req->maxKeyCode);
1924         return 0;
1925     }
1926     start = wire;
1927     for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
1928         if ((wire[0] < first) || (wire[0] > last)) {
1929             *errorRtrn = _XkbErrCode4(0x53, first, last, wire[0]);
1930             return 0;
1931         }
1932         if (wire[1] & (~XkbAllExplicitMask)) {
1933             *errorRtrn = _XkbErrCode3(0x52, ~XkbAllExplicitMask, wire[1]);
1934             return 0;
1935         }
1936     }
1937     wire += XkbPaddedSize(wire - start) - (wire - start);
1938     *wireRtrn = wire;
1939     return 1;
1940 }
1941 
1942 static int
CheckModifierMap(XkbDescPtr xkb,xkbSetMapReq * req,CARD8 ** wireRtrn,int * errRtrn)1943 CheckModifierMap(XkbDescPtr xkb, xkbSetMapReq * req, CARD8 **wireRtrn,
1944                  int *errRtrn)
1945 {
1946     register CARD8 *wire = *wireRtrn;
1947     CARD8 *start;
1948     register unsigned i;
1949     int first, last;
1950 
1951     if (((req->present & XkbModifierMapMask) == 0) || (req->nModMapKeys < 1)) {
1952         req->present &= ~XkbModifierMapMask;
1953         req->nModMapKeys = 0;
1954         return 1;
1955     }
1956     first = req->firstModMapKey;
1957     last = first + req->nModMapKeys - 1;
1958     if (first < req->minKeyCode) {
1959         *errRtrn = _XkbErrCode3(0x61, first, req->minKeyCode);
1960         return 0;
1961     }
1962     if (last > req->maxKeyCode) {
1963         *errRtrn = _XkbErrCode3(0x62, last, req->maxKeyCode);
1964         return 0;
1965     }
1966     start = wire;
1967     for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
1968         if ((wire[0] < first) || (wire[0] > last)) {
1969             *errRtrn = _XkbErrCode4(0x63, first, last, wire[0]);
1970             return 0;
1971         }
1972     }
1973     wire += XkbPaddedSize(wire - start) - (wire - start);
1974     *wireRtrn = wire;
1975     return 1;
1976 }
1977 
1978 static int
CheckVirtualModMap(XkbDescPtr xkb,xkbSetMapReq * req,xkbVModMapWireDesc ** wireRtrn,int * errRtrn)1979 CheckVirtualModMap(XkbDescPtr xkb,
1980                    xkbSetMapReq * req,
1981                    xkbVModMapWireDesc ** wireRtrn, int *errRtrn)
1982 {
1983     register xkbVModMapWireDesc *wire = *wireRtrn;
1984     register unsigned i;
1985     int first, last;
1986 
1987     if (((req->present & XkbVirtualModMapMask) == 0) || (req->nVModMapKeys < 1)) {
1988         req->present &= ~XkbVirtualModMapMask;
1989         req->nVModMapKeys = 0;
1990         return 1;
1991     }
1992     first = req->firstVModMapKey;
1993     last = first + req->nVModMapKeys - 1;
1994     if (first < req->minKeyCode) {
1995         *errRtrn = _XkbErrCode3(0x71, first, req->minKeyCode);
1996         return 0;
1997     }
1998     if (last > req->maxKeyCode) {
1999         *errRtrn = _XkbErrCode3(0x72, last, req->maxKeyCode);
2000         return 0;
2001     }
2002     for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2003         if ((wire->key < first) || (wire->key > last)) {
2004             *errRtrn = _XkbErrCode4(0x73, first, last, wire->key);
2005             return 0;
2006         }
2007     }
2008     *wireRtrn = wire;
2009     return 1;
2010 }
2011 
2012 static char *
SetKeyTypes(XkbDescPtr xkb,xkbSetMapReq * req,xkbKeyTypeWireDesc * wire,XkbChangesPtr changes)2013 SetKeyTypes(XkbDescPtr xkb,
2014             xkbSetMapReq * req,
2015             xkbKeyTypeWireDesc * wire, XkbChangesPtr changes)
2016 {
2017     register unsigned i;
2018     unsigned first, last;
2019     CARD8 *map;
2020 
2021     if ((unsigned) (req->firstType + req->nTypes) > xkb->map->size_types) {
2022         i = req->firstType + req->nTypes;
2023         if (XkbAllocClientMap(xkb, XkbKeyTypesMask, i) != Success) {
2024             return NULL;
2025         }
2026     }
2027     if ((unsigned) (req->firstType + req->nTypes) > xkb->map->num_types)
2028         xkb->map->num_types = req->firstType + req->nTypes;
2029 
2030     for (i = 0; i < req->nTypes; i++) {
2031         XkbKeyTypePtr pOld;
2032         register unsigned n;
2033 
2034         if (XkbResizeKeyType(xkb, i + req->firstType, wire->nMapEntries,
2035                              wire->preserve, wire->numLevels) != Success) {
2036             return NULL;
2037         }
2038         pOld = &xkb->map->types[i + req->firstType];
2039         map = (CARD8 *) &wire[1];
2040 
2041         pOld->mods.real_mods = wire->realMods;
2042         pOld->mods.vmods = wire->virtualMods;
2043         pOld->num_levels = wire->numLevels;
2044         pOld->map_count = wire->nMapEntries;
2045 
2046         pOld->mods.mask = pOld->mods.real_mods |
2047             XkbMaskForVMask(xkb, pOld->mods.vmods);
2048 
2049         if (wire->nMapEntries) {
2050             xkbKTSetMapEntryWireDesc *mapWire;
2051             xkbModsWireDesc *preWire;
2052             unsigned tmp;
2053 
2054             mapWire = (xkbKTSetMapEntryWireDesc *) map;
2055             preWire = (xkbModsWireDesc *) &mapWire[wire->nMapEntries];
2056             for (n = 0; n < wire->nMapEntries; n++) {
2057                 pOld->map[n].active = 1;
2058                 pOld->map[n].mods.mask = mapWire[n].realMods;
2059                 pOld->map[n].mods.real_mods = mapWire[n].realMods;
2060                 pOld->map[n].mods.vmods = mapWire[n].virtualMods;
2061                 pOld->map[n].level = mapWire[n].level;
2062                 if (mapWire[n].virtualMods != 0) {
2063                     tmp = XkbMaskForVMask(xkb, mapWire[n].virtualMods);
2064                     pOld->map[n].active = (tmp != 0);
2065                     pOld->map[n].mods.mask |= tmp;
2066                 }
2067                 if (wire->preserve) {
2068                     pOld->preserve[n].real_mods = preWire[n].realMods;
2069                     pOld->preserve[n].vmods = preWire[n].virtualMods;
2070                     tmp = XkbMaskForVMask(xkb, preWire[n].virtualMods);
2071                     pOld->preserve[n].mask = preWire[n].realMods | tmp;
2072                 }
2073             }
2074             if (wire->preserve)
2075                 map = (CARD8 *) &preWire[wire->nMapEntries];
2076             else
2077                 map = (CARD8 *) &mapWire[wire->nMapEntries];
2078         }
2079         else
2080             map = (CARD8 *) &wire[1];
2081         wire = (xkbKeyTypeWireDesc *) map;
2082     }
2083     first = req->firstType;
2084     last = first + req->nTypes - 1;     /* last changed type */
2085     if (changes->map.changed & XkbKeyTypesMask) {
2086         int oldLast;
2087 
2088         oldLast = changes->map.first_type + changes->map.num_types - 1;
2089         if (changes->map.first_type < first)
2090             first = changes->map.first_type;
2091         if (oldLast > last)
2092             last = oldLast;
2093     }
2094     changes->map.changed |= XkbKeyTypesMask;
2095     changes->map.first_type = first;
2096     changes->map.num_types = (last - first) + 1;
2097     return (char *) wire;
2098 }
2099 
2100 static char *
SetKeySyms(ClientPtr client,XkbDescPtr xkb,xkbSetMapReq * req,xkbSymMapWireDesc * wire,XkbChangesPtr changes,DeviceIntPtr dev)2101 SetKeySyms(ClientPtr client,
2102            XkbDescPtr xkb,
2103            xkbSetMapReq * req,
2104            xkbSymMapWireDesc * wire, XkbChangesPtr changes, DeviceIntPtr dev)
2105 {
2106     register unsigned i, s;
2107     XkbSymMapPtr oldMap;
2108     KeySym *newSyms;
2109     KeySym *pSyms;
2110     unsigned first, last;
2111 
2112     oldMap = &xkb->map->key_sym_map[req->firstKeySym];
2113     for (i = 0; i < req->nKeySyms; i++, oldMap++) {
2114         pSyms = (KeySym *) &wire[1];
2115         if (wire->nSyms > 0) {
2116             newSyms = XkbResizeKeySyms(xkb, i + req->firstKeySym, wire->nSyms);
2117             for (s = 0; s < wire->nSyms; s++) {
2118                 newSyms[s] = pSyms[s];
2119             }
2120             if (client->swapped) {
2121                 for (s = 0; s < wire->nSyms; s++) {
2122                     swapl(&newSyms[s]);
2123                 }
2124             }
2125         }
2126         if (XkbKeyHasActions(xkb, i + req->firstKeySym))
2127             XkbResizeKeyActions(xkb, i + req->firstKeySym,
2128                                 XkbNumGroups(wire->groupInfo) * wire->width);
2129         oldMap->kt_index[0] = wire->ktIndex[0];
2130         oldMap->kt_index[1] = wire->ktIndex[1];
2131         oldMap->kt_index[2] = wire->ktIndex[2];
2132         oldMap->kt_index[3] = wire->ktIndex[3];
2133         oldMap->group_info = wire->groupInfo;
2134         oldMap->width = wire->width;
2135         wire = (xkbSymMapWireDesc *) &pSyms[wire->nSyms];
2136     }
2137     first = req->firstKeySym;
2138     last = first + req->nKeySyms - 1;
2139     if (changes->map.changed & XkbKeySymsMask) {
2140         int oldLast =
2141             (changes->map.first_key_sym + changes->map.num_key_syms - 1);
2142         if (changes->map.first_key_sym < first)
2143             first = changes->map.first_key_sym;
2144         if (oldLast > last)
2145             last = oldLast;
2146     }
2147     changes->map.changed |= XkbKeySymsMask;
2148     changes->map.first_key_sym = first;
2149     changes->map.num_key_syms = (last - first + 1);
2150 
2151     s = 0;
2152     for (i = xkb->min_key_code; i <= xkb->max_key_code; i++) {
2153         if (XkbKeyNumGroups(xkb, i) > s)
2154             s = XkbKeyNumGroups(xkb, i);
2155     }
2156     if (s != xkb->ctrls->num_groups) {
2157         xkbControlsNotify cn;
2158         XkbControlsRec old;
2159 
2160         cn.keycode = 0;
2161         cn.eventType = 0;
2162         cn.requestMajor = XkbReqCode;
2163         cn.requestMinor = X_kbSetMap;
2164         old = *xkb->ctrls;
2165         xkb->ctrls->num_groups = s;
2166         if (XkbComputeControlsNotify(dev, &old, xkb->ctrls, &cn, FALSE))
2167             XkbSendControlsNotify(dev, &cn);
2168     }
2169     return (char *) wire;
2170 }
2171 
2172 static char *
SetKeyActions(XkbDescPtr xkb,xkbSetMapReq * req,CARD8 * wire,XkbChangesPtr changes)2173 SetKeyActions(XkbDescPtr xkb,
2174               xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2175 {
2176     register unsigned i, first, last;
2177     CARD8 *nActs = wire;
2178     XkbAction *newActs;
2179 
2180     wire += XkbPaddedSize(req->nKeyActs);
2181     for (i = 0; i < req->nKeyActs; i++) {
2182         if (nActs[i] == 0)
2183             xkb->server->key_acts[i + req->firstKeyAct] = 0;
2184         else {
2185             newActs = XkbResizeKeyActions(xkb, i + req->firstKeyAct, nActs[i]);
2186             memcpy((char *) newActs, (char *) wire,
2187                    nActs[i] * SIZEOF(xkbActionWireDesc));
2188             wire += nActs[i] * SIZEOF(xkbActionWireDesc);
2189         }
2190     }
2191     first = req->firstKeyAct;
2192     last = (first + req->nKeyActs - 1);
2193     if (changes->map.changed & XkbKeyActionsMask) {
2194         int oldLast;
2195 
2196         oldLast = changes->map.first_key_act + changes->map.num_key_acts - 1;
2197         if (changes->map.first_key_act < first)
2198             first = changes->map.first_key_act;
2199         if (oldLast > last)
2200             last = oldLast;
2201     }
2202     changes->map.changed |= XkbKeyActionsMask;
2203     changes->map.first_key_act = first;
2204     changes->map.num_key_acts = (last - first + 1);
2205     return (char *) wire;
2206 }
2207 
2208 static char *
SetKeyBehaviors(XkbSrvInfoPtr xkbi,xkbSetMapReq * req,xkbBehaviorWireDesc * wire,XkbChangesPtr changes)2209 SetKeyBehaviors(XkbSrvInfoPtr xkbi,
2210                 xkbSetMapReq * req,
2211                 xkbBehaviorWireDesc * wire, XkbChangesPtr changes)
2212 {
2213     register unsigned i;
2214     int maxRG = -1;
2215     XkbDescPtr xkb = xkbi->desc;
2216     XkbServerMapPtr server = xkb->server;
2217     unsigned first, last;
2218 
2219     first = req->firstKeyBehavior;
2220     last = req->firstKeyBehavior + req->nKeyBehaviors - 1;
2221     memset(&server->behaviors[first], 0,
2222            req->nKeyBehaviors * sizeof(XkbBehavior));
2223     for (i = 0; i < req->totalKeyBehaviors; i++) {
2224         if ((server->behaviors[wire->key].type & XkbKB_Permanent) == 0) {
2225             server->behaviors[wire->key].type = wire->type;
2226             server->behaviors[wire->key].data = wire->data;
2227             if ((wire->type == XkbKB_RadioGroup) &&
2228                 (((int) wire->data) > maxRG))
2229                 maxRG = wire->data + 1;
2230         }
2231         wire++;
2232     }
2233 
2234     if (maxRG > (int) xkbi->nRadioGroups) {
2235         if (xkbi->radioGroups)
2236             xkbi->radioGroups = reallocarray(xkbi->radioGroups, maxRG,
2237                                              sizeof(XkbRadioGroupRec));
2238         else
2239             xkbi->radioGroups = calloc(maxRG, sizeof(XkbRadioGroupRec));
2240         if (xkbi->radioGroups) {
2241             if (xkbi->nRadioGroups)
2242                 memset(&xkbi->radioGroups[xkbi->nRadioGroups], 0,
2243                        (maxRG - xkbi->nRadioGroups) * sizeof(XkbRadioGroupRec));
2244             xkbi->nRadioGroups = maxRG;
2245         }
2246         else
2247             xkbi->nRadioGroups = 0;
2248         /* should compute members here */
2249     }
2250     if (changes->map.changed & XkbKeyBehaviorsMask) {
2251         unsigned oldLast;
2252 
2253         oldLast = changes->map.first_key_behavior +
2254             changes->map.num_key_behaviors - 1;
2255         if (changes->map.first_key_behavior < req->firstKeyBehavior)
2256             first = changes->map.first_key_behavior;
2257         if (oldLast > last)
2258             last = oldLast;
2259     }
2260     changes->map.changed |= XkbKeyBehaviorsMask;
2261     changes->map.first_key_behavior = first;
2262     changes->map.num_key_behaviors = (last - first + 1);
2263     return (char *) wire;
2264 }
2265 
2266 static char *
SetVirtualMods(XkbSrvInfoPtr xkbi,xkbSetMapReq * req,CARD8 * wire,XkbChangesPtr changes)2267 SetVirtualMods(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2268                XkbChangesPtr changes)
2269 {
2270     register int i, bit, nMods;
2271     XkbServerMapPtr srv = xkbi->desc->server;
2272 
2273     if (((req->present & XkbVirtualModsMask) == 0) || (req->virtualMods == 0))
2274         return (char *) wire;
2275     for (i = nMods = 0, bit = 1; i < XkbNumVirtualMods; i++, bit <<= 1) {
2276         if (req->virtualMods & bit) {
2277             if (srv->vmods[i] != wire[nMods]) {
2278                 changes->map.changed |= XkbVirtualModsMask;
2279                 changes->map.vmods |= bit;
2280                 srv->vmods[i] = wire[nMods];
2281             }
2282             nMods++;
2283         }
2284     }
2285     return (char *) (wire + XkbPaddedSize(nMods));
2286 }
2287 
2288 static char *
SetKeyExplicit(XkbSrvInfoPtr xkbi,xkbSetMapReq * req,CARD8 * wire,XkbChangesPtr changes)2289 SetKeyExplicit(XkbSrvInfoPtr xkbi, xkbSetMapReq * req, CARD8 *wire,
2290                XkbChangesPtr changes)
2291 {
2292     register unsigned i, first, last;
2293     XkbServerMapPtr xkb = xkbi->desc->server;
2294     CARD8 *start;
2295 
2296     start = wire;
2297     first = req->firstKeyExplicit;
2298     last = req->firstKeyExplicit + req->nKeyExplicit - 1;
2299     memset(&xkb->explicit[first], 0, req->nKeyExplicit);
2300     for (i = 0; i < req->totalKeyExplicit; i++, wire += 2) {
2301         xkb->explicit[wire[0]] = wire[1];
2302     }
2303     if (first > 0) {
2304         if (changes->map.changed & XkbExplicitComponentsMask) {
2305             int oldLast;
2306 
2307             oldLast = changes->map.first_key_explicit +
2308                 changes->map.num_key_explicit - 1;
2309             if (changes->map.first_key_explicit < first)
2310                 first = changes->map.first_key_explicit;
2311             if (oldLast > last)
2312                 last = oldLast;
2313         }
2314         changes->map.first_key_explicit = first;
2315         changes->map.num_key_explicit = (last - first) + 1;
2316     }
2317     wire += XkbPaddedSize(wire - start) - (wire - start);
2318     return (char *) wire;
2319 }
2320 
2321 static char *
SetModifierMap(XkbSrvInfoPtr xkbi,xkbSetMapReq * req,CARD8 * wire,XkbChangesPtr changes)2322 SetModifierMap(XkbSrvInfoPtr xkbi,
2323                xkbSetMapReq * req, CARD8 *wire, XkbChangesPtr changes)
2324 {
2325     register unsigned i, first, last;
2326     XkbClientMapPtr xkb = xkbi->desc->map;
2327     CARD8 *start;
2328 
2329     start = wire;
2330     first = req->firstModMapKey;
2331     last = req->firstModMapKey + req->nModMapKeys - 1;
2332     memset(&xkb->modmap[first], 0, req->nModMapKeys);
2333     for (i = 0; i < req->totalModMapKeys; i++, wire += 2) {
2334         xkb->modmap[wire[0]] = wire[1];
2335     }
2336     if (first > 0) {
2337         if (changes->map.changed & XkbModifierMapMask) {
2338             int oldLast;
2339 
2340             oldLast = changes->map.first_modmap_key +
2341                 changes->map.num_modmap_keys - 1;
2342             if (changes->map.first_modmap_key < first)
2343                 first = changes->map.first_modmap_key;
2344             if (oldLast > last)
2345                 last = oldLast;
2346         }
2347         changes->map.first_modmap_key = first;
2348         changes->map.num_modmap_keys = (last - first) + 1;
2349     }
2350     wire += XkbPaddedSize(wire - start) - (wire - start);
2351     return (char *) wire;
2352 }
2353 
2354 static char *
SetVirtualModMap(XkbSrvInfoPtr xkbi,xkbSetMapReq * req,xkbVModMapWireDesc * wire,XkbChangesPtr changes)2355 SetVirtualModMap(XkbSrvInfoPtr xkbi,
2356                  xkbSetMapReq * req,
2357                  xkbVModMapWireDesc * wire, XkbChangesPtr changes)
2358 {
2359     register unsigned i, first, last;
2360     XkbServerMapPtr srv = xkbi->desc->server;
2361 
2362     first = req->firstVModMapKey;
2363     last = req->firstVModMapKey + req->nVModMapKeys - 1;
2364     memset(&srv->vmodmap[first], 0, req->nVModMapKeys * sizeof(unsigned short));
2365     for (i = 0; i < req->totalVModMapKeys; i++, wire++) {
2366         srv->vmodmap[wire->key] = wire->vmods;
2367     }
2368     if (first > 0) {
2369         if (changes->map.changed & XkbVirtualModMapMask) {
2370             int oldLast;
2371 
2372             oldLast = changes->map.first_vmodmap_key +
2373                 changes->map.num_vmodmap_keys - 1;
2374             if (changes->map.first_vmodmap_key < first)
2375                 first = changes->map.first_vmodmap_key;
2376             if (oldLast > last)
2377                 last = oldLast;
2378         }
2379         changes->map.first_vmodmap_key = first;
2380         changes->map.num_vmodmap_keys = (last - first) + 1;
2381     }
2382     return (char *) wire;
2383 }
2384 
2385 /**
2386  * Check if the given request can be applied to the given device but don't
2387  * actually do anything, except swap values when client->swapped and doswap are both true.
2388  */
2389 static int
_XkbSetMapChecks(ClientPtr client,DeviceIntPtr dev,xkbSetMapReq * req,char * values,Bool doswap)2390 _XkbSetMapChecks(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req,
2391                  char *values, Bool doswap)
2392 {
2393     XkbSrvInfoPtr xkbi;
2394     XkbDescPtr xkb;
2395     int error;
2396     int nTypes = 0, nActions;
2397     CARD8 mapWidths[XkbMaxLegalKeyCode + 1] = { 0 };
2398     CARD16 symsPerKey[XkbMaxLegalKeyCode + 1] = { 0 };
2399     XkbSymMapPtr map;
2400     int i;
2401 
2402     if (!dev->key)
2403         return 0;
2404 
2405     xkbi = dev->key->xkbInfo;
2406     xkb = xkbi->desc;
2407 
2408     if ((xkb->min_key_code != req->minKeyCode) ||
2409         (xkb->max_key_code != req->maxKeyCode)) {
2410         if (client->xkbClientFlags & _XkbClientIsAncient) {
2411             /* pre 1.0 versions of Xlib have a bug */
2412             req->minKeyCode = xkb->min_key_code;
2413             req->maxKeyCode = xkb->max_key_code;
2414         }
2415         else {
2416             if (!XkbIsLegalKeycode(req->minKeyCode)) {
2417                 client->errorValue =
2418                     _XkbErrCode3(2, req->minKeyCode, req->maxKeyCode);
2419                 return BadValue;
2420             }
2421             if (req->minKeyCode > req->maxKeyCode) {
2422                 client->errorValue =
2423                     _XkbErrCode3(3, req->minKeyCode, req->maxKeyCode);
2424                 return BadMatch;
2425             }
2426         }
2427     }
2428 
2429     if ((req->present & XkbKeyTypesMask) &&
2430         (!CheckKeyTypes(client, xkb, req, (xkbKeyTypeWireDesc **) &values,
2431                         &nTypes, mapWidths, doswap))) {
2432         client->errorValue = nTypes;
2433         return BadValue;
2434     }
2435     else {
2436         nTypes = xkb->map->num_types;
2437     }
2438 
2439     /* symsPerKey/mapWidths must be filled regardless of client-side flags */
2440     map = &xkb->map->key_sym_map[xkb->min_key_code];
2441     for (i = xkb->min_key_code; i < xkb->max_key_code; i++, map++) {
2442         register int g, ng, w;
2443 
2444         ng = XkbNumGroups(map->group_info);
2445         for (w = g = 0; g < ng; g++) {
2446             if (map->kt_index[g] >= (unsigned) nTypes) {
2447                 client->errorValue = _XkbErrCode4(0x13, i, g, map->kt_index[g]);
2448                 return BadValue;
2449             }
2450             if (mapWidths[map->kt_index[g]] > w)
2451                 w = mapWidths[map->kt_index[g]];
2452         }
2453         symsPerKey[i] = w * ng;
2454     }
2455 
2456     if ((req->present & XkbKeySymsMask) &&
2457         (!CheckKeySyms(client, xkb, req, nTypes, mapWidths, symsPerKey,
2458                        (xkbSymMapWireDesc **) &values, &error, doswap))) {
2459         client->errorValue = error;
2460         return BadValue;
2461     }
2462 
2463     if ((req->present & XkbKeyActionsMask) &&
2464         (!CheckKeyActions(xkb, req, nTypes, mapWidths, symsPerKey,
2465                           (CARD8 **) &values, &nActions))) {
2466         client->errorValue = nActions;
2467         return BadValue;
2468     }
2469 
2470     if ((req->present & XkbKeyBehaviorsMask) &&
2471         (!CheckKeyBehaviors
2472          (xkb, req, (xkbBehaviorWireDesc **) &values, &error))) {
2473         client->errorValue = error;
2474         return BadValue;
2475     }
2476 
2477     if ((req->present & XkbVirtualModsMask) &&
2478         (!CheckVirtualMods(xkb, req, (CARD8 **) &values, &error))) {
2479         client->errorValue = error;
2480         return BadValue;
2481     }
2482     if ((req->present & XkbExplicitComponentsMask) &&
2483         (!CheckKeyExplicit(xkb, req, (CARD8 **) &values, &error))) {
2484         client->errorValue = error;
2485         return BadValue;
2486     }
2487     if ((req->present & XkbModifierMapMask) &&
2488         (!CheckModifierMap(xkb, req, (CARD8 **) &values, &error))) {
2489         client->errorValue = error;
2490         return BadValue;
2491     }
2492     if ((req->present & XkbVirtualModMapMask) &&
2493         (!CheckVirtualModMap
2494          (xkb, req, (xkbVModMapWireDesc **) &values, &error))) {
2495         client->errorValue = error;
2496         return BadValue;
2497     }
2498 
2499     if (((values - ((char *) req)) / 4) != req->length) {
2500         ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n");
2501         client->errorValue = values - ((char *) &req[1]);
2502         return BadLength;
2503     }
2504 
2505     return Success;
2506 }
2507 
2508 /**
2509  * Apply the given request on the given device.
2510  */
2511 static int
_XkbSetMap(ClientPtr client,DeviceIntPtr dev,xkbSetMapReq * req,char * values)2512 _XkbSetMap(ClientPtr client, DeviceIntPtr dev, xkbSetMapReq * req, char *values)
2513 {
2514     XkbEventCauseRec cause;
2515     XkbChangesRec change;
2516     Bool sentNKN;
2517     XkbSrvInfoPtr xkbi;
2518     XkbDescPtr xkb;
2519 
2520     if (!dev->key)
2521         return Success;
2522 
2523     xkbi = dev->key->xkbInfo;
2524     xkb = xkbi->desc;
2525 
2526     XkbSetCauseXkbReq(&cause, X_kbSetMap, client);
2527     memset(&change, 0, sizeof(change));
2528     sentNKN = FALSE;
2529     if ((xkb->min_key_code != req->minKeyCode) ||
2530         (xkb->max_key_code != req->maxKeyCode)) {
2531         Status status;
2532         xkbNewKeyboardNotify nkn;
2533 
2534         nkn.deviceID = nkn.oldDeviceID = dev->id;
2535         nkn.oldMinKeyCode = xkb->min_key_code;
2536         nkn.oldMaxKeyCode = xkb->max_key_code;
2537         status = XkbChangeKeycodeRange(xkb, req->minKeyCode,
2538                                        req->maxKeyCode, &change);
2539         if (status != Success)
2540             return status;      /* oh-oh. what about the other keyboards? */
2541         nkn.minKeyCode = xkb->min_key_code;
2542         nkn.maxKeyCode = xkb->max_key_code;
2543         nkn.requestMajor = XkbReqCode;
2544         nkn.requestMinor = X_kbSetMap;
2545         nkn.changed = XkbNKN_KeycodesMask;
2546         XkbSendNewKeyboardNotify(dev, &nkn);
2547         sentNKN = TRUE;
2548     }
2549 
2550     if (req->present & XkbKeyTypesMask) {
2551         values = SetKeyTypes(xkb, req, (xkbKeyTypeWireDesc *) values, &change);
2552         if (!values)
2553             goto allocFailure;
2554     }
2555     if (req->present & XkbKeySymsMask) {
2556         values =
2557             SetKeySyms(client, xkb, req, (xkbSymMapWireDesc *) values, &change,
2558                        dev);
2559         if (!values)
2560             goto allocFailure;
2561     }
2562     if (req->present & XkbKeyActionsMask) {
2563         values = SetKeyActions(xkb, req, (CARD8 *) values, &change);
2564         if (!values)
2565             goto allocFailure;
2566     }
2567     if (req->present & XkbKeyBehaviorsMask) {
2568         values =
2569             SetKeyBehaviors(xkbi, req, (xkbBehaviorWireDesc *) values, &change);
2570         if (!values)
2571             goto allocFailure;
2572     }
2573     if (req->present & XkbVirtualModsMask)
2574         values = SetVirtualMods(xkbi, req, (CARD8 *) values, &change);
2575     if (req->present & XkbExplicitComponentsMask)
2576         values = SetKeyExplicit(xkbi, req, (CARD8 *) values, &change);
2577     if (req->present & XkbModifierMapMask)
2578         values = SetModifierMap(xkbi, req, (CARD8 *) values, &change);
2579     if (req->present & XkbVirtualModMapMask)
2580         values =
2581             SetVirtualModMap(xkbi, req, (xkbVModMapWireDesc *) values, &change);
2582     if (((values - ((char *) req)) / 4) != req->length) {
2583         ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n");
2584         client->errorValue = values - ((char *) &req[1]);
2585         return BadLength;
2586     }
2587     if (req->flags & XkbSetMapRecomputeActions) {
2588         KeyCode first, last, firstMM, lastMM;
2589 
2590         if (change.map.num_key_syms > 0) {
2591             first = change.map.first_key_sym;
2592             last = first + change.map.num_key_syms - 1;
2593         }
2594         else
2595             first = last = 0;
2596         if (change.map.num_modmap_keys > 0) {
2597             firstMM = change.map.first_modmap_key;
2598             lastMM = firstMM + change.map.num_modmap_keys - 1;
2599         }
2600         else
2601             firstMM = lastMM = 0;
2602         if ((last > 0) && (lastMM > 0)) {
2603             if (firstMM < first)
2604                 first = firstMM;
2605             if (lastMM > last)
2606                 last = lastMM;
2607         }
2608         else if (lastMM > 0) {
2609             first = firstMM;
2610             last = lastMM;
2611         }
2612         if (last > 0) {
2613             unsigned check = 0;
2614 
2615             XkbUpdateActions(dev, first, (last - first + 1), &change, &check,
2616                              &cause);
2617             if (check)
2618                 XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
2619         }
2620     }
2621     if (!sentNKN)
2622         XkbSendNotification(dev, &change, &cause);
2623 
2624     return Success;
2625  allocFailure:
2626     return BadAlloc;
2627 }
2628 
2629 int
ProcXkbSetMap(ClientPtr client)2630 ProcXkbSetMap(ClientPtr client)
2631 {
2632     DeviceIntPtr dev;
2633     char *tmp;
2634     int rc;
2635 
2636     REQUEST(xkbSetMapReq);
2637     REQUEST_AT_LEAST_SIZE(xkbSetMapReq);
2638 
2639     if (!(client->xkbClientFlags & _XkbClientInitialized))
2640         return BadAccess;
2641 
2642     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
2643     CHK_MASK_LEGAL(0x01, stuff->present, XkbAllMapComponentsMask);
2644 
2645     tmp = (char *) &stuff[1];
2646 
2647     /* Check if we can to the SetMap on the requested device. If this
2648        succeeds, do the same thing for all extension devices (if needed).
2649        If any of them fails, fail.  */
2650     rc = _XkbSetMapChecks(client, dev, stuff, tmp, TRUE);
2651 
2652     if (rc != Success)
2653         return rc;
2654 
2655     DeviceIntPtr master = GetMaster(dev, MASTER_KEYBOARD);
2656 
2657     if (stuff->deviceSpec == XkbUseCoreKbd) {
2658         DeviceIntPtr other;
2659 
2660         for (other = inputInfo.devices; other; other = other->next) {
2661             if ((other != dev) && other->key && !IsMaster(other) &&
2662                 GetMaster(other, MASTER_KEYBOARD) == dev) {
2663                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2664                               DixManageAccess);
2665                 if (rc == Success) {
2666                     rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
2667                     if (rc != Success)
2668                         return rc;
2669                 }
2670             }
2671         }
2672     } else {
2673         DeviceIntPtr other;
2674 
2675         for (other = inputInfo.devices; other; other = other->next) {
2676             if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2677                 (other != master || dev != master->lastSlave))
2678                 continue;
2679 
2680             rc = _XkbSetMapChecks(client, other, stuff, tmp, FALSE);
2681             if (rc != Success)
2682                 return rc;
2683         }
2684     }
2685 
2686     /* We know now that we will succeed with the SetMap. In theory anyway. */
2687     rc = _XkbSetMap(client, dev, stuff, tmp);
2688     if (rc != Success)
2689         return rc;
2690 
2691     if (stuff->deviceSpec == XkbUseCoreKbd) {
2692         DeviceIntPtr other;
2693 
2694         for (other = inputInfo.devices; other; other = other->next) {
2695             if ((other != dev) && other->key && !IsMaster(other) &&
2696                 GetMaster(other, MASTER_KEYBOARD) == dev) {
2697                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
2698                               DixManageAccess);
2699                 if (rc == Success)
2700                     _XkbSetMap(client, other, stuff, tmp);
2701                 /* ignore rc. if the SetMap failed although the check above
2702                    reported true there isn't much we can do. we still need to
2703                    set all other devices, hoping that at least they stay in
2704                    sync. */
2705             }
2706         }
2707     } else {
2708         DeviceIntPtr other;
2709 
2710         for (other = inputInfo.devices; other; other = other->next) {
2711             if (other != dev && GetMaster(other, MASTER_KEYBOARD) != dev &&
2712                 (other != master || dev != master->lastSlave))
2713                 continue;
2714 
2715             _XkbSetMap(client, other, stuff, tmp); //ignore rc
2716         }
2717     }
2718 
2719     return Success;
2720 }
2721 
2722 /***====================================================================***/
2723 
2724 static Status
XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,xkbGetCompatMapReply * rep)2725 XkbComputeGetCompatMapReplySize(XkbCompatMapPtr compat,
2726                                 xkbGetCompatMapReply * rep)
2727 {
2728     unsigned size, nGroups;
2729 
2730     nGroups = 0;
2731     if (rep->groups != 0) {
2732         register int i, bit;
2733 
2734         for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2735             if (rep->groups & bit)
2736                 nGroups++;
2737         }
2738     }
2739     size = nGroups * SIZEOF(xkbModsWireDesc);
2740     size += (rep->nSI * SIZEOF(xkbSymInterpretWireDesc));
2741     rep->length = size / 4;
2742     return Success;
2743 }
2744 
2745 static int
XkbSendCompatMap(ClientPtr client,XkbCompatMapPtr compat,xkbGetCompatMapReply * rep)2746 XkbSendCompatMap(ClientPtr client,
2747                  XkbCompatMapPtr compat, xkbGetCompatMapReply * rep)
2748 {
2749     char *data;
2750     int size;
2751 
2752     if (rep->length > 0) {
2753         data = xallocarray(rep->length, 4);
2754         if (data) {
2755             register unsigned i, bit;
2756             xkbModsWireDesc *grp;
2757             XkbSymInterpretPtr sym = &compat->sym_interpret[rep->firstSI];
2758             xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2759 
2760             size = rep->length * 4;
2761 
2762             for (i = 0; i < rep->nSI; i++, sym++, wire++) {
2763                 wire->sym = sym->sym;
2764                 wire->mods = sym->mods;
2765                 wire->match = sym->match;
2766                 wire->virtualMod = sym->virtual_mod;
2767                 wire->flags = sym->flags;
2768                 memcpy((char *) &wire->act, (char *) &sym->act,
2769                        sz_xkbActionWireDesc);
2770                 if (client->swapped) {
2771                     swapl(&wire->sym);
2772                 }
2773             }
2774             if (rep->groups) {
2775                 grp = (xkbModsWireDesc *) wire;
2776                 for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2777                     if (rep->groups & bit) {
2778                         grp->mask = compat->groups[i].mask;
2779                         grp->realMods = compat->groups[i].real_mods;
2780                         grp->virtualMods = compat->groups[i].vmods;
2781                         if (client->swapped) {
2782                             swaps(&grp->virtualMods);
2783                         }
2784                         grp++;
2785                     }
2786                 }
2787                 wire = (xkbSymInterpretWireDesc *) grp;
2788             }
2789         }
2790         else
2791             return BadAlloc;
2792     }
2793     else
2794         data = NULL;
2795 
2796     if (client->swapped) {
2797         swaps(&rep->sequenceNumber);
2798         swapl(&rep->length);
2799         swaps(&rep->firstSI);
2800         swaps(&rep->nSI);
2801         swaps(&rep->nTotalSI);
2802     }
2803 
2804     WriteToClient(client, SIZEOF(xkbGetCompatMapReply), rep);
2805     if (data) {
2806         WriteToClient(client, size, data);
2807         free((char *) data);
2808     }
2809     return Success;
2810 }
2811 
2812 int
ProcXkbGetCompatMap(ClientPtr client)2813 ProcXkbGetCompatMap(ClientPtr client)
2814 {
2815     xkbGetCompatMapReply rep;
2816     DeviceIntPtr dev;
2817     XkbDescPtr xkb;
2818     XkbCompatMapPtr compat;
2819 
2820     REQUEST(xkbGetCompatMapReq);
2821     REQUEST_SIZE_MATCH(xkbGetCompatMapReq);
2822 
2823     if (!(client->xkbClientFlags & _XkbClientInitialized))
2824         return BadAccess;
2825 
2826     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
2827 
2828     xkb = dev->key->xkbInfo->desc;
2829     compat = xkb->compat;
2830 
2831     rep = (xkbGetCompatMapReply) {
2832         .type = X_Reply,
2833         .sequenceNumber = client->sequence,
2834         .length = 0,
2835         .deviceID = dev->id,
2836         .firstSI = stuff->firstSI,
2837         .nSI = stuff->nSI
2838     };
2839     if (stuff->getAllSI) {
2840         rep.firstSI = 0;
2841         rep.nSI = compat->num_si;
2842     }
2843     else if ((((unsigned) stuff->nSI) > 0) &&
2844              ((unsigned) (stuff->firstSI + stuff->nSI - 1) >= compat->num_si)) {
2845         client->errorValue = _XkbErrCode2(0x05, compat->num_si);
2846         return BadValue;
2847     }
2848     rep.nTotalSI = compat->num_si;
2849     rep.groups = stuff->groups;
2850     XkbComputeGetCompatMapReplySize(compat, &rep);
2851     return XkbSendCompatMap(client, compat, &rep);
2852 }
2853 
2854 /**
2855  * Apply the given request on the given device.
2856  * If dryRun is TRUE, then value checks are performed, but the device isn't
2857  * modified.
2858  */
2859 static int
_XkbSetCompatMap(ClientPtr client,DeviceIntPtr dev,xkbSetCompatMapReq * req,char * data,BOOL dryRun)2860 _XkbSetCompatMap(ClientPtr client, DeviceIntPtr dev,
2861                  xkbSetCompatMapReq * req, char *data, BOOL dryRun)
2862 {
2863     XkbSrvInfoPtr xkbi;
2864     XkbDescPtr xkb;
2865     XkbCompatMapPtr compat;
2866     int nGroups;
2867     unsigned i, bit;
2868 
2869     xkbi = dev->key->xkbInfo;
2870     xkb = xkbi->desc;
2871     compat = xkb->compat;
2872 
2873     if ((req->nSI > 0) || (req->truncateSI)) {
2874         xkbSymInterpretWireDesc *wire;
2875 
2876         if (req->firstSI > compat->num_si) {
2877             client->errorValue = _XkbErrCode2(0x02, compat->num_si);
2878             return BadValue;
2879         }
2880         wire = (xkbSymInterpretWireDesc *) data;
2881         wire += req->nSI;
2882         data = (char *) wire;
2883     }
2884 
2885     nGroups = 0;
2886     if (req->groups != 0) {
2887         for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2888             if (req->groups & bit)
2889                 nGroups++;
2890         }
2891     }
2892     data += nGroups * SIZEOF(xkbModsWireDesc);
2893     if (((data - ((char *) req)) / 4) != req->length) {
2894         return BadLength;
2895     }
2896 
2897     /* Done all the checks we can do */
2898     if (dryRun)
2899         return Success;
2900 
2901     data = (char *) &req[1];
2902     if (req->nSI > 0) {
2903         xkbSymInterpretWireDesc *wire = (xkbSymInterpretWireDesc *) data;
2904         XkbSymInterpretPtr sym;
2905         unsigned int skipped = 0;
2906 
2907         if ((unsigned) (req->firstSI + req->nSI) > compat->num_si) {
2908             compat->num_si = req->firstSI + req->nSI;
2909             compat->sym_interpret = reallocarray(compat->sym_interpret,
2910                                                  compat->num_si,
2911                                                  sizeof(XkbSymInterpretRec));
2912             if (!compat->sym_interpret) {
2913                 compat->num_si = 0;
2914                 return BadAlloc;
2915             }
2916         }
2917         else if (req->truncateSI) {
2918             compat->num_si = req->firstSI + req->nSI;
2919         }
2920         sym = &compat->sym_interpret[req->firstSI];
2921         for (i = 0; i < req->nSI; i++, wire++) {
2922             if (client->swapped) {
2923                 swapl(&wire->sym);
2924             }
2925             if (wire->sym == NoSymbol && wire->match == XkbSI_AnyOfOrNone &&
2926                 (wire->mods & 0xff) == 0xff &&
2927                 wire->act.type == XkbSA_XFree86Private) {
2928                 ErrorF("XKB: Skipping broken Any+AnyOfOrNone(All) -> Private "
2929                        "action from client\n");
2930                 skipped++;
2931                 continue;
2932             }
2933             sym->sym = wire->sym;
2934             sym->mods = wire->mods;
2935             sym->match = wire->match;
2936             sym->flags = wire->flags;
2937             sym->virtual_mod = wire->virtualMod;
2938             memcpy((char *) &sym->act, (char *) &wire->act,
2939                    SIZEOF(xkbActionWireDesc));
2940             sym++;
2941         }
2942         if (skipped) {
2943             if (req->firstSI + req->nSI < compat->num_si)
2944                 memmove(sym, sym + skipped,
2945                         (compat->num_si - req->firstSI - req->nSI) *
2946                         sizeof(*sym));
2947             compat->num_si -= skipped;
2948         }
2949         data = (char *) wire;
2950     }
2951     else if (req->truncateSI) {
2952         compat->num_si = req->firstSI;
2953     }
2954 
2955     if (req->groups != 0) {
2956         xkbModsWireDesc *wire = (xkbModsWireDesc *) data;
2957 
2958         for (i = 0, bit = 1; i < XkbNumKbdGroups; i++, bit <<= 1) {
2959             if (req->groups & bit) {
2960                 if (client->swapped) {
2961                     swaps(&wire->virtualMods);
2962                 }
2963                 compat->groups[i].mask = wire->realMods;
2964                 compat->groups[i].real_mods = wire->realMods;
2965                 compat->groups[i].vmods = wire->virtualMods;
2966                 if (wire->virtualMods != 0) {
2967                     unsigned tmp;
2968 
2969                     tmp = XkbMaskForVMask(xkb, wire->virtualMods);
2970                     compat->groups[i].mask |= tmp;
2971                 }
2972                 data += SIZEOF(xkbModsWireDesc);
2973                 wire = (xkbModsWireDesc *) data;
2974             }
2975         }
2976     }
2977     i = XkbPaddedSize((data - ((char *) req)));
2978     if ((i / 4) != req->length) {
2979         ErrorF("[xkb] Internal length error on read in _XkbSetCompatMap\n");
2980         return BadLength;
2981     }
2982 
2983     if (dev->xkb_interest) {
2984         xkbCompatMapNotify ev;
2985 
2986         ev.deviceID = dev->id;
2987         ev.changedGroups = req->groups;
2988         ev.firstSI = req->firstSI;
2989         ev.nSI = req->nSI;
2990         ev.nTotalSI = compat->num_si;
2991         XkbSendCompatMapNotify(dev, &ev);
2992     }
2993 
2994     if (req->recomputeActions) {
2995         XkbChangesRec change;
2996         unsigned check;
2997         XkbEventCauseRec cause;
2998 
2999         XkbSetCauseXkbReq(&cause, X_kbSetCompatMap, client);
3000         memset(&change, 0, sizeof(XkbChangesRec));
3001         XkbUpdateActions(dev, xkb->min_key_code, XkbNumKeys(xkb), &change,
3002                          &check, &cause);
3003         if (check)
3004             XkbCheckSecondaryEffects(xkbi, check, &change, &cause);
3005         XkbSendNotification(dev, &change, &cause);
3006     }
3007     return Success;
3008 }
3009 
3010 int
ProcXkbSetCompatMap(ClientPtr client)3011 ProcXkbSetCompatMap(ClientPtr client)
3012 {
3013     DeviceIntPtr dev;
3014     char *data;
3015     int rc;
3016 
3017     REQUEST(xkbSetCompatMapReq);
3018     REQUEST_AT_LEAST_SIZE(xkbSetCompatMapReq);
3019 
3020     if (!(client->xkbClientFlags & _XkbClientInitialized))
3021         return BadAccess;
3022 
3023     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
3024 
3025     data = (char *) &stuff[1];
3026 
3027     /* check first using a dry-run */
3028     rc = _XkbSetCompatMap(client, dev, stuff, data, TRUE);
3029     if (rc != Success)
3030         return rc;
3031     if (stuff->deviceSpec == XkbUseCoreKbd) {
3032         DeviceIntPtr other;
3033 
3034         for (other = inputInfo.devices; other; other = other->next) {
3035             if ((other != dev) && other->key && !IsMaster(other) &&
3036                 GetMaster(other, MASTER_KEYBOARD) == dev) {
3037                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3038                               DixManageAccess);
3039                 if (rc == Success) {
3040                     /* dry-run */
3041                     rc = _XkbSetCompatMap(client, other, stuff, data, TRUE);
3042                     if (rc != Success)
3043                         return rc;
3044                 }
3045             }
3046         }
3047     }
3048 
3049     /* Yay, the dry-runs succeed. Let's apply */
3050     rc = _XkbSetCompatMap(client, dev, stuff, data, FALSE);
3051     if (rc != Success)
3052         return rc;
3053     if (stuff->deviceSpec == XkbUseCoreKbd) {
3054         DeviceIntPtr other;
3055 
3056         for (other = inputInfo.devices; other; other = other->next) {
3057             if ((other != dev) && other->key && !IsMaster(other) &&
3058                 GetMaster(other, MASTER_KEYBOARD) == dev) {
3059                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3060                               DixManageAccess);
3061                 if (rc == Success) {
3062                     rc = _XkbSetCompatMap(client, other, stuff, data, FALSE);
3063                     if (rc != Success)
3064                         return rc;
3065                 }
3066             }
3067         }
3068     }
3069 
3070     return Success;
3071 }
3072 
3073 /***====================================================================***/
3074 
3075 int
ProcXkbGetIndicatorState(ClientPtr client)3076 ProcXkbGetIndicatorState(ClientPtr client)
3077 {
3078     xkbGetIndicatorStateReply rep;
3079     XkbSrvLedInfoPtr sli;
3080     DeviceIntPtr dev;
3081 
3082     REQUEST(xkbGetIndicatorStateReq);
3083     REQUEST_SIZE_MATCH(xkbGetIndicatorStateReq);
3084 
3085     if (!(client->xkbClientFlags & _XkbClientInitialized))
3086         return BadAccess;
3087 
3088     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3089 
3090     sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3091                             XkbXI_IndicatorStateMask);
3092     if (!sli)
3093         return BadAlloc;
3094 
3095     rep = (xkbGetIndicatorStateReply) {
3096         .type = X_Reply,
3097         .deviceID = dev->id,
3098         .sequenceNumber = client->sequence,
3099         .length = 0,
3100         .state = sli->effectiveState
3101     };
3102 
3103     if (client->swapped) {
3104         swaps(&rep.sequenceNumber);
3105         swapl(&rep.state);
3106     }
3107     WriteToClient(client, SIZEOF(xkbGetIndicatorStateReply), &rep);
3108     return Success;
3109 }
3110 
3111 /***====================================================================***/
3112 
3113 static Status
XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,xkbGetIndicatorMapReply * rep)3114 XkbComputeGetIndicatorMapReplySize(XkbIndicatorPtr indicators,
3115                                    xkbGetIndicatorMapReply * rep)
3116 {
3117     register int i, bit;
3118     int nIndicators;
3119 
3120     rep->realIndicators = indicators->phys_indicators;
3121     for (i = nIndicators = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3122         if (rep->which & bit)
3123             nIndicators++;
3124     }
3125     rep->length = (nIndicators * SIZEOF(xkbIndicatorMapWireDesc)) / 4;
3126     rep->nIndicators = nIndicators;
3127     return Success;
3128 }
3129 
3130 static int
XkbSendIndicatorMap(ClientPtr client,XkbIndicatorPtr indicators,xkbGetIndicatorMapReply * rep)3131 XkbSendIndicatorMap(ClientPtr client,
3132                     XkbIndicatorPtr indicators, xkbGetIndicatorMapReply * rep)
3133 {
3134     int length;
3135     CARD8 *map;
3136     register int i;
3137     register unsigned bit;
3138 
3139     if (rep->length > 0) {
3140         CARD8 *to;
3141 
3142         to = map = xallocarray(rep->length, 4);
3143         if (map) {
3144             xkbIndicatorMapWireDesc *wire = (xkbIndicatorMapWireDesc *) to;
3145 
3146             length = rep->length * 4;
3147 
3148             for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3149                 if (rep->which & bit) {
3150                     wire->flags = indicators->maps[i].flags;
3151                     wire->whichGroups = indicators->maps[i].which_groups;
3152                     wire->groups = indicators->maps[i].groups;
3153                     wire->whichMods = indicators->maps[i].which_mods;
3154                     wire->mods = indicators->maps[i].mods.mask;
3155                     wire->realMods = indicators->maps[i].mods.real_mods;
3156                     wire->virtualMods = indicators->maps[i].mods.vmods;
3157                     wire->ctrls = indicators->maps[i].ctrls;
3158                     if (client->swapped) {
3159                         swaps(&wire->virtualMods);
3160                         swapl(&wire->ctrls);
3161                     }
3162                     wire++;
3163                 }
3164             }
3165             to = (CARD8 *) wire;
3166             if ((to - map) != length) {
3167                 client->errorValue = _XkbErrCode2(0xff, length);
3168                 free(map);
3169                 return BadLength;
3170             }
3171         }
3172         else
3173             return BadAlloc;
3174     }
3175     else
3176         map = NULL;
3177     if (client->swapped) {
3178         swaps(&rep->sequenceNumber);
3179         swapl(&rep->length);
3180         swapl(&rep->which);
3181         swapl(&rep->realIndicators);
3182     }
3183     WriteToClient(client, SIZEOF(xkbGetIndicatorMapReply), rep);
3184     if (map) {
3185         WriteToClient(client, length, map);
3186         free((char *) map);
3187     }
3188     return Success;
3189 }
3190 
3191 int
ProcXkbGetIndicatorMap(ClientPtr client)3192 ProcXkbGetIndicatorMap(ClientPtr client)
3193 {
3194     xkbGetIndicatorMapReply rep;
3195     DeviceIntPtr dev;
3196     XkbDescPtr xkb;
3197     XkbIndicatorPtr leds;
3198 
3199     REQUEST(xkbGetIndicatorMapReq);
3200     REQUEST_SIZE_MATCH(xkbGetIndicatorMapReq);
3201 
3202     if (!(client->xkbClientFlags & _XkbClientInitialized))
3203         return BadAccess;
3204 
3205     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3206 
3207     xkb = dev->key->xkbInfo->desc;
3208     leds = xkb->indicators;
3209 
3210     rep = (xkbGetIndicatorMapReply) {
3211         .type = X_Reply,
3212         .deviceID = dev->id,
3213         .sequenceNumber = client->sequence,
3214         .length = 0,
3215         .which = stuff->which
3216     };
3217     XkbComputeGetIndicatorMapReplySize(leds, &rep);
3218     return XkbSendIndicatorMap(client, leds, &rep);
3219 }
3220 
3221 /**
3222  * Apply the given map to the given device. Which specifies which components
3223  * to apply.
3224  */
3225 static int
_XkbSetIndicatorMap(ClientPtr client,DeviceIntPtr dev,int which,xkbIndicatorMapWireDesc * desc)3226 _XkbSetIndicatorMap(ClientPtr client, DeviceIntPtr dev,
3227                     int which, xkbIndicatorMapWireDesc * desc)
3228 {
3229     XkbSrvInfoPtr xkbi;
3230     XkbSrvLedInfoPtr sli;
3231     XkbEventCauseRec cause;
3232     int i, bit;
3233 
3234     xkbi = dev->key->xkbInfo;
3235 
3236     sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
3237                             XkbXI_IndicatorMapsMask);
3238     if (!sli)
3239         return BadAlloc;
3240 
3241     for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3242         if (which & bit) {
3243             sli->maps[i].flags = desc->flags;
3244             sli->maps[i].which_groups = desc->whichGroups;
3245             sli->maps[i].groups = desc->groups;
3246             sli->maps[i].which_mods = desc->whichMods;
3247             sli->maps[i].mods.mask = desc->mods;
3248             sli->maps[i].mods.real_mods = desc->mods;
3249             sli->maps[i].mods.vmods = desc->virtualMods;
3250             sli->maps[i].ctrls = desc->ctrls;
3251             if (desc->virtualMods != 0) {
3252                 unsigned tmp;
3253 
3254                 tmp = XkbMaskForVMask(xkbi->desc, desc->virtualMods);
3255                 sli->maps[i].mods.mask = desc->mods | tmp;
3256             }
3257             desc++;
3258         }
3259     }
3260 
3261     XkbSetCauseXkbReq(&cause, X_kbSetIndicatorMap, client);
3262     XkbApplyLedMapChanges(dev, sli, which, NULL, NULL, &cause);
3263 
3264     return Success;
3265 }
3266 
3267 int
ProcXkbSetIndicatorMap(ClientPtr client)3268 ProcXkbSetIndicatorMap(ClientPtr client)
3269 {
3270     int i, bit;
3271     int nIndicators;
3272     DeviceIntPtr dev;
3273     xkbIndicatorMapWireDesc *from;
3274     int rc;
3275 
3276     REQUEST(xkbSetIndicatorMapReq);
3277     REQUEST_AT_LEAST_SIZE(xkbSetIndicatorMapReq);
3278 
3279     if (!(client->xkbClientFlags & _XkbClientInitialized))
3280         return BadAccess;
3281 
3282     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3283 
3284     if (stuff->which == 0)
3285         return Success;
3286 
3287     for (nIndicators = i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3288         if (stuff->which & bit)
3289             nIndicators++;
3290     }
3291     if (stuff->length != ((SIZEOF(xkbSetIndicatorMapReq) +
3292                            (nIndicators * SIZEOF(xkbIndicatorMapWireDesc))) /
3293                           4)) {
3294         return BadLength;
3295     }
3296 
3297     from = (xkbIndicatorMapWireDesc *) &stuff[1];
3298     for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
3299         if (stuff->which & bit) {
3300             if (client->swapped) {
3301                 swaps(&from->virtualMods);
3302                 swapl(&from->ctrls);
3303             }
3304             CHK_MASK_LEGAL(i, from->whichGroups, XkbIM_UseAnyGroup);
3305             CHK_MASK_LEGAL(i, from->whichMods, XkbIM_UseAnyMods);
3306             from++;
3307         }
3308     }
3309 
3310     from = (xkbIndicatorMapWireDesc *) &stuff[1];
3311     rc = _XkbSetIndicatorMap(client, dev, stuff->which, from);
3312     if (rc != Success)
3313         return rc;
3314 
3315     if (stuff->deviceSpec == XkbUseCoreKbd) {
3316         DeviceIntPtr other;
3317 
3318         for (other = inputInfo.devices; other; other = other->next) {
3319             if ((other != dev) && other->key && !IsMaster(other) &&
3320                 GetMaster(other, MASTER_KEYBOARD) == dev) {
3321                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
3322                               DixSetAttrAccess);
3323                 if (rc == Success)
3324                     _XkbSetIndicatorMap(client, other, stuff->which, from);
3325             }
3326         }
3327     }
3328 
3329     return Success;
3330 }
3331 
3332 /***====================================================================***/
3333 
3334 int
ProcXkbGetNamedIndicator(ClientPtr client)3335 ProcXkbGetNamedIndicator(ClientPtr client)
3336 {
3337     DeviceIntPtr dev;
3338     xkbGetNamedIndicatorReply rep;
3339     register int i = 0;
3340     XkbSrvLedInfoPtr sli;
3341     XkbIndicatorMapPtr map = NULL;
3342 
3343     REQUEST(xkbGetNamedIndicatorReq);
3344     REQUEST_SIZE_MATCH(xkbGetNamedIndicatorReq);
3345 
3346     if (!(client->xkbClientFlags & _XkbClientInitialized))
3347         return BadAccess;
3348 
3349     CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixReadAccess);
3350     CHK_ATOM_ONLY(stuff->indicator);
3351 
3352     sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID, 0);
3353     if (!sli)
3354         return BadAlloc;
3355 
3356     i = 0;
3357     map = NULL;
3358     if ((sli->names) && (sli->maps)) {
3359         for (i = 0; i < XkbNumIndicators; i++) {
3360             if (stuff->indicator == sli->names[i]) {
3361                 map = &sli->maps[i];
3362                 break;
3363             }
3364         }
3365     }
3366 
3367     rep = (xkbGetNamedIndicatorReply) {
3368         .type = X_Reply,
3369         .sequenceNumber = client->sequence,
3370         .length = 0,
3371         .deviceID = dev->id,
3372         .indicator = stuff->indicator
3373     };
3374     if (map != NULL) {
3375         rep.found = TRUE;
3376         rep.on = ((sli->effectiveState & (1 << i)) != 0);
3377         rep.realIndicator = ((sli->physIndicators & (1 << i)) != 0);
3378         rep.ndx = i;
3379         rep.flags = map->flags;
3380         rep.whichGroups = map->which_groups;
3381         rep.groups = map->groups;
3382         rep.whichMods = map->which_mods;
3383         rep.mods = map->mods.mask;
3384         rep.realMods = map->mods.real_mods;
3385         rep.virtualMods = map->mods.vmods;
3386         rep.ctrls = map->ctrls;
3387         rep.supported = TRUE;
3388     }
3389     else {
3390         rep.found = FALSE;
3391         rep.on = FALSE;
3392         rep.realIndicator = FALSE;
3393         rep.ndx = XkbNoIndicator;
3394         rep.flags = 0;
3395         rep.whichGroups = 0;
3396         rep.groups = 0;
3397         rep.whichMods = 0;
3398         rep.mods = 0;
3399         rep.realMods = 0;
3400         rep.virtualMods = 0;
3401         rep.ctrls = 0;
3402         rep.supported = TRUE;
3403     }
3404     if (client->swapped) {
3405         swapl(&rep.length);
3406         swaps(&rep.sequenceNumber);
3407         swapl(&rep.indicator);
3408         swaps(&rep.virtualMods);
3409         swapl(&rep.ctrls);
3410     }
3411 
3412     WriteToClient(client, SIZEOF(xkbGetNamedIndicatorReply), &rep);
3413     return Success;
3414 }
3415 
3416 /**
3417  * Find the IM on the device.
3418  * Returns the map, or NULL if the map doesn't exist.
3419  * If the return value is NULL, led_return is undefined. Otherwise, led_return
3420  * is set to the led index of the map.
3421  */
3422 static XkbIndicatorMapPtr
_XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli,Atom indicator,int * led_return)3423 _XkbFindNamedIndicatorMap(XkbSrvLedInfoPtr sli, Atom indicator, int *led_return)
3424 {
3425     XkbIndicatorMapPtr map;
3426 
3427     /* search for the right indicator */
3428     map = NULL;
3429     if (sli->names && sli->maps) {
3430         int led;
3431 
3432         for (led = 0; (led < XkbNumIndicators) && (map == NULL); led++) {
3433             if (sli->names[led] == indicator) {
3434                 map = &sli->maps[led];
3435                 *led_return = led;
3436                 break;
3437             }
3438         }
3439     }
3440 
3441     return map;
3442 }
3443 
3444 /**
3445  * Creates an indicator map on the device. If dryRun is TRUE, it only checks
3446  * if creation is possible, but doesn't actually create it.
3447  */
3448 static int
_XkbCreateIndicatorMap(DeviceIntPtr dev,Atom indicator,int ledClass,int ledID,XkbIndicatorMapPtr * map_return,int * led_return,Bool dryRun)3449 _XkbCreateIndicatorMap(DeviceIntPtr dev, Atom indicator,
3450                        int ledClass, int ledID,
3451                        XkbIndicatorMapPtr * map_return, int *led_return,
3452                        Bool dryRun)
3453 {
3454     XkbSrvLedInfoPtr sli;
3455     XkbIndicatorMapPtr map;
3456     int led;
3457 
3458     sli = XkbFindSrvLedInfo(dev, ledClass, ledID, XkbXI_IndicatorsMask);
3459     if (!sli)
3460         return BadAlloc;
3461 
3462     map = _XkbFindNamedIndicatorMap(sli, indicator, &led);
3463 
3464     if (!map) {
3465         /* find first unused indicator maps and assign the name to it */
3466         for (led = 0, map = NULL; (led < XkbNumIndicators) && (map == NULL);
3467              led++) {
3468             if ((sli->names) && (sli->maps) && (sli->names[led] == None) &&
3469                 (!XkbIM_InUse(&sli->maps[led]))) {
3470                 map = &sli->maps[led];
3471                 if (!dryRun)
3472                     sli->names[led] = indicator;
3473                 break;
3474             }
3475         }
3476     }
3477 
3478     if (!map)
3479         return BadAlloc;
3480 
3481     *led_return = led;
3482     *map_return = map;
3483     return Success;
3484 }
3485 
3486 static int
_XkbSetNamedIndicator(ClientPtr client,DeviceIntPtr dev,xkbSetNamedIndicatorReq * stuff)3487 _XkbSetNamedIndicator(ClientPtr client, DeviceIntPtr dev,
3488                       xkbSetNamedIndicatorReq * stuff)
3489 {
3490     unsigned int extDevReason;
3491     unsigned int statec, namec, mapc;
3492     XkbSrvLedInfoPtr sli;
3493     int led = 0;
3494     XkbIndicatorMapPtr map;
3495     DeviceIntPtr kbd;
3496     XkbEventCauseRec cause;
3497     xkbExtensionDeviceNotify ed;
3498     XkbChangesRec changes;
3499     int rc;
3500 
3501     rc = _XkbCreateIndicatorMap(dev, stuff->indicator, stuff->ledClass,
3502                                 stuff->ledID, &map, &led, FALSE);
3503     if (rc != Success || !map)  /* oh-oh */
3504         return rc;
3505 
3506     sli = XkbFindSrvLedInfo(dev, stuff->ledClass, stuff->ledID,
3507                             XkbXI_IndicatorsMask);
3508     if (!sli)
3509         return BadAlloc;
3510 
3511     namec = mapc = statec = 0;
3512     extDevReason = 0;
3513 
3514     namec |= (1 << led);
3515     sli->namesPresent |= ((stuff->indicator != None) ? (1 << led) : 0);
3516     extDevReason |= XkbXI_IndicatorNamesMask;
3517 
3518     if (stuff->setMap) {
3519         map->flags = stuff->flags;
3520         map->which_groups = stuff->whichGroups;
3521         map->groups = stuff->groups;
3522         map->which_mods = stuff->whichMods;
3523         map->mods.mask = stuff->realMods;
3524         map->mods.real_mods = stuff->realMods;
3525         map->mods.vmods = stuff->virtualMods;
3526         map->ctrls = stuff->ctrls;
3527         mapc |= (1 << led);
3528     }
3529 
3530     if ((stuff->setState) && ((map->flags & XkbIM_NoExplicit) == 0)) {
3531         if (stuff->on)
3532             sli->explicitState |= (1 << led);
3533         else
3534             sli->explicitState &= ~(1 << led);
3535         statec |= ((sli->effectiveState ^ sli->explicitState) & (1 << led));
3536     }
3537 
3538     memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
3539     memset((char *) &changes, 0, sizeof(XkbChangesRec));
3540     XkbSetCauseXkbReq(&cause, X_kbSetNamedIndicator, client);
3541     if (namec)
3542         XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
3543     if (mapc)
3544         XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
3545     if (statec)
3546         XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
3547 
3548     kbd = dev;
3549     if ((sli->flags & XkbSLI_HasOwnState) == 0)
3550         kbd = inputInfo.keyboard;
3551     XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
3552 
3553     return Success;
3554 }
3555 
3556 int
ProcXkbSetNamedIndicator(ClientPtr client)3557 ProcXkbSetNamedIndicator(ClientPtr client)
3558 {
3559     int rc;
3560     DeviceIntPtr dev;
3561     int led = 0;
3562     XkbIndicatorMapPtr map;
3563 
3564     REQUEST(xkbSetNamedIndicatorReq);
3565     REQUEST_SIZE_MATCH(xkbSetNamedIndicatorReq);
3566 
3567     if (!(client->xkbClientFlags & _XkbClientInitialized))
3568         return BadAccess;
3569 
3570     CHK_LED_DEVICE(dev, stuff->deviceSpec, client, DixSetAttrAccess);
3571     CHK_ATOM_ONLY(stuff->indicator);
3572     CHK_MASK_LEGAL(0x10, stuff->whichGroups, XkbIM_UseAnyGroup);
3573     CHK_MASK_LEGAL(0x11, stuff->whichMods, XkbIM_UseAnyMods);
3574 
3575     /* Dry-run for checks */
3576     rc = _XkbCreateIndicatorMap(dev, stuff->indicator,
3577                                 stuff->ledClass, stuff->ledID,
3578                                 &map, &led, TRUE);
3579     if (rc != Success || !map)  /* couldn't be created or didn't exist */
3580         return rc;
3581 
3582     if (stuff->deviceSpec == XkbUseCoreKbd ||
3583         stuff->deviceSpec == XkbUseCorePtr) {
3584         DeviceIntPtr other;
3585 
3586         for (other = inputInfo.devices; other; other = other->next) {
3587             if ((other != dev) && !IsMaster(other) &&
3588                 GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3589                                                              other->leds) &&
3590                 (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3591                  == Success)) {
3592                 rc = _XkbCreateIndicatorMap(other, stuff->indicator,
3593                                             stuff->ledClass, stuff->ledID, &map,
3594                                             &led, TRUE);
3595                 if (rc != Success || !map)
3596                     return rc;
3597             }
3598         }
3599     }
3600 
3601     /* All checks passed, let's do it */
3602     rc = _XkbSetNamedIndicator(client, dev, stuff);
3603     if (rc != Success)
3604         return rc;
3605 
3606     if (stuff->deviceSpec == XkbUseCoreKbd ||
3607         stuff->deviceSpec == XkbUseCorePtr) {
3608         DeviceIntPtr other;
3609 
3610         for (other = inputInfo.devices; other; other = other->next) {
3611             if ((other != dev) && !IsMaster(other) &&
3612                 GetMaster(other, MASTER_KEYBOARD) == dev && (other->kbdfeed ||
3613                                                              other->leds) &&
3614                 (XaceHook(XACE_DEVICE_ACCESS, client, other, DixSetAttrAccess)
3615                  == Success)) {
3616                 _XkbSetNamedIndicator(client, other, stuff);
3617             }
3618         }
3619     }
3620 
3621     return Success;
3622 }
3623 
3624 /***====================================================================***/
3625 
3626 static CARD32
_XkbCountAtoms(Atom * atoms,int maxAtoms,int * count)3627 _XkbCountAtoms(Atom *atoms, int maxAtoms, int *count)
3628 {
3629     register unsigned int i, bit, nAtoms;
3630     register CARD32 atomsPresent;
3631 
3632     for (i = nAtoms = atomsPresent = 0, bit = 1; i < maxAtoms; i++, bit <<= 1) {
3633         if (atoms[i] != None) {
3634             atomsPresent |= bit;
3635             nAtoms++;
3636         }
3637     }
3638     if (count)
3639         *count = nAtoms;
3640     return atomsPresent;
3641 }
3642 
3643 static char *
_XkbWriteAtoms(char * wire,Atom * atoms,int maxAtoms,int swap)3644 _XkbWriteAtoms(char *wire, Atom *atoms, int maxAtoms, int swap)
3645 {
3646     register unsigned int i;
3647     Atom *atm;
3648 
3649     atm = (Atom *) wire;
3650     for (i = 0; i < maxAtoms; i++) {
3651         if (atoms[i] != None) {
3652             *atm = atoms[i];
3653             if (swap) {
3654                 swapl(atm);
3655             }
3656             atm++;
3657         }
3658     }
3659     return (char *) atm;
3660 }
3661 
3662 static Status
XkbComputeGetNamesReplySize(XkbDescPtr xkb,xkbGetNamesReply * rep)3663 XkbComputeGetNamesReplySize(XkbDescPtr xkb, xkbGetNamesReply * rep)
3664 {
3665     register unsigned which, length;
3666     register int i;
3667 
3668     rep->minKeyCode = xkb->min_key_code;
3669     rep->maxKeyCode = xkb->max_key_code;
3670     which = rep->which;
3671     length = 0;
3672     if (xkb->names != NULL) {
3673         if (which & XkbKeycodesNameMask)
3674             length++;
3675         if (which & XkbGeometryNameMask)
3676             length++;
3677         if (which & XkbSymbolsNameMask)
3678             length++;
3679         if (which & XkbPhysSymbolsNameMask)
3680             length++;
3681         if (which & XkbTypesNameMask)
3682             length++;
3683         if (which & XkbCompatNameMask)
3684             length++;
3685     }
3686     else
3687         which &= ~XkbComponentNamesMask;
3688 
3689     if (xkb->map != NULL) {
3690         if (which & XkbKeyTypeNamesMask)
3691             length += xkb->map->num_types;
3692         rep->nTypes = xkb->map->num_types;
3693         if (which & XkbKTLevelNamesMask) {
3694             XkbKeyTypePtr pType = xkb->map->types;
3695             int nKTLevels = 0;
3696 
3697             length += XkbPaddedSize(xkb->map->num_types) / 4;
3698             for (i = 0; i < xkb->map->num_types; i++, pType++) {
3699                 if (pType->level_names != NULL)
3700                     nKTLevels += pType->num_levels;
3701             }
3702             rep->nKTLevels = nKTLevels;
3703             length += nKTLevels;
3704         }
3705     }
3706     else {
3707         rep->nTypes = 0;
3708         rep->nKTLevels = 0;
3709         which &= ~(XkbKeyTypeNamesMask | XkbKTLevelNamesMask);
3710     }
3711 
3712     rep->minKeyCode = xkb->min_key_code;
3713     rep->maxKeyCode = xkb->max_key_code;
3714     rep->indicators = 0;
3715     rep->virtualMods = 0;
3716     rep->groupNames = 0;
3717     if (xkb->names != NULL) {
3718         if (which & XkbIndicatorNamesMask) {
3719             int nLeds;
3720 
3721             rep->indicators =
3722                 _XkbCountAtoms(xkb->names->indicators, XkbNumIndicators,
3723                                &nLeds);
3724             length += nLeds;
3725             if (nLeds == 0)
3726                 which &= ~XkbIndicatorNamesMask;
3727         }
3728 
3729         if (which & XkbVirtualModNamesMask) {
3730             int nVMods;
3731 
3732             rep->virtualMods =
3733                 _XkbCountAtoms(xkb->names->vmods, XkbNumVirtualMods, &nVMods);
3734             length += nVMods;
3735             if (nVMods == 0)
3736                 which &= ~XkbVirtualModNamesMask;
3737         }
3738 
3739         if (which & XkbGroupNamesMask) {
3740             int nGroups;
3741 
3742             rep->groupNames =
3743                 _XkbCountAtoms(xkb->names->groups, XkbNumKbdGroups, &nGroups);
3744             length += nGroups;
3745             if (nGroups == 0)
3746                 which &= ~XkbGroupNamesMask;
3747         }
3748 
3749         if ((which & XkbKeyNamesMask) && (xkb->names->keys))
3750             length += rep->nKeys;
3751         else
3752             which &= ~XkbKeyNamesMask;
3753 
3754         if ((which & XkbKeyAliasesMask) &&
3755             (xkb->names->key_aliases) && (xkb->names->num_key_aliases > 0)) {
3756             rep->nKeyAliases = xkb->names->num_key_aliases;
3757             length += rep->nKeyAliases * 2;
3758         }
3759         else {
3760             which &= ~XkbKeyAliasesMask;
3761             rep->nKeyAliases = 0;
3762         }
3763 
3764         if ((which & XkbRGNamesMask) && (xkb->names->num_rg > 0))
3765             length += xkb->names->num_rg;
3766         else
3767             which &= ~XkbRGNamesMask;
3768     }
3769     else {
3770         which &= ~(XkbIndicatorNamesMask | XkbVirtualModNamesMask);
3771         which &= ~(XkbGroupNamesMask | XkbKeyNamesMask | XkbKeyAliasesMask);
3772         which &= ~XkbRGNamesMask;
3773     }
3774 
3775     rep->length = length;
3776     rep->which = which;
3777     return Success;
3778 }
3779 
3780 static int
XkbSendNames(ClientPtr client,XkbDescPtr xkb,xkbGetNamesReply * rep)3781 XkbSendNames(ClientPtr client, XkbDescPtr xkb, xkbGetNamesReply * rep)
3782 {
3783     register unsigned i, length, which;
3784     char *start;
3785     char *desc;
3786 
3787     length = rep->length * 4;
3788     which = rep->which;
3789     if (client->swapped) {
3790         swaps(&rep->sequenceNumber);
3791         swapl(&rep->length);
3792         swapl(&rep->which);
3793         swaps(&rep->virtualMods);
3794         swapl(&rep->indicators);
3795     }
3796 
3797     start = desc = calloc(1, length);
3798     if (!start)
3799         return BadAlloc;
3800     if (xkb->names) {
3801         if (which & XkbKeycodesNameMask) {
3802             *((CARD32 *) desc) = xkb->names->keycodes;
3803             if (client->swapped) {
3804                 swapl((int *) desc);
3805             }
3806             desc += 4;
3807         }
3808         if (which & XkbGeometryNameMask) {
3809             *((CARD32 *) desc) = xkb->names->geometry;
3810             if (client->swapped) {
3811                 swapl((int *) desc);
3812             }
3813             desc += 4;
3814         }
3815         if (which & XkbSymbolsNameMask) {
3816             *((CARD32 *) desc) = xkb->names->symbols;
3817             if (client->swapped) {
3818                 swapl((int *) desc);
3819             }
3820             desc += 4;
3821         }
3822         if (which & XkbPhysSymbolsNameMask) {
3823             register CARD32 *atm = (CARD32 *) desc;
3824 
3825             atm[0] = (CARD32) xkb->names->phys_symbols;
3826             if (client->swapped) {
3827                 swapl(&atm[0]);
3828             }
3829             desc += 4;
3830         }
3831         if (which & XkbTypesNameMask) {
3832             *((CARD32 *) desc) = (CARD32) xkb->names->types;
3833             if (client->swapped) {
3834                 swapl((int *) desc);
3835             }
3836             desc += 4;
3837         }
3838         if (which & XkbCompatNameMask) {
3839             *((CARD32 *) desc) = (CARD32) xkb->names->compat;
3840             if (client->swapped) {
3841                 swapl((int *) desc);
3842             }
3843             desc += 4;
3844         }
3845         if (which & XkbKeyTypeNamesMask) {
3846             register CARD32 *atm = (CARD32 *) desc;
3847             register XkbKeyTypePtr type = xkb->map->types;
3848 
3849             for (i = 0; i < xkb->map->num_types; i++, atm++, type++) {
3850                 *atm = (CARD32) type->name;
3851                 if (client->swapped) {
3852                     swapl(atm);
3853                 }
3854             }
3855             desc = (char *) atm;
3856         }
3857         if (which & XkbKTLevelNamesMask && xkb->map) {
3858             XkbKeyTypePtr type = xkb->map->types;
3859             register CARD32 *atm;
3860 
3861             for (i = 0; i < rep->nTypes; i++, type++) {
3862                 *desc++ = type->num_levels;
3863             }
3864             desc += XkbPaddedSize(rep->nTypes) - rep->nTypes;
3865 
3866             atm = (CARD32 *) desc;
3867             type = xkb->map->types;
3868             for (i = 0; i < xkb->map->num_types; i++, type++) {
3869                 register unsigned l;
3870 
3871                 if (type->level_names) {
3872                     for (l = 0; l < type->num_levels; l++, atm++) {
3873                         *atm = type->level_names[l];
3874                         if (client->swapped) {
3875                             swapl(atm);
3876                         }
3877                     }
3878                     desc += type->num_levels * 4;
3879                 }
3880             }
3881         }
3882         if (which & XkbIndicatorNamesMask) {
3883             desc =
3884                 _XkbWriteAtoms(desc, xkb->names->indicators, XkbNumIndicators,
3885                                client->swapped);
3886         }
3887         if (which & XkbVirtualModNamesMask) {
3888             desc = _XkbWriteAtoms(desc, xkb->names->vmods, XkbNumVirtualMods,
3889                                   client->swapped);
3890         }
3891         if (which & XkbGroupNamesMask) {
3892             desc = _XkbWriteAtoms(desc, xkb->names->groups, XkbNumKbdGroups,
3893                                   client->swapped);
3894         }
3895         if (which & XkbKeyNamesMask) {
3896             for (i = 0; i < rep->nKeys; i++, desc += sizeof(XkbKeyNameRec)) {
3897                 *((XkbKeyNamePtr) desc) = xkb->names->keys[i + rep->firstKey];
3898             }
3899         }
3900         if (which & XkbKeyAliasesMask) {
3901             XkbKeyAliasPtr pAl;
3902 
3903             pAl = xkb->names->key_aliases;
3904             for (i = 0; i < rep->nKeyAliases;
3905                  i++, pAl++, desc += 2 * XkbKeyNameLength) {
3906                 *((XkbKeyAliasPtr) desc) = *pAl;
3907             }
3908         }
3909         if ((which & XkbRGNamesMask) && (rep->nRadioGroups > 0)) {
3910             register CARD32 *atm = (CARD32 *) desc;
3911 
3912             for (i = 0; i < rep->nRadioGroups; i++, atm++) {
3913                 *atm = (CARD32) xkb->names->radio_groups[i];
3914                 if (client->swapped) {
3915                     swapl(atm);
3916                 }
3917             }
3918             desc += rep->nRadioGroups * 4;
3919         }
3920     }
3921 
3922     if ((desc - start) != (length)) {
3923         ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n",
3924                length, (unsigned long) (desc - start));
3925     }
3926     WriteToClient(client, SIZEOF(xkbGetNamesReply), rep);
3927     WriteToClient(client, length, start);
3928     free((char *) start);
3929     return Success;
3930 }
3931 
3932 int
ProcXkbGetNames(ClientPtr client)3933 ProcXkbGetNames(ClientPtr client)
3934 {
3935     DeviceIntPtr dev;
3936     XkbDescPtr xkb;
3937     xkbGetNamesReply rep;
3938 
3939     REQUEST(xkbGetNamesReq);
3940     REQUEST_SIZE_MATCH(xkbGetNamesReq);
3941 
3942     if (!(client->xkbClientFlags & _XkbClientInitialized))
3943         return BadAccess;
3944 
3945     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
3946     CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
3947 
3948     xkb = dev->key->xkbInfo->desc;
3949     rep = (xkbGetNamesReply) {
3950         .type = X_Reply,
3951         .deviceID = dev->id,
3952         .sequenceNumber = client->sequence,
3953         .length = 0,
3954         .which = stuff->which,
3955         .nTypes = xkb->map->num_types,
3956         .firstKey = xkb->min_key_code,
3957         .nKeys = XkbNumKeys(xkb),
3958         .nKeyAliases = xkb->names ? xkb->names->num_key_aliases : 0,
3959         .nRadioGroups = xkb->names ? xkb->names->num_rg : 0
3960     };
3961     XkbComputeGetNamesReplySize(xkb, &rep);
3962     return XkbSendNames(client, xkb, &rep);
3963 }
3964 
3965 /***====================================================================***/
3966 
3967 static CARD32 *
_XkbCheckAtoms(CARD32 * wire,int nAtoms,int swapped,Atom * pError)3968 _XkbCheckAtoms(CARD32 *wire, int nAtoms, int swapped, Atom *pError)
3969 {
3970     register int i;
3971 
3972     for (i = 0; i < nAtoms; i++, wire++) {
3973         if (swapped) {
3974             swapl(wire);
3975         }
3976         if ((((Atom) *wire) != None) && (!ValidAtom((Atom) *wire))) {
3977             *pError = ((Atom) *wire);
3978             return NULL;
3979         }
3980     }
3981     return wire;
3982 }
3983 
3984 static CARD32 *
_XkbCheckMaskedAtoms(CARD32 * wire,int nAtoms,CARD32 present,int swapped,Atom * pError)3985 _XkbCheckMaskedAtoms(CARD32 *wire, int nAtoms, CARD32 present, int swapped,
3986                      Atom *pError)
3987 {
3988     register unsigned i, bit;
3989 
3990     for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
3991         if ((present & bit) == 0)
3992             continue;
3993         if (swapped) {
3994             swapl(wire);
3995         }
3996         if ((((Atom) *wire) != None) && (!ValidAtom(((Atom) *wire)))) {
3997             *pError = (Atom) *wire;
3998             return NULL;
3999         }
4000         wire++;
4001     }
4002     return wire;
4003 }
4004 
4005 static Atom *
_XkbCopyMaskedAtoms(Atom * wire,Atom * dest,int nAtoms,CARD32 present)4006 _XkbCopyMaskedAtoms(Atom *wire, Atom *dest, int nAtoms, CARD32 present)
4007 {
4008     register int i, bit;
4009 
4010     for (i = 0, bit = 1; (i < nAtoms) && (present); i++, bit <<= 1) {
4011         if ((present & bit) == 0)
4012             continue;
4013         dest[i] = *wire++;
4014     }
4015     return wire;
4016 }
4017 
4018 static Bool
_XkbCheckTypeName(Atom name,int typeNdx)4019 _XkbCheckTypeName(Atom name, int typeNdx)
4020 {
4021     const char *str;
4022 
4023     str = NameForAtom(name);
4024     if ((strcmp(str, "ONE_LEVEL") == 0) || (strcmp(str, "TWO_LEVEL") == 0) ||
4025         (strcmp(str, "ALPHABETIC") == 0) || (strcmp(str, "KEYPAD") == 0))
4026         return FALSE;
4027     return TRUE;
4028 }
4029 
4030 /**
4031  * Check the device-dependent data in the request against the device. Returns
4032  * Success, or the appropriate error code.
4033  */
4034 static int
_XkbSetNamesCheck(ClientPtr client,DeviceIntPtr dev,xkbSetNamesReq * stuff,CARD32 * data)4035 _XkbSetNamesCheck(ClientPtr client, DeviceIntPtr dev,
4036                   xkbSetNamesReq * stuff, CARD32 *data)
4037 {
4038     XkbDescRec *xkb;
4039     CARD32 *tmp;
4040     Atom bad = None;
4041 
4042     tmp = data;
4043     xkb = dev->key->xkbInfo->desc;
4044 
4045     if (stuff->which & XkbKeyTypeNamesMask) {
4046         int i;
4047         CARD32 *old;
4048 
4049         if (stuff->nTypes < 1) {
4050             client->errorValue = _XkbErrCode2(0x02, stuff->nTypes);
4051             return BadValue;
4052         }
4053         if ((unsigned) (stuff->firstType + stuff->nTypes - 1) >=
4054             xkb->map->num_types) {
4055             client->errorValue =
4056                 _XkbErrCode4(0x03, stuff->firstType, stuff->nTypes,
4057                              xkb->map->num_types);
4058             return BadValue;
4059         }
4060         if (((unsigned) stuff->firstType) <= XkbLastRequiredType) {
4061             client->errorValue = _XkbErrCode2(0x04, stuff->firstType);
4062             return BadAccess;
4063         }
4064         if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nTypes))
4065             return BadLength;
4066         old = tmp;
4067         tmp = _XkbCheckAtoms(tmp, stuff->nTypes, client->swapped, &bad);
4068         if (!tmp) {
4069             client->errorValue = bad;
4070             return BadAtom;
4071         }
4072         for (i = 0; i < stuff->nTypes; i++, old++) {
4073             if (!_XkbCheckTypeName((Atom) *old, stuff->firstType + i))
4074                 client->errorValue = _XkbErrCode2(0x05, i);
4075         }
4076     }
4077     if (stuff->which & XkbKTLevelNamesMask) {
4078         unsigned i;
4079         XkbKeyTypePtr type;
4080         CARD8 *width;
4081 
4082         if (stuff->nKTLevels < 1) {
4083             client->errorValue = _XkbErrCode2(0x05, stuff->nKTLevels);
4084             return BadValue;
4085         }
4086         if ((unsigned) (stuff->firstKTLevel + stuff->nKTLevels - 1) >=
4087             xkb->map->num_types) {
4088             client->errorValue = _XkbErrCode4(0x06, stuff->firstKTLevel,
4089                                               stuff->nKTLevels,
4090                                               xkb->map->num_types);
4091             return BadValue;
4092         }
4093         width = (CARD8 *) tmp;
4094         tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4095         if (!_XkbCheckRequestBounds(client, stuff, width, tmp))
4096             return BadLength;
4097         type = &xkb->map->types[stuff->firstKTLevel];
4098         for (i = 0; i < stuff->nKTLevels; i++, type++) {
4099             if (width[i] == 0)
4100                 continue;
4101             else if (width[i] != type->num_levels) {
4102                 client->errorValue = _XkbErrCode4(0x07, i + stuff->firstKTLevel,
4103                                                   type->num_levels, width[i]);
4104                 return BadMatch;
4105             }
4106             if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + width[i]))
4107                 return BadLength;
4108             tmp = _XkbCheckAtoms(tmp, width[i], client->swapped, &bad);
4109             if (!tmp) {
4110                 client->errorValue = bad;
4111                 return BadAtom;
4112             }
4113         }
4114     }
4115     if (stuff->which & XkbIndicatorNamesMask) {
4116         if (stuff->indicators == 0) {
4117             client->errorValue = 0x08;
4118             return BadMatch;
4119         }
4120         if (!_XkbCheckRequestBounds(client, stuff, tmp,
4121                                     tmp + Ones(stuff->indicators)))
4122             return BadLength;
4123         tmp = _XkbCheckMaskedAtoms(tmp, XkbNumIndicators, stuff->indicators,
4124                                    client->swapped, &bad);
4125         if (!tmp) {
4126             client->errorValue = bad;
4127             return BadAtom;
4128         }
4129     }
4130     if (stuff->which & XkbVirtualModNamesMask) {
4131         if (stuff->virtualMods == 0) {
4132             client->errorValue = 0x09;
4133             return BadMatch;
4134         }
4135         if (!_XkbCheckRequestBounds(client, stuff, tmp,
4136                                     tmp + Ones(stuff->virtualMods)))
4137             return BadLength;
4138         tmp = _XkbCheckMaskedAtoms(tmp, XkbNumVirtualMods,
4139                                    (CARD32) stuff->virtualMods,
4140                                    client->swapped, &bad);
4141         if (!tmp) {
4142             client->errorValue = bad;
4143             return BadAtom;
4144         }
4145     }
4146     if (stuff->which & XkbGroupNamesMask) {
4147         if (stuff->groupNames == 0) {
4148             client->errorValue = 0x0a;
4149             return BadMatch;
4150         }
4151         if (!_XkbCheckRequestBounds(client, stuff, tmp,
4152                                     tmp + Ones(stuff->groupNames)))
4153             return BadLength;
4154         tmp = _XkbCheckMaskedAtoms(tmp, XkbNumKbdGroups,
4155                                    (CARD32) stuff->groupNames,
4156                                    client->swapped, &bad);
4157         if (!tmp) {
4158             client->errorValue = bad;
4159             return BadAtom;
4160         }
4161     }
4162     if (stuff->which & XkbKeyNamesMask) {
4163         if (stuff->firstKey < (unsigned) xkb->min_key_code) {
4164             client->errorValue = _XkbErrCode3(0x0b, xkb->min_key_code,
4165                                               stuff->firstKey);
4166             return BadValue;
4167         }
4168         if (((unsigned) (stuff->firstKey + stuff->nKeys - 1) >
4169              xkb->max_key_code) || (stuff->nKeys < 1)) {
4170             client->errorValue =
4171                 _XkbErrCode4(0x0c, xkb->max_key_code, stuff->firstKey,
4172                              stuff->nKeys);
4173             return BadValue;
4174         }
4175         if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + stuff->nKeys))
4176             return BadLength;
4177         tmp += stuff->nKeys;
4178     }
4179     if ((stuff->which & XkbKeyAliasesMask) && (stuff->nKeyAliases > 0)) {
4180         if (!_XkbCheckRequestBounds(client, stuff, tmp,
4181                                     tmp + (stuff->nKeyAliases * 2)))
4182             return BadLength;
4183         tmp += stuff->nKeyAliases * 2;
4184     }
4185     if (stuff->which & XkbRGNamesMask) {
4186         if (stuff->nRadioGroups < 1) {
4187             client->errorValue = _XkbErrCode2(0x0d, stuff->nRadioGroups);
4188             return BadValue;
4189         }
4190         if (!_XkbCheckRequestBounds(client, stuff, tmp,
4191                                     tmp + stuff->nRadioGroups))
4192             return BadLength;
4193         tmp = _XkbCheckAtoms(tmp, stuff->nRadioGroups, client->swapped, &bad);
4194         if (!tmp) {
4195             client->errorValue = bad;
4196             return BadAtom;
4197         }
4198     }
4199     if ((tmp - ((CARD32 *) stuff)) != stuff->length) {
4200         client->errorValue = stuff->length;
4201         return BadLength;
4202     }
4203 
4204     return Success;
4205 }
4206 
4207 static int
_XkbSetNames(ClientPtr client,DeviceIntPtr dev,xkbSetNamesReq * stuff)4208 _XkbSetNames(ClientPtr client, DeviceIntPtr dev, xkbSetNamesReq * stuff)
4209 {
4210     XkbDescRec *xkb;
4211     XkbNamesRec *names;
4212     CARD32 *tmp;
4213     xkbNamesNotify nn;
4214 
4215     tmp = (CARD32 *) &stuff[1];
4216     xkb = dev->key->xkbInfo->desc;
4217     names = xkb->names;
4218 
4219     if (XkbAllocNames(xkb, stuff->which, stuff->nRadioGroups,
4220                       stuff->nKeyAliases) != Success) {
4221         return BadAlloc;
4222     }
4223 
4224     memset(&nn, 0, sizeof(xkbNamesNotify));
4225     nn.changed = stuff->which;
4226     tmp = (CARD32 *) &stuff[1];
4227     if (stuff->which & XkbKeycodesNameMask)
4228         names->keycodes = *tmp++;
4229     if (stuff->which & XkbGeometryNameMask)
4230         names->geometry = *tmp++;
4231     if (stuff->which & XkbSymbolsNameMask)
4232         names->symbols = *tmp++;
4233     if (stuff->which & XkbPhysSymbolsNameMask)
4234         names->phys_symbols = *tmp++;
4235     if (stuff->which & XkbTypesNameMask)
4236         names->types = *tmp++;
4237     if (stuff->which & XkbCompatNameMask)
4238         names->compat = *tmp++;
4239     if ((stuff->which & XkbKeyTypeNamesMask) && (stuff->nTypes > 0)) {
4240         register unsigned i;
4241         register XkbKeyTypePtr type;
4242 
4243         type = &xkb->map->types[stuff->firstType];
4244         for (i = 0; i < stuff->nTypes; i++, type++) {
4245             type->name = *tmp++;
4246         }
4247         nn.firstType = stuff->firstType;
4248         nn.nTypes = stuff->nTypes;
4249     }
4250     if (stuff->which & XkbKTLevelNamesMask) {
4251         register XkbKeyTypePtr type;
4252         register unsigned i;
4253         CARD8 *width;
4254 
4255         width = (CARD8 *) tmp;
4256         tmp = (CARD32 *) (((char *) tmp) + XkbPaddedSize(stuff->nKTLevels));
4257         type = &xkb->map->types[stuff->firstKTLevel];
4258         for (i = 0; i < stuff->nKTLevels; i++, type++) {
4259             if (width[i] > 0) {
4260                 if (type->level_names) {
4261                     register unsigned n;
4262 
4263                     for (n = 0; n < width[i]; n++) {
4264                         type->level_names[n] = tmp[n];
4265                     }
4266                 }
4267                 tmp += width[i];
4268             }
4269         }
4270         nn.firstLevelName = 0;
4271         nn.nLevelNames = stuff->nTypes;
4272     }
4273     if (stuff->which & XkbIndicatorNamesMask) {
4274         tmp = _XkbCopyMaskedAtoms(tmp, names->indicators, XkbNumIndicators,
4275                                   stuff->indicators);
4276         nn.changedIndicators = stuff->indicators;
4277     }
4278     if (stuff->which & XkbVirtualModNamesMask) {
4279         tmp = _XkbCopyMaskedAtoms(tmp, names->vmods, XkbNumVirtualMods,
4280                                   stuff->virtualMods);
4281         nn.changedVirtualMods = stuff->virtualMods;
4282     }
4283     if (stuff->which & XkbGroupNamesMask) {
4284         tmp = _XkbCopyMaskedAtoms(tmp, names->groups, XkbNumKbdGroups,
4285                                   stuff->groupNames);
4286         nn.changedVirtualMods = stuff->groupNames;
4287     }
4288     if (stuff->which & XkbKeyNamesMask) {
4289         memcpy((char *) &names->keys[stuff->firstKey], (char *) tmp,
4290                stuff->nKeys * XkbKeyNameLength);
4291         tmp += stuff->nKeys;
4292         nn.firstKey = stuff->firstKey;
4293         nn.nKeys = stuff->nKeys;
4294     }
4295     if (stuff->which & XkbKeyAliasesMask) {
4296         if (stuff->nKeyAliases > 0) {
4297             register int na = stuff->nKeyAliases;
4298 
4299             if (XkbAllocNames(xkb, XkbKeyAliasesMask, 0, na) != Success)
4300                 return BadAlloc;
4301             memcpy((char *) names->key_aliases, (char *) tmp,
4302                    stuff->nKeyAliases * sizeof(XkbKeyAliasRec));
4303             tmp += stuff->nKeyAliases * 2;
4304         }
4305         else if (names->key_aliases != NULL) {
4306             free(names->key_aliases);
4307             names->key_aliases = NULL;
4308             names->num_key_aliases = 0;
4309         }
4310         nn.nAliases = names->num_key_aliases;
4311     }
4312     if (stuff->which & XkbRGNamesMask) {
4313         if (stuff->nRadioGroups > 0) {
4314             register unsigned i, nrg;
4315 
4316             nrg = stuff->nRadioGroups;
4317             if (XkbAllocNames(xkb, XkbRGNamesMask, nrg, 0) != Success)
4318                 return BadAlloc;
4319 
4320             for (i = 0; i < stuff->nRadioGroups; i++) {
4321                 names->radio_groups[i] = tmp[i];
4322             }
4323             tmp += stuff->nRadioGroups;
4324         }
4325         else if (names->radio_groups) {
4326             free(names->radio_groups);
4327             names->radio_groups = NULL;
4328             names->num_rg = 0;
4329         }
4330         nn.nRadioGroups = names->num_rg;
4331     }
4332     if (nn.changed) {
4333         Bool needExtEvent;
4334 
4335         needExtEvent = (nn.changed & XkbIndicatorNamesMask) != 0;
4336         XkbSendNamesNotify(dev, &nn);
4337         if (needExtEvent) {
4338             XkbSrvLedInfoPtr sli;
4339             xkbExtensionDeviceNotify edev;
4340             register int i;
4341             register unsigned bit;
4342 
4343             sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId,
4344                                     XkbXI_IndicatorsMask);
4345             sli->namesPresent = 0;
4346             for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
4347                 if (names->indicators[i] != None)
4348                     sli->namesPresent |= bit;
4349             }
4350             memset(&edev, 0, sizeof(xkbExtensionDeviceNotify));
4351             edev.reason = XkbXI_IndicatorNamesMask;
4352             edev.ledClass = KbdFeedbackClass;
4353             edev.ledID = dev->kbdfeed->ctrl.id;
4354             edev.ledsDefined = sli->namesPresent | sli->mapsPresent;
4355             edev.ledState = sli->effectiveState;
4356             edev.firstBtn = 0;
4357             edev.nBtns = 0;
4358             edev.supported = XkbXI_AllFeaturesMask;
4359             edev.unsupported = 0;
4360             XkbSendExtensionDeviceNotify(dev, client, &edev);
4361         }
4362     }
4363     return Success;
4364 }
4365 
4366 int
ProcXkbSetNames(ClientPtr client)4367 ProcXkbSetNames(ClientPtr client)
4368 {
4369     DeviceIntPtr dev;
4370     CARD32 *tmp;
4371     Atom bad;
4372     int rc;
4373 
4374     REQUEST(xkbSetNamesReq);
4375     REQUEST_AT_LEAST_SIZE(xkbSetNamesReq);
4376 
4377     if (!(client->xkbClientFlags & _XkbClientInitialized))
4378         return BadAccess;
4379 
4380     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
4381     CHK_MASK_LEGAL(0x01, stuff->which, XkbAllNamesMask);
4382 
4383     /* check device-independent stuff */
4384     tmp = (CARD32 *) &stuff[1];
4385 
4386     if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4387         return BadLength;
4388     if (stuff->which & XkbKeycodesNameMask) {
4389         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4390         if (!tmp) {
4391             client->errorValue = bad;
4392             return BadAtom;
4393         }
4394     }
4395     if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4396         return BadLength;
4397     if (stuff->which & XkbGeometryNameMask) {
4398         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4399         if (!tmp) {
4400             client->errorValue = bad;
4401             return BadAtom;
4402         }
4403     }
4404     if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4405         return BadLength;
4406     if (stuff->which & XkbSymbolsNameMask) {
4407         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4408         if (!tmp) {
4409             client->errorValue = bad;
4410             return BadAtom;
4411         }
4412     }
4413     if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4414         return BadLength;
4415     if (stuff->which & XkbPhysSymbolsNameMask) {
4416         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4417         if (!tmp) {
4418             client->errorValue = bad;
4419             return BadAtom;
4420         }
4421     }
4422     if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4423         return BadLength;
4424     if (stuff->which & XkbTypesNameMask) {
4425         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4426         if (!tmp) {
4427             client->errorValue = bad;
4428             return BadAtom;
4429         }
4430     }
4431     if (!_XkbCheckRequestBounds(client, stuff, tmp, tmp + 1))
4432         return BadLength;
4433     if (stuff->which & XkbCompatNameMask) {
4434         tmp = _XkbCheckAtoms(tmp, 1, client->swapped, &bad);
4435         if (!tmp) {
4436             client->errorValue = bad;
4437             return BadAtom;
4438         }
4439     }
4440 
4441     /* start of device-dependent tests */
4442     rc = _XkbSetNamesCheck(client, dev, stuff, tmp);
4443     if (rc != Success)
4444         return rc;
4445 
4446     if (stuff->deviceSpec == XkbUseCoreKbd) {
4447         DeviceIntPtr other;
4448 
4449         for (other = inputInfo.devices; other; other = other->next) {
4450             if ((other != dev) && other->key && !IsMaster(other) &&
4451                 GetMaster(other, MASTER_KEYBOARD) == dev) {
4452 
4453                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4454                               DixManageAccess);
4455                 if (rc == Success) {
4456                     rc = _XkbSetNamesCheck(client, other, stuff, tmp);
4457                     if (rc != Success)
4458                         return rc;
4459                 }
4460             }
4461         }
4462     }
4463 
4464     /* everything is okay -- update names */
4465 
4466     rc = _XkbSetNames(client, dev, stuff);
4467     if (rc != Success)
4468         return rc;
4469 
4470     if (stuff->deviceSpec == XkbUseCoreKbd) {
4471         DeviceIntPtr other;
4472 
4473         for (other = inputInfo.devices; other; other = other->next) {
4474             if ((other != dev) && other->key && !IsMaster(other) &&
4475                 GetMaster(other, MASTER_KEYBOARD) == dev) {
4476 
4477                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
4478                               DixManageAccess);
4479                 if (rc == Success)
4480                     _XkbSetNames(client, other, stuff);
4481             }
4482         }
4483     }
4484 
4485     /* everything is okay -- update names */
4486 
4487     return Success;
4488 }
4489 
4490 /***====================================================================***/
4491 
4492 #include "xkbgeom.h"
4493 
4494 #define	XkbSizeCountedString(s)  ((s)?((((2+strlen(s))+3)/4)*4):4)
4495 
4496 /**
4497  * Write the zero-terminated string str into wire as a pascal string with a
4498  * 16-bit length field prefixed before the actual string.
4499  *
4500  * @param wire The destination array, usually the wire struct
4501  * @param str The source string as zero-terminated C string
4502  * @param swap If TRUE, the length field is swapped.
4503  *
4504  * @return The input string in the format <string length><string> with a
4505  * (swapped) 16 bit string length, non-zero terminated.
4506  */
4507 static char *
XkbWriteCountedString(char * wire,const char * str,Bool swap)4508 XkbWriteCountedString(char *wire, const char *str, Bool swap)
4509 {
4510     CARD16 len, *pLen, paddedLen;
4511 
4512     if (!str)
4513         return wire;
4514 
4515     len = strlen(str);
4516     pLen = (CARD16 *) wire;
4517     *pLen = len;
4518     if (swap) {
4519         swaps(pLen);
4520     }
4521     paddedLen = pad_to_int32(sizeof(len) + len) - sizeof(len);
4522     strncpy(&wire[sizeof(len)], str, paddedLen);
4523     wire += sizeof(len) + paddedLen;
4524     return wire;
4525 }
4526 
4527 static int
XkbSizeGeomProperties(XkbGeometryPtr geom)4528 XkbSizeGeomProperties(XkbGeometryPtr geom)
4529 {
4530     register int i, size;
4531     XkbPropertyPtr prop;
4532 
4533     for (size = i = 0, prop = geom->properties; i < geom->num_properties;
4534          i++, prop++) {
4535         size += XkbSizeCountedString(prop->name);
4536         size += XkbSizeCountedString(prop->value);
4537     }
4538     return size;
4539 }
4540 
4541 static char *
XkbWriteGeomProperties(char * wire,XkbGeometryPtr geom,Bool swap)4542 XkbWriteGeomProperties(char *wire, XkbGeometryPtr geom, Bool swap)
4543 {
4544     register int i;
4545     register XkbPropertyPtr prop;
4546 
4547     for (i = 0, prop = geom->properties; i < geom->num_properties; i++, prop++) {
4548         wire = XkbWriteCountedString(wire, prop->name, swap);
4549         wire = XkbWriteCountedString(wire, prop->value, swap);
4550     }
4551     return wire;
4552 }
4553 
4554 static int
XkbSizeGeomKeyAliases(XkbGeometryPtr geom)4555 XkbSizeGeomKeyAliases(XkbGeometryPtr geom)
4556 {
4557     return geom->num_key_aliases * (2 * XkbKeyNameLength);
4558 }
4559 
4560 static char *
XkbWriteGeomKeyAliases(char * wire,XkbGeometryPtr geom,Bool swap)4561 XkbWriteGeomKeyAliases(char *wire, XkbGeometryPtr geom, Bool swap)
4562 {
4563     register int sz;
4564 
4565     sz = geom->num_key_aliases * (XkbKeyNameLength * 2);
4566     if (sz > 0) {
4567         memcpy(wire, (char *) geom->key_aliases, sz);
4568         wire += sz;
4569     }
4570     return wire;
4571 }
4572 
4573 static int
XkbSizeGeomColors(XkbGeometryPtr geom)4574 XkbSizeGeomColors(XkbGeometryPtr geom)
4575 {
4576     register int i, size;
4577     register XkbColorPtr color;
4578 
4579     for (i = size = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4580         size += XkbSizeCountedString(color->spec);
4581     }
4582     return size;
4583 }
4584 
4585 static char *
XkbWriteGeomColors(char * wire,XkbGeometryPtr geom,Bool swap)4586 XkbWriteGeomColors(char *wire, XkbGeometryPtr geom, Bool swap)
4587 {
4588     register int i;
4589     register XkbColorPtr color;
4590 
4591     for (i = 0, color = geom->colors; i < geom->num_colors; i++, color++) {
4592         wire = XkbWriteCountedString(wire, color->spec, swap);
4593     }
4594     return wire;
4595 }
4596 
4597 static int
XkbSizeGeomShapes(XkbGeometryPtr geom)4598 XkbSizeGeomShapes(XkbGeometryPtr geom)
4599 {
4600     register int i, size;
4601     register XkbShapePtr shape;
4602 
4603     for (i = size = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4604         register int n;
4605         register XkbOutlinePtr ol;
4606 
4607         size += SIZEOF(xkbShapeWireDesc);
4608         for (n = 0, ol = shape->outlines; n < shape->num_outlines; n++, ol++) {
4609             size += SIZEOF(xkbOutlineWireDesc);
4610             size += ol->num_points * SIZEOF(xkbPointWireDesc);
4611         }
4612     }
4613     return size;
4614 }
4615 
4616 static char *
XkbWriteGeomShapes(char * wire,XkbGeometryPtr geom,Bool swap)4617 XkbWriteGeomShapes(char *wire, XkbGeometryPtr geom, Bool swap)
4618 {
4619     int i;
4620     XkbShapePtr shape;
4621     xkbShapeWireDesc *shapeWire;
4622 
4623     for (i = 0, shape = geom->shapes; i < geom->num_shapes; i++, shape++) {
4624         register int o;
4625         XkbOutlinePtr ol;
4626         xkbOutlineWireDesc *olWire;
4627 
4628         shapeWire = (xkbShapeWireDesc *) wire;
4629         shapeWire->name = shape->name;
4630         shapeWire->nOutlines = shape->num_outlines;
4631         if (shape->primary != NULL)
4632             shapeWire->primaryNdx = XkbOutlineIndex(shape, shape->primary);
4633         else
4634             shapeWire->primaryNdx = XkbNoShape;
4635         if (shape->approx != NULL)
4636             shapeWire->approxNdx = XkbOutlineIndex(shape, shape->approx);
4637         else
4638             shapeWire->approxNdx = XkbNoShape;
4639         shapeWire->pad = 0;
4640         if (swap) {
4641             swapl(&shapeWire->name);
4642         }
4643         wire = (char *) &shapeWire[1];
4644         for (o = 0, ol = shape->outlines; o < shape->num_outlines; o++, ol++) {
4645             register int p;
4646             XkbPointPtr pt;
4647             xkbPointWireDesc *ptWire;
4648 
4649             olWire = (xkbOutlineWireDesc *) wire;
4650             olWire->nPoints = ol->num_points;
4651             olWire->cornerRadius = ol->corner_radius;
4652             olWire->pad = 0;
4653             wire = (char *) &olWire[1];
4654             ptWire = (xkbPointWireDesc *) wire;
4655             for (p = 0, pt = ol->points; p < ol->num_points; p++, pt++) {
4656                 ptWire[p].x = pt->x;
4657                 ptWire[p].y = pt->y;
4658                 if (swap) {
4659                     swaps(&ptWire[p].x);
4660                     swaps(&ptWire[p].y);
4661                 }
4662             }
4663             wire = (char *) &ptWire[ol->num_points];
4664         }
4665     }
4666     return wire;
4667 }
4668 
4669 static int
XkbSizeGeomDoodads(int num_doodads,XkbDoodadPtr doodad)4670 XkbSizeGeomDoodads(int num_doodads, XkbDoodadPtr doodad)
4671 {
4672     register int i, size;
4673 
4674     for (i = size = 0; i < num_doodads; i++, doodad++) {
4675         size += SIZEOF(xkbAnyDoodadWireDesc);
4676         if (doodad->any.type == XkbTextDoodad) {
4677             size += XkbSizeCountedString(doodad->text.text);
4678             size += XkbSizeCountedString(doodad->text.font);
4679         }
4680         else if (doodad->any.type == XkbLogoDoodad) {
4681             size += XkbSizeCountedString(doodad->logo.logo_name);
4682         }
4683     }
4684     return size;
4685 }
4686 
4687 static char *
XkbWriteGeomDoodads(char * wire,int num_doodads,XkbDoodadPtr doodad,Bool swap)4688 XkbWriteGeomDoodads(char *wire, int num_doodads, XkbDoodadPtr doodad, Bool swap)
4689 {
4690     register int i;
4691     xkbDoodadWireDesc *doodadWire;
4692 
4693     for (i = 0; i < num_doodads; i++, doodad++) {
4694         doodadWire = (xkbDoodadWireDesc *) wire;
4695         wire = (char *) &doodadWire[1];
4696         memset(doodadWire, 0, SIZEOF(xkbDoodadWireDesc));
4697         doodadWire->any.name = doodad->any.name;
4698         doodadWire->any.type = doodad->any.type;
4699         doodadWire->any.priority = doodad->any.priority;
4700         doodadWire->any.top = doodad->any.top;
4701         doodadWire->any.left = doodad->any.left;
4702         if (swap) {
4703             swapl(&doodadWire->any.name);
4704             swaps(&doodadWire->any.top);
4705             swaps(&doodadWire->any.left);
4706         }
4707         switch (doodad->any.type) {
4708         case XkbOutlineDoodad:
4709         case XkbSolidDoodad:
4710             doodadWire->shape.angle = doodad->shape.angle;
4711             doodadWire->shape.colorNdx = doodad->shape.color_ndx;
4712             doodadWire->shape.shapeNdx = doodad->shape.shape_ndx;
4713             if (swap) {
4714                 swaps(&doodadWire->shape.angle);
4715             }
4716             break;
4717         case XkbTextDoodad:
4718             doodadWire->text.angle = doodad->text.angle;
4719             doodadWire->text.width = doodad->text.width;
4720             doodadWire->text.height = doodad->text.height;
4721             doodadWire->text.colorNdx = doodad->text.color_ndx;
4722             if (swap) {
4723                 swaps(&doodadWire->text.angle);
4724                 swaps(&doodadWire->text.width);
4725                 swaps(&doodadWire->text.height);
4726             }
4727             wire = XkbWriteCountedString(wire, doodad->text.text, swap);
4728             wire = XkbWriteCountedString(wire, doodad->text.font, swap);
4729             break;
4730         case XkbIndicatorDoodad:
4731             doodadWire->indicator.shapeNdx = doodad->indicator.shape_ndx;
4732             doodadWire->indicator.onColorNdx = doodad->indicator.on_color_ndx;
4733             doodadWire->indicator.offColorNdx = doodad->indicator.off_color_ndx;
4734             break;
4735         case XkbLogoDoodad:
4736             doodadWire->logo.angle = doodad->logo.angle;
4737             doodadWire->logo.colorNdx = doodad->logo.color_ndx;
4738             doodadWire->logo.shapeNdx = doodad->logo.shape_ndx;
4739             wire = XkbWriteCountedString(wire, doodad->logo.logo_name, swap);
4740             break;
4741         default:
4742             ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n",
4743                    doodad->any.type);
4744             ErrorF("[xkb] Ignored\n");
4745             break;
4746         }
4747     }
4748     return wire;
4749 }
4750 
4751 static char *
XkbWriteGeomOverlay(char * wire,XkbOverlayPtr ol,Bool swap)4752 XkbWriteGeomOverlay(char *wire, XkbOverlayPtr ol, Bool swap)
4753 {
4754     register int r;
4755     XkbOverlayRowPtr row;
4756     xkbOverlayWireDesc *olWire;
4757 
4758     olWire = (xkbOverlayWireDesc *) wire;
4759     olWire->name = ol->name;
4760     olWire->nRows = ol->num_rows;
4761     olWire->pad1 = 0;
4762     olWire->pad2 = 0;
4763     if (swap) {
4764         swapl(&olWire->name);
4765     }
4766     wire = (char *) &olWire[1];
4767     for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4768         unsigned int k;
4769         XkbOverlayKeyPtr key;
4770         xkbOverlayRowWireDesc *rowWire;
4771 
4772         rowWire = (xkbOverlayRowWireDesc *) wire;
4773         rowWire->rowUnder = row->row_under;
4774         rowWire->nKeys = row->num_keys;
4775         rowWire->pad1 = 0;
4776         wire = (char *) &rowWire[1];
4777         for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4778             xkbOverlayKeyWireDesc *keyWire;
4779 
4780             keyWire = (xkbOverlayKeyWireDesc *) wire;
4781             memcpy(keyWire->over, key->over.name, XkbKeyNameLength);
4782             memcpy(keyWire->under, key->under.name, XkbKeyNameLength);
4783             wire = (char *) &keyWire[1];
4784         }
4785     }
4786     return wire;
4787 }
4788 
4789 static int
XkbSizeGeomSections(XkbGeometryPtr geom)4790 XkbSizeGeomSections(XkbGeometryPtr geom)
4791 {
4792     register int i, size;
4793     XkbSectionPtr section;
4794 
4795     for (i = size = 0, section = geom->sections; i < geom->num_sections;
4796          i++, section++) {
4797         size += SIZEOF(xkbSectionWireDesc);
4798         if (section->rows) {
4799             int r;
4800             XkbRowPtr row;
4801 
4802             for (r = 0, row = section->rows; r < section->num_rows; row++, r++) {
4803                 size += SIZEOF(xkbRowWireDesc);
4804                 size += row->num_keys * SIZEOF(xkbKeyWireDesc);
4805             }
4806         }
4807         if (section->doodads)
4808             size += XkbSizeGeomDoodads(section->num_doodads, section->doodads);
4809         if (section->overlays) {
4810             int o;
4811             XkbOverlayPtr ol;
4812 
4813             for (o = 0, ol = section->overlays; o < section->num_overlays;
4814                  o++, ol++) {
4815                 int r;
4816                 XkbOverlayRowPtr row;
4817 
4818                 size += SIZEOF(xkbOverlayWireDesc);
4819                 for (r = 0, row = ol->rows; r < ol->num_rows; r++, row++) {
4820                     size += SIZEOF(xkbOverlayRowWireDesc);
4821                     size += row->num_keys * SIZEOF(xkbOverlayKeyWireDesc);
4822                 }
4823             }
4824         }
4825     }
4826     return size;
4827 }
4828 
4829 static char *
XkbWriteGeomSections(char * wire,XkbGeometryPtr geom,Bool swap)4830 XkbWriteGeomSections(char *wire, XkbGeometryPtr geom, Bool swap)
4831 {
4832     register int i;
4833     XkbSectionPtr section;
4834     xkbSectionWireDesc *sectionWire;
4835 
4836     for (i = 0, section = geom->sections; i < geom->num_sections;
4837          i++, section++) {
4838         sectionWire = (xkbSectionWireDesc *) wire;
4839         sectionWire->name = section->name;
4840         sectionWire->top = section->top;
4841         sectionWire->left = section->left;
4842         sectionWire->width = section->width;
4843         sectionWire->height = section->height;
4844         sectionWire->angle = section->angle;
4845         sectionWire->priority = section->priority;
4846         sectionWire->nRows = section->num_rows;
4847         sectionWire->nDoodads = section->num_doodads;
4848         sectionWire->nOverlays = section->num_overlays;
4849         sectionWire->pad = 0;
4850         if (swap) {
4851             swapl(&sectionWire->name);
4852             swaps(&sectionWire->top);
4853             swaps(&sectionWire->left);
4854             swaps(&sectionWire->width);
4855             swaps(&sectionWire->height);
4856             swaps(&sectionWire->angle);
4857         }
4858         wire = (char *) &sectionWire[1];
4859         if (section->rows) {
4860             int r;
4861             XkbRowPtr row;
4862             xkbRowWireDesc *rowWire;
4863 
4864             for (r = 0, row = section->rows; r < section->num_rows; r++, row++) {
4865                 rowWire = (xkbRowWireDesc *) wire;
4866                 rowWire->top = row->top;
4867                 rowWire->left = row->left;
4868                 rowWire->nKeys = row->num_keys;
4869                 rowWire->vertical = row->vertical;
4870                 rowWire->pad = 0;
4871                 if (swap) {
4872                     swaps(&rowWire->top);
4873                     swaps(&rowWire->left);
4874                 }
4875                 wire = (char *) &rowWire[1];
4876                 if (row->keys) {
4877                     int k;
4878                     XkbKeyPtr key;
4879                     xkbKeyWireDesc *keyWire;
4880 
4881                     keyWire = (xkbKeyWireDesc *) wire;
4882                     for (k = 0, key = row->keys; k < row->num_keys; k++, key++) {
4883                         memcpy(keyWire[k].name, key->name.name,
4884                                XkbKeyNameLength);
4885                         keyWire[k].gap = key->gap;
4886                         keyWire[k].shapeNdx = key->shape_ndx;
4887                         keyWire[k].colorNdx = key->color_ndx;
4888                         if (swap) {
4889                             swaps(&keyWire[k].gap);
4890                         }
4891                     }
4892                     wire = (char *) &keyWire[row->num_keys];
4893                 }
4894             }
4895         }
4896         if (section->doodads) {
4897             wire = XkbWriteGeomDoodads(wire,
4898                                        section->num_doodads, section->doodads,
4899                                        swap);
4900         }
4901         if (section->overlays) {
4902             register int o;
4903 
4904             for (o = 0; o < section->num_overlays; o++) {
4905                 wire = XkbWriteGeomOverlay(wire, &section->overlays[o], swap);
4906             }
4907         }
4908     }
4909     return wire;
4910 }
4911 
4912 static Status
XkbComputeGetGeometryReplySize(XkbGeometryPtr geom,xkbGetGeometryReply * rep,Atom name)4913 XkbComputeGetGeometryReplySize(XkbGeometryPtr geom,
4914                                xkbGetGeometryReply * rep, Atom name)
4915 {
4916     int len;
4917 
4918     if (geom != NULL) {
4919         len = XkbSizeCountedString(geom->label_font);
4920         len += XkbSizeGeomProperties(geom);
4921         len += XkbSizeGeomColors(geom);
4922         len += XkbSizeGeomShapes(geom);
4923         len += XkbSizeGeomSections(geom);
4924         len += XkbSizeGeomDoodads(geom->num_doodads, geom->doodads);
4925         len += XkbSizeGeomKeyAliases(geom);
4926         rep->length = len / 4;
4927         rep->found = TRUE;
4928         rep->name = geom->name;
4929         rep->widthMM = geom->width_mm;
4930         rep->heightMM = geom->height_mm;
4931         rep->nProperties = geom->num_properties;
4932         rep->nColors = geom->num_colors;
4933         rep->nShapes = geom->num_shapes;
4934         rep->nSections = geom->num_sections;
4935         rep->nDoodads = geom->num_doodads;
4936         rep->nKeyAliases = geom->num_key_aliases;
4937         rep->baseColorNdx = XkbGeomColorIndex(geom, geom->base_color);
4938         rep->labelColorNdx = XkbGeomColorIndex(geom, geom->label_color);
4939     }
4940     else {
4941         rep->length = 0;
4942         rep->found = FALSE;
4943         rep->name = name;
4944         rep->widthMM = rep->heightMM = 0;
4945         rep->nProperties = rep->nColors = rep->nShapes = 0;
4946         rep->nSections = rep->nDoodads = 0;
4947         rep->nKeyAliases = 0;
4948         rep->labelColorNdx = rep->baseColorNdx = 0;
4949     }
4950     return Success;
4951 }
4952 static int
XkbSendGeometry(ClientPtr client,XkbGeometryPtr geom,xkbGetGeometryReply * rep,Bool freeGeom)4953 XkbSendGeometry(ClientPtr client,
4954                 XkbGeometryPtr geom, xkbGetGeometryReply * rep, Bool freeGeom)
4955 {
4956     char *desc, *start;
4957     int len;
4958 
4959     if (geom != NULL) {
4960         start = desc = xallocarray(rep->length, 4);
4961         if (!start)
4962             return BadAlloc;
4963         len = rep->length * 4;
4964         desc = XkbWriteCountedString(desc, geom->label_font, client->swapped);
4965         if (rep->nProperties > 0)
4966             desc = XkbWriteGeomProperties(desc, geom, client->swapped);
4967         if (rep->nColors > 0)
4968             desc = XkbWriteGeomColors(desc, geom, client->swapped);
4969         if (rep->nShapes > 0)
4970             desc = XkbWriteGeomShapes(desc, geom, client->swapped);
4971         if (rep->nSections > 0)
4972             desc = XkbWriteGeomSections(desc, geom, client->swapped);
4973         if (rep->nDoodads > 0)
4974             desc = XkbWriteGeomDoodads(desc, geom->num_doodads, geom->doodads,
4975                                        client->swapped);
4976         if (rep->nKeyAliases > 0)
4977             desc = XkbWriteGeomKeyAliases(desc, geom, client->swapped);
4978         if ((desc - start) != (len)) {
4979             ErrorF
4980                 ("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n",
4981                  len, (unsigned long) (desc - start));
4982         }
4983     }
4984     else {
4985         len = 0;
4986         start = NULL;
4987     }
4988     if (client->swapped) {
4989         swaps(&rep->sequenceNumber);
4990         swapl(&rep->length);
4991         swapl(&rep->name);
4992         swaps(&rep->widthMM);
4993         swaps(&rep->heightMM);
4994         swaps(&rep->nProperties);
4995         swaps(&rep->nColors);
4996         swaps(&rep->nShapes);
4997         swaps(&rep->nSections);
4998         swaps(&rep->nDoodads);
4999         swaps(&rep->nKeyAliases);
5000     }
5001     WriteToClient(client, SIZEOF(xkbGetGeometryReply), rep);
5002     if (len > 0)
5003         WriteToClient(client, len, start);
5004     if (start != NULL)
5005         free((char *) start);
5006     if (freeGeom)
5007         XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5008     return Success;
5009 }
5010 
5011 int
ProcXkbGetGeometry(ClientPtr client)5012 ProcXkbGetGeometry(ClientPtr client)
5013 {
5014     DeviceIntPtr dev;
5015     xkbGetGeometryReply rep;
5016     XkbGeometryPtr geom;
5017     Bool shouldFree;
5018     Status status;
5019 
5020     REQUEST(xkbGetGeometryReq);
5021     REQUEST_SIZE_MATCH(xkbGetGeometryReq);
5022 
5023     if (!(client->xkbClientFlags & _XkbClientInitialized))
5024         return BadAccess;
5025 
5026     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5027     CHK_ATOM_OR_NONE(stuff->name);
5028 
5029     geom = XkbLookupNamedGeometry(dev, stuff->name, &shouldFree);
5030     rep = (xkbGetGeometryReply) {
5031         .type = X_Reply,
5032         .deviceID = dev->id,
5033         .sequenceNumber = client->sequence,
5034         .length = 0
5035     };
5036     status = XkbComputeGetGeometryReplySize(geom, &rep, stuff->name);
5037     if (status != Success)
5038         return status;
5039     else
5040         return XkbSendGeometry(client, geom, &rep, shouldFree);
5041 }
5042 
5043 /***====================================================================***/
5044 
5045 static Status
_GetCountedString(char ** wire_inout,ClientPtr client,char ** str)5046 _GetCountedString(char **wire_inout, ClientPtr client, char **str)
5047 {
5048     char *wire, *next;
5049     CARD16 len;
5050 
5051     wire = *wire_inout;
5052     len = *(CARD16 *) wire;
5053     if (client->swapped) {
5054         swaps(&len);
5055     }
5056     next = wire + XkbPaddedSize(len + 2);
5057     /* Check we're still within the size of the request */
5058     if (client->req_len <
5059         bytes_to_int32(next - (char *) client->requestBuffer))
5060         return BadValue;
5061     *str = malloc(len + 1);
5062     if (!*str)
5063         return BadAlloc;
5064     memcpy(*str, &wire[2], len);
5065     *(*str + len) = '\0';
5066     *wire_inout = next;
5067     return Success;
5068 }
5069 
5070 static Status
_CheckSetDoodad(char ** wire_inout,XkbGeometryPtr geom,XkbSectionPtr section,ClientPtr client)5071 _CheckSetDoodad(char **wire_inout,
5072                 XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5073 {
5074     char *wire;
5075     xkbDoodadWireDesc *dWire;
5076     xkbAnyDoodadWireDesc any;
5077     xkbTextDoodadWireDesc text;
5078     XkbDoodadPtr doodad;
5079     Status status;
5080 
5081     dWire = (xkbDoodadWireDesc *) (*wire_inout);
5082     any = dWire->any;
5083     wire = (char *) &dWire[1];
5084     if (client->swapped) {
5085         swapl(&any.name);
5086         swaps(&any.top);
5087         swaps(&any.left);
5088         swaps(&any.angle);
5089     }
5090     CHK_ATOM_ONLY(dWire->any.name);
5091     doodad = XkbAddGeomDoodad(geom, section, any.name);
5092     if (!doodad)
5093         return BadAlloc;
5094     doodad->any.type = dWire->any.type;
5095     doodad->any.priority = dWire->any.priority;
5096     doodad->any.top = any.top;
5097     doodad->any.left = any.left;
5098     doodad->any.angle = any.angle;
5099     switch (doodad->any.type) {
5100     case XkbOutlineDoodad:
5101     case XkbSolidDoodad:
5102         if (dWire->shape.colorNdx >= geom->num_colors) {
5103             client->errorValue = _XkbErrCode3(0x40, geom->num_colors,
5104                                               dWire->shape.colorNdx);
5105             return BadMatch;
5106         }
5107         if (dWire->shape.shapeNdx >= geom->num_shapes) {
5108             client->errorValue = _XkbErrCode3(0x41, geom->num_shapes,
5109                                               dWire->shape.shapeNdx);
5110             return BadMatch;
5111         }
5112         doodad->shape.color_ndx = dWire->shape.colorNdx;
5113         doodad->shape.shape_ndx = dWire->shape.shapeNdx;
5114         break;
5115     case XkbTextDoodad:
5116         if (dWire->text.colorNdx >= geom->num_colors) {
5117             client->errorValue = _XkbErrCode3(0x42, geom->num_colors,
5118                                               dWire->text.colorNdx);
5119             return BadMatch;
5120         }
5121         text = dWire->text;
5122         if (client->swapped) {
5123             swaps(&text.width);
5124             swaps(&text.height);
5125         }
5126         doodad->text.width = text.width;
5127         doodad->text.height = text.height;
5128         doodad->text.color_ndx = dWire->text.colorNdx;
5129         status = _GetCountedString(&wire, client, &doodad->text.text);
5130         if (status != Success)
5131             return status;
5132         status = _GetCountedString(&wire, client, &doodad->text.font);
5133         if (status != Success) {
5134             free (doodad->text.text);
5135             return status;
5136         }
5137         break;
5138     case XkbIndicatorDoodad:
5139         if (dWire->indicator.onColorNdx >= geom->num_colors) {
5140             client->errorValue = _XkbErrCode3(0x43, geom->num_colors,
5141                                               dWire->indicator.onColorNdx);
5142             return BadMatch;
5143         }
5144         if (dWire->indicator.offColorNdx >= geom->num_colors) {
5145             client->errorValue = _XkbErrCode3(0x44, geom->num_colors,
5146                                               dWire->indicator.offColorNdx);
5147             return BadMatch;
5148         }
5149         if (dWire->indicator.shapeNdx >= geom->num_shapes) {
5150             client->errorValue = _XkbErrCode3(0x45, geom->num_shapes,
5151                                               dWire->indicator.shapeNdx);
5152             return BadMatch;
5153         }
5154         doodad->indicator.shape_ndx = dWire->indicator.shapeNdx;
5155         doodad->indicator.on_color_ndx = dWire->indicator.onColorNdx;
5156         doodad->indicator.off_color_ndx = dWire->indicator.offColorNdx;
5157         break;
5158     case XkbLogoDoodad:
5159         if (dWire->logo.colorNdx >= geom->num_colors) {
5160             client->errorValue = _XkbErrCode3(0x46, geom->num_colors,
5161                                               dWire->logo.colorNdx);
5162             return BadMatch;
5163         }
5164         if (dWire->logo.shapeNdx >= geom->num_shapes) {
5165             client->errorValue = _XkbErrCode3(0x47, geom->num_shapes,
5166                                               dWire->logo.shapeNdx);
5167             return BadMatch;
5168         }
5169         doodad->logo.color_ndx = dWire->logo.colorNdx;
5170         doodad->logo.shape_ndx = dWire->logo.shapeNdx;
5171         status = _GetCountedString(&wire, client, &doodad->logo.logo_name);
5172         if (status != Success)
5173             return status;
5174         break;
5175     default:
5176         client->errorValue = _XkbErrCode2(0x4F, dWire->any.type);
5177         return BadValue;
5178     }
5179     *wire_inout = wire;
5180     return Success;
5181 }
5182 
5183 static Status
_CheckSetOverlay(char ** wire_inout,XkbGeometryPtr geom,XkbSectionPtr section,ClientPtr client)5184 _CheckSetOverlay(char **wire_inout,
5185                  XkbGeometryPtr geom, XkbSectionPtr section, ClientPtr client)
5186 {
5187     register int r;
5188     char *wire;
5189     XkbOverlayPtr ol;
5190     xkbOverlayWireDesc *olWire;
5191     xkbOverlayRowWireDesc *rWire;
5192 
5193     wire = *wire_inout;
5194     olWire = (xkbOverlayWireDesc *) wire;
5195     if (client->swapped) {
5196         swapl(&olWire->name);
5197     }
5198     CHK_ATOM_ONLY(olWire->name);
5199     ol = XkbAddGeomOverlay(section, olWire->name, olWire->nRows);
5200     rWire = (xkbOverlayRowWireDesc *) &olWire[1];
5201     for (r = 0; r < olWire->nRows; r++) {
5202         register int k;
5203         xkbOverlayKeyWireDesc *kWire;
5204         XkbOverlayRowPtr row;
5205 
5206         if (rWire->rowUnder > section->num_rows) {
5207             client->errorValue = _XkbErrCode4(0x20, r, section->num_rows,
5208                                               rWire->rowUnder);
5209             return BadMatch;
5210         }
5211         row = XkbAddGeomOverlayRow(ol, rWire->rowUnder, rWire->nKeys);
5212         kWire = (xkbOverlayKeyWireDesc *) &rWire[1];
5213         for (k = 0; k < rWire->nKeys; k++, kWire++) {
5214             if (XkbAddGeomOverlayKey(ol, row,
5215                                      (char *) kWire->over,
5216                                      (char *) kWire->under) == NULL) {
5217                 client->errorValue = _XkbErrCode3(0x21, r, k);
5218                 return BadMatch;
5219             }
5220         }
5221         rWire = (xkbOverlayRowWireDesc *) kWire;
5222     }
5223     olWire = (xkbOverlayWireDesc *) rWire;
5224     wire = (char *) olWire;
5225     *wire_inout = wire;
5226     return Success;
5227 }
5228 
5229 static Status
_CheckSetSections(XkbGeometryPtr geom,xkbSetGeometryReq * req,char ** wire_inout,ClientPtr client)5230 _CheckSetSections(XkbGeometryPtr geom,
5231                   xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5232 {
5233     Status status;
5234     register int s;
5235     char *wire;
5236     xkbSectionWireDesc *sWire;
5237     XkbSectionPtr section;
5238 
5239     wire = *wire_inout;
5240     if (req->nSections < 1)
5241         return Success;
5242     sWire = (xkbSectionWireDesc *) wire;
5243     for (s = 0; s < req->nSections; s++) {
5244         register int r;
5245         xkbRowWireDesc *rWire;
5246 
5247         if (client->swapped) {
5248             swapl(&sWire->name);
5249             swaps(&sWire->top);
5250             swaps(&sWire->left);
5251             swaps(&sWire->width);
5252             swaps(&sWire->height);
5253             swaps(&sWire->angle);
5254         }
5255         CHK_ATOM_ONLY(sWire->name);
5256         section = XkbAddGeomSection(geom, sWire->name, sWire->nRows,
5257                                     sWire->nDoodads, sWire->nOverlays);
5258         if (!section)
5259             return BadAlloc;
5260         section->priority = sWire->priority;
5261         section->top = sWire->top;
5262         section->left = sWire->left;
5263         section->width = sWire->width;
5264         section->height = sWire->height;
5265         section->angle = sWire->angle;
5266         rWire = (xkbRowWireDesc *) &sWire[1];
5267         for (r = 0; r < sWire->nRows; r++) {
5268             register int k;
5269             XkbRowPtr row;
5270             xkbKeyWireDesc *kWire;
5271 
5272             if (client->swapped) {
5273                 swaps(&rWire->top);
5274                 swaps(&rWire->left);
5275             }
5276             row = XkbAddGeomRow(section, rWire->nKeys);
5277             if (!row)
5278                 return BadAlloc;
5279             row->top = rWire->top;
5280             row->left = rWire->left;
5281             row->vertical = rWire->vertical;
5282             kWire = (xkbKeyWireDesc *) &rWire[1];
5283             for (k = 0; k < rWire->nKeys; k++) {
5284                 XkbKeyPtr key;
5285 
5286                 key = XkbAddGeomKey(row);
5287                 if (!key)
5288                     return BadAlloc;
5289                 memcpy(key->name.name, kWire[k].name, XkbKeyNameLength);
5290                 key->gap = kWire[k].gap;
5291                 key->shape_ndx = kWire[k].shapeNdx;
5292                 key->color_ndx = kWire[k].colorNdx;
5293                 if (key->shape_ndx >= geom->num_shapes) {
5294                     client->errorValue = _XkbErrCode3(0x10, key->shape_ndx,
5295                                                       geom->num_shapes);
5296                     return BadMatch;
5297                 }
5298                 if (key->color_ndx >= geom->num_colors) {
5299                     client->errorValue = _XkbErrCode3(0x11, key->color_ndx,
5300                                                       geom->num_colors);
5301                     return BadMatch;
5302                 }
5303             }
5304             rWire = (xkbRowWireDesc *) &kWire[rWire->nKeys];
5305         }
5306         wire = (char *) rWire;
5307         if (sWire->nDoodads > 0) {
5308             register int d;
5309 
5310             for (d = 0; d < sWire->nDoodads; d++) {
5311                 status = _CheckSetDoodad(&wire, geom, section, client);
5312                 if (status != Success)
5313                     return status;
5314             }
5315         }
5316         if (sWire->nOverlays > 0) {
5317             register int o;
5318 
5319             for (o = 0; o < sWire->nOverlays; o++) {
5320                 status = _CheckSetOverlay(&wire, geom, section, client);
5321                 if (status != Success)
5322                     return status;
5323             }
5324         }
5325         sWire = (xkbSectionWireDesc *) wire;
5326     }
5327     wire = (char *) sWire;
5328     *wire_inout = wire;
5329     return Success;
5330 }
5331 
5332 static Status
_CheckSetShapes(XkbGeometryPtr geom,xkbSetGeometryReq * req,char ** wire_inout,ClientPtr client)5333 _CheckSetShapes(XkbGeometryPtr geom,
5334                 xkbSetGeometryReq * req, char **wire_inout, ClientPtr client)
5335 {
5336     register int i;
5337     char *wire;
5338 
5339     wire = *wire_inout;
5340     if (req->nShapes < 1) {
5341         client->errorValue = _XkbErrCode2(0x06, req->nShapes);
5342         return BadValue;
5343     }
5344     else {
5345         xkbShapeWireDesc *shapeWire;
5346         XkbShapePtr shape;
5347         register int o;
5348 
5349         shapeWire = (xkbShapeWireDesc *) wire;
5350         for (i = 0; i < req->nShapes; i++) {
5351             xkbOutlineWireDesc *olWire;
5352             XkbOutlinePtr ol;
5353 
5354             shape =
5355                 XkbAddGeomShape(geom, shapeWire->name, shapeWire->nOutlines);
5356             if (!shape)
5357                 return BadAlloc;
5358             olWire = (xkbOutlineWireDesc *) (&shapeWire[1]);
5359             for (o = 0; o < shapeWire->nOutlines; o++) {
5360                 register int p;
5361                 XkbPointPtr pt;
5362                 xkbPointWireDesc *ptWire;
5363 
5364                 ol = XkbAddGeomOutline(shape, olWire->nPoints);
5365                 if (!ol)
5366                     return BadAlloc;
5367                 ol->corner_radius = olWire->cornerRadius;
5368                 ptWire = (xkbPointWireDesc *) &olWire[1];
5369                 for (p = 0, pt = ol->points; p < olWire->nPoints; p++, pt++) {
5370                     pt->x = ptWire[p].x;
5371                     pt->y = ptWire[p].y;
5372                     if (client->swapped) {
5373                         swaps(&pt->x);
5374                         swaps(&pt->y);
5375                     }
5376                 }
5377                 ol->num_points = olWire->nPoints;
5378                 olWire = (xkbOutlineWireDesc *) (&ptWire[olWire->nPoints]);
5379             }
5380             if (shapeWire->primaryNdx != XkbNoShape)
5381                 shape->primary = &shape->outlines[shapeWire->primaryNdx];
5382             if (shapeWire->approxNdx != XkbNoShape)
5383                 shape->approx = &shape->outlines[shapeWire->approxNdx];
5384             shapeWire = (xkbShapeWireDesc *) olWire;
5385         }
5386         wire = (char *) shapeWire;
5387     }
5388     if (geom->num_shapes != req->nShapes) {
5389         client->errorValue = _XkbErrCode3(0x07, geom->num_shapes, req->nShapes);
5390         return BadMatch;
5391     }
5392 
5393     *wire_inout = wire;
5394     return Success;
5395 }
5396 
5397 static Status
_CheckSetGeom(XkbGeometryPtr geom,xkbSetGeometryReq * req,ClientPtr client)5398 _CheckSetGeom(XkbGeometryPtr geom, xkbSetGeometryReq * req, ClientPtr client)
5399 {
5400     register int i;
5401     Status status;
5402     char *wire;
5403 
5404     wire = (char *) &req[1];
5405     status = _GetCountedString(&wire, client, &geom->label_font);
5406     if (status != Success)
5407         return status;
5408 
5409     for (i = 0; i < req->nProperties; i++) {
5410         char *name, *val;
5411 
5412         status = _GetCountedString(&wire, client, &name);
5413         if (status != Success)
5414             return status;
5415         status = _GetCountedString(&wire, client, &val);
5416         if (status != Success) {
5417             free(name);
5418             return status;
5419         }
5420         if (XkbAddGeomProperty(geom, name, val) == NULL) {
5421             free(name);
5422             free(val);
5423             return BadAlloc;
5424         }
5425         free(name);
5426         free(val);
5427     }
5428 
5429     if (req->nColors < 2) {
5430         client->errorValue = _XkbErrCode3(0x01, 2, req->nColors);
5431         return BadValue;
5432     }
5433     if (req->baseColorNdx > req->nColors) {
5434         client->errorValue =
5435             _XkbErrCode3(0x03, req->nColors, req->baseColorNdx);
5436         return BadMatch;
5437     }
5438     if (req->labelColorNdx > req->nColors) {
5439         client->errorValue =
5440             _XkbErrCode3(0x03, req->nColors, req->labelColorNdx);
5441         return BadMatch;
5442     }
5443     if (req->labelColorNdx == req->baseColorNdx) {
5444         client->errorValue = _XkbErrCode3(0x04, req->baseColorNdx,
5445                                           req->labelColorNdx);
5446         return BadMatch;
5447     }
5448 
5449     for (i = 0; i < req->nColors; i++) {
5450         char *name;
5451 
5452         status = _GetCountedString(&wire, client, &name);
5453         if (status != Success)
5454             return status;
5455         if (!XkbAddGeomColor(geom, name, geom->num_colors)) {
5456             free(name);
5457             return BadAlloc;
5458         }
5459         free(name);
5460     }
5461     if (req->nColors != geom->num_colors) {
5462         client->errorValue = _XkbErrCode3(0x05, req->nColors, geom->num_colors);
5463         return BadMatch;
5464     }
5465     geom->label_color = &geom->colors[req->labelColorNdx];
5466     geom->base_color = &geom->colors[req->baseColorNdx];
5467 
5468     if ((status = _CheckSetShapes(geom, req, &wire, client)) != Success)
5469         return status;
5470 
5471     if ((status = _CheckSetSections(geom, req, &wire, client)) != Success)
5472         return status;
5473 
5474     for (i = 0; i < req->nDoodads; i++) {
5475         status = _CheckSetDoodad(&wire, geom, NULL, client);
5476         if (status != Success)
5477             return status;
5478     }
5479 
5480     for (i = 0; i < req->nKeyAliases; i++) {
5481         if (XkbAddGeomKeyAlias(geom, &wire[XkbKeyNameLength], wire) == NULL)
5482             return BadAlloc;
5483         wire += 2 * XkbKeyNameLength;
5484     }
5485     return Success;
5486 }
5487 
5488 static int
_XkbSetGeometry(ClientPtr client,DeviceIntPtr dev,xkbSetGeometryReq * stuff)5489 _XkbSetGeometry(ClientPtr client, DeviceIntPtr dev, xkbSetGeometryReq * stuff)
5490 {
5491     XkbDescPtr xkb;
5492     Bool new_name;
5493     xkbNewKeyboardNotify nkn;
5494     XkbGeometryPtr geom, old;
5495     XkbGeometrySizesRec sizes;
5496     Status status;
5497 
5498     xkb = dev->key->xkbInfo->desc;
5499     old = xkb->geom;
5500     xkb->geom = NULL;
5501 
5502     sizes.which = XkbGeomAllMask;
5503     sizes.num_properties = stuff->nProperties;
5504     sizes.num_colors = stuff->nColors;
5505     sizes.num_shapes = stuff->nShapes;
5506     sizes.num_sections = stuff->nSections;
5507     sizes.num_doodads = stuff->nDoodads;
5508     sizes.num_key_aliases = stuff->nKeyAliases;
5509     if ((status = XkbAllocGeometry(xkb, &sizes)) != Success) {
5510         xkb->geom = old;
5511         return status;
5512     }
5513     geom = xkb->geom;
5514     geom->name = stuff->name;
5515     geom->width_mm = stuff->widthMM;
5516     geom->height_mm = stuff->heightMM;
5517     if ((status = _CheckSetGeom(geom, stuff, client)) != Success) {
5518         XkbFreeGeometry(geom, XkbGeomAllMask, TRUE);
5519         xkb->geom = old;
5520         return status;
5521     }
5522     new_name = (xkb->names->geometry != geom->name);
5523     xkb->names->geometry = geom->name;
5524     if (old)
5525         XkbFreeGeometry(old, XkbGeomAllMask, TRUE);
5526     if (new_name) {
5527         xkbNamesNotify nn;
5528 
5529         memset(&nn, 0, sizeof(xkbNamesNotify));
5530         nn.changed = XkbGeometryNameMask;
5531         XkbSendNamesNotify(dev, &nn);
5532     }
5533     nkn.deviceID = nkn.oldDeviceID = dev->id;
5534     nkn.minKeyCode = nkn.oldMinKeyCode = xkb->min_key_code;
5535     nkn.maxKeyCode = nkn.oldMaxKeyCode = xkb->max_key_code;
5536     nkn.requestMajor = XkbReqCode;
5537     nkn.requestMinor = X_kbSetGeometry;
5538     nkn.changed = XkbNKN_GeometryMask;
5539     XkbSendNewKeyboardNotify(dev, &nkn);
5540     return Success;
5541 }
5542 
5543 int
ProcXkbSetGeometry(ClientPtr client)5544 ProcXkbSetGeometry(ClientPtr client)
5545 {
5546     DeviceIntPtr dev;
5547     int rc;
5548 
5549     REQUEST(xkbSetGeometryReq);
5550     REQUEST_AT_LEAST_SIZE(xkbSetGeometryReq);
5551 
5552     if (!(client->xkbClientFlags & _XkbClientInitialized))
5553         return BadAccess;
5554 
5555     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
5556     CHK_ATOM_OR_NONE(stuff->name);
5557 
5558     rc = _XkbSetGeometry(client, dev, stuff);
5559     if (rc != Success)
5560         return rc;
5561 
5562     if (stuff->deviceSpec == XkbUseCoreKbd) {
5563         DeviceIntPtr other;
5564 
5565         for (other = inputInfo.devices; other; other = other->next) {
5566             if ((other != dev) && other->key && !IsMaster(other) &&
5567                 GetMaster(other, MASTER_KEYBOARD) == dev) {
5568                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
5569                               DixManageAccess);
5570                 if (rc == Success)
5571                     _XkbSetGeometry(client, other, stuff);
5572             }
5573         }
5574     }
5575 
5576     return Success;
5577 }
5578 
5579 /***====================================================================***/
5580 
5581 int
ProcXkbPerClientFlags(ClientPtr client)5582 ProcXkbPerClientFlags(ClientPtr client)
5583 {
5584     DeviceIntPtr dev;
5585     xkbPerClientFlagsReply rep;
5586     XkbInterestPtr interest;
5587     Mask access_mode = DixGetAttrAccess | DixSetAttrAccess;
5588 
5589     REQUEST(xkbPerClientFlagsReq);
5590     REQUEST_SIZE_MATCH(xkbPerClientFlagsReq);
5591 
5592     if (!(client->xkbClientFlags & _XkbClientInitialized))
5593         return BadAccess;
5594 
5595     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5596     CHK_MASK_LEGAL(0x01, stuff->change, XkbPCF_AllFlagsMask);
5597     CHK_MASK_MATCH(0x02, stuff->change, stuff->value);
5598 
5599     interest = XkbFindClientResource((DevicePtr) dev, client);
5600     if (stuff->change) {
5601         client->xkbClientFlags &= ~stuff->change;
5602         client->xkbClientFlags |= stuff->value;
5603     }
5604     if (stuff->change & XkbPCF_AutoResetControlsMask) {
5605         Bool want;
5606 
5607         want = stuff->value & XkbPCF_AutoResetControlsMask;
5608         if (interest && !want) {
5609             interest->autoCtrls = interest->autoCtrlValues = 0;
5610         }
5611         else if (want && (!interest)) {
5612             XID id = FakeClientID(client->index);
5613 
5614             if (!AddResource(id, RT_XKBCLIENT, dev))
5615                 return BadAlloc;
5616             interest = XkbAddClientResource((DevicePtr) dev, client, id);
5617             if (!interest)
5618                 return BadAlloc;
5619         }
5620         if (interest && want) {
5621             register unsigned affect;
5622 
5623             affect = stuff->ctrlsToChange;
5624 
5625             CHK_MASK_LEGAL(0x03, affect, XkbAllBooleanCtrlsMask);
5626             CHK_MASK_MATCH(0x04, affect, stuff->autoCtrls);
5627             CHK_MASK_MATCH(0x05, stuff->autoCtrls, stuff->autoCtrlValues);
5628 
5629             interest->autoCtrls &= ~affect;
5630             interest->autoCtrlValues &= ~affect;
5631             interest->autoCtrls |= stuff->autoCtrls & affect;
5632             interest->autoCtrlValues |= stuff->autoCtrlValues & affect;
5633         }
5634     }
5635 
5636     rep = (xkbPerClientFlagsReply) {
5637         .type = X_Reply,
5638         .sequenceNumber = client->sequence,
5639         .length = 0,
5640         .supported = XkbPCF_AllFlagsMask,
5641         .value = client->xkbClientFlags & XkbPCF_AllFlagsMask,
5642         .autoCtrls = interest ? interest->autoCtrls : 0,
5643         .autoCtrlValues =  interest ? interest->autoCtrlValues : 0,
5644     };
5645     if (client->swapped) {
5646         swaps(&rep.sequenceNumber);
5647         swapl(&rep.supported);
5648         swapl(&rep.value);
5649         swapl(&rep.autoCtrls);
5650         swapl(&rep.autoCtrlValues);
5651     }
5652     WriteToClient(client, SIZEOF(xkbPerClientFlagsReply), &rep);
5653     return Success;
5654 }
5655 
5656 /***====================================================================***/
5657 
5658 /* all latin-1 alphanumerics, plus parens, minus, underscore, slash */
5659 /* and wildcards */
5660 static unsigned char componentSpecLegal[] = {
5661     0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0xff, 0x87,
5662     0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x07,
5663     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5664     0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5665 };
5666 
5667 /* same as above but accepts percent, plus and bar too */
5668 static unsigned char componentExprLegal[] = {
5669     0x00, 0x00, 0x00, 0x00, 0x20, 0xaf, 0xff, 0x87,
5670     0xfe, 0xff, 0xff, 0x87, 0xfe, 0xff, 0xff, 0x17,
5671     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5672     0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff
5673 };
5674 
5675 static char *
GetComponentSpec(unsigned char ** pWire,Bool allowExpr,int * errRtrn)5676 GetComponentSpec(unsigned char **pWire, Bool allowExpr, int *errRtrn)
5677 {
5678     int len;
5679     register int i;
5680     unsigned char *wire, *str, *tmp, *legal;
5681 
5682     if (allowExpr)
5683         legal = &componentExprLegal[0];
5684     else
5685         legal = &componentSpecLegal[0];
5686 
5687     wire = *pWire;
5688     len = (*(unsigned char *) wire++);
5689     if (len > 0) {
5690         str = calloc(1, len + 1);
5691         if (str) {
5692             tmp = str;
5693             for (i = 0; i < len; i++) {
5694                 if (legal[(*wire) / 8] & (1 << ((*wire) % 8)))
5695                     *tmp++ = *wire++;
5696                 else
5697                     wire++;
5698             }
5699             if (tmp != str)
5700                 *tmp++ = '\0';
5701             else {
5702                 free(str);
5703                 str = NULL;
5704             }
5705         }
5706         else {
5707             *errRtrn = BadAlloc;
5708         }
5709     }
5710     else {
5711         str = NULL;
5712     }
5713     *pWire = wire;
5714     return (char *) str;
5715 }
5716 
5717 /***====================================================================***/
5718 
5719 int
ProcXkbListComponents(ClientPtr client)5720 ProcXkbListComponents(ClientPtr client)
5721 {
5722     DeviceIntPtr dev;
5723     xkbListComponentsReply rep;
5724     unsigned len;
5725     unsigned char *str;
5726     uint8_t size;
5727     int i;
5728 
5729     REQUEST(xkbListComponentsReq);
5730     REQUEST_AT_LEAST_SIZE(xkbListComponentsReq);
5731 
5732     if (!(client->xkbClientFlags & _XkbClientInitialized))
5733         return BadAccess;
5734 
5735     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
5736 
5737     /* The request is followed by six Pascal strings (i.e. size in characters
5738      * followed by a string pattern) describing what the client wants us to
5739      * list.  We don't care, but might as well check they haven't got the
5740      * length wrong. */
5741     str = (unsigned char *) &stuff[1];
5742     for (i = 0; i < 6; i++) {
5743         size = *((uint8_t *)str);
5744         len = (str + size + 1) - ((unsigned char *) stuff);
5745         if ((XkbPaddedSize(len) / 4) > stuff->length)
5746             return BadLength;
5747         str += (size + 1);
5748     }
5749     if ((XkbPaddedSize(len) / 4) != stuff->length)
5750         return BadLength;
5751     rep = (xkbListComponentsReply) {
5752         .type = X_Reply,
5753         .deviceID = dev->id,
5754         .sequenceNumber = client->sequence,
5755         .length = 0,
5756         .nKeymaps = 0,
5757         .nKeycodes = 0,
5758         .nTypes = 0,
5759         .nCompatMaps = 0,
5760         .nSymbols = 0,
5761         .nGeometries = 0,
5762         .extra = 0
5763     };
5764     if (client->swapped) {
5765         swaps(&rep.sequenceNumber);
5766         swapl(&rep.length);
5767         swaps(&rep.nKeymaps);
5768         swaps(&rep.nKeycodes);
5769         swaps(&rep.nTypes);
5770         swaps(&rep.nCompatMaps);
5771         swaps(&rep.nSymbols);
5772         swaps(&rep.nGeometries);
5773         swaps(&rep.extra);
5774     }
5775     WriteToClient(client, SIZEOF(xkbListComponentsReply), &rep);
5776     return Success;
5777 }
5778 
5779 /***====================================================================***/
5780 int
ProcXkbGetKbdByName(ClientPtr client)5781 ProcXkbGetKbdByName(ClientPtr client)
5782 {
5783     DeviceIntPtr dev;
5784     DeviceIntPtr tmpd;
5785     DeviceIntPtr master;
5786     xkbGetKbdByNameReply rep = { 0 };
5787     xkbGetMapReply mrep = { 0 };
5788     xkbGetCompatMapReply crep = { 0 };
5789     xkbGetIndicatorMapReply irep = { 0 };
5790     xkbGetNamesReply nrep = { 0 };
5791     xkbGetGeometryReply grep = { 0 };
5792     XkbComponentNamesRec names = { 0 };
5793     XkbDescPtr xkb, new;
5794     XkbEventCauseRec cause;
5795     unsigned char *str;
5796     char mapFile[PATH_MAX];
5797     unsigned len;
5798     unsigned fwant, fneed, reported;
5799     int status;
5800     Bool geom_changed;
5801     XkbSrvLedInfoPtr old_sli;
5802     XkbSrvLedInfoPtr sli;
5803     Mask access_mode = DixGetAttrAccess | DixManageAccess;
5804 
5805     REQUEST(xkbGetKbdByNameReq);
5806     REQUEST_AT_LEAST_SIZE(xkbGetKbdByNameReq);
5807 
5808     if (!(client->xkbClientFlags & _XkbClientInitialized))
5809         return BadAccess;
5810 
5811     CHK_KBD_DEVICE(dev, stuff->deviceSpec, client, access_mode);
5812     master = GetMaster(dev, MASTER_KEYBOARD);
5813 
5814     xkb = dev->key->xkbInfo->desc;
5815     status = Success;
5816     str = (unsigned char *) &stuff[1];
5817     if (GetComponentSpec(&str, TRUE, &status))  /* keymap, unsupported */
5818         return BadMatch;
5819     names.keycodes = GetComponentSpec(&str, TRUE, &status);
5820     names.types = GetComponentSpec(&str, TRUE, &status);
5821     names.compat = GetComponentSpec(&str, TRUE, &status);
5822     names.symbols = GetComponentSpec(&str, TRUE, &status);
5823     names.geometry = GetComponentSpec(&str, TRUE, &status);
5824     if (status != Success)
5825         return status;
5826     len = str - ((unsigned char *) stuff);
5827     if ((XkbPaddedSize(len) / 4) != stuff->length)
5828         return BadLength;
5829 
5830     CHK_MASK_LEGAL(0x01, stuff->want, XkbGBN_AllComponentsMask);
5831     CHK_MASK_LEGAL(0x02, stuff->need, XkbGBN_AllComponentsMask);
5832 
5833     if (stuff->load)
5834         fwant = XkbGBN_AllComponentsMask;
5835     else
5836         fwant = stuff->want | stuff->need;
5837     if ((!names.compat) &&
5838         (fwant & (XkbGBN_CompatMapMask | XkbGBN_IndicatorMapMask))) {
5839         names.compat = Xstrdup("%");
5840     }
5841     if ((!names.types) && (fwant & (XkbGBN_TypesMask))) {
5842         names.types = Xstrdup("%");
5843     }
5844     if ((!names.symbols) && (fwant & XkbGBN_SymbolsMask)) {
5845         names.symbols = Xstrdup("%");
5846     }
5847     geom_changed = ((names.geometry != NULL) &&
5848                     (strcmp(names.geometry, "%") != 0));
5849     if ((!names.geometry) && (fwant & XkbGBN_GeometryMask)) {
5850         names.geometry = Xstrdup("%");
5851         geom_changed = FALSE;
5852     }
5853 
5854     memset(mapFile, 0, PATH_MAX);
5855     rep.type = X_Reply;
5856     rep.deviceID = dev->id;
5857     rep.sequenceNumber = client->sequence;
5858     rep.length = 0;
5859     rep.minKeyCode = xkb->min_key_code;
5860     rep.maxKeyCode = xkb->max_key_code;
5861     rep.loaded = FALSE;
5862     fwant =
5863         XkbConvertGetByNameComponents(TRUE, stuff->want) | XkmVirtualModsMask;
5864     fneed = XkbConvertGetByNameComponents(TRUE, stuff->need);
5865     rep.reported = XkbConvertGetByNameComponents(FALSE, fwant | fneed);
5866     if (stuff->load) {
5867         fneed |= XkmKeymapRequired;
5868         fwant |= XkmKeymapLegal;
5869     }
5870     if ((fwant | fneed) & XkmSymbolsMask) {
5871         fneed |= XkmKeyNamesIndex | XkmTypesIndex;
5872         fwant |= XkmIndicatorsIndex;
5873     }
5874 
5875     /* We pass dev in here so we can get the old names out if needed. */
5876     rep.found = XkbDDXLoadKeymapByNames(dev, &names, fwant, fneed, &new,
5877                                         mapFile, PATH_MAX);
5878     rep.newKeyboard = FALSE;
5879     rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
5880 
5881     stuff->want |= stuff->need;
5882     if (new == NULL)
5883         rep.reported = 0;
5884     else {
5885         if (stuff->load)
5886             rep.loaded = TRUE;
5887         if (stuff->load ||
5888             ((rep.reported & XkbGBN_SymbolsMask) && (new->compat))) {
5889             XkbChangesRec changes;
5890 
5891             memset(&changes, 0, sizeof(changes));
5892             XkbUpdateDescActions(new,
5893                                  new->min_key_code, XkbNumKeys(new), &changes);
5894         }
5895 
5896         if (new->map == NULL)
5897             rep.reported &= ~(XkbGBN_SymbolsMask | XkbGBN_TypesMask);
5898         else if (rep.reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask)) {
5899             mrep.type = X_Reply;
5900             mrep.deviceID = dev->id;
5901             mrep.sequenceNumber = client->sequence;
5902             mrep.length =
5903                 ((SIZEOF(xkbGetMapReply) - SIZEOF(xGenericReply)) >> 2);
5904             mrep.minKeyCode = new->min_key_code;
5905             mrep.maxKeyCode = new->max_key_code;
5906             mrep.present = 0;
5907             mrep.totalSyms = mrep.totalActs =
5908                 mrep.totalKeyBehaviors = mrep.totalKeyExplicit =
5909                 mrep.totalModMapKeys = mrep.totalVModMapKeys = 0;
5910             if (rep.reported & (XkbGBN_TypesMask | XkbGBN_ClientSymbolsMask)) {
5911                 mrep.present |= XkbKeyTypesMask;
5912                 mrep.firstType = 0;
5913                 mrep.nTypes = mrep.totalTypes = new->map->num_types;
5914             }
5915             else {
5916                 mrep.firstType = mrep.nTypes = 0;
5917                 mrep.totalTypes = 0;
5918             }
5919             if (rep.reported & XkbGBN_ClientSymbolsMask) {
5920                 mrep.present |= (XkbKeySymsMask | XkbModifierMapMask);
5921                 mrep.firstKeySym = mrep.firstModMapKey = new->min_key_code;
5922                 mrep.nKeySyms = mrep.nModMapKeys = XkbNumKeys(new);
5923             }
5924             else {
5925                 mrep.firstKeySym = mrep.firstModMapKey = 0;
5926                 mrep.nKeySyms = mrep.nModMapKeys = 0;
5927             }
5928             if (rep.reported & XkbGBN_ServerSymbolsMask) {
5929                 mrep.present |= XkbAllServerInfoMask;
5930                 mrep.virtualMods = ~0;
5931                 mrep.firstKeyAct = mrep.firstKeyBehavior =
5932                     mrep.firstKeyExplicit = new->min_key_code;
5933                 mrep.nKeyActs = mrep.nKeyBehaviors =
5934                     mrep.nKeyExplicit = XkbNumKeys(new);
5935                 mrep.firstVModMapKey = new->min_key_code;
5936                 mrep.nVModMapKeys = XkbNumKeys(new);
5937             }
5938             else {
5939                 mrep.virtualMods = 0;
5940                 mrep.firstKeyAct = mrep.firstKeyBehavior =
5941                     mrep.firstKeyExplicit = 0;
5942                 mrep.nKeyActs = mrep.nKeyBehaviors = mrep.nKeyExplicit = 0;
5943             }
5944             XkbComputeGetMapReplySize(new, &mrep);
5945             rep.length += SIZEOF(xGenericReply) / 4 + mrep.length;
5946         }
5947         if (new->compat == NULL)
5948             rep.reported &= ~XkbGBN_CompatMapMask;
5949         else if (rep.reported & XkbGBN_CompatMapMask) {
5950             crep.type = X_Reply;
5951             crep.deviceID = dev->id;
5952             crep.sequenceNumber = client->sequence;
5953             crep.length = 0;
5954             crep.groups = XkbAllGroupsMask;
5955             crep.firstSI = 0;
5956             crep.nSI = crep.nTotalSI = new->compat->num_si;
5957             XkbComputeGetCompatMapReplySize(new->compat, &crep);
5958             rep.length += SIZEOF(xGenericReply) / 4 + crep.length;
5959         }
5960         if (new->indicators == NULL)
5961             rep.reported &= ~XkbGBN_IndicatorMapMask;
5962         else if (rep.reported & XkbGBN_IndicatorMapMask) {
5963             irep.type = X_Reply;
5964             irep.deviceID = dev->id;
5965             irep.sequenceNumber = client->sequence;
5966             irep.length = 0;
5967             irep.which = XkbAllIndicatorsMask;
5968             XkbComputeGetIndicatorMapReplySize(new->indicators, &irep);
5969             rep.length += SIZEOF(xGenericReply) / 4 + irep.length;
5970         }
5971         if (new->names == NULL)
5972             rep.reported &= ~(XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask);
5973         else if (rep.reported & (XkbGBN_OtherNamesMask | XkbGBN_KeyNamesMask)) {
5974             nrep.type = X_Reply;
5975             nrep.deviceID = dev->id;
5976             nrep.sequenceNumber = client->sequence;
5977             nrep.length = 0;
5978             nrep.minKeyCode = new->min_key_code;
5979             nrep.maxKeyCode = new->max_key_code;
5980             if (rep.reported & XkbGBN_OtherNamesMask) {
5981                 nrep.which = XkbAllNamesMask;
5982                 if (new->map != NULL)
5983                     nrep.nTypes = new->map->num_types;
5984                 else
5985                     nrep.nTypes = 0;
5986                 nrep.nKTLevels = 0;
5987                 nrep.groupNames = XkbAllGroupsMask;
5988                 nrep.virtualMods = XkbAllVirtualModsMask;
5989                 nrep.indicators = XkbAllIndicatorsMask;
5990                 nrep.nRadioGroups = new->names->num_rg;
5991             }
5992             else {
5993                 nrep.which = 0;
5994                 nrep.nTypes = 0;
5995                 nrep.nKTLevels = 0;
5996                 nrep.groupNames = 0;
5997                 nrep.virtualMods = 0;
5998                 nrep.indicators = 0;
5999                 nrep.nRadioGroups = 0;
6000             }
6001             if (rep.reported & XkbGBN_KeyNamesMask) {
6002                 nrep.which |= XkbKeyNamesMask;
6003                 nrep.firstKey = new->min_key_code;
6004                 nrep.nKeys = XkbNumKeys(new);
6005                 nrep.nKeyAliases = new->names->num_key_aliases;
6006                 if (nrep.nKeyAliases)
6007                     nrep.which |= XkbKeyAliasesMask;
6008             }
6009             else {
6010                 nrep.which &= ~(XkbKeyNamesMask | XkbKeyAliasesMask);
6011                 nrep.firstKey = nrep.nKeys = 0;
6012                 nrep.nKeyAliases = 0;
6013             }
6014             XkbComputeGetNamesReplySize(new, &nrep);
6015             rep.length += SIZEOF(xGenericReply) / 4 + nrep.length;
6016         }
6017         if (new->geom == NULL)
6018             rep.reported &= ~XkbGBN_GeometryMask;
6019         else if (rep.reported & XkbGBN_GeometryMask) {
6020             grep.type = X_Reply;
6021             grep.deviceID = dev->id;
6022             grep.sequenceNumber = client->sequence;
6023             grep.length = 0;
6024             grep.found = TRUE;
6025             grep.pad = 0;
6026             grep.widthMM = grep.heightMM = 0;
6027             grep.nProperties = grep.nColors = grep.nShapes = 0;
6028             grep.nSections = grep.nDoodads = 0;
6029             grep.baseColorNdx = grep.labelColorNdx = 0;
6030             XkbComputeGetGeometryReplySize(new->geom, &grep, None);
6031             rep.length += SIZEOF(xGenericReply) / 4 + grep.length;
6032         }
6033     }
6034 
6035     reported = rep.reported;
6036     if (client->swapped) {
6037         swaps(&rep.sequenceNumber);
6038         swapl(&rep.length);
6039         swaps(&rep.found);
6040         swaps(&rep.reported);
6041     }
6042     WriteToClient(client, SIZEOF(xkbGetKbdByNameReply), &rep);
6043     if (reported & (XkbGBN_SymbolsMask | XkbGBN_TypesMask))
6044         XkbSendMap(client, new, &mrep);
6045     if (reported & XkbGBN_CompatMapMask)
6046         XkbSendCompatMap(client, new->compat, &crep);
6047     if (reported & XkbGBN_IndicatorMapMask)
6048         XkbSendIndicatorMap(client, new->indicators, &irep);
6049     if (reported & (XkbGBN_KeyNamesMask | XkbGBN_OtherNamesMask))
6050         XkbSendNames(client, new, &nrep);
6051     if (reported & XkbGBN_GeometryMask)
6052         XkbSendGeometry(client, new->geom, &grep, FALSE);
6053     if (rep.loaded) {
6054         XkbDescPtr old_xkb;
6055         xkbNewKeyboardNotify nkn;
6056 
6057         old_xkb = xkb;
6058         xkb = new;
6059         dev->key->xkbInfo->desc = xkb;
6060         new = old_xkb;          /* so it'll get freed automatically */
6061 
6062         XkbCopyControls(xkb, old_xkb);
6063 
6064         nkn.deviceID = nkn.oldDeviceID = dev->id;
6065         nkn.minKeyCode = new->min_key_code;
6066         nkn.maxKeyCode = new->max_key_code;
6067         nkn.oldMinKeyCode = xkb->min_key_code;
6068         nkn.oldMaxKeyCode = xkb->max_key_code;
6069         nkn.requestMajor = XkbReqCode;
6070         nkn.requestMinor = X_kbGetKbdByName;
6071         nkn.changed = XkbNKN_KeycodesMask;
6072         if (geom_changed)
6073             nkn.changed |= XkbNKN_GeometryMask;
6074         XkbSendNewKeyboardNotify(dev, &nkn);
6075 
6076         /* Update the map and LED info on the device itself, as well as
6077          * any slaves if it's an MD, or its MD if it's an SD and was the
6078          * last device used on that MD. */
6079         for (tmpd = inputInfo.devices; tmpd; tmpd = tmpd->next) {
6080             if (tmpd != dev && GetMaster(tmpd, MASTER_KEYBOARD) != dev &&
6081                 (tmpd != master || dev != master->lastSlave))
6082                 continue;
6083 
6084             if (tmpd != dev)
6085                 XkbDeviceApplyKeymap(tmpd, xkb);
6086 
6087             if (tmpd->kbdfeed && tmpd->kbdfeed->xkb_sli) {
6088                 old_sli = tmpd->kbdfeed->xkb_sli;
6089                 tmpd->kbdfeed->xkb_sli = NULL;
6090                 sli = XkbAllocSrvLedInfo(tmpd, tmpd->kbdfeed, NULL, 0);
6091                 if (sli) {
6092                     sli->explicitState = old_sli->explicitState;
6093                     sli->effectiveState = old_sli->effectiveState;
6094                 }
6095                 tmpd->kbdfeed->xkb_sli = sli;
6096                 XkbFreeSrvLedInfo(old_sli);
6097             }
6098         }
6099     }
6100     if ((new != NULL) && (new != xkb)) {
6101         XkbFreeKeyboard(new, XkbAllComponentsMask, TRUE);
6102         new = NULL;
6103     }
6104     XkbFreeComponentNames(&names, FALSE);
6105     XkbSetCauseXkbReq(&cause, X_kbGetKbdByName, client);
6106     XkbUpdateAllDeviceIndicators(NULL, &cause);
6107 
6108     return Success;
6109 }
6110 
6111 /***====================================================================***/
6112 
6113 static int
ComputeDeviceLedInfoSize(DeviceIntPtr dev,unsigned int what,XkbSrvLedInfoPtr sli)6114 ComputeDeviceLedInfoSize(DeviceIntPtr dev,
6115                          unsigned int what, XkbSrvLedInfoPtr sli)
6116 {
6117     int nNames, nMaps;
6118     register unsigned n, bit;
6119 
6120     if (sli == NULL)
6121         return 0;
6122     nNames = nMaps = 0;
6123     if ((what & XkbXI_IndicatorNamesMask) == 0)
6124         sli->namesPresent = 0;
6125     if ((what & XkbXI_IndicatorMapsMask) == 0)
6126         sli->mapsPresent = 0;
6127 
6128     for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6129         if (sli->names && sli->names[n] != None) {
6130             sli->namesPresent |= bit;
6131             nNames++;
6132         }
6133         if (sli->maps && XkbIM_InUse(&sli->maps[n])) {
6134             sli->mapsPresent |= bit;
6135             nMaps++;
6136         }
6137     }
6138     return (nNames * 4) + (nMaps * SIZEOF(xkbIndicatorMapWireDesc));
6139 }
6140 
6141 static int
CheckDeviceLedFBs(DeviceIntPtr dev,int class,int id,xkbGetDeviceInfoReply * rep,ClientPtr client)6142 CheckDeviceLedFBs(DeviceIntPtr dev,
6143                   int class,
6144                   int id, xkbGetDeviceInfoReply * rep, ClientPtr client)
6145 {
6146     int nFBs = 0;
6147     int length = 0;
6148     Bool classOk;
6149 
6150     if (class == XkbDfltXIClass) {
6151         if (dev->kbdfeed)
6152             class = KbdFeedbackClass;
6153         else if (dev->leds)
6154             class = LedFeedbackClass;
6155         else {
6156             client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6157             return XkbKeyboardErrorCode;
6158         }
6159     }
6160     classOk = FALSE;
6161     if ((dev->kbdfeed) &&
6162         ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6163         KbdFeedbackPtr kf;
6164 
6165         classOk = TRUE;
6166         for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6167             if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6168                 (id != kf->ctrl.id))
6169                 continue;
6170             nFBs++;
6171             length += SIZEOF(xkbDeviceLedsWireDesc);
6172             if (!kf->xkb_sli)
6173                 kf->xkb_sli = XkbAllocSrvLedInfo(dev, kf, NULL, 0);
6174             length += ComputeDeviceLedInfoSize(dev, rep->present, kf->xkb_sli);
6175             if (id != XkbAllXIIds)
6176                 break;
6177         }
6178     }
6179     if ((dev->leds) &&
6180         ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6181         LedFeedbackPtr lf;
6182 
6183         classOk = TRUE;
6184         for (lf = dev->leds; (lf); lf = lf->next) {
6185             if ((id != XkbAllXIIds) && (id != XkbDfltXIId) &&
6186                 (id != lf->ctrl.id))
6187                 continue;
6188             nFBs++;
6189             length += SIZEOF(xkbDeviceLedsWireDesc);
6190             if (!lf->xkb_sli)
6191                 lf->xkb_sli = XkbAllocSrvLedInfo(dev, NULL, lf, 0);
6192             length += ComputeDeviceLedInfoSize(dev, rep->present, lf->xkb_sli);
6193             if (id != XkbAllXIIds)
6194                 break;
6195         }
6196     }
6197     if (nFBs > 0) {
6198         rep->nDeviceLedFBs = nFBs;
6199         rep->length += (length / 4);
6200         return Success;
6201     }
6202     if (classOk)
6203         client->errorValue = _XkbErrCode2(XkbErr_BadId, id);
6204     else
6205         client->errorValue = _XkbErrCode2(XkbErr_BadClass, class);
6206     return XkbKeyboardErrorCode;
6207 }
6208 
6209 static int
SendDeviceLedInfo(XkbSrvLedInfoPtr sli,ClientPtr client)6210 SendDeviceLedInfo(XkbSrvLedInfoPtr sli, ClientPtr client)
6211 {
6212     xkbDeviceLedsWireDesc wire;
6213     int length;
6214 
6215     length = 0;
6216     wire.ledClass = sli->class;
6217     wire.ledID = sli->id;
6218     wire.namesPresent = sli->namesPresent;
6219     wire.mapsPresent = sli->mapsPresent;
6220     wire.physIndicators = sli->physIndicators;
6221     wire.state = sli->effectiveState;
6222     if (client->swapped) {
6223         swaps(&wire.ledClass);
6224         swaps(&wire.ledID);
6225         swapl(&wire.namesPresent);
6226         swapl(&wire.mapsPresent);
6227         swapl(&wire.physIndicators);
6228         swapl(&wire.state);
6229     }
6230     WriteToClient(client, SIZEOF(xkbDeviceLedsWireDesc), &wire);
6231     length += SIZEOF(xkbDeviceLedsWireDesc);
6232     if (sli->namesPresent | sli->mapsPresent) {
6233         register unsigned i, bit;
6234 
6235         if (sli->namesPresent) {
6236             CARD32 awire;
6237 
6238             for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6239                 if (sli->namesPresent & bit) {
6240                     awire = (CARD32) sli->names[i];
6241                     if (client->swapped) {
6242                         swapl(&awire);
6243                     }
6244                     WriteToClient(client, 4, &awire);
6245                     length += 4;
6246                 }
6247             }
6248         }
6249         if (sli->mapsPresent) {
6250             for (i = 0, bit = 1; i < XkbNumIndicators; i++, bit <<= 1) {
6251                 xkbIndicatorMapWireDesc iwire;
6252 
6253                 if (sli->mapsPresent & bit) {
6254                     iwire.flags = sli->maps[i].flags;
6255                     iwire.whichGroups = sli->maps[i].which_groups;
6256                     iwire.groups = sli->maps[i].groups;
6257                     iwire.whichMods = sli->maps[i].which_mods;
6258                     iwire.mods = sli->maps[i].mods.mask;
6259                     iwire.realMods = sli->maps[i].mods.real_mods;
6260                     iwire.virtualMods = sli->maps[i].mods.vmods;
6261                     iwire.ctrls = sli->maps[i].ctrls;
6262                     if (client->swapped) {
6263                         swaps(&iwire.virtualMods);
6264                         swapl(&iwire.ctrls);
6265                     }
6266                     WriteToClient(client, SIZEOF(xkbIndicatorMapWireDesc),
6267                                   &iwire);
6268                     length += SIZEOF(xkbIndicatorMapWireDesc);
6269                 }
6270             }
6271         }
6272     }
6273     return length;
6274 }
6275 
6276 static int
SendDeviceLedFBs(DeviceIntPtr dev,int class,int id,unsigned wantLength,ClientPtr client)6277 SendDeviceLedFBs(DeviceIntPtr dev,
6278                  int class, int id, unsigned wantLength, ClientPtr client)
6279 {
6280     int length = 0;
6281 
6282     if (class == XkbDfltXIClass) {
6283         if (dev->kbdfeed)
6284             class = KbdFeedbackClass;
6285         else if (dev->leds)
6286             class = LedFeedbackClass;
6287     }
6288     if ((dev->kbdfeed) &&
6289         ((class == KbdFeedbackClass) || (class == XkbAllXIClasses))) {
6290         KbdFeedbackPtr kf;
6291 
6292         for (kf = dev->kbdfeed; (kf); kf = kf->next) {
6293             if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6294                 (id == kf->ctrl.id)) {
6295                 length += SendDeviceLedInfo(kf->xkb_sli, client);
6296                 if (id != XkbAllXIIds)
6297                     break;
6298             }
6299         }
6300     }
6301     if ((dev->leds) &&
6302         ((class == LedFeedbackClass) || (class == XkbAllXIClasses))) {
6303         LedFeedbackPtr lf;
6304 
6305         for (lf = dev->leds; (lf); lf = lf->next) {
6306             if ((id == XkbAllXIIds) || (id == XkbDfltXIId) ||
6307                 (id == lf->ctrl.id)) {
6308                 length += SendDeviceLedInfo(lf->xkb_sli, client);
6309                 if (id != XkbAllXIIds)
6310                     break;
6311             }
6312         }
6313     }
6314     if (length == wantLength)
6315         return Success;
6316     else
6317         return BadLength;
6318 }
6319 
6320 int
ProcXkbGetDeviceInfo(ClientPtr client)6321 ProcXkbGetDeviceInfo(ClientPtr client)
6322 {
6323     DeviceIntPtr dev;
6324     xkbGetDeviceInfoReply rep;
6325     int status, nDeviceLedFBs;
6326     unsigned length, nameLen;
6327     CARD16 ledClass, ledID;
6328     unsigned wanted;
6329     char *str;
6330 
6331     REQUEST(xkbGetDeviceInfoReq);
6332     REQUEST_SIZE_MATCH(xkbGetDeviceInfoReq);
6333 
6334     if (!(client->xkbClientFlags & _XkbClientInitialized))
6335         return BadAccess;
6336 
6337     wanted = stuff->wanted;
6338 
6339     CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixGetAttrAccess);
6340     CHK_MASK_LEGAL(0x01, wanted, XkbXI_AllDeviceFeaturesMask);
6341 
6342     if ((!dev->button) || ((stuff->nBtns < 1) && (!stuff->allBtns)))
6343         wanted &= ~XkbXI_ButtonActionsMask;
6344     if ((!dev->kbdfeed) && (!dev->leds))
6345         wanted &= ~XkbXI_IndicatorsMask;
6346 
6347     nameLen = XkbSizeCountedString(dev->name);
6348     rep = (xkbGetDeviceInfoReply) {
6349         .type = X_Reply,
6350         .deviceID = dev->id,
6351         .sequenceNumber = client->sequence,
6352         .length = nameLen / 4,
6353         .present = wanted,
6354         .supported = XkbXI_AllDeviceFeaturesMask,
6355         .unsupported = 0,
6356         .nDeviceLedFBs = 0,
6357         .firstBtnWanted = 0,
6358         .nBtnsWanted = 0,
6359         .firstBtnRtrn = 0,
6360         .nBtnsRtrn = 0,
6361         .totalBtns = dev->button ? dev->button->numButtons : 0,
6362         .hasOwnState = (dev->key && dev->key->xkbInfo),
6363         .dfltKbdFB = dev->kbdfeed ? dev->kbdfeed->ctrl.id : XkbXINone,
6364         .dfltLedFB = dev->leds ? dev->leds->ctrl.id : XkbXINone,
6365         .devType = dev->xinput_type
6366     };
6367 
6368     ledClass = stuff->ledClass;
6369     ledID = stuff->ledID;
6370 
6371     if (wanted & XkbXI_ButtonActionsMask) {
6372         if (stuff->allBtns) {
6373             stuff->firstBtn = 0;
6374             stuff->nBtns = dev->button->numButtons;
6375         }
6376 
6377         if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6378             client->errorValue = _XkbErrCode4(0x02, dev->button->numButtons,
6379                                               stuff->firstBtn, stuff->nBtns);
6380             return BadValue;
6381         }
6382         else {
6383             rep.firstBtnWanted = stuff->firstBtn;
6384             rep.nBtnsWanted = stuff->nBtns;
6385             if (dev->button->xkb_acts != NULL) {
6386                 XkbAction *act;
6387                 register int i;
6388 
6389                 rep.firstBtnRtrn = stuff->firstBtn;
6390                 rep.nBtnsRtrn = stuff->nBtns;
6391                 act = &dev->button->xkb_acts[rep.firstBtnWanted];
6392                 for (i = 0; i < rep.nBtnsRtrn; i++, act++) {
6393                     if (act->type != XkbSA_NoAction)
6394                         break;
6395                 }
6396                 rep.firstBtnRtrn += i;
6397                 rep.nBtnsRtrn -= i;
6398                 act =
6399                     &dev->button->xkb_acts[rep.firstBtnRtrn + rep.nBtnsRtrn -
6400                                            1];
6401                 for (i = 0; i < rep.nBtnsRtrn; i++, act--) {
6402                     if (act->type != XkbSA_NoAction)
6403                         break;
6404                 }
6405                 rep.nBtnsRtrn -= i;
6406             }
6407             rep.length += (rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc)) / 4;
6408         }
6409     }
6410 
6411     if (wanted & XkbXI_IndicatorsMask) {
6412         status = CheckDeviceLedFBs(dev, ledClass, ledID, &rep, client);
6413         if (status != Success)
6414             return status;
6415     }
6416     length = rep.length * 4;
6417     nDeviceLedFBs = rep.nDeviceLedFBs;
6418     if (client->swapped) {
6419         swaps(&rep.sequenceNumber);
6420         swapl(&rep.length);
6421         swaps(&rep.present);
6422         swaps(&rep.supported);
6423         swaps(&rep.unsupported);
6424         swaps(&rep.nDeviceLedFBs);
6425         swaps(&rep.dfltKbdFB);
6426         swaps(&rep.dfltLedFB);
6427         swapl(&rep.devType);
6428     }
6429     WriteToClient(client, SIZEOF(xkbGetDeviceInfoReply), &rep);
6430 
6431     str = malloc(nameLen);
6432     if (!str)
6433         return BadAlloc;
6434     XkbWriteCountedString(str, dev->name, client->swapped);
6435     WriteToClient(client, nameLen, str);
6436     free(str);
6437     length -= nameLen;
6438 
6439     if (rep.nBtnsRtrn > 0) {
6440         int sz;
6441         xkbActionWireDesc *awire;
6442 
6443         sz = rep.nBtnsRtrn * SIZEOF(xkbActionWireDesc);
6444         awire = (xkbActionWireDesc *) &dev->button->xkb_acts[rep.firstBtnRtrn];
6445         WriteToClient(client, sz, awire);
6446         length -= sz;
6447     }
6448     if (nDeviceLedFBs > 0) {
6449         status = SendDeviceLedFBs(dev, ledClass, ledID, length, client);
6450         if (status != Success)
6451             return status;
6452     }
6453     else if (length != 0) {
6454         ErrorF("[xkb] Internal Error!  BadLength in ProcXkbGetDeviceInfo\n");
6455         ErrorF("[xkb]                  Wrote %d fewer bytes than expected\n",
6456                length);
6457         return BadLength;
6458     }
6459     return Success;
6460 }
6461 
6462 static char *
CheckSetDeviceIndicators(char * wire,DeviceIntPtr dev,int num,int * status_rtrn,ClientPtr client)6463 CheckSetDeviceIndicators(char *wire,
6464                          DeviceIntPtr dev,
6465                          int num, int *status_rtrn, ClientPtr client)
6466 {
6467     xkbDeviceLedsWireDesc *ledWire;
6468     int i;
6469     XkbSrvLedInfoPtr sli;
6470 
6471     ledWire = (xkbDeviceLedsWireDesc *) wire;
6472     for (i = 0; i < num; i++) {
6473         if (client->swapped) {
6474             swaps(&ledWire->ledClass);
6475             swaps(&ledWire->ledID);
6476             swapl(&ledWire->namesPresent);
6477             swapl(&ledWire->mapsPresent);
6478             swapl(&ledWire->physIndicators);
6479         }
6480 
6481         sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6482                                 XkbXI_IndicatorsMask);
6483         if (sli != NULL) {
6484             register int n;
6485             register unsigned bit;
6486             int nMaps, nNames;
6487             CARD32 *atomWire;
6488             xkbIndicatorMapWireDesc *mapWire;
6489 
6490             nMaps = nNames = 0;
6491             for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6492                 if (ledWire->namesPresent & bit)
6493                     nNames++;
6494                 if (ledWire->mapsPresent & bit)
6495                     nMaps++;
6496             }
6497             atomWire = (CARD32 *) &ledWire[1];
6498             if (nNames > 0) {
6499                 for (n = 0; n < nNames; n++) {
6500                     if (client->swapped) {
6501                         swapl(atomWire);
6502                     }
6503                     CHK_ATOM_OR_NONE3(((Atom) (*atomWire)), client->errorValue,
6504                                       *status_rtrn, NULL);
6505                     atomWire++;
6506                 }
6507             }
6508             mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6509             if (nMaps > 0) {
6510                 for (n = 0; n < nMaps; n++) {
6511                     if (client->swapped) {
6512                         swaps(&mapWire->virtualMods);
6513                         swapl(&mapWire->ctrls);
6514                     }
6515                     CHK_MASK_LEGAL3(0x21, mapWire->whichGroups,
6516                                     XkbIM_UseAnyGroup,
6517                                     client->errorValue, *status_rtrn, NULL);
6518                     CHK_MASK_LEGAL3(0x22, mapWire->whichMods, XkbIM_UseAnyMods,
6519                                     client->errorValue, *status_rtrn, NULL);
6520                     mapWire++;
6521                 }
6522             }
6523             ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6524         }
6525         else {
6526             /* SHOULD NEVER HAPPEN */
6527             return (char *) ledWire;
6528         }
6529     }
6530     return (char *) ledWire;
6531 }
6532 
6533 static char *
SetDeviceIndicators(char * wire,DeviceIntPtr dev,unsigned changed,int num,int * status_rtrn,ClientPtr client,xkbExtensionDeviceNotify * ev)6534 SetDeviceIndicators(char *wire,
6535                     DeviceIntPtr dev,
6536                     unsigned changed,
6537                     int num,
6538                     int *status_rtrn,
6539                     ClientPtr client, xkbExtensionDeviceNotify * ev)
6540 {
6541     xkbDeviceLedsWireDesc *ledWire;
6542     int i;
6543     XkbEventCauseRec cause;
6544     unsigned namec, mapc, statec;
6545     xkbExtensionDeviceNotify ed;
6546     XkbChangesRec changes;
6547     DeviceIntPtr kbd;
6548 
6549     memset((char *) &ed, 0, sizeof(xkbExtensionDeviceNotify));
6550     memset((char *) &changes, 0, sizeof(XkbChangesRec));
6551     XkbSetCauseXkbReq(&cause, X_kbSetDeviceInfo, client);
6552     ledWire = (xkbDeviceLedsWireDesc *) wire;
6553     for (i = 0; i < num; i++) {
6554         register int n;
6555         register unsigned bit;
6556         CARD32 *atomWire;
6557         xkbIndicatorMapWireDesc *mapWire;
6558         XkbSrvLedInfoPtr sli;
6559 
6560         namec = mapc = statec = 0;
6561         sli = XkbFindSrvLedInfo(dev, ledWire->ledClass, ledWire->ledID,
6562                                 XkbXI_IndicatorMapsMask);
6563         if (!sli) {
6564             /* SHOULD NEVER HAPPEN!! */
6565             return (char *) ledWire;
6566         }
6567 
6568         atomWire = (CARD32 *) &ledWire[1];
6569         if (changed & XkbXI_IndicatorNamesMask) {
6570             namec = sli->namesPresent | ledWire->namesPresent;
6571             memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6572         }
6573         if (ledWire->namesPresent) {
6574             sli->namesPresent = ledWire->namesPresent;
6575             memset((char *) sli->names, 0, XkbNumIndicators * sizeof(Atom));
6576             for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6577                 if (ledWire->namesPresent & bit) {
6578                     sli->names[n] = (Atom) *atomWire;
6579                     if (sli->names[n] == None)
6580                         ledWire->namesPresent &= ~bit;
6581                     atomWire++;
6582                 }
6583             }
6584         }
6585         mapWire = (xkbIndicatorMapWireDesc *) atomWire;
6586         if (changed & XkbXI_IndicatorMapsMask) {
6587             mapc = sli->mapsPresent | ledWire->mapsPresent;
6588             sli->mapsPresent = ledWire->mapsPresent;
6589             memset((char *) sli->maps, 0,
6590                    XkbNumIndicators * sizeof(XkbIndicatorMapRec));
6591         }
6592         if (ledWire->mapsPresent) {
6593             for (n = 0, bit = 1; n < XkbNumIndicators; n++, bit <<= 1) {
6594                 if (ledWire->mapsPresent & bit) {
6595                     sli->maps[n].flags = mapWire->flags;
6596                     sli->maps[n].which_groups = mapWire->whichGroups;
6597                     sli->maps[n].groups = mapWire->groups;
6598                     sli->maps[n].which_mods = mapWire->whichMods;
6599                     sli->maps[n].mods.mask = mapWire->mods;
6600                     sli->maps[n].mods.real_mods = mapWire->realMods;
6601                     sli->maps[n].mods.vmods = mapWire->virtualMods;
6602                     sli->maps[n].ctrls = mapWire->ctrls;
6603                     mapWire++;
6604                 }
6605             }
6606         }
6607         if (changed & XkbXI_IndicatorStateMask) {
6608             statec = sli->effectiveState ^ ledWire->state;
6609             sli->explicitState &= ~statec;
6610             sli->explicitState |= (ledWire->state & statec);
6611         }
6612         if (namec)
6613             XkbApplyLedNameChanges(dev, sli, namec, &ed, &changes, &cause);
6614         if (mapc)
6615             XkbApplyLedMapChanges(dev, sli, mapc, &ed, &changes, &cause);
6616         if (statec)
6617             XkbApplyLedStateChanges(dev, sli, statec, &ed, &changes, &cause);
6618 
6619         kbd = dev;
6620         if ((sli->flags & XkbSLI_HasOwnState) == 0)
6621             kbd = inputInfo.keyboard;
6622 
6623         XkbFlushLedEvents(dev, kbd, sli, &ed, &changes, &cause);
6624         ledWire = (xkbDeviceLedsWireDesc *) mapWire;
6625     }
6626     return (char *) ledWire;
6627 }
6628 
6629 static int
_XkbSetDeviceInfo(ClientPtr client,DeviceIntPtr dev,xkbSetDeviceInfoReq * stuff)6630 _XkbSetDeviceInfo(ClientPtr client, DeviceIntPtr dev,
6631                   xkbSetDeviceInfoReq * stuff)
6632 {
6633     char *wire;
6634 
6635     wire = (char *) &stuff[1];
6636     if (stuff->change & XkbXI_ButtonActionsMask) {
6637         if (!dev->button) {
6638             client->errorValue = _XkbErrCode2(XkbErr_BadClass, ButtonClass);
6639             return XkbKeyboardErrorCode;
6640         }
6641         if ((stuff->firstBtn + stuff->nBtns) > dev->button->numButtons) {
6642             client->errorValue =
6643                 _XkbErrCode4(0x02, stuff->firstBtn, stuff->nBtns,
6644                              dev->button->numButtons);
6645             return BadMatch;
6646         }
6647         wire += (stuff->nBtns * SIZEOF(xkbActionWireDesc));
6648     }
6649     if (stuff->change & XkbXI_IndicatorsMask) {
6650         int status = Success;
6651 
6652         wire = CheckSetDeviceIndicators(wire, dev, stuff->nDeviceLedFBs,
6653                                         &status, client);
6654         if (status != Success)
6655             return status;
6656     }
6657     if (((wire - ((char *) stuff)) / 4) != stuff->length)
6658         return BadLength;
6659 
6660     return Success;
6661 }
6662 
6663 static int
_XkbSetDeviceInfoCheck(ClientPtr client,DeviceIntPtr dev,xkbSetDeviceInfoReq * stuff)6664 _XkbSetDeviceInfoCheck(ClientPtr client, DeviceIntPtr dev,
6665                        xkbSetDeviceInfoReq * stuff)
6666 {
6667     char *wire;
6668     xkbExtensionDeviceNotify ed;
6669 
6670     memset((char *) &ed, 0, SIZEOF(xkbExtensionDeviceNotify));
6671     ed.deviceID = dev->id;
6672     wire = (char *) &stuff[1];
6673     if (stuff->change & XkbXI_ButtonActionsMask) {
6674         int nBtns, sz, i;
6675         XkbAction *acts;
6676         DeviceIntPtr kbd;
6677 
6678         nBtns = dev->button->numButtons;
6679         acts = dev->button->xkb_acts;
6680         if (acts == NULL) {
6681             acts = calloc(nBtns, sizeof(XkbAction));
6682             if (!acts)
6683                 return BadAlloc;
6684             dev->button->xkb_acts = acts;
6685         }
6686         sz = stuff->nBtns * SIZEOF(xkbActionWireDesc);
6687         memcpy((char *) &acts[stuff->firstBtn], (char *) wire, sz);
6688         wire += sz;
6689         ed.reason |= XkbXI_ButtonActionsMask;
6690         ed.firstBtn = stuff->firstBtn;
6691         ed.nBtns = stuff->nBtns;
6692 
6693         if (dev->key)
6694             kbd = dev;
6695         else
6696             kbd = inputInfo.keyboard;
6697         acts = &dev->button->xkb_acts[stuff->firstBtn];
6698         for (i = 0; i < stuff->nBtns; i++, acts++) {
6699             if (acts->type != XkbSA_NoAction)
6700                 XkbSetActionKeyMods(kbd->key->xkbInfo->desc, acts, 0);
6701         }
6702     }
6703     if (stuff->change & XkbXI_IndicatorsMask) {
6704         int status = Success;
6705 
6706         wire = SetDeviceIndicators(wire, dev, stuff->change,
6707                                    stuff->nDeviceLedFBs, &status, client, &ed);
6708         if (status != Success)
6709             return status;
6710     }
6711     if ((stuff->change) && (ed.reason))
6712         XkbSendExtensionDeviceNotify(dev, client, &ed);
6713     return Success;
6714 }
6715 
6716 int
ProcXkbSetDeviceInfo(ClientPtr client)6717 ProcXkbSetDeviceInfo(ClientPtr client)
6718 {
6719     DeviceIntPtr dev;
6720     int rc;
6721 
6722     REQUEST(xkbSetDeviceInfoReq);
6723     REQUEST_AT_LEAST_SIZE(xkbSetDeviceInfoReq);
6724 
6725     if (!(client->xkbClientFlags & _XkbClientInitialized))
6726         return BadAccess;
6727 
6728     CHK_ANY_DEVICE(dev, stuff->deviceSpec, client, DixManageAccess);
6729     CHK_MASK_LEGAL(0x01, stuff->change, XkbXI_AllFeaturesMask);
6730 
6731     rc = _XkbSetDeviceInfoCheck(client, dev, stuff);
6732 
6733     if (rc != Success)
6734         return rc;
6735 
6736     if (stuff->deviceSpec == XkbUseCoreKbd ||
6737         stuff->deviceSpec == XkbUseCorePtr) {
6738         DeviceIntPtr other;
6739 
6740         for (other = inputInfo.devices; other; other = other->next) {
6741             if (((other != dev) && !IsMaster(other) &&
6742                  GetMaster(other, MASTER_KEYBOARD) == dev) &&
6743                 ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6744                  (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6745                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6746                               DixManageAccess);
6747                 if (rc == Success) {
6748                     rc = _XkbSetDeviceInfoCheck(client, other, stuff);
6749                     if (rc != Success)
6750                         return rc;
6751                 }
6752             }
6753         }
6754     }
6755 
6756     /* checks done, apply */
6757     rc = _XkbSetDeviceInfo(client, dev, stuff);
6758     if (rc != Success)
6759         return rc;
6760 
6761     if (stuff->deviceSpec == XkbUseCoreKbd ||
6762         stuff->deviceSpec == XkbUseCorePtr) {
6763         DeviceIntPtr other;
6764 
6765         for (other = inputInfo.devices; other; other = other->next) {
6766             if (((other != dev) && !IsMaster(other) &&
6767                  GetMaster(other, MASTER_KEYBOARD) == dev) &&
6768                 ((stuff->deviceSpec == XkbUseCoreKbd && other->key) ||
6769                  (stuff->deviceSpec == XkbUseCorePtr && other->button))) {
6770                 rc = XaceHook(XACE_DEVICE_ACCESS, client, other,
6771                               DixManageAccess);
6772                 if (rc == Success) {
6773                     rc = _XkbSetDeviceInfo(client, other, stuff);
6774                     if (rc != Success)
6775                         return rc;
6776                 }
6777             }
6778         }
6779     }
6780 
6781     return Success;
6782 }
6783 
6784 /***====================================================================***/
6785 
6786 int
ProcXkbSetDebuggingFlags(ClientPtr client)6787 ProcXkbSetDebuggingFlags(ClientPtr client)
6788 {
6789     CARD32 newFlags, newCtrls, extraLength;
6790     xkbSetDebuggingFlagsReply rep;
6791     int rc;
6792 
6793     REQUEST(xkbSetDebuggingFlagsReq);
6794     REQUEST_AT_LEAST_SIZE(xkbSetDebuggingFlagsReq);
6795 
6796     rc = XaceHook(XACE_SERVER_ACCESS, client, DixDebugAccess);
6797     if (rc != Success)
6798         return rc;
6799 
6800     newFlags = xkbDebugFlags & (~stuff->affectFlags);
6801     newFlags |= (stuff->flags & stuff->affectFlags);
6802     newCtrls = xkbDebugCtrls & (~stuff->affectCtrls);
6803     newCtrls |= (stuff->ctrls & stuff->affectCtrls);
6804     if (xkbDebugFlags || newFlags || stuff->msgLength) {
6805         ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",
6806                (long) newFlags);
6807         if (newCtrls != xkbDebugCtrls)
6808             ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",
6809                    (long) newCtrls);
6810     }
6811     extraLength = (stuff->length << 2) - sz_xkbSetDebuggingFlagsReq;
6812     if (stuff->msgLength > 0) {
6813         char *msg;
6814 
6815         if (extraLength < XkbPaddedSize(stuff->msgLength)) {
6816             ErrorF
6817                 ("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n",
6818                  stuff->msgLength, (long) extraLength,
6819                  XkbPaddedSize(stuff->msgLength));
6820             return BadLength;
6821         }
6822         msg = (char *) &stuff[1];
6823         if (msg[stuff->msgLength - 1] != '\0') {
6824             ErrorF("[xkb] XkbDebug: message not null-terminated\n");
6825             return BadValue;
6826         }
6827         ErrorF("[xkb] XkbDebug: %s\n", msg);
6828     }
6829     xkbDebugFlags = newFlags;
6830     xkbDebugCtrls = newCtrls;
6831 
6832     rep = (xkbSetDebuggingFlagsReply) {
6833         .type = X_Reply,
6834         .sequenceNumber = client->sequence,
6835         .length = 0,
6836         .currentFlags = newFlags,
6837         .currentCtrls = newCtrls,
6838         .supportedFlags = ~0,
6839         .supportedCtrls = ~0
6840     };
6841     if (client->swapped) {
6842         swaps(&rep.sequenceNumber);
6843         swapl(&rep.currentFlags);
6844         swapl(&rep.currentCtrls);
6845         swapl(&rep.supportedFlags);
6846         swapl(&rep.supportedCtrls);
6847     }
6848     WriteToClient(client, SIZEOF(xkbSetDebuggingFlagsReply), &rep);
6849     return Success;
6850 }
6851 
6852 /***====================================================================***/
6853 
6854 static int
ProcXkbDispatch(ClientPtr client)6855 ProcXkbDispatch(ClientPtr client)
6856 {
6857     REQUEST(xReq);
6858     switch (stuff->data) {
6859     case X_kbUseExtension:
6860         return ProcXkbUseExtension(client);
6861     case X_kbSelectEvents:
6862         return ProcXkbSelectEvents(client);
6863     case X_kbBell:
6864         return ProcXkbBell(client);
6865     case X_kbGetState:
6866         return ProcXkbGetState(client);
6867     case X_kbLatchLockState:
6868         return ProcXkbLatchLockState(client);
6869     case X_kbGetControls:
6870         return ProcXkbGetControls(client);
6871     case X_kbSetControls:
6872         return ProcXkbSetControls(client);
6873     case X_kbGetMap:
6874         return ProcXkbGetMap(client);
6875     case X_kbSetMap:
6876         return ProcXkbSetMap(client);
6877     case X_kbGetCompatMap:
6878         return ProcXkbGetCompatMap(client);
6879     case X_kbSetCompatMap:
6880         return ProcXkbSetCompatMap(client);
6881     case X_kbGetIndicatorState:
6882         return ProcXkbGetIndicatorState(client);
6883     case X_kbGetIndicatorMap:
6884         return ProcXkbGetIndicatorMap(client);
6885     case X_kbSetIndicatorMap:
6886         return ProcXkbSetIndicatorMap(client);
6887     case X_kbGetNamedIndicator:
6888         return ProcXkbGetNamedIndicator(client);
6889     case X_kbSetNamedIndicator:
6890         return ProcXkbSetNamedIndicator(client);
6891     case X_kbGetNames:
6892         return ProcXkbGetNames(client);
6893     case X_kbSetNames:
6894         return ProcXkbSetNames(client);
6895     case X_kbGetGeometry:
6896         return ProcXkbGetGeometry(client);
6897     case X_kbSetGeometry:
6898         return ProcXkbSetGeometry(client);
6899     case X_kbPerClientFlags:
6900         return ProcXkbPerClientFlags(client);
6901     case X_kbListComponents:
6902         return ProcXkbListComponents(client);
6903     case X_kbGetKbdByName:
6904         return ProcXkbGetKbdByName(client);
6905     case X_kbGetDeviceInfo:
6906         return ProcXkbGetDeviceInfo(client);
6907     case X_kbSetDeviceInfo:
6908         return ProcXkbSetDeviceInfo(client);
6909     case X_kbSetDebuggingFlags:
6910         return ProcXkbSetDebuggingFlags(client);
6911     default:
6912         return BadRequest;
6913     }
6914 }
6915 
6916 static int
XkbClientGone(void * data,XID id)6917 XkbClientGone(void *data, XID id)
6918 {
6919     DevicePtr pXDev = (DevicePtr) data;
6920 
6921     if (!XkbRemoveResourceClient(pXDev, id)) {
6922         ErrorF
6923             ("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n");
6924     }
6925     return 1;
6926 }
6927 
6928 void
XkbExtensionInit(void)6929 XkbExtensionInit(void)
6930 {
6931     ExtensionEntry *extEntry;
6932 
6933     RT_XKBCLIENT = CreateNewResourceType(XkbClientGone, "XkbClient");
6934     if (!RT_XKBCLIENT)
6935         return;
6936 
6937     if (!XkbInitPrivates())
6938         return;
6939 
6940     if ((extEntry = AddExtension(XkbName, XkbNumberEvents, XkbNumberErrors,
6941                                  ProcXkbDispatch, SProcXkbDispatch,
6942                                  NULL, StandardMinorOpcode))) {
6943         XkbReqCode = (unsigned char) extEntry->base;
6944         XkbEventBase = (unsigned char) extEntry->eventBase;
6945         XkbErrorBase = (unsigned char) extEntry->errorBase;
6946         XkbKeyboardErrorCode = XkbErrorBase + XkbKeyboard;
6947     }
6948     return;
6949 }
6950