Bug Summary

File:record/record.c
Location:line 2154, column 34
Description:Call to 'malloc' has an allocation size of 0 bytes

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 << 8) - 1) << (29 - 8
))) >> (29 - 8)))
];
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 << 8) - 1) << (29 - 8
))) >> (29 - 8)))
];
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 = (XID *) realloc(pRCAP->pClientIDs,
1078 (pRCAP->sizeClients +
1079 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 = (XID *) malloc((pRCAP->sizeClients +
1088 CLIENT_ARRAY_GROWTH_INCREMENT4) *
1089 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 << 8) - 1) << (29 - 8
)))
== errorspec))
1153 return BadMatch8;
1154 clientIndex = CLIENT_ID(clientspecs[i])((int)(((clientspecs[i]) & (((1 << 8) - 1) <<
(29 - 8))) >> (29 - 8)))
;
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 << 8) - 1) << (29 - 8)));
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 = (XID *) malloc(sizeof(XID) * (currentMaxClients + 1));
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 = (RecordSetInterval *)
1425 malloc(nIntervals * sizeof(RecordSetInterval));
1426 if (!psi->intervals)
1427 return BadAlloc11;
1428 memset(psi->intervals, 0, nIntervals * sizeof(RecordSetInterval))__builtin___memset_chk (psi->intervals, 0, nIntervals * sizeof
(RecordSetInterval), __builtin_object_size (psi->intervals
, 0))
;
1429 psi->size = nIntervals;
1430 return Success0;
1431} /* end RecordAllocIntervals */
1432
1433/* RecordConvertRangesToIntervals
1434 *
1435 * Arguments:
1436 * psi is a pointer to the SetInfoRec we are building.
1437 * pRanges is an array of xRecordRanges.
1438 * nRanges is the number of elements in pRanges.
1439 * byteoffset is the offset from the start of an xRecordRange of the
1440 * two bytes (1 for first, 1 for last) we are interested in.
1441 * pExtSetInfo, if non-NULL, indicates that the two bytes mentioned
1442 * above are followed by four bytes (2 for first, 2 for last)
1443 * representing a minor opcode range, and this information should be
1444 * stored in one of the SetInfoRecs starting at pExtSetInfo.
1445 * pnExtSetInfo is the number of elements in the pExtSetInfo array.
1446 *
1447 * Returns: BadAlloc if a memory allocation error occurred, else Success.
1448 *
1449 * Side Effects:
1450 * The slice of pRanges indicated by byteoffset is stored in psi.
1451 * If pExtSetInfo is non-NULL, minor opcode intervals are stored
1452 * in an existing SetInfoRec if the major opcode interval matches, else
1453 * they are stored in a new SetInfoRec, and *pnExtSetInfo is
1454 * increased accordingly.
1455 */
1456static int
1457RecordConvertRangesToIntervals(SetInfoPtr psi,
1458 xRecordRange * pRanges,
1459 int nRanges,
1460 int byteoffset,
1461 SetInfoPtr pExtSetInfo, int *pnExtSetInfo)
1462{
1463 int i;
1464 CARD8 *pCARD8;
1465 int first, last;
1466 int err;
1467
1468 for (i = 0; i < nRanges; i++, pRanges++) {
1469 pCARD8 = ((CARD8 *) pRanges) + byteoffset;
1470 first = pCARD8[0];
1471 last = pCARD8[1];
1472 if (first || last) {
1473 if (!psi->intervals) {
1474 err = RecordAllocIntervals(psi, 2 * (nRanges - i));
1475 if (err != Success0)
1476 return err;
1477 }
1478 psi->intervals[psi->nintervals].first = first;
1479 psi->intervals[psi->nintervals].last = last;
1480 psi->nintervals++;
1481 assert(psi->nintervals <= psi->size)(__builtin_expect(!(psi->nintervals <= psi->size), 0
) ? __assert_rtn(__func__, "record.c", 1481, "psi->nintervals <= psi->size"
) : (void)0)
;
1482 if (pExtSetInfo) {
1483 SetInfoPtr pesi = pExtSetInfo;
1484 CARD16 *pCARD16 = (CARD16 *) (pCARD8 + 2);
1485 int j;
1486
1487 for (j = 0; j < *pnExtSetInfo; j++, pesi++) {
1488 if ((first == pesi->first) && (last == pesi->last))
1489 break;
1490 }
1491 if (j == *pnExtSetInfo) {
1492 err = RecordAllocIntervals(pesi, 2 * (nRanges - i));
1493 if (err != Success0)
1494 return err;
1495 pesi->first = first;
1496 pesi->last = last;
1497 (*pnExtSetInfo)++;
1498 }
1499 pesi->intervals[pesi->nintervals].first = pCARD16[0];
1500 pesi->intervals[pesi->nintervals].last = pCARD16[1];
1501 pesi->nintervals++;
1502 assert(pesi->nintervals <= pesi->size)(__builtin_expect(!(pesi->nintervals <= pesi->size),
0) ? __assert_rtn(__func__, "record.c", 1502, "pesi->nintervals <= pesi->size"
) : (void)0)
;
1503 }
1504 }
1505 }
1506 return Success0;
1507} /* end RecordConvertRangesToIntervals */
1508
1509#define offset_of(_structure, _field)((char *)(& (_structure . _field)) - (char *)(&_structure
))
\
1510 ((char *)(& (_structure . _field)) - (char *)(&_structure))
1511
1512/* RecordRegisterClients
1513 *
1514 * Arguments:
1515 * pContext is the context on which to register the clients.
1516 * client is the client that issued the RecordCreateContext or
1517 * RecordRegisterClients request.
1518 * stuff is a pointer to the request.
1519 *
1520 * Returns:
1521 * Any one of several possible error values defined by the protocol.
1522 * Success if everything is OK.
1523 *
1524 * Side Effects:
1525 * If different element headers are specified, the context is flushed.
1526 * If any of the specified clients are already registered on the
1527 * context, they are first unregistered. A new RCAP is created to
1528 * hold the specified protocol and clients, and it is linked onto the
1529 * context. If the context is enabled, appropriate hooks are installed
1530 * to record the new clients and protocol.
1531 */
1532static int
1533RecordRegisterClients(RecordContextPtr pContext, ClientPtr client,
1534 xRecordRegisterClientsReq * stuff)
1535{
1536 int err;
1537 int i;
1538 SetInfoPtr si;
1539 int maxSets;
1540 int nExtReqSets = 0;
1541 int nExtRepSets = 0;
1542 int extReqSetsOffset = 0;
1543 int extRepSetsOffset = 0;
1544 SetInfoPtr pExtReqSets, pExtRepSets;
1545 int clientListOffset;
1546 XID *pCanonClients;
1547 int clientStarted = 0, clientDied = 0;
1548 xRecordRange *pRanges, rr;
1549 int nClients;
1550 int sizeClients;
1551 int totRCAPsize;
1552 RecordClientsAndProtocolPtr pRCAP;
1553 int pad;
1554 XID recordingClient;
1555
1556 /* do all sanity checking up front */
1557
1558 err = RecordSanityCheckRegisterClients(pContext, client, stuff);
1559 if (err != Success0)
1560 return err;
1561
1562 /* if element headers changed, flush buffer */
1563
1564 if (pContext->elemHeaders != stuff->elementHeader) {
1565 RecordFlushReplyBuffer(pContext, NULL((void*)0), 0, NULL((void*)0), 0);
1566 pContext->elemHeaders = stuff->elementHeader;
1567 }
1568
1569 nClients = stuff->nClients;
1570 if (!nClients)
1571 /* if empty clients list, we're done. */
1572 return Success0;
1573
1574 recordingClient = pContext->pRecordingClient ?
1575 pContext->pRecordingClient->clientAsMask : 0;
1576 pCanonClients = RecordCanonicalizeClientSpecifiers((XID *) &stuff[1],
1577 &nClients,
1578 recordingClient);
1579 if (!pCanonClients)
1580 return BadAlloc11;
1581
1582 /* We may have to create as many as one set for each "predefined"
1583 * protocol types, plus one per range for extension reuests, plus one per
1584 * range for extension replies.
1585 */
1586 maxSets = PREDEFSETS + 2 * stuff->nRanges;
1587 si = (SetInfoPtr) malloc(sizeof(SetInfoRec) * maxSets);
1588 if (!si) {
1589 err = BadAlloc11;
1590 goto bailout;
1591 }
1592 memset(si, 0, sizeof(SetInfoRec) * maxSets)__builtin___memset_chk (si, 0, sizeof(SetInfoRec) * maxSets, __builtin_object_size
(si, 0))
;
1593
1594 /* theoretically you must do this because NULL may not be all-bits-zero */
1595 for (i = 0; i < maxSets; i++)
1596 si[i].intervals = NULL((void*)0);
1597
1598 pExtReqSets = si + PREDEFSETS;
1599 pExtRepSets = pExtReqSets + stuff->nRanges;
1600
1601 pRanges = (xRecordRange *) (((XID *) &stuff[1]) + stuff->nClients);
1602
1603 err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges,
1604 offset_of(rr, coreRequestsFirst)((char *)(& (rr . coreRequestsFirst)) - (char *)(&rr)
)
, NULL((void*)0),
1605 NULL((void*)0));
1606 if (err != Success0)
1607 goto bailout;
1608
1609 err = RecordConvertRangesToIntervals(&si[REQ], pRanges, stuff->nRanges,
1610 offset_of(rr, extRequestsMajorFirst)((char *)(& (rr . extRequestsMajorFirst)) - (char *)(&
rr))
,
1611 pExtReqSets, &nExtReqSets);
1612 if (err != Success0)
1613 goto bailout;
1614
1615 err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges,
1616 offset_of(rr, coreRepliesFirst)((char *)(& (rr . coreRepliesFirst)) - (char *)(&rr)), NULL((void*)0),
1617 NULL((void*)0));
1618 if (err != Success0)
1619 goto bailout;
1620
1621 err = RecordConvertRangesToIntervals(&si[REP], pRanges, stuff->nRanges,
1622 offset_of(rr, extRepliesMajorFirst)((char *)(& (rr . extRepliesMajorFirst)) - (char *)(&
rr))
,
1623 pExtRepSets, &nExtRepSets);
1624 if (err != Success0)
1625 goto bailout;
1626
1627 err = RecordConvertRangesToIntervals(&si[ERR], pRanges, stuff->nRanges,
1628 offset_of(rr, errorsFirst)((char *)(& (rr . errorsFirst)) - (char *)(&rr)), NULL((void*)0),
1629 NULL((void*)0));
1630 if (err != Success0)
1631 goto bailout;
1632
1633 err = RecordConvertRangesToIntervals(&si[DLEV], pRanges, stuff->nRanges,
1634 offset_of(rr, deliveredEventsFirst)((char *)(& (rr . deliveredEventsFirst)) - (char *)(&
rr))
,
1635 NULL((void*)0), NULL((void*)0));
1636 if (err != Success0)
1637 goto bailout;
1638
1639 err = RecordConvertRangesToIntervals(&si[DEV], pRanges, stuff->nRanges,
1640 offset_of(rr, deviceEventsFirst)((char *)(& (rr . deviceEventsFirst)) - (char *)(&rr)
)
, NULL((void*)0),
1641 NULL((void*)0));
1642 if (err != Success0)
1643 goto bailout;
1644
1645 /* collect client-started and client-died */
1646
1647 for (i = 0; i < stuff->nRanges; i++) {
1648 if (pRanges[i].clientStarted)
1649 clientStarted = TRUE1;
1650 if (pRanges[i].clientDied)
1651 clientDied = TRUE1;
1652 }
1653
1654 /* We now have all the information collected to create all the sets,
1655 * and we can compute the total memory required for the RCAP.
1656 */
1657
1658 totRCAPsize = sizeof(RecordClientsAndProtocolRec);
1659
1660 /* leave a little room to grow before forcing a separate allocation */
1661 sizeClients = nClients + CLIENT_ARRAY_GROWTH_INCREMENT4;
1662 pad = RecordPadAlign(totRCAPsize, sizeof(XID));
1663 clientListOffset = totRCAPsize + pad;
1664 totRCAPsize += pad + sizeClients * sizeof(XID);
1665
1666 if (nExtReqSets) {
1667 pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr));
1668 extReqSetsOffset = totRCAPsize + pad;
1669 totRCAPsize += pad + (nExtReqSets + 1) * sizeof(RecordMinorOpRec);
1670 }
1671 if (nExtRepSets) {
1672 pad = RecordPadAlign(totRCAPsize, sizeof(RecordSetPtr));
1673 extRepSetsOffset = totRCAPsize + pad;
1674 totRCAPsize += pad + (nExtRepSets + 1) * sizeof(RecordMinorOpRec);
1675 }
1676
1677 for (i = 0; i < maxSets; i++) {
1678 if (si[i].nintervals) {
1679 si[i].size =
1680 RecordSetMemoryRequirements(si[i].intervals, si[i].nintervals,
1681 &si[i].align);
1682 pad = RecordPadAlign(totRCAPsize, si[i].align);
1683 si[i].offset = pad + totRCAPsize;
1684 totRCAPsize += pad + si[i].size;
1685 }
1686 }
1687
1688 /* allocate memory for the whole RCAP */
1689
1690 pRCAP = (RecordClientsAndProtocolPtr) malloc(totRCAPsize);
1691 if (!pRCAP) {
1692 err = BadAlloc11;
1693 goto bailout;
1694 }
1695
1696 /* fill in the RCAP */
1697
1698 pRCAP->pContext = pContext;
1699 pRCAP->pClientIDs = (XID *) ((char *) pRCAP + clientListOffset);
1700 pRCAP->numClients = nClients;
1701 pRCAP->sizeClients = sizeClients;
1702 pRCAP->clientIDsSeparatelyAllocated = 0;
1703 for (i = 0; i < nClients; i++) {
1704 RecordDeleteClientFromContext(pContext, pCanonClients[i]);
1705 pRCAP->pClientIDs[i] = pCanonClients[i];
1706 }
1707
1708 /* create all the sets */
1709
1710 if (si[REQ].intervals) {
1711 pRCAP->pRequestMajorOpSet =
1712 RecordCreateSet(si[REQ].intervals, si[REQ].nintervals,
1713 (RecordSetPtr) ((char *) pRCAP + si[REQ].offset),
1714 si[REQ].size);
1715 }
1716 else
1717 pRCAP->pRequestMajorOpSet = NULL((void*)0);
1718
1719 if (si[REP].intervals) {
1720 pRCAP->pReplyMajorOpSet =
1721 RecordCreateSet(si[REP].intervals, si[REP].nintervals,
1722 (RecordSetPtr) ((char *) pRCAP + si[REP].offset),
1723 si[REP].size);
1724 }
1725 else
1726 pRCAP->pReplyMajorOpSet = NULL((void*)0);
1727
1728 if (si[ERR].intervals) {
1729 pRCAP->pErrorSet =
1730 RecordCreateSet(si[ERR].intervals, si[ERR].nintervals,
1731 (RecordSetPtr) ((char *) pRCAP + si[ERR].offset),
1732 si[ERR].size);
1733 }
1734 else
1735 pRCAP->pErrorSet = NULL((void*)0);
1736
1737 if (si[DEV].intervals) {
1738 pRCAP->pDeviceEventSet =
1739 RecordCreateSet(si[DEV].intervals, si[DEV].nintervals,
1740 (RecordSetPtr) ((char *) pRCAP + si[DEV].offset),
1741 si[DEV].size);
1742 }
1743 else
1744 pRCAP->pDeviceEventSet = NULL((void*)0);
1745
1746 if (si[DLEV].intervals) {
1747 pRCAP->pDeliveredEventSet =
1748 RecordCreateSet(si[DLEV].intervals, si[DLEV].nintervals,
1749 (RecordSetPtr) ((char *) pRCAP + si[DLEV].offset),
1750 si[DLEV].size);
1751 }
1752 else
1753 pRCAP->pDeliveredEventSet = NULL((void*)0);
1754
1755 if (nExtReqSets) {
1756 pRCAP->pRequestMinOpInfo = (RecordMinorOpPtr)
1757 ((char *) pRCAP + extReqSetsOffset);
1758 pRCAP->pRequestMinOpInfo[0].count = nExtReqSets;
1759 for (i = 0; i < nExtReqSets; i++, pExtReqSets++) {
1760 pRCAP->pRequestMinOpInfo[i + 1].major.first = pExtReqSets->first;
1761 pRCAP->pRequestMinOpInfo[i + 1].major.last = pExtReqSets->last;
1762 pRCAP->pRequestMinOpInfo[i + 1].major.pMinOpSet =
1763 RecordCreateSet(pExtReqSets->intervals,
1764 pExtReqSets->nintervals,
1765 (RecordSetPtr) ((char *) pRCAP +
1766 pExtReqSets->offset),
1767 pExtReqSets->size);
1768 }
1769 }
1770 else
1771 pRCAP->pRequestMinOpInfo = NULL((void*)0);
1772
1773 if (nExtRepSets) {
1774 pRCAP->pReplyMinOpInfo = (RecordMinorOpPtr)
1775 ((char *) pRCAP + extRepSetsOffset);
1776 pRCAP->pReplyMinOpInfo[0].count = nExtRepSets;
1777 for (i = 0; i < nExtRepSets; i++, pExtRepSets++) {
1778 pRCAP->pReplyMinOpInfo[i + 1].major.first = pExtRepSets->first;
1779 pRCAP->pReplyMinOpInfo[i + 1].major.last = pExtRepSets->last;
1780 pRCAP->pReplyMinOpInfo[i + 1].major.pMinOpSet =
1781 RecordCreateSet(pExtRepSets->intervals,
1782 pExtRepSets->nintervals,
1783 (RecordSetPtr) ((char *) pRCAP +
1784 pExtRepSets->offset),
1785 pExtRepSets->size);
1786 }
1787 }
1788 else
1789 pRCAP->pReplyMinOpInfo = NULL((void*)0);
1790
1791 pRCAP->clientStarted = clientStarted;
1792 pRCAP->clientDied = clientDied;
1793
1794 /* link the RCAP onto the context */
1795
1796 pRCAP->pNextRCAP = pContext->pListOfRCAP;
1797 pContext->pListOfRCAP = pRCAP;
1798
1799 if (pContext->pRecordingClient) /* context enabled */
1800 RecordInstallHooks(pRCAP, 0);
1801
1802 bailout:
1803 if (si) {
1804 for (i = 0; i < maxSets; i++)
1805 free(si[i].intervals);
1806 free(si);
1807 }
1808 if (pCanonClients && pCanonClients != (XID *) &stuff[1])
1809 free(pCanonClients);
1810 return err;
1811} /* RecordRegisterClients */
1812
1813/* Proc functions all take a client argument, execute the request in
1814 * client->requestBuffer, and return a protocol error status.
1815 */
1816
1817static int
1818ProcRecordQueryVersion(ClientPtr client)
1819{
1820 /* REQUEST(xRecordQueryVersionReq); */
1821 xRecordQueryVersionReply rep = {
1822 .type = X_Reply1,
1823 .sequenceNumber = client->sequence,
1824 .length = 0,
1825 .majorVersion = SERVER_RECORD_MAJOR_VERSION1,
1826 .minorVersion = SERVER_RECORD_MINOR_VERSION13
1827 };
1828
1829 REQUEST_SIZE_MATCH(xRecordQueryVersionReq)if ((sizeof(xRecordQueryVersionReq) >> 2) != client->
req_len) return(16)
;
1830 if (client->swapped) {
1831 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)
;
1832 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)
;
1833 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)
;
1834 }
1835 WriteToClient(client, sizeof(xRecordQueryVersionReply), &rep);
1836 return Success0;
1837} /* ProcRecordQueryVersion */
1838
1839static int
1840ProcRecordCreateContext(ClientPtr client)
1841{
1842 REQUEST(xRecordCreateContextReq)xRecordCreateContextReq *stuff = (xRecordCreateContextReq *)client
->requestBuffer
;
1843 RecordContextPtr pContext;
1844 RecordContextPtr *ppNewAllContexts = NULL((void*)0);
1845 int err = BadAlloc11;
1846
1847 REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq)if ((sizeof(xRecordCreateContextReq) >> 2) > client->
req_len ) return(16)
;
1848 LEGAL_NEW_RESOURCE(stuff->context, client)if (!LegalNewID(stuff->context,client)) { client->errorValue
= stuff->context; return 14; }
;
1849
1850 pContext = (RecordContextPtr) malloc(sizeof(RecordContextRec));
1851 if (!pContext)
1852 goto bailout;
1853
1854 /* make sure there is room in ppAllContexts to store the new context */
1855
1856 ppNewAllContexts = (RecordContextPtr *)
1857 realloc(ppAllContexts, sizeof(RecordContextPtr) * (numContexts + 1));
1858 if (!ppNewAllContexts)
1859 goto bailout;
1860 ppAllContexts = ppNewAllContexts;
1861
1862 pContext->id = stuff->context;
1863 pContext->pRecordingClient = NULL((void*)0);
1864 pContext->pListOfRCAP = NULL((void*)0);
1865 pContext->elemHeaders = 0;
1866 pContext->bufCategory = 0;
1867 pContext->numBufBytes = 0;
1868 pContext->pBufClient = NULL((void*)0);
1869 pContext->continuedReply = 0;
1870 pContext->inFlush = 0;
1871
1872 err = RecordRegisterClients(pContext, client,
1873 (xRecordRegisterClientsReq *) stuff);
1874 if (err != Success0)
1875 goto bailout;
1876
1877 if (AddResourceDarwin_X_AddResource(pContext->id, RTContext, pContext)) {
1878 ppAllContexts[numContexts++] = pContext;
1879 return Success0;
1880 }
1881 else {
1882 RecordDeleteContext((void *) pContext, pContext->id);
1883 return BadAlloc11;
1884 }
1885 bailout:
1886 free(pContext);
1887 return err;
1888} /* ProcRecordCreateContext */
1889
1890static int
1891ProcRecordRegisterClients(ClientPtr client)
1892{
1893 RecordContextPtr pContext;
1894
1895 REQUEST(xRecordRegisterClientsReq)xRecordRegisterClientsReq *stuff = (xRecordRegisterClientsReq
*)client->requestBuffer
;
1896
1897 REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq)if ((sizeof(xRecordRegisterClientsReq) >> 2) > client
->req_len ) return(16)
;
1898 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
1899
1900 return RecordRegisterClients(pContext, client, stuff);
1901} /* ProcRecordRegisterClients */
1902
1903static int
1904ProcRecordUnregisterClients(ClientPtr client)
1905{
1906 RecordContextPtr pContext;
1907 int err;
1908
1909 REQUEST(xRecordUnregisterClientsReq)xRecordUnregisterClientsReq *stuff = (xRecordUnregisterClientsReq
*)client->requestBuffer
;
1910 XID *pCanonClients;
1911 int nClients;
1912 int i;
1913
1914 REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq)if ((sizeof(xRecordUnregisterClientsReq) >> 2) > client
->req_len ) return(16)
;
1915 if ((client->req_len << 2) - SIZEOF(xRecordUnregisterClientsReq)12 !=
1916 4 * stuff->nClients)
1917 return BadLength16;
1918 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
1919 err = RecordSanityCheckClientSpecifiers(client, (XID *) &stuff[1],
1920 stuff->nClients, 0);
1921 if (err != Success0)
1922 return err;
1923
1924 nClients = stuff->nClients;
1925 pCanonClients = RecordCanonicalizeClientSpecifiers((XID *) &stuff[1],
1926 &nClients, 0);
1927 if (!pCanonClients)
1928 return BadAlloc11;
1929
1930 for (i = 0; i < nClients; i++) {
1931 RecordDeleteClientFromContext(pContext, pCanonClients[i]);
1932 }
1933 if (pCanonClients != (XID *) &stuff[1])
1934 free(pCanonClients);
1935 return Success0;
1936} /* ProcRecordUnregisterClients */
1937
1938/****************************************************************************/
1939
1940/* stuff for GetContext */
1941
1942/* This is a tactical structure used to hold the xRecordRanges as they are
1943 * being reconstituted from the sets in the RCAPs.
1944 */
1945
1946typedef struct {
1947 xRecordRange *pRanges; /* array of xRecordRanges for one RCAP */
1948 int size; /* number of elements in pRanges, >= nRanges */
1949 int nRanges; /* number of occupied element of pRanges */
1950} GetContextRangeInfoRec, *GetContextRangeInfoPtr;
1951
1952/* RecordAllocRanges
1953 *
1954 * Arguments:
1955 * pri is a pointer to a GetContextRangeInfoRec to allocate for.
1956 * nRanges is the number of xRecordRanges desired for pri.
1957 *
1958 * Returns: BadAlloc if a memory allocation error occurred, else Success.
1959 *
1960 * Side Effects:
1961 * If Success is returned, pri->pRanges points to at least nRanges
1962 * ranges. pri->nRanges is set to nRanges. pri->size is the actual
1963 * number of ranges. Newly allocated ranges are zeroed.
1964 */
1965static int
1966RecordAllocRanges(GetContextRangeInfoPtr pri, int nRanges)
1967{
1968 int newsize;
1969 xRecordRange *pNewRange;
1970
1971#define SZINCR8 8
1972
1973 newsize = max(pri->size + SZINCR, nRanges)(((pri->size + 8) > (nRanges)) ? (pri->size + 8) : (
nRanges))
;
1974 pNewRange = (xRecordRange *) realloc(pri->pRanges,
1975 newsize * sizeof(xRecordRange));
1976 if (!pNewRange)
1977 return BadAlloc11;
1978
1979 pri->pRanges = pNewRange;
1980 pri->size = newsize;
1981 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))
;
1982 if (pri->nRanges < nRanges)
1983 pri->nRanges = nRanges;
1984 return Success0;
1985} /* RecordAllocRanges */
1986
1987/* RecordConvertSetToRanges
1988 *
1989 * Arguments:
1990 * pSet is the set to be converted.
1991 * pri is where the result should be stored.
1992 * byteoffset is the offset from the start of an xRecordRange of the
1993 * two vales (first, last) we are interested in.
1994 * card8 is TRUE if the vales are one byte each and FALSE if two bytes
1995 * each.
1996 * imax is the largest set value to store in pri->pRanges.
1997 * pStartIndex, if non-NULL, is the index of the first range in
1998 * pri->pRanges that should be stored to. If NULL,
1999 * start at index 0.
2000 *
2001 * Returns: BadAlloc if a memory allocation error occurred, else Success.
2002 *
2003 * Side Effects:
2004 * If Success is returned, the slice of pri->pRanges indicated by
2005 * byteoffset and card8 is filled in with the intervals from pSet.
2006 * if pStartIndex was non-NULL, *pStartIndex is filled in with one
2007 * more than the index of the last xRecordRange that was touched.
2008 */
2009static int
2010RecordConvertSetToRanges(RecordSetPtr pSet,
2011 GetContextRangeInfoPtr pri,
2012 int byteoffset,
2013 Bool card8, unsigned int imax, int *pStartIndex)
2014{
2015 int nRanges;
2016 RecordSetIteratePtr pIter = NULL((void*)0);
2017 RecordSetInterval interval;
2018 CARD8 *pCARD8;
2019 CARD16 *pCARD16;
2020 int err;
2021
2022 if (!pSet)
2023 return Success0;
2024
2025 nRanges = pStartIndex ? *pStartIndex : 0;
2026 while ((pIter = RecordIterateSet(pSet, pIter, &interval)(*pSet->ops->IterateSet)( pSet, pIter, &interval))) {
2027 if (interval.first > imax)
2028 break;
2029 if (interval.last > imax)
2030 interval.last = imax;
2031 nRanges++;
2032 if (nRanges > pri->size) {
2033 err = RecordAllocRanges(pri, nRanges);
2034 if (err != Success0)
2035 return err;
2036 }
2037 else
2038 pri->nRanges = max(pri->nRanges, nRanges)(((pri->nRanges) > (nRanges)) ? (pri->nRanges) : (nRanges
))
;
2039 if (card8) {
2040 pCARD8 = ((CARD8 *) &pri->pRanges[nRanges - 1]) + byteoffset;
2041 *pCARD8++ = interval.first;
2042 *pCARD8 = interval.last;
2043 }
2044 else {
2045 pCARD16 = (CARD16 *)
2046 (((char *) &pri->pRanges[nRanges - 1]) + byteoffset);
2047 *pCARD16++ = interval.first;
2048 *pCARD16 = interval.last;
2049 }
2050 }
2051 if (pStartIndex)
2052 *pStartIndex = nRanges;
2053 return Success0;
2054} /* RecordConvertSetToRanges */
2055
2056/* RecordConvertMinorOpInfoToRanges
2057 *
2058 * Arguments:
2059 * pMinOpInfo is the minor opcode info to convert to xRecordRanges.
2060 * pri is where the result should be stored.
2061 * byteoffset is the offset from the start of an xRecordRange of the
2062 * four vales (CARD8 major_first, CARD8 major_last,
2063 * CARD16 minor_first, CARD16 minor_last) we are going to store.
2064 *
2065 * Returns: BadAlloc if a memory allocation error occurred, else Success.
2066 *
2067 * Side Effects:
2068 * If Success is returned, the slice of pri->pRanges indicated by
2069 * byteoffset is filled in with the information from pMinOpInfo.
2070 */
2071static int
2072RecordConvertMinorOpInfoToRanges(RecordMinorOpPtr pMinOpInfo,
2073 GetContextRangeInfoPtr pri, int byteoffset)
2074{
2075 int nsets;
2076 int start;
2077 int i;
2078 int err;
2079
2080 if (!pMinOpInfo)
2081 return Success0;
2082
2083 nsets = pMinOpInfo->count;
2084 pMinOpInfo++;
2085 start = 0;
2086 for (i = 0; i < nsets; i++) {
2087 int j, s;
2088
2089 s = start;
2090 err = RecordConvertSetToRanges(pMinOpInfo[i].major.pMinOpSet, pri,
2091 byteoffset + 2, FALSE0, 65535, &start);
2092 if (err != Success0)
2093 return err;
2094 for (j = s; j < start; j++) {
2095 CARD8 *pCARD8 = ((CARD8 *) &pri->pRanges[j]) + byteoffset;
2096
2097 *pCARD8++ = pMinOpInfo[i].major.first;
2098 *pCARD8 = pMinOpInfo[i].major.last;
2099 }
2100 }
2101 return Success0;
2102} /* RecordConvertMinorOpInfoToRanges */
2103
2104/* RecordSwapRanges
2105 *
2106 * Arguments:
2107 * pRanges is an array of xRecordRanges.
2108 * nRanges is the number of elements in pRanges.
2109 *
2110 * Returns: nothing.
2111 *
2112 * Side Effects:
2113 * The 16 bit fields of each xRecordRange are byte swapped.
2114 */
2115static void
2116RecordSwapRanges(xRecordRange * pRanges, int nRanges)
2117{
2118 int i;
2119
2120 for (i = 0; i < nRanges; i++, pRanges++) {
2121 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)
;
2122 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)
;
2123 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)
;
2124 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)
;
2125 }
2126} /* RecordSwapRanges */
2127
2128static int
2129ProcRecordGetContext(ClientPtr client)
2130{
2131 RecordContextPtr pContext;
2132
2133 REQUEST(xRecordGetContextReq)xRecordGetContextReq *stuff = (xRecordGetContextReq *)client->
requestBuffer
;
2134 xRecordGetContextReply rep;
2135 RecordClientsAndProtocolPtr pRCAP;
2136 int nRCAPs = 0;
2137 GetContextRangeInfoPtr pRangeInfo;
2138 GetContextRangeInfoPtr pri;
2139 int i;
2140 int err;
2141 CARD32 nClients, length;
2142
2143 REQUEST_SIZE_MATCH(xRecordGetContextReq)if ((sizeof(xRecordGetContextReq) >> 2) != client->req_len
) return(16)
;
2144 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2145
2146 /* how many RCAPs are there on this context? */
2147
2148 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP)
1
Loop condition is false. Execution continues on line 2154
2149 nRCAPs++;
2150
2151 /* allocate and initialize space for record range info */
2152
2153 pRangeInfo =
2154 (GetContextRangeInfoPtr) malloc(nRCAPs *
2
Call to 'malloc' has an allocation size of 0 bytes
2155 sizeof(GetContextRangeInfoRec));
2156 if (!pRangeInfo && nRCAPs > 0)
2157 return BadAlloc11;
2158 for (i = 0; i < nRCAPs; i++) {
2159 pRangeInfo[i].pRanges = NULL((void*)0);
2160 pRangeInfo[i].size = 0;
2161 pRangeInfo[i].nRanges = 0;
2162 }
2163
2164 /* convert the RCAP (internal) representation of the recorded protocol
2165 * to the wire protocol (external) representation, storing the information
2166 * for the ith RCAP in pri[i]
2167 */
2168
2169 for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo;
2170 pRCAP; pRCAP = pRCAP->pNextRCAP, pri++) {
2171 xRecordRange rr;
2172
2173 err = RecordConvertSetToRanges(pRCAP->pRequestMajorOpSet, pri,
2174 offset_of(rr, coreRequestsFirst)((char *)(& (rr . coreRequestsFirst)) - (char *)(&rr)
)
, TRUE1,
2175 127, NULL((void*)0));
2176 if (err != Success0)
2177 goto bailout;
2178
2179 err = RecordConvertSetToRanges(pRCAP->pReplyMajorOpSet, pri,
2180 offset_of(rr, coreRepliesFirst)((char *)(& (rr . coreRepliesFirst)) - (char *)(&rr)), TRUE1,
2181 127, NULL((void*)0));
2182 if (err != Success0)
2183 goto bailout;
2184
2185 err = RecordConvertSetToRanges(pRCAP->pDeliveredEventSet, pri,
2186 offset_of(rr, deliveredEventsFirst)((char *)(& (rr . deliveredEventsFirst)) - (char *)(&
rr))
,
2187 TRUE1, 255, NULL((void*)0));
2188 if (err != Success0)
2189 goto bailout;
2190
2191 err = RecordConvertSetToRanges(pRCAP->pDeviceEventSet, pri,
2192 offset_of(rr, deviceEventsFirst)((char *)(& (rr . deviceEventsFirst)) - (char *)(&rr)
)
, TRUE1,
2193 255, NULL((void*)0));
2194 if (err != Success0)
2195 goto bailout;
2196
2197 err = RecordConvertSetToRanges(pRCAP->pErrorSet, pri,
2198 offset_of(rr, errorsFirst)((char *)(& (rr . errorsFirst)) - (char *)(&rr)), TRUE1, 255,
2199 NULL((void*)0));
2200 if (err != Success0)
2201 goto bailout;
2202
2203 err = RecordConvertMinorOpInfoToRanges(pRCAP->pRequestMinOpInfo,
2204 pri, offset_of(rr,((char *)(& (rr . extRequestsMajorFirst)) - (char *)(&
rr))
2205 extRequestsMajorFirst)((char *)(& (rr . extRequestsMajorFirst)) - (char *)(&
rr))
);
2206 if (err != Success0)
2207 goto bailout;
2208
2209 err = RecordConvertMinorOpInfoToRanges(pRCAP->pReplyMinOpInfo,
2210 pri, offset_of(rr,((char *)(& (rr . extRepliesMajorFirst)) - (char *)(&
rr))
2211 extRepliesMajorFirst)((char *)(& (rr . extRepliesMajorFirst)) - (char *)(&
rr))
);
2212 if (err != Success0)
2213 goto bailout;
2214
2215 if (pRCAP->clientStarted || pRCAP->clientDied) {
2216 if (pri->nRanges == 0)
2217 RecordAllocRanges(pri, 1);
2218 pri->pRanges[0].clientStarted = pRCAP->clientStarted;
2219 pri->pRanges[0].clientDied = pRCAP->clientDied;
2220 }
2221 }
2222
2223 /* calculate number of clients and reply length */
2224
2225 nClients = 0;
2226 length = 0;
2227 for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo;
2228 pRCAP; pRCAP = pRCAP->pNextRCAP, pri++) {
2229 nClients += pRCAP->numClients;
2230 length += pRCAP->numClients *
2231 (bytes_to_int32(sizeof(xRecordClientInfo)) +
2232 pri->nRanges * bytes_to_int32(sizeof(xRecordRange)));
2233 }
2234
2235 /* write the reply header */
2236
2237 rep = (xRecordGetContextReply) {
2238 .type = X_Reply1,
2239 .enabled = pContext->pRecordingClient != NULL((void*)0),
2240 .sequenceNumber = client->sequence,
2241 .length = length,
2242 .elementHeader = pContext->elemHeaders,
2243 .nClients = nClients
2244 };
2245 if (client->swapped) {
2246 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)
;
2247 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)
;
2248 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)
;
2249 }
2250 WriteToClient(client, sizeof(xRecordGetContextReply), &rep);
2251
2252 /* write all the CLIENT_INFOs */
2253
2254 for (pRCAP = pContext->pListOfRCAP, pri = pRangeInfo;
2255 pRCAP; pRCAP = pRCAP->pNextRCAP, pri++) {
2256 xRecordClientInfo rci;
2257
2258 rci.nRanges = pri->nRanges;
2259 if (client->swapped) {
2260 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)
;
2261 RecordSwapRanges(pri->pRanges, pri->nRanges);
2262 }
2263 for (i = 0; i < pRCAP->numClients; i++) {
2264 rci.clientResource = pRCAP->pClientIDs[i];
2265 if (client->swapped)
2266 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)
;
2267 WriteToClient(client, sizeof(xRecordClientInfo), &rci);
2268 WriteToClient(client, sizeof(xRecordRange) * pri->nRanges,
2269 pri->pRanges);
2270 }
2271 }
2272 err = Success0;
2273
2274 bailout:
2275 for (i = 0; i < nRCAPs; i++) {
2276 free(pRangeInfo[i].pRanges);
2277 }
2278 free(pRangeInfo);
2279 return err;
2280} /* ProcRecordGetContext */
2281
2282static int
2283ProcRecordEnableContext(ClientPtr client)
2284{
2285 RecordContextPtr pContext;
2286
2287 REQUEST(xRecordEnableContextReq)xRecordEnableContextReq *stuff = (xRecordEnableContextReq *)client
->requestBuffer
;
2288 int i;
2289 RecordClientsAndProtocolPtr pRCAP;
2290
2291 REQUEST_SIZE_MATCH(xRecordGetContextReq)if ((sizeof(xRecordGetContextReq) >> 2) != client->req_len
) return(16)
;
2292 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2293 if (pContext->pRecordingClient)
2294 return BadMatch8; /* already enabled */
2295
2296 /* install record hooks for each RCAP */
2297
2298 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
2299 int err = RecordInstallHooks(pRCAP, 0);
2300
2301 if (err != Success0) { /* undo the previous installs */
2302 RecordClientsAndProtocolPtr pUninstallRCAP;
2303
2304 for (pUninstallRCAP = pContext->pListOfRCAP;
2305 pUninstallRCAP != pRCAP;
2306 pUninstallRCAP = pUninstallRCAP->pNextRCAP) {
2307 RecordUninstallHooks(pUninstallRCAP, 0);
2308 }
2309 return err;
2310 }
2311 }
2312
2313 /* Disallow further request processing on this connection until
2314 * the context is disabled.
2315 */
2316 IgnoreClient(client);
2317 pContext->pRecordingClient = client;
2318
2319 /* Don't allow the data connection to record itself; unregister it. */
2320 RecordDeleteClientFromContext(pContext,
2321 pContext->pRecordingClient->clientAsMask);
2322
2323 /* move the newly enabled context to the front part of ppAllContexts,
2324 * where all the enabled contexts are
2325 */
2326 i = RecordFindContextOnAllContexts(pContext);
2327 assert(i >= numEnabledContexts)(__builtin_expect(!(i >= numEnabledContexts), 0) ? __assert_rtn
(__func__, "record.c", 2327, "i >= numEnabledContexts") : (
void)0)
;
2328 if (i != numEnabledContexts) {
2329 ppAllContexts[i] = ppAllContexts[numEnabledContexts];
2330 ppAllContexts[numEnabledContexts] = pContext;
2331 }
2332
2333 ++numEnabledContexts;
2334 assert(numEnabledContexts > 0)(__builtin_expect(!(numEnabledContexts > 0), 0) ? __assert_rtn
(__func__, "record.c", 2334, "numEnabledContexts > 0") : (
void)0)
;
2335
2336 /* send StartOfData */
2337 RecordAProtocolElement(pContext, NULL((void*)0), XRecordStartOfData4, NULL((void*)0), 0, 0, 0);
2338 RecordFlushReplyBuffer(pContext, NULL((void*)0), 0, NULL((void*)0), 0);
2339 return Success0;
2340} /* ProcRecordEnableContext */
2341
2342/* RecordDisableContext
2343 *
2344 * Arguments:
2345 * pContext is the context to disable.
2346 * nRanges is the number of elements in pRanges.
2347 *
2348 * Returns: nothing.
2349 *
2350 * Side Effects:
2351 * If the context was enabled, it is disabled. An EndOfData
2352 * message is sent to the recording client. Recording hooks for
2353 * this context are uninstalled. The context is moved to the
2354 * rear part of the ppAllContexts array. numEnabledContexts is
2355 * decremented. Request processing for the formerly recording client
2356 * is resumed.
2357 */
2358static void
2359RecordDisableContext(RecordContextPtr pContext)
2360{
2361 RecordClientsAndProtocolPtr pRCAP;
2362 int i;
2363
2364 if (!pContext->pRecordingClient)
2365 return;
2366 if (!pContext->pRecordingClient->clientGone) {
2367 RecordAProtocolElement(pContext, NULL((void*)0), XRecordEndOfData5, NULL((void*)0), 0, 0, 0);
2368 RecordFlushReplyBuffer(pContext, NULL((void*)0), 0, NULL((void*)0), 0);
2369 /* Re-enable request processing on this connection. */
2370 AttendClient(pContext->pRecordingClient);
2371 }
2372
2373 for (pRCAP = pContext->pListOfRCAP; pRCAP; pRCAP = pRCAP->pNextRCAP) {
2374 RecordUninstallHooks(pRCAP, 0);
2375 }
2376
2377 pContext->pRecordingClient = NULL((void*)0);
2378
2379 /* move the newly disabled context to the rear part of ppAllContexts,
2380 * where all the disabled contexts are
2381 */
2382 i = RecordFindContextOnAllContexts(pContext);
2383 assert((i != -1) && (i < numEnabledContexts))(__builtin_expect(!((i != -1) && (i < numEnabledContexts
)), 0) ? __assert_rtn(__func__, "record.c", 2383, "(i != -1) && (i < numEnabledContexts)"
) : (void)0)
;
2384 if (i != (numEnabledContexts - 1)) {
2385 ppAllContexts[i] = ppAllContexts[numEnabledContexts - 1];
2386 ppAllContexts[numEnabledContexts - 1] = pContext;
2387 }
2388 --numEnabledContexts;
2389 assert(numEnabledContexts >= 0)(__builtin_expect(!(numEnabledContexts >= 0), 0) ? __assert_rtn
(__func__, "record.c", 2389, "numEnabledContexts >= 0") : (
void)0)
;
2390} /* RecordDisableContext */
2391
2392static int
2393ProcRecordDisableContext(ClientPtr client)
2394{
2395 RecordContextPtr pContext;
2396
2397 REQUEST(xRecordDisableContextReq)xRecordDisableContextReq *stuff = (xRecordDisableContextReq *
)client->requestBuffer
;
2398
2399 REQUEST_SIZE_MATCH(xRecordDisableContextReq)if ((sizeof(xRecordDisableContextReq) >> 2) != client->
req_len) return(16)
;
2400 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2401 RecordDisableContext(pContext);
2402 return Success0;
2403} /* ProcRecordDisableContext */
2404
2405/* RecordDeleteContext
2406 *
2407 * Arguments:
2408 * value is the context to delete.
2409 * id is its resource ID.
2410 *
2411 * Returns: Success.
2412 *
2413 * Side Effects:
2414 * Disables the context, frees all associated memory, and removes
2415 * it from the ppAllContexts array.
2416 */
2417static int
2418RecordDeleteContext(void *value, XID id)
2419{
2420 int i;
2421 RecordContextPtr pContext = (RecordContextPtr) value;
2422 RecordClientsAndProtocolPtr pRCAP;
2423
2424 RecordDisableContext(pContext);
2425
2426 /* Remove all the clients from all the RCAPs.
2427 * As a result, the RCAPs will be freed.
2428 */
2429
2430 while ((pRCAP = pContext->pListOfRCAP)) {
2431 int numClients = pRCAP->numClients;
2432
2433 /* when the last client is deleted, the RCAP will go away. */
2434 while (numClients--) {
2435 RecordDeleteClientFromRCAP(pRCAP, numClients);
2436 }
2437 }
2438
2439 /* remove context from AllContexts list */
2440
2441 if (-1 != (i = RecordFindContextOnAllContexts(pContext))) {
2442 ppAllContexts[i] = ppAllContexts[numContexts - 1];
2443 if (--numContexts == 0) {
2444 free(ppAllContexts);
2445 ppAllContexts = NULL((void*)0);
2446 }
2447 }
2448 free(pContext);
2449
2450 return Success0;
2451} /* RecordDeleteContext */
2452
2453static int
2454ProcRecordFreeContext(ClientPtr client)
2455{
2456 RecordContextPtr pContext;
2457
2458 REQUEST(xRecordFreeContextReq)xRecordFreeContextReq *stuff = (xRecordFreeContextReq *)client
->requestBuffer
;
2459
2460 REQUEST_SIZE_MATCH(xRecordFreeContextReq)if ((sizeof(xRecordFreeContextReq) >> 2) != client->
req_len) return(16)
;
2461 VERIFY_CONTEXT(pContext, stuff->context, client){ int rc = dixLookupResourceByType((void **)&(pContext), stuff
->context, RTContext, client, (1<<24)); if (rc != 0)
return rc; }
;
2462 FreeResource(stuff->context, RT_NONE((RESTYPE)0));
2463 return Success0;
2464} /* ProcRecordFreeContext */
2465
2466static int
2467ProcRecordDispatch(ClientPtr client)
2468{
2469 REQUEST(xReq)xReq *stuff = (xReq *)client->requestBuffer;
2470
2471 switch (stuff->data) {
2472 case X_RecordQueryVersion0:
2473 return ProcRecordQueryVersion(client);
2474 case X_RecordCreateContext1:
2475 return ProcRecordCreateContext(client);
2476 case X_RecordRegisterClients2:
2477 return ProcRecordRegisterClients(client);
2478 case X_RecordUnregisterClients3:
2479 return ProcRecordUnregisterClients(client);
2480 case X_RecordGetContext4:
2481 return ProcRecordGetContext(client);
2482 case X_RecordEnableContext5:
2483 return ProcRecordEnableContext(client);
2484 case X_RecordDisableContext6:
2485 return ProcRecordDisableContext(client);
2486 case X_RecordFreeContext7:
2487 return ProcRecordFreeContext(client);
2488 default:
2489 return BadRequest1;
2490 }
2491} /* ProcRecordDispatch */
2492
2493static int
2494SProcRecordQueryVersion(ClientPtr client)
2495{
2496 REQUEST(xRecordQueryVersionReq)xRecordQueryVersionReq *stuff = (xRecordQueryVersionReq *)client
->requestBuffer
;
2497
2498 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)
;
2499 REQUEST_SIZE_MATCH(xRecordQueryVersionReq)if ((sizeof(xRecordQueryVersionReq) >> 2) != client->
req_len) return(16)
;
2500 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)
;
2501 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)
;
2502 return ProcRecordQueryVersion(client);
2503} /* SProcRecordQueryVersion */
2504
2505static int
2506SwapCreateRegister(xRecordRegisterClientsReq * stuff)
2507{
2508 int i;
2509 XID *pClientID;
2510
2511 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)
;
2512 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)
;
2513 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)
;
2514 pClientID = (XID *) &stuff[1];
2515 if (stuff->nClients >
2516 stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq20))
2517 return BadLength16;
2518 for (i = 0; i < stuff->nClients; i++, pClientID++) {
2519 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)
;
2520 }
2521 if (stuff->nRanges >
2522 stuff->length - bytes_to_int32(sz_xRecordRegisterClientsReq20)
2523 - stuff->nClients)
2524 return BadLength16;
2525 RecordSwapRanges((xRecordRange *) pClientID, stuff->nRanges);
2526 return Success0;
2527} /* SwapCreateRegister */
2528
2529static int
2530SProcRecordCreateContext(ClientPtr client)
2531{
2532 REQUEST(xRecordCreateContextReq)xRecordCreateContextReq *stuff = (xRecordCreateContextReq *)client
->requestBuffer
;
2533 int status;
2534
2535 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)
;
2536 REQUEST_AT_LEAST_SIZE(xRecordCreateContextReq)if ((sizeof(xRecordCreateContextReq) >> 2) > client->
req_len ) return(16)
;
2537 if ((status = SwapCreateRegister((void *) stuff)) != Success0)
2538 return status;
2539 return ProcRecordCreateContext(client);
2540} /* SProcRecordCreateContext */
2541
2542static int
2543SProcRecordRegisterClients(ClientPtr client)
2544{
2545 REQUEST(xRecordRegisterClientsReq)xRecordRegisterClientsReq *stuff = (xRecordRegisterClientsReq
*)client->requestBuffer
;
2546 int status;
2547
2548 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)
;
2549 REQUEST_AT_LEAST_SIZE(xRecordRegisterClientsReq)if ((sizeof(xRecordRegisterClientsReq) >> 2) > client
->req_len ) return(16)
;
2550 if ((status = SwapCreateRegister((void *) stuff)) != Success0)
2551 return status;
2552 return ProcRecordRegisterClients(client);
2553} /* SProcRecordRegisterClients */
2554
2555static int
2556SProcRecordUnregisterClients(ClientPtr client)
2557{
2558 REQUEST(xRecordUnregisterClientsReq)xRecordUnregisterClientsReq *stuff = (xRecordUnregisterClientsReq
*)client->requestBuffer
;
2559
2560 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)
;
2561 REQUEST_AT_LEAST_SIZE(xRecordUnregisterClientsReq)if ((sizeof(xRecordUnregisterClientsReq) >> 2) > client
->req_len ) return(16)
;
2562 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)
;
2563 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)
;
2564 SwapRestL(stuff)SwapLongs((CARD32 *)(stuff + 1), (client->req_len - (sizeof
(*stuff) >> 2)))
;
2565 return ProcRecordUnregisterClients(client);
2566} /* SProcRecordUnregisterClients */
2567
2568static int
2569SProcRecordGetContext(ClientPtr client)
2570{
2571 REQUEST(xRecordGetContextReq)xRecordGetContextReq *stuff = (xRecordGetContextReq *)client->
requestBuffer
;
2572
2573 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)
;
2574 REQUEST_SIZE_MATCH(xRecordGetContextReq)if ((sizeof(xRecordGetContextReq) >> 2) != client->req_len
) return(16)
;
2575 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)
;
2576 return ProcRecordGetContext(client);
2577} /* SProcRecordGetContext */
2578
2579static int
2580SProcRecordEnableContext(ClientPtr client)
2581{
2582 REQUEST(xRecordEnableContextReq)xRecordEnableContextReq *stuff = (xRecordEnableContextReq *)client
->requestBuffer
;
2583
2584 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)
;
2585 REQUEST_SIZE_MATCH(xRecordEnableContextReq)if ((sizeof(xRecordEnableContextReq) >> 2) != client->
req_len) return(16)
;
2586 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)
;
2587 return ProcRecordEnableContext(client);
2588} /* SProcRecordEnableContext */
2589
2590static int
2591SProcRecordDisableContext(ClientPtr client)
2592{
2593 REQUEST(xRecordDisableContextReq)xRecordDisableContextReq *stuff = (xRecordDisableContextReq *
)client->requestBuffer
;
2594
2595 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)
;
2596 REQUEST_SIZE_MATCH(xRecordDisableContextReq)if ((sizeof(xRecordDisableContextReq) >> 2) != client->
req_len) return(16)
;
2597 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)
;
2598 return ProcRecordDisableContext(client);
2599} /* SProcRecordDisableContext */
2600
2601static int
2602SProcRecordFreeContext(ClientPtr client)
2603{
2604 REQUEST(xRecordFreeContextReq)xRecordFreeContextReq *stuff = (xRecordFreeContextReq *)client
->requestBuffer
;
2605
2606 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)
;
2607 REQUEST_SIZE_MATCH(xRecordFreeContextReq)if ((sizeof(xRecordFreeContextReq) >> 2) != client->
req_len) return(16)
;
2608 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)
;
2609 return ProcRecordFreeContext(client);
2610} /* SProcRecordFreeContext */
2611
2612static int
2613SProcRecordDispatch(ClientPtr client)
2614{
2615 REQUEST(xReq)xReq *stuff = (xReq *)client->requestBuffer;
2616
2617 switch (stuff->data) {
2618 case X_RecordQueryVersion0:
2619 return SProcRecordQueryVersion(client);
2620 case X_RecordCreateContext1:
2621 return SProcRecordCreateContext(client);
2622 case X_RecordRegisterClients2:
2623 return SProcRecordRegisterClients(client);
2624 case X_RecordUnregisterClients3:
2625 return SProcRecordUnregisterClients(client);
2626 case X_RecordGetContext4:
2627 return SProcRecordGetContext(client);
2628 case X_RecordEnableContext5:
2629 return SProcRecordEnableContext(client);
2630 case X_RecordDisableContext6:
2631 return SProcRecordDisableContext(client);
2632 case X_RecordFreeContext7:
2633 return SProcRecordFreeContext(client);
2634 default:
2635 return BadRequest1;
2636 }
2637} /* SProcRecordDispatch */
2638
2639/* RecordConnectionSetupInfo
2640 *
2641 * Arguments:
2642 * pContext is an enabled context that specifies recording of
2643 * connection setup info.
2644 * pci holds the connection setup info.
2645 *
2646 * Returns: nothing.
2647 *
2648 * Side Effects:
2649 * The connection setup info is sent to the recording client.
2650 */
2651static void
2652RecordConnectionSetupInfo(RecordContextPtr pContext, NewClientInfoRec * pci)
2653{
2654 int prefixsize = SIZEOF(xConnSetupPrefix)8;
2655 int restsize = pci->prefix->length * 4;
2656
2657 if (pci->client->swapped) {
2658 char *pConnSetup = (char *) malloc(prefixsize + restsize);
2659
2660 if (!pConnSetup)
2661 return;
2662 SwapConnSetupPrefix(pci->prefix, (xConnSetupPrefix *) pConnSetup);
2663 SwapConnSetupInfo((char *) pci->setup,
2664 (char *) (pConnSetup + prefixsize));
2665 RecordAProtocolElement(pContext, pci->client, XRecordClientStarted2,
2666 (void *) pConnSetup, prefixsize + restsize, 0,
2667 0);
2668 free(pConnSetup);
2669 }
2670 else {
2671 /* don't alloc and copy as in the swapped case; just send the
2672 * data in two pieces
2673 */
2674 RecordAProtocolElement(pContext, pci->client, XRecordClientStarted2,
2675 (void *) pci->prefix, prefixsize, 0, restsize);
2676 RecordAProtocolElement(pContext, pci->client, XRecordClientStarted2,
2677 (void *) pci->setup, restsize, 0,
2678 /* continuation */ -1);
2679 }
2680} /* RecordConnectionSetupInfo */
2681
2682/* RecordDeleteContext
2683 *
2684 * Arguments:
2685 * pcbl is &ClientStateCallback.
2686 * nullata is NULL.
2687 * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
2688 * which contains information about client state changes.
2689 *
2690 * Returns: nothing.
2691 *
2692 * Side Effects:
2693 * If a new client has connected and any contexts have specified
2694 * XRecordFutureClients, the new client is registered on those contexts.
2695 * If any of those contexts specify recording of the connection setup
2696 * info, it is recorded.
2697 *
2698 * If an existing client has disconnected, it is deleted from any
2699 * contexts that it was registered on. If any of those contexts
2700 * specified XRecordClientDied, they record a ClientDied protocol element.
2701 * If the disconnectiong client happened to be the data connection of an
2702 * enabled context, the context is disabled.
2703 */
2704
2705static void
2706RecordAClientStateChange(CallbackListPtr *pcbl, void *nulldata,
2707 void *calldata)
2708{
2709 NewClientInfoRec *pci = (NewClientInfoRec *) calldata;
2710 int i;
2711 ClientPtr pClient = pci->client;
2712 RecordContextPtr *ppAllContextsCopy = NULL((void*)0);
2713 int numContextsCopy = 0;
2714
2715 switch (pClient->clientState) {
2716 case ClientStateRunning: /* new client */
2717 for (i = 0; i < numContexts; i++) {
2718 RecordClientsAndProtocolPtr pRCAP;
2719 RecordContextPtr pContext = ppAllContexts[i];
2720
2721 if ((pRCAP = RecordFindClientOnContext(pContext,
2722 XRecordFutureClients2, NULL((void*)0))))
2723 {
2724 RecordAddClientToRCAP(pRCAP, pClient->clientAsMask);
2725 if (pContext->pRecordingClient && pRCAP->clientStarted)
2726 RecordConnectionSetupInfo(pContext, pci);
2727 }
2728 }
2729 break;
2730
2731 case ClientStateGone:
2732 case ClientStateRetained: /* client disconnected */
2733
2734 /* RecordDisableContext modifies contents of ppAllContexts. */
2735 numContextsCopy = numContexts;
2736 ppAllContextsCopy = malloc(numContextsCopy * sizeof(RecordContextPtr));
2737 assert(ppAllContextsCopy)(__builtin_expect(!(ppAllContextsCopy), 0) ? __assert_rtn(__func__
, "record.c", 2737, "ppAllContextsCopy") : (void)0)
;
2738 memcpy(ppAllContextsCopy, ppAllContexts,__builtin___memcpy_chk (ppAllContextsCopy, ppAllContexts, numContextsCopy
* sizeof(RecordContextPtr), __builtin_object_size (ppAllContextsCopy
, 0))
2739 numContextsCopy * sizeof(RecordContextPtr))__builtin___memcpy_chk (ppAllContextsCopy, ppAllContexts, numContextsCopy
* sizeof(RecordContextPtr), __builtin_object_size (ppAllContextsCopy
, 0))
;
2740
2741 for (i = 0; i < numContextsCopy; i++) {
2742 RecordClientsAndProtocolPtr pRCAP;
2743 RecordContextPtr pContext = ppAllContextsCopy[i];
2744 int pos;
2745
2746 if (pContext->pRecordingClient == pClient)
2747 RecordDisableContext(pContext);
2748 if ((pRCAP = RecordFindClientOnContext(pContext,
2749 pClient->clientAsMask,
2750 &pos))) {
2751 if (pContext->pRecordingClient && pRCAP->clientDied)
2752 RecordAProtocolElement(pContext, pClient,
2753 XRecordClientDied3, NULL((void*)0), 0, 0, 0);
2754 RecordDeleteClientFromRCAP(pRCAP, pos);
2755 }
2756 }
2757
2758 free(ppAllContextsCopy);
2759 break;
2760
2761 default:
2762 break;
2763 } /* end switch on client state */
2764} /* RecordAClientStateChange */
2765
2766/* RecordCloseDown
2767 *
2768 * Arguments:
2769 * extEntry is the extension information for RECORD.
2770 *
2771 * Returns: nothing.
2772 *
2773 * Side Effects:
2774 * Performs any cleanup needed by RECORD at server shutdown time.
2775 *
2776 */
2777static void
2778RecordCloseDown(ExtensionEntry * extEntry)
2779{
2780 DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL((void*)0));
2781} /* RecordCloseDown */
2782
2783/* RecordExtensionInit
2784 *
2785 * Arguments: none.
2786 *
2787 * Returns: nothing.
2788 *
2789 * Side Effects:
2790 * Enables the RECORD extension if possible.
2791 */
2792void
2793RecordExtensionInit(void)
2794{
2795 ExtensionEntry *extentry;
2796
2797 RTContext = CreateNewResourceType(RecordDeleteContext, "RecordContext");
2798 if (!RTContext)
2799 return;
2800
2801 if (!dixRegisterPrivateKey(RecordClientPrivateKey(&RecordClientPrivateKeyRec), PRIVATE_CLIENT, 0))
2802 return;
2803
2804 ppAllContexts = NULL((void*)0);
2805 numContexts = numEnabledContexts = numEnabledRCAPs = 0;
2806
2807 if (!AddCallback(&ClientStateCallback, RecordAClientStateChange, NULL((void*)0)))
2808 return;
2809
2810 extentry = AddExtension(RECORD_NAME"RECORD", RecordNumEvents0L, RecordNumErrors(0 + 1),
2811 ProcRecordDispatch, SProcRecordDispatch,
2812 RecordCloseDown, StandardMinorOpcode);
2813 if (!extentry) {
2814 DeleteCallback(&ClientStateCallback, RecordAClientStateChange, NULL((void*)0));
2815 return;
2816 }
2817 SetResourceTypeErrorValue(RTContext,
2818 extentry->errorBase + XRecordBadContext0);
2819
2820} /* RecordExtensionInit */