Bug Summary

File:record/record.c
Location:line 2213, column 43
Description:Dereference of null pointer

Annotated Source Code

1
2/*
3
4Copyright 1995, 1998 The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be
13included in all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
19OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21OTHER DEALINGS IN THE SOFTWARE.
22
23Except as contained in this notice, the name of The Open Group shall
24not be used in advertising or otherwise to promote the sale, use or
25other dealings in this Software without prior written authorization
26from The Open Group.
27
28Author: David P. Wiggins, The Open Group
29
30This work benefited from earlier work done by Martha Zimet of NCD
31and Jim Haggerty of Metheus.
32
33*/
34
35#ifdef HAVE_DIX_CONFIG_H1
36#include <dix-config.h>
37#endif
38
39#include "dixstruct.h"
40#include "extnsionst.h"
41#include "extinit.h"
42#include <X11/extensions/recordproto.h>
43#include "set.h"
44#include "swaprep.h"
45#include "inputstr.h"
46#include "eventconvert.h"
47#include "scrnintstr.h"
48
49#include <stdio.h>
50#include <assert.h>
51
52#ifdef PANORAMIX1
53#include "globals.h"
54#include "panoramiX.h"
55#include "panoramiXsrv.h"
56#include "cursor.h"
57#endif
58
59#include "protocol-versions.h"
60
61static RESTYPE RTContext; /* internal resource type for Record contexts */
62
63/* How many bytes of protocol data to buffer in a context. Don't set to less
64 * than 32.
65 */
66#define REPLY_BUF_SIZE1024 1024
67
68/* Record Context structure */
69
70typedef struct {
71 XID id; /* resource id of context */
72 ClientPtr pRecordingClient; /* client that has context enabled */
73 struct _RecordClientsAndProtocolRec *pListOfRCAP; /* all registered info */
74 ClientPtr pBufClient; /* client whose protocol is in replyBuffer */
75 unsigned int continuedReply:1; /* recording a reply that is split up? */
76 char elemHeaders; /* element header flags (time/seq no.) */
77 char bufCategory; /* category of protocol in replyBuffer */
78 int numBufBytes; /* number of bytes in replyBuffer */
79 char replyBuffer[REPLY_BUF_SIZE1024]; /* buffered recorded protocol */
80 int inFlush; /* are we inside RecordFlushReplyBuffer */
81} RecordContextRec, *RecordContextPtr;
82
83/* RecordMinorOpRec - to hold minor opcode selections for extension requests
84 * and replies
85 */
86
87typedef union {
88 int count; /* first element of array: how many "major" structs to follow */
89 struct { /* rest of array elements are this */
90 short first; /* first major opcode */
91 short last; /* last major opcode */
92 RecordSetPtr pMinOpSet; /* minor opcode set for above major range */
93 } major;
94} RecordMinorOpRec, *RecordMinorOpPtr;
95
96/* RecordClientsAndProtocolRec, nicknamed RCAP - holds all the client and
97 * protocol selections passed in a single CreateContext or RegisterClients.
98 * Generally, a context will have one of these from the create and an
99 * additional one for each RegisterClients. RCAPs are freed when all their
100 * clients are unregistered.
101 */
102
103typedef struct _RecordClientsAndProtocolRec {
104 RecordContextPtr pContext; /* context that owns this RCAP */
105 struct _RecordClientsAndProtocolRec *pNextRCAP; /* next RCAP on context */
106 RecordSetPtr pRequestMajorOpSet; /* requests to record */
107 RecordMinorOpPtr pRequestMinOpInfo; /* extension requests to record */
108 RecordSetPtr pReplyMajorOpSet; /* replies to record */
109 RecordMinorOpPtr pReplyMinOpInfo; /* extension replies to record */
110 RecordSetPtr pDeviceEventSet; /* device events to record */
111 RecordSetPtr pDeliveredEventSet; /* delivered events to record */
112 RecordSetPtr pErrorSet; /* errors to record */
113 XID *pClientIDs; /* array of clients to record */
114 short numClients; /* number of clients in pClientIDs */
115 short sizeClients; /* size of pClientIDs array */
116 unsigned int clientStarted:1; /* record new client connections? */
117 unsigned int clientDied:1; /* record client disconnections? */
118 unsigned int clientIDsSeparatelyAllocated:1; /* pClientIDs malloced? */
119} RecordClientsAndProtocolRec, *RecordClientsAndProtocolPtr;
120
121/* how much bigger to make pRCAP->pClientIDs when reallocing */
122#define CLIENT_ARRAY_GROWTH_INCREMENT4 4
123
124/* counts the total number of RCAPs belonging to enabled contexts. */
125static int numEnabledRCAPs;
126
127/* void VERIFY_CONTEXT(RecordContextPtr, XID, ClientPtr)
128 * In the spirit of the VERIFY_* macros in dix.h, this macro fills in
129 * the context pointer if the given ID is a valid Record Context, else it
130 * returns an error.
131 */
132#define VERIFY_CONTEXT(_pContext, _contextid, _client){ int rc = dixLookupResourceByType((void **)&(_pContext),
_contextid, RTContext, _client, (1<<24)); if (rc != 0)
return rc; }
{ \
133 int rc = dixLookupResourceByType((void **)&(_pContext), _contextid, \
134 RTContext, _client, DixUseAccess(1<<24)); \
135 if (rc != Success0) \
136 return rc; \
137}
138
139static int RecordDeleteContext(void *value,
140 XID id);
141
142/***************************************************************************/
143
144/* client private stuff */
145
146/* To make declarations less obfuscated, have a typedef for a pointer to a
147 * Proc function.
148 */
149typedef int (*ProcFunctionPtr) (ClientPtr /*pClient */
150 );
151
152/* Record client private. Generally a client only has one of these if
153 * any of its requests are being recorded.
154 */
155typedef struct {
156/* ptr to client's proc vector before Record stuck its nose in */
157 ProcFunctionPtr *originalVector;
158
159/* proc vector with pointers for recorded requests redirected to the
160 * function RecordARequest
161 */
162 ProcFunctionPtr recordVector[256];
163} RecordClientPrivateRec, *RecordClientPrivatePtr;
164
165static DevPrivateKeyRec RecordClientPrivateKeyRec;
166
167#define RecordClientPrivateKey(&RecordClientPrivateKeyRec) (&RecordClientPrivateKeyRec)
168
169/* RecordClientPrivatePtr RecordClientPrivate(ClientPtr)
170 * gets the client private of the given client. Syntactic sugar.
171 */
172#define RecordClientPrivate(_pClient)(RecordClientPrivatePtr) dixLookupPrivate(&(_pClient)->
devPrivates, (&RecordClientPrivateKeyRec))
(RecordClientPrivatePtr) \
173 dixLookupPrivate(&(_pClient)->devPrivates, RecordClientPrivateKey(&RecordClientPrivateKeyRec))
174
175/***************************************************************************/
176
177/* global list of all contexts */
178
179static RecordContextPtr *ppAllContexts;
180
181static int numContexts; /* number of contexts in ppAllContexts */
182
183/* number of currently enabled contexts. All enabled contexts are bunched
184 * up at the front of the ppAllContexts array, from ppAllContexts[0] to
185 * ppAllContexts[numEnabledContexts-1], to eliminate time spent skipping
186 * past disabled contexts.
187 */
188static int numEnabledContexts;
189
190/* RecordFindContextOnAllContexts
191 *
192 * Arguments:
193 * pContext is the context to search for.
194 *
195 * Returns:
196 * The index into the array ppAllContexts at which pContext is stored.
197 * If pContext is not found in ppAllContexts, returns -1.
198 *
199 * Side Effects: none.
200 */
201static int
202RecordFindContextOnAllContexts(RecordContextPtr pContext)
203{
204 int i;
205
206 assert(numContexts >= numEnabledContexts)(__builtin_expect(!(numContexts >= numEnabledContexts), 0)
? __assert_rtn(__func__, "record.c", 206, "numContexts >= numEnabledContexts"
) : (void)0)
;
207 for (i = 0; i < numContexts; i++) {
208 if (ppAllContexts[i] == pContext)
209 return i;
210 }
211 return -1;
212} /* RecordFindContextOnAllContexts */
213
214/***************************************************************************/
215
216/* RecordFlushReplyBuffer
217 *
218 * Arguments:
219 * pContext is the context to flush.
220 * data1 is a pointer to additional data, and len1 is its length in bytes.
221 * data2 is a pointer to additional data, and len2 is its length in bytes.
222 *
223 * Returns: nothing.
224 *
225 * Side Effects:
226 * If the context is enabled, any buffered (recorded) protocol is written
227 * to the recording client, and the number of buffered bytes is set to
228 * zero. If len1 is not zero, data1/len1 are then written to the
229 * recording client, and similarly for data2/len2 (written after
230 * data1/len1).
231 */
232static void
233RecordFlushReplyBuffer(RecordContextPtr pContext,
234 void *data1, int len1, void *data2, int len2)
235{
236 if (!pContext->pRecordingClient || pContext->pRecordingClient->clientGone ||
237 pContext->inFlush)
238 return;
239 ++pContext->inFlush;
240 if (pContext->numBufBytes)
241 WriteToClient(pContext->pRecordingClient, pContext->numBufBytes,
242 pContext->replyBuffer);
243 pContext->numBufBytes = 0;
244 if (len1)
245 WriteToClient(pContext->pRecordingClient, len1, data1);
246 if (len2)
247 WriteToClient(pContext->pRecordingClient, len2, data2);
248 --pContext->inFlush;
249} /* RecordFlushReplyBuffer */
250
251/* RecordAProtocolElement
252 *
253 * Arguments:
254 * pContext is the context that is recording a protocol element.
255 * pClient is the client whose protocol is being recorded. For
256 * device events and EndOfData, pClient is NULL.
257 * category is the category of the protocol element, as defined
258 * by the RECORD spec.
259 * data is a pointer to the protocol data, and datalen - padlen
260 * is its length in bytes.
261 * padlen is the number of pad bytes from a zeroed array.
262 * futurelen is the number of bytes that will be sent in subsequent
263 * calls to this function to complete this protocol element.
264 * In those subsequent calls, futurelen will be -1 to indicate
265 * that the current data is a continuation of the same protocol
266 * element.
267 *
268 * Returns: nothing.
269 *
270 * Side Effects:
271 * The context may be flushed. The new protocol element will be
272 * added to the context's protocol buffer with appropriate element
273 * headers prepended (sequence number and timestamp). If the data
274 * is continuation data (futurelen == -1), element headers won't
275 * be added. If the protocol element and headers won't fit in
276 * the context's buffer, it is sent directly to the recording
277 * client (after any buffered data).
278 */
279static void
280RecordAProtocolElement(RecordContextPtr pContext, ClientPtr pClient,
281 int category, void *data, int datalen, int padlen,
282 int futurelen)
283{
284 CARD32 elemHeaderData[2];
285 int numElemHeaders = 0;
286 Bool recordingClientSwapped = pContext->pRecordingClient->swapped;
287 CARD32 serverTime = 0;
288 Bool gotServerTime = FALSE0;
289 int replylen;
290
291 if (futurelen >= 0) { /* start of new protocol element */
292 xRecordEnableContextReply *pRep = (xRecordEnableContextReply *)
293 pContext->replyBuffer;
294
295 if (pContext->pBufClient != pClient ||
296 pContext->bufCategory != category) {
297 RecordFlushReplyBuffer(pContext, NULL((void*)0), 0, NULL((void*)0), 0);
298 pContext->pBufClient = pClient;
299 pContext->bufCategory = category;
300 }
301
302 if (!pContext->numBufBytes) {
303 serverTime = GetTimeInMillis();
304 gotServerTime = TRUE1;
305 pRep->type = X_Reply1;
306 pRep->category = category;
307 pRep->sequenceNumber = pContext->pRecordingClient->sequence;
308 pRep->length = 0;
309 pRep->elementHeader = pContext->elemHeaders;
310 pRep->serverTime = serverTime;
311 if (pClient) {
312 pRep->clientSwapped =
313 (pClient->swapped != recordingClientSwapped);
314 pRep->idBase = pClient->clientAsMask;
315 pRep->recordedSequenceNumber = pClient->sequence;
316 }
317 else { /* it's a device event, StartOfData, or EndOfData */
318
319 pRep->clientSwapped = (category != XRecordFromServer0) &&
320 recordingClientSwapped;
321 pRep->idBase = 0;
322 pRep->recordedSequenceNumber = 0;
323 }
324
325 if (recordingClientSwapped) {
326 swaps(&pRep->sequenceNumber)do { if (sizeof(*(&pRep->sequenceNumber)) != 2) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&pRep->sequenceNumber
) & 1) && ((uintptr_t)(&pRep->sequenceNumber
) & 1) == 0) *(&pRep->sequenceNumber) = lswaps(*(&
pRep->sequenceNumber)); else swap_uint16((uint16_t *)(&
pRep->sequenceNumber)); } while (0)
;
327 swapl(&pRep->length)do { if (sizeof(*(&pRep->length)) != 4) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&pRep->length) &
3) && ((uintptr_t)(&pRep->length) & 3) ==
0) *(&pRep->length) = lswapl(*(&pRep->length))
; else swap_uint32((uint32_t *)(&pRep->length)); } while
(0)
;
328 swapl(&pRep->idBase)do { if (sizeof(*(&pRep->idBase)) != 4) wrong_size(); if
(__builtin_constant_p((uintptr_t)(&pRep->idBase) &
3) && ((uintptr_t)(&pRep->idBase) & 3) ==
0) *(&pRep->idBase) = lswapl(*(&pRep->idBase))
; else swap_uint32((uint32_t *)(&pRep->idBase)); } while
(0)
;
329 swapl(&pRep->serverTime)do { if (sizeof(*(&pRep->serverTime)) != 4) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&pRep->serverTime
) & 3) && ((uintptr_t)(&pRep->serverTime) &
3) == 0) *(&pRep->serverTime) = lswapl(*(&pRep->
serverTime)); else swap_uint32((uint32_t *)(&pRep->serverTime
)); } while (0)
;
330 swapl(&pRep->recordedSequenceNumber)do { if (sizeof(*(&pRep->recordedSequenceNumber)) != 4
) wrong_size(); if (__builtin_constant_p((uintptr_t)(&pRep
->recordedSequenceNumber) & 3) && ((uintptr_t)
(&pRep->recordedSequenceNumber) & 3) == 0) *(&
pRep->recordedSequenceNumber) = lswapl(*(&pRep->recordedSequenceNumber
)); else swap_uint32((uint32_t *)(&pRep->recordedSequenceNumber
)); } while (0)
;
331 }
332 pContext->numBufBytes = SIZEOF(xRecordEnableContextReply)32;
333 }
334
335 /* generate element headers if needed */
336
337 if (((pContext->elemHeaders & XRecordFromClientTime0x02)
338 && category == XRecordFromClient1)
339 || ((pContext->elemHeaders & XRecordFromServerTime0x01)
340 && category == XRecordFromServer0)) {
341 if (gotServerTime)
342 elemHeaderData[numElemHeaders] = serverTime;
343 else
344 elemHeaderData[numElemHeaders] = GetTimeInMillis();
345 if (recordingClientSwapped)
346 swapl(&elemHeaderData[numElemHeaders])do { if (sizeof(*(&elemHeaderData[numElemHeaders])) != 4)
wrong_size(); if (__builtin_constant_p((uintptr_t)(&elemHeaderData
[numElemHeaders]) & 3) && ((uintptr_t)(&elemHeaderData
[numElemHeaders]) & 3) == 0) *(&elemHeaderData[numElemHeaders
]) = lswapl(*(&elemHeaderData[numElemHeaders])); else swap_uint32
((uint32_t *)(&elemHeaderData[numElemHeaders])); } while (
0)
;
347 numElemHeaders++;
348 }
349
350 if ((pContext->elemHeaders & XRecordFromClientSequence0x04)
351 && (category == XRecordFromClient1 || category == XRecordClientDied3)) {
352 elemHeaderData[numElemHeaders] = pClient->sequence;
353 if (recordingClientSwapped)
354 swapl(&elemHeaderData[numElemHeaders])do { if (sizeof(*(&elemHeaderData[numElemHeaders])) != 4)
wrong_size(); if (__builtin_constant_p((uintptr_t)(&elemHeaderData
[numElemHeaders]) & 3) && ((uintptr_t)(&elemHeaderData
[numElemHeaders]) & 3) == 0) *(&elemHeaderData[numElemHeaders
]) = lswapl(*(&elemHeaderData[numElemHeaders])); else swap_uint32
((uint32_t *)(&elemHeaderData[numElemHeaders])); } while (
0)
;
355 numElemHeaders++;
356 }
357
358 /* adjust reply length */
359
360 replylen = pRep->length;
361 if (recordingClientSwapped)
362 swapl(&replylen)do { if (sizeof(*(&replylen)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&replylen) & 3) && ((uintptr_t)(
&replylen) & 3) == 0) *(&replylen) = lswapl(*(&
replylen)); else swap_uint32((uint32_t *)(&replylen)); } while
(0)
;
363 replylen += numElemHeaders + bytes_to_int32(datalen) +
364 bytes_to_int32(futurelen);
365 if (recordingClientSwapped)
366 swapl(&replylen)do { if (sizeof(*(&replylen)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&replylen) & 3) && ((uintptr_t)(
&replylen) & 3) == 0) *(&replylen) = lswapl(*(&
replylen)); else swap_uint32((uint32_t *)(&replylen)); } while
(0)
;
367 pRep->length = replylen;
368 } /* end if not continued reply */
369
370 numElemHeaders *= 4;
371
372 /* if space available >= space needed, buffer the data */
373
374 if (REPLY_BUF_SIZE1024 - pContext->numBufBytes >= datalen + numElemHeaders) {
375 if (numElemHeaders) {
376 memcpy(pContext->replyBuffer + pContext->numBufBytes,__builtin___memcpy_chk (pContext->replyBuffer + pContext->
numBufBytes, elemHeaderData, numElemHeaders, __builtin_object_size
(pContext->replyBuffer + pContext->numBufBytes, 0))
377 elemHeaderData, numElemHeaders)__builtin___memcpy_chk (pContext->replyBuffer + pContext->
numBufBytes, elemHeaderData, numElemHeaders, __builtin_object_size
(pContext->replyBuffer + pContext->numBufBytes, 0))
;
378 pContext->numBufBytes += numElemHeaders;
379 }
380 if (datalen) {
381 static char padBuffer[3]; /* as in FlushClient */
382
383 memcpy(pContext->replyBuffer + pContext->numBufBytes,__builtin___memcpy_chk (pContext->replyBuffer + pContext->
numBufBytes, data, datalen - padlen, __builtin_object_size (pContext
->replyBuffer + pContext->numBufBytes, 0))
384 data, datalen - padlen)__builtin___memcpy_chk (pContext->replyBuffer + pContext->
numBufBytes, data, datalen - padlen, __builtin_object_size (pContext
->replyBuffer + pContext->numBufBytes, 0))
;
385 pContext->numBufBytes += datalen - padlen;
386 memcpy(pContext->replyBuffer + pContext->numBufBytes,__builtin___memcpy_chk (pContext->replyBuffer + pContext->
numBufBytes, padBuffer, padlen, __builtin_object_size (pContext
->replyBuffer + pContext->numBufBytes, 0))
387 padBuffer, padlen)__builtin___memcpy_chk (pContext->replyBuffer + pContext->
numBufBytes, padBuffer, padlen, __builtin_object_size (pContext
->replyBuffer + pContext->numBufBytes, 0))
;
388 pContext->numBufBytes += padlen;
389 }
390 }
391 else {
392 RecordFlushReplyBuffer(pContext, (void *) elemHeaderData,
393 numElemHeaders, (void *) data,
394 datalen - padlen);
395 }
396} /* RecordAProtocolElement */
397
398/* RecordFindClientOnContext
399 *
400 * Arguments:
401 * pContext is the context to search.
402 * clientspec is the resource ID mask identifying the client to search
403 * for, or XRecordFutureClients.
404 * pposition is a pointer to an int, or NULL. See Returns.
405 *
406 * Returns:
407 * The RCAP on which clientspec was found, or NULL if not found on
408 * any RCAP on the given context.
409 * If pposition was not NULL and the returned RCAP is not NULL,
410 * *pposition will be set to the index into the returned the RCAP's
411 * pClientIDs array that holds clientspec.
412 *
413 * Side Effects: none.
414 */
415static RecordClientsAndProtocolPtr
416RecordFindClientOnContext(RecordContextPtr pContext,
417 XID clientspec, int *pposition)
418{
419 RecordClientsAndProtocolPtr pRCAP;
420
421 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
422 int i;
423
424 for (i = 0; i < pRCAP->numClients; i++) {
425 if (pRCAP->pClientIDs[i] == clientspec) {
426 if (pposition)
427 *pposition = i;
428 return pRCAP;
429 }
430 }
431 }
432 return NULL((void*)0);
433} /* RecordFindClientOnContext */
434
435/* RecordABigRequest
436 *
437 * Arguments:
438 * pContext is the recording context.
439 * client is the client being recorded.
440 * stuff is a pointer to the big request of client (see the Big Requests
441 * extension for details.)
442 *
443 * Returns: nothing.
444 *
445 * Side Effects:
446 * The big request is recorded with the correct length field re-inserted.
447 *
448 * Note: this function exists mainly to make RecordARequest smaller.
449 */
450static void
451RecordABigRequest(RecordContextPtr pContext, ClientPtr client, xReq * stuff)
452{
453 CARD32 bigLength;
454 int bytesLeft;
455
456 /* note: client->req_len has been frobbed by ReadRequestFromClient
457 * (os/io.c) to discount the extra 4 bytes taken by the extended length
458 * field in a big request. The actual request length to record is
459 * client->req_len + 1 (measured in CARD32s).
460 */
461
462 /* record the request header */
463 bytesLeft = client->req_len << 2;
464 RecordAProtocolElement(pContext, client, XRecordFromClient1,
465 (void *) stuff, SIZEOF(xReq)4, 0, bytesLeft);
466
467 /* reinsert the extended length field that was squished out */
468 bigLength = client->req_len + bytes_to_int32(sizeof(bigLength));
469 if (client->swapped)
470 swapl(&bigLength)do { if (sizeof(*(&bigLength)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&bigLength) & 3) && ((uintptr_t)
(&bigLength) & 3) == 0) *(&bigLength) = lswapl(*(
&bigLength)); else swap_uint32((uint32_t *)(&bigLength
)); } while (0)
;
471 RecordAProtocolElement(pContext, client, XRecordFromClient1,
472 (void *) &bigLength, sizeof(bigLength), 0,
473 /* continuation */ -1);
474 bytesLeft -= sizeof(bigLength);
475
476 /* record the rest of the request after the length */
477 RecordAProtocolElement(pContext, client, XRecordFromClient1,
478 (void *) (stuff + 1), bytesLeft, 0,
479 /* continuation */ -1);
480} /* RecordABigRequest */
481
482/* RecordARequest
483 *
484 * Arguments:
485 * client is a client that the server has dispatched a request to by
486 * calling client->requestVector[request opcode] .
487 * The request is in client->requestBuffer.
488 *
489 * Returns:
490 * Whatever is returned by the "real" Proc function for this request.
491 * The "real" Proc function is the function that was in
492 * client->requestVector[request opcode] before it was replaced by
493 * RecordARequest. (See the function RecordInstallHooks.)
494 *
495 * Side Effects:
496 * The request is recorded by all contexts that have registered this
497 * request for this client. The real Proc function is called.
498 */
499static int
500RecordARequest(ClientPtr client)
501{
502 RecordContextPtr pContext;
503 RecordClientsAndProtocolPtr pRCAP;
504 int i;
505 RecordClientPrivatePtr pClientPriv;
506
507 REQUEST(xReq)xReq *stuff = (xReq *)client->requestBuffer;
508 int majorop;
509
510 majorop = stuff->reqType;
511 for (i = 0; i < numEnabledContexts; i++) {
512 pContext = ppAllContexts[i];
513 pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, NULL((void*)0));
514 if (pRCAP && pRCAP->pRequestMajorOpSet &&
515 RecordIsMemberOfSet(pRCAP->pRequestMajorOpSet, majorop)(*pRCAP->pRequestMajorOpSet->ops->IsMemberOfSet)( pRCAP
->pRequestMajorOpSet, majorop)
) {
516 if (majorop <= 127) { /* core request */
517
518 if (stuff->length == 0)
519 RecordABigRequest(pContext, client, stuff);
520 else
521 RecordAProtocolElement(pContext, client, XRecordFromClient1,
522 (void *) stuff,
523 client->req_len << 2, 0, 0);
524 }
525 else { /* extension, check minor opcode */
526
527 int minorop = client->minorOp;
528 int numMinOpInfo;
529 RecordMinorOpPtr pMinorOpInfo = pRCAP->pRequestMinOpInfo;
530
531 assert(pMinorOpInfo)(__builtin_expect(!(pMinorOpInfo), 0) ? __assert_rtn(__func__
, "record.c", 531, "pMinorOpInfo") : (void)0)
;
532 numMinOpInfo = pMinorOpInfo->count;
533 pMinorOpInfo++;
534 assert(numMinOpInfo)(__builtin_expect(!(numMinOpInfo), 0) ? __assert_rtn(__func__
, "record.c", 534, "numMinOpInfo") : (void)0)
;
535 for (; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) {
536 if (majorop >= pMinorOpInfo->major.first &&
537 majorop <= pMinorOpInfo->major.last &&
538 RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet,(*pMinorOpInfo->major.pMinOpSet->ops->IsMemberOfSet)
( pMinorOpInfo->major.pMinOpSet, minorop)
539 minorop)(*pMinorOpInfo->major.pMinOpSet->ops->IsMemberOfSet)
( pMinorOpInfo->major.pMinOpSet, minorop)
) {
540 if (stuff->length == 0)
541 RecordABigRequest(pContext, client, stuff);
542 else
543 RecordAProtocolElement(pContext, client,
544 XRecordFromClient1,
545 (void *) stuff,
546 client->req_len << 2, 0, 0);
547 break;
548 }
549 } /* end for each minor op info */
550 } /* end extension request */
551 } /* end this RCAP wants this major opcode */
552 } /* end for each context */
553 pClientPriv = RecordClientPrivate(client)(RecordClientPrivatePtr) dixLookupPrivate(&(client)->devPrivates
, (&RecordClientPrivateKeyRec))
;
554 assert(pClientPriv)(__builtin_expect(!(pClientPriv), 0) ? __assert_rtn(__func__,
"record.c", 554, "pClientPriv") : (void)0)
;
555 return (*pClientPriv->originalVector[majorop]) (client);
556} /* RecordARequest */
557
558/* RecordAReply
559 *
560 * Arguments:
561 * pcbl is &ReplyCallback.
562 * nulldata is NULL.
563 * calldata is a pointer to a ReplyInfoRec (include/os.h)
564 * which provides information about replies that are being sent
565 * to clients.
566 *
567 * Returns: nothing.
568 *
569 * Side Effects:
570 * The reply is recorded by all contexts that have registered this
571 * reply type for this client. If more data belonging to the same
572 * reply is expected, and if the reply is being recorded by any
573 * context, pContext->continuedReply is set to 1.
574 * If pContext->continuedReply was already 1 and this is the last
575 * chunk of data belonging to this reply, it is set to 0.
576 */
577static void
578RecordAReply(CallbackListPtr *pcbl, void *nulldata, void *calldata)
579{
580 RecordContextPtr pContext;
581 RecordClientsAndProtocolPtr pRCAP;
582 int eci;
583 ReplyInfoRec *pri = (ReplyInfoRec *) calldata;
584 ClientPtr client = pri->client;
585
586 for (eci = 0; eci < numEnabledContexts; eci++) {
587 pContext = ppAllContexts[eci];
588 pRCAP = RecordFindClientOnContext(pContext, client->clientAsMask, NULL((void*)0));
589 if (pRCAP) {
590 int majorop = client->majorOp;
591
592 if (pContext->continuedReply) {
593 RecordAProtocolElement(pContext, client, XRecordFromServer0,
594 (void *) pri->replyData,
595 pri->dataLenBytes, pri->padBytes,
596 /* continuation */ -1);
597 if (!pri->bytesRemaining)
598 pContext->continuedReply = 0;
599 }
600 else if (pri->startOfReply && pRCAP->pReplyMajorOpSet &&
601 RecordIsMemberOfSet(pRCAP->pReplyMajorOpSet, majorop)(*pRCAP->pReplyMajorOpSet->ops->IsMemberOfSet)( pRCAP
->pReplyMajorOpSet, majorop)
) {
602 if (majorop <= 127) { /* core reply */
603 RecordAProtocolElement(pContext, client, XRecordFromServer0,
604 (void *) pri->replyData,
605 pri->dataLenBytes, 0,
606 pri->bytesRemaining);
607 if (pri->bytesRemaining)
608 pContext->continuedReply = 1;
609 }
610 else { /* extension, check minor opcode */
611
612 int minorop = client->minorOp;
613 int numMinOpInfo;
614 RecordMinorOpPtr pMinorOpInfo = pRCAP->pReplyMinOpInfo;
615
616 assert(pMinorOpInfo)(__builtin_expect(!(pMinorOpInfo), 0) ? __assert_rtn(__func__
, "record.c", 616, "pMinorOpInfo") : (void)0)
;
617 numMinOpInfo = pMinorOpInfo->count;
618 pMinorOpInfo++;
619 assert(numMinOpInfo)(__builtin_expect(!(numMinOpInfo), 0) ? __assert_rtn(__func__
, "record.c", 619, "numMinOpInfo") : (void)0)
;
620 for (; numMinOpInfo; numMinOpInfo--, pMinorOpInfo++) {
621 if (majorop >= pMinorOpInfo->major.first &&
622 majorop <= pMinorOpInfo->major.last &&
623 RecordIsMemberOfSet(pMinorOpInfo->major.pMinOpSet,(*pMinorOpInfo->major.pMinOpSet->ops->IsMemberOfSet)
( pMinorOpInfo->major.pMinOpSet, minorop)
624 minorop)(*pMinorOpInfo->major.pMinOpSet->ops->IsMemberOfSet)
( pMinorOpInfo->major.pMinOpSet, minorop)
) {
625 RecordAProtocolElement(pContext, client,
626 XRecordFromServer0,
627 (void *) pri->replyData,
628 pri->dataLenBytes, 0,
629 pri->bytesRemaining);
630 if (pri->bytesRemaining)
631 pContext->continuedReply = 1;
632 break;
633 }
634 } /* end for each minor op info */
635 } /* end extension reply */
636 } /* end continued reply vs. start of reply */
637 } /* end client is registered on this context */
638 } /* end for each context */
639} /* RecordAReply */
640
641/* RecordADeliveredEventOrError
642 *
643 * Arguments:
644 * pcbl is &EventCallback.
645 * nulldata is NULL.
646 * calldata is a pointer to a EventInfoRec (include/dix.h)
647 * which provides information about events that are being sent
648 * to clients.
649 *
650 * Returns: nothing.
651 *
652 * Side Effects:
653 * The event or error is recorded by all contexts that have registered
654 * it for this client.
655 */
656static void
657RecordADeliveredEventOrError(CallbackListPtr *pcbl, void *nulldata,
658 void *calldata)
659{
660 EventInfoRec *pei = (EventInfoRec *) calldata;
661 RecordContextPtr pContext;
662 RecordClientsAndProtocolPtr pRCAP;
663 int eci; /* enabled context index */
664 ClientPtr pClient = pei->client;
665
666 for (eci = 0; eci < numEnabledContexts; eci++) {
667 pContext = ppAllContexts[eci];
668 pRCAP = RecordFindClientOnContext(pContext, pClient->clientAsMask,
669 NULL((void*)0));
670 if (pRCAP && (pRCAP->pDeliveredEventSet || pRCAP->pErrorSet)) {
671 int ev; /* event index */
672 xEvent *pev = pei->events;
673
674 for (ev = 0; ev < pei->count; ev++, pev++) {
675 int recordit = 0;
676
677 if (pRCAP->pErrorSet) {
678 recordit = RecordIsMemberOfSet(pRCAP->pErrorSet,(*pRCAP->pErrorSet->ops->IsMemberOfSet)( pRCAP->pErrorSet
, ((xError *) (pev))-> errorCode)
679 ((xError *) (pev))->(*pRCAP->pErrorSet->ops->IsMemberOfSet)( pRCAP->pErrorSet
, ((xError *) (pev))-> errorCode)
680 errorCode)(*pRCAP->pErrorSet->ops->IsMemberOfSet)( pRCAP->pErrorSet
, ((xError *) (pev))-> errorCode)
;
681 }
682 else if (pRCAP->pDeliveredEventSet) {
683 recordit = RecordIsMemberOfSet(pRCAP->pDeliveredEventSet,(*pRCAP->pDeliveredEventSet->ops->IsMemberOfSet)( pRCAP
->pDeliveredEventSet, pev->u.u.type & 0177)
684 pev->u.u.type & 0177)(*pRCAP->pDeliveredEventSet->ops->IsMemberOfSet)( pRCAP
->pDeliveredEventSet, pev->u.u.type & 0177)
;
685 }
686 if (recordit) {
687 xEvent swappedEvent;
688 xEvent *pEvToRecord = pev;
689
690 if (pClient->swapped) {
691 (*EventSwapVector[pev->u.u.type & 0177])
692 (pev, &swappedEvent);
693 pEvToRecord = &swappedEvent;
694
695 }
696 RecordAProtocolElement(pContext, pClient,
697 XRecordFromServer0, pEvToRecord,
698 SIZEOF(xEvent)32, 0, 0);
699 }
700 } /* end for each event */
701 } /* end this client is on this context */
702 } /* end for each enabled context */
703} /* RecordADeliveredEventOrError */
704
705static void
706RecordSendProtocolEvents(RecordClientsAndProtocolPtr pRCAP,
707 RecordContextPtr pContext, xEvent *pev, int count)
708{
709 int ev; /* event index */
710
711 for (ev = 0; ev < count; ev++, pev++) {
712 if (RecordIsMemberOfSet(pRCAP->pDeviceEventSet, pev->u.u.type & 0177)(*pRCAP->pDeviceEventSet->ops->IsMemberOfSet)( pRCAP
->pDeviceEventSet, pev->u.u.type & 0177)
) {
713 xEvent swappedEvent;
714 xEvent *pEvToRecord = pev;
715
716#ifdef PANORAMIX1
717 xEvent shiftedEvent;
718
719 if (!noPanoramiXExtension &&
720 (pev->u.u.type == MotionNotify6 ||
721 pev->u.u.type == ButtonPress4 ||
722 pev->u.u.type == ButtonRelease5 ||
723 pev->u.u.type == KeyPress2 || pev->u.u.type == KeyRelease3)) {
724 int scr = XineramaGetCursorScreen(inputInfo.pointer);
725
726 memcpy(&shiftedEvent, pev, sizeof(xEvent))__builtin___memcpy_chk (&shiftedEvent, pev, sizeof(xEvent
), __builtin_object_size (&shiftedEvent, 0))
;
727 shiftedEvent.u.keyButtonPointer.rootX +=
728 screenInfo.screens[scr]->x - screenInfo.screens[0]->x;
729 shiftedEvent.u.keyButtonPointer.rootY +=
730 screenInfo.screens[scr]->y - screenInfo.screens[0]->y;
731 pEvToRecord = &shiftedEvent;
732 }
733#endif /* PANORAMIX */
734
735 if (pContext->pRecordingClient->swapped) {
736 (*EventSwapVector[pEvToRecord->u.u.type & 0177])
737 (pEvToRecord, &swappedEvent);
738 pEvToRecord = &swappedEvent;
739 }
740
741 RecordAProtocolElement(pContext, NULL((void*)0),
742 XRecordFromServer0, pEvToRecord,
743 SIZEOF(xEvent)32, 0, 0);
744 /* make sure device events get flushed in the absence
745 * of other client activity
746 */
747 SetCriticalOutputPending();
748 }
749 } /* end for each event */
750
751} /* RecordADeviceEvent */
752
753/* RecordADeviceEvent
754 *
755 * Arguments:
756 * pcbl is &DeviceEventCallback.
757 * nulldata is NULL.
758 * calldata is a pointer to a DeviceEventInfoRec (include/dix.h)
759 * which provides information about device events that occur.
760 *
761 * Returns: nothing.
762 *
763 * Side Effects:
764 * The device event is recorded by all contexts that have registered
765 * it for this client.
766 */
767static void
768RecordADeviceEvent(CallbackListPtr *pcbl, void *nulldata, void *calldata)
769{
770 DeviceEventInfoRec *pei = (DeviceEventInfoRec *) calldata;
771 RecordContextPtr pContext;
772 RecordClientsAndProtocolPtr pRCAP;
773 int eci; /* enabled context index */
774
775 for (eci = 0; eci < numEnabledContexts; eci++) {
776 pContext = ppAllContexts[eci];
777 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
778 if (pRCAP->pDeviceEventSet) {
779 int count;
780 xEvent *xi_events = NULL((void*)0);
781
782 /* TODO check return values */
783 if (IsMaster(pei->device)) {
784 xEvent *core_events;
785
786 EventToCore(pei->event, &core_events, &count);
787 RecordSendProtocolEvents(pRCAP, pContext, core_events,
788 count);
789 free(core_events);
790 }
791
792 EventToXI(pei->event, &xi_events, &count);
793 RecordSendProtocolEvents(pRCAP, pContext, xi_events, count);
794 free(xi_events);
795 } /* end this RCAP selects device events */
796 } /* end for each RCAP on this context */
797 } /* end for each enabled context */
798}
799
800/* RecordFlushAllContexts
801 *
802 * Arguments:
803 * pcbl is &FlushCallback.
804 * nulldata and calldata are NULL.
805 *
806 * Returns: nothing.
807 *
808 * Side Effects:
809 * All buffered reply data of all enabled contexts is written to
810 * the recording clients.
811 */
812static void
813RecordFlushAllContexts(CallbackListPtr *pcbl,
814 void *nulldata, void *calldata)
815{
816 int eci; /* enabled context index */
817 RecordContextPtr pContext;
818
819 for (eci = 0; eci < numEnabledContexts; eci++) {
820 pContext = ppAllContexts[eci];
821
822 /* In most cases we leave it to RecordFlushReplyBuffer to make
823 * this check, but this function could be called very often, so we
824 * check before calling hoping to save the function call cost
825 * most of the time.
826 */
827 if (pContext->numBufBytes)
828 RecordFlushReplyBuffer(ppAllContexts[eci], NULL((void*)0), 0, NULL((void*)0), 0);
829 }
830} /* RecordFlushAllContexts */
831
832/* RecordInstallHooks
833 *
834 * Arguments:
835 * pRCAP is an RCAP on an enabled or being-enabled context.
836 * oneclient can be zero or the resource ID mask identifying a client.
837 *
838 * Returns: BadAlloc if a memory allocation error occurred, else Success.
839 *
840 * Side Effects:
841 * Recording hooks needed by RCAP are installed.
842 * If oneclient is zero, recording hooks needed for all clients and
843 * protocol on the RCAP are installed. If oneclient is non-zero,
844 * only those hooks needed for the specified client are installed.
845 *
846 * Client requestVectors may be altered. numEnabledRCAPs will be
847 * incremented if oneclient == 0. Callbacks may be added to
848 * various callback lists.
849 */
850static int
851RecordInstallHooks(RecordClientsAndProtocolPtr pRCAP, XID oneclient)
852{
853 int i = 0;
854 XID client;
855
856 if (oneclient)
857 client = oneclient;
858 else
859 client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0;
860
861 while (client) {
862 if (client != XRecordFutureClients2) {
863 if (pRCAP->pRequestMajorOpSet) {
864 RecordSetIteratePtr pIter = NULL((void*)0);
865 RecordSetInterval interval;
866 ClientPtr pClient = clients[CLIENT_ID(client)((int)(((client) & (((1 << ResourceClientBits()) - 1
) << (29 - ResourceClientBits()))) >> (29 - ResourceClientBits
())))
];
867
868 if (pClient && !RecordClientPrivate(pClient)(RecordClientPrivatePtr) dixLookupPrivate(&(pClient)->
devPrivates, (&RecordClientPrivateKeyRec))
) {
869 RecordClientPrivatePtr pClientPriv;
870
871 /* no Record proc vector; allocate one */
872 pClientPriv = (RecordClientPrivatePtr)
873 malloc(sizeof(RecordClientPrivateRec));
874 if (!pClientPriv)
875 return BadAlloc11;
876 /* copy old proc vector to new */
877 memcpy(pClientPriv->recordVector, pClient->requestVector,__builtin___memcpy_chk (pClientPriv->recordVector, pClient
->requestVector, sizeof(pClientPriv->recordVector), __builtin_object_size
(pClientPriv->recordVector, 0))
878 sizeof(pClientPriv->recordVector))__builtin___memcpy_chk (pClientPriv->recordVector, pClient
->requestVector, sizeof(pClientPriv->recordVector), __builtin_object_size
(pClientPriv->recordVector, 0))
;
879 pClientPriv->originalVector = pClient->requestVector;
880 dixSetPrivate(&pClient->devPrivates,
881 RecordClientPrivateKey(&RecordClientPrivateKeyRec), pClientPriv);
882 pClient->requestVector = pClientPriv->recordVector;
883 }
884 while ((pIter = RecordIterateSet(pRCAP->pRequestMajorOpSet,(*pRCAP->pRequestMajorOpSet->ops->IterateSet)( pRCAP
->pRequestMajorOpSet, pIter, &interval)
885 pIter, &interval)(*pRCAP->pRequestMajorOpSet->ops->IterateSet)( pRCAP
->pRequestMajorOpSet, pIter, &interval)
)) {
886 unsigned int j;
887
888 for (j = interval.first; j <= interval.last; j++)
889 pClient->requestVector[j] = RecordARequest;
890 }
891 }
892 }
893 if (oneclient)
894 client = 0;
895 else
896 client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0;
897 }
898
899 assert(numEnabledRCAPs >= 0)(__builtin_expect(!(numEnabledRCAPs >= 0), 0) ? __assert_rtn
(__func__, "record.c", 899, "numEnabledRCAPs >= 0") : (void
)0)
;
900 if (!oneclient && ++numEnabledRCAPs == 1) { /* we're enabling the first context */
901 if (!AddCallback(&EventCallback, RecordADeliveredEventOrError, NULL((void*)0)))
902 return BadAlloc11;
903 if (!AddCallback(&DeviceEventCallback, RecordADeviceEvent, NULL((void*)0)))
904 return BadAlloc11;
905 if (!AddCallback(&ReplyCallback, RecordAReply, NULL((void*)0)))
906 return BadAlloc11;
907 if (!AddCallback(&FlushCallback, RecordFlushAllContexts, NULL((void*)0)))
908 return BadAlloc11;
909 /* Alternate context flushing scheme: delete the line above
910 * and call RegisterBlockAndWakeupHandlers here passing
911 * RecordFlushAllContexts. Is this any better?
912 */
913 }
914 return Success0;
915} /* RecordInstallHooks */
916
917/* RecordUninstallHooks
918 *
919 * Arguments:
920 * pRCAP is an RCAP on an enabled or being-disabled context.
921 * oneclient can be zero or the resource ID mask identifying a client.
922 *
923 * Returns: nothing.
924 *
925 * Side Effects:
926 * Recording hooks needed by RCAP may be uninstalled.
927 * If oneclient is zero, recording hooks needed for all clients and
928 * protocol on the RCAP may be uninstalled. If oneclient is non-zero,
929 * only those hooks needed for the specified client may be uninstalled.
930 *
931 * Client requestVectors may be altered. numEnabledRCAPs will be
932 * decremented if oneclient == 0. Callbacks may be deleted from
933 * various callback lists.
934 */
935static void
936RecordUninstallHooks(RecordClientsAndProtocolPtr pRCAP, XID oneclient)
937{
938 int i = 0;
939 XID client;
940
941 if (oneclient)
942 client = oneclient;
943 else
944 client = pRCAP->numClients ? pRCAP->pClientIDs[i++] : 0;
945
946 while (client) {
947 if (client != XRecordFutureClients2) {
948 if (pRCAP->pRequestMajorOpSet) {
949 ClientPtr pClient = clients[CLIENT_ID(client)((int)(((client) & (((1 << ResourceClientBits()) - 1
) << (29 - ResourceClientBits()))) >> (29 - ResourceClientBits
())))
];
950 int c;
951 Bool otherRCAPwantsProcVector = FALSE0;
952 RecordClientPrivatePtr pClientPriv = NULL((void*)0);
953
954 assert(pClient)(__builtin_expect(!(pClient), 0) ? __assert_rtn(__func__, "record.c"
, 954, "pClient") : (void)0)
;
955 pClientPriv = RecordClientPrivate(pClient)(RecordClientPrivatePtr) dixLookupPrivate(&(pClient)->
devPrivates, (&RecordClientPrivateKeyRec))
;
956 assert(pClientPriv)(__builtin_expect(!(pClientPriv), 0) ? __assert_rtn(__func__,
"record.c", 956, "pClientPriv") : (void)0)
;
957 memcpy(pClientPriv->recordVector, pClientPriv->originalVector,__builtin___memcpy_chk (pClientPriv->recordVector, pClientPriv
->originalVector, sizeof(pClientPriv->recordVector), __builtin_object_size
(pClientPriv->recordVector, 0))
958 sizeof(pClientPriv->recordVector))__builtin___memcpy_chk (pClientPriv->recordVector, pClientPriv
->originalVector, sizeof(pClientPriv->recordVector), __builtin_object_size
(pClientPriv->recordVector, 0))
;
959
960 for (c = 0; c < numEnabledContexts; c++) {
961 RecordClientsAndProtocolPtr pOtherRCAP;
962 RecordContextPtr pContext = ppAllContexts[c];
963
964 if (pContext == pRCAP->pContext)
965 continue;
966 pOtherRCAP = RecordFindClientOnContext(pContext, client,
967 NULL((void*)0));
968 if (pOtherRCAP && pOtherRCAP->pRequestMajorOpSet) {
969 RecordSetIteratePtr pIter = NULL((void*)0);
970 RecordSetInterval interval;
971
972 otherRCAPwantsProcVector = TRUE1;
973 while ((pIter =
974 RecordIterateSet(pOtherRCAP->pRequestMajorOpSet,(*pOtherRCAP->pRequestMajorOpSet->ops->IterateSet)( pOtherRCAP
->pRequestMajorOpSet, pIter, &interval)
975 pIter, &interval)(*pOtherRCAP->pRequestMajorOpSet->ops->IterateSet)( pOtherRCAP
->pRequestMajorOpSet, pIter, &interval)
)) {
976 unsigned int j;
977
978 for (j = interval.first; j <= interval.last; j++)
979 pClient->requestVector[j] = RecordARequest;
980 }
981 }
982 }
983 if (!otherRCAPwantsProcVector) { /* nobody needs it, so free it */
984 pClient->requestVector = pClientPriv->originalVector;
985 dixSetPrivate(&pClient->devPrivates,
986 RecordClientPrivateKey(&RecordClientPrivateKeyRec), NULL((void*)0));
987 free(pClientPriv);
988 }
989 } /* end if this RCAP specifies any requests */
990 } /* end if not future clients */
991 if (oneclient)
992 client = 0;
993 else
994 client = (i < pRCAP->numClients) ? pRCAP->pClientIDs[i++] : 0;
995 }
996
997 assert(numEnabledRCAPs >= 1)(__builtin_expect(!(numEnabledRCAPs >= 1), 0) ? __assert_rtn
(__func__, "record.c", 997, "numEnabledRCAPs >= 1") : (void
)0)
;
998 if (!oneclient && --numEnabledRCAPs == 0) { /* we're disabling the last context */
999 DeleteCallback(&EventCallback, RecordADeliveredEventOrError, NULL((void*)0));
1000 DeleteCallback(&DeviceEventCallback, RecordADeviceEvent, NULL((void*)0));
1001 DeleteCallback(&ReplyCallback, RecordAReply, NULL((void*)0));
1002 DeleteCallback(&FlushCallback, RecordFlushAllContexts, NULL((void*)0));
1003 /* Alternate context flushing scheme: delete the line above
1004 * and call RemoveBlockAndWakeupHandlers here passing
1005 * RecordFlushAllContexts. Is this any better?
1006 */
1007 /* Having deleted the callback, call it one last time. -gildea */
1008 RecordFlushAllContexts(&FlushCallback, NULL((void*)0), NULL((void*)0));
1009 }
1010} /* RecordUninstallHooks */
1011
1012/* RecordDeleteClientFromRCAP
1013 *
1014 * Arguments:
1015 * pRCAP is an RCAP to delete the client from.
1016 * position is the index into the array pRCAP->pClientIDs of the
1017 * client to delete.
1018 *
1019 * Returns: nothing.
1020 *
1021 * Side Effects:
1022 * Recording hooks needed by client will be uninstalled if the context
1023 * is enabled. The designated client will be removed from the
1024 * pRCAP->pClientIDs array. If it was the only client on the RCAP,
1025 * the RCAP is removed from the context and freed. (Invariant: RCAPs
1026 * have at least one client.)
1027 */
1028static void
1029RecordDeleteClientFromRCAP(RecordClientsAndProtocolPtr pRCAP, int position)
1030{
1031 if (pRCAP->pContext->pRecordingClient)
1032 RecordUninstallHooks(pRCAP, pRCAP->pClientIDs[position]);
1033 if (position != pRCAP->numClients - 1)
1034 pRCAP->pClientIDs[position] = pRCAP->pClientIDs[pRCAP->numClients - 1];
1035 if (--pRCAP->numClients == 0) { /* no more clients; remove RCAP from context's list */
1036 RecordContextPtr pContext = pRCAP->pContext;
1037
1038 if (pContext->pRecordingClient)
1039 RecordUninstallHooks(pRCAP, 0);
1040 if (pContext->pListOfRCAP == pRCAP)
1041 pContext->pListOfRCAP = pRCAP->pNextRCAP;
1042 else {
1043 RecordClientsAndProtocolPtr prevRCAP;
1044
1045 for (prevRCAP = pContext->pListOfRCAP;
1046 prevRCAP->pNextRCAP != pRCAP; prevRCAP = prevRCAP->pNextRCAP);
1047 prevRCAP->pNextRCAP = pRCAP->pNextRCAP;
1048 }
1049 /* free the RCAP */
1050 if (pRCAP->clientIDsSeparatelyAllocated)
1051 free(pRCAP->pClientIDs);
1052 free(pRCAP);
1053 }
1054} /* RecordDeleteClientFromRCAP */
1055
1056/* RecordAddClientToRCAP
1057 *
1058 * Arguments:
1059 * pRCAP is an RCAP to add the client to.
1060 * clientspec is the resource ID mask identifying a client, or
1061 * XRecordFutureClients.
1062 *
1063 * Returns: nothing.
1064 *
1065 * Side Effects:
1066 * Recording hooks needed by client will be installed if the context
1067 * is enabled. The designated client will be added to the
1068 * pRCAP->pClientIDs array, which may be realloced.
1069 * pRCAP->clientIDsSeparatelyAllocated may be set to 1 if there
1070 * is no more room to hold clients internal to the RCAP.
1071 */
1072static void
1073RecordAddClientToRCAP(RecordClientsAndProtocolPtr pRCAP, XID clientspec)
1074{
1075 if (pRCAP->numClients == pRCAP->sizeClients) {
1076 if (pRCAP->clientIDsSeparatelyAllocated) {
1077 XID *pNewIDs =
1078 reallocarrayxreallocarray(pRCAP->pClientIDs,
1079 pRCAP->sizeClients + CLIENT_ARRAY_GROWTH_INCREMENT4,
1080 sizeof(XID));
1081 if (!pNewIDs)
1082 return;
1083 pRCAP->pClientIDs = pNewIDs;
1084 pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT4;
1085 }
1086 else {
1087 XID *pNewIDs =
1088 xallocarray(pRCAP->sizeClients + CLIENT_ARRAY_GROWTH_INCREMENT,xreallocarray(((void*)0), (pRCAP->sizeClients + 4), (sizeof
(XID)))
1089 sizeof(XID))xreallocarray(((void*)0), (pRCAP->sizeClients + 4), (sizeof
(XID)))
;
1090 if (!pNewIDs)
1091 return;
1092 memcpy(pNewIDs, pRCAP->pClientIDs, pRCAP->numClients * sizeof(XID))__builtin___memcpy_chk (pNewIDs, pRCAP->pClientIDs, pRCAP->
numClients * sizeof(XID), __builtin_object_size (pNewIDs, 0))
;
1093 pRCAP->pClientIDs = pNewIDs;
1094 pRCAP->sizeClients += CLIENT_ARRAY_GROWTH_INCREMENT4;
1095 pRCAP->clientIDsSeparatelyAllocated = 1;
1096 }
1097 }
1098 pRCAP->pClientIDs[pRCAP->numClients++] = clientspec;
1099 if (pRCAP->pContext->pRecordingClient)
1100 RecordInstallHooks(pRCAP, clientspec);
1101} /* RecordDeleteClientFromRCAP */
1102
1103/* RecordDeleteClientFromContext
1104 *
1105 * Arguments:
1106 * pContext is the context to delete from.
1107 * clientspec is the resource ID mask identifying a client, or
1108 * XRecordFutureClients.
1109 *
1110 * Returns: nothing.
1111 *
1112 * Side Effects:
1113 * If clientspec is on any RCAP of the context, it is deleted from that
1114 * RCAP. (A given clientspec can only be on one RCAP of a context.)
1115 */
1116static void
1117RecordDeleteClientFromContext(RecordContextPtr pContext, XID clientspec)
1118{
1119 RecordClientsAndProtocolPtr pRCAP;
1120 int position;
1121
1122 if ((pRCAP = RecordFindClientOnContext(pContext, clientspec, &position)))
1123 RecordDeleteClientFromRCAP(pRCAP, position);
1124} /* RecordDeleteClientFromContext */
1125
1126/* RecordSanityCheckClientSpecifiers
1127 *
1128 * Arguments:
1129 * clientspecs is an array of alleged CLIENTSPECs passed by the client.
1130 * nspecs is the number of elements in clientspecs.
1131 * errorspec, if non-zero, is the resource id base of a client that
1132 * must not appear in clienspecs.
1133 *
1134 * Returns: BadMatch if any of the clientspecs are invalid, else Success.
1135 *
1136 * Side Effects: none.
1137 */
1138static int
1139RecordSanityCheckClientSpecifiers(ClientPtr client, XID *clientspecs,
1140 int nspecs, XID errorspec)
1141{
1142 int i;
1143 int clientIndex;
1144 int rc;
1145 void *value;
1146
1147 for (i = 0; i < nspecs; i++) {
1148 if (clientspecs[i] == XRecordCurrentClients1 ||
1149 clientspecs[i] == XRecordFutureClients2 ||
1150 clientspecs[i] == XRecordAllClients3)
1151 continue;
1152 if (errorspec && (CLIENT_BITS(clientspecs[i])((clientspecs[i]) & (((1 << ResourceClientBits()) -
1) << (29 - ResourceClientBits())))
== errorspec))
1153 return BadMatch8;
1154 clientIndex = CLIENT_ID(clientspecs[i])((int)(((clientspecs[i]) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))
;
1155 if (clientIndex && clients[clientIndex] &&
1156 clients[clientIndex]->clientState == ClientStateRunning) {
1157 if (clientspecs[i] == clients[clientIndex]->clientAsMask)
1158 continue;
1159 rc = dixLookupResourceByClass(&value, clientspecs[i], RC_ANY(~(RESTYPE)0),
1160 client, DixGetAttrAccess(1<<4));
1161 if (rc != Success0)
1162 return rc;
1163 }
1164 else
1165 return BadMatch8;
1166 }
1167 return Success0;
1168} /* RecordSanityCheckClientSpecifiers */
1169
1170/* RecordCanonicalizeClientSpecifiers
1171 *
1172 * Arguments:
1173 * pClientspecs is an array of CLIENTSPECs that have been sanity
1174 * checked.
1175 * pNumClientspecs is a pointer to the number of elements in pClientspecs.
1176 * excludespec, if non-zero, is the resource id base of a client that
1177 * should not be included in the expansion of XRecordAllClients or
1178 * XRecordCurrentClients.
1179 *
1180 * Returns:
1181 * A pointer to an array of CLIENTSPECs that is the same as the
1182 * passed array with the following modifications:
1183 * - all but the client id bits of resource IDs are stripped off.
1184 * - duplicates removed.
1185 * - XRecordAllClients expanded to a list of all currently connected
1186 * clients + XRecordFutureClients - excludespec (if non-zero)
1187 * - XRecordCurrentClients expanded to a list of all currently
1188 * connected clients - excludespec (if non-zero)
1189 * The returned array may be the passed array modified in place, or
1190 * it may be an malloc'ed array. The caller should keep a pointer to the
1191 * original array and free the returned array if it is different.
1192 *
1193 * *pNumClientspecs is set to the number of elements in the returned
1194 * array.
1195 *
1196 * Side Effects:
1197 * pClientspecs may be modified in place.
1198 */
1199static XID *
1200RecordCanonicalizeClientSpecifiers(XID *pClientspecs, int *pNumClientspecs,
1201 XID excludespec)
1202{
1203 int i;
1204 int numClients = *pNumClientspecs;
1205
1206 /* first pass strips off the resource index bits, leaving just the
1207 * client id bits. This makes searching for a particular client simpler
1208 * (and faster.)
1209 */
1210 for (i = 0; i < numClients; i++) {
1211 XID cs = pClientspecs[i];
1212
1213 if (cs > XRecordAllClients3)
1214 pClientspecs[i] = CLIENT_BITS(cs)((cs) & (((1 << ResourceClientBits()) - 1) <<
(29 - ResourceClientBits())))
;
1215 }
1216
1217 for (i = 0; i < numClients; i++) {
1218 if (pClientspecs[i] == XRecordAllClients3 || pClientspecs[i] == XRecordCurrentClients1) { /* expand All/Current */
1219 int j, nc;
1220 XID *pCanon = xallocarray(currentMaxClients + 1, sizeof(XID))xreallocarray(((void*)0), (currentMaxClients + 1), (sizeof(XID
)))
;
1221
1222 if (!pCanon)
1223 return NULL((void*)0);
1224 for (nc = 0, j = 1; j < currentMaxClients; j++) {
1225 ClientPtr client = clients[j];
1226
1227 if (client != NullClient((ClientPtr) 0) &&
1228 client->clientState == ClientStateRunning &&
1229 client->clientAsMask != excludespec) {
1230 pCanon[nc++] = client->clientAsMask;
1231 }
1232 }
1233 if (pClientspecs[i] == XRecordAllClients3)
1234 pCanon[nc++] = XRecordFutureClients2;
1235 *pNumClientspecs = nc;
1236 return pCanon;
1237 }
1238 else { /* not All or Current */
1239
1240 int j;
1241
1242 for (j = i + 1; j < numClients;) {
1243 if (pClientspecs[i] == pClientspecs[j]) {
1244 pClientspecs[j] = pClientspecs[--numClients];
1245 }
1246 else
1247 j++;
1248 }
1249 }
1250 } /* end for each clientspec */
1251 *pNumClientspecs = numClients;
1252 return pClientspecs;
1253} /* RecordCanonicalizeClientSpecifiers */
1254
1255/****************************************************************************/
1256
1257/* stuff for RegisterClients */
1258
1259/* RecordPadAlign
1260 *
1261 * Arguments:
1262 * size is the number of bytes taken by an object.
1263 * align is a byte boundary (e.g. 4, 8)
1264 *
1265 * Returns:
1266 * the number of pad bytes to add at the end of an object of the
1267 * given size so that an object placed immediately behind it will
1268 * begin on an <align>-byte boundary.
1269 *
1270 * Side Effects: none.
1271 */
1272static int
1273RecordPadAlign(int size, int align)
1274{
1275 return (align - (size & (align - 1))) & (align - 1);
1276} /* RecordPadAlign */
1277
1278/* RecordSanityCheckRegisterClients
1279 *
1280 * Arguments:
1281 * pContext is the context being registered on.
1282 * client is the client that issued a RecordCreateContext or
1283 * RecordRegisterClients request.
1284 * stuff is a pointer to the request.
1285 *
1286 * Returns:
1287 * Any one of several possible error values if any of the request
1288 * arguments are invalid. Success if everything is OK.
1289 *
1290 * Side Effects: none.
1291 */
1292static int
1293RecordSanityCheckRegisterClients(RecordContextPtr pContext, ClientPtr client,
1294 xRecordRegisterClientsReq * stuff)
1295{
1296 int err;
1297 xRecordRange *pRange;
1298 int i;
1299 XID recordingClient;
1300
1301 if (((client->req_len << 2) - SIZEOF(xRecordRegisterClientsReq)20) !=
1302 4 * stuff->nClients + SIZEOF(xRecordRange)24 * stuff->nRanges)
1303 return BadLength16;
1304
1305 if (stuff->elementHeader &
1306 ~(XRecordFromClientSequence0x04 | XRecordFromClientTime0x02 |
1307 XRecordFromServerTime0x01)) {
1308 client->errorValue = stuff->elementHeader;
1309 return BadValue2;
1310 }
1311
1312 recordingClient = pContext->pRecordingClient ?
1313 pContext->pRecordingClient->clientAsMask : 0;
1314 err = RecordSanityCheckClientSpecifiers(client, (XID *) &stuff[1],
1315 stuff->nClients, recordingClient);
1316 if (err != Success0)
1317 return err;
1318
1319 pRange = (xRecordRange *) (((XID *) &stuff[1]) + stuff->nClients);
1320 for (i = 0; i < stuff->nRanges; i++, pRange++) {
1321 if (pRange->coreRequestsFirst > pRange->coreRequestsLast) {
1322 client->errorValue = pRange->coreRequestsFirst;
1323 return BadValue2;
1324 }
1325 if (pRange->coreRepliesFirst > pRange->coreRepliesLast) {
1326 client->errorValue = pRange->coreRepliesFirst;
1327 return BadValue2;
1328 }
1329 if ((pRange->extRequestsMajorFirst || pRange->extRequestsMajorLast) &&
1330 (pRange->extRequestsMajorFirst < 128 ||
1331 pRange->extRequestsMajorLast < 128 ||
1332 pRange->extRequestsMajorFirst > pRange->extRequestsMajorLast)) {
1333 client->errorValue = pRange->extRequestsMajorFirst;
1334 return BadValue2;
1335 }
1336 if (pRange->extRequestsMinorFirst > pRange->extRequestsMinorLast) {
1337 client->errorValue = pRange->extRequestsMinorFirst;
1338 return BadValue2;
1339 }
1340 if ((pRange->extRepliesMajorFirst || pRange->extRepliesMajorLast) &&
1341 (pRange->extRepliesMajorFirst < 128 ||
1342 pRange->extRepliesMajorLast < 128 ||
1343 pRange->extRepliesMajorFirst > pRange->extRepliesMajorLast)) {
1344 client->errorValue = pRange->extRepliesMajorFirst;
1345 return BadValue2;
1346 }
1347 if (pRange->extRepliesMinorFirst > pRange->extRepliesMinorLast) {
1348 client->errorValue = pRange->extRepliesMinorFirst;
1349 return BadValue2;
1350 }
1351 if ((pRange->deliveredEventsFirst || pRange->deliveredEventsLast) &&
1352 (pRange->deliveredEventsFirst < 2 ||
1353 pRange->deliveredEventsLast < 2 ||
1354 pRange->deliveredEventsFirst > pRange->deliveredEventsLast)) {
1355 client->errorValue = pRange->deliveredEventsFirst;
1356 return BadValue2;
1357 }
1358 if ((pRange->deviceEventsFirst || pRange->deviceEventsLast) &&
1359 (pRange->deviceEventsFirst < 2 ||
1360 pRange->deviceEventsLast < 2 ||
1361 pRange->deviceEventsFirst > pRange->deviceEventsLast)) {
1362 client->errorValue = pRange->deviceEventsFirst;
1363 return BadValue2;
1364 }
1365 if (pRange->errorsFirst > pRange->errorsLast) {
1366 client->errorValue = pRange->errorsFirst;
1367 return BadValue2;
1368 }
1369 if (pRange->clientStarted != xFalse0 && pRange->clientStarted != xTrue1) {
1370 client->errorValue = pRange->clientStarted;
1371 return BadValue2;
1372 }
1373 if (pRange->clientDied != xFalse0 && pRange->clientDied != xTrue1) {
1374 client->errorValue = pRange->clientDied;
1375 return BadValue2;
1376 }
1377 } /* end for each range */
1378 return Success0;
1379} /* end RecordSanityCheckRegisterClients */
1380
1381/* This is a tactical structure used to gather information about all the sets
1382 * (RecordSetPtr) that need to be created for an RCAP in the process of
1383 * digesting a list of RECORDRANGEs (converting it to the internal
1384 * representation).
1385 */
1386typedef struct {
1387 int nintervals; /* number of intervals in following array */
1388 RecordSetInterval *intervals; /* array of intervals for this set */
1389 int size; /* size of intevals array; >= nintervals */
1390 int align; /* alignment restriction for set */
1391 int offset; /* where to store set pointer rel. to start of RCAP */
1392 short first, last; /* if for extension, major opcode interval */
1393} SetInfoRec, *SetInfoPtr;
1394
1395#if defined(ERR) && defined(__sun)
1396#undef ERR /* Avoid conflict with Solaris <sys/regset.h> */
1397#endif
1398
1399/* These constant are used to index into an array of SetInfoRec. */
1400enum { REQ, /* set info for requests */
1401 REP, /* set info for replies */
1402 ERR, /* set info for errors */
1403 DEV, /* set info for device events */
1404 DLEV, /* set info for delivered events */
1405 PREDEFSETS
1406}; /* number of predefined array entries */
1407
1408/* RecordAllocIntervals
1409 *
1410 * Arguments:
1411 * psi is a pointer to a SetInfoRec whose intervals pointer is NULL.
1412 * nIntervals is the desired size of the intervals array.
1413 *
1414 * Returns: BadAlloc if a memory allocation error occurred, else Success.
1415 *
1416 * Side Effects:
1417 * If Success is returned, psi->intervals is a pointer to size
1418 * RecordSetIntervals, all zeroed, and psi->size is set to size.
1419 */
1420static int
1421RecordAllocIntervals(SetInfoPtr psi, int nIntervals)
1422{
1423 assert(!psi->intervals)(__builtin_expect(!(!psi->intervals), 0) ? __assert_rtn(__func__
, "record.c", 1423, "!psi->intervals") : (void)0)
;
1424 psi->intervals = xallocarray(nIntervals, sizeof(RecordSetInterval))xreallocarray(((void*)0), (nIntervals), (sizeof(RecordSetInterval
)))
;
1425 if (!psi->intervals)
1426 return BadAlloc11;
1427 memset(psi->intervals, 0, nIntervals * sizeof(RecordSetInterval))__builtin___memset_chk (psi->intervals, 0, nIntervals * sizeof
(RecordSetInterval), __builtin_object_size (psi->intervals
, 0))
;
1428 psi->size = nIntervals;
1429 return Success0;
1430} /* end RecordAllocIntervals */
1431
1432/* RecordConvertRangesToIntervals
1433 *
1434 * Arguments:
1435 * psi is a pointer to the SetInfoRec we are building.
1436 * pRanges is an array of xRecordRanges.
1437 * nRanges is the number of elements in pRanges.
1438 * byteoffset is the offset from the start of an xRecordRange of the
1439 * two bytes (1 for first, 1 for last) we are interested in.
1440 * pExtSetInfo, if non-NULL, indicates that the two bytes mentioned
1441 * above are followed by four bytes (2 for first, 2 for last)
1442 * representing a minor opcode range, and this information should be
1443 * stored in one of the SetInfoRecs starting at pExtSetInfo.
1444 * pnExtSetInfo is the number of elements in the pExtSetInfo array.
1445 *
1446 * Returns: BadAlloc if a memory allocation error occurred, else Success.
1447 *
1448 * Side Effects:
1449 * The slice of pRanges indicated by byteoffset is stored in psi.
1450 * If pExtSetInfo is non-NULL, minor opcode intervals are stored
1451 * in an existing SetInfoRec if the major opcode interval matches, else
1452 * they are stored in a new SetInfoRec, and *pnExtSetInfo is
1453 * increased accordingly.
1454 */
1455static int
1456RecordConvertRangesToIntervals(SetInfoPtr psi,
1457 xRecordRange * pRanges,
1458 int nRanges,
1459 int byteoffset,
1460 SetInfoPtr pExtSetInfo, int *pnExtSetInfo)
1461{
1462 int i;
1463 CARD8 *pCARD8;
1464 int first, last;
1465 int err;
1466
1467 for (i = 0; i < nRanges; i++, pRanges++) {
1468 pCARD8 = ((CARD8 *) pRanges) + byteoffset;
1469 first = pCARD8[0];
1470 last = pCARD8[1];
1471 if (first || last) {
1472 if (!psi->intervals) {
1473 err = RecordAllocIntervals(psi, 2 * (nRanges - i));
1474 if (err != Success0)
1475 return err;
1476 }
1477 psi->intervals[psi->nintervals].first = first;
1478 psi->intervals[psi->nintervals].last = last;
1479 psi->nintervals++;
1480 assert(psi->nintervals <= psi->size)(__builtin_expect(!(psi->nintervals <= psi->size), 0
) ? __assert_rtn(__func__, "record.c", 1480, "psi->nintervals <= psi->size"
) : (void)0)
;
1481 if (pExtSetInfo) {
1482 SetInfoPtr pesi = pExtSetInfo;
1483 CARD16 *pCARD16 = (CARD16 *) (pCARD8 + 2);
1484 int j;
1485
1486 for (j = 0; j < *pnExtSetInfo; j++, pesi++) {
1487 if ((first == pesi->first) && (last == pesi->last))
1488 break;
1489 }
1490 if (j == *pnExtSetInfo) {
1491 err = RecordAllocIntervals(pesi, 2 * (nRanges - i));
1492 if (err != Success0)
1493 return err;
1494 pesi->first = first;
1495 pesi->last = last;
1496 (*pnExtSetInfo)++;
1497 }
1498 pesi->intervals[pesi->nintervals].first = pCARD16[0];
1499 pesi->intervals[pesi->nintervals].last = pCARD16[1];
1500 pesi->nintervals++;
1501 assert(pesi->nintervals <= pesi->size)(__builtin_expect(!(pesi->nintervals <= pesi->size),
0) ? __assert_rtn(__func__, "record.c", 1501, "pesi->nintervals <= pesi->size"
) : (void)0)
;
1502 }
1503 }
1504 }
1505 return Success0;
1506} /* end RecordConvertRangesToIntervals */
1507
1508#define offset_of(_structure, _field)((char *)(& (_structure . _field)) - (char *)(&_structure
))
\
1509 ((char *)(& (_structure . _field)) - (char *)(&_structure))
1510
1511/* RecordRegisterClients
1512 *
1513 * Arguments:
1514 * pContext is the context on which to register the clients.
1515 * client is the client that issued the RecordCreateContext or
1516 * RecordRegisterClients request.
1517 * stuff is a pointer to the request.
1518 *
1519 * Returns:
1520 * Any one of several possible error values defined by the protocol.
1521 * Success if everything is OK.
1522 *
1523 * Side Effects:
1524 * If different element headers are specified, the context is flushed.
1525 * If any of the specified clients are already registered on the
1526 * context, they are first unregistered. A new RCAP is created to
1527 * hold the specified protocol and clients, and it is linked onto the
1528 * context. If the context is enabled, appropriate hooks are installed
1529 * to record the new clients and protocol.
1530 */
1531static int
1532RecordRegisterClients(RecordContextPtr pContext, ClientPtr client,
1533 xRecordRegisterClientsReq * stuff)
1534{
1535 int err;
1536 int i;
1537 SetInfoPtr si;
1538 int maxSets;
1539 int nExtReqSets = 0;
1540 int nExtRepSets = 0;
1541 int extReqSetsOffset = 0;
1542 int extRepSetsOffset = 0;
1543 SetInfoPtr pExtReqSets, pExtRepSets;
1544 int clientListOffset;
1545 XID *pCanonClients;
1546 int clientStarted = 0, clientDied = 0;
1547 xRecordRange *pRanges, rr;
1548 int nClients;
1549 int sizeClients;
1550 int totRCAPsize;
1551 RecordClientsAndProtocolPtr pRCAP;
1552 int pad;
1553 XID recordingClient;
1554
1555 /* do all sanity checking up front */
1556
1557 err = RecordSanityCheckRegisterClients(pContext, client, stuff);
1558 if (err != Success0)
1559 return err;
1560
1561 /* if element headers changed, flush buffer */
1562
1563 if (pContext->elemHeaders != stuff->elementHeader) {
1564 RecordFlushReplyBuffer(pContext, NULL((void*)0), 0, NULL((void*)0), 0);
1565 pContext->elemHeaders = stuff->elementHeader;
1566 }
1567
1568 nClients = stuff->nClients;
1569 if (!nClients)
1570 /* if empty clients list, we're done. */
1571 return Success0;
1572
1573 recordingClient = pContext->pRecordingClient ?
1574 pContext->pRecordingClient->clientAsMask : 0;
1575 pCanonClients = RecordCanonicalizeClientSpecifiers((XID *) &stuff[1],
1576 &nClients,
1577 recordingClient);
1578 if (!pCanonClients)
1579 return BadAlloc11;
1580
1581 /* We may have to create as many as one set for each "predefined"
1582 * protocol types, plus one per range for extension reuests, plus one per
1583 * range for extension replies.
1584 */
1585 maxSets = PREDEFSETS + 2 * stuff->nRanges;
1586 si = xallocarray(maxSets, sizeof(SetInfoRec))xreallocarray(((void*)0), (maxSets), (sizeof(SetInfoRec)));
1587 if (!si) {
1588 err = BadAlloc11;
1589 goto bailout;
1590 }
1591 memset(si, 0, sizeof(SetInfoRec) * maxSets)__builtin___memset_chk (si, 0, sizeof(SetInfoRec) * maxSets, __builtin_object_size
(si, 0))
;
1592
1593 /* theoretically you must do this because NULL may not be all-bits-zero */
1594 for (i = 0; i < maxSets; i++)
1595 si[i].intervals = NULL((void*)0);
1596
1597 pExtReqSets = si + PREDEFSETS;
1598 pExtRepSets = pExtReqSets + stuff->nRanges;
1599
1600 pRanges = (xRecordRange *) (((XID *) &stuff[1]) + stuff->nClients);
1601
1602 err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges,
1603 offset_of(rr, coreRequestsFirst)((char *)(& (rr . coreRequestsFirst)) - (char *)(&rr)
)
, NULL((void*)0),
1604 NULL((void*)0));
1605 if (err != Success0)
1606 goto bailout;
1607
1608 err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges,
1609 offset_of(rr, extRequestsMajorFirst)((char *)(& (rr . extRequestsMajorFirst)) - (char *)(&
rr))
,
1610 pExtReqSets, &nExtReqSets);
1611 if (err != Success0)
1612 goto bailout;
1613
1614 err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges,
1615 offset_of(rr, coreRepliesFirst)((char *)(& (rr . coreRepliesFirst)) - (char *)(&rr)), NULL((void*)0),
1616 NULL((void*)0));
1617 if (err != Success0)
1618 goto bailout;
1619
1620 err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges,
1621 offset_of(rr, extRepliesMajorFirst)((char *)(& (rr . extRepliesMajorFirst)) - (char *)(&
rr))
,
1622 pExtRepSets, &nExtRepSets);
1623 if (err != Success0)
1624 goto bailout;
1625
1626 err = RecordConvertRangesToIntervals(&si[ERR], pRanges, stuff->nRanges,
1627 offset_of(rr, errorsFirst)((char *)(& (rr . errorsFirst)) - (char *)(&rr)), NULL((void*)0),
1628 NULL((void*)0));
1629 if (err != Success0)
1630 goto bailout;
1631
1632 err = RecordConvertRangesToIntervals(&si[DLEV], pRanges, stuff->nRanges,
1633 offset_of(rr, deliveredEventsFirst)((char *)(& (rr . deliveredEventsFirst)) - (char *)(&
rr))
,
1634 NULL((void*)0), NULL((void*)0));
1635 if (err != Success0)
1636 goto bailout;
1637
1638 err = RecordConvertRangesToIntervals(&si[DEV], pRanges, stuff->nRanges,
1639 offset_of(rr, deviceEventsFirst)((char *)(& (rr . deviceEventsFirst)) - (char *)(&rr)
)
, NULL((void*)0),
1640 NULL((void*)0));
1641 if (err != Success0)
1642 goto bailout;
1643
1644 /* collect client-started and client-died */
1645
1646 for (i = 0; i < stuff->nRanges; i++) {
1647 if (pRanges[i].clientStarted)
1648 clientStarted = TRUE1;
1649 if (pRanges[i].clientDied)
1650 clientDied = TRUE1;
1651 }
1652
1653 /* We now have all the information collected to create all the sets,
1654 * and we can compute the total memory required for the RCAP.
1655 */
1656
1657 totRCAPsize = sizeof(RecordClientsAndProtocolRec);
1658
1659 /* leave a little room to grow before forcing a separate allocation */
1660 sizeClients = nClients + CLIENT_ARRAY_GROWTH_INCREMENT4;
1661 pad = RecordPadAlign(totRCAPsize, sizeof(XID));
1662 clientListOffset = totRCAPsize + pad;
1663 totRCAPsize += pad + sizeClients * sizeof(XID);
1664
1665 if (nExtReqSets) {
1666 pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr));
1667 extReqSetsOffset = totRCAPsize + pad;
1668 totRCAPsize += pad + (nExtReqSets + 1) * sizeof(RecordMinorOpRec);
1669 }
1670 if (nExtRepSets) {
1671 pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr));
1672 extRepSetsOffset = totRCAPsize + pad;
1673 totRCAPsize += pad + (nExtRepSets + 1) * sizeof(RecordMinorOpRec);
1674 }
1675
1676 for (i = 0; i < maxSets; i++) {
1677 if (si[i].nintervals) {
1678 si[i].size =
1679 RecordSetMemoryRequirements(si[i].intervals, si[i].nintervals,
1680 &si[i].align);
1681 pad = RecordPadAlign(totRCAPsize, si[i].align);
1682 si[i].offset = pad + totRCAPsize;
1683 totRCAPsize += pad + si[i].size;
1684 }
1685 }
1686
1687 /* allocate memory for the whole RCAP */
1688
1689 pRCAP = (RecordClientsAndProtocolPtr) malloc(totRCAPsize);
1690 if (!pRCAP) {
1691 err = BadAlloc11;
1692 goto bailout;
1693 }
1694
1695 /* fill in the RCAP */
1696
1697 pRCAP->pContext = pContext;
1698 pRCAP->pClientIDs = (XID *) ((char *) pRCAP + clientListOffset);
1699 pRCAP->numClients = nClients;
1700 pRCAP->sizeClients = sizeClients;
1701 pRCAP->clientIDsSeparatelyAllocated = 0;
1702 for (i = 0; i < nClients; i++) {
1703 RecordDeleteClientFromContext(pContext, pCanonClients[i]);
1704 pRCAP->pClientIDs[i] = pCanonClients[i];
1705 }
1706
1707 /* create all the sets */
1708
1709 if (si[REQ].intervals) {
1710 pRCAP->pRequestMajorOpSet =
1711 RecordCreateSet(si[REQ].intervals, si[REQ].nintervals,
1712 (RecordSetPtr) ((char *) pRCAP + si[REQ].offset),
1713 si[REQ].size);
1714 }
1715 else
1716 pRCAP->pRequestMajorOpSet = NULL((void*)0);
1717
1718 if (si[REP].intervals) {
1719 pRCAP->pReplyMajorOpSet =
1720 RecordCreateSet(si[REP].intervals, si[REP].nintervals,
1721 (RecordSetPtr) ((char *) pRCAP + si[REP].offset),
1722 si[REP].size);
1723 }
1724 else
1725 pRCAP->pReplyMajorOpSet = NULL((void*)0);
1726
1727 if (si[ERR].intervals) {
1728 pRCAP->pErrorSet =
1729 RecordCreateSet(si[ERR].intervals, si[ERR].nintervals,
1730 (RecordSetPtr) ((char *) pRCAP + si[ERR].offset),
1731 si[ERR].size);
1732 }
1733 else
1734 pRCAP->pErrorSet = NULL((void*)0);
1735
1736 if (si[DEV].intervals) {
1737 pRCAP->pDeviceEventSet =
1738 RecordCreateSet(si[DEV].intervals, si[DEV].nintervals,
1739 (RecordSetPtr) ((char *) pRCAP + si[DEV].offset),
1740 si[DEV].size);
1741 }
1742 else
1743 pRCAP->pDeviceEventSet = NULL((void*)0);
1744
1745 if (si[DLEV].intervals) {
1746 pRCAP->pDeliveredEventSet =
1747 RecordCreateSet(si[DLEV].intervals, si[DLEV].nintervals,
1748 (RecordSetPtr) ((char *) pRCAP + si[DLEV].offset),
1749 si[DLEV].size);
1750 }
1751 else
1752 pRCAP->pDeliveredEventSet = NULL((void*)0);
1753
1754 if (nExtReqSets) {
1755 pRCAP->pRequestMinOpInfo = (RecordMinorOpPtr)
1756 ((char *) pRCAP + extReqSetsOffset);
1757 pRCAP->pRequestMinOpInfo[0].count = nExtReqSets;
1758 for (i = 0; i < nExtReqSets; i++, pExtReqSets++) {
1759 pRCAP->pRequestMinOpInfo[i + 1].major.first = pExtReqSets->first;
1760 pRCAP->pRequestMinOpInfo[i + 1].major.last = pExtReqSets->last;
1761 pRCAP->pRequestMinOpInfo[i + 1].major.pMinOpSet =
1762 RecordCreateSet(pExtReqSets->intervals,
1763 pExtReqSets->nintervals,
1764 (RecordSetPtr) ((char *) pRCAP +
1765 pExtReqSets->offset),
1766 pExtReqSets->size);
1767 }
1768 }
1769 else
1770 pRCAP->pRequestMinOpInfo = NULL((void*)0);
1771
1772 if (nExtRepSets) {
1773 pRCAP->pReplyMinOpInfo = (RecordMinorOpPtr)
1774 ((char *) pRCAP + extRepSetsOffset);
1775 pRCAP->pReplyMinOpInfo[0].count = nExtRepSets;
1776 for (i = 0; i < nExtRepSets; i++, pExtRepSets++) {
1777 pRCAP->pReplyMinOpInfo[i + 1].major.first = pExtRepSets->first;
1778 pRCAP->pReplyMinOpInfo[i + 1].major.last = pExtRepSets->last;
1779 pRCAP->pReplyMinOpInfo[i + 1].major.pMinOpSet =
1780 RecordCreateSet(pExtRepSets->intervals,
1781 pExtRepSets->nintervals,
1782 (RecordSetPtr) ((char *) pRCAP +
1783 pExtRepSets->offset),
1784 pExtRepSets->size);
1785 }
1786 }
1787 else
1788 pRCAP->pReplyMinOpInfo = NULL((void*)0);
1789
1790 pRCAP->clientStarted = clientStarted;
1791 pRCAP->clientDied = clientDied;
1792
1793 /* link the RCAP onto the context */
1794
1795 pRCAP->pNextRCAP = pContext->pListOfRCAP;
1796 pContext->pListOfRCAP = pRCAP;
1797
1798 if (pContext->pRecordingClient) /* context enabled */
1799 RecordInstallHooks(pRCAP, 0);
1800
1801 bailout:
1802 if (si) {
1803 for (i = 0; i < maxSets; i++)
1804 free(si[i].intervals);
1805 free(si);
1806 }
1807 if (pCanonClients && pCanonClients != (XID *) &stuff[1])
1808 free(pCanonClients);
1809 return err;
1810} /* RecordRegisterClients */
1811
1812/* Proc functions all take a client argument, execute the request in
1813 * client->requestBuffer, and return a protocol error status.
1814 */
1815
1816static int
1817ProcRecordQueryVersion(ClientPtr client)
1818{
1819 /* REQUEST(xRecordQueryVersionReq); */
1820 xRecordQueryVersionReply rep = {
1821 .type = X_Reply1,
1822 .sequenceNumber = client->sequence,
1823 .length = 0,
1824 .majorVersion = SERVER_RECORD_MAJOR_VERSION1,
1825 .minorVersion = SERVER_RECORD_MINOR_VERSION13
1826 };
1827
1828 REQUEST_SIZE_MATCH(xRecordQueryVersionReq)if ((sizeof(xRecordQueryVersionReq) >> 2) != client->
req_len) return(16)
;
1829 if (client->swapped) {
1830 swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber
) & 1) && ((uintptr_t)(&rep.sequenceNumber) &
1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber
)); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); }
while (0)
;
1831 swaps(&rep.majorVersion)do { if (sizeof(*(&rep.majorVersion)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&rep.majorVersion) &
1) && ((uintptr_t)(&rep.majorVersion) & 1) ==
0) *(&rep.majorVersion) = lswaps(*(&rep.majorVersion
)); else swap_uint16((uint16_t *)(&rep.majorVersion)); } while
(0)
;
1832 swaps(&rep.minorVersion)do { if (sizeof(*(&rep.minorVersion)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&rep.minorVersion) &
1) && ((uintptr_t)(&rep.minorVersion) & 1) ==
0) *(&rep.minorVersion) = lswaps(*(&rep.minorVersion
)); else swap_uint16((uint16_t *)(&rep.minorVersion)); } while
(0)
;
1833 }
1834 WriteToClient(client, sizeof(xRecordQueryVersionReply), &rep);
1835 return Success0;
1836} /* ProcRecordQueryVersion */
1837
1838static int
1839ProcRecordCreateContext(ClientPtr client)
1840{
1841 REQUEST(xRecordCreateContextReq)xRecordCreateContextReq *stuff = (xRecordCreateContextReq *)client
->requestBuffer
;
1842 RecordContextPtr pContext;
1843 RecordContextPtr *ppNewAllContexts = NULL((void*)0);
1844 int err = BadAlloc11;
1845
1846 REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq)if ((sizeof(xRecordCreateContextReq) >> 2) > client->
req_len ) return(16)
;
1847 LEGAL_NEW_RESOURCE(stuff->context, client)if (!LegalNewID(stuff->context,client)) { client->errorValue
= stuff->context; return 14; }
;
1848
1849 pContext = (RecordContextPtr) malloc(sizeof(RecordContextRec));
1850 if (!pContext)
1851 goto bailout;
1852
1853 /* make sure there is room in ppAllContexts to store the new context */
1854
1855 ppNewAllContexts =
1856 reallocarrayxreallocarray(ppAllContexts, numContexts + 1, sizeof(RecordContextPtr));
1857 if (!ppNewAllContexts)
1858 goto bailout;
1859 ppAllContexts = ppNewAllContexts;
1860
1861 pContext->id = stuff->context;
1862 pContext->pRecordingClient = NULL((void*)0);
1863 pContext->pListOfRCAP = NULL((void*)0);
1864 pContext->elemHeaders = 0;
1865 pContext->bufCategory = 0;
1866 pContext->numBufBytes = 0;
1867 pContext->pBufClient = NULL((void*)0);
1868 pContext->continuedReply = 0;
1869 pContext->inFlush = 0;
1870
1871 err = RecordRegisterClients(pContext, client,
1872 (xRecordRegisterClientsReq *) stuff);
1873 if (err != Success0)
1874 goto bailout;
1875
1876 if (AddResourceDarwin_X_AddResource(pContext->id, RTContext, pContext)) {
1877 ppAllContexts[numContexts++] = pContext;
1878 return Success0;
1879 }
1880 else {
1881 return BadAlloc11;
1882 }
1883 bailout:
1884 free(pContext);
1885 return err;
1886} /* ProcRecordCreateContext */
1887
1888static int
1889ProcRecordRegisterClients(ClientPtr client)
1890{
1891 RecordContextPtr pContext;
1892
1893 REQUEST(xRecordRegisterClientsReq)xRecordRegisterClientsReq *stuff = (xRecordRegisterClientsReq
*)client->requestBuffer
;
1894
1895 REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq)if ((sizeof(xRecordRegisterClientsReq) >> 2) > client
->req_len ) return(16)
;
1896 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
1897
1898 return RecordRegisterClients(pContext, client, stuff);
1899} /* ProcRecordRegisterClients */
1900
1901static int
1902ProcRecordUnregisterClients(ClientPtr client)
1903{
1904 RecordContextPtr pContext;
1905 int err;
1906
1907 REQUEST(xRecordUnregisterClientsReq)xRecordUnregisterClientsReq *stuff = (xRecordUnregisterClientsReq
*)client->requestBuffer
;
1908 XID *pCanonClients;
1909 int nClients;
1910 int i;
1911
1912 REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq)if ((sizeof(xRecordUnregisterClientsReq) >> 2) > client
->req_len ) return(16)
;
1913 if ((client->req_len << 2) - SIZEOF(xRecordUnregisterClientsReq)12 !=
1914 4 * stuff->nClients)
1915 return BadLength16;
1916 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
1917 err = RecordSanityCheckClientSpecifiers(client, (XID *) &stuff[1],
1918 stuff->nClients, 0);
1919 if (err != Success0)
1920 return err;
1921
1922 nClients = stuff->nClients;
1923 pCanonClients = RecordCanonicalizeClientSpecifiers((XID *) &stuff[1],
1924 &nClients, 0);
1925 if (!pCanonClients)
1926 return BadAlloc11;
1927
1928 for (i = 0; i < nClients; i++) {
1929 RecordDeleteClientFromContext(pContext, pCanonClients[i]);
1930 }
1931 if (pCanonClients != (XID *) &stuff[1])
1932 free(pCanonClients);
1933 return Success0;
1934} /* ProcRecordUnregisterClients */
1935
1936/****************************************************************************/
1937
1938/* stuff for GetContext */
1939
1940/* This is a tactical structure used to hold the xRecordRanges as they are
1941 * being reconstituted from the sets in the RCAPs.
1942 */
1943
1944typedef struct {
1945 xRecordRange *pRanges; /* array of xRecordRanges for one RCAP */
1946 int size; /* number of elements in pRanges, >= nRanges */
1947 int nRanges; /* number of occupied element of pRanges */
1948} GetContextRangeInfoRec, *GetContextRangeInfoPtr;
1949
1950/* RecordAllocRanges
1951 *
1952 * Arguments:
1953 * pri is a pointer to a GetContextRangeInfoRec to allocate for.
1954 * nRanges is the number of xRecordRanges desired for pri.
1955 *
1956 * Returns: BadAlloc if a memory allocation error occurred, else Success.
1957 *
1958 * Side Effects:
1959 * If Success is returned, pri->pRanges points to at least nRanges
1960 * ranges. pri->nRanges is set to nRanges. pri->size is the actual
1961 * number of ranges. Newly allocated ranges are zeroed.
1962 */
1963static int
1964RecordAllocRanges(GetContextRangeInfoPtr pri, int nRanges)
1965{
1966 int newsize;
1967 xRecordRange *pNewRange;
1968
1969#define SZINCR8 8
1970
1971 newsize = max(pri->size + SZINCR, nRanges)(((pri->size + 8) > (nRanges)) ? (pri->size + 8) : (
nRanges))
;
64
Within the expansion of the macro 'max':
1972 pNewRange = reallocarrayxreallocarray(pri->pRanges, newsize, sizeof(xRecordRange));
1973 if (!pNewRange)
65
Assuming 'pNewRange' is null
66
Taking true branch
1974 return BadAlloc11;
1975
1976 pri->pRanges = pNewRange;
1977 pri->size = newsize;
1978 memset(&pri->pRanges[pri->size - SZINCR], 0, SZINCR * sizeof(xRecordRange))__builtin___memset_chk (&pri->pRanges[pri->size - 8
], 0, 8 * sizeof(xRecordRange), __builtin_object_size (&pri
->pRanges[pri->size - 8], 0))
;
1979 if (pri->nRanges < nRanges)
1980 pri->nRanges = nRanges;
1981 return Success0;
1982} /* RecordAllocRanges */
1983
1984/* RecordConvertSetToRanges
1985 *
1986 * Arguments:
1987 * pSet is the set to be converted.
1988 * pri is where the result should be stored.
1989 * byteoffset is the offset from the start of an xRecordRange of the
1990 * two vales (first, last) we are interested in.
1991 * card8 is TRUE if the vales are one byte each and FALSE if two bytes
1992 * each.
1993 * imax is the largest set value to store in pri->pRanges.
1994 * pStartIndex, if non-NULL, is the index of the first range in
1995 * pri->pRanges that should be stored to. If NULL,
1996 * start at index 0.
1997 *
1998 * Returns: BadAlloc if a memory allocation error occurred, else Success.
1999 *
2000 * Side Effects:
2001 * If Success is returned, the slice of pri->pRanges indicated by
2002 * byteoffset and card8 is filled in with the intervals from pSet.
2003 * if pStartIndex was non-NULL, *pStartIndex is filled in with one
2004 * more than the index of the last xRecordRange that was touched.
2005 */
2006static int
2007RecordConvertSetToRanges(RecordSetPtr pSet,
2008 GetContextRangeInfoPtr pri,
2009 int byteoffset,
2010 Bool card8, unsigned int imax, int *pStartIndex)
2011{
2012 int nRanges;
2013 RecordSetIteratePtr pIter = NULL((void*)0);
2014 RecordSetInterval interval;
2015 CARD8 *pCARD8;
2016 CARD16 *pCARD16;
2017 int err;
2018
2019 if (!pSet)
9
Assuming 'pSet' is non-null
10
Taking false branch
17
Assuming 'pSet' is non-null
18
Taking false branch
25
Assuming 'pSet' is non-null
26
Taking false branch
33
Assuming 'pSet' is non-null
34
Taking false branch
41
Assuming 'pSet' is non-null
42
Taking false branch
2020 return Success0;
2021
2022 nRanges = pStartIndex ? *pStartIndex : 0;
11
'?' condition is false
19
'?' condition is false
27
'?' condition is false
35
'?' condition is false
43
'?' condition is false
2023 while ((pIter = RecordIterateSet(pSet, pIter, &interval)(*pSet->ops->IterateSet)( pSet, pIter, &interval))) {
12
Loop condition is false. Execution continues on line 2048
20
Loop condition is false. Execution continues on line 2048
28
Loop condition is false. Execution continues on line 2048
36
Loop condition is false. Execution continues on line 2048
44
Loop condition is false. Execution continues on line 2048
2024 if (interval.first > imax)
2025 break;
2026 if (interval.last > imax)
2027 interval.last = imax;
2028 nRanges++;
2029 if (nRanges > pri->size) {
2030 err = RecordAllocRanges(pri, nRanges);
2031 if (err != Success0)
2032 return err;
2033 }
2034 else
2035 pri->nRanges = max(pri->nRanges, nRanges)(((pri->nRanges) > (nRanges)) ? (pri->nRanges) : (nRanges
))
;
2036 if (card8) {
2037 pCARD8 = ((CARD8 *) &pri->pRanges[nRanges - 1]) + byteoffset;
2038 *pCARD8++ = interval.first;
2039 *pCARD8 = interval.last;
2040 }
2041 else {
2042 pCARD16 = (CARD16 *)
2043 (((char *) &pri->pRanges[nRanges - 1]) + byteoffset);
2044 *pCARD16++ = interval.first;
2045 *pCARD16 = interval.last;
2046 }
2047 }
2048 if (pStartIndex)
13
Taking false branch
21
Taking false branch
29
Taking false branch
37
Taking false branch
45
Taking false branch
2049 *pStartIndex = nRanges;
2050 return Success0;
2051} /* RecordConvertSetToRanges */
2052
2053/* RecordConvertMinorOpInfoToRanges
2054 *
2055 * Arguments:
2056 * pMinOpInfo is the minor opcode info to convert to xRecordRanges.
2057 * pri is where the result should be stored.
2058 * byteoffset is the offset from the start of an xRecordRange of the
2059 * four vales (CARD8 major_first, CARD8 major_last,
2060 * CARD16 minor_first, CARD16 minor_last) we are going to store.
2061 *
2062 * Returns: BadAlloc if a memory allocation error occurred, else Success.
2063 *
2064 * Side Effects:
2065 * If Success is returned, the slice of pri->pRanges indicated by
2066 * byteoffset is filled in with the information from pMinOpInfo.
2067 */
2068static int
2069RecordConvertMinorOpInfoToRanges(RecordMinorOpPtr pMinOpInfo,
2070 GetContextRangeInfoPtr pri, int byteoffset)
2071{
2072 int nsets;
2073 int start;
2074 int i;
2075 int err;
2076
2077 if (!pMinOpInfo)
49
Assuming 'pMinOpInfo' is non-null
50
Taking false branch
56
Assuming 'pMinOpInfo' is non-null
57
Taking false branch
2078 return Success0;
2079
2080 nsets = pMinOpInfo->count;
2081 pMinOpInfo++;
2082 start = 0;
2083 for (i = 0; i < nsets; i++) {
51
Assuming 'i' is >= 'nsets'
52
Loop condition is false. Execution continues on line 2098
58
Assuming 'i' is >= 'nsets'
59
Loop condition is false. Execution continues on line 2098
2084 int j, s;
2085
2086 s = start;
2087 err = RecordConvertSetToRanges(pMinOpInfo[i].major.pMinOpSet, pri,
2088 byteoffset + 2, FALSE0, 65535, &start);
2089 if (err != Success0)
2090 return err;
2091 for (j = s; j < start; j++) {
2092 CARD8 *pCARD8 = ((CARD8 *) &pri->pRanges[j]) + byteoffset;
2093
2094 *pCARD8++ = pMinOpInfo[i].major.first;
2095 *pCARD8 = pMinOpInfo[i].major.last;
2096 }
2097 }
2098 return Success0;
2099} /* RecordConvertMinorOpInfoToRanges */
2100
2101/* RecordSwapRanges
2102 *
2103 * Arguments:
2104 * pRanges is an array of xRecordRanges.
2105 * nRanges is the number of elements in pRanges.
2106 *
2107 * Returns: nothing.
2108 *
2109 * Side Effects:
2110 * The 16 bit fields of each xRecordRange are byte swapped.
2111 */
2112static void
2113RecordSwapRanges(xRecordRange * pRanges, int nRanges)
2114{
2115 int i;
2116
2117 for (i = 0; i < nRanges; i++, pRanges++) {
2118 swaps(&pRanges->extRequestsMinorFirst)do { if (sizeof(*(&pRanges->extRequestsMinorFirst)) !=
2) wrong_size(); if (__builtin_constant_p((uintptr_t)(&pRanges
->extRequestsMinorFirst) & 1) && ((uintptr_t)(
&pRanges->extRequestsMinorFirst) & 1) == 0) *(&
pRanges->extRequestsMinorFirst) = lswaps(*(&pRanges->
extRequestsMinorFirst)); else swap_uint16((uint16_t *)(&pRanges
->extRequestsMinorFirst)); } while (0)
;
2119 swaps(&pRanges->extRequestsMinorLast)do { if (sizeof(*(&pRanges->extRequestsMinorLast)) != 2
) wrong_size(); if (__builtin_constant_p((uintptr_t)(&pRanges
->extRequestsMinorLast) & 1) && ((uintptr_t)(&
pRanges->extRequestsMinorLast) & 1) == 0) *(&pRanges
->extRequestsMinorLast) = lswaps(*(&pRanges->extRequestsMinorLast
)); else swap_uint16((uint16_t *)(&pRanges->extRequestsMinorLast
)); } while (0)
;
2120 swaps(&pRanges->extRepliesMinorFirst)do { if (sizeof(*(&pRanges->extRepliesMinorFirst)) != 2
) wrong_size(); if (__builtin_constant_p((uintptr_t)(&pRanges
->extRepliesMinorFirst) & 1) && ((uintptr_t)(&
pRanges->extRepliesMinorFirst) & 1) == 0) *(&pRanges
->extRepliesMinorFirst) = lswaps(*(&pRanges->extRepliesMinorFirst
)); else swap_uint16((uint16_t *)(&pRanges->extRepliesMinorFirst
)); } while (0)
;
2121 swaps(&pRanges->extRepliesMinorLast)do { if (sizeof(*(&pRanges->extRepliesMinorLast)) != 2
) wrong_size(); if (__builtin_constant_p((uintptr_t)(&pRanges
->extRepliesMinorLast) & 1) && ((uintptr_t)(&
pRanges->extRepliesMinorLast) & 1) == 0) *(&pRanges
->extRepliesMinorLast) = lswaps(*(&pRanges->extRepliesMinorLast
)); else swap_uint16((uint16_t *)(&pRanges->extRepliesMinorLast
)); } while (0)
;
2122 }
2123} /* RecordSwapRanges */
2124
2125static int
2126ProcRecordGetContext(ClientPtr client)
2127{
2128 RecordContextPtr pContext;
2129
2130 REQUEST(xRecordGetContextReq)xRecordGetContextReq *stuff = (xRecordGetContextReq *)client->
requestBuffer
;
2131 xRecordGetContextReply rep;
2132 RecordClientsAndProtocolPtr pRCAP;
2133 int nRCAPs = 0;
2134 GetContextRangeInfoPtr pRangeInfo;
2135 GetContextRangeInfoPtr pri;
2136 int i;
2137 int err;
2138 CARD32 nClients, length;
2139
2140 REQUEST_SIZE_MATCH(xRecordGetContextReq)if ((sizeof(xRecordGetContextReq) >> 2) != client->req_len
) return(16)
;
2141 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2142
2143 /* how many RCAPs are there on this context? */
2144
2145 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP)
1
Loop condition is true. Entering loop body
2
Loop condition is false. Execution continues on line 2150
2146 nRCAPs++;
2147
2148 /* allocate and initialize space for record range info */
2149
2150 pRangeInfo = xallocarray(nRCAPs, sizeof(GetContextRangeInfoRec))xreallocarray(((void*)0), (nRCAPs), (sizeof(GetContextRangeInfoRec
)))
;
2151 if (!pRangeInfo && nRCAPs > 0)
3
Assuming 'pRangeInfo' is non-null
2152 return BadAlloc11;
2153 for (i = 0; i < nRCAPs; i++) {
4
Loop condition is true. Entering loop body
6
Loop condition is false. Execution continues on line 2164
2154 pRangeInfo[i].pRanges = NULL((void*)0);
5
Null pointer value stored to field 'pRanges'
2155 pRangeInfo[i].size = 0;
2156 pRangeInfo[i].nRanges = 0;
2157 }
2158
2159 /* convert the RCAP (internal) representation of the recorded protocol
2160 * to the wire protocol (external) representation, storing the information
2161 * for the ith RCAP in pri[i]
2162 */
2163
2164 for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo;
7
Loop condition is true. Entering loop body
2165 pRCAP; pRCAP = pRCAP->pNextRCAP, pri++) {
2166 xRecordRange rr;
2167
2168 err = RecordConvertSetToRanges(pRCAP->pRequestMajorOpSet, pri,
8
Calling 'RecordConvertSetToRanges'
14
Returning from 'RecordConvertSetToRanges'
2169 offset_of(rr, coreRequestsFirst)((char *)(& (rr . coreRequestsFirst)) - (char *)(&rr)
)
, TRUE1,
2170 127, NULL((void*)0));
2171 if (err != Success0)
15
Taking false branch
2172 goto bailout;
2173
2174 err = RecordConvertSetToRanges(pRCAP->pReplyMajorOpSet, pri,
16
Calling 'RecordConvertSetToRanges'
22
Returning from 'RecordConvertSetToRanges'
2175 offset_of(rr, coreRepliesFirst)((char *)(& (rr . coreRepliesFirst)) - (char *)(&rr)), TRUE1,
2176 127, NULL((void*)0));
2177 if (err != Success0)
23
Taking false branch
2178 goto bailout;
2179
2180 err = RecordConvertSetToRanges(pRCAP->pDeliveredEventSet, pri,
24
Calling 'RecordConvertSetToRanges'
30
Returning from 'RecordConvertSetToRanges'
2181 offset_of(rr, deliveredEventsFirst)((char *)(& (rr . deliveredEventsFirst)) - (char *)(&
rr))
,
2182 TRUE1, 255, NULL((void*)0));
2183 if (err != Success0)
31
Taking false branch
2184 goto bailout;
2185
2186 err = RecordConvertSetToRanges(pRCAP->pDeviceEventSet, pri,
32
Calling 'RecordConvertSetToRanges'
38
Returning from 'RecordConvertSetToRanges'
2187 offset_of(rr, deviceEventsFirst)((char *)(& (rr . deviceEventsFirst)) - (char *)(&rr)
)
, TRUE1,
2188 255, NULL((void*)0));
2189 if (err != Success0)
39
Taking false branch
2190 goto bailout;
2191
2192 err = RecordConvertSetToRanges(pRCAP->pErrorSet, pri,
40
Calling 'RecordConvertSetToRanges'
46
Returning from 'RecordConvertSetToRanges'
2193 offset_of(rr, errorsFirst)((char *)(& (rr . errorsFirst)) - (char *)(&rr)), TRUE1, 255,
2194 NULL((void*)0));
2195 if (err != Success0)
47
Taking false branch
2196 goto bailout;
2197
2198 err = RecordConvertMinorOpInfoToRanges(pRCAP->pRequestMinOpInfo,
48
Calling 'RecordConvertMinorOpInfoToRanges'
53
Returning from 'RecordConvertMinorOpInfoToRanges'
2199 pri, offset_of(rr,((char *)(& (rr . extRequestsMajorFirst)) - (char *)(&
rr))
2200 extRequestsMajorFirst)((char *)(& (rr . extRequestsMajorFirst)) - (char *)(&
rr))
)
;
2201 if (err != Success0)
54
Taking false branch
2202 goto bailout;
2203
2204 err = RecordConvertMinorOpInfoToRanges(pRCAP->pReplyMinOpInfo,
55
Calling 'RecordConvertMinorOpInfoToRanges'
60
Returning from 'RecordConvertMinorOpInfoToRanges'
2205 pri, offset_of(rr,((char *)(& (rr . extRepliesMajorFirst)) - (char *)(&
rr))
2206 extRepliesMajorFirst)((char *)(& (rr . extRepliesMajorFirst)) - (char *)(&
rr))
)
;
2207 if (err != Success0)
61
Taking false branch
2208 goto bailout;
2209
2210 if (pRCAP->clientStarted || pRCAP->clientDied) {
2211 if (pri->nRanges == 0)
62
Taking true branch
2212 RecordAllocRanges(pri, 1);
63
Calling 'RecordAllocRanges'
67
Returning from 'RecordAllocRanges'
2213 pri->pRanges[0].clientStarted = pRCAP->clientStarted;
68
Dereference of null pointer
2214 pri->pRanges[0].clientDied = pRCAP->clientDied;
2215 }
2216 }
2217
2218 /* calculate number of clients and reply length */
2219
2220 nClients = 0;
2221 length = 0;
2222 for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo;
2223 pRCAP; pRCAP = pRCAP->pNextRCAP, pri++) {
2224 nClients += pRCAP->numClients;
2225 length += pRCAP->numClients *
2226 (bytes_to_int32(sizeof(xRecordClientInfo)) +
2227 pri->nRanges * bytes_to_int32(sizeof(xRecordRange)));
2228 }
2229
2230 /* write the reply header */
2231
2232 rep = (xRecordGetContextReply) {
2233 .type = X_Reply1,
2234 .enabled = pContext->pRecordingClient != NULL((void*)0),
2235 .sequenceNumber = client->sequence,
2236 .length = length,
2237 .elementHeader = pContext->elemHeaders,
2238 .nClients = nClients
2239 };
2240 if (client->swapped) {
2241 swaps(&rep.sequenceNumber)do { if (sizeof(*(&rep.sequenceNumber)) != 2) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&rep.sequenceNumber
) & 1) && ((uintptr_t)(&rep.sequenceNumber) &
1) == 0) *(&rep.sequenceNumber) = lswaps(*(&rep.sequenceNumber
)); else swap_uint16((uint16_t *)(&rep.sequenceNumber)); }
while (0)
;
2242 swapl(&rep.length)do { if (sizeof(*(&rep.length)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(&rep.length) & 3) && ((uintptr_t
)(&rep.length) & 3) == 0) *(&rep.length) = lswapl
(*(&rep.length)); else swap_uint32((uint32_t *)(&rep.
length)); } while (0)
;
2243 swapl(&rep.nClients)do { if (sizeof(*(&rep.nClients)) != 4) wrong_size(); if (
__builtin_constant_p((uintptr_t)(&rep.nClients) & 3) &&
((uintptr_t)(&rep.nClients) & 3) == 0) *(&rep.nClients
) = lswapl(*(&rep.nClients)); else swap_uint32((uint32_t *
)(&rep.nClients)); } while (0)
;
2244 }
2245 WriteToClient(client, sizeof(xRecordGetContextReply), &rep);
2246
2247 /* write all the CLIENT_INFOs */
2248
2249 for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo;
2250 pRCAP; pRCAP = pRCAP->pNextRCAP, pri++) {
2251 xRecordClientInfo rci;
2252
2253 rci.nRanges = pri->nRanges;
2254 if (client->swapped) {
2255 swapl(&rci.nRanges)do { if (sizeof(*(&rci.nRanges)) != 4) wrong_size(); if (
__builtin_constant_p((uintptr_t)(&rci.nRanges) & 3) &&
((uintptr_t)(&rci.nRanges) & 3) == 0) *(&rci.nRanges
) = lswapl(*(&rci.nRanges)); else swap_uint32((uint32_t *
)(&rci.nRanges)); } while (0)
;
2256 RecordSwapRanges(pri->pRanges, pri->nRanges);
2257 }
2258 for (i = 0; i < pRCAP->numClients; i++) {
2259 rci.clientResource = pRCAP->pClientIDs[i];
2260 if (client->swapped)
2261 swapl(&rci.clientResource)do { if (sizeof(*(&rci.clientResource)) != 4) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&rci.clientResource
) & 3) && ((uintptr_t)(&rci.clientResource) &
3) == 0) *(&rci.clientResource) = lswapl(*(&rci.clientResource
)); else swap_uint32((uint32_t *)(&rci.clientResource)); }
while (0)
;
2262 WriteToClient(client, sizeof(xRecordClientInfo), &rci);
2263 WriteToClient(client, sizeof(xRecordRange) * pri->nRanges,
2264 pri->pRanges);
2265 }
2266 }
2267 err = Success0;
2268
2269 bailout:
2270 for (i = 0; i < nRCAPs; i++) {
2271 free(pRangeInfo[i].pRanges);
2272 }
2273 free(pRangeInfo);
2274 return err;
2275} /* ProcRecordGetContext */
2276
2277static int
2278ProcRecordEnableContext(ClientPtr client)
2279{
2280 RecordContextPtr pContext;
2281
2282 REQUEST(xRecordEnableContextReq)xRecordEnableContextReq *stuff = (xRecordEnableContextReq *)client
->requestBuffer
;
2283 int i;
2284 RecordClientsAndProtocolPtr pRCAP;
2285
2286 REQUEST_SIZE_MATCH(xRecordGetContextReq)if ((sizeof(xRecordGetContextReq) >> 2) != client->req_len
) return(16)
;
2287 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2288 if (pContext->pRecordingClient)
2289 return BadMatch8; /* already enabled */
2290
2291 /* install record hooks for each RCAP */
2292
2293 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
2294 int err = RecordInstallHooks(pRCAP, 0);
2295
2296 if (err != Success0) { /* undo the previous installs */
2297 RecordClientsAndProtocolPtr pUninstallRCAP;
2298
2299 for (pUninstallRCAP = pContext->pListOfRCAP;
2300 pUninstallRCAP != pRCAP;
2301 pUninstallRCAP = pUninstallRCAP->pNextRCAP) {
2302 RecordUninstallHooks(pUninstallRCAP, 0);
2303 }
2304 return err;
2305 }
2306 }
2307
2308 /* Disallow further request processing on this connection until
2309 * the context is disabled.
2310 */
2311 IgnoreClient(client);
2312 pContext->pRecordingClient = client;
2313
2314 /* Don't allow the data connection to record itself; unregister it. */
2315 RecordDeleteClientFromContext(pContext,
2316 pContext->pRecordingClient->clientAsMask);
2317
2318 /* move the newly enabled context to the front part of ppAllContexts,
2319 * where all the enabled contexts are
2320 */
2321 i = RecordFindContextOnAllContexts(pContext);
2322 assert(i >= numEnabledContexts)(__builtin_expect(!(i >= numEnabledContexts), 0) ? __assert_rtn
(__func__, "record.c", 2322, "i >= numEnabledContexts") : (
void)0)
;
2323 if (i != numEnabledContexts) {
2324 ppAllContexts[i] = ppAllContexts[numEnabledContexts];
2325 ppAllContexts[numEnabledContexts] = pContext;
2326 }
2327
2328 ++numEnabledContexts;
2329 assert(numEnabledContexts > 0)(__builtin_expect(!(numEnabledContexts > 0), 0) ? __assert_rtn
(__func__, "record.c", 2329, "numEnabledContexts > 0") : (
void)0)
;
2330
2331 /* send StartOfData */
2332 RecordAProtocolElement(pContext, NULL((void*)0), XRecordStartOfData4, NULL((void*)0), 0, 0, 0);
2333 RecordFlushReplyBuffer(pContext, NULL((void*)0), 0, NULL((void*)0), 0);
2334 return Success0;
2335} /* ProcRecordEnableContext */
2336
2337/* RecordDisableContext
2338 *
2339 * Arguments:
2340 * pContext is the context to disable.
2341 * nRanges is the number of elements in pRanges.
2342 *
2343 * Returns: nothing.
2344 *
2345 * Side Effects:
2346 * If the context was enabled, it is disabled. An EndOfData
2347 * message is sent to the recording client. Recording hooks for
2348 * this context are uninstalled. The context is moved to the
2349 * rear part of the ppAllContexts array. numEnabledContexts is
2350 * decremented. Request processing for the formerly recording client
2351 * is resumed.
2352 */
2353static void
2354RecordDisableContext(RecordContextPtr pContext)
2355{
2356 RecordClientsAndProtocolPtr pRCAP;
2357 int i;
2358
2359 if (!pContext->pRecordingClient)
2360 return;
2361 if (!pContext->pRecordingClient->clientGone) {
2362 RecordAProtocolElement(pContext, NULL((void*)0), XRecordEndOfData5, NULL((void*)0), 0, 0, 0);
2363 RecordFlushReplyBuffer(pContext, NULL((void*)0), 0, NULL((void*)0), 0);
2364 /* Re-enable request processing on this connection. */
2365 AttendClient(pContext->pRecordingClient);
2366 }
2367
2368 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
2369 RecordUninstallHooks(pRCAP, 0);
2370 }
2371
2372 pContext->pRecordingClient = NULL((void*)0);
2373
2374 /* move the newly disabled context to the rear part of ppAllContexts,
2375 * where all the disabled contexts are
2376 */
2377 i = RecordFindContextOnAllContexts(pContext);
2378 assert((i != -1) && (i < numEnabledContexts))(__builtin_expect(!((i != -1) && (i < numEnabledContexts
)), 0) ? __assert_rtn(__func__, "record.c", 2378, "(i != -1) && (i < numEnabledContexts)"
) : (void)0)
;
2379 if (i != (numEnabledContexts - 1)) {
2380 ppAllContexts[i] = ppAllContexts[numEnabledContexts - 1];
2381 ppAllContexts[numEnabledContexts - 1] = pContext;
2382 }
2383 --numEnabledContexts;
2384 assert(numEnabledContexts >= 0)(__builtin_expect(!(numEnabledContexts >= 0), 0) ? __assert_rtn
(__func__, "record.c", 2384, "numEnabledContexts >= 0") : (
void)0)
;
2385} /* RecordDisableContext */
2386
2387static int
2388ProcRecordDisableContext(ClientPtr client)
2389{
2390 RecordContextPtr pContext;
2391
2392 REQUEST(xRecordDisableContextReq)xRecordDisableContextReq *stuff = (xRecordDisableContextReq *
)client->requestBuffer
;
2393
2394 REQUEST_SIZE_MATCH(xRecordDisableContextReq)if ((sizeof(xRecordDisableContextReq) >> 2) != client->
req_len) return(16)
;
2395 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2396 RecordDisableContext(pContext);
2397 return Success0;
2398} /* ProcRecordDisableContext */
2399
2400/* RecordDeleteContext
2401 *
2402 * Arguments:
2403 * value is the context to delete.
2404 * id is its resource ID.
2405 *
2406 * Returns: Success.
2407 *
2408 * Side Effects:
2409 * Disables the context, frees all associated memory, and removes
2410 * it from the ppAllContexts array.
2411 */
2412static int
2413RecordDeleteContext(void *value, XID id)
2414{
2415 int i;
2416 RecordContextPtr pContext = (RecordContextPtr) value;
2417 RecordClientsAndProtocolPtr pRCAP;
2418
2419 RecordDisableContext(pContext);
2420
2421 /* Remove all the clients from all the RCAPs.
2422 * As a result, the RCAPs will be freed.
2423 */
2424
2425 while ((pRCAP = pContext->pListOfRCAP)) {
2426 int numClients = pRCAP->numClients;
2427
2428 /* when the last client is deleted, the RCAP will go away. */
2429 while (numClients--) {
2430 RecordDeleteClientFromRCAP(pRCAP, numClients);
2431 }
2432 }
2433
2434 /* remove context from AllContexts list */
2435
2436 if (-1 != (i = RecordFindContextOnAllContexts(pContext))) {
2437 ppAllContexts[i] = ppAllContexts[numContexts - 1];
2438 if (--numContexts == 0) {
2439 free(ppAllContexts);
2440 ppAllContexts = NULL((void*)0);
2441 }
2442 }
2443 free(pContext);
2444
2445 return Success0;
2446} /* RecordDeleteContext */
2447
2448static int
2449ProcRecordFreeContext(ClientPtr client)
2450{
2451 RecordContextPtr pContext;
2452
2453 REQUEST(xRecordFreeContextReq)xRecordFreeContextReq *stuff = (xRecordFreeContextReq *)client
->requestBuffer
;
2454
2455 REQUEST_SIZE_MATCH(xRecordFreeContextReq)if ((sizeof(xRecordFreeContextReq) >> 2) != client->
req_len) return(16)
;
2456 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2457 FreeResource(stuff->context, RT_NONE((RESTYPE)0));
2458 return Success0;
2459} /* ProcRecordFreeContext */
2460
2461static int
2462ProcRecordDispatch(ClientPtr client)
2463{
2464 REQUEST(xReq)xReq *stuff = (xReq *)client->requestBuffer;
2465
2466 switch (stuff->data) {
2467 case X_RecordQueryVersion0:
2468 return ProcRecordQueryVersion(client);
2469 case X_RecordCreateContext1:
2470 return ProcRecordCreateContext(client);
2471 case X_RecordRegisterClients2:
2472 return ProcRecordRegisterClients(client);
2473 case X_RecordUnregisterClients3:
2474 return ProcRecordUnregisterClients(client);
2475 case X_RecordGetContext4:
2476 return ProcRecordGetContext(client);
2477 case X_RecordEnableContext5:
2478 return ProcRecordEnableContext(client);
2479 case X_RecordDisableContext6:
2480 return ProcRecordDisableContext(client);
2481 case X_RecordFreeContext7:
2482 return ProcRecordFreeContext(client);
2483 default:
2484 return BadRequest1;
2485 }
2486} /* ProcRecordDispatch */
2487
2488static int
2489SProcRecordQueryVersion(ClientPtr client)
2490{
2491 REQUEST(xRecordQueryVersionReq)xRecordQueryVersionReq *stuff = (xRecordQueryVersionReq *)client
->requestBuffer
;
2492
2493 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2494 REQUEST_SIZE_MATCH(xRecordQueryVersionReq)if ((sizeof(xRecordQueryVersionReq) >> 2) != client->
req_len) return(16)
;
2495 swaps(&stuff->majorVersion)do { if (sizeof(*(&stuff->majorVersion)) != 2) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&stuff->majorVersion
) & 1) && ((uintptr_t)(&stuff->majorVersion
) & 1) == 0) *(&stuff->majorVersion) = lswaps(*(&
stuff->majorVersion)); else swap_uint16((uint16_t *)(&
stuff->majorVersion)); } while (0)
;
2496 swaps(&stuff->minorVersion)do { if (sizeof(*(&stuff->minorVersion)) != 2) wrong_size
(); if (__builtin_constant_p((uintptr_t)(&stuff->minorVersion
) & 1) && ((uintptr_t)(&stuff->minorVersion
) & 1) == 0) *(&stuff->minorVersion) = lswaps(*(&
stuff->minorVersion)); else swap_uint16((uint16_t *)(&
stuff->minorVersion)); } while (0)
;
2497 return ProcRecordQueryVersion(client);
2498} /* SProcRecordQueryVersion */
2499
2500static int
2501SwapCreateRegister(xRecordRegisterClientsReq * stuff)
2502{
2503 int i;
2504 XID *pClientID;
2505
2506 swapl(&stuff->context)do { if (sizeof(*(&stuff->context)) != 4) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&stuff->context
) & 3) && ((uintptr_t)(&stuff->context) &
3) == 0) *(&stuff->context) = lswapl(*(&stuff->
context)); else swap_uint32((uint32_t *)(&stuff->context
)); } while (0)
;
2507 swapl(&stuff->nClients)do { if (sizeof(*(&stuff->nClients)) != 4) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&stuff->nClients
) & 3) && ((uintptr_t)(&stuff->nClients) &
3) == 0) *(&stuff->nClients) = lswapl(*(&stuff->
nClients)); else swap_uint32((uint32_t *)(&stuff->nClients
)); } while (0)
;
2508 swapl(&stuff->nRanges)do { if (sizeof(*(&stuff->nRanges)) != 4) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&stuff->nRanges
) & 3) && ((uintptr_t)(&stuff->nRanges) &
3) == 0) *(&stuff->nRanges) = lswapl(*(&stuff->
nRanges)); else swap_uint32((uint32_t *)(&stuff->nRanges
)); } while (0)
;
2509 pClientID = (XID *) &stuff[1];
2510 if (stuff->nClients >
2511 stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq20))
2512 return BadLength16;
2513 for (i = 0; i < stuff->nClients; i++, pClientID++) {
2514 swapl(pClientID)do { if (sizeof(*(pClientID)) != 4) wrong_size(); if (__builtin_constant_p
((uintptr_t)(pClientID) & 3) && ((uintptr_t)(pClientID
) & 3) == 0) *(pClientID) = lswapl(*(pClientID)); else swap_uint32
((uint32_t *)(pClientID)); } while (0)
;
2515 }
2516 if (stuff->nRanges >
2517 stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq20)
2518 - stuff->nClients)
2519 return BadLength16;
2520 RecordSwapRanges((xRecordRange *) pClientID, stuff->nRanges);
2521 return Success0;
2522} /* SwapCreateRegister */
2523
2524static int
2525SProcRecordCreateContext(ClientPtr client)
2526{
2527 REQUEST(xRecordCreateContextReq)xRecordCreateContextReq *stuff = (xRecordCreateContextReq *)client
->requestBuffer
;
2528 int status;
2529
2530 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2531 REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq)if ((sizeof(xRecordCreateContextReq) >> 2) > client->
req_len ) return(16)
;
2532 if ((status = SwapCreateRegister((void *) stuff)) != Success0)
2533 return status;
2534 return ProcRecordCreateContext(client);
2535} /* SProcRecordCreateContext */
2536
2537static int
2538SProcRecordRegisterClients(ClientPtr client)
2539{
2540 REQUEST(xRecordRegisterClientsReq)xRecordRegisterClientsReq *stuff = (xRecordRegisterClientsReq
*)client->requestBuffer
;
2541 int status;
2542
2543 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2544 REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq)if ((sizeof(xRecordRegisterClientsReq) >> 2) > client
->req_len ) return(16)
;
2545 if ((status = SwapCreateRegister((void *) stuff)) != Success0)
2546 return status;
2547 return ProcRecordRegisterClients(client);
2548} /* SProcRecordRegisterClients */
2549
2550static int
2551SProcRecordUnregisterClients(ClientPtr client)
2552{
2553 REQUEST(xRecordUnregisterClientsReq)xRecordUnregisterClientsReq *stuff = (xRecordUnregisterClientsReq
*)client->requestBuffer
;
2554
2555 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2556 REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq)if ((sizeof(xRecordUnregisterClientsReq) >> 2) > client
->req_len ) return(16)
;
2557 swapl(&stuff->context)do { if (sizeof(*(&stuff->context)) != 4) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&stuff->context
) & 3) && ((uintptr_t)(&stuff->context) &
3) == 0) *(&stuff->context) = lswapl(*(&stuff->
context)); else swap_uint32((uint32_t *)(&stuff->context
)); } while (0)
;
2558 swapl(&stuff->nClients)do { if (sizeof(*(&stuff->nClients)) != 4) wrong_size(
); if (__builtin_constant_p((uintptr_t)(&stuff->nClients
) & 3) && ((uintptr_t)(&stuff->nClients) &
3) == 0) *(&stuff->nClients) = lswapl(*(&stuff->
nClients)); else swap_uint32((uint32_t *)(&stuff->nClients
)); } while (0)
;
2559 SwapRestL(stuff)SwapLongs((CARD32 *)(stuff + 1), (client->req_len - (sizeof
(*stuff) >> 2)))
;
2560 return ProcRecordUnregisterClients(client);
2561} /* SProcRecordUnregisterClients */
2562
2563static int
2564SProcRecordGetContext(ClientPtr client)
2565{
2566 REQUEST(xRecordGetContextReq)xRecordGetContextReq *stuff = (xRecordGetContextReq *)client->
requestBuffer
;
2567
2568 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2569 REQUEST_SIZE_MATCH(xRecordGetContextReq)if ((sizeof(xRecordGetContextReq) >> 2) != client->req_len
) return(16)
;
2570 swapl(&stuff->context)do { if (sizeof(*(&stuff->context)) != 4) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&stuff->context
) & 3) && ((uintptr_t)(&stuff->context) &
3) == 0) *(&stuff->context) = lswapl(*(&stuff->
context)); else swap_uint32((uint32_t *)(&stuff->context
)); } while (0)
;
2571 return ProcRecordGetContext(client);
2572} /* SProcRecordGetContext */
2573
2574static int
2575SProcRecordEnableContext(ClientPtr client)
2576{
2577 REQUEST(xRecordEnableContextReq)xRecordEnableContextReq *stuff = (xRecordEnableContextReq *)client
->requestBuffer
;
2578
2579 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2580 REQUEST_SIZE_MATCH(xRecordEnableContextReq)if ((sizeof(xRecordEnableContextReq) >> 2) != client->
req_len) return(16)
;
2581 swapl(&stuff->context)do { if (sizeof(*(&stuff->context)) != 4) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&stuff->context
) & 3) && ((uintptr_t)(&stuff->context) &
3) == 0) *(&stuff->context) = lswapl(*(&stuff->
context)); else swap_uint32((uint32_t *)(&stuff->context
)); } while (0)
;
2582 return ProcRecordEnableContext(client);
2583} /* SProcRecordEnableContext */
2584
2585static int
2586SProcRecordDisableContext(ClientPtr client)
2587{
2588 REQUEST(xRecordDisableContextReq)xRecordDisableContextReq *stuff = (xRecordDisableContextReq *
)client->requestBuffer
;
2589
2590 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2591 REQUEST_SIZE_MATCH(xRecordDisableContextReq)if ((sizeof(xRecordDisableContextReq) >> 2) != client->
req_len) return(16)
;
2592 swapl(&stuff->context)do { if (sizeof(*(&stuff->context)) != 4) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&stuff->context
) & 3) && ((uintptr_t)(&stuff->context) &
3) == 0) *(&stuff->context) = lswapl(*(&stuff->
context)); else swap_uint32((uint32_t *)(&stuff->context
)); } while (0)
;
2593 return ProcRecordDisableContext(client);
2594} /* SProcRecordDisableContext */
2595
2596static int
2597SProcRecordFreeContext(ClientPtr client)
2598{
2599 REQUEST(xRecordFreeContextReq)xRecordFreeContextReq *stuff = (xRecordFreeContextReq *)client
->requestBuffer
;
2600
2601 swaps(&stuff->length)do { if (sizeof(*(&stuff->length)) != 2) wrong_size();
if (__builtin_constant_p((uintptr_t)(&stuff->length) &
1) && ((uintptr_t)(&stuff->length) & 1) ==
0) *(&stuff->length) = lswaps(*(&stuff->length
)); else swap_uint16((uint16_t *)(&stuff->length)); } while
(0)
;
2602 REQUEST_SIZE_MATCH(xRecordFreeContextReq)if ((sizeof(xRecordFreeContextReq) >> 2) != client->
req_len) return(16)
;
2603 swapl(&stuff->context)do { if (sizeof(*(&stuff->context)) != 4) wrong_size()
; if (__builtin_constant_p((uintptr_t)(&stuff->context
) & 3) && ((uintptr_t)(&stuff->context) &
3) == 0) *(&stuff->context) = lswapl(*(&stuff->
context)); else swap_uint32((uint32_t *)(&stuff->context
)); } while (0)
;
2604 return ProcRecordFreeContext(client);
2605} /* SProcRecordFreeContext */
2606
2607static int
2608SProcRecordDispatch(ClientPtr client)
2609{
2610 REQUEST(xReq)xReq *stuff = (xReq *)client->requestBuffer;
2611
2612 switch (stuff->data) {
2613 case X_RecordQueryVersion0:
2614 return SProcRecordQueryVersion(client);
2615 case X_RecordCreateContext1:
2616 return SProcRecordCreateContext(client);
2617 case X_RecordRegisterClients2:
2618 return SProcRecordRegisterClients(client);
2619 case X_RecordUnregisterClients3:
2620 return SProcRecordUnregisterClients(client);
2621 case X_RecordGetContext4:
2622 return SProcRecordGetContext(client);
2623 case X_RecordEnableContext5:
2624 return SProcRecordEnableContext(client);
2625 case X_RecordDisableContext6:
2626 return SProcRecordDisableContext(client);
2627 case X_RecordFreeContext7:
2628 return SProcRecordFreeContext(client);
2629 default:
2630 return BadRequest1;
2631 }
2632} /* SProcRecordDispatch */
2633
2634/* RecordConnectionSetupInfo
2635 *
2636 * Arguments:
2637 * pContext is an enabled context that specifies recording of
2638 * connection setup info.
2639 * pci holds the connection setup info.
2640 *
2641 * Returns: nothing.
2642 *
2643 * Side Effects:
2644 * The connection setup info is sent to the recording client.
2645 */
2646static void
2647RecordConnectionSetupInfo(RecordContextPtr pContext, NewClientInfoRec * pci)
2648{
2649 int prefixsize = SIZEOF(xConnSetupPrefix)8;
2650 int restsize = pci->prefix->length * 4;
2651
2652 if (pci->client->swapped) {
2653 char *pConnSetup = (char *) malloc(prefixsize + restsize);
2654
2655 if (!pConnSetup)
2656 return;
2657 SwapConnSetupPrefix(pci->prefix, (xConnSetupPrefix *) pConnSetup);
2658 SwapConnSetupInfo((char *) pci->setup,
2659 (char *) (pConnSetup + prefixsize));
2660 RecordAProtocolElement(pContext, pci->client, XRecordClientStarted2,
2661 (void *) pConnSetup, prefixsize + restsize, 0,
2662 0);
2663 free(pConnSetup);
2664 }
2665 else {
2666 /* don't alloc and copy as in the swapped case; just send the
2667 * data in two pieces
2668 */
2669 RecordAProtocolElement(pContext, pci->client, XRecordClientStarted2,
2670 (void *) pci->prefix, prefixsize, 0, restsize);
2671 RecordAProtocolElement(pContext, pci->client, XRecordClientStarted2,
2672 (void *) pci->setup, restsize, 0,
2673 /* continuation */ -1);
2674 }
2675} /* RecordConnectionSetupInfo */
2676
2677/* RecordDeleteContext
2678 *
2679 * Arguments:
2680 * pcbl is &ClientStateCallback.
2681 * nullata is NULL.
2682 * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
2683 * which contains information about client state changes.
2684 *
2685 * Returns: nothing.
2686 *
2687 * Side Effects:
2688 * If a new client has connected and any contexts have specified
2689 * XRecordFutureClients, the new client is registered on those contexts.
2690 * If any of those contexts specify recording of the connection setup
2691 * info, it is recorded.
2692 *
2693 * If an existing client has disconnected, it is deleted from any
2694 * contexts that it was registered on. If any of those contexts
2695 * specified XRecordClientDied, they record a ClientDied protocol element.
2696 * If the disconnectiong client happened to be the data connection of an
2697 * enabled context, the context is disabled.
2698 */
2699
2700static void
2701RecordAClientStateChange(CallbackListPtr *pcbl, void *nulldata,
2702 void *calldata)
2703{
2704 NewClientInfoRec *pci = (NewClientInfoRec *) calldata;
2705 int i;
2706 ClientPtr pClient = pci->client;
2707 RecordContextPtr *ppAllContextsCopy = NULL((void*)0);
2708 int numContextsCopy = 0;
2709
2710 switch (pClient->clientState) {
2711 case ClientStateRunning: /* new client */
2712 for (i = 0; i < numContexts; i++) {
2713 RecordClientsAndProtocolPtr pRCAP;
2714 RecordContextPtr pContext = ppAllContexts[i];
2715
2716 if ((pRCAP = RecordFindClientOnContext(pContext,
2717 XRecordFutureClients2, NULL((void*)0))))
2718 {
2719 RecordAddClientToRCAP(pRCAP, pClient->clientAsMask);
2720 if (pContext->pRecordingClient && pRCAP->clientStarted)
2721 RecordConnectionSetupInfo(pContext, pci);
2722 }
2723 }
2724 break;
2725
2726 case ClientStateGone:
2727 case ClientStateRetained: /* client disconnected */
2728
2729 /* RecordDisableContext modifies contents of ppAllContexts. */
2730 numContextsCopy = numContexts;
2731 ppAllContextsCopy = xallocarray(numContextsCopy,xreallocarray(((void*)0), (numContextsCopy), (sizeof(RecordContextPtr
)))
2732 sizeof(RecordContextPtr))xreallocarray(((void*)0), (numContextsCopy), (sizeof(RecordContextPtr
)))
;
2733 assert(ppAllContextsCopy)(__builtin_expect(!(ppAllContextsCopy), 0) ? __assert_rtn(__func__
, "record.c", 2733, "ppAllContextsCopy") : (void)0)
;
2734 memcpy(ppAllContextsCopy, ppAllContexts,__builtin___memcpy_chk (ppAllContextsCopy, ppAllContexts, numContextsCopy
* sizeof(RecordContextPtr), __builtin_object_size (ppAllContextsCopy
, 0))
2735 numContextsCopy * sizeof(RecordContextPtr))__builtin___memcpy_chk (ppAllContextsCopy, ppAllContexts, numContextsCopy
* sizeof(RecordContextPtr), __builtin_object_size (ppAllContextsCopy
, 0))
;
2736
2737 for (i = 0; i < numContextsCopy; i++) {
2738 RecordClientsAndProtocolPtr pRCAP;
2739 RecordContextPtr pContext = ppAllContextsCopy[i];
2740 int pos;
2741
2742 if (pContext->pRecordingClient == pClient)
2743 RecordDisableContext(pContext);
2744 if ((pRCAP = RecordFindClientOnContext(pContext,
2745 pClient->clientAsMask,
2746 &pos))) {
2747 if (pContext->pRecordingClient && pRCAP->clientDied)
2748 RecordAProtocolElement(pContext, pClient,
2749 XRecordClientDied3, NULL((void*)0), 0, 0, 0);
2750 RecordDeleteClientFromRCAP(pRCAP, pos);
2751 }
2752 }
2753
2754 free(ppAllContextsCopy);
2755 break;
2756
2757 default:
2758 break;
2759 } /* end switch on client state */
2760} /* RecordAClientStateChange */
2761
2762/* RecordCloseDown
2763 *
2764 * Arguments:
2765 * extEntry is the extension information for RECORD.
2766 *
2767 * Returns: nothing.
2768 *
2769 * Side Effects:
2770 * Performs any cleanup needed by RECORD at server shutdown time.
2771 *
2772 */
2773static void
2774RecordCloseDown(ExtensionEntry * extEntry)
2775{
2776 DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL((void*)0));
2777} /* RecordCloseDown */
2778
2779/* RecordExtensionInit
2780 *
2781 * Arguments: none.
2782 *
2783 * Returns: nothing.
2784 *
2785 * Side Effects:
2786 * Enables the RECORD extension if possible.
2787 */
2788void
2789RecordExtensionInit(void)
2790{
2791 ExtensionEntry *extentry;
2792
2793 RTContext = CreateNewResourceType(RecordDeleteContext, "RecordContext");
2794 if (!RTContext)
2795 return;
2796
2797 if (!dixRegisterPrivateKey(RecordClientPrivateKey(&RecordClientPrivateKeyRec), PRIVATE_CLIENT, 0))
2798 return;
2799
2800 ppAllContexts = NULL((void*)0);
2801 numContexts = numEnabledContexts = numEnabledRCAPs = 0;
2802
2803 if (!AddCallback(&ClientStateCallback, RecordAClientStateChange, NULL((void*)0)))
2804 return;
2805
2806 extentry = AddExtension(RECORD_NAME"RECORD", RecordNumEvents0L, RecordNumErrors(0 + 1),
2807 ProcRecordDispatch, SProcRecordDispatch,
2808 RecordCloseDown, StandardMinorOpcode);
2809 if (!extentry) {
2810 DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL((void*)0));
2811 return;
2812 }
2813 SetResourceTypeErrorValue(RTContext,
2814 extentry->errorBase + XRecordBadContext0);
2815
2816} /* RecordExtensionInit */