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