Imported Upstream version 1.15.1
[deb_xorg-server.git] / dix / dispatch.c
CommitLineData
a09e091a
JB
1/************************************************************
2
3Copyright 1987, 1989, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27 All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Digital not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45********************************************************/
46
47/* The panoramix components contained the following notice */
48/*****************************************************************
49
50Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
51
52Permission is hereby granted, free of charge, to any person obtaining a copy
53of this software and associated documentation files (the "Software"), to deal
54in the Software without restriction, including without limitation the rights
55to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56copies of the Software.
57
58The above copyright notice and this permission notice shall be included in
59all copies or substantial portions of the Software.
60
61THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
64DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
65BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
66WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
67IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68
69Except as contained in this notice, the name of Digital Equipment Corporation
70shall not be used in advertising or otherwise to promote the sale, use or other
71dealings in this Software without prior written authorization from Digital
72Equipment Corporation.
73
74******************************************************************/
75
76/* XSERVER_DTRACE additions:
77 * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
78 *
79 * Permission is hereby granted, free of charge, to any person obtaining a
80 * copy of this software and associated documentation files (the "Software"),
81 * to deal in the Software without restriction, including without limitation
82 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83 * and/or sell copies of the Software, and to permit persons to whom the
84 * Software is furnished to do so, subject to the following conditions:
85 *
86 * The above copyright notice and this permission notice (including the next
87 * paragraph) shall be included in all copies or substantial portions of the
88 * Software.
89 *
90 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
93 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
95 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
96 * DEALINGS IN THE SOFTWARE.
97 */
98
99#ifdef HAVE_DIX_CONFIG_H
100#include <dix-config.h>
101#include <version-config.h>
102#endif
103
104#ifdef PANORAMIX_DEBUG
105#include <stdio.h>
106int ProcInitialConnection();
107#endif
108
109#include "windowstr.h"
110#include <X11/fonts/fontstruct.h>
111#include "dixfontstr.h"
112#include "gcstruct.h"
113#include "selection.h"
114#include "colormapst.h"
115#include "cursorstr.h"
116#include "scrnintstr.h"
117#include "opaque.h"
118#include "input.h"
119#include "servermd.h"
120#include "extnsionst.h"
121#include "dixfont.h"
122#include "dispatch.h"
123#include "swaprep.h"
124#include "swapreq.h"
125#include "privates.h"
126#include "xace.h"
127#include "inputstr.h"
128#include "xkbsrv.h"
129#include "site.h"
130#include "client.h"
131
132#ifdef XSERVER_DTRACE
133#include "registry.h"
134#include <sys/types.h>
135typedef const char *string;
136
137#include "Xserver-dtrace.h"
138#endif
139
140#define mskcnt ((MAXCLIENTS + 31) / 32)
141#define BITMASK(i) (1U << ((i) & 31))
142#define MASKIDX(i) ((i) >> 5)
143#define MASKWORD(buf, i) buf[MASKIDX(i)]
144#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
145#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
146#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
147
148xConnSetupPrefix connSetupPrefix;
149
150PaddingInfo PixmapWidthPaddingInfo[33];
151
152static ClientPtr grabClient;
153
154#define GrabNone 0
155#define GrabActive 1
156#define GrabKickout 2
157static int grabState = GrabNone;
158static long grabWaiters[mskcnt];
159CallbackListPtr ServerGrabCallback = NULL;
160HWEventQueuePtr checkForInput[2];
161int connBlockScreenStart;
162
163static void KillAllClients(void);
164
165static int nextFreeClientID; /* always MIN free client ID */
166
167static int nClients; /* number of authorized clients */
168
169CallbackListPtr ClientStateCallback;
170
171/* dispatchException & isItTimeToYield must be declared volatile since they
172 * are modified by signal handlers - otherwise optimizer may assume it doesn't
173 * need to actually check value in memory when used and may miss changes from
174 * signal handlers.
175 */
176volatile char dispatchException = 0;
177volatile char isItTimeToYield;
178
179#define SAME_SCREENS(a, b) (\
180 (a.pScreen == b.pScreen))
181
182void
183SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
184{
185 checkForInput[0] = c0;
186 checkForInput[1] = c1;
187}
188
189void
190UpdateCurrentTime(void)
191{
192 TimeStamp systime;
193
194 /* To avoid time running backwards, we must call GetTimeInMillis before
195 * calling ProcessInputEvents.
196 */
197 systime.months = currentTime.months;
198 systime.milliseconds = GetTimeInMillis();
199 if (systime.milliseconds < currentTime.milliseconds)
200 systime.months++;
201 if (*checkForInput[0] != *checkForInput[1])
202 ProcessInputEvents();
203 if (CompareTimeStamps(systime, currentTime) == LATER)
204 currentTime = systime;
205}
206
207/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
208void
209UpdateCurrentTimeIf(void)
210{
211 TimeStamp systime;
212
213 systime.months = currentTime.months;
214 systime.milliseconds = GetTimeInMillis();
215 if (systime.milliseconds < currentTime.milliseconds)
216 systime.months++;
217 if (CompareTimeStamps(systime, currentTime) == LATER)
218 currentTime = systime;
219}
220
221#undef SMART_DEBUG
222
223/* in milliseconds */
224#define SMART_SCHEDULE_DEFAULT_INTERVAL 5
225#define SMART_SCHEDULE_MAX_SLICE 15
226
227#if defined(WIN32) && !defined(__CYGWIN__)
228Bool SmartScheduleDisable = TRUE;
229#else
230Bool SmartScheduleDisable = FALSE;
231#endif
232long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
233long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
234long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
235long SmartScheduleTime;
236int SmartScheduleLatencyLimited = 0;
237static ClientPtr SmartLastClient;
238static int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
239
240#ifdef SMART_DEBUG
241long SmartLastPrint;
242#endif
243
244void Dispatch(void);
245
246static int
247SmartScheduleClient(int *clientReady, int nready)
248{
249 ClientPtr pClient;
250 int i;
251 int client;
252 int bestPrio, best = 0;
253 int bestRobin, robin;
254 long now = SmartScheduleTime;
255 long idle;
256
257 bestPrio = -0x7fffffff;
258 bestRobin = 0;
259 idle = 2 * SmartScheduleSlice;
260 for (i = 0; i < nready; i++) {
261 client = clientReady[i];
262 pClient = clients[client];
263 /* Praise clients which are idle */
264 if ((now - pClient->smart_check_tick) >= idle) {
265 if (pClient->smart_priority < 0)
266 pClient->smart_priority++;
267 }
268 pClient->smart_check_tick = now;
269
270 /* check priority to select best client */
271 robin =
272 (pClient->index -
273 SmartLastIndex[pClient->smart_priority -
274 SMART_MIN_PRIORITY]) & 0xff;
275 if (pClient->smart_priority > bestPrio ||
276 (pClient->smart_priority == bestPrio && robin > bestRobin)) {
277 bestPrio = pClient->smart_priority;
278 bestRobin = robin;
279 best = client;
280 }
281#ifdef SMART_DEBUG
282 if ((now - SmartLastPrint) >= 5000)
283 fprintf(stderr, " %2d: %3d", client, pClient->smart_priority);
284#endif
285 }
286#ifdef SMART_DEBUG
287 if ((now - SmartLastPrint) >= 5000) {
288 fprintf(stderr, " use %2d\n", best);
289 SmartLastPrint = now;
290 }
291#endif
292 pClient = clients[best];
293 SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index;
294 /*
295 * Set current client pointer
296 */
297 if (SmartLastClient != pClient) {
298 pClient->smart_start_tick = now;
299 SmartLastClient = pClient;
300 }
301 /*
302 * Adjust slice
303 */
304 if (nready == 1 && SmartScheduleLatencyLimited == 0) {
305 /*
306 * If it's been a long time since another client
307 * has run, bump the slice up to get maximal
308 * performance from a single client
309 */
310 if ((now - pClient->smart_start_tick) > 1000 &&
311 SmartScheduleSlice < SmartScheduleMaxSlice) {
312 SmartScheduleSlice += SmartScheduleInterval;
313 }
314 }
315 else {
316 SmartScheduleSlice = SmartScheduleInterval;
317 }
318 return best;
319}
320
321void
322EnableLimitedSchedulingLatency(void)
323{
324 ++SmartScheduleLatencyLimited;
325 SmartScheduleSlice = SmartScheduleInterval;
326}
327
328void
329DisableLimitedSchedulingLatency(void)
330{
331 --SmartScheduleLatencyLimited;
332
333 /* protect against bugs */
334 if (SmartScheduleLatencyLimited < 0)
335 SmartScheduleLatencyLimited = 0;
336}
337
338void
339Dispatch(void)
340{
341 int *clientReady; /* array of request ready clients */
342 int result;
343 ClientPtr client;
344 int nready;
345 HWEventQueuePtr *icheck = checkForInput;
346 long start_tick;
347
348 nextFreeClientID = 1;
349 nClients = 0;
350
351 clientReady = malloc(sizeof(int) * MaxClients);
352 if (!clientReady)
353 return;
354
355 SmartScheduleSlice = SmartScheduleInterval;
356 while (!dispatchException) {
357 if (*icheck[0] != *icheck[1]) {
358 ProcessInputEvents();
359 FlushIfCriticalOutputPending();
360 }
361
362 nready = WaitForSomething(clientReady);
363
364 if (nready && !SmartScheduleDisable) {
365 clientReady[0] = SmartScheduleClient(clientReady, nready);
366 nready = 1;
367 }
368 /*****************
369 * Handle events in round robin fashion, doing input between
370 * each round
371 *****************/
372
373 while (!dispatchException && (--nready >= 0)) {
374 client = clients[clientReady[nready]];
375 if (!client) {
376 /* KillClient can cause this to happen */
377 continue;
378 }
379 /* GrabServer activation can cause this to be true */
380 if (grabState == GrabKickout) {
381 grabState = GrabActive;
382 break;
383 }
384 isItTimeToYield = FALSE;
385
386 start_tick = SmartScheduleTime;
387 while (!isItTimeToYield) {
388 if (*icheck[0] != *icheck[1])
389 ProcessInputEvents();
390
391 FlushIfCriticalOutputPending();
392 if (!SmartScheduleDisable &&
393 (SmartScheduleTime - start_tick) >= SmartScheduleSlice) {
394 /* Penalize clients which consume ticks */
395 if (client->smart_priority > SMART_MIN_PRIORITY)
396 client->smart_priority--;
397 break;
398 }
399 /* now, finally, deal with client requests */
400
401 /* Update currentTime so request time checks, such as for input
402 * device grabs, are calculated correctly */
403 UpdateCurrentTimeIf();
404 result = ReadRequestFromClient(client);
405 if (result <= 0) {
406 if (result < 0)
407 CloseDownClient(client);
408 break;
409 }
410
411 client->sequence++;
412 client->majorOp = ((xReq *) client->requestBuffer)->reqType;
413 client->minorOp = 0;
414 if (client->majorOp >= EXTENSION_BASE) {
415 ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
416
417 if (ext)
418 client->minorOp = ext->MinorOpcode(client);
419 }
420#ifdef XSERVER_DTRACE
421 if (XSERVER_REQUEST_START_ENABLED())
422 XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
423 client->majorOp,
424 ((xReq *) client->requestBuffer)->length,
425 client->index,
426 client->requestBuffer);
427#endif
428 if (result > (maxBigRequestSize << 2))
429 result = BadLength;
430 else {
431 result = XaceHookDispatch(client, client->majorOp);
432 if (result == Success)
433 result =
434 (*client->requestVector[client->majorOp]) (client);
435 XaceHookAuditEnd(client, result);
436 }
437#ifdef XSERVER_DTRACE
438 if (XSERVER_REQUEST_DONE_ENABLED())
439 XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
440 client->majorOp, client->sequence,
441 client->index, result);
442#endif
443
444 if (client->noClientException != Success) {
445 CloseDownClient(client);
446 break;
447 }
448 else if (result != Success) {
449 SendErrorToClient(client, client->majorOp,
450 client->minorOp,
451 client->errorValue, result);
452 break;
453 }
454 }
455 FlushAllOutput();
456 client = clients[clientReady[nready]];
457 if (client)
458 client->smart_stop_tick = SmartScheduleTime;
459 }
460 dispatchException &= ~DE_PRIORITYCHANGE;
461 }
462#if defined(DDXBEFORERESET)
463 ddxBeforeReset();
464#endif
465 KillAllClients();
466 free(clientReady);
467 dispatchException &= ~DE_RESET;
468 SmartScheduleLatencyLimited = 0;
469 ResetOsBuffers();
470}
471
472static int VendorRelease = VENDOR_RELEASE;
473static char *VendorString = VENDOR_NAME;
474
475void
476SetVendorRelease(int release)
477{
478 VendorRelease = release;
479}
480
481void
482SetVendorString(char *string)
483{
484 VendorString = string;
485}
486
487Bool
488CreateConnectionBlock(void)
489{
490 xConnSetup setup;
491 xWindowRoot root;
492 xDepth depth;
493 xVisualType visual;
494 xPixmapFormat format;
495 unsigned long vid;
496 int i, j, k, lenofblock, sizesofar = 0;
497 char *pBuf;
498
499 memset(&setup, 0, sizeof(xConnSetup));
500 /* Leave off the ridBase and ridMask, these must be sent with
501 connection */
502
503 setup.release = VendorRelease;
504 /*
505 * per-server image and bitmap parameters are defined in Xmd.h
506 */
507 setup.imageByteOrder = screenInfo.imageByteOrder;
508
509 setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
510 setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
511
512 setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
513 setup.motionBufferSize = NumMotionEvents();
514 setup.numRoots = screenInfo.numScreens;
515 setup.nbytesVendor = strlen(VendorString);
516 setup.numFormats = screenInfo.numPixmapFormats;
517 setup.maxRequestSize = MAX_REQUEST_SIZE;
518 QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
519
520 lenofblock = sizeof(xConnSetup) +
521 pad_to_int32(setup.nbytesVendor) +
522 (setup.numFormats * sizeof(xPixmapFormat)) +
523 (setup.numRoots * sizeof(xWindowRoot));
524 ConnectionInfo = malloc(lenofblock);
525 if (!ConnectionInfo)
526 return FALSE;
527
528 memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
529 sizesofar = sizeof(xConnSetup);
530 pBuf = ConnectionInfo + sizeof(xConnSetup);
531
532 memmove(pBuf, VendorString, (int) setup.nbytesVendor);
533 sizesofar += setup.nbytesVendor;
534 pBuf += setup.nbytesVendor;
535 i = padding_for_int32(setup.nbytesVendor);
536 sizesofar += i;
537 while (--i >= 0)
538 *pBuf++ = 0;
539
540 memset(&format, 0, sizeof(xPixmapFormat));
541 for (i = 0; i < screenInfo.numPixmapFormats; i++) {
542 format.depth = screenInfo.formats[i].depth;
543 format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
544 format.scanLinePad = screenInfo.formats[i].scanlinePad;
545 memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
546 pBuf += sizeof(xPixmapFormat);
547 sizesofar += sizeof(xPixmapFormat);
548 }
549
550 connBlockScreenStart = sizesofar;
551 memset(&depth, 0, sizeof(xDepth));
552 memset(&visual, 0, sizeof(xVisualType));
553 for (i = 0; i < screenInfo.numScreens; i++) {
554 ScreenPtr pScreen;
555 DepthPtr pDepth;
556 VisualPtr pVisual;
557
558 pScreen = screenInfo.screens[i];
559 root.windowId = pScreen->root->drawable.id;
560 root.defaultColormap = pScreen->defColormap;
561 root.whitePixel = pScreen->whitePixel;
562 root.blackPixel = pScreen->blackPixel;
563 root.currentInputMask = 0; /* filled in when sent */
564 root.pixWidth = pScreen->width;
565 root.pixHeight = pScreen->height;
566 root.mmWidth = pScreen->mmWidth;
567 root.mmHeight = pScreen->mmHeight;
568 root.minInstalledMaps = pScreen->minInstalledCmaps;
569 root.maxInstalledMaps = pScreen->maxInstalledCmaps;
570 root.rootVisualID = pScreen->rootVisual;
571 root.backingStore = pScreen->backingStoreSupport;
572 root.saveUnders = FALSE;
573 root.rootDepth = pScreen->rootDepth;
574 root.nDepths = pScreen->numDepths;
575 memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
576 sizesofar += sizeof(xWindowRoot);
577 pBuf += sizeof(xWindowRoot);
578
579 pDepth = pScreen->allowedDepths;
580 for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
581 lenofblock += sizeof(xDepth) +
582 (pDepth->numVids * sizeof(xVisualType));
583 pBuf = (char *) realloc(ConnectionInfo, lenofblock);
584 if (!pBuf) {
585 free(ConnectionInfo);
586 return FALSE;
587 }
588 ConnectionInfo = pBuf;
589 pBuf += sizesofar;
590 depth.depth = pDepth->depth;
591 depth.nVisuals = pDepth->numVids;
592 memmove(pBuf, (char *) &depth, sizeof(xDepth));
593 pBuf += sizeof(xDepth);
594 sizesofar += sizeof(xDepth);
595 for (k = 0; k < pDepth->numVids; k++) {
596 vid = pDepth->vids[k];
597 for (pVisual = pScreen->visuals;
598 pVisual->vid != vid; pVisual++);
599 visual.visualID = vid;
600 visual.class = pVisual->class;
601 visual.bitsPerRGB = pVisual->bitsPerRGBValue;
602 visual.colormapEntries = pVisual->ColormapEntries;
603 visual.redMask = pVisual->redMask;
604 visual.greenMask = pVisual->greenMask;
605 visual.blueMask = pVisual->blueMask;
606 memmove(pBuf, (char *) &visual, sizeof(xVisualType));
607 pBuf += sizeof(xVisualType);
608 sizesofar += sizeof(xVisualType);
609 }
610 }
611 }
612 connSetupPrefix.success = xTrue;
613 connSetupPrefix.length = lenofblock / 4;
614 connSetupPrefix.majorVersion = X_PROTOCOL;
615 connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
616 return TRUE;
617}
618
619int
620ProcBadRequest(ClientPtr client)
621{
622 return BadRequest;
623}
624
625int
626ProcCreateWindow(ClientPtr client)
627{
628 WindowPtr pParent, pWin;
629
630 REQUEST(xCreateWindowReq);
631 int len, rc;
632
633 REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
634
635 LEGAL_NEW_RESOURCE(stuff->wid, client);
636 rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
637 if (rc != Success)
638 return rc;
639 len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
640 if (Ones(stuff->mask) != len)
641 return BadLength;
642 if (!stuff->width || !stuff->height) {
643 client->errorValue = 0;
644 return BadValue;
645 }
646 pWin = CreateWindow(stuff->wid, pParent, stuff->x,
647 stuff->y, stuff->width, stuff->height,
648 stuff->borderWidth, stuff->class,
649 stuff->mask, (XID *) &stuff[1],
650 (int) stuff->depth, client, stuff->visual, &rc);
651 if (pWin) {
652 Mask mask = pWin->eventMask;
653
654 pWin->eventMask = 0; /* subterfuge in case AddResource fails */
655 if (!AddResource(stuff->wid, RT_WINDOW, (pointer) pWin))
656 return BadAlloc;
657 pWin->eventMask = mask;
658 }
659 return rc;
660}
661
662int
663ProcChangeWindowAttributes(ClientPtr client)
664{
665 WindowPtr pWin;
666
667 REQUEST(xChangeWindowAttributesReq);
668 int len, rc;
669 Mask access_mode = 0;
670
671 REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
672 access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
673 access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
674 rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
675 if (rc != Success)
676 return rc;
677 len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
678 if (len != Ones(stuff->valueMask))
679 return BadLength;
680 return ChangeWindowAttributes(pWin,
681 stuff->valueMask, (XID *) &stuff[1], client);
682}
683
684int
685ProcGetWindowAttributes(ClientPtr client)
686{
687 WindowPtr pWin;
688
689 REQUEST(xResourceReq);
690 xGetWindowAttributesReply wa;
691 int rc;
692
693 REQUEST_SIZE_MATCH(xResourceReq);
694 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
695 if (rc != Success)
696 return rc;
697 memset(&wa, 0, sizeof(xGetWindowAttributesReply));
698 GetWindowAttributes(pWin, client, &wa);
699 WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
700 return Success;
701}
702
703int
704ProcDestroyWindow(ClientPtr client)
705{
706 WindowPtr pWin;
707
708 REQUEST(xResourceReq);
709 int rc;
710
711 REQUEST_SIZE_MATCH(xResourceReq);
712 rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
713 if (rc != Success)
714 return rc;
715 if (pWin->parent) {
716 rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
717 DixRemoveAccess);
718 if (rc != Success)
719 return rc;
720 FreeResource(stuff->id, RT_NONE);
721 }
722 return Success;
723}
724
725int
726ProcDestroySubwindows(ClientPtr client)
727{
728 WindowPtr pWin;
729
730 REQUEST(xResourceReq);
731 int rc;
732
733 REQUEST_SIZE_MATCH(xResourceReq);
734 rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
735 if (rc != Success)
736 return rc;
737 DestroySubwindows(pWin, client);
738 return Success;
739}
740
741int
742ProcChangeSaveSet(ClientPtr client)
743{
744 WindowPtr pWin;
745
746 REQUEST(xChangeSaveSetReq);
747 int rc;
748
749 REQUEST_SIZE_MATCH(xChangeSaveSetReq);
750 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
751 if (rc != Success)
752 return rc;
753 if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
754 return BadMatch;
755 if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
756 return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
757 client->errorValue = stuff->mode;
758 return BadValue;
759}
760
761int
762ProcReparentWindow(ClientPtr client)
763{
764 WindowPtr pWin, pParent;
765
766 REQUEST(xReparentWindowReq);
767 int rc;
768
769 REQUEST_SIZE_MATCH(xReparentWindowReq);
770 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
771 if (rc != Success)
772 return rc;
773 rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
774 if (rc != Success)
775 return rc;
776 if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
777 return BadMatch;
778 if ((pWin->backgroundState == ParentRelative) &&
779 (pParent->drawable.depth != pWin->drawable.depth))
780 return BadMatch;
781 if ((pWin->drawable.class != InputOnly) &&
782 (pParent->drawable.class == InputOnly))
783 return BadMatch;
784 return ReparentWindow(pWin, pParent,
785 (short) stuff->x, (short) stuff->y, client);
786}
787
788int
789ProcMapWindow(ClientPtr client)
790{
791 WindowPtr pWin;
792
793 REQUEST(xResourceReq);
794 int rc;
795
796 REQUEST_SIZE_MATCH(xResourceReq);
797 rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
798 if (rc != Success)
799 return rc;
800 MapWindow(pWin, client);
801 /* update cache to say it is mapped */
802 return Success;
803}
804
805int
806ProcMapSubwindows(ClientPtr client)
807{
808 WindowPtr pWin;
809
810 REQUEST(xResourceReq);
811 int rc;
812
813 REQUEST_SIZE_MATCH(xResourceReq);
814 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
815 if (rc != Success)
816 return rc;
817 MapSubwindows(pWin, client);
818 /* update cache to say it is mapped */
819 return Success;
820}
821
822int
823ProcUnmapWindow(ClientPtr client)
824{
825 WindowPtr pWin;
826
827 REQUEST(xResourceReq);
828 int rc;
829
830 REQUEST_SIZE_MATCH(xResourceReq);
831 rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
832 if (rc != Success)
833 return rc;
834 UnmapWindow(pWin, FALSE);
835 /* update cache to say it is mapped */
836 return Success;
837}
838
839int
840ProcUnmapSubwindows(ClientPtr client)
841{
842 WindowPtr pWin;
843
844 REQUEST(xResourceReq);
845 int rc;
846
847 REQUEST_SIZE_MATCH(xResourceReq);
848 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
849 if (rc != Success)
850 return rc;
851 UnmapSubwindows(pWin);
852 return Success;
853}
854
855int
856ProcConfigureWindow(ClientPtr client)
857{
858 WindowPtr pWin;
859
860 REQUEST(xConfigureWindowReq);
861 int len, rc;
862
863 REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
864 rc = dixLookupWindow(&pWin, stuff->window, client,
865 DixManageAccess | DixSetAttrAccess);
866 if (rc != Success)
867 return rc;
868 len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
869 if (Ones((Mask) stuff->mask) != len)
870 return BadLength;
871 return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
872}
873
874int
875ProcCirculateWindow(ClientPtr client)
876{
877 WindowPtr pWin;
878
879 REQUEST(xCirculateWindowReq);
880 int rc;
881
882 REQUEST_SIZE_MATCH(xCirculateWindowReq);
883 if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
884 client->errorValue = stuff->direction;
885 return BadValue;
886 }
887 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
888 if (rc != Success)
889 return rc;
890 CirculateWindow(pWin, (int) stuff->direction, client);
891 return Success;
892}
893
894static int
895GetGeometry(ClientPtr client, xGetGeometryReply * rep)
896{
897 DrawablePtr pDraw;
898 int rc;
899
900 REQUEST(xResourceReq);
901 REQUEST_SIZE_MATCH(xResourceReq);
902
903 rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
904 if (rc != Success)
905 return rc;
906
907 rep->type = X_Reply;
908 rep->length = 0;
909 rep->sequenceNumber = client->sequence;
910 rep->root = pDraw->pScreen->root->drawable.id;
911 rep->depth = pDraw->depth;
912 rep->width = pDraw->width;
913 rep->height = pDraw->height;
914
915 if (WindowDrawable(pDraw->type)) {
916 WindowPtr pWin = (WindowPtr) pDraw;
917
918 rep->x = pWin->origin.x - wBorderWidth(pWin);
919 rep->y = pWin->origin.y - wBorderWidth(pWin);
920 rep->borderWidth = pWin->borderWidth;
921 }
922 else { /* DRAWABLE_PIXMAP */
923
924 rep->x = rep->y = rep->borderWidth = 0;
925 }
926
927 return Success;
928}
929
930int
931ProcGetGeometry(ClientPtr client)
932{
933 xGetGeometryReply rep = { .type = X_Reply };
934 int status;
935
936 if ((status = GetGeometry(client, &rep)) != Success)
937 return status;
938
939 WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
940 return Success;
941}
942
943int
944ProcQueryTree(ClientPtr client)
945{
946 xQueryTreeReply reply;
947 int rc, numChildren = 0;
948 WindowPtr pChild, pWin, pHead;
949 Window *childIDs = (Window *) NULL;
950
951 REQUEST(xResourceReq);
952
953 REQUEST_SIZE_MATCH(xResourceReq);
954 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
955 if (rc != Success)
956 return rc;
957
958 reply = (xQueryTreeReply) {
959 .type = X_Reply,
960 .sequenceNumber = client->sequence,
961 .root = pWin->drawable.pScreen->root->drawable.id,
962 .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None
963 };
964 pHead = RealChildHead(pWin);
965 for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
966 numChildren++;
967 if (numChildren) {
968 int curChild = 0;
969
970 childIDs = malloc(numChildren * sizeof(Window));
971 if (!childIDs)
972 return BadAlloc;
973 for (pChild = pWin->lastChild; pChild != pHead;
974 pChild = pChild->prevSib)
975 childIDs[curChild++] = pChild->drawable.id;
976 }
977
978 reply.nChildren = numChildren;
979 reply.length = bytes_to_int32(numChildren * sizeof(Window));
980
981 WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
982 if (numChildren) {
983 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
984 WriteSwappedDataToClient(client, numChildren * sizeof(Window),
985 childIDs);
986 free(childIDs);
987 }
988
989 return Success;
990}
991
992int
993ProcInternAtom(ClientPtr client)
994{
995 Atom atom;
996 char *tchar;
997
998 REQUEST(xInternAtomReq);
999
1000 REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
1001 if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
1002 client->errorValue = stuff->onlyIfExists;
1003 return BadValue;
1004 }
1005 tchar = (char *) &stuff[1];
1006 atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
1007 if (atom != BAD_RESOURCE) {
1008 xInternAtomReply reply = {
1009 .type = X_Reply,
1010 .sequenceNumber = client->sequence,
1011 .length = 0,
1012 .atom = atom
1013 };
1014 WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
1015 return Success;
1016 }
1017 else
1018 return BadAlloc;
1019}
1020
1021int
1022ProcGetAtomName(ClientPtr client)
1023{
1024 const char *str;
1025
1026 REQUEST(xResourceReq);
1027
1028 REQUEST_SIZE_MATCH(xResourceReq);
1029 if ((str = NameForAtom(stuff->id))) {
1030 int len = strlen(str);
1031 xGetAtomNameReply reply = {
1032 .type = X_Reply,
1033 .sequenceNumber = client->sequence,
1034 .length = bytes_to_int32(len),
1035 .nameLength = len
1036 };
1037
1038 WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
1039 WriteToClient(client, len, str);
1040 return Success;
1041 }
1042 else {
1043 client->errorValue = stuff->id;
1044 return BadAtom;
1045 }
1046}
1047
1048int
1049ProcGrabServer(ClientPtr client)
1050{
1051 int rc;
1052
1053 REQUEST_SIZE_MATCH(xReq);
1054 if (grabState != GrabNone && client != grabClient) {
1055 ResetCurrentRequest(client);
1056 client->sequence--;
1057 BITSET(grabWaiters, client->index);
1058 IgnoreClient(client);
1059 return Success;
1060 }
1061 rc = OnlyListenToOneClient(client);
1062 if (rc != Success)
1063 return rc;
1064 grabState = GrabKickout;
1065 grabClient = client;
1066
1067 if (ServerGrabCallback) {
1068 ServerGrabInfoRec grabinfo;
1069
1070 grabinfo.client = client;
1071 grabinfo.grabstate = SERVER_GRABBED;
1072 CallCallbacks(&ServerGrabCallback, (pointer) &grabinfo);
1073 }
1074
1075 return Success;
1076}
1077
1078static void
1079UngrabServer(ClientPtr client)
1080{
1081 int i;
1082
1083 grabState = GrabNone;
1084 ListenToAllClients();
1085 for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
1086 if (i >= 0) {
1087 i <<= 5;
1088 while (!GETBIT(grabWaiters, i))
1089 i++;
1090 BITCLEAR(grabWaiters, i);
1091 AttendClient(clients[i]);
1092 }
1093
1094 if (ServerGrabCallback) {
1095 ServerGrabInfoRec grabinfo;
1096
1097 grabinfo.client = client;
1098 grabinfo.grabstate = SERVER_UNGRABBED;
1099 CallCallbacks(&ServerGrabCallback, (pointer) &grabinfo);
1100 }
1101}
1102
1103int
1104ProcUngrabServer(ClientPtr client)
1105{
1106 REQUEST_SIZE_MATCH(xReq);
1107 UngrabServer(client);
1108 return Success;
1109}
1110
1111int
1112ProcTranslateCoords(ClientPtr client)
1113{
1114 REQUEST(xTranslateCoordsReq);
1115
1116 WindowPtr pWin, pDst;
1117 xTranslateCoordsReply rep;
1118 int rc;
1119
1120 REQUEST_SIZE_MATCH(xTranslateCoordsReq);
1121 rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
1122 if (rc != Success)
1123 return rc;
1124 rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
1125 if (rc != Success)
1126 return rc;
1127
1128 rep = (xTranslateCoordsReply) {
1129 .type = X_Reply,
1130 .sequenceNumber = client->sequence,
1131 .length = 0
1132 };
1133 if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
1134 rep.sameScreen = xFalse;
1135 rep.child = None;
1136 rep.dstX = rep.dstY = 0;
1137 }
1138 else {
1139 INT16 x, y;
1140
1141 rep.sameScreen = xTrue;
1142 rep.child = None;
1143 /* computing absolute coordinates -- adjust to destination later */
1144 x = pWin->drawable.x + stuff->srcX;
1145 y = pWin->drawable.y + stuff->srcY;
1146 pWin = pDst->firstChild;
1147 while (pWin) {
1148 BoxRec box;
1149
1150 if ((pWin->mapped) &&
1151 (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
1152 (x < pWin->drawable.x + (int) pWin->drawable.width +
1153 wBorderWidth(pWin)) &&
1154 (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
1155 (y < pWin->drawable.y + (int) pWin->drawable.height +
1156 wBorderWidth(pWin))
1157 /* When a window is shaped, a further check
1158 * is made to see if the point is inside
1159 * borderSize
1160 */
1161 && (!wBoundingShape(pWin) ||
1162 RegionContainsPoint(&pWin->borderSize, x, y, &box))
1163
1164 && (!wInputShape(pWin) ||
1165 RegionContainsPoint(wInputShape(pWin),
1166 x - pWin->drawable.x,
1167 y - pWin->drawable.y, &box))
1168 ) {
1169 rep.child = pWin->drawable.id;
1170 pWin = (WindowPtr) NULL;
1171 }
1172 else
1173 pWin = pWin->nextSib;
1174 }
1175 /* adjust to destination coordinates */
1176 rep.dstX = x - pDst->drawable.x;
1177 rep.dstY = y - pDst->drawable.y;
1178 }
1179 WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
1180 return Success;
1181}
1182
1183int
1184ProcOpenFont(ClientPtr client)
1185{
1186 int err;
1187
1188 REQUEST(xOpenFontReq);
1189
1190 REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
1191 client->errorValue = stuff->fid;
1192 LEGAL_NEW_RESOURCE(stuff->fid, client);
1193 err = OpenFont(client, stuff->fid, (Mask) 0,
1194 stuff->nbytes, (char *) &stuff[1]);
1195 if (err == Success) {
1196 return Success;
1197 }
1198 else
1199 return err;
1200}
1201
1202int
1203ProcCloseFont(ClientPtr client)
1204{
1205 FontPtr pFont;
1206 int rc;
1207
1208 REQUEST(xResourceReq);
1209
1210 REQUEST_SIZE_MATCH(xResourceReq);
1211 rc = dixLookupResourceByType((pointer *) &pFont, stuff->id, RT_FONT,
1212 client, DixDestroyAccess);
1213 if (rc == Success) {
1214 FreeResource(stuff->id, RT_NONE);
1215 return Success;
1216 }
1217 else {
1218 client->errorValue = stuff->id;
1219 return rc;
1220 }
1221}
1222
1223int
1224ProcQueryFont(ClientPtr client)
1225{
1226 xQueryFontReply *reply;
1227 FontPtr pFont;
1228 int rc;
1229
1230 REQUEST(xResourceReq);
1231 REQUEST_SIZE_MATCH(xResourceReq);
1232
1233 rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
1234 if (rc != Success)
1235 return rc;
1236
1237 {
1238 xCharInfo *pmax = FONTINKMAX(pFont);
1239 xCharInfo *pmin = FONTINKMIN(pFont);
1240 int nprotoxcistructs;
1241 int rlength;
1242
1243 nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
1244 pmax->leftSideBearing == pmin->leftSideBearing &&
1245 pmax->descent == pmin->descent &&
1246 pmax->ascent == pmin->ascent &&
1247 pmax->characterWidth == pmin->characterWidth) ?
1248 0 : N2dChars(pFont);
1249
1250 rlength = sizeof(xQueryFontReply) +
1251 FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
1252 nprotoxcistructs * sizeof(xCharInfo);
1253 reply = calloc(1, rlength);
1254 if (!reply) {
1255 return BadAlloc;
1256 }
1257
1258 reply->type = X_Reply;
1259 reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
1260 reply->sequenceNumber = client->sequence;
1261 QueryFont(pFont, reply, nprotoxcistructs);
1262
1263 WriteReplyToClient(client, rlength, reply);
1264 free(reply);
1265 return Success;
1266 }
1267}
1268
1269int
1270ProcQueryTextExtents(ClientPtr client)
1271{
1272 xQueryTextExtentsReply reply;
1273 FontPtr pFont;
1274 ExtentInfoRec info;
1275 unsigned long length;
1276 int rc;
1277
1278 REQUEST(xQueryTextExtentsReq);
1279 REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
1280
1281 rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
1282 if (rc != Success)
1283 return rc;
1284
1285 length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
1286 length = length << 1;
1287 if (stuff->oddLength) {
1288 if (length == 0)
1289 return BadLength;
1290 length--;
1291 }
1292 if (!QueryTextExtents(pFont, length, (unsigned char *) &stuff[1], &info))
1293 return BadAlloc;
1294 reply = (xQueryTextExtentsReply) {
1295 .type = X_Reply,
1296 .drawDirection = info.drawDirection,
1297 .sequenceNumber = client->sequence,
1298 .length = 0,
1299 .fontAscent = info.fontAscent,
1300 .fontDescent = info.fontDescent,
1301 .overallAscent = info.overallAscent,
1302 .overallDescent = info.overallDescent,
1303 .overallWidth = info.overallWidth,
1304 .overallLeft = info.overallLeft,
1305 .overallRight = info.overallRight
1306 };
1307 WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
1308 return Success;
1309}
1310
1311int
1312ProcListFonts(ClientPtr client)
1313{
1314 REQUEST(xListFontsReq);
1315
1316 REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
1317
1318 return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
1319 stuff->maxNames);
1320}
1321
1322int
1323ProcListFontsWithInfo(ClientPtr client)
1324{
1325 REQUEST(xListFontsWithInfoReq);
1326
1327 REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
1328
1329 return StartListFontsWithInfo(client, stuff->nbytes,
1330 (unsigned char *) &stuff[1], stuff->maxNames);
1331}
1332
1333/**
1334 *
1335 * \param value must conform to DeleteType
1336 */
1337int
1338dixDestroyPixmap(pointer value, XID pid)
1339{
1340 PixmapPtr pPixmap = (PixmapPtr) value;
1341
1342 return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
1343}
1344
1345int
1346ProcCreatePixmap(ClientPtr client)
1347{
1348 PixmapPtr pMap;
1349 DrawablePtr pDraw;
1350
1351 REQUEST(xCreatePixmapReq);
1352 DepthPtr pDepth;
1353 int i, rc;
1354
1355 REQUEST_SIZE_MATCH(xCreatePixmapReq);
1356 client->errorValue = stuff->pid;
1357 LEGAL_NEW_RESOURCE(stuff->pid, client);
1358
1359 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1360 DixGetAttrAccess);
1361 if (rc != Success)
1362 return rc;
1363
1364 if (!stuff->width || !stuff->height) {
1365 client->errorValue = 0;
1366 return BadValue;
1367 }
1368 if (stuff->width > 32767 || stuff->height > 32767) {
1369 /* It is allowed to try and allocate a pixmap which is larger than
1370 * 32767 in either dimension. However, all of the framebuffer code
1371 * is buggy and does not reliably draw to such big pixmaps, basically
1372 * because the Region data structure operates with signed shorts
1373 * for the rectangles in it.
1374 *
1375 * Furthermore, several places in the X server computes the
1376 * size in bytes of the pixmap and tries to store it in an
1377 * integer. This integer can overflow and cause the allocated size
1378 * to be much smaller.
1379 *
1380 * So, such big pixmaps are rejected here with a BadAlloc
1381 */
1382 return BadAlloc;
1383 }
1384 if (stuff->depth != 1) {
1385 pDepth = pDraw->pScreen->allowedDepths;
1386 for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
1387 if (pDepth->depth == stuff->depth)
1388 goto CreatePmap;
1389 client->errorValue = stuff->depth;
1390 return BadValue;
1391 }
1392 CreatePmap:
1393 pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
1394 (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
1395 if (pMap) {
1396 pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1397 pMap->drawable.id = stuff->pid;
1398 /* security creation/labeling check */
1399 rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1400 pMap, RT_NONE, NULL, DixCreateAccess);
1401 if (rc != Success) {
1402 (*pDraw->pScreen->DestroyPixmap) (pMap);
1403 return rc;
1404 }
1405 if (AddResource(stuff->pid, RT_PIXMAP, (pointer) pMap))
1406 return Success;
1407 }
1408 return BadAlloc;
1409}
1410
1411int
1412ProcFreePixmap(ClientPtr client)
1413{
1414 PixmapPtr pMap;
1415 int rc;
1416
1417 REQUEST(xResourceReq);
1418 REQUEST_SIZE_MATCH(xResourceReq);
1419
1420 rc = dixLookupResourceByType((pointer *) &pMap, stuff->id, RT_PIXMAP,
1421 client, DixDestroyAccess);
1422 if (rc == Success) {
1423 FreeResource(stuff->id, RT_NONE);
1424 return Success;
1425 }
1426 else {
1427 client->errorValue = stuff->id;
1428 return rc;
1429 }
1430}
1431
1432int
1433ProcCreateGC(ClientPtr client)
1434{
1435 int error, rc;
1436 GC *pGC;
1437 DrawablePtr pDraw;
1438 unsigned len;
1439
1440 REQUEST(xCreateGCReq);
1441
1442 REQUEST_AT_LEAST_SIZE(xCreateGCReq);
1443 client->errorValue = stuff->gc;
1444 LEGAL_NEW_RESOURCE(stuff->gc, client);
1445 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1446 DixGetAttrAccess);
1447 if (rc != Success)
1448 return rc;
1449
1450 len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
1451 if (len != Ones(stuff->mask))
1452 return BadLength;
1453 pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
1454 stuff->gc, client);
1455 if (error != Success)
1456 return error;
1457 if (!AddResource(stuff->gc, RT_GC, (pointer) pGC))
1458 return BadAlloc;
1459 return Success;
1460}
1461
1462int
1463ProcChangeGC(ClientPtr client)
1464{
1465 GC *pGC;
1466 int result;
1467 unsigned len;
1468
1469 REQUEST(xChangeGCReq);
1470 REQUEST_AT_LEAST_SIZE(xChangeGCReq);
1471
1472 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
1473 if (result != Success)
1474 return result;
1475
1476 len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
1477 if (len != Ones(stuff->mask))
1478 return BadLength;
1479
1480 return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
1481}
1482
1483int
1484ProcCopyGC(ClientPtr client)
1485{
1486 GC *dstGC;
1487 GC *pGC;
1488 int result;
1489
1490 REQUEST(xCopyGCReq);
1491 REQUEST_SIZE_MATCH(xCopyGCReq);
1492
1493 result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
1494 if (result != Success)
1495 return result;
1496 result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
1497 if (result != Success)
1498 return result;
1499 if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
1500 return BadMatch;
1501 if (stuff->mask & ~GCAllBits) {
1502 client->errorValue = stuff->mask;
1503 return BadValue;
1504 }
1505 return CopyGC(pGC, dstGC, stuff->mask);
1506}
1507
1508int
1509ProcSetDashes(ClientPtr client)
1510{
1511 GC *pGC;
1512 int result;
1513
1514 REQUEST(xSetDashesReq);
1515
1516 REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
1517 if (stuff->nDashes == 0) {
1518 client->errorValue = 0;
1519 return BadValue;
1520 }
1521
1522 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
1523 if (result != Success)
1524 return result;
1525
1526 /* If there's an error, either there's no sensible errorValue,
1527 * or there was a dash segment of 0. */
1528 client->errorValue = 0;
1529 return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
1530 (unsigned char *) &stuff[1]);
1531}
1532
1533int
1534ProcSetClipRectangles(ClientPtr client)
1535{
1536 int nr, result;
1537 GC *pGC;
1538
1539 REQUEST(xSetClipRectanglesReq);
1540
1541 REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
1542 if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
1543 (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
1544 client->errorValue = stuff->ordering;
1545 return BadValue;
1546 }
1547 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
1548 if (result != Success)
1549 return result;
1550
1551 nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
1552 if (nr & 4)
1553 return BadLength;
1554 nr >>= 3;
1555 return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
1556 nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
1557}
1558
1559int
1560ProcFreeGC(ClientPtr client)
1561{
1562 GC *pGC;
1563 int rc;
1564
1565 REQUEST(xResourceReq);
1566 REQUEST_SIZE_MATCH(xResourceReq);
1567
1568 rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
1569 if (rc != Success)
1570 return rc;
1571
1572 FreeResource(stuff->id, RT_NONE);
1573 return Success;
1574}
1575
1576int
1577ProcClearToBackground(ClientPtr client)
1578{
1579 REQUEST(xClearAreaReq);
1580 WindowPtr pWin;
1581 int rc;
1582
1583 REQUEST_SIZE_MATCH(xClearAreaReq);
1584 rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
1585 if (rc != Success)
1586 return rc;
1587 if (pWin->drawable.class == InputOnly) {
1588 client->errorValue = stuff->window;
1589 return BadMatch;
1590 }
1591 if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
1592 client->errorValue = stuff->exposures;
1593 return BadValue;
1594 }
1595 (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
1596 stuff->width, stuff->height,
1597 (Bool) stuff->exposures);
1598 return Success;
1599}
1600
1601int
1602ProcCopyArea(ClientPtr client)
1603{
1604 DrawablePtr pDst;
1605 DrawablePtr pSrc;
1606 GC *pGC;
1607
1608 REQUEST(xCopyAreaReq);
1609 RegionPtr pRgn;
1610 int rc;
1611
1612 REQUEST_SIZE_MATCH(xCopyAreaReq);
1613
1614 VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1615 if (stuff->dstDrawable != stuff->srcDrawable) {
1616 rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1617 DixReadAccess);
1618 if (rc != Success)
1619 return rc;
1620 if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
1621 client->errorValue = stuff->dstDrawable;
1622 return BadMatch;
1623 }
1624 }
1625 else
1626 pSrc = pDst;
1627
1628 pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
1629 stuff->width, stuff->height,
1630 stuff->dstX, stuff->dstY);
1631 if (pGC->graphicsExposures) {
1632 (*pDst->pScreen->SendGraphicsExpose)
1633 (client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
1634 if (pRgn)
1635 RegionDestroy(pRgn);
1636 }
1637
1638 return Success;
1639}
1640
1641int
1642ProcCopyPlane(ClientPtr client)
1643{
1644 DrawablePtr psrcDraw, pdstDraw;
1645 GC *pGC;
1646
1647 REQUEST(xCopyPlaneReq);
1648 RegionPtr pRgn;
1649 int rc;
1650
1651 REQUEST_SIZE_MATCH(xCopyPlaneReq);
1652
1653 VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1654 if (stuff->dstDrawable != stuff->srcDrawable) {
1655 rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1656 DixReadAccess);
1657 if (rc != Success)
1658 return rc;
1659
1660 if (pdstDraw->pScreen != psrcDraw->pScreen) {
1661 client->errorValue = stuff->dstDrawable;
1662 return BadMatch;
1663 }
1664 }
1665 else
1666 psrcDraw = pdstDraw;
1667
1668 /* Check to see if stuff->bitPlane has exactly ONE good bit set */
1669 if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1670 (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
1671 client->errorValue = stuff->bitPlane;
1672 return BadValue;
1673 }
1674
1675 pRgn =
1676 (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
1677 stuff->srcY, stuff->width, stuff->height,
1678 stuff->dstX, stuff->dstY, stuff->bitPlane);
1679 if (pGC->graphicsExposures) {
1680 (*pdstDraw->pScreen->SendGraphicsExpose)
1681 (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
1682 if (pRgn)
1683 RegionDestroy(pRgn);
1684 }
1685 return Success;
1686}
1687
1688int
1689ProcPolyPoint(ClientPtr client)
1690{
1691 int npoint;
1692 GC *pGC;
1693 DrawablePtr pDraw;
1694
1695 REQUEST(xPolyPointReq);
1696
1697 REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1698 if ((stuff->coordMode != CoordModeOrigin) &&
1699 (stuff->coordMode != CoordModePrevious)) {
1700 client->errorValue = stuff->coordMode;
1701 return BadValue;
1702 }
1703 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1704 npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
1705 if (npoint)
1706 (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
1707 (xPoint *) &stuff[1]);
1708 return Success;
1709}
1710
1711int
1712ProcPolyLine(ClientPtr client)
1713{
1714 int npoint;
1715 GC *pGC;
1716 DrawablePtr pDraw;
1717
1718 REQUEST(xPolyLineReq);
1719
1720 REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1721 if ((stuff->coordMode != CoordModeOrigin) &&
1722 (stuff->coordMode != CoordModePrevious)) {
1723 client->errorValue = stuff->coordMode;
1724 return BadValue;
1725 }
1726 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1727 npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
1728 if (npoint > 1)
1729 (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
1730 (DDXPointPtr) &stuff[1]);
1731 return Success;
1732}
1733
1734int
1735ProcPolySegment(ClientPtr client)
1736{
1737 int nsegs;
1738 GC *pGC;
1739 DrawablePtr pDraw;
1740
1741 REQUEST(xPolySegmentReq);
1742
1743 REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
1744 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1745 nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
1746 if (nsegs & 4)
1747 return BadLength;
1748 nsegs >>= 3;
1749 if (nsegs)
1750 (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
1751 return Success;
1752}
1753
1754int
1755ProcPolyRectangle(ClientPtr client)
1756{
1757 int nrects;
1758 GC *pGC;
1759 DrawablePtr pDraw;
1760
1761 REQUEST(xPolyRectangleReq);
1762
1763 REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
1764 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1765 nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
1766 if (nrects & 4)
1767 return BadLength;
1768 nrects >>= 3;
1769 if (nrects)
1770 (*pGC->ops->PolyRectangle) (pDraw, pGC,
1771 nrects, (xRectangle *) &stuff[1]);
1772 return Success;
1773}
1774
1775int
1776ProcPolyArc(ClientPtr client)
1777{
1778 int narcs;
1779 GC *pGC;
1780 DrawablePtr pDraw;
1781
1782 REQUEST(xPolyArcReq);
1783
1784 REQUEST_AT_LEAST_SIZE(xPolyArcReq);
1785 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1786 narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
1787 if (narcs % sizeof(xArc))
1788 return BadLength;
1789 narcs /= sizeof(xArc);
1790 if (narcs)
1791 (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
1792 return Success;
1793}
1794
1795int
1796ProcFillPoly(ClientPtr client)
1797{
1798 int things;
1799 GC *pGC;
1800 DrawablePtr pDraw;
1801
1802 REQUEST(xFillPolyReq);
1803
1804 REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1805 if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
1806 (stuff->shape != Convex)) {
1807 client->errorValue = stuff->shape;
1808 return BadValue;
1809 }
1810 if ((stuff->coordMode != CoordModeOrigin) &&
1811 (stuff->coordMode != CoordModePrevious)) {
1812 client->errorValue = stuff->coordMode;
1813 return BadValue;
1814 }
1815
1816 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1817 things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
1818 if (things)
1819 (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
1820 stuff->coordMode, things,
1821 (DDXPointPtr) &stuff[1]);
1822 return Success;
1823}
1824
1825int
1826ProcPolyFillRectangle(ClientPtr client)
1827{
1828 int things;
1829 GC *pGC;
1830 DrawablePtr pDraw;
1831
1832 REQUEST(xPolyFillRectangleReq);
1833
1834 REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
1835 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1836 things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
1837 if (things & 4)
1838 return BadLength;
1839 things >>= 3;
1840
1841 if (things)
1842 (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
1843 (xRectangle *) &stuff[1]);
1844 return Success;
1845}
1846
1847int
1848ProcPolyFillArc(ClientPtr client)
1849{
1850 int narcs;
1851 GC *pGC;
1852 DrawablePtr pDraw;
1853
1854 REQUEST(xPolyFillArcReq);
1855
1856 REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
1857 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1858 narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
1859 if (narcs % sizeof(xArc))
1860 return BadLength;
1861 narcs /= sizeof(xArc);
1862 if (narcs)
1863 (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
1864 return Success;
1865}
1866
1867#ifdef MATCH_CLIENT_ENDIAN
1868
1869int
1870ServerOrder(void)
1871{
1872 int whichbyte = 1;
1873
1874 if (*((char *) &whichbyte))
1875 return LSBFirst;
1876 return MSBFirst;
1877}
1878
1879#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
1880
1881void
1882ReformatImage(char *base, int nbytes, int bpp, int order)
1883{
1884 switch (bpp) {
1885 case 1: /* yuck */
1886 if (BITMAP_BIT_ORDER != order)
1887 BitOrderInvert((unsigned char *) base, nbytes);
1888#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
1889 ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
1890#endif
1891 break;
1892 case 4:
1893 break; /* yuck */
1894 case 8:
1895 break;
1896 case 16:
1897 if (IMAGE_BYTE_ORDER != order)
1898 TwoByteSwap((unsigned char *) base, nbytes);
1899 break;
1900 case 32:
1901 if (IMAGE_BYTE_ORDER != order)
1902 FourByteSwap((unsigned char *) base, nbytes);
1903 break;
1904 }
1905}
1906#else
1907#define ReformatImage(b,n,bpp,o)
1908#endif
1909
1910/* 64-bit server notes: the protocol restricts padding of images to
1911 * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
1912 * to use internally. Removes need for internal alignment checking.
1913 * All of the PutImage functions could be changed individually, but
1914 * as currently written, they call other routines which require things
1915 * to be 64-bit padded on scanlines, so we changed things here.
1916 * If an image would be padded differently for 64- versus 32-, then
1917 * copy each scanline to a 64-bit padded scanline.
1918 * Also, we need to make sure that the image is aligned on a 64-bit
1919 * boundary, even if the scanlines are padded to our satisfaction.
1920 */
1921int
1922ProcPutImage(ClientPtr client)
1923{
1924 GC *pGC;
1925 DrawablePtr pDraw;
1926 long length; /* length of scanline server padded */
1927 long lengthProto; /* length of scanline protocol padded */
1928 char *tmpImage;
1929
1930 REQUEST(xPutImageReq);
1931
1932 REQUEST_AT_LEAST_SIZE(xPutImageReq);
1933 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1934 if (stuff->format == XYBitmap) {
1935 if ((stuff->depth != 1) ||
1936 (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
1937 return BadMatch;
1938 length = BitmapBytePad(stuff->width + stuff->leftPad);
1939 }
1940 else if (stuff->format == XYPixmap) {
1941 if ((pDraw->depth != stuff->depth) ||
1942 (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
1943 return BadMatch;
1944 length = BitmapBytePad(stuff->width + stuff->leftPad);
1945 length *= stuff->depth;
1946 }
1947 else if (stuff->format == ZPixmap) {
1948 if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
1949 return BadMatch;
1950 length = PixmapBytePad(stuff->width, stuff->depth);
1951 }
1952 else {
1953 client->errorValue = stuff->format;
1954 return BadValue;
1955 }
1956
1957 tmpImage = (char *) &stuff[1];
1958 lengthProto = length;
1959
1960 if ((bytes_to_int32(lengthProto * stuff->height) +
1961 bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
1962 return BadLength;
1963
1964 ReformatImage(tmpImage, lengthProto * stuff->height,
1965 stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
1966 ClientOrder(client));
1967
1968 (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
1969 stuff->width, stuff->height,
1970 stuff->leftPad, stuff->format, tmpImage);
1971
1972 return Success;
1973}
1974
1975static int
1976DoGetImage(ClientPtr client, int format, Drawable drawable,
1977 int x, int y, int width, int height,
1978 Mask planemask)
1979{
1980 DrawablePtr pDraw, pBoundingDraw;
1981 int nlines, linesPerBuf, rc;
1982 int linesDone;
1983
1984 /* coordinates relative to the bounding drawable */
1985 int relx, rely;
1986 long widthBytesLine, length;
1987 Mask plane = 0;
1988 char *pBuf;
1989 xGetImageReply xgi;
1990 RegionPtr pVisibleRegion = NULL;
1991
1992 if ((format != XYPixmap) && (format != ZPixmap)) {
1993 client->errorValue = format;
1994 return BadValue;
1995 }
1996 rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
1997 if (rc != Success)
1998 return rc;
1999
2000 memset(&xgi, 0, sizeof(xGetImageReply));
2001
2002 relx = x;
2003 rely = y;
2004
2005 if (pDraw->type == DRAWABLE_WINDOW) {
2006 WindowPtr pWin = (WindowPtr) pDraw;
2007
2008 /* "If the drawable is a window, the window must be viewable ... or a
2009 * BadMatch error results" */
2010 if (!pWin->viewable)
2011 return BadMatch;
2012
2013 /* If the drawable is a window, the rectangle must be contained within
2014 * its bounds (including the border). */
2015 if (x < -wBorderWidth(pWin) ||
2016 x + width > wBorderWidth(pWin) + (int) pDraw->width ||
2017 y < -wBorderWidth(pWin) ||
2018 y + height > wBorderWidth(pWin) + (int) pDraw->height)
2019 return BadMatch;
2020
2021 relx += pDraw->x;
2022 rely += pDraw->y;
2023
2024 if (pDraw->pScreen->GetWindowPixmap) {
2025 PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
2026
2027 pBoundingDraw = &pPix->drawable;
2028#ifdef COMPOSITE
2029 relx -= pPix->screen_x;
2030 rely -= pPix->screen_y;
2031#endif
2032 }
2033 else {
2034 pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
2035 }
2036
2037 xgi.visual = wVisual(pWin);
2038 }
2039 else {
2040 pBoundingDraw = pDraw;
2041 xgi.visual = None;
2042 }
2043
2044 /* "If the drawable is a pixmap, the given rectangle must be wholly
2045 * contained within the pixmap, or a BadMatch error results. If the
2046 * drawable is a window [...] it must be the case that if there were no
2047 * inferiors or overlapping windows, the specified rectangle of the window
2048 * would be fully visible on the screen and wholly contained within the
2049 * outside edges of the window, or a BadMatch error results."
2050 *
2051 * We relax the window case slightly to mean that the rectangle must exist
2052 * within the bounds of the window's backing pixmap. In particular, this
2053 * means that a GetImage request may succeed or fail with BadMatch depending
2054 * on whether any of its ancestor windows are redirected. */
2055 if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
2056 rely < 0 || rely + height > (int) pBoundingDraw->height)
2057 return BadMatch;
2058
2059 xgi.type = X_Reply;
2060 xgi.sequenceNumber = client->sequence;
2061 xgi.depth = pDraw->depth;
2062 if (format == ZPixmap) {
2063 widthBytesLine = PixmapBytePad(width, pDraw->depth);
2064 length = widthBytesLine * height;
2065
2066 }
2067 else {
2068 widthBytesLine = BitmapBytePad(width);
2069 plane = ((Mask) 1) << (pDraw->depth - 1);
2070 /* only planes asked for */
2071 length = widthBytesLine * height *
2072 Ones(planemask & (plane | (plane - 1)));
2073
2074 }
2075
2076 xgi.length = length;
2077
2078 xgi.length = bytes_to_int32(xgi.length);
2079 if (widthBytesLine == 0 || height == 0)
2080 linesPerBuf = 0;
2081 else if (widthBytesLine >= IMAGE_BUFSIZE)
2082 linesPerBuf = 1;
2083 else {
2084 linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
2085 if (linesPerBuf > height)
2086 linesPerBuf = height;
2087 }
2088 length = linesPerBuf * widthBytesLine;
2089 if (linesPerBuf < height) {
2090 /* we have to make sure intermediate buffers don't need padding */
2091 while ((linesPerBuf > 1) &&
2092 (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
2093 linesPerBuf--;
2094 length -= widthBytesLine;
2095 }
2096 while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
2097 linesPerBuf++;
2098 length += widthBytesLine;
2099 }
2100 }
2101 if (!(pBuf = calloc(1, length)))
2102 return BadAlloc;
2103 WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
2104
2105 if (pDraw->type == DRAWABLE_WINDOW) {
2106 pVisibleRegion = NotClippedByChildren((WindowPtr) pDraw);
2107 if (pVisibleRegion) {
2108 RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y);
2109 }
2110 }
2111
2112 if (linesPerBuf == 0) {
2113 /* nothing to do */
2114 }
2115 else if (format == ZPixmap) {
2116 linesDone = 0;
2117 while (height - linesDone > 0) {
2118 nlines = min(linesPerBuf, height - linesDone);
2119 (*pDraw->pScreen->GetImage) (pDraw,
2120 x,
2121 y + linesDone,
2122 width,
2123 nlines,
2124 format, planemask, (pointer) pBuf);
2125 if (pVisibleRegion)
2126 XaceCensorImage(client, pVisibleRegion, widthBytesLine,
2127 pDraw, x, y + linesDone, width,
2128 nlines, format, pBuf);
2129
2130 /* Note that this is NOT a call to WriteSwappedDataToClient,
2131 as we do NOT byte swap */
2132 ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2133 BitsPerPixel(pDraw->depth), ClientOrder(client));
2134
2135 WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
2136 linesDone += nlines;
2137 }
2138 }
2139 else { /* XYPixmap */
2140
2141 for (; plane; plane >>= 1) {
2142 if (planemask & plane) {
2143 linesDone = 0;
2144 while (height - linesDone > 0) {
2145 nlines = min(linesPerBuf, height - linesDone);
2146 (*pDraw->pScreen->GetImage) (pDraw,
2147 x,
2148 y + linesDone,
2149 width,
2150 nlines,
2151 format, plane, (pointer) pBuf);
2152 if (pVisibleRegion)
2153 XaceCensorImage(client, pVisibleRegion,
2154 widthBytesLine,
2155 pDraw, x, y + linesDone, width,
2156 nlines, format, pBuf);
2157
2158 /* Note: NOT a call to WriteSwappedDataToClient,
2159 as we do NOT byte swap */
2160 ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2161 1, ClientOrder(client));
2162
2163 WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
2164 linesDone += nlines;
2165 }
2166 }
2167 }
2168 }
2169 if (pVisibleRegion)
2170 RegionDestroy(pVisibleRegion);
2171 free(pBuf);
2172 return Success;
2173}
2174
2175int
2176ProcGetImage(ClientPtr client)
2177{
2178 REQUEST(xGetImageReq);
2179
2180 REQUEST_SIZE_MATCH(xGetImageReq);
2181
2182 return DoGetImage(client, stuff->format, stuff->drawable,
2183 stuff->x, stuff->y,
2184 (int) stuff->width, (int) stuff->height,
2185 stuff->planeMask);
2186}
2187
2188int
2189ProcPolyText(ClientPtr client)
2190{
2191 int err;
2192
2193 REQUEST(xPolyTextReq);
2194 DrawablePtr pDraw;
2195 GC *pGC;
2196
2197 REQUEST_AT_LEAST_SIZE(xPolyTextReq);
2198 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2199
2200 err = PolyText(client,
2201 pDraw,
2202 pGC,
2203 (unsigned char *) &stuff[1],
2204 ((unsigned char *) stuff) + (client->req_len << 2),
2205 stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2206
2207 if (err == Success) {
2208 return Success;
2209 }
2210 else
2211 return err;
2212}
2213
2214int
2215ProcImageText8(ClientPtr client)
2216{
2217 int err;
2218 DrawablePtr pDraw;
2219 GC *pGC;
2220
2221 REQUEST(xImageTextReq);
2222
2223 REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
2224 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2225
2226 err = ImageText(client,
2227 pDraw,
2228 pGC,
2229 stuff->nChars,
2230 (unsigned char *) &stuff[1],
2231 stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2232
2233 if (err == Success) {
2234 return Success;
2235 }
2236 else
2237 return err;
2238}
2239
2240int
2241ProcImageText16(ClientPtr client)
2242{
2243 int err;
2244 DrawablePtr pDraw;
2245 GC *pGC;
2246
2247 REQUEST(xImageTextReq);
2248
2249 REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
2250 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2251
2252 err = ImageText(client,
2253 pDraw,
2254 pGC,
2255 stuff->nChars,
2256 (unsigned char *) &stuff[1],
2257 stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2258
2259 if (err == Success) {
2260 return Success;
2261 }
2262 else
2263 return err;
2264}
2265
2266int
2267ProcCreateColormap(ClientPtr client)
2268{
2269 VisualPtr pVisual;
2270 ColormapPtr pmap;
2271 Colormap mid;
2272 WindowPtr pWin;
2273 ScreenPtr pScreen;
2274
2275 REQUEST(xCreateColormapReq);
2276 int i, result;
2277
2278 REQUEST_SIZE_MATCH(xCreateColormapReq);
2279
2280 if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
2281 client->errorValue = stuff->alloc;
2282 return BadValue;
2283 }
2284 mid = stuff->mid;
2285 LEGAL_NEW_RESOURCE(mid, client);
2286 result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
2287 if (result != Success)
2288 return result;
2289
2290 pScreen = pWin->drawable.pScreen;
2291 for (i = 0, pVisual = pScreen->visuals;
2292 i < pScreen->numVisuals; i++, pVisual++) {
2293 if (pVisual->vid != stuff->visual)
2294 continue;
2295 return CreateColormap(mid, pScreen, pVisual, &pmap,
2296 (int) stuff->alloc, client->index);
2297 }
2298 client->errorValue = stuff->visual;
2299 return BadMatch;
2300}
2301
2302int
2303ProcFreeColormap(ClientPtr client)
2304{
2305 ColormapPtr pmap;
2306 int rc;
2307
2308 REQUEST(xResourceReq);
2309
2310 REQUEST_SIZE_MATCH(xResourceReq);
2311 rc = dixLookupResourceByType((pointer *) &pmap, stuff->id, RT_COLORMAP,
2312 client, DixDestroyAccess);
2313 if (rc == Success) {
2314 /* Freeing a default colormap is a no-op */
2315 if (!(pmap->flags & IsDefault))
2316 FreeResource(stuff->id, RT_NONE);
2317 return Success;
2318 }
2319 else {
2320 client->errorValue = stuff->id;
2321 return rc;
2322 }
2323}
2324
2325int
2326ProcCopyColormapAndFree(ClientPtr client)
2327{
2328 Colormap mid;
2329 ColormapPtr pSrcMap;
2330
2331 REQUEST(xCopyColormapAndFreeReq);
2332 int rc;
2333
2334 REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
2335 mid = stuff->mid;
2336 LEGAL_NEW_RESOURCE(mid, client);
2337 rc = dixLookupResourceByType((pointer *) &pSrcMap, stuff->srcCmap,
2338 RT_COLORMAP, client,
2339 DixReadAccess | DixRemoveAccess);
2340 if (rc == Success)
2341 return CopyColormapAndFree(mid, pSrcMap, client->index);
2342 client->errorValue = stuff->srcCmap;
2343 return rc;
2344}
2345
2346int
2347ProcInstallColormap(ClientPtr client)
2348{
2349 ColormapPtr pcmp;
2350 int rc;
2351
2352 REQUEST(xResourceReq);
2353 REQUEST_SIZE_MATCH(xResourceReq);
2354
2355 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->id, RT_COLORMAP,
2356 client, DixInstallAccess);
2357 if (rc != Success)
2358 goto out;
2359
2360 rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
2361 if (rc != Success) {
2362 if (rc == BadValue)
2363 rc = BadColor;
2364 goto out;
2365 }
2366
2367 (*(pcmp->pScreen->InstallColormap)) (pcmp);
2368 return Success;
2369
2370 out:
2371 client->errorValue = stuff->id;
2372 return rc;
2373}
2374
2375int
2376ProcUninstallColormap(ClientPtr client)
2377{
2378 ColormapPtr pcmp;
2379 int rc;
2380
2381 REQUEST(xResourceReq);
2382 REQUEST_SIZE_MATCH(xResourceReq);
2383
2384 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->id, RT_COLORMAP,
2385 client, DixUninstallAccess);
2386 if (rc != Success)
2387 goto out;
2388
2389 rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
2390 if (rc != Success) {
2391 if (rc == BadValue)
2392 rc = BadColor;
2393 goto out;
2394 }
2395
2396 if (pcmp->mid != pcmp->pScreen->defColormap)
2397 (*(pcmp->pScreen->UninstallColormap)) (pcmp);
2398 return Success;
2399
2400 out:
2401 client->errorValue = stuff->id;
2402 return rc;
2403}
2404
2405int
2406ProcListInstalledColormaps(ClientPtr client)
2407{
2408 xListInstalledColormapsReply *preply;
2409 int nummaps, rc;
2410 WindowPtr pWin;
2411
2412 REQUEST(xResourceReq);
2413 REQUEST_SIZE_MATCH(xResourceReq);
2414
2415 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
2416 if (rc != Success)
2417 return rc;
2418
2419 rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
2420 DixGetAttrAccess);
2421 if (rc != Success)
2422 return rc;
2423
2424 preply = malloc(sizeof(xListInstalledColormapsReply) +
2425 pWin->drawable.pScreen->maxInstalledCmaps *
2426 sizeof(Colormap));
2427 if (!preply)
2428 return BadAlloc;
2429
2430 preply->type = X_Reply;
2431 preply->sequenceNumber = client->sequence;
2432 nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
2433 (pWin->drawable.pScreen, (Colormap *) &preply[1]);
2434 preply->nColormaps = nummaps;
2435 preply->length = nummaps;
2436 WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
2437 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2438 WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
2439 free(preply);
2440 return Success;
2441}
2442
2443int
2444ProcAllocColor(ClientPtr client)
2445{
2446 ColormapPtr pmap;
2447 int rc;
2448
2449 REQUEST(xAllocColorReq);
2450
2451 REQUEST_SIZE_MATCH(xAllocColorReq);
2452 rc = dixLookupResourceByType((pointer *) &pmap, stuff->cmap, RT_COLORMAP,
2453 client, DixAddAccess);
2454 if (rc == Success) {
2455 xAllocColorReply acr = {
2456 .type = X_Reply,
2457 .sequenceNumber = client->sequence,
2458 .length = 0,
2459 .red = stuff->red,
2460 .green = stuff->green,
2461 .blue = stuff->blue,
2462 .pixel = 0
2463 };
2464 if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
2465 &acr.pixel, client->index)))
2466 return rc;
2467#ifdef PANORAMIX
2468 if (noPanoramiXExtension || !pmap->pScreen->myNum)
2469#endif
2470 WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
2471 return Success;
2472
2473 }
2474 else {
2475 client->errorValue = stuff->cmap;
2476 return rc;
2477 }
2478}
2479
2480int
2481ProcAllocNamedColor(ClientPtr client)
2482{
2483 ColormapPtr pcmp;
2484 int rc;
2485
2486 REQUEST(xAllocNamedColorReq);
2487
2488 REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2489 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2490 client, DixAddAccess);
2491 if (rc == Success) {
2492 xAllocNamedColorReply ancr = {
2493 .type = X_Reply,
2494 .sequenceNumber = client->sequence,
2495 .length = 0
2496 };
2497 if (OsLookupColor
2498 (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2499 &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
2500 ancr.screenRed = ancr.exactRed;
2501 ancr.screenGreen = ancr.exactGreen;
2502 ancr.screenBlue = ancr.exactBlue;
2503 ancr.pixel = 0;
2504 if ((rc = AllocColor(pcmp,
2505 &ancr.screenRed, &ancr.screenGreen,
2506 &ancr.screenBlue, &ancr.pixel, client->index)))
2507 return rc;
2508#ifdef PANORAMIX
2509 if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2510#endif
2511 WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
2512 &ancr);
2513 return Success;
2514 }
2515 else
2516 return BadName;
2517
2518 }
2519 else {
2520 client->errorValue = stuff->cmap;
2521 return rc;
2522 }
2523}
2524
2525int
2526ProcAllocColorCells(ClientPtr client)
2527{
2528 ColormapPtr pcmp;
2529 int rc;
2530
2531 REQUEST(xAllocColorCellsReq);
2532
2533 REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2534 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2535 client, DixAddAccess);
2536 if (rc == Success) {
2537 int npixels, nmasks;
2538 long length;
2539 Pixel *ppixels, *pmasks;
2540
2541 npixels = stuff->colors;
2542 if (!npixels) {
2543 client->errorValue = npixels;
2544 return BadValue;
2545 }
2546 if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2547 client->errorValue = stuff->contiguous;
2548 return BadValue;
2549 }
2550 nmasks = stuff->planes;
2551 length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
2552 ppixels = malloc(length);
2553 if (!ppixels)
2554 return BadAlloc;
2555 pmasks = ppixels + npixels;
2556
2557 if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
2558 (Bool) stuff->contiguous, ppixels, pmasks))) {
2559 free(ppixels);
2560 return rc;
2561 }
2562#ifdef PANORAMIX
2563 if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2564#endif
2565 {
2566 xAllocColorCellsReply accr = {
2567 .type = X_Reply,
2568 .sequenceNumber = client->sequence,
2569 .length = bytes_to_int32(length),
2570 .nPixels = npixels,
2571 .nMasks = nmasks
2572 };
2573 WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
2574 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2575 WriteSwappedDataToClient(client, length, ppixels);
2576 }
2577 free(ppixels);
2578 return Success;
2579 }
2580 else {
2581 client->errorValue = stuff->cmap;
2582 return rc;
2583 }
2584}
2585
2586int
2587ProcAllocColorPlanes(ClientPtr client)
2588{
2589 ColormapPtr pcmp;
2590 int rc;
2591
2592 REQUEST(xAllocColorPlanesReq);
2593
2594 REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2595 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2596 client, DixAddAccess);
2597 if (rc == Success) {
2598 xAllocColorPlanesReply acpr;
2599 int npixels;
2600 long length;
2601 Pixel *ppixels;
2602
2603 npixels = stuff->colors;
2604 if (!npixels) {
2605 client->errorValue = npixels;
2606 return BadValue;
2607 }
2608 if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2609 client->errorValue = stuff->contiguous;
2610 return BadValue;
2611 }
2612 acpr = (xAllocColorPlanesReply) {
2613 .type = X_Reply,
2614 .sequenceNumber = client->sequence,
2615 .nPixels = npixels
2616 };
2617 length = (long) npixels *sizeof(Pixel);
2618
2619 ppixels = malloc(length);
2620 if (!ppixels)
2621 return BadAlloc;
2622 if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
2623 (int) stuff->red, (int) stuff->green,
2624 (int) stuff->blue, (Bool) stuff->contiguous,
2625 ppixels, &acpr.redMask, &acpr.greenMask,
2626 &acpr.blueMask))) {
2627 free(ppixels);
2628 return rc;
2629 }
2630 acpr.length = bytes_to_int32(length);
2631#ifdef PANORAMIX
2632 if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2633#endif
2634 {
2635 WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
2636 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2637 WriteSwappedDataToClient(client, length, ppixels);
2638 }
2639 free(ppixels);
2640 return Success;
2641 }
2642 else {
2643 client->errorValue = stuff->cmap;
2644 return rc;
2645 }
2646}
2647
2648int
2649ProcFreeColors(ClientPtr client)
2650{
2651 ColormapPtr pcmp;
2652 int rc;
2653
2654 REQUEST(xFreeColorsReq);
2655
2656 REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2657 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2658 client, DixRemoveAccess);
2659 if (rc == Success) {
2660 int count;
2661
2662 if (pcmp->flags & AllAllocated)
2663 return BadAccess;
2664 count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
2665 return FreeColors(pcmp, client->index, count,
2666 (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
2667 }
2668 else {
2669 client->errorValue = stuff->cmap;
2670 return rc;
2671 }
2672}
2673
2674int
2675ProcStoreColors(ClientPtr client)
2676{
2677 ColormapPtr pcmp;
2678 int rc;
2679
2680 REQUEST(xStoreColorsReq);
2681
2682 REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2683 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2684 client, DixWriteAccess);
2685 if (rc == Success) {
2686 int count;
2687
2688 count = (client->req_len << 2) - sizeof(xStoreColorsReq);
2689 if (count % sizeof(xColorItem))
2690 return BadLength;
2691 count /= sizeof(xColorItem);
2692 return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
2693 }
2694 else {
2695 client->errorValue = stuff->cmap;
2696 return rc;
2697 }
2698}
2699
2700int
2701ProcStoreNamedColor(ClientPtr client)
2702{
2703 ColormapPtr pcmp;
2704 int rc;
2705
2706 REQUEST(xStoreNamedColorReq);
2707
2708 REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2709 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2710 client, DixWriteAccess);
2711 if (rc == Success) {
2712 xColorItem def;
2713
2714 if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
2715 stuff->nbytes, &def.red, &def.green, &def.blue)) {
2716 def.flags = stuff->flags;
2717 def.pixel = stuff->pixel;
2718 return StoreColors(pcmp, 1, &def, client);
2719 }
2720 return BadName;
2721 }
2722 else {
2723 client->errorValue = stuff->cmap;
2724 return rc;
2725 }
2726}
2727
2728int
2729ProcQueryColors(ClientPtr client)
2730{
2731 ColormapPtr pcmp;
2732 int rc;
2733
2734 REQUEST(xQueryColorsReq);
2735
2736 REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
2737 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2738 client, DixReadAccess);
2739 if (rc == Success) {
2740 int count;
2741 xrgb *prgbs;
2742 xQueryColorsReply qcr;
2743
2744 count =
2745 bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
2746 prgbs = calloc(1, count * sizeof(xrgb));
2747 if (!prgbs && count)
2748 return BadAlloc;
2749 if ((rc =
2750 QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
2751 free(prgbs);
2752 return rc;
2753 }
2754 qcr = (xQueryColorsReply) {
2755 .type = X_Reply,
2756 .sequenceNumber = client->sequence,
2757 .length = bytes_to_int32(count * sizeof(xrgb)),
2758 .nColors = count
2759 };
2760 WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
2761 if (count) {
2762 client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
2763 WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
2764 }
2765 free(prgbs);
2766 return Success;
2767
2768 }
2769 else {
2770 client->errorValue = stuff->cmap;
2771 return rc;
2772 }
2773}
2774
2775int
2776ProcLookupColor(ClientPtr client)
2777{
2778 ColormapPtr pcmp;
2779 int rc;
2780
2781 REQUEST(xLookupColorReq);
2782
2783 REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
2784 rc = dixLookupResourceByType((pointer *) &pcmp, stuff->cmap, RT_COLORMAP,
2785 client, DixReadAccess);
2786 if (rc == Success) {
2787 CARD16 exactRed, exactGreen, exactBlue;
2788
2789 if (OsLookupColor
2790 (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2791 &exactRed, &exactGreen, &exactBlue)) {
2792 xLookupColorReply lcr = {
2793 .type = X_Reply,
2794 .sequenceNumber = client->sequence,
2795 .length = 0,
2796 .exactRed = exactRed,
2797 .exactGreen = exactGreen,
2798 .exactBlue = exactBlue,
2799 .screenRed = exactRed,
2800 .screenGreen = exactGreen,
2801 .screenBlue = exactBlue
2802 };
2803 (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
2804 &lcr.screenGreen,
2805 &lcr.screenBlue, pcmp->pVisual);
2806 WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
2807 return Success;
2808 }
2809 return BadName;
2810 }
2811 else {
2812 client->errorValue = stuff->cmap;
2813 return rc;
2814 }
2815}
2816
2817int
2818ProcCreateCursor(ClientPtr client)
2819{
2820 CursorPtr pCursor;
2821 PixmapPtr src;
2822 PixmapPtr msk;
2823 unsigned char *srcbits;
2824 unsigned char *mskbits;
2825 unsigned short width, height;
2826 long n;
2827 CursorMetricRec cm;
2828 int rc;
2829
2830 REQUEST(xCreateCursorReq);
2831
2832 REQUEST_SIZE_MATCH(xCreateCursorReq);
2833 LEGAL_NEW_RESOURCE(stuff->cid, client);
2834
2835 rc = dixLookupResourceByType((pointer *) &src, stuff->source, RT_PIXMAP,
2836 client, DixReadAccess);
2837 if (rc != Success) {
2838 client->errorValue = stuff->source;
2839 return rc;
2840 }
2841
2842 if (src->drawable.depth != 1)
2843 return (BadMatch);
2844
2845 /* Find and validate cursor mask pixmap, if one is provided */
2846 if (stuff->mask != None) {
2847 rc = dixLookupResourceByType((pointer *) &msk, stuff->mask, RT_PIXMAP,
2848 client, DixReadAccess);
2849 if (rc != Success) {
2850 client->errorValue = stuff->mask;
2851 return rc;
2852 }
2853
2854 if (src->drawable.width != msk->drawable.width
2855 || src->drawable.height != msk->drawable.height
2856 || src->drawable.depth != 1 || msk->drawable.depth != 1)
2857 return BadMatch;
2858 }
2859 else
2860 msk = NULL;
2861
2862 width = src->drawable.width;
2863 height = src->drawable.height;
2864
2865 if (stuff->x > width || stuff->y > height)
2866 return BadMatch;
2867
2868 n = BitmapBytePad(width) * height;
2869 srcbits = calloc(1, n);
2870 if (!srcbits)
2871 return BadAlloc;
2872 mskbits = malloc(n);
2873 if (!mskbits) {
2874 free(srcbits);
2875 return BadAlloc;
2876 }
2877
2878 (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
2879 XYPixmap, 1, (pointer) srcbits);
2880 if (msk == (PixmapPtr) NULL) {
2881 unsigned char *bits = mskbits;
2882
2883 while (--n >= 0)
2884 *bits++ = ~0;
2885 }
2886 else {
2887 /* zeroing the (pad) bits helps some ddx cursor handling */
2888 memset((char *) mskbits, 0, n);
2889 (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
2890 height, XYPixmap, 1,
2891 (pointer) mskbits);
2892 }
2893 cm.width = width;
2894 cm.height = height;
2895 cm.xhot = stuff->x;
2896 cm.yhot = stuff->y;
2897 rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
2898 stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2899 stuff->backRed, stuff->backGreen, stuff->backBlue,
2900 &pCursor, client, stuff->cid);
2901
2902 if (rc != Success)
2903 goto bail;
2904 if (!AddResource(stuff->cid, RT_CURSOR, (pointer) pCursor)) {
2905 rc = BadAlloc;
2906 goto bail;
2907 }
2908
2909 return Success;
2910 bail:
2911 free(srcbits);
2912 free(mskbits);
2913 return rc;
2914}
2915
2916int
2917ProcCreateGlyphCursor(ClientPtr client)
2918{
2919 CursorPtr pCursor;
2920 int res;
2921
2922 REQUEST(xCreateGlyphCursorReq);
2923
2924 REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
2925 LEGAL_NEW_RESOURCE(stuff->cid, client);
2926
2927 res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
2928 stuff->mask, stuff->maskChar,
2929 stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2930 stuff->backRed, stuff->backGreen, stuff->backBlue,
2931 &pCursor, client, stuff->cid);
2932 if (res != Success)
2933 return res;
2934 if (AddResource(stuff->cid, RT_CURSOR, (pointer) pCursor))
2935 return Success;
2936 return BadAlloc;
2937}
2938
2939int
2940ProcFreeCursor(ClientPtr client)
2941{
2942 CursorPtr pCursor;
2943 int rc;
2944
2945 REQUEST(xResourceReq);
2946
2947 REQUEST_SIZE_MATCH(xResourceReq);
2948 rc = dixLookupResourceByType((pointer *) &pCursor, stuff->id, RT_CURSOR,
2949 client, DixDestroyAccess);
2950 if (rc == Success) {
2951 FreeResource(stuff->id, RT_NONE);
2952 return Success;
2953 }
2954 else {
2955 client->errorValue = stuff->id;
2956 return rc;
2957 }
2958}
2959
2960int
2961ProcQueryBestSize(ClientPtr client)
2962{
2963 xQueryBestSizeReply reply;
2964 DrawablePtr pDraw;
2965 ScreenPtr pScreen;
2966 int rc;
2967
2968 REQUEST(xQueryBestSizeReq);
2969 REQUEST_SIZE_MATCH(xQueryBestSizeReq);
2970
2971 if ((stuff->class != CursorShape) &&
2972 (stuff->class != TileShape) && (stuff->class != StippleShape)) {
2973 client->errorValue = stuff->class;
2974 return BadValue;
2975 }
2976
2977 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
2978 DixGetAttrAccess);
2979 if (rc != Success)
2980 return rc;
2981 if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
2982 return BadMatch;
2983 pScreen = pDraw->pScreen;
2984 rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
2985 if (rc != Success)
2986 return rc;
2987 (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
2988 &stuff->height, pScreen);
2989 reply = (xQueryBestSizeReply) {
2990 .type = X_Reply,
2991 .sequenceNumber = client->sequence,
2992 .length = 0,
2993 .width = stuff->width,
2994 .height = stuff->height
2995 };
2996 WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
2997 return Success;
2998}
2999
3000int
3001ProcSetScreenSaver(ClientPtr client)
3002{
3003 int rc, i, blankingOption, exposureOption;
3004
3005 REQUEST(xSetScreenSaverReq);
3006 REQUEST_SIZE_MATCH(xSetScreenSaverReq);
3007
3008 for (i = 0; i < screenInfo.numScreens; i++) {
3009 rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3010 DixSetAttrAccess);
3011 if (rc != Success)
3012 return rc;
3013 }
3014
3015 blankingOption = stuff->preferBlank;
3016 if ((blankingOption != DontPreferBlanking) &&
3017 (blankingOption != PreferBlanking) &&
3018 (blankingOption != DefaultBlanking)) {
3019 client->errorValue = blankingOption;
3020 return BadValue;
3021 }
3022 exposureOption = stuff->allowExpose;
3023 if ((exposureOption != DontAllowExposures) &&
3024 (exposureOption != AllowExposures) &&
3025 (exposureOption != DefaultExposures)) {
3026 client->errorValue = exposureOption;
3027 return BadValue;
3028 }
3029 if (stuff->timeout < -1) {
3030 client->errorValue = stuff->timeout;
3031 return BadValue;
3032 }
3033 if (stuff->interval < -1) {
3034 client->errorValue = stuff->interval;
3035 return BadValue;
3036 }
3037
3038 if (blankingOption == DefaultBlanking)
3039 ScreenSaverBlanking = defaultScreenSaverBlanking;
3040 else
3041 ScreenSaverBlanking = blankingOption;
3042 if (exposureOption == DefaultExposures)
3043 ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
3044 else
3045 ScreenSaverAllowExposures = exposureOption;
3046
3047 if (stuff->timeout >= 0)
3048 ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
3049 else
3050 ScreenSaverTime = defaultScreenSaverTime;
3051 if (stuff->interval >= 0)
3052 ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
3053 else
3054 ScreenSaverInterval = defaultScreenSaverInterval;
3055
3056 SetScreenSaverTimer();
3057 return Success;
3058}
3059
3060int
3061ProcGetScreenSaver(ClientPtr client)
3062{
3063 xGetScreenSaverReply rep;
3064 int rc, i;
3065
3066 REQUEST_SIZE_MATCH(xReq);
3067
3068 for (i = 0; i < screenInfo.numScreens; i++) {
3069 rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3070 DixGetAttrAccess);
3071 if (rc != Success)
3072 return rc;
3073 }
3074
3075 rep = (xGetScreenSaverReply) {
3076 .type = X_Reply,
3077 .sequenceNumber = client->sequence,
3078 .length = 0,
3079 .timeout = ScreenSaverTime / MILLI_PER_SECOND,
3080 .interval = ScreenSaverInterval / MILLI_PER_SECOND,
3081 .preferBlanking = ScreenSaverBlanking,
3082 .allowExposures = ScreenSaverAllowExposures
3083 };
3084 WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
3085 return Success;
3086}
3087
3088int
3089ProcChangeHosts(ClientPtr client)
3090{
3091 REQUEST(xChangeHostsReq);
3092
3093 REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
3094
3095 if (stuff->mode == HostInsert)
3096 return AddHost(client, (int) stuff->hostFamily,
3097 stuff->hostLength, (pointer) &stuff[1]);
3098 if (stuff->mode == HostDelete)
3099 return RemoveHost(client, (int) stuff->hostFamily,
3100 stuff->hostLength, (pointer) &stuff[1]);
3101 client->errorValue = stuff->mode;
3102 return BadValue;
3103}
3104
3105int
3106ProcListHosts(ClientPtr client)
3107{
3108 xListHostsReply reply;
3109 int len, nHosts, result;
3110 BOOL enabled;
3111 pointer pdata;
3112
3113 /* REQUEST(xListHostsReq); */
3114
3115 REQUEST_SIZE_MATCH(xListHostsReq);
3116
3117 /* untrusted clients can't list hosts */
3118 result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
3119 if (result != Success)
3120 return result;
3121
3122 result = GetHosts(&pdata, &nHosts, &len, &enabled);
3123 if (result != Success)
3124 return result;
3125
3126 reply = (xListHostsReply) {
3127 .type = X_Reply,
3128 .enabled = enabled,
3129 .sequenceNumber = client->sequence,
3130 .length = bytes_to_int32(len),
3131 .nHosts = nHosts
3132 };
3133 WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
3134 if (nHosts) {
3135 client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
3136 WriteSwappedDataToClient(client, len, pdata);
3137 }
3138 free(pdata);
3139 return Success;
3140}
3141
3142int
3143ProcChangeAccessControl(ClientPtr client)
3144{
3145 REQUEST(xSetAccessControlReq);
3146
3147 REQUEST_SIZE_MATCH(xSetAccessControlReq);
3148 if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
3149 client->errorValue = stuff->mode;
3150 return BadValue;
3151 }
3152 return ChangeAccessControl(client, stuff->mode == EnableAccess);
3153}
3154
3155/*********************
3156 * CloseDownRetainedResources
3157 *
3158 * Find all clients that are gone and have terminated in RetainTemporary
3159 * and destroy their resources.
3160 *********************/
3161
3162static void
3163CloseDownRetainedResources(void)
3164{
3165 int i;
3166 ClientPtr client;
3167
3168 for (i = 1; i < currentMaxClients; i++) {
3169 client = clients[i];
3170 if (client && (client->closeDownMode == RetainTemporary)
3171 && (client->clientGone))
3172 CloseDownClient(client);
3173 }
3174}
3175
3176int
3177ProcKillClient(ClientPtr client)
3178{
3179 REQUEST(xResourceReq);
3180 ClientPtr killclient;
3181 int rc;
3182
3183 REQUEST_SIZE_MATCH(xResourceReq);
3184 if (stuff->id == AllTemporary) {
3185 CloseDownRetainedResources();
3186 return Success;
3187 }
3188
3189 rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
3190 if (rc == Success) {
3191 CloseDownClient(killclient);
3192 /* if an LBX proxy gets killed, isItTimeToYield will be set */
3193 if (isItTimeToYield || (client == killclient)) {
3194 /* force yield and return Success, so that Dispatch()
3195 * doesn't try to touch client
3196 */
3197 isItTimeToYield = TRUE;
3198 return Success;
3199 }
3200 return Success;
3201 }
3202 else
3203 return rc;
3204}
3205
3206int
3207ProcSetFontPath(ClientPtr client)
3208{
3209 unsigned char *ptr;
3210 unsigned long nbytes, total;
3211 long nfonts;
3212 int n;
3213
3214 REQUEST(xSetFontPathReq);
3215
3216 REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
3217
3218 nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
3219 total = nbytes;
3220 ptr = (unsigned char *) &stuff[1];
3221 nfonts = stuff->nFonts;
3222 while (--nfonts >= 0) {
3223 if ((total == 0) || (total < (n = (*ptr + 1))))
3224 return BadLength;
3225 total -= n;
3226 ptr += n;
3227 }
3228 if (total >= 4)
3229 return BadLength;
3230 return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
3231}
3232
3233int
3234ProcGetFontPath(ClientPtr client)
3235{
3236 xGetFontPathReply reply;
3237 int rc, stringLens, numpaths;
3238 unsigned char *bufferStart;
3239
3240 /* REQUEST (xReq); */
3241
3242 REQUEST_SIZE_MATCH(xReq);
3243 rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
3244 if (rc != Success)
3245 return rc;
3246
3247 reply = (xGetFontPathReply) {
3248 .type = X_Reply,
3249 .sequenceNumber = client->sequence,
3250 .length = bytes_to_int32(stringLens + numpaths),
3251 .nPaths = numpaths
3252 };
3253
3254 WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
3255 if (stringLens || numpaths)
3256 WriteToClient(client, stringLens + numpaths, bufferStart);
3257 return Success;
3258}
3259
3260int
3261ProcChangeCloseDownMode(ClientPtr client)
3262{
3263 int rc;
3264
3265 REQUEST(xSetCloseDownModeReq);
3266 REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
3267
3268 rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
3269 if (rc != Success)
3270 return rc;
3271
3272 if ((stuff->mode == AllTemporary) ||
3273 (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
3274 client->closeDownMode = stuff->mode;
3275 return Success;
3276 }
3277 else {
3278 client->errorValue = stuff->mode;
3279 return BadValue;
3280 }
3281}
3282
3283int
3284ProcForceScreenSaver(ClientPtr client)
3285{
3286 int rc;
3287
3288 REQUEST(xForceScreenSaverReq);
3289
3290 REQUEST_SIZE_MATCH(xForceScreenSaverReq);
3291
3292 if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
3293 client->errorValue = stuff->mode;
3294 return BadValue;
3295 }
3296 rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
3297 if (rc != Success)
3298 return rc;
3299 return Success;
3300}
3301
3302int
3303ProcNoOperation(ClientPtr client)
3304{
3305 REQUEST_AT_LEAST_SIZE(xReq);
3306
3307 /* noop -- don't do anything */
3308 return Success;
3309}
3310
3311/**********************
3312 * CloseDownClient
3313 *
3314 * Client can either mark his resources destroy or retain. If retained and
3315 * then killed again, the client is really destroyed.
3316 *********************/
3317
3318char dispatchExceptionAtReset = DE_RESET;
3319
3320void
3321CloseDownClient(ClientPtr client)
3322{
3323 Bool really_close_down = client->clientGone ||
3324 client->closeDownMode == DestroyAll;
3325
3326 if (!client->clientGone) {
3327 /* ungrab server if grabbing client dies */
3328 if (grabState != GrabNone && grabClient == client) {
3329 UngrabServer(client);
3330 }
3331 BITCLEAR(grabWaiters, client->index);
3332 DeleteClientFromAnySelections(client);
3333 ReleaseActiveGrabs(client);
3334 DeleteClientFontStuff(client);
3335 if (!really_close_down) {
3336 /* This frees resources that should never be retained
3337 * no matter what the close down mode is. Actually we
3338 * could do this unconditionally, but it's probably
3339 * better not to traverse all the client's resources
3340 * twice (once here, once a few lines down in
3341 * FreeClientResources) in the common case of
3342 * really_close_down == TRUE.
3343 */
3344 FreeClientNeverRetainResources(client);
3345 client->clientState = ClientStateRetained;
3346 if (ClientStateCallback) {
3347 NewClientInfoRec clientinfo;
3348
3349 clientinfo.client = client;
3350 clientinfo.prefix = (xConnSetupPrefix *) NULL;
3351 clientinfo.setup = (xConnSetup *) NULL;
3352 CallCallbacks((&ClientStateCallback), (pointer) &clientinfo);
3353 }
3354 }
3355 client->clientGone = TRUE; /* so events aren't sent to client */
3356 if (ClientIsAsleep(client))
3357 ClientSignal(client);
3358 ProcessWorkQueueZombies();
3359 CloseDownConnection(client);
3360
3361 /* If the client made it to the Running stage, nClients has
3362 * been incremented on its behalf, so we need to decrement it
3363 * now. If it hasn't gotten to Running, nClients has *not*
3364 * been incremented, so *don't* decrement it.
3365 */
3366 if (client->clientState != ClientStateInitial) {
3367 --nClients;
3368 }
3369 }
3370
3371 if (really_close_down) {
3372 if (client->clientState == ClientStateRunning && nClients == 0)
3373 dispatchException |= dispatchExceptionAtReset;
3374
3375 client->clientState = ClientStateGone;
3376 if (ClientStateCallback) {
3377 NewClientInfoRec clientinfo;
3378
3379 clientinfo.client = client;
3380 clientinfo.prefix = (xConnSetupPrefix *) NULL;
3381 clientinfo.setup = (xConnSetup *) NULL;
3382 CallCallbacks((&ClientStateCallback), (pointer) &clientinfo);
3383 }
3384 TouchListenerGone(client->clientAsMask);
3385 FreeClientResources(client);
3386 /* Disable client ID tracking. This must be done after
3387 * ClientStateCallback. */
3388 ReleaseClientIds(client);
3389#ifdef XSERVER_DTRACE
3390 XSERVER_CLIENT_DISCONNECT(client->index);
3391#endif
3392 if (client->index < nextFreeClientID)
3393 nextFreeClientID = client->index;
3394 clients[client->index] = NullClient;
3395 SmartLastClient = NullClient;
3396 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3397
3398 while (!clients[currentMaxClients - 1])
3399 currentMaxClients--;
3400 }
3401}
3402
3403static void
3404KillAllClients(void)
3405{
3406 int i;
3407
3408 for (i = 1; i < currentMaxClients; i++)
3409 if (clients[i]) {
3410 /* Make sure Retained clients are released. */
3411 clients[i]->closeDownMode = DestroyAll;
3412 CloseDownClient(clients[i]);
3413 }
3414}
3415
3416void
3417InitClient(ClientPtr client, int i, pointer ospriv)
3418{
3419 client->index = i;
3420 client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
3421 client->closeDownMode = i ? DestroyAll : RetainPermanent;
3422 client->requestVector = InitialVector;
3423 client->osPrivate = ospriv;
3424 QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
3425 client->smart_start_tick = SmartScheduleTime;
3426 client->smart_stop_tick = SmartScheduleTime;
3427 client->smart_check_tick = SmartScheduleTime;
3428 client->clientIds = NULL;
3429}
3430
3431/************************
3432 * int NextAvailableClient(ospriv)
3433 *
3434 * OS dependent portion can't assign client id's because of CloseDownModes.
3435 * Returns NULL if there are no free clients.
3436 *************************/
3437
3438ClientPtr
3439NextAvailableClient(pointer ospriv)
3440{
3441 int i;
3442 ClientPtr client;
3443 xReq data;
3444
3445 i = nextFreeClientID;
3446 if (i == MAXCLIENTS)
3447 return (ClientPtr) NULL;
3448 clients[i] = client =
3449 dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
3450 if (!client)
3451 return (ClientPtr) NULL;
3452 InitClient(client, i, ospriv);
3453 if (!InitClientResources(client)) {
3454 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3455 return (ClientPtr) NULL;
3456 }
3457 data.reqType = 1;
3458 data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
3459 if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
3460 FreeClientResources(client);
3461 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3462 return (ClientPtr) NULL;
3463 }
3464 if (i == currentMaxClients)
3465 currentMaxClients++;
3466 while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
3467 nextFreeClientID++;
3468
3469 /* Enable client ID tracking. This must be done before
3470 * ClientStateCallback. */
3471 ReserveClientIds(client);
3472
3473 if (ClientStateCallback) {
3474 NewClientInfoRec clientinfo;
3475
3476 clientinfo.client = client;
3477 clientinfo.prefix = (xConnSetupPrefix *) NULL;
3478 clientinfo.setup = (xConnSetup *) NULL;
3479 CallCallbacks((&ClientStateCallback), (pointer) &clientinfo);
3480 }
3481 return client;
3482}
3483
3484int
3485ProcInitialConnection(ClientPtr client)
3486{
3487 REQUEST(xReq);
3488 xConnClientPrefix *prefix;
3489 int whichbyte = 1;
3490 char order;
3491
3492 prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
3493 order = prefix->byteOrder;
3494 if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
3495 return client->noClientException = -1;
3496 if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
3497 (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
3498 client->swapped = TRUE;
3499 SwapConnClientPrefix(prefix);
3500 }
3501 stuff->reqType = 2;
3502 stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
3503 bytes_to_int32(prefix->nbytesAuthString);
3504 if (client->swapped) {
3505 swaps(&stuff->length);
3506 }
3507 if (order == 'r' || order == 'R') {
3508 client->local = FALSE;
3509 }
3510 ResetCurrentRequest(client);
3511 return Success;
3512}
3513
3514static int
3515SendConnSetup(ClientPtr client, const char *reason)
3516{
3517 xWindowRoot *root;
3518 int i;
3519 int numScreens;
3520 char *lConnectionInfo;
3521 xConnSetupPrefix *lconnSetupPrefix;
3522
3523 if (reason) {
3524 xConnSetupPrefix csp;
3525
3526 csp.success = xFalse;
3527 csp.lengthReason = strlen(reason);
3528 csp.length = bytes_to_int32(csp.lengthReason);
3529 csp.majorVersion = X_PROTOCOL;
3530 csp.minorVersion = X_PROTOCOL_REVISION;
3531 if (client->swapped)
3532 WriteSConnSetupPrefix(client, &csp);
3533 else
3534 WriteToClient(client, sz_xConnSetupPrefix, &csp);
3535 WriteToClient(client, (int) csp.lengthReason, reason);
3536 return client->noClientException = -1;
3537 }
3538
3539 numScreens = screenInfo.numScreens;
3540 lConnectionInfo = ConnectionInfo;
3541 lconnSetupPrefix = &connSetupPrefix;
3542
3543 /* We're about to start speaking X protocol back to the client by
3544 * sending the connection setup info. This means the authorization
3545 * step is complete, and we can count the client as an
3546 * authorized one.
3547 */
3548 nClients++;
3549
3550 client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
3551 client->sequence = 0;
3552 ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
3553 ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
3554#ifdef MATCH_CLIENT_ENDIAN
3555 ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
3556 ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
3557#endif
3558 /* fill in the "currentInputMask" */
3559 root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
3560#ifdef PANORAMIX
3561 if (noPanoramiXExtension)
3562 numScreens = screenInfo.numScreens;
3563 else
3564 numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
3565#endif
3566
3567 for (i = 0; i < numScreens; i++) {
3568 unsigned int j;
3569 xDepth *pDepth;
3570 WindowPtr pRoot = screenInfo.screens[i]->root;
3571
3572 root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
3573 pDepth = (xDepth *) (root + 1);
3574 for (j = 0; j < root->nDepths; j++) {
3575 pDepth = (xDepth *) (((char *) (pDepth + 1)) +
3576 pDepth->nVisuals * sizeof(xVisualType));
3577 }
3578 root = (xWindowRoot *) pDepth;
3579 }
3580
3581 if (client->swapped) {
3582 WriteSConnSetupPrefix(client, lconnSetupPrefix);
3583 WriteSConnectionInfo(client,
3584 (unsigned long) (lconnSetupPrefix->length << 2),
3585 lConnectionInfo);
3586 }
3587 else {
3588 WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
3589 WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
3590 lConnectionInfo);
3591 }
3592 client->clientState = ClientStateRunning;
3593 if (ClientStateCallback) {
3594 NewClientInfoRec clientinfo;
3595
3596 clientinfo.client = client;
3597 clientinfo.prefix = lconnSetupPrefix;
3598 clientinfo.setup = (xConnSetup *) lConnectionInfo;
3599 CallCallbacks((&ClientStateCallback), (pointer) &clientinfo);
3600 }
3601 return Success;
3602}
3603
3604int
3605ProcEstablishConnection(ClientPtr client)
3606{
3607 const char *reason;
3608 char *auth_proto, *auth_string;
3609 xConnClientPrefix *prefix;
3610
3611 REQUEST(xReq);
3612
3613 prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
3614 auth_proto = (char *) prefix + sz_xConnClientPrefix;
3615 auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
3616 if ((prefix->majorVersion != X_PROTOCOL) ||
3617 (prefix->minorVersion != X_PROTOCOL_REVISION))
3618 reason = "Protocol version mismatch";
3619 else
3620 reason = ClientAuthorized(client,
3621 (unsigned short) prefix->nbytesAuthProto,
3622 auth_proto,
3623 (unsigned short) prefix->nbytesAuthString,
3624 auth_string);
3625
3626 return (SendConnSetup(client, reason));
3627}
3628
3629void
3630SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
3631 XID resId, int errorCode)
3632{
3633 xError rep = {
3634 .type = X_Error,
3635 .errorCode = errorCode,
3636 .resourceID = resId,
3637 .minorCode = minorCode,
3638 .majorCode = majorCode
3639 };
3640
3641 WriteEventsToClient(client, 1, (xEvent *) &rep);
3642}
3643
3644void
3645MarkClientException(ClientPtr client)
3646{
3647 client->noClientException = -1;
3648}
3649
3650/*
3651 * This array encodes the answer to the question "what is the log base 2
3652 * of the number of pixels that fit in a scanline pad unit?"
3653 * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
3654 */
3655static int answer[6][4] = {
3656 /* pad pad pad pad */
3657 /* 8 16 32 64 */
3658
3659 {3, 4, 5, 6}, /* 1 bit per pixel */
3660 {1, 2, 3, 4}, /* 4 bits per pixel */
3661 {0, 1, 2, 3}, /* 8 bits per pixel */
3662 {~0, 0, 1, 2}, /* 16 bits per pixel */
3663 {~0, ~0, 0, 1}, /* 24 bits per pixel */
3664 {~0, ~0, 0, 1} /* 32 bits per pixel */
3665};
3666
3667/*
3668 * This array gives the answer to the question "what is the first index for
3669 * the answer array above given the number of bits per pixel?"
3670 * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
3671 */
3672static int indexForBitsPerPixel[33] = {
3673 ~0, 0, ~0, ~0, /* 1 bit per pixel */
3674 1, ~0, ~0, ~0, /* 4 bits per pixel */
3675 2, ~0, ~0, ~0, /* 8 bits per pixel */
3676 ~0, ~0, ~0, ~0,
3677 3, ~0, ~0, ~0, /* 16 bits per pixel */
3678 ~0, ~0, ~0, ~0,
3679 4, ~0, ~0, ~0, /* 24 bits per pixel */
3680 ~0, ~0, ~0, ~0,
3681 5 /* 32 bits per pixel */
3682};
3683
3684/*
3685 * This array gives the bytesperPixel value for cases where the number
3686 * of bits per pixel is a multiple of 8 but not a power of 2.
3687 */
3688static int answerBytesPerPixel[33] = {
3689 ~0, 0, ~0, ~0, /* 1 bit per pixel */
3690 0, ~0, ~0, ~0, /* 4 bits per pixel */
3691 0, ~0, ~0, ~0, /* 8 bits per pixel */
3692 ~0, ~0, ~0, ~0,
3693 0, ~0, ~0, ~0, /* 16 bits per pixel */
3694 ~0, ~0, ~0, ~0,
3695 3, ~0, ~0, ~0, /* 24 bits per pixel */
3696 ~0, ~0, ~0, ~0,
3697 0 /* 32 bits per pixel */
3698};
3699
3700/*
3701 * This array gives the answer to the question "what is the second index for
3702 * the answer array above given the number of bits per scanline pad unit?"
3703 * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
3704 */
3705static int indexForScanlinePad[65] = {
3706 ~0, ~0, ~0, ~0,
3707 ~0, ~0, ~0, ~0,
3708 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */
3709 ~0, ~0, ~0, ~0,
3710 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */
3711 ~0, ~0, ~0, ~0,
3712 ~0, ~0, ~0, ~0,
3713 ~0, ~0, ~0, ~0,
3714 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */
3715 ~0, ~0, ~0, ~0,
3716 ~0, ~0, ~0, ~0,
3717 ~0, ~0, ~0, ~0,
3718 ~0, ~0, ~0, ~0,
3719 ~0, ~0, ~0, ~0,
3720 ~0, ~0, ~0, ~0,
3721 ~0, ~0, ~0, ~0,
3722 3 /* 64 bits per scanline pad unit */
3723};
3724
3725/*
3726 grow the array of screenRecs if necessary.
3727 call the device-supplied initialization procedure
3728with its screen number, a pointer to its ScreenRec, argc, and argv.
3729 return the number of successfully installed screens.
3730
3731*/
3732
3733static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
3734{
3735 int scanlinepad, format, depth, bitsPerPixel, j, k;
3736
3737 dixInitScreenSpecificPrivates(pScreen);
3738
3739 if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
3740 return -1;
3741 }
3742 pScreen->myNum = i;
3743 if (gpu) {
3744 pScreen->myNum += GPU_SCREEN_OFFSET;
3745 pScreen->isGPU = TRUE;
3746 }
3747 pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */
3748 pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
3749 pScreen->CreateScreenResources = 0;
3750
3751 xorg_list_init(&pScreen->pixmap_dirty_list);
3752 xorg_list_init(&pScreen->unattached_list);
3753 xorg_list_init(&pScreen->output_slave_list);
3754 xorg_list_init(&pScreen->offload_slave_list);
3755
3756 /*
3757 * This loop gets run once for every Screen that gets added,
3758 * but thats ok. If the ddx layer initializes the formats
3759 * one at a time calling AddScreen() after each, then each
3760 * iteration will make it a little more accurate. Worst case
3761 * we do this loop N * numPixmapFormats where N is # of screens.
3762 * Anyway, this must be called after InitOutput and before the
3763 * screen init routine is called.
3764 */
3765 for (format = 0; format < screenInfo.numPixmapFormats; format++) {
3766 depth = screenInfo.formats[format].depth;
3767 bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
3768 scanlinepad = screenInfo.formats[format].scanlinePad;
3769 j = indexForBitsPerPixel[bitsPerPixel];
3770 k = indexForScanlinePad[scanlinepad];
3771 PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
3772 PixmapWidthPaddingInfo[depth].padRoundUp =
3773 (scanlinepad / bitsPerPixel) - 1;
3774 j = indexForBitsPerPixel[8]; /* bits per byte */
3775 PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
3776 PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
3777 if (answerBytesPerPixel[bitsPerPixel]) {
3778 PixmapWidthPaddingInfo[depth].notPower2 = 1;
3779 PixmapWidthPaddingInfo[depth].bytesPerPixel =
3780 answerBytesPerPixel[bitsPerPixel];
3781 }
3782 else {
3783 PixmapWidthPaddingInfo[depth].notPower2 = 0;
3784 }
3785 }
3786 return 0;
3787}
3788
3789int
3790AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3791 int /*argc */ ,
3792 char ** /*argv */
3793 ), int argc, char **argv)
3794{
3795
3796 int i;
3797 ScreenPtr pScreen;
3798 Bool ret;
3799
3800 i = screenInfo.numScreens;
3801 if (i == MAXSCREENS)
3802 return -1;
3803
3804 pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3805 if (!pScreen)
3806 return -1;
3807
3808 ret = init_screen(pScreen, i, FALSE);
3809 if (ret != 0) {
3810 free(pScreen);
3811 return ret;
3812 }
3813 /* This is where screen specific stuff gets initialized. Load the
3814 screen structure, call the hardware, whatever.
3815 This is also where the default colormap should be allocated and
3816 also pixel values for blackPixel, whitePixel, and the cursor
3817 Note that InitScreen is NOT allowed to modify argc, argv, or
3818 any of the strings pointed to by argv. They may be passed to
3819 multiple screens.
3820 */
3821 screenInfo.screens[i] = pScreen;
3822 screenInfo.numScreens++;
3823 if (!(*pfnInit) (pScreen, argc, argv)) {
3824 dixFreeScreenSpecificPrivates(pScreen);
3825 dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3826 free(pScreen);
3827 screenInfo.numScreens--;
3828 return -1;
3829 }
3830
3831 update_desktop_dimensions();
3832
3833 dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
3834 0);
3835
3836 return i;
3837}
3838
3839int
3840AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3841 int /*argc */ ,
3842 char ** /*argv */
3843 ),
3844 int argc, char **argv)
3845{
3846 int i;
3847 ScreenPtr pScreen;
3848 Bool ret;
3849
3850 i = screenInfo.numGPUScreens;
3851 if (i == MAXGPUSCREENS)
3852 return -1;
3853
3854 pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3855 if (!pScreen)
3856 return -1;
3857
3858 ret = init_screen(pScreen, i, TRUE);
3859 if (ret != 0) {
3860 free(pScreen);
3861 return ret;
3862 }
3863
3864 /* This is where screen specific stuff gets initialized. Load the
3865 screen structure, call the hardware, whatever.
3866 This is also where the default colormap should be allocated and
3867 also pixel values for blackPixel, whitePixel, and the cursor
3868 Note that InitScreen is NOT allowed to modify argc, argv, or
3869 any of the strings pointed to by argv. They may be passed to
3870 multiple screens.
3871 */
3872 screenInfo.gpuscreens[i] = pScreen;
3873 screenInfo.numGPUScreens++;
3874 if (!(*pfnInit) (pScreen, argc, argv)) {
3875 dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3876 free(pScreen);
3877 screenInfo.numGPUScreens--;
3878 return -1;
3879 }
3880
3881 update_desktop_dimensions();
3882
3883 return i;
3884}
3885
3886void
3887RemoveGPUScreen(ScreenPtr pScreen)
3888{
3889 int idx, j;
3890 if (!pScreen->isGPU)
3891 return;
3892
3893 idx = pScreen->myNum - GPU_SCREEN_OFFSET;
3894 for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
3895 screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
3896 screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
3897 }
3898 screenInfo.numGPUScreens--;
3899
3900 /* this gets freed later in the resource list, but without
3901 * the screen existing it causes crashes - so remove it here */
3902 if (pScreen->defColormap)
3903 FreeResource(pScreen->defColormap, RT_COLORMAP);
3904 free(pScreen);
3905
3906}
3907
3908void
3909AttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
3910{
3911 assert(new->isGPU);
3912 assert(!new->current_master);
3913 xorg_list_add(&new->unattached_head, &pScreen->unattached_list);
3914 new->current_master = pScreen;
3915}
3916
3917void
3918DetachUnboundGPU(ScreenPtr slave)
3919{
3920 assert(slave->isGPU);
3921 xorg_list_del(&slave->unattached_head);
3922 slave->current_master = NULL;
3923}
3924
3925void
3926AttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
3927{
3928 assert(new->isGPU);
3929 xorg_list_add(&new->output_head, &pScreen->output_slave_list);
3930 new->current_master = pScreen;
3931}
3932
3933void
3934DetachOutputGPU(ScreenPtr slave)
3935{
3936 assert(slave->isGPU);
3937 xorg_list_del(&slave->output_head);
3938 slave->current_master = NULL;
3939}
3940
3941void
3942AttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
3943{
3944 assert(new->isGPU);
3945 xorg_list_add(&new->offload_head, &pScreen->offload_slave_list);
3946 new->current_master = pScreen;
3947}
3948
3949void
3950DetachOffloadGPU(ScreenPtr slave)
3951{
3952 assert(slave->isGPU);
3953 xorg_list_del(&slave->offload_head);
3954 slave->current_master = NULL;
3955}
3956