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