shm.c revision 05b261ec
105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */
2805b261ecSmrg
2905b261ecSmrg
3005b261ecSmrg#define SHM
3105b261ecSmrg
3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3305b261ecSmrg#include <dix-config.h>
3405b261ecSmrg#endif
3505b261ecSmrg
3605b261ecSmrg#include <sys/types.h>
3705b261ecSmrg#ifndef Lynx
3805b261ecSmrg#include <sys/ipc.h>
3905b261ecSmrg#include <sys/shm.h>
4005b261ecSmrg#else
4105b261ecSmrg#include <ipc.h>
4205b261ecSmrg#include <shm.h>
4305b261ecSmrg#endif
4405b261ecSmrg#include <unistd.h>
4505b261ecSmrg#include <sys/stat.h>
4605b261ecSmrg#define NEED_REPLIES
4705b261ecSmrg#define NEED_EVENTS
4805b261ecSmrg#include <X11/X.h>
4905b261ecSmrg#include <X11/Xproto.h>
5005b261ecSmrg#include "misc.h"
5105b261ecSmrg#include "os.h"
5205b261ecSmrg#include "dixstruct.h"
5305b261ecSmrg#include "resource.h"
5405b261ecSmrg#include "scrnintstr.h"
5505b261ecSmrg#include "windowstr.h"
5605b261ecSmrg#include "pixmapstr.h"
5705b261ecSmrg#include "gcstruct.h"
5805b261ecSmrg#include "extnsionst.h"
5905b261ecSmrg#include "servermd.h"
6005b261ecSmrg#define _XSHM_SERVER_
6105b261ecSmrg#include <X11/extensions/shmstr.h>
6205b261ecSmrg#include <X11/Xfuncproto.h>
6305b261ecSmrg
6405b261ecSmrg#ifdef PANORAMIX
6505b261ecSmrg#include "panoramiX.h"
6605b261ecSmrg#include "panoramiXsrv.h"
6705b261ecSmrg#endif
6805b261ecSmrg
6905b261ecSmrg#include "modinit.h"
7005b261ecSmrg
7105b261ecSmrgtypedef struct _ShmDesc {
7205b261ecSmrg    struct _ShmDesc *next;
7305b261ecSmrg    int shmid;
7405b261ecSmrg    int refcnt;
7505b261ecSmrg    char *addr;
7605b261ecSmrg    Bool writable;
7705b261ecSmrg    unsigned long size;
7805b261ecSmrg} ShmDescRec, *ShmDescPtr;
7905b261ecSmrg
8005b261ecSmrgstatic void miShmPutImage(XSHM_PUT_IMAGE_ARGS);
8105b261ecSmrgstatic void fbShmPutImage(XSHM_PUT_IMAGE_ARGS);
8205b261ecSmrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS);
8305b261ecSmrgstatic int ShmDetachSegment(
8405b261ecSmrg    pointer		/* value */,
8505b261ecSmrg    XID			/* shmseg */
8605b261ecSmrg    );
8705b261ecSmrgstatic void ShmResetProc(
8805b261ecSmrg    ExtensionEntry *	/* extEntry */
8905b261ecSmrg    );
9005b261ecSmrgstatic void SShmCompletionEvent(
9105b261ecSmrg    xShmCompletionEvent * /* from */,
9205b261ecSmrg    xShmCompletionEvent * /* to */
9305b261ecSmrg    );
9405b261ecSmrg
9505b261ecSmrgstatic Bool ShmDestroyPixmap (PixmapPtr pPixmap);
9605b261ecSmrg
9705b261ecSmrgstatic DISPATCH_PROC(ProcShmAttach);
9805b261ecSmrgstatic DISPATCH_PROC(ProcShmCreatePixmap);
9905b261ecSmrgstatic DISPATCH_PROC(ProcShmDetach);
10005b261ecSmrgstatic DISPATCH_PROC(ProcShmDispatch);
10105b261ecSmrgstatic DISPATCH_PROC(ProcShmGetImage);
10205b261ecSmrgstatic DISPATCH_PROC(ProcShmPutImage);
10305b261ecSmrgstatic DISPATCH_PROC(ProcShmQueryVersion);
10405b261ecSmrgstatic DISPATCH_PROC(SProcShmAttach);
10505b261ecSmrgstatic DISPATCH_PROC(SProcShmCreatePixmap);
10605b261ecSmrgstatic DISPATCH_PROC(SProcShmDetach);
10705b261ecSmrgstatic DISPATCH_PROC(SProcShmDispatch);
10805b261ecSmrgstatic DISPATCH_PROC(SProcShmGetImage);
10905b261ecSmrgstatic DISPATCH_PROC(SProcShmPutImage);
11005b261ecSmrgstatic DISPATCH_PROC(SProcShmQueryVersion);
11105b261ecSmrg
11205b261ecSmrgstatic unsigned char ShmReqCode;
11305b261ecSmrg_X_EXPORT int ShmCompletionCode;
11405b261ecSmrg_X_EXPORT int BadShmSegCode;
11505b261ecSmrg_X_EXPORT RESTYPE ShmSegType;
11605b261ecSmrgstatic ShmDescPtr Shmsegs;
11705b261ecSmrgstatic Bool sharedPixmaps;
11805b261ecSmrgstatic int pixmapFormat;
11905b261ecSmrgstatic int shmPixFormat[MAXSCREENS];
12005b261ecSmrgstatic ShmFuncsPtr shmFuncs[MAXSCREENS];
12105b261ecSmrgstatic DestroyPixmapProcPtr destroyPixmap[MAXSCREENS];
12205b261ecSmrgstatic int  shmPixmapPrivate;
12305b261ecSmrgstatic ShmFuncs miFuncs = {NULL, miShmPutImage};
12405b261ecSmrgstatic ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage};
12505b261ecSmrg
12605b261ecSmrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
12705b261ecSmrg{ \
12805b261ecSmrg    shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \
12905b261ecSmrg    if (!shmdesc) \
13005b261ecSmrg    { \
13105b261ecSmrg	client->errorValue = shmseg; \
13205b261ecSmrg	return BadShmSegCode; \
13305b261ecSmrg    } \
13405b261ecSmrg}
13505b261ecSmrg
13605b261ecSmrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
13705b261ecSmrg{ \
13805b261ecSmrg    VERIFY_SHMSEG(shmseg, shmdesc, client); \
13905b261ecSmrg    if ((offset & 3) || (offset > shmdesc->size)) \
14005b261ecSmrg    { \
14105b261ecSmrg	client->errorValue = offset; \
14205b261ecSmrg	return BadValue; \
14305b261ecSmrg    } \
14405b261ecSmrg    if (needwrite && !shmdesc->writable) \
14505b261ecSmrg	return BadAccess; \
14605b261ecSmrg}
14705b261ecSmrg
14805b261ecSmrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
14905b261ecSmrg{ \
15005b261ecSmrg    if ((offset + len) > shmdesc->size) \
15105b261ecSmrg    { \
15205b261ecSmrg	return BadAccess; \
15305b261ecSmrg    } \
15405b261ecSmrg}
15505b261ecSmrg
15605b261ecSmrg
15705b261ecSmrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
15805b261ecSmrg#include <sys/signal.h>
15905b261ecSmrg
16005b261ecSmrgstatic Bool badSysCall = FALSE;
16105b261ecSmrg
16205b261ecSmrgstatic void
16305b261ecSmrgSigSysHandler(signo)
16405b261ecSmrgint signo;
16505b261ecSmrg{
16605b261ecSmrg    badSysCall = TRUE;
16705b261ecSmrg}
16805b261ecSmrg
16905b261ecSmrgstatic Bool CheckForShmSyscall()
17005b261ecSmrg{
17105b261ecSmrg    void (*oldHandler)();
17205b261ecSmrg    int shmid = -1;
17305b261ecSmrg
17405b261ecSmrg    /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
17505b261ecSmrg    oldHandler = signal(SIGSYS, SigSysHandler);
17605b261ecSmrg
17705b261ecSmrg    badSysCall = FALSE;
17805b261ecSmrg    shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
17905b261ecSmrg
18005b261ecSmrg    if (shmid != -1)
18105b261ecSmrg    {
18205b261ecSmrg        /* Successful allocation - clean up */
18305b261ecSmrg	shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL);
18405b261ecSmrg    }
18505b261ecSmrg    else
18605b261ecSmrg    {
18705b261ecSmrg        /* Allocation failed */
18805b261ecSmrg        badSysCall = TRUE;
18905b261ecSmrg    }
19005b261ecSmrg    signal(SIGSYS, oldHandler);
19105b261ecSmrg    return(!badSysCall);
19205b261ecSmrg}
19305b261ecSmrg
19405b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL
19505b261ecSmrg
19605b261ecSmrg#endif
19705b261ecSmrg
19805b261ecSmrgvoid
19905b261ecSmrgShmExtensionInit(INITARGS)
20005b261ecSmrg{
20105b261ecSmrg    ExtensionEntry *extEntry;
20205b261ecSmrg    int i;
20305b261ecSmrg
20405b261ecSmrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL
20505b261ecSmrg    if (!CheckForShmSyscall())
20605b261ecSmrg    {
20705b261ecSmrg	ErrorF("MIT-SHM extension disabled due to lack of kernel support\n");
20805b261ecSmrg	return;
20905b261ecSmrg    }
21005b261ecSmrg#endif
21105b261ecSmrg
21205b261ecSmrg    sharedPixmaps = xFalse;
21305b261ecSmrg    pixmapFormat = 0;
21405b261ecSmrg    {
21505b261ecSmrg      sharedPixmaps = xTrue;
21605b261ecSmrg      pixmapFormat = shmPixFormat[0];
21705b261ecSmrg      for (i = 0; i < screenInfo.numScreens; i++)
21805b261ecSmrg      {
21905b261ecSmrg	if (!shmFuncs[i])
22005b261ecSmrg	    shmFuncs[i] = &miFuncs;
22105b261ecSmrg	if (!shmFuncs[i]->CreatePixmap)
22205b261ecSmrg	    sharedPixmaps = xFalse;
22305b261ecSmrg	if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat))
22405b261ecSmrg	{
22505b261ecSmrg	    sharedPixmaps = xFalse;
22605b261ecSmrg	    pixmapFormat = 0;
22705b261ecSmrg	}
22805b261ecSmrg      }
22905b261ecSmrg      if (!pixmapFormat)
23005b261ecSmrg	pixmapFormat = ZPixmap;
23105b261ecSmrg      if (sharedPixmaps)
23205b261ecSmrg      {
23305b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++)
23405b261ecSmrg	{
23505b261ecSmrg	    destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap;
23605b261ecSmrg	    screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap;
23705b261ecSmrg	}
23805b261ecSmrg	shmPixmapPrivate = AllocatePixmapPrivateIndex();
23905b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++)
24005b261ecSmrg	{
24105b261ecSmrg	    if (!AllocatePixmapPrivate(screenInfo.screens[i],
24205b261ecSmrg				       shmPixmapPrivate, 0))
24305b261ecSmrg		return;
24405b261ecSmrg	}
24505b261ecSmrg      }
24605b261ecSmrg    }
24705b261ecSmrg    ShmSegType = CreateNewResourceType(ShmDetachSegment);
24805b261ecSmrg    if (ShmSegType &&
24905b261ecSmrg	(extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors,
25005b261ecSmrg				 ProcShmDispatch, SProcShmDispatch,
25105b261ecSmrg				 ShmResetProc, StandardMinorOpcode)))
25205b261ecSmrg    {
25305b261ecSmrg	ShmReqCode = (unsigned char)extEntry->base;
25405b261ecSmrg	ShmCompletionCode = extEntry->eventBase;
25505b261ecSmrg	BadShmSegCode = extEntry->errorBase;
25605b261ecSmrg	EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent;
25705b261ecSmrg    }
25805b261ecSmrg}
25905b261ecSmrg
26005b261ecSmrg/*ARGSUSED*/
26105b261ecSmrgstatic void
26205b261ecSmrgShmResetProc (extEntry)
26305b261ecSmrgExtensionEntry	*extEntry;
26405b261ecSmrg{
26505b261ecSmrg    int i;
26605b261ecSmrg
26705b261ecSmrg    for (i = 0; i < MAXSCREENS; i++)
26805b261ecSmrg    {
26905b261ecSmrg	shmFuncs[i] = (ShmFuncsPtr)NULL;
27005b261ecSmrg	shmPixFormat[i] = 0;
27105b261ecSmrg    }
27205b261ecSmrg}
27305b261ecSmrg
27405b261ecSmrgvoid
27505b261ecSmrgShmRegisterFuncs(
27605b261ecSmrg    ScreenPtr pScreen,
27705b261ecSmrg    ShmFuncsPtr funcs)
27805b261ecSmrg{
27905b261ecSmrg    shmFuncs[pScreen->myNum] = funcs;
28005b261ecSmrg}
28105b261ecSmrg
28205b261ecSmrgvoid
28305b261ecSmrgShmSetPixmapFormat(
28405b261ecSmrg    ScreenPtr pScreen,
28505b261ecSmrg    int format)
28605b261ecSmrg{
28705b261ecSmrg    shmPixFormat[pScreen->myNum] = format;
28805b261ecSmrg}
28905b261ecSmrg
29005b261ecSmrgstatic Bool
29105b261ecSmrgShmDestroyPixmap (PixmapPtr pPixmap)
29205b261ecSmrg{
29305b261ecSmrg    ScreenPtr	    pScreen = pPixmap->drawable.pScreen;
29405b261ecSmrg    Bool	    ret;
29505b261ecSmrg    if (pPixmap->refcnt == 1)
29605b261ecSmrg    {
29705b261ecSmrg	ShmDescPtr  shmdesc;
29805b261ecSmrg	shmdesc = (ShmDescPtr) pPixmap->devPrivates[shmPixmapPrivate].ptr;
29905b261ecSmrg	if (shmdesc)
30005b261ecSmrg	    ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id);
30105b261ecSmrg    }
30205b261ecSmrg
30305b261ecSmrg    pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum];
30405b261ecSmrg    ret = (*pScreen->DestroyPixmap) (pPixmap);
30505b261ecSmrg    destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap;
30605b261ecSmrg    pScreen->DestroyPixmap = ShmDestroyPixmap;
30705b261ecSmrg    return ret;
30805b261ecSmrg}
30905b261ecSmrg
31005b261ecSmrgvoid
31105b261ecSmrgShmRegisterFbFuncs(pScreen)
31205b261ecSmrg    ScreenPtr pScreen;
31305b261ecSmrg{
31405b261ecSmrg    shmFuncs[pScreen->myNum] = &fbFuncs;
31505b261ecSmrg}
31605b261ecSmrg
31705b261ecSmrgstatic int
31805b261ecSmrgProcShmQueryVersion(client)
31905b261ecSmrg    register ClientPtr client;
32005b261ecSmrg{
32105b261ecSmrg    xShmQueryVersionReply rep;
32205b261ecSmrg    register int n;
32305b261ecSmrg
32405b261ecSmrg    REQUEST_SIZE_MATCH(xShmQueryVersionReq);
32505b261ecSmrg    rep.type = X_Reply;
32605b261ecSmrg    rep.length = 0;
32705b261ecSmrg    rep.sequenceNumber = client->sequence;
32805b261ecSmrg    rep.sharedPixmaps = sharedPixmaps;
32905b261ecSmrg    rep.pixmapFormat = pixmapFormat;
33005b261ecSmrg    rep.majorVersion = SHM_MAJOR_VERSION;
33105b261ecSmrg    rep.minorVersion = SHM_MINOR_VERSION;
33205b261ecSmrg    rep.uid = geteuid();
33305b261ecSmrg    rep.gid = getegid();
33405b261ecSmrg    if (client->swapped) {
33505b261ecSmrg    	swaps(&rep.sequenceNumber, n);
33605b261ecSmrg    	swapl(&rep.length, n);
33705b261ecSmrg	swaps(&rep.majorVersion, n);
33805b261ecSmrg	swaps(&rep.minorVersion, n);
33905b261ecSmrg	swaps(&rep.uid, n);
34005b261ecSmrg	swaps(&rep.gid, n);
34105b261ecSmrg    }
34205b261ecSmrg    WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep);
34305b261ecSmrg    return (client->noClientException);
34405b261ecSmrg}
34505b261ecSmrg
34605b261ecSmrg/*
34705b261ecSmrg * Simulate the access() system call for a shared memory segement,
34805b261ecSmrg * using the credentials from the client if available
34905b261ecSmrg */
35005b261ecSmrgstatic int
35105b261ecSmrgshm_access(ClientPtr client, struct ipc_perm *perm, int readonly)
35205b261ecSmrg{
35305b261ecSmrg    int uid, gid;
35405b261ecSmrg    mode_t mask;
35505b261ecSmrg
35605b261ecSmrg    if (LocalClientCred(client, &uid, &gid) != -1) {
35705b261ecSmrg
35805b261ecSmrg	/* User id 0 always gets access */
35905b261ecSmrg	if (uid == 0) {
36005b261ecSmrg	    return 0;
36105b261ecSmrg	}
36205b261ecSmrg	/* Check the owner */
36305b261ecSmrg	if (perm->uid == uid || perm->cuid == uid) {
36405b261ecSmrg	    mask = S_IRUSR;
36505b261ecSmrg	    if (!readonly) {
36605b261ecSmrg		mask |= S_IWUSR;
36705b261ecSmrg	    }
36805b261ecSmrg	    return (perm->mode & mask) == mask ? 0 : -1;
36905b261ecSmrg	}
37005b261ecSmrg	/* Check the group */
37105b261ecSmrg	if (perm->gid == gid || perm->cgid == gid) {
37205b261ecSmrg	    mask = S_IRGRP;
37305b261ecSmrg	    if (!readonly) {
37405b261ecSmrg		mask |= S_IWGRP;
37505b261ecSmrg	    }
37605b261ecSmrg	    return (perm->mode & mask) == mask ? 0 : -1;
37705b261ecSmrg	}
37805b261ecSmrg    }
37905b261ecSmrg    /* Otherwise, check everyone else */
38005b261ecSmrg    mask = S_IROTH;
38105b261ecSmrg    if (!readonly) {
38205b261ecSmrg	mask |= S_IWOTH;
38305b261ecSmrg    }
38405b261ecSmrg    return (perm->mode & mask) == mask ? 0 : -1;
38505b261ecSmrg}
38605b261ecSmrg
38705b261ecSmrgstatic int
38805b261ecSmrgProcShmAttach(client)
38905b261ecSmrg    register ClientPtr client;
39005b261ecSmrg{
39105b261ecSmrg    struct shmid_ds buf;
39205b261ecSmrg    ShmDescPtr shmdesc;
39305b261ecSmrg    REQUEST(xShmAttachReq);
39405b261ecSmrg
39505b261ecSmrg    REQUEST_SIZE_MATCH(xShmAttachReq);
39605b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->shmseg, client);
39705b261ecSmrg    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse))
39805b261ecSmrg    {
39905b261ecSmrg	client->errorValue = stuff->readOnly;
40005b261ecSmrg        return(BadValue);
40105b261ecSmrg    }
40205b261ecSmrg    for (shmdesc = Shmsegs;
40305b261ecSmrg	 shmdesc && (shmdesc->shmid != stuff->shmid);
40405b261ecSmrg	 shmdesc = shmdesc->next)
40505b261ecSmrg	;
40605b261ecSmrg    if (shmdesc)
40705b261ecSmrg    {
40805b261ecSmrg	if (!stuff->readOnly && !shmdesc->writable)
40905b261ecSmrg	    return BadAccess;
41005b261ecSmrg	shmdesc->refcnt++;
41105b261ecSmrg    }
41205b261ecSmrg    else
41305b261ecSmrg    {
41405b261ecSmrg	shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec));
41505b261ecSmrg	if (!shmdesc)
41605b261ecSmrg	    return BadAlloc;
41705b261ecSmrg	shmdesc->addr = shmat(stuff->shmid, 0,
41805b261ecSmrg			      stuff->readOnly ? SHM_RDONLY : 0);
41905b261ecSmrg	if ((shmdesc->addr == ((char *)-1)) ||
42005b261ecSmrg	    shmctl(stuff->shmid, IPC_STAT, &buf))
42105b261ecSmrg	{
42205b261ecSmrg	    xfree(shmdesc);
42305b261ecSmrg	    return BadAccess;
42405b261ecSmrg	}
42505b261ecSmrg
42605b261ecSmrg	/* The attach was performed with root privs. We must
42705b261ecSmrg	 * do manual checking of access rights for the credentials
42805b261ecSmrg	 * of the client */
42905b261ecSmrg
43005b261ecSmrg	if (shm_access(client, &(buf.shm_perm), stuff->readOnly) == -1) {
43105b261ecSmrg	    shmdt(shmdesc->addr);
43205b261ecSmrg	    xfree(shmdesc);
43305b261ecSmrg	    return BadAccess;
43405b261ecSmrg	}
43505b261ecSmrg
43605b261ecSmrg	shmdesc->shmid = stuff->shmid;
43705b261ecSmrg	shmdesc->refcnt = 1;
43805b261ecSmrg	shmdesc->writable = !stuff->readOnly;
43905b261ecSmrg	shmdesc->size = buf.shm_segsz;
44005b261ecSmrg	shmdesc->next = Shmsegs;
44105b261ecSmrg	Shmsegs = shmdesc;
44205b261ecSmrg    }
44305b261ecSmrg    if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc))
44405b261ecSmrg	return BadAlloc;
44505b261ecSmrg    return(client->noClientException);
44605b261ecSmrg}
44705b261ecSmrg
44805b261ecSmrg/*ARGSUSED*/
44905b261ecSmrgstatic int
45005b261ecSmrgShmDetachSegment(value, shmseg)
45105b261ecSmrg    pointer value; /* must conform to DeleteType */
45205b261ecSmrg    XID shmseg;
45305b261ecSmrg{
45405b261ecSmrg    ShmDescPtr shmdesc = (ShmDescPtr)value;
45505b261ecSmrg    ShmDescPtr *prev;
45605b261ecSmrg
45705b261ecSmrg    if (--shmdesc->refcnt)
45805b261ecSmrg	return TRUE;
45905b261ecSmrg    shmdt(shmdesc->addr);
46005b261ecSmrg    for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next)
46105b261ecSmrg	;
46205b261ecSmrg    *prev = shmdesc->next;
46305b261ecSmrg    xfree(shmdesc);
46405b261ecSmrg    return Success;
46505b261ecSmrg}
46605b261ecSmrg
46705b261ecSmrgstatic int
46805b261ecSmrgProcShmDetach(client)
46905b261ecSmrg    register ClientPtr client;
47005b261ecSmrg{
47105b261ecSmrg    ShmDescPtr shmdesc;
47205b261ecSmrg    REQUEST(xShmDetachReq);
47305b261ecSmrg
47405b261ecSmrg    REQUEST_SIZE_MATCH(xShmDetachReq);
47505b261ecSmrg    VERIFY_SHMSEG(stuff->shmseg, shmdesc, client);
47605b261ecSmrg    FreeResource(stuff->shmseg, RT_NONE);
47705b261ecSmrg    return(client->noClientException);
47805b261ecSmrg}
47905b261ecSmrg
48005b261ecSmrgstatic void
48105b261ecSmrgmiShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data)
48205b261ecSmrg    DrawablePtr dst;
48305b261ecSmrg    GCPtr	pGC;
48405b261ecSmrg    int		depth, w, h, sx, sy, sw, sh, dx, dy;
48505b261ecSmrg    unsigned int format;
48605b261ecSmrg    char 	*data;
48705b261ecSmrg{
48805b261ecSmrg    PixmapPtr pmap;
48905b261ecSmrg    GCPtr putGC;
49005b261ecSmrg
49105b261ecSmrg    putGC = GetScratchGC(depth, dst->pScreen);
49205b261ecSmrg    if (!putGC)
49305b261ecSmrg	return;
49405b261ecSmrg    pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth);
49505b261ecSmrg    if (!pmap)
49605b261ecSmrg    {
49705b261ecSmrg	FreeScratchGC(putGC);
49805b261ecSmrg	return;
49905b261ecSmrg    }
50005b261ecSmrg    ValidateGC((DrawablePtr)pmap, putGC);
50105b261ecSmrg    (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0,
50205b261ecSmrg			    (format == XYPixmap) ? XYPixmap : ZPixmap, data);
50305b261ecSmrg    FreeScratchGC(putGC);
50405b261ecSmrg    if (format == XYBitmap)
50505b261ecSmrg	(void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh,
50605b261ecSmrg				     dx, dy, 1L);
50705b261ecSmrg    else
50805b261ecSmrg	(void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh,
50905b261ecSmrg				    dx, dy);
51005b261ecSmrg    (*pmap->drawable.pScreen->DestroyPixmap)(pmap);
51105b261ecSmrg}
51205b261ecSmrg
51305b261ecSmrgstatic void
51405b261ecSmrgfbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data)
51505b261ecSmrg    DrawablePtr dst;
51605b261ecSmrg    GCPtr	pGC;
51705b261ecSmrg    int		depth, w, h, sx, sy, sw, sh, dx, dy;
51805b261ecSmrg    unsigned int format;
51905b261ecSmrg    char 	*data;
52005b261ecSmrg{
52105b261ecSmrg    if ((format == ZPixmap) || (depth == 1))
52205b261ecSmrg    {
52305b261ecSmrg	PixmapPtr pPixmap;
52405b261ecSmrg
52505b261ecSmrg	pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
52605b261ecSmrg		BitsPerPixel(depth), PixmapBytePad(w, depth), (pointer)data);
52705b261ecSmrg	if (!pPixmap)
52805b261ecSmrg	    return;
52905b261ecSmrg	if (format == XYBitmap)
53005b261ecSmrg	    (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC,
53105b261ecSmrg					 sx, sy, sw, sh, dx, dy, 1L);
53205b261ecSmrg	else
53305b261ecSmrg	    (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC,
53405b261ecSmrg					sx, sy, sw, sh, dx, dy);
53505b261ecSmrg	FreeScratchPixmapHeader(pPixmap);
53605b261ecSmrg    }
53705b261ecSmrg    else
53805b261ecSmrg	miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
53905b261ecSmrg		      data);
54005b261ecSmrg}
54105b261ecSmrg
54205b261ecSmrg
54305b261ecSmrg#ifdef PANORAMIX
54405b261ecSmrgstatic int
54505b261ecSmrgProcPanoramiXShmPutImage(register ClientPtr client)
54605b261ecSmrg{
54705b261ecSmrg    int			 j, result = 0, orig_x, orig_y;
54805b261ecSmrg    PanoramiXRes	*draw, *gc;
54905b261ecSmrg    Bool		 sendEvent, isRoot;
55005b261ecSmrg
55105b261ecSmrg    REQUEST(xShmPutImageReq);
55205b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
55305b261ecSmrg
55405b261ecSmrg    if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass(
55505b261ecSmrg                client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess)))
55605b261ecSmrg        return BadDrawable;
55705b261ecSmrg
55805b261ecSmrg    if(!(gc = (PanoramiXRes *)SecurityLookupIDByType(
55905b261ecSmrg                client, stuff->gc, XRT_GC, DixReadAccess)))
56005b261ecSmrg        return BadGC;
56105b261ecSmrg
56205b261ecSmrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
56305b261ecSmrg
56405b261ecSmrg    orig_x = stuff->dstX;
56505b261ecSmrg    orig_y = stuff->dstY;
56605b261ecSmrg    sendEvent = stuff->sendEvent;
56705b261ecSmrg    stuff->sendEvent = 0;
56805b261ecSmrg    FOR_NSCREENS(j) {
56905b261ecSmrg	if(!j) stuff->sendEvent = sendEvent;
57005b261ecSmrg	stuff->drawable = draw->info[j].id;
57105b261ecSmrg	stuff->gc = gc->info[j].id;
57205b261ecSmrg	if (isRoot) {
57305b261ecSmrg	    stuff->dstX = orig_x - panoramiXdataPtr[j].x;
57405b261ecSmrg	    stuff->dstY = orig_y - panoramiXdataPtr[j].y;
57505b261ecSmrg	}
57605b261ecSmrg	result = ProcShmPutImage(client);
57705b261ecSmrg	if(result != client->noClientException) break;
57805b261ecSmrg    }
57905b261ecSmrg    return(result);
58005b261ecSmrg}
58105b261ecSmrg
58205b261ecSmrgstatic int
58305b261ecSmrgProcPanoramiXShmGetImage(ClientPtr client)
58405b261ecSmrg{
58505b261ecSmrg    PanoramiXRes	*draw;
58605b261ecSmrg    DrawablePtr 	drawables[MAXSCREENS];
58705b261ecSmrg    DrawablePtr 	pDraw;
58805b261ecSmrg    xShmGetImageReply	xgi;
58905b261ecSmrg    ShmDescPtr		shmdesc;
59005b261ecSmrg    int         	i, x, y, w, h, format, rc;
59105b261ecSmrg    Mask		plane = 0, planemask;
59205b261ecSmrg    long		lenPer = 0, length, widthBytesLine;
59305b261ecSmrg    Bool		isRoot;
59405b261ecSmrg
59505b261ecSmrg    REQUEST(xShmGetImageReq);
59605b261ecSmrg
59705b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
59805b261ecSmrg
59905b261ecSmrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) {
60005b261ecSmrg	client->errorValue = stuff->format;
60105b261ecSmrg        return(BadValue);
60205b261ecSmrg    }
60305b261ecSmrg
60405b261ecSmrg    if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass(
60505b261ecSmrg		client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess)))
60605b261ecSmrg	return BadDrawable;
60705b261ecSmrg
60805b261ecSmrg    if (draw->type == XRT_PIXMAP)
60905b261ecSmrg	return ProcShmGetImage(client);
61005b261ecSmrg
61105b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
61205b261ecSmrg			   DixUnknownAccess);
61305b261ecSmrg    if (rc != Success)
61405b261ecSmrg	return rc;
61505b261ecSmrg
61605b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
61705b261ecSmrg
61805b261ecSmrg    x = stuff->x;
61905b261ecSmrg    y = stuff->y;
62005b261ecSmrg    w = stuff->width;
62105b261ecSmrg    h = stuff->height;
62205b261ecSmrg    format = stuff->format;
62305b261ecSmrg    planemask = stuff->planeMask;
62405b261ecSmrg
62505b261ecSmrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
62605b261ecSmrg
62705b261ecSmrg    if(isRoot) {
62805b261ecSmrg      if( /* check for being onscreen */
62905b261ecSmrg	x < 0 || x + w > PanoramiXPixWidth ||
63005b261ecSmrg	y < 0 || y + h > PanoramiXPixHeight )
63105b261ecSmrg	    return(BadMatch);
63205b261ecSmrg    } else {
63305b261ecSmrg      if( /* check for being onscreen */
63405b261ecSmrg	panoramiXdataPtr[0].x + pDraw->x + x < 0 ||
63505b261ecSmrg	panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth ||
63605b261ecSmrg        panoramiXdataPtr[0].y + pDraw->y + y < 0 ||
63705b261ecSmrg	panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight ||
63805b261ecSmrg	 /* check for being inside of border */
63905b261ecSmrg       	x < - wBorderWidth((WindowPtr)pDraw) ||
64005b261ecSmrg	x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
64105b261ecSmrg	y < -wBorderWidth((WindowPtr)pDraw) ||
64205b261ecSmrg	y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height)
64305b261ecSmrg	    return(BadMatch);
64405b261ecSmrg    }
64505b261ecSmrg
64605b261ecSmrg    drawables[0] = pDraw;
64705b261ecSmrg    for(i = 1; i < PanoramiXNumScreens; i++) {
64805b261ecSmrg	rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
64905b261ecSmrg			       DixUnknownAccess);
65005b261ecSmrg	if (rc != Success)
65105b261ecSmrg	    return rc;
65205b261ecSmrg    }
65305b261ecSmrg
65405b261ecSmrg    xgi.visual = wVisual(((WindowPtr)pDraw));
65505b261ecSmrg    xgi.type = X_Reply;
65605b261ecSmrg    xgi.length = 0;
65705b261ecSmrg    xgi.sequenceNumber = client->sequence;
65805b261ecSmrg    xgi.depth = pDraw->depth;
65905b261ecSmrg
66005b261ecSmrg    if(format == ZPixmap) {
66105b261ecSmrg	widthBytesLine = PixmapBytePad(w, pDraw->depth);
66205b261ecSmrg	length = widthBytesLine * h;
66305b261ecSmrg    } else {
66405b261ecSmrg	widthBytesLine = PixmapBytePad(w, 1);
66505b261ecSmrg	lenPer = widthBytesLine * h;
66605b261ecSmrg	plane = ((Mask)1) << (pDraw->depth - 1);
66705b261ecSmrg	length = lenPer * Ones(planemask & (plane | (plane - 1)));
66805b261ecSmrg    }
66905b261ecSmrg
67005b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
67105b261ecSmrg    xgi.size = length;
67205b261ecSmrg
67305b261ecSmrg    if (length == 0) {/* nothing to do */ }
67405b261ecSmrg    else if (format == ZPixmap) {
67505b261ecSmrg	    XineramaGetImageData(drawables, x, y, w, h, format, planemask,
67605b261ecSmrg					shmdesc->addr + stuff->offset,
67705b261ecSmrg					widthBytesLine, isRoot);
67805b261ecSmrg    } else {
67905b261ecSmrg
68005b261ecSmrg	length = stuff->offset;
68105b261ecSmrg        for (; plane; plane >>= 1) {
68205b261ecSmrg	    if (planemask & plane) {
68305b261ecSmrg		XineramaGetImageData(drawables, x, y, w, h,
68405b261ecSmrg				     format, plane, shmdesc->addr + length,
68505b261ecSmrg				     widthBytesLine, isRoot);
68605b261ecSmrg		length += lenPer;
68705b261ecSmrg	    }
68805b261ecSmrg	}
68905b261ecSmrg    }
69005b261ecSmrg
69105b261ecSmrg    if (client->swapped) {
69205b261ecSmrg	register int n;
69305b261ecSmrg    	swaps(&xgi.sequenceNumber, n);
69405b261ecSmrg    	swapl(&xgi.length, n);
69505b261ecSmrg	swapl(&xgi.visual, n);
69605b261ecSmrg	swapl(&xgi.size, n);
69705b261ecSmrg    }
69805b261ecSmrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
69905b261ecSmrg
70005b261ecSmrg    return(client->noClientException);
70105b261ecSmrg}
70205b261ecSmrg
70305b261ecSmrgstatic int
70405b261ecSmrgProcPanoramiXShmCreatePixmap(
70505b261ecSmrg    register ClientPtr client)
70605b261ecSmrg{
70705b261ecSmrg    ScreenPtr pScreen = NULL;
70805b261ecSmrg    PixmapPtr pMap = NULL;
70905b261ecSmrg    DrawablePtr pDraw;
71005b261ecSmrg    DepthPtr pDepth;
71105b261ecSmrg    int i, j, result, rc;
71205b261ecSmrg    ShmDescPtr shmdesc;
71305b261ecSmrg    REQUEST(xShmCreatePixmapReq);
71405b261ecSmrg    unsigned int width, height, depth;
71505b261ecSmrg    unsigned long size;
71605b261ecSmrg    PanoramiXRes *newPix;
71705b261ecSmrg
71805b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
71905b261ecSmrg    client->errorValue = stuff->pid;
72005b261ecSmrg    if (!sharedPixmaps)
72105b261ecSmrg	return BadImplementation;
72205b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
72305b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
72405b261ecSmrg			   DixUnknownAccess);
72505b261ecSmrg    if (rc != Success)
72605b261ecSmrg	return rc;
72705b261ecSmrg
72805b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
72905b261ecSmrg
73005b261ecSmrg    width = stuff->width;
73105b261ecSmrg    height = stuff->height;
73205b261ecSmrg    depth = stuff->depth;
73305b261ecSmrg    if (!width || !height || !depth)
73405b261ecSmrg    {
73505b261ecSmrg	client->errorValue = 0;
73605b261ecSmrg        return BadValue;
73705b261ecSmrg    }
73805b261ecSmrg    if (width > 32767 || height > 32767)
73905b261ecSmrg        return BadAlloc;
74005b261ecSmrg
74105b261ecSmrg    if (stuff->depth != 1)
74205b261ecSmrg    {
74305b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
74405b261ecSmrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
74505b261ecSmrg	   if (pDepth->depth == stuff->depth)
74605b261ecSmrg               goto CreatePmap;
74705b261ecSmrg	client->errorValue = stuff->depth;
74805b261ecSmrg        return BadValue;
74905b261ecSmrg    }
75005b261ecSmrg
75105b261ecSmrgCreatePmap:
75205b261ecSmrg    size = PixmapBytePad(width, depth) * height;
75305b261ecSmrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
75405b261ecSmrg        if (size < width * height)
75505b261ecSmrg            return BadAlloc;
75605b261ecSmrg    }
75705b261ecSmrg    /* thankfully, offset is unsigned */
75805b261ecSmrg    if (stuff->offset + size < size)
75905b261ecSmrg	return BadAlloc;
76005b261ecSmrg
76105b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
76205b261ecSmrg
76305b261ecSmrg    if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes))))
76405b261ecSmrg	return BadAlloc;
76505b261ecSmrg
76605b261ecSmrg    newPix->type = XRT_PIXMAP;
76705b261ecSmrg    newPix->u.pix.shared = TRUE;
76805b261ecSmrg    newPix->info[0].id = stuff->pid;
76905b261ecSmrg    for(j = 1; j < PanoramiXNumScreens; j++)
77005b261ecSmrg	newPix->info[j].id = FakeClientID(client->index);
77105b261ecSmrg
77205b261ecSmrg    result = (client->noClientException);
77305b261ecSmrg
77405b261ecSmrg    FOR_NSCREENS(j) {
77505b261ecSmrg	pScreen = screenInfo.screens[j];
77605b261ecSmrg
77705b261ecSmrg	pMap = (*shmFuncs[j]->CreatePixmap)(pScreen,
77805b261ecSmrg				stuff->width, stuff->height, stuff->depth,
77905b261ecSmrg				shmdesc->addr + stuff->offset);
78005b261ecSmrg
78105b261ecSmrg	if (pMap) {
78205b261ecSmrg            pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc;
78305b261ecSmrg            shmdesc->refcnt++;
78405b261ecSmrg	    pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
78505b261ecSmrg	    pMap->drawable.id = newPix->info[j].id;
78605b261ecSmrg	    if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) {
78705b261ecSmrg		(*pScreen->DestroyPixmap)(pMap);
78805b261ecSmrg		result = BadAlloc;
78905b261ecSmrg		break;
79005b261ecSmrg	    }
79105b261ecSmrg	} else {
79205b261ecSmrg	   result = BadAlloc;
79305b261ecSmrg	   break;
79405b261ecSmrg	}
79505b261ecSmrg    }
79605b261ecSmrg
79705b261ecSmrg    if(result == BadAlloc) {
79805b261ecSmrg	while(j--) {
79905b261ecSmrg	    (*pScreen->DestroyPixmap)(pMap);
80005b261ecSmrg	    FreeResource(newPix->info[j].id, RT_NONE);
80105b261ecSmrg	}
80205b261ecSmrg	xfree(newPix);
80305b261ecSmrg    } else
80405b261ecSmrg	AddResource(stuff->pid, XRT_PIXMAP, newPix);
80505b261ecSmrg
80605b261ecSmrg    return result;
80705b261ecSmrg}
80805b261ecSmrg
80905b261ecSmrg#endif
81005b261ecSmrg
81105b261ecSmrgstatic int
81205b261ecSmrgProcShmPutImage(client)
81305b261ecSmrg    register ClientPtr client;
81405b261ecSmrg{
81505b261ecSmrg    GCPtr pGC;
81605b261ecSmrg    DrawablePtr pDraw;
81705b261ecSmrg    long length;
81805b261ecSmrg    ShmDescPtr shmdesc;
81905b261ecSmrg    REQUEST(xShmPutImageReq);
82005b261ecSmrg
82105b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
82205b261ecSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
82305b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);
82405b261ecSmrg    if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
82505b261ecSmrg	return BadValue;
82605b261ecSmrg    if (stuff->format == XYBitmap)
82705b261ecSmrg    {
82805b261ecSmrg        if (stuff->depth != 1)
82905b261ecSmrg            return BadMatch;
83005b261ecSmrg        length = PixmapBytePad(stuff->totalWidth, 1);
83105b261ecSmrg    }
83205b261ecSmrg    else if (stuff->format == XYPixmap)
83305b261ecSmrg    {
83405b261ecSmrg        if (pDraw->depth != stuff->depth)
83505b261ecSmrg            return BadMatch;
83605b261ecSmrg        length = PixmapBytePad(stuff->totalWidth, 1);
83705b261ecSmrg	length *= stuff->depth;
83805b261ecSmrg    }
83905b261ecSmrg    else if (stuff->format == ZPixmap)
84005b261ecSmrg    {
84105b261ecSmrg        if (pDraw->depth != stuff->depth)
84205b261ecSmrg            return BadMatch;
84305b261ecSmrg        length = PixmapBytePad(stuff->totalWidth, stuff->depth);
84405b261ecSmrg    }
84505b261ecSmrg    else
84605b261ecSmrg    {
84705b261ecSmrg	client->errorValue = stuff->format;
84805b261ecSmrg        return BadValue;
84905b261ecSmrg    }
85005b261ecSmrg
85105b261ecSmrg    /*
85205b261ecSmrg     * There's a potential integer overflow in this check:
85305b261ecSmrg     * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
85405b261ecSmrg     *                client);
85505b261ecSmrg     * the version below ought to avoid it
85605b261ecSmrg     */
85705b261ecSmrg    if (stuff->totalHeight != 0 &&
85805b261ecSmrg	length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
85905b261ecSmrg	client->errorValue = stuff->totalWidth;
86005b261ecSmrg	return BadValue;
86105b261ecSmrg    }
86205b261ecSmrg    if (stuff->srcX > stuff->totalWidth)
86305b261ecSmrg    {
86405b261ecSmrg	client->errorValue = stuff->srcX;
86505b261ecSmrg	return BadValue;
86605b261ecSmrg    }
86705b261ecSmrg    if (stuff->srcY > stuff->totalHeight)
86805b261ecSmrg    {
86905b261ecSmrg	client->errorValue = stuff->srcY;
87005b261ecSmrg	return BadValue;
87105b261ecSmrg    }
87205b261ecSmrg    if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth)
87305b261ecSmrg    {
87405b261ecSmrg	client->errorValue = stuff->srcWidth;
87505b261ecSmrg	return BadValue;
87605b261ecSmrg    }
87705b261ecSmrg    if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight)
87805b261ecSmrg    {
87905b261ecSmrg	client->errorValue = stuff->srcHeight;
88005b261ecSmrg	return BadValue;
88105b261ecSmrg    }
88205b261ecSmrg
88305b261ecSmrg    if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) ||
88405b261ecSmrg	 ((stuff->format != ZPixmap) &&
88505b261ecSmrg	  (stuff->srcX < screenInfo.bitmapScanlinePad) &&
88605b261ecSmrg	  ((stuff->format == XYBitmap) ||
88705b261ecSmrg	   ((stuff->srcY == 0) &&
88805b261ecSmrg	    (stuff->srcHeight == stuff->totalHeight))))) &&
88905b261ecSmrg	((stuff->srcX + stuff->srcWidth) == stuff->totalWidth))
89005b261ecSmrg	(*pGC->ops->PutImage) (pDraw, pGC, stuff->depth,
89105b261ecSmrg			       stuff->dstX, stuff->dstY,
89205b261ecSmrg			       stuff->totalWidth, stuff->srcHeight,
89305b261ecSmrg			       stuff->srcX, stuff->format,
89405b261ecSmrg			       shmdesc->addr + stuff->offset +
89505b261ecSmrg			       (stuff->srcY * length));
89605b261ecSmrg    else
89705b261ecSmrg	(*shmFuncs[pDraw->pScreen->myNum]->PutImage)(
89805b261ecSmrg			       pDraw, pGC, stuff->depth, stuff->format,
89905b261ecSmrg			       stuff->totalWidth, stuff->totalHeight,
90005b261ecSmrg			       stuff->srcX, stuff->srcY,
90105b261ecSmrg			       stuff->srcWidth, stuff->srcHeight,
90205b261ecSmrg			       stuff->dstX, stuff->dstY,
90305b261ecSmrg                               shmdesc->addr + stuff->offset);
90405b261ecSmrg
90505b261ecSmrg    if (stuff->sendEvent)
90605b261ecSmrg    {
90705b261ecSmrg	xShmCompletionEvent ev;
90805b261ecSmrg
90905b261ecSmrg	ev.type = ShmCompletionCode;
91005b261ecSmrg	ev.drawable = stuff->drawable;
91105b261ecSmrg	ev.sequenceNumber = client->sequence;
91205b261ecSmrg	ev.minorEvent = X_ShmPutImage;
91305b261ecSmrg	ev.majorEvent = ShmReqCode;
91405b261ecSmrg	ev.shmseg = stuff->shmseg;
91505b261ecSmrg	ev.offset = stuff->offset;
91605b261ecSmrg	WriteEventsToClient(client, 1, (xEvent *) &ev);
91705b261ecSmrg    }
91805b261ecSmrg
91905b261ecSmrg    return (client->noClientException);
92005b261ecSmrg}
92105b261ecSmrg
92205b261ecSmrg
92305b261ecSmrg
92405b261ecSmrgstatic int
92505b261ecSmrgProcShmGetImage(client)
92605b261ecSmrg    register ClientPtr client;
92705b261ecSmrg{
92805b261ecSmrg    DrawablePtr		pDraw;
92905b261ecSmrg    long		lenPer = 0, length;
93005b261ecSmrg    Mask		plane = 0;
93105b261ecSmrg    xShmGetImageReply	xgi;
93205b261ecSmrg    ShmDescPtr		shmdesc;
93305b261ecSmrg    int			n, rc;
93405b261ecSmrg
93505b261ecSmrg    REQUEST(xShmGetImageReq);
93605b261ecSmrg
93705b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
93805b261ecSmrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap))
93905b261ecSmrg    {
94005b261ecSmrg	client->errorValue = stuff->format;
94105b261ecSmrg        return(BadValue);
94205b261ecSmrg    }
94305b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
94405b261ecSmrg			   DixUnknownAccess);
94505b261ecSmrg    if (rc != Success)
94605b261ecSmrg	return rc;
94705b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
94805b261ecSmrg    if (pDraw->type == DRAWABLE_WINDOW)
94905b261ecSmrg    {
95005b261ecSmrg      if( /* check for being viewable */
95105b261ecSmrg	 !((WindowPtr) pDraw)->realized ||
95205b261ecSmrg	  /* check for being on screen */
95305b261ecSmrg         pDraw->x + stuff->x < 0 ||
95405b261ecSmrg 	 pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width ||
95505b261ecSmrg         pDraw->y + stuff->y < 0 ||
95605b261ecSmrg         pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height ||
95705b261ecSmrg          /* check for being inside of border */
95805b261ecSmrg         stuff->x < - wBorderWidth((WindowPtr)pDraw) ||
95905b261ecSmrg         stuff->x + (int)stuff->width >
96005b261ecSmrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
96105b261ecSmrg         stuff->y < -wBorderWidth((WindowPtr)pDraw) ||
96205b261ecSmrg         stuff->y + (int)stuff->height >
96305b261ecSmrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height
96405b261ecSmrg        )
96505b261ecSmrg	    return(BadMatch);
96605b261ecSmrg	xgi.visual = wVisual(((WindowPtr)pDraw));
96705b261ecSmrg    }
96805b261ecSmrg    else
96905b261ecSmrg    {
97005b261ecSmrg	if (stuff->x < 0 ||
97105b261ecSmrg	    stuff->x+(int)stuff->width > pDraw->width ||
97205b261ecSmrg	    stuff->y < 0 ||
97305b261ecSmrg	    stuff->y+(int)stuff->height > pDraw->height
97405b261ecSmrg	    )
97505b261ecSmrg	    return(BadMatch);
97605b261ecSmrg	xgi.visual = None;
97705b261ecSmrg    }
97805b261ecSmrg    xgi.type = X_Reply;
97905b261ecSmrg    xgi.length = 0;
98005b261ecSmrg    xgi.sequenceNumber = client->sequence;
98105b261ecSmrg    xgi.depth = pDraw->depth;
98205b261ecSmrg    if(stuff->format == ZPixmap)
98305b261ecSmrg    {
98405b261ecSmrg	length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height;
98505b261ecSmrg    }
98605b261ecSmrg    else
98705b261ecSmrg    {
98805b261ecSmrg	lenPer = PixmapBytePad(stuff->width, 1) * stuff->height;
98905b261ecSmrg	plane = ((Mask)1) << (pDraw->depth - 1);
99005b261ecSmrg	/* only planes asked for */
99105b261ecSmrg	length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1)));
99205b261ecSmrg    }
99305b261ecSmrg
99405b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
99505b261ecSmrg    xgi.size = length;
99605b261ecSmrg
99705b261ecSmrg    if (length == 0)
99805b261ecSmrg    {
99905b261ecSmrg	/* nothing to do */
100005b261ecSmrg    }
100105b261ecSmrg    else if (stuff->format == ZPixmap)
100205b261ecSmrg    {
100305b261ecSmrg	(*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y,
100405b261ecSmrg				    stuff->width, stuff->height,
100505b261ecSmrg				    stuff->format, stuff->planeMask,
100605b261ecSmrg				    shmdesc->addr + stuff->offset);
100705b261ecSmrg    }
100805b261ecSmrg    else
100905b261ecSmrg    {
101005b261ecSmrg
101105b261ecSmrg	length = stuff->offset;
101205b261ecSmrg        for (; plane; plane >>= 1)
101305b261ecSmrg	{
101405b261ecSmrg	    if (stuff->planeMask & plane)
101505b261ecSmrg	    {
101605b261ecSmrg		(*pDraw->pScreen->GetImage)(pDraw,
101705b261ecSmrg					    stuff->x, stuff->y,
101805b261ecSmrg					    stuff->width, stuff->height,
101905b261ecSmrg					    stuff->format, plane,
102005b261ecSmrg					    shmdesc->addr + length);
102105b261ecSmrg		length += lenPer;
102205b261ecSmrg	    }
102305b261ecSmrg	}
102405b261ecSmrg    }
102505b261ecSmrg
102605b261ecSmrg    if (client->swapped) {
102705b261ecSmrg    	swaps(&xgi.sequenceNumber, n);
102805b261ecSmrg    	swapl(&xgi.length, n);
102905b261ecSmrg	swapl(&xgi.visual, n);
103005b261ecSmrg	swapl(&xgi.size, n);
103105b261ecSmrg    }
103205b261ecSmrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
103305b261ecSmrg
103405b261ecSmrg    return(client->noClientException);
103505b261ecSmrg}
103605b261ecSmrg
103705b261ecSmrgstatic PixmapPtr
103805b261ecSmrgfbShmCreatePixmap (pScreen, width, height, depth, addr)
103905b261ecSmrg    ScreenPtr	pScreen;
104005b261ecSmrg    int		width;
104105b261ecSmrg    int		height;
104205b261ecSmrg    int		depth;
104305b261ecSmrg    char	*addr;
104405b261ecSmrg{
104505b261ecSmrg    register PixmapPtr pPixmap;
104605b261ecSmrg
104705b261ecSmrg    pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth);
104805b261ecSmrg    if (!pPixmap)
104905b261ecSmrg	return NullPixmap;
105005b261ecSmrg
105105b261ecSmrg    if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
105205b261ecSmrg	    BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) {
105305b261ecSmrg	(*pScreen->DestroyPixmap)(pPixmap);
105405b261ecSmrg	return NullPixmap;
105505b261ecSmrg    }
105605b261ecSmrg    return pPixmap;
105705b261ecSmrg}
105805b261ecSmrg
105905b261ecSmrgstatic int
106005b261ecSmrgProcShmCreatePixmap(client)
106105b261ecSmrg    register ClientPtr client;
106205b261ecSmrg{
106305b261ecSmrg    PixmapPtr pMap;
106405b261ecSmrg    DrawablePtr pDraw;
106505b261ecSmrg    DepthPtr pDepth;
106605b261ecSmrg    register int i, rc;
106705b261ecSmrg    ShmDescPtr shmdesc;
106805b261ecSmrg    REQUEST(xShmCreatePixmapReq);
106905b261ecSmrg    unsigned int width, height, depth;
107005b261ecSmrg    unsigned long size;
107105b261ecSmrg
107205b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
107305b261ecSmrg    client->errorValue = stuff->pid;
107405b261ecSmrg    if (!sharedPixmaps)
107505b261ecSmrg	return BadImplementation;
107605b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
107705b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
107805b261ecSmrg			   DixUnknownAccess);
107905b261ecSmrg    if (rc != Success)
108005b261ecSmrg	return rc;
108105b261ecSmrg
108205b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
108305b261ecSmrg
108405b261ecSmrg    width = stuff->width;
108505b261ecSmrg    height = stuff->height;
108605b261ecSmrg    depth = stuff->depth;
108705b261ecSmrg    if (!width || !height || !depth)
108805b261ecSmrg    {
108905b261ecSmrg	client->errorValue = 0;
109005b261ecSmrg        return BadValue;
109105b261ecSmrg    }
109205b261ecSmrg    if (width > 32767 || height > 32767)
109305b261ecSmrg	return BadAlloc;
109405b261ecSmrg
109505b261ecSmrg    if (stuff->depth != 1)
109605b261ecSmrg    {
109705b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
109805b261ecSmrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
109905b261ecSmrg	   if (pDepth->depth == stuff->depth)
110005b261ecSmrg               goto CreatePmap;
110105b261ecSmrg	client->errorValue = stuff->depth;
110205b261ecSmrg        return BadValue;
110305b261ecSmrg    }
110405b261ecSmrg
110505b261ecSmrgCreatePmap:
110605b261ecSmrg    size = PixmapBytePad(width, depth) * height;
110705b261ecSmrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
110805b261ecSmrg	if (size < width * height)
110905b261ecSmrg	    return BadAlloc;
111005b261ecSmrg    }
111105b261ecSmrg    /* thankfully, offset is unsigned */
111205b261ecSmrg    if (stuff->offset + size < size)
111305b261ecSmrg	return BadAlloc;
111405b261ecSmrg
111505b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
111605b261ecSmrg    pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)(
111705b261ecSmrg			    pDraw->pScreen, stuff->width,
111805b261ecSmrg			    stuff->height, stuff->depth,
111905b261ecSmrg			    shmdesc->addr + stuff->offset);
112005b261ecSmrg    if (pMap)
112105b261ecSmrg    {
112205b261ecSmrg	pMap->devPrivates[shmPixmapPrivate].ptr = (pointer) shmdesc;
112305b261ecSmrg	shmdesc->refcnt++;
112405b261ecSmrg	pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
112505b261ecSmrg	pMap->drawable.id = stuff->pid;
112605b261ecSmrg	if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
112705b261ecSmrg	{
112805b261ecSmrg	    return(client->noClientException);
112905b261ecSmrg	}
113005b261ecSmrg    }
113105b261ecSmrg    return (BadAlloc);
113205b261ecSmrg}
113305b261ecSmrg
113405b261ecSmrgstatic int
113505b261ecSmrgProcShmDispatch (client)
113605b261ecSmrg    register ClientPtr	client;
113705b261ecSmrg{
113805b261ecSmrg    REQUEST(xReq);
113905b261ecSmrg    switch (stuff->data)
114005b261ecSmrg    {
114105b261ecSmrg    case X_ShmQueryVersion:
114205b261ecSmrg	return ProcShmQueryVersion(client);
114305b261ecSmrg    case X_ShmAttach:
114405b261ecSmrg	return ProcShmAttach(client);
114505b261ecSmrg    case X_ShmDetach:
114605b261ecSmrg	return ProcShmDetach(client);
114705b261ecSmrg    case X_ShmPutImage:
114805b261ecSmrg#ifdef PANORAMIX
114905b261ecSmrg        if ( !noPanoramiXExtension )
115005b261ecSmrg	   return ProcPanoramiXShmPutImage(client);
115105b261ecSmrg#endif
115205b261ecSmrg	return ProcShmPutImage(client);
115305b261ecSmrg    case X_ShmGetImage:
115405b261ecSmrg#ifdef PANORAMIX
115505b261ecSmrg        if ( !noPanoramiXExtension )
115605b261ecSmrg	   return ProcPanoramiXShmGetImage(client);
115705b261ecSmrg#endif
115805b261ecSmrg	return ProcShmGetImage(client);
115905b261ecSmrg    case X_ShmCreatePixmap:
116005b261ecSmrg#ifdef PANORAMIX
116105b261ecSmrg        if ( !noPanoramiXExtension )
116205b261ecSmrg	   return ProcPanoramiXShmCreatePixmap(client);
116305b261ecSmrg#endif
116405b261ecSmrg	   return ProcShmCreatePixmap(client);
116505b261ecSmrg    default:
116605b261ecSmrg	return BadRequest;
116705b261ecSmrg    }
116805b261ecSmrg}
116905b261ecSmrg
117005b261ecSmrgstatic void
117105b261ecSmrgSShmCompletionEvent(from, to)
117205b261ecSmrg    xShmCompletionEvent *from, *to;
117305b261ecSmrg{
117405b261ecSmrg    to->type = from->type;
117505b261ecSmrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
117605b261ecSmrg    cpswapl(from->drawable, to->drawable);
117705b261ecSmrg    cpswaps(from->minorEvent, to->minorEvent);
117805b261ecSmrg    to->majorEvent = from->majorEvent;
117905b261ecSmrg    cpswapl(from->shmseg, to->shmseg);
118005b261ecSmrg    cpswapl(from->offset, to->offset);
118105b261ecSmrg}
118205b261ecSmrg
118305b261ecSmrgstatic int
118405b261ecSmrgSProcShmQueryVersion(client)
118505b261ecSmrg    register ClientPtr	client;
118605b261ecSmrg{
118705b261ecSmrg    register int n;
118805b261ecSmrg    REQUEST(xShmQueryVersionReq);
118905b261ecSmrg
119005b261ecSmrg    swaps(&stuff->length, n);
119105b261ecSmrg    return ProcShmQueryVersion(client);
119205b261ecSmrg}
119305b261ecSmrg
119405b261ecSmrgstatic int
119505b261ecSmrgSProcShmAttach(client)
119605b261ecSmrg    ClientPtr client;
119705b261ecSmrg{
119805b261ecSmrg    register int n;
119905b261ecSmrg    REQUEST(xShmAttachReq);
120005b261ecSmrg    swaps(&stuff->length, n);
120105b261ecSmrg    REQUEST_SIZE_MATCH(xShmAttachReq);
120205b261ecSmrg    swapl(&stuff->shmseg, n);
120305b261ecSmrg    swapl(&stuff->shmid, n);
120405b261ecSmrg    return ProcShmAttach(client);
120505b261ecSmrg}
120605b261ecSmrg
120705b261ecSmrgstatic int
120805b261ecSmrgSProcShmDetach(client)
120905b261ecSmrg    ClientPtr client;
121005b261ecSmrg{
121105b261ecSmrg    register int n;
121205b261ecSmrg    REQUEST(xShmDetachReq);
121305b261ecSmrg    swaps(&stuff->length, n);
121405b261ecSmrg    REQUEST_SIZE_MATCH(xShmDetachReq);
121505b261ecSmrg    swapl(&stuff->shmseg, n);
121605b261ecSmrg    return ProcShmDetach(client);
121705b261ecSmrg}
121805b261ecSmrg
121905b261ecSmrgstatic int
122005b261ecSmrgSProcShmPutImage(client)
122105b261ecSmrg    ClientPtr client;
122205b261ecSmrg{
122305b261ecSmrg    register int n;
122405b261ecSmrg    REQUEST(xShmPutImageReq);
122505b261ecSmrg    swaps(&stuff->length, n);
122605b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
122705b261ecSmrg    swapl(&stuff->drawable, n);
122805b261ecSmrg    swapl(&stuff->gc, n);
122905b261ecSmrg    swaps(&stuff->totalWidth, n);
123005b261ecSmrg    swaps(&stuff->totalHeight, n);
123105b261ecSmrg    swaps(&stuff->srcX, n);
123205b261ecSmrg    swaps(&stuff->srcY, n);
123305b261ecSmrg    swaps(&stuff->srcWidth, n);
123405b261ecSmrg    swaps(&stuff->srcHeight, n);
123505b261ecSmrg    swaps(&stuff->dstX, n);
123605b261ecSmrg    swaps(&stuff->dstY, n);
123705b261ecSmrg    swapl(&stuff->shmseg, n);
123805b261ecSmrg    swapl(&stuff->offset, n);
123905b261ecSmrg    return ProcShmPutImage(client);
124005b261ecSmrg}
124105b261ecSmrg
124205b261ecSmrgstatic int
124305b261ecSmrgSProcShmGetImage(client)
124405b261ecSmrg    ClientPtr client;
124505b261ecSmrg{
124605b261ecSmrg    register int n;
124705b261ecSmrg    REQUEST(xShmGetImageReq);
124805b261ecSmrg    swaps(&stuff->length, n);
124905b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
125005b261ecSmrg    swapl(&stuff->drawable, n);
125105b261ecSmrg    swaps(&stuff->x, n);
125205b261ecSmrg    swaps(&stuff->y, n);
125305b261ecSmrg    swaps(&stuff->width, n);
125405b261ecSmrg    swaps(&stuff->height, n);
125505b261ecSmrg    swapl(&stuff->planeMask, n);
125605b261ecSmrg    swapl(&stuff->shmseg, n);
125705b261ecSmrg    swapl(&stuff->offset, n);
125805b261ecSmrg    return ProcShmGetImage(client);
125905b261ecSmrg}
126005b261ecSmrg
126105b261ecSmrgstatic int
126205b261ecSmrgSProcShmCreatePixmap(client)
126305b261ecSmrg    ClientPtr client;
126405b261ecSmrg{
126505b261ecSmrg    register int n;
126605b261ecSmrg    REQUEST(xShmCreatePixmapReq);
126705b261ecSmrg    swaps(&stuff->length, n);
126805b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
126905b261ecSmrg    swapl(&stuff->pid, n);
127005b261ecSmrg    swapl(&stuff->drawable, n);
127105b261ecSmrg    swaps(&stuff->width, n);
127205b261ecSmrg    swaps(&stuff->height, n);
127305b261ecSmrg    swapl(&stuff->shmseg, n);
127405b261ecSmrg    swapl(&stuff->offset, n);
127505b261ecSmrg    return ProcShmCreatePixmap(client);
127605b261ecSmrg}
127705b261ecSmrg
127805b261ecSmrgstatic int
127905b261ecSmrgSProcShmDispatch (client)
128005b261ecSmrg    register ClientPtr	client;
128105b261ecSmrg{
128205b261ecSmrg    REQUEST(xReq);
128305b261ecSmrg    switch (stuff->data)
128405b261ecSmrg    {
128505b261ecSmrg    case X_ShmQueryVersion:
128605b261ecSmrg	return SProcShmQueryVersion(client);
128705b261ecSmrg    case X_ShmAttach:
128805b261ecSmrg	return SProcShmAttach(client);
128905b261ecSmrg    case X_ShmDetach:
129005b261ecSmrg	return SProcShmDetach(client);
129105b261ecSmrg    case X_ShmPutImage:
129205b261ecSmrg	return SProcShmPutImage(client);
129305b261ecSmrg    case X_ShmGetImage:
129405b261ecSmrg	return SProcShmGetImage(client);
129505b261ecSmrg    case X_ShmCreatePixmap:
129605b261ecSmrg	return SProcShmCreatePixmap(client);
129705b261ecSmrg    default:
129805b261ecSmrg	return BadRequest;
129905b261ecSmrg    }
130005b261ecSmrg}
1301