shm.c revision 4202a189
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#include <sys/ipc.h>
3805b261ecSmrg#include <sys/shm.h>
3905b261ecSmrg#include <unistd.h>
4005b261ecSmrg#include <sys/stat.h>
4105b261ecSmrg#include <X11/X.h>
4205b261ecSmrg#include <X11/Xproto.h>
4305b261ecSmrg#include "misc.h"
4405b261ecSmrg#include "os.h"
4505b261ecSmrg#include "dixstruct.h"
4605b261ecSmrg#include "resource.h"
4705b261ecSmrg#include "scrnintstr.h"
4805b261ecSmrg#include "windowstr.h"
4905b261ecSmrg#include "pixmapstr.h"
5005b261ecSmrg#include "gcstruct.h"
5105b261ecSmrg#include "extnsionst.h"
5205b261ecSmrg#include "servermd.h"
534642e01fSmrg#include "shmint.h"
544642e01fSmrg#include "xace.h"
55684baedfSmrg#include <X11/extensions/shmproto.h>
5605b261ecSmrg#include <X11/Xfuncproto.h>
574202a189Smrg#include "protocol-versions.h"
5805b261ecSmrg
594642e01fSmrg/* Needed for Solaris cross-zone shared memory extension */
604642e01fSmrg#ifdef HAVE_SHMCTL64
614642e01fSmrg#include <sys/ipc_impl.h>
624642e01fSmrg#define SHMSTAT(id, buf)	shmctl64(id, IPC_STAT64, buf)
634642e01fSmrg#define SHMSTAT_TYPE 		struct shmid_ds64
644642e01fSmrg#define SHMPERM_TYPE 		struct ipc_perm64
654642e01fSmrg#define SHM_PERM(buf) 		buf.shmx_perm
664642e01fSmrg#define SHM_SEGSZ(buf)		buf.shmx_segsz
674642e01fSmrg#define SHMPERM_UID(p)		p->ipcx_uid
684642e01fSmrg#define SHMPERM_CUID(p)		p->ipcx_cuid
694642e01fSmrg#define SHMPERM_GID(p)		p->ipcx_gid
704642e01fSmrg#define SHMPERM_CGID(p)		p->ipcx_cgid
714642e01fSmrg#define SHMPERM_MODE(p)		p->ipcx_mode
724642e01fSmrg#define SHMPERM_ZONEID(p)	p->ipcx_zoneid
734642e01fSmrg#else
744642e01fSmrg#define SHMSTAT(id, buf) 	shmctl(id, IPC_STAT, buf)
754642e01fSmrg#define SHMSTAT_TYPE 		struct shmid_ds
764642e01fSmrg#define SHMPERM_TYPE 		struct ipc_perm
774642e01fSmrg#define SHM_PERM(buf) 		buf.shm_perm
784642e01fSmrg#define SHM_SEGSZ(buf)		buf.shm_segsz
794642e01fSmrg#define SHMPERM_UID(p)		p->uid
804642e01fSmrg#define SHMPERM_CUID(p)		p->cuid
814642e01fSmrg#define SHMPERM_GID(p)		p->gid
824642e01fSmrg#define SHMPERM_CGID(p)		p->cgid
834642e01fSmrg#define SHMPERM_MODE(p)		p->mode
844642e01fSmrg#endif
854642e01fSmrg
8605b261ecSmrg#ifdef PANORAMIX
8705b261ecSmrg#include "panoramiX.h"
8805b261ecSmrg#include "panoramiXsrv.h"
8905b261ecSmrg#endif
9005b261ecSmrg
9105b261ecSmrg#include "modinit.h"
9205b261ecSmrg
9305b261ecSmrgtypedef struct _ShmDesc {
9405b261ecSmrg    struct _ShmDesc *next;
9505b261ecSmrg    int shmid;
9605b261ecSmrg    int refcnt;
9705b261ecSmrg    char *addr;
9805b261ecSmrg    Bool writable;
9905b261ecSmrg    unsigned long size;
10005b261ecSmrg} ShmDescRec, *ShmDescPtr;
10105b261ecSmrg
1024202a189Smrgtypedef struct _ShmScrPrivateRec {
1034202a189Smrg    CloseScreenProcPtr CloseScreen;
1044202a189Smrg    ShmFuncsPtr shmFuncs;
1054202a189Smrg    DestroyPixmapProcPtr destroyPixmap;
1064202a189Smrg} ShmScrPrivateRec;
1074202a189Smrg
10805b261ecSmrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS);
10905b261ecSmrgstatic int ShmDetachSegment(
11005b261ecSmrg    pointer		/* value */,
11105b261ecSmrg    XID			/* shmseg */
11205b261ecSmrg    );
11305b261ecSmrgstatic void ShmResetProc(
11405b261ecSmrg    ExtensionEntry *	/* extEntry */
11505b261ecSmrg    );
11605b261ecSmrgstatic void SShmCompletionEvent(
11705b261ecSmrg    xShmCompletionEvent * /* from */,
11805b261ecSmrg    xShmCompletionEvent * /* to */
11905b261ecSmrg    );
12005b261ecSmrg
12105b261ecSmrgstatic Bool ShmDestroyPixmap (PixmapPtr pPixmap);
12205b261ecSmrg
12305b261ecSmrgstatic DISPATCH_PROC(ProcShmAttach);
12405b261ecSmrgstatic DISPATCH_PROC(ProcShmCreatePixmap);
12505b261ecSmrgstatic DISPATCH_PROC(ProcShmDetach);
12605b261ecSmrgstatic DISPATCH_PROC(ProcShmDispatch);
12705b261ecSmrgstatic DISPATCH_PROC(ProcShmGetImage);
12805b261ecSmrgstatic DISPATCH_PROC(ProcShmPutImage);
12905b261ecSmrgstatic DISPATCH_PROC(ProcShmQueryVersion);
13005b261ecSmrgstatic DISPATCH_PROC(SProcShmAttach);
13105b261ecSmrgstatic DISPATCH_PROC(SProcShmCreatePixmap);
13205b261ecSmrgstatic DISPATCH_PROC(SProcShmDetach);
13305b261ecSmrgstatic DISPATCH_PROC(SProcShmDispatch);
13405b261ecSmrgstatic DISPATCH_PROC(SProcShmGetImage);
13505b261ecSmrgstatic DISPATCH_PROC(SProcShmPutImage);
13605b261ecSmrgstatic DISPATCH_PROC(SProcShmQueryVersion);
13705b261ecSmrg
13805b261ecSmrgstatic unsigned char ShmReqCode;
1394202a189Smrgint ShmCompletionCode;
1404202a189Smrgint BadShmSegCode;
1414202a189SmrgRESTYPE ShmSegType;
14205b261ecSmrgstatic ShmDescPtr Shmsegs;
14305b261ecSmrgstatic Bool sharedPixmaps;
1444202a189Smrgstatic DevPrivateKeyRec shmScrPrivateKeyRec;
1454202a189Smrg#define shmScrPrivateKey (&shmScrPrivateKeyRec)
1464202a189Smrgstatic DevPrivateKeyRec shmPixmapPrivateKeyRec;
1474202a189Smrg#define shmPixmapPrivateKey (&shmPixmapPrivateKeyRec)
1484642e01fSmrgstatic ShmFuncs miFuncs = {NULL, NULL};
1494642e01fSmrgstatic ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL};
15005b261ecSmrg
1514202a189Smrg#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey))
1524202a189Smrg
15305b261ecSmrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
15405b261ecSmrg{ \
1554202a189Smrg    int rc; \
1564202a189Smrg    rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \
1574202a189Smrg                                 client, DixReadAccess); \
1584202a189Smrg    if (rc != Success) \
1594202a189Smrg	return rc; \
16005b261ecSmrg}
16105b261ecSmrg
16205b261ecSmrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
16305b261ecSmrg{ \
16405b261ecSmrg    VERIFY_SHMSEG(shmseg, shmdesc, client); \
16505b261ecSmrg    if ((offset & 3) || (offset > shmdesc->size)) \
16605b261ecSmrg    { \
16705b261ecSmrg	client->errorValue = offset; \
16805b261ecSmrg	return BadValue; \
16905b261ecSmrg    } \
17005b261ecSmrg    if (needwrite && !shmdesc->writable) \
17105b261ecSmrg	return BadAccess; \
17205b261ecSmrg}
17305b261ecSmrg
17405b261ecSmrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
17505b261ecSmrg{ \
17605b261ecSmrg    if ((offset + len) > shmdesc->size) \
17705b261ecSmrg    { \
17805b261ecSmrg	return BadAccess; \
17905b261ecSmrg    } \
18005b261ecSmrg}
18105b261ecSmrg
18205b261ecSmrg
18305b261ecSmrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
18405b261ecSmrg#include <sys/signal.h>
18505b261ecSmrg
18605b261ecSmrgstatic Bool badSysCall = FALSE;
18705b261ecSmrg
18805b261ecSmrgstatic void
1894642e01fSmrgSigSysHandler(int signo)
19005b261ecSmrg{
19105b261ecSmrg    badSysCall = TRUE;
19205b261ecSmrg}
19305b261ecSmrg
1944642e01fSmrgstatic Bool CheckForShmSyscall(void)
19505b261ecSmrg{
19605b261ecSmrg    void (*oldHandler)();
19705b261ecSmrg    int shmid = -1;
19805b261ecSmrg
19905b261ecSmrg    /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
20005b261ecSmrg    oldHandler = signal(SIGSYS, SigSysHandler);
20105b261ecSmrg
20205b261ecSmrg    badSysCall = FALSE;
20305b261ecSmrg    shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
20405b261ecSmrg
20505b261ecSmrg    if (shmid != -1)
20605b261ecSmrg    {
20705b261ecSmrg        /* Successful allocation - clean up */
2084202a189Smrg	shmctl(shmid, IPC_RMID, NULL);
20905b261ecSmrg    }
21005b261ecSmrg    else
21105b261ecSmrg    {
21205b261ecSmrg        /* Allocation failed */
21305b261ecSmrg        badSysCall = TRUE;
21405b261ecSmrg    }
21505b261ecSmrg    signal(SIGSYS, oldHandler);
2164202a189Smrg    return !badSysCall;
21705b261ecSmrg}
21805b261ecSmrg
21905b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL
22005b261ecSmrg
22105b261ecSmrg#endif
22205b261ecSmrg
2234202a189Smrgstatic Bool
2244202a189SmrgShmCloseScreen(int i, ScreenPtr pScreen)
2254202a189Smrg{
2264202a189Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
2274202a189Smrg    pScreen->CloseScreen = screen_priv->CloseScreen;
2284202a189Smrg    dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL);
2294202a189Smrg    free(screen_priv);
2304202a189Smrg    return (*pScreen->CloseScreen) (i, pScreen);
2314202a189Smrg}
2324202a189Smrg
2334202a189Smrgstatic ShmScrPrivateRec *
2344202a189SmrgShmInitScreenPriv(ScreenPtr pScreen)
2354202a189Smrg{
2364202a189Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
2374202a189Smrg    if (!screen_priv)
2384202a189Smrg    {
2394202a189Smrg	screen_priv = calloc(1, sizeof (ShmScrPrivateRec));
2404202a189Smrg	screen_priv->CloseScreen = pScreen->CloseScreen;
2414202a189Smrg	dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv);
2424202a189Smrg	pScreen->CloseScreen = ShmCloseScreen;
2434202a189Smrg    }
2444202a189Smrg    return screen_priv;
2454202a189Smrg}
2464202a189Smrg
2474202a189Smrgstatic Bool
2484202a189SmrgShmRegisterPrivates(void)
2494202a189Smrg{
2504202a189Smrg    if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec, PRIVATE_SCREEN, 0))
2514202a189Smrg	return FALSE;
2524202a189Smrg    if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec, PRIVATE_PIXMAP, 0))
2534202a189Smrg	return FALSE;
2544202a189Smrg    return TRUE;
2554202a189Smrg}
2564202a189Smrg
25705b261ecSmrgvoid
25805b261ecSmrgShmExtensionInit(INITARGS)
25905b261ecSmrg{
26005b261ecSmrg    ExtensionEntry *extEntry;
26105b261ecSmrg    int i;
26205b261ecSmrg
26305b261ecSmrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL
26405b261ecSmrg    if (!CheckForShmSyscall())
26505b261ecSmrg    {
26605b261ecSmrg	ErrorF("MIT-SHM extension disabled due to lack of kernel support\n");
26705b261ecSmrg	return;
26805b261ecSmrg    }
26905b261ecSmrg#endif
27005b261ecSmrg
2714202a189Smrg    if (!ShmRegisterPrivates())
2724202a189Smrg	return;
2734202a189Smrg
27405b261ecSmrg    sharedPixmaps = xFalse;
27505b261ecSmrg    {
27605b261ecSmrg      sharedPixmaps = xTrue;
27705b261ecSmrg      for (i = 0; i < screenInfo.numScreens; i++)
27805b261ecSmrg      {
2794202a189Smrg	ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]);
2804202a189Smrg	if (!screen_priv->shmFuncs)
2814202a189Smrg	    screen_priv->shmFuncs = &miFuncs;
2824202a189Smrg	if (!screen_priv->shmFuncs->CreatePixmap)
28305b261ecSmrg	    sharedPixmaps = xFalse;
28405b261ecSmrg      }
28505b261ecSmrg      if (sharedPixmaps)
28605b261ecSmrg	for (i = 0; i < screenInfo.numScreens; i++)
28705b261ecSmrg	{
2884202a189Smrg	    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]);
2894202a189Smrg	    screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap;
29005b261ecSmrg	    screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap;
29105b261ecSmrg	}
29205b261ecSmrg    }
2934202a189Smrg    ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg");
29405b261ecSmrg    if (ShmSegType &&
29505b261ecSmrg	(extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors,
29605b261ecSmrg				 ProcShmDispatch, SProcShmDispatch,
29705b261ecSmrg				 ShmResetProc, StandardMinorOpcode)))
29805b261ecSmrg    {
29905b261ecSmrg	ShmReqCode = (unsigned char)extEntry->base;
30005b261ecSmrg	ShmCompletionCode = extEntry->eventBase;
30105b261ecSmrg	BadShmSegCode = extEntry->errorBase;
3024202a189Smrg	SetResourceTypeErrorValue(ShmSegType, BadShmSegCode);
30305b261ecSmrg	EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent;
30405b261ecSmrg    }
30505b261ecSmrg}
30605b261ecSmrg
30705b261ecSmrg/*ARGSUSED*/
30805b261ecSmrgstatic void
3094642e01fSmrgShmResetProc(ExtensionEntry *extEntry)
31005b261ecSmrg{
31105b261ecSmrg    int i;
3124202a189Smrg    for (i = 0; i < screenInfo.numScreens; i++)
3134202a189Smrg	ShmRegisterFuncs(screenInfo.screens[i], NULL);
31405b261ecSmrg}
31505b261ecSmrg
3164202a189Smrgvoid
3174642e01fSmrgShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs)
31805b261ecSmrg{
3194202a189Smrg    if (!ShmRegisterPrivates())
3204202a189Smrg	return;
3214202a189Smrg    ShmInitScreenPriv(pScreen)->shmFuncs = funcs;
32205b261ecSmrg}
32305b261ecSmrg
32405b261ecSmrgstatic Bool
32505b261ecSmrgShmDestroyPixmap (PixmapPtr pPixmap)
32605b261ecSmrg{
32705b261ecSmrg    ScreenPtr	    pScreen = pPixmap->drawable.pScreen;
3284202a189Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
32905b261ecSmrg    Bool	    ret;
33005b261ecSmrg    if (pPixmap->refcnt == 1)
33105b261ecSmrg    {
33205b261ecSmrg	ShmDescPtr  shmdesc;
3334642e01fSmrg	shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates,
3344202a189Smrg					       shmPixmapPrivateKey);
33505b261ecSmrg	if (shmdesc)
33605b261ecSmrg	    ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id);
33705b261ecSmrg    }
33805b261ecSmrg
3394202a189Smrg    pScreen->DestroyPixmap = screen_priv->destroyPixmap;
34005b261ecSmrg    ret = (*pScreen->DestroyPixmap) (pPixmap);
3414202a189Smrg    screen_priv->destroyPixmap = pScreen->DestroyPixmap;
34205b261ecSmrg    pScreen->DestroyPixmap = ShmDestroyPixmap;
34305b261ecSmrg    return ret;
34405b261ecSmrg}
34505b261ecSmrg
3464202a189Smrgvoid
3474642e01fSmrgShmRegisterFbFuncs(ScreenPtr pScreen)
34805b261ecSmrg{
3494202a189Smrg    ShmRegisterFuncs(pScreen, &fbFuncs);
35005b261ecSmrg}
35105b261ecSmrg
35205b261ecSmrgstatic int
3534642e01fSmrgProcShmQueryVersion(ClientPtr client)
35405b261ecSmrg{
35505b261ecSmrg    xShmQueryVersionReply rep;
3564642e01fSmrg    int n;
35705b261ecSmrg
35805b261ecSmrg    REQUEST_SIZE_MATCH(xShmQueryVersionReq);
3594202a189Smrg    memset(&rep, 0, sizeof(xShmQueryVersionReply));
36005b261ecSmrg    rep.type = X_Reply;
36105b261ecSmrg    rep.length = 0;
36205b261ecSmrg    rep.sequenceNumber = client->sequence;
36305b261ecSmrg    rep.sharedPixmaps = sharedPixmaps;
3644642e01fSmrg    rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0;
3654202a189Smrg    rep.majorVersion = SERVER_SHM_MAJOR_VERSION;
3664202a189Smrg    rep.minorVersion = SERVER_SHM_MINOR_VERSION;
36705b261ecSmrg    rep.uid = geteuid();
36805b261ecSmrg    rep.gid = getegid();
36905b261ecSmrg    if (client->swapped) {
37005b261ecSmrg    	swaps(&rep.sequenceNumber, n);
37105b261ecSmrg    	swapl(&rep.length, n);
37205b261ecSmrg	swaps(&rep.majorVersion, n);
37305b261ecSmrg	swaps(&rep.minorVersion, n);
37405b261ecSmrg	swaps(&rep.uid, n);
37505b261ecSmrg	swaps(&rep.gid, n);
37605b261ecSmrg    }
37705b261ecSmrg    WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep);
3784202a189Smrg    return Success;
37905b261ecSmrg}
38005b261ecSmrg
38105b261ecSmrg/*
38205b261ecSmrg * Simulate the access() system call for a shared memory segement,
38305b261ecSmrg * using the credentials from the client if available
38405b261ecSmrg */
38505b261ecSmrgstatic int
3864642e01fSmrgshm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly)
38705b261ecSmrg{
38805b261ecSmrg    int uid, gid;
38905b261ecSmrg    mode_t mask;
3904642e01fSmrg    int uidset = 0, gidset = 0;
3914642e01fSmrg    LocalClientCredRec *lcc;
3924642e01fSmrg
3934642e01fSmrg    if (GetLocalClientCreds(client, &lcc) != -1) {
39405b261ecSmrg
3954642e01fSmrg	if (lcc->fieldsSet & LCC_UID_SET) {
3964642e01fSmrg	    uid = lcc->euid;
3974642e01fSmrg	    uidset = 1;
3984642e01fSmrg	}
3994642e01fSmrg	if (lcc->fieldsSet & LCC_GID_SET) {
4004642e01fSmrg	    gid = lcc->egid;
4014642e01fSmrg	    gidset = 1;
4024642e01fSmrg	}
4034642e01fSmrg
4044642e01fSmrg#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID)
4054642e01fSmrg	if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1)
4064642e01fSmrg	     || (lcc->zoneid != SHMPERM_ZONEID(perm))) {
4074642e01fSmrg		uidset = 0;
4084642e01fSmrg		gidset = 0;
40905b261ecSmrg	}
4104642e01fSmrg#endif
4114642e01fSmrg	FreeLocalClientCreds(lcc);
4124642e01fSmrg
4134642e01fSmrg	if (uidset) {
4144642e01fSmrg	    /* User id 0 always gets access */
4154642e01fSmrg	    if (uid == 0) {
4164642e01fSmrg		return 0;
4174642e01fSmrg	    }
4184642e01fSmrg	    /* Check the owner */
4194642e01fSmrg	    if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) {
4204642e01fSmrg		mask = S_IRUSR;
4214642e01fSmrg		if (!readonly) {
4224642e01fSmrg		    mask |= S_IWUSR;
4234642e01fSmrg		}
4244642e01fSmrg		return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
42505b261ecSmrg	    }
42605b261ecSmrg	}
4274642e01fSmrg
4284642e01fSmrg	if (gidset) {
4294642e01fSmrg	    /* Check the group */
4304642e01fSmrg	    if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) {
4314642e01fSmrg		mask = S_IRGRP;
4324642e01fSmrg		if (!readonly) {
4334642e01fSmrg		    mask |= S_IWGRP;
4344642e01fSmrg		}
4354642e01fSmrg		return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
43605b261ecSmrg	    }
43705b261ecSmrg	}
43805b261ecSmrg    }
43905b261ecSmrg    /* Otherwise, check everyone else */
44005b261ecSmrg    mask = S_IROTH;
44105b261ecSmrg    if (!readonly) {
44205b261ecSmrg	mask |= S_IWOTH;
44305b261ecSmrg    }
4444642e01fSmrg    return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
44505b261ecSmrg}
44605b261ecSmrg
44705b261ecSmrgstatic int
4484642e01fSmrgProcShmAttach(ClientPtr client)
44905b261ecSmrg{
4504642e01fSmrg    SHMSTAT_TYPE buf;
45105b261ecSmrg    ShmDescPtr shmdesc;
45205b261ecSmrg    REQUEST(xShmAttachReq);
45305b261ecSmrg
45405b261ecSmrg    REQUEST_SIZE_MATCH(xShmAttachReq);
45505b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->shmseg, client);
45605b261ecSmrg    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse))
45705b261ecSmrg    {
45805b261ecSmrg	client->errorValue = stuff->readOnly;
4594202a189Smrg        return BadValue;
46005b261ecSmrg    }
46105b261ecSmrg    for (shmdesc = Shmsegs;
46205b261ecSmrg	 shmdesc && (shmdesc->shmid != stuff->shmid);
46305b261ecSmrg	 shmdesc = shmdesc->next)
46405b261ecSmrg	;
46505b261ecSmrg    if (shmdesc)
46605b261ecSmrg    {
46705b261ecSmrg	if (!stuff->readOnly && !shmdesc->writable)
46805b261ecSmrg	    return BadAccess;
46905b261ecSmrg	shmdesc->refcnt++;
47005b261ecSmrg    }
47105b261ecSmrg    else
47205b261ecSmrg    {
4734202a189Smrg	shmdesc = malloc(sizeof(ShmDescRec));
47405b261ecSmrg	if (!shmdesc)
47505b261ecSmrg	    return BadAlloc;
47605b261ecSmrg	shmdesc->addr = shmat(stuff->shmid, 0,
47705b261ecSmrg			      stuff->readOnly ? SHM_RDONLY : 0);
47805b261ecSmrg	if ((shmdesc->addr == ((char *)-1)) ||
4794642e01fSmrg	    SHMSTAT(stuff->shmid, &buf))
48005b261ecSmrg	{
4814202a189Smrg	    free(shmdesc);
48205b261ecSmrg	    return BadAccess;
48305b261ecSmrg	}
48405b261ecSmrg
48505b261ecSmrg	/* The attach was performed with root privs. We must
48605b261ecSmrg	 * do manual checking of access rights for the credentials
48705b261ecSmrg	 * of the client */
48805b261ecSmrg
4894642e01fSmrg	if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) {
49005b261ecSmrg	    shmdt(shmdesc->addr);
4914202a189Smrg	    free(shmdesc);
49205b261ecSmrg	    return BadAccess;
49305b261ecSmrg	}
49405b261ecSmrg
49505b261ecSmrg	shmdesc->shmid = stuff->shmid;
49605b261ecSmrg	shmdesc->refcnt = 1;
49705b261ecSmrg	shmdesc->writable = !stuff->readOnly;
4984642e01fSmrg	shmdesc->size = SHM_SEGSZ(buf);
49905b261ecSmrg	shmdesc->next = Shmsegs;
50005b261ecSmrg	Shmsegs = shmdesc;
50105b261ecSmrg    }
50205b261ecSmrg    if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc))
50305b261ecSmrg	return BadAlloc;
5044202a189Smrg    return Success;
50505b261ecSmrg}
50605b261ecSmrg
50705b261ecSmrg/*ARGSUSED*/
50805b261ecSmrgstatic int
5094642e01fSmrgShmDetachSegment(pointer value, /* must conform to DeleteType */
5104642e01fSmrg		 XID shmseg)
51105b261ecSmrg{
51205b261ecSmrg    ShmDescPtr shmdesc = (ShmDescPtr)value;
51305b261ecSmrg    ShmDescPtr *prev;
51405b261ecSmrg
51505b261ecSmrg    if (--shmdesc->refcnt)
51605b261ecSmrg	return TRUE;
51705b261ecSmrg    shmdt(shmdesc->addr);
51805b261ecSmrg    for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next)
51905b261ecSmrg	;
52005b261ecSmrg    *prev = shmdesc->next;
5214202a189Smrg    free(shmdesc);
52205b261ecSmrg    return Success;
52305b261ecSmrg}
52405b261ecSmrg
52505b261ecSmrgstatic int
5264642e01fSmrgProcShmDetach(ClientPtr client)
52705b261ecSmrg{
52805b261ecSmrg    ShmDescPtr shmdesc;
52905b261ecSmrg    REQUEST(xShmDetachReq);
53005b261ecSmrg
53105b261ecSmrg    REQUEST_SIZE_MATCH(xShmDetachReq);
53205b261ecSmrg    VERIFY_SHMSEG(stuff->shmseg, shmdesc, client);
53305b261ecSmrg    FreeResource(stuff->shmseg, RT_NONE);
5344202a189Smrg    return Success;
53505b261ecSmrg}
53605b261ecSmrg
5374642e01fSmrg/*
5384642e01fSmrg * If the given request doesn't exactly match PutImage's constraints,
5394642e01fSmrg * wrap the image in a scratch pixmap header and let CopyArea sort it out.
5404642e01fSmrg */
54105b261ecSmrgstatic void
5424642e01fSmrgdoShmPutImage(DrawablePtr dst, GCPtr pGC,
5434642e01fSmrg	      int depth, unsigned int format,
5444642e01fSmrg	      int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
5454642e01fSmrg	      char *data)
54605b261ecSmrg{
5474642e01fSmrg    PixmapPtr pPixmap;
5484202a189Smrg
5494202a189Smrg    if (format == ZPixmap || depth == 1) {
5504202a189Smrg	pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
5514202a189Smrg					 BitsPerPixel(depth),
5524202a189Smrg					 PixmapBytePad(w, depth),
5534202a189Smrg					 data);
5544202a189Smrg	if (!pPixmap)
5554202a189Smrg	    return;
5564202a189Smrg	pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy);
5574202a189Smrg	FreeScratchPixmapHeader(pPixmap);
5584202a189Smrg    } else {
5594202a189Smrg	GCPtr putGC = GetScratchGC(depth, dst->pScreen);
5604202a189Smrg
5614202a189Smrg	if (!putGC)
5624202a189Smrg	    return;
5634202a189Smrg
5644202a189Smrg	pPixmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth,
5654202a189Smrg						CREATE_PIXMAP_USAGE_SCRATCH);
5664202a189Smrg	if (!pPixmap) {
5674202a189Smrg	    FreeScratchGC(putGC);
5684202a189Smrg	    return;
5694202a189Smrg	}
5704202a189Smrg	ValidateGC(&pPixmap->drawable, putGC);
5714202a189Smrg	(*putGC->ops->PutImage)(&pPixmap->drawable, putGC, depth, -sx, -sy, w, h, 0,
5724202a189Smrg				(format == XYPixmap) ? XYPixmap : ZPixmap, data);
5734202a189Smrg	FreeScratchGC(putGC);
5744202a189Smrg	if (format == XYBitmap)
5754202a189Smrg	    (void)(*pGC->ops->CopyPlane)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
5764202a189Smrg					 dx, dy, 1L);
5774202a189Smrg	else
5784202a189Smrg	    (void)(*pGC->ops->CopyArea)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
5794202a189Smrg					dx, dy);
5804202a189Smrg	(*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
5814202a189Smrg    }
58205b261ecSmrg}
58305b261ecSmrg
58405b261ecSmrg#ifdef PANORAMIX
58505b261ecSmrgstatic int
5864642e01fSmrgProcPanoramiXShmPutImage(ClientPtr client)
58705b261ecSmrg{
5884202a189Smrg    int			 j, result, orig_x, orig_y;
58905b261ecSmrg    PanoramiXRes	*draw, *gc;
59005b261ecSmrg    Bool		 sendEvent, isRoot;
59105b261ecSmrg
59205b261ecSmrg    REQUEST(xShmPutImageReq);
59305b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
59405b261ecSmrg
5954202a189Smrg    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
5964202a189Smrg				      XRC_DRAWABLE, client, DixWriteAccess);
5974202a189Smrg    if (result != Success)
5984202a189Smrg        return (result == BadValue) ? BadDrawable : result;
59905b261ecSmrg
6004202a189Smrg    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
6014202a189Smrg				     XRT_GC, client, DixReadAccess);
6024202a189Smrg    if (result != Success)
6034202a189Smrg        return result;
60405b261ecSmrg
60505b261ecSmrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
60605b261ecSmrg
60705b261ecSmrg    orig_x = stuff->dstX;
60805b261ecSmrg    orig_y = stuff->dstY;
60905b261ecSmrg    sendEvent = stuff->sendEvent;
61005b261ecSmrg    stuff->sendEvent = 0;
61105b261ecSmrg    FOR_NSCREENS(j) {
61205b261ecSmrg	if(!j) stuff->sendEvent = sendEvent;
61305b261ecSmrg	stuff->drawable = draw->info[j].id;
61405b261ecSmrg	stuff->gc = gc->info[j].id;
61505b261ecSmrg	if (isRoot) {
6164202a189Smrg	    stuff->dstX = orig_x - screenInfo.screens[j]->x;
6174202a189Smrg	    stuff->dstY = orig_y - screenInfo.screens[j]->y;
61805b261ecSmrg	}
61905b261ecSmrg	result = ProcShmPutImage(client);
6204202a189Smrg	if(result != Success) break;
62105b261ecSmrg    }
6224202a189Smrg    return result;
62305b261ecSmrg}
62405b261ecSmrg
62505b261ecSmrgstatic int
62605b261ecSmrgProcPanoramiXShmGetImage(ClientPtr client)
62705b261ecSmrg{
62805b261ecSmrg    PanoramiXRes	*draw;
6294202a189Smrg    DrawablePtr 	*drawables;
63005b261ecSmrg    DrawablePtr 	pDraw;
63105b261ecSmrg    xShmGetImageReply	xgi;
63205b261ecSmrg    ShmDescPtr		shmdesc;
63305b261ecSmrg    int         	i, x, y, w, h, format, rc;
63405b261ecSmrg    Mask		plane = 0, planemask;
63505b261ecSmrg    long		lenPer = 0, length, widthBytesLine;
63605b261ecSmrg    Bool		isRoot;
63705b261ecSmrg
63805b261ecSmrg    REQUEST(xShmGetImageReq);
63905b261ecSmrg
64005b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
64105b261ecSmrg
64205b261ecSmrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) {
64305b261ecSmrg	client->errorValue = stuff->format;
6444202a189Smrg        return BadValue;
64505b261ecSmrg    }
64605b261ecSmrg
6474202a189Smrg    rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
6484202a189Smrg				  XRC_DRAWABLE, client, DixWriteAccess);
6494202a189Smrg    if (rc != Success)
6504202a189Smrg	return (rc == BadValue) ? BadDrawable : rc;
65105b261ecSmrg
65205b261ecSmrg    if (draw->type == XRT_PIXMAP)
65305b261ecSmrg	return ProcShmGetImage(client);
65405b261ecSmrg
65505b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
6564642e01fSmrg			   DixReadAccess);
65705b261ecSmrg    if (rc != Success)
65805b261ecSmrg	return rc;
65905b261ecSmrg
66005b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
66105b261ecSmrg
66205b261ecSmrg    x = stuff->x;
66305b261ecSmrg    y = stuff->y;
66405b261ecSmrg    w = stuff->width;
66505b261ecSmrg    h = stuff->height;
66605b261ecSmrg    format = stuff->format;
66705b261ecSmrg    planemask = stuff->planeMask;
66805b261ecSmrg
66905b261ecSmrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
67005b261ecSmrg
67105b261ecSmrg    if(isRoot) {
67205b261ecSmrg      if( /* check for being onscreen */
67305b261ecSmrg	x < 0 || x + w > PanoramiXPixWidth ||
67405b261ecSmrg	y < 0 || y + h > PanoramiXPixHeight )
6754202a189Smrg	    return BadMatch;
67605b261ecSmrg    } else {
67705b261ecSmrg      if( /* check for being onscreen */
6784202a189Smrg	screenInfo.screens[0]->x + pDraw->x + x < 0 ||
6794202a189Smrg	screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth ||
6804202a189Smrg	screenInfo.screens[0]->y + pDraw->y + y < 0 ||
6814202a189Smrg	screenInfo.screens[0]->y + pDraw->y + y + h > PanoramiXPixHeight ||
68205b261ecSmrg	 /* check for being inside of border */
68305b261ecSmrg       	x < - wBorderWidth((WindowPtr)pDraw) ||
68405b261ecSmrg	x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
68505b261ecSmrg	y < -wBorderWidth((WindowPtr)pDraw) ||
68605b261ecSmrg	y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height)
6874202a189Smrg	    return BadMatch;
68805b261ecSmrg    }
68905b261ecSmrg
6904202a189Smrg    drawables = calloc(PanoramiXNumScreens, sizeof(DrawablePtr));
6914202a189Smrg    if(!drawables)
6924202a189Smrg	return BadAlloc;
6934202a189Smrg
69405b261ecSmrg    drawables[0] = pDraw;
69505b261ecSmrg    for(i = 1; i < PanoramiXNumScreens; i++) {
69605b261ecSmrg	rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
6974642e01fSmrg			       DixReadAccess);
69805b261ecSmrg	if (rc != Success)
6994202a189Smrg	{
7004202a189Smrg	    free(drawables);
70105b261ecSmrg	    return rc;
7024202a189Smrg	}
70305b261ecSmrg    }
70405b261ecSmrg
70505b261ecSmrg    xgi.visual = wVisual(((WindowPtr)pDraw));
70605b261ecSmrg    xgi.type = X_Reply;
70705b261ecSmrg    xgi.length = 0;
70805b261ecSmrg    xgi.sequenceNumber = client->sequence;
70905b261ecSmrg    xgi.depth = pDraw->depth;
71005b261ecSmrg
71105b261ecSmrg    if(format == ZPixmap) {
71205b261ecSmrg	widthBytesLine = PixmapBytePad(w, pDraw->depth);
71305b261ecSmrg	length = widthBytesLine * h;
71405b261ecSmrg    } else {
71505b261ecSmrg	widthBytesLine = PixmapBytePad(w, 1);
71605b261ecSmrg	lenPer = widthBytesLine * h;
71705b261ecSmrg	plane = ((Mask)1) << (pDraw->depth - 1);
71805b261ecSmrg	length = lenPer * Ones(planemask & (plane | (plane - 1)));
71905b261ecSmrg    }
72005b261ecSmrg
72105b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
72205b261ecSmrg    xgi.size = length;
72305b261ecSmrg
72405b261ecSmrg    if (length == 0) {/* nothing to do */ }
72505b261ecSmrg    else if (format == ZPixmap) {
72605b261ecSmrg	    XineramaGetImageData(drawables, x, y, w, h, format, planemask,
72705b261ecSmrg					shmdesc->addr + stuff->offset,
72805b261ecSmrg					widthBytesLine, isRoot);
72905b261ecSmrg    } else {
73005b261ecSmrg
73105b261ecSmrg	length = stuff->offset;
73205b261ecSmrg        for (; plane; plane >>= 1) {
73305b261ecSmrg	    if (planemask & plane) {
73405b261ecSmrg		XineramaGetImageData(drawables, x, y, w, h,
73505b261ecSmrg				     format, plane, shmdesc->addr + length,
73605b261ecSmrg				     widthBytesLine, isRoot);
73705b261ecSmrg		length += lenPer;
73805b261ecSmrg	    }
73905b261ecSmrg	}
74005b261ecSmrg    }
7414202a189Smrg    free(drawables);
74205b261ecSmrg
74305b261ecSmrg    if (client->swapped) {
7444642e01fSmrg	int n;
74505b261ecSmrg    	swaps(&xgi.sequenceNumber, n);
74605b261ecSmrg    	swapl(&xgi.length, n);
74705b261ecSmrg	swapl(&xgi.visual, n);
74805b261ecSmrg	swapl(&xgi.size, n);
74905b261ecSmrg    }
75005b261ecSmrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
75105b261ecSmrg
7524202a189Smrg    return Success;
75305b261ecSmrg}
75405b261ecSmrg
75505b261ecSmrgstatic int
7564642e01fSmrgProcPanoramiXShmCreatePixmap(ClientPtr client)
75705b261ecSmrg{
75805b261ecSmrg    ScreenPtr pScreen = NULL;
75905b261ecSmrg    PixmapPtr pMap = NULL;
76005b261ecSmrg    DrawablePtr pDraw;
76105b261ecSmrg    DepthPtr pDepth;
76205b261ecSmrg    int i, j, result, rc;
76305b261ecSmrg    ShmDescPtr shmdesc;
76405b261ecSmrg    REQUEST(xShmCreatePixmapReq);
76505b261ecSmrg    unsigned int width, height, depth;
76605b261ecSmrg    unsigned long size;
76705b261ecSmrg    PanoramiXRes *newPix;
76805b261ecSmrg
76905b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
77005b261ecSmrg    client->errorValue = stuff->pid;
77105b261ecSmrg    if (!sharedPixmaps)
77205b261ecSmrg	return BadImplementation;
77305b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
77405b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
7754642e01fSmrg			   DixGetAttrAccess);
77605b261ecSmrg    if (rc != Success)
77705b261ecSmrg	return rc;
77805b261ecSmrg
77905b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
78005b261ecSmrg
78105b261ecSmrg    width = stuff->width;
78205b261ecSmrg    height = stuff->height;
78305b261ecSmrg    depth = stuff->depth;
78405b261ecSmrg    if (!width || !height || !depth)
78505b261ecSmrg    {
78605b261ecSmrg	client->errorValue = 0;
78705b261ecSmrg        return BadValue;
78805b261ecSmrg    }
78905b261ecSmrg    if (width > 32767 || height > 32767)
79005b261ecSmrg        return BadAlloc;
79105b261ecSmrg
79205b261ecSmrg    if (stuff->depth != 1)
79305b261ecSmrg    {
79405b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
79505b261ecSmrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
79605b261ecSmrg	   if (pDepth->depth == stuff->depth)
79705b261ecSmrg               goto CreatePmap;
79805b261ecSmrg	client->errorValue = stuff->depth;
79905b261ecSmrg        return BadValue;
80005b261ecSmrg    }
80105b261ecSmrg
80205b261ecSmrgCreatePmap:
80305b261ecSmrg    size = PixmapBytePad(width, depth) * height;
80405b261ecSmrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
80505b261ecSmrg        if (size < width * height)
80605b261ecSmrg            return BadAlloc;
80705b261ecSmrg    }
80805b261ecSmrg    /* thankfully, offset is unsigned */
80905b261ecSmrg    if (stuff->offset + size < size)
81005b261ecSmrg	return BadAlloc;
81105b261ecSmrg
81205b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
81305b261ecSmrg
8144202a189Smrg    if(!(newPix = malloc(sizeof(PanoramiXRes))))
81505b261ecSmrg	return BadAlloc;
81605b261ecSmrg
81705b261ecSmrg    newPix->type = XRT_PIXMAP;
81805b261ecSmrg    newPix->u.pix.shared = TRUE;
81905b261ecSmrg    newPix->info[0].id = stuff->pid;
82005b261ecSmrg    for(j = 1; j < PanoramiXNumScreens; j++)
82105b261ecSmrg	newPix->info[j].id = FakeClientID(client->index);
82205b261ecSmrg
8234202a189Smrg    result = Success;
82405b261ecSmrg
82505b261ecSmrg    FOR_NSCREENS(j) {
8264202a189Smrg	ShmScrPrivateRec *screen_priv;
82705b261ecSmrg	pScreen = screenInfo.screens[j];
82805b261ecSmrg
8294202a189Smrg	screen_priv = ShmGetScreenPriv(pScreen);
8304202a189Smrg	pMap = (*screen_priv->shmFuncs->CreatePixmap)(pScreen,
83105b261ecSmrg				stuff->width, stuff->height, stuff->depth,
83205b261ecSmrg				shmdesc->addr + stuff->offset);
83305b261ecSmrg
83405b261ecSmrg	if (pMap) {
8354202a189Smrg	    dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc);
83605b261ecSmrg            shmdesc->refcnt++;
83705b261ecSmrg	    pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
83805b261ecSmrg	    pMap->drawable.id = newPix->info[j].id;
83905b261ecSmrg	    if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) {
84005b261ecSmrg		(*pScreen->DestroyPixmap)(pMap);
84105b261ecSmrg		result = BadAlloc;
84205b261ecSmrg		break;
84305b261ecSmrg	    }
84405b261ecSmrg	} else {
84505b261ecSmrg	   result = BadAlloc;
84605b261ecSmrg	   break;
84705b261ecSmrg	}
84805b261ecSmrg    }
84905b261ecSmrg
85005b261ecSmrg    if(result == BadAlloc) {
85105b261ecSmrg	while(j--) {
85205b261ecSmrg	    (*pScreen->DestroyPixmap)(pMap);
85305b261ecSmrg	    FreeResource(newPix->info[j].id, RT_NONE);
85405b261ecSmrg	}
8554202a189Smrg	free(newPix);
85605b261ecSmrg    } else
85705b261ecSmrg	AddResource(stuff->pid, XRT_PIXMAP, newPix);
85805b261ecSmrg
85905b261ecSmrg    return result;
86005b261ecSmrg}
86105b261ecSmrg
86205b261ecSmrg#endif
86305b261ecSmrg
86405b261ecSmrgstatic int
8654642e01fSmrgProcShmPutImage(ClientPtr client)
86605b261ecSmrg{
86705b261ecSmrg    GCPtr pGC;
86805b261ecSmrg    DrawablePtr pDraw;
86905b261ecSmrg    long length;
87005b261ecSmrg    ShmDescPtr shmdesc;
87105b261ecSmrg    REQUEST(xShmPutImageReq);
87205b261ecSmrg
87305b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
8744642e01fSmrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
87505b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);
87605b261ecSmrg    if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
87705b261ecSmrg	return BadValue;
87805b261ecSmrg    if (stuff->format == XYBitmap)
87905b261ecSmrg    {
88005b261ecSmrg        if (stuff->depth != 1)
88105b261ecSmrg            return BadMatch;
88205b261ecSmrg        length = PixmapBytePad(stuff->totalWidth, 1);
88305b261ecSmrg    }
88405b261ecSmrg    else if (stuff->format == XYPixmap)
88505b261ecSmrg    {
88605b261ecSmrg        if (pDraw->depth != stuff->depth)
88705b261ecSmrg            return BadMatch;
88805b261ecSmrg        length = PixmapBytePad(stuff->totalWidth, 1);
88905b261ecSmrg	length *= stuff->depth;
89005b261ecSmrg    }
89105b261ecSmrg    else if (stuff->format == ZPixmap)
89205b261ecSmrg    {
89305b261ecSmrg        if (pDraw->depth != stuff->depth)
89405b261ecSmrg            return BadMatch;
89505b261ecSmrg        length = PixmapBytePad(stuff->totalWidth, stuff->depth);
89605b261ecSmrg    }
89705b261ecSmrg    else
89805b261ecSmrg    {
89905b261ecSmrg	client->errorValue = stuff->format;
90005b261ecSmrg        return BadValue;
90105b261ecSmrg    }
90205b261ecSmrg
90305b261ecSmrg    /*
90405b261ecSmrg     * There's a potential integer overflow in this check:
90505b261ecSmrg     * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
90605b261ecSmrg     *                client);
90705b261ecSmrg     * the version below ought to avoid it
90805b261ecSmrg     */
90905b261ecSmrg    if (stuff->totalHeight != 0 &&
91005b261ecSmrg	length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
91105b261ecSmrg	client->errorValue = stuff->totalWidth;
91205b261ecSmrg	return BadValue;
91305b261ecSmrg    }
91405b261ecSmrg    if (stuff->srcX > stuff->totalWidth)
91505b261ecSmrg    {
91605b261ecSmrg	client->errorValue = stuff->srcX;
91705b261ecSmrg	return BadValue;
91805b261ecSmrg    }
91905b261ecSmrg    if (stuff->srcY > stuff->totalHeight)
92005b261ecSmrg    {
92105b261ecSmrg	client->errorValue = stuff->srcY;
92205b261ecSmrg	return BadValue;
92305b261ecSmrg    }
92405b261ecSmrg    if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth)
92505b261ecSmrg    {
92605b261ecSmrg	client->errorValue = stuff->srcWidth;
92705b261ecSmrg	return BadValue;
92805b261ecSmrg    }
92905b261ecSmrg    if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight)
93005b261ecSmrg    {
93105b261ecSmrg	client->errorValue = stuff->srcHeight;
93205b261ecSmrg	return BadValue;
93305b261ecSmrg    }
93405b261ecSmrg
93505b261ecSmrg    if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) ||
93605b261ecSmrg	 ((stuff->format != ZPixmap) &&
93705b261ecSmrg	  (stuff->srcX < screenInfo.bitmapScanlinePad) &&
93805b261ecSmrg	  ((stuff->format == XYBitmap) ||
93905b261ecSmrg	   ((stuff->srcY == 0) &&
94005b261ecSmrg	    (stuff->srcHeight == stuff->totalHeight))))) &&
94105b261ecSmrg	((stuff->srcX + stuff->srcWidth) == stuff->totalWidth))
94205b261ecSmrg	(*pGC->ops->PutImage) (pDraw, pGC, stuff->depth,
94305b261ecSmrg			       stuff->dstX, stuff->dstY,
94405b261ecSmrg			       stuff->totalWidth, stuff->srcHeight,
94505b261ecSmrg			       stuff->srcX, stuff->format,
94605b261ecSmrg			       shmdesc->addr + stuff->offset +
94705b261ecSmrg			       (stuff->srcY * length));
94805b261ecSmrg    else
9494642e01fSmrg	doShmPutImage(pDraw, pGC, stuff->depth, stuff->format,
9504642e01fSmrg		      stuff->totalWidth, stuff->totalHeight,
9514642e01fSmrg		      stuff->srcX, stuff->srcY,
9524642e01fSmrg		      stuff->srcWidth, stuff->srcHeight,
9534642e01fSmrg		      stuff->dstX, stuff->dstY,
9544642e01fSmrg                      shmdesc->addr + stuff->offset);
95505b261ecSmrg
95605b261ecSmrg    if (stuff->sendEvent)
95705b261ecSmrg    {
95805b261ecSmrg	xShmCompletionEvent ev;
95905b261ecSmrg
96005b261ecSmrg	ev.type = ShmCompletionCode;
96105b261ecSmrg	ev.drawable = stuff->drawable;
96205b261ecSmrg	ev.minorEvent = X_ShmPutImage;
96305b261ecSmrg	ev.majorEvent = ShmReqCode;
96405b261ecSmrg	ev.shmseg = stuff->shmseg;
96505b261ecSmrg	ev.offset = stuff->offset;
96605b261ecSmrg	WriteEventsToClient(client, 1, (xEvent *) &ev);
96705b261ecSmrg    }
96805b261ecSmrg
9694202a189Smrg    return Success;
97005b261ecSmrg}
97105b261ecSmrg
97205b261ecSmrg
97305b261ecSmrg
97405b261ecSmrgstatic int
9754642e01fSmrgProcShmGetImage(ClientPtr client)
97605b261ecSmrg{
97705b261ecSmrg    DrawablePtr		pDraw;
97805b261ecSmrg    long		lenPer = 0, length;
97905b261ecSmrg    Mask		plane = 0;
98005b261ecSmrg    xShmGetImageReply	xgi;
98105b261ecSmrg    ShmDescPtr		shmdesc;
98205b261ecSmrg    int			n, rc;
98305b261ecSmrg
98405b261ecSmrg    REQUEST(xShmGetImageReq);
98505b261ecSmrg
98605b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
98705b261ecSmrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap))
98805b261ecSmrg    {
98905b261ecSmrg	client->errorValue = stuff->format;
9904202a189Smrg        return BadValue;
99105b261ecSmrg    }
99205b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
9934642e01fSmrg			   DixReadAccess);
99405b261ecSmrg    if (rc != Success)
99505b261ecSmrg	return rc;
99605b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
99705b261ecSmrg    if (pDraw->type == DRAWABLE_WINDOW)
99805b261ecSmrg    {
99905b261ecSmrg      if( /* check for being viewable */
100005b261ecSmrg	 !((WindowPtr) pDraw)->realized ||
100105b261ecSmrg	  /* check for being on screen */
100205b261ecSmrg         pDraw->x + stuff->x < 0 ||
100305b261ecSmrg 	 pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width ||
100405b261ecSmrg         pDraw->y + stuff->y < 0 ||
100505b261ecSmrg         pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height ||
100605b261ecSmrg          /* check for being inside of border */
100705b261ecSmrg         stuff->x < - wBorderWidth((WindowPtr)pDraw) ||
100805b261ecSmrg         stuff->x + (int)stuff->width >
100905b261ecSmrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
101005b261ecSmrg         stuff->y < -wBorderWidth((WindowPtr)pDraw) ||
101105b261ecSmrg         stuff->y + (int)stuff->height >
101205b261ecSmrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height
101305b261ecSmrg        )
10144202a189Smrg	    return BadMatch;
101505b261ecSmrg	xgi.visual = wVisual(((WindowPtr)pDraw));
101605b261ecSmrg    }
101705b261ecSmrg    else
101805b261ecSmrg    {
101905b261ecSmrg	if (stuff->x < 0 ||
102005b261ecSmrg	    stuff->x+(int)stuff->width > pDraw->width ||
102105b261ecSmrg	    stuff->y < 0 ||
102205b261ecSmrg	    stuff->y+(int)stuff->height > pDraw->height
102305b261ecSmrg	    )
10244202a189Smrg	    return BadMatch;
102505b261ecSmrg	xgi.visual = None;
102605b261ecSmrg    }
102705b261ecSmrg    xgi.type = X_Reply;
102805b261ecSmrg    xgi.length = 0;
102905b261ecSmrg    xgi.sequenceNumber = client->sequence;
103005b261ecSmrg    xgi.depth = pDraw->depth;
103105b261ecSmrg    if(stuff->format == ZPixmap)
103205b261ecSmrg    {
103305b261ecSmrg	length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height;
103405b261ecSmrg    }
103505b261ecSmrg    else
103605b261ecSmrg    {
103705b261ecSmrg	lenPer = PixmapBytePad(stuff->width, 1) * stuff->height;
103805b261ecSmrg	plane = ((Mask)1) << (pDraw->depth - 1);
103905b261ecSmrg	/* only planes asked for */
104005b261ecSmrg	length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1)));
104105b261ecSmrg    }
104205b261ecSmrg
104305b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
104405b261ecSmrg    xgi.size = length;
104505b261ecSmrg
104605b261ecSmrg    if (length == 0)
104705b261ecSmrg    {
104805b261ecSmrg	/* nothing to do */
104905b261ecSmrg    }
105005b261ecSmrg    else if (stuff->format == ZPixmap)
105105b261ecSmrg    {
105205b261ecSmrg	(*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y,
105305b261ecSmrg				    stuff->width, stuff->height,
105405b261ecSmrg				    stuff->format, stuff->planeMask,
105505b261ecSmrg				    shmdesc->addr + stuff->offset);
105605b261ecSmrg    }
105705b261ecSmrg    else
105805b261ecSmrg    {
105905b261ecSmrg
106005b261ecSmrg	length = stuff->offset;
106105b261ecSmrg        for (; plane; plane >>= 1)
106205b261ecSmrg	{
106305b261ecSmrg	    if (stuff->planeMask & plane)
106405b261ecSmrg	    {
106505b261ecSmrg		(*pDraw->pScreen->GetImage)(pDraw,
106605b261ecSmrg					    stuff->x, stuff->y,
106705b261ecSmrg					    stuff->width, stuff->height,
106805b261ecSmrg					    stuff->format, plane,
106905b261ecSmrg					    shmdesc->addr + length);
107005b261ecSmrg		length += lenPer;
107105b261ecSmrg	    }
107205b261ecSmrg	}
107305b261ecSmrg    }
107405b261ecSmrg
107505b261ecSmrg    if (client->swapped) {
107605b261ecSmrg    	swaps(&xgi.sequenceNumber, n);
107705b261ecSmrg    	swapl(&xgi.length, n);
107805b261ecSmrg	swapl(&xgi.visual, n);
107905b261ecSmrg	swapl(&xgi.size, n);
108005b261ecSmrg    }
108105b261ecSmrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
108205b261ecSmrg
10834202a189Smrg    return Success;
108405b261ecSmrg}
108505b261ecSmrg
108605b261ecSmrgstatic PixmapPtr
10874642e01fSmrgfbShmCreatePixmap (ScreenPtr pScreen,
10884642e01fSmrg		   int width, int height, int depth, char *addr)
108905b261ecSmrg{
10904642e01fSmrg    PixmapPtr pPixmap;
109105b261ecSmrg
10924642e01fSmrg    pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
109305b261ecSmrg    if (!pPixmap)
109405b261ecSmrg	return NullPixmap;
109505b261ecSmrg
109605b261ecSmrg    if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
109705b261ecSmrg	    BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) {
109805b261ecSmrg	(*pScreen->DestroyPixmap)(pPixmap);
109905b261ecSmrg	return NullPixmap;
110005b261ecSmrg    }
110105b261ecSmrg    return pPixmap;
110205b261ecSmrg}
110305b261ecSmrg
110405b261ecSmrgstatic int
11054642e01fSmrgProcShmCreatePixmap(ClientPtr client)
110605b261ecSmrg{
110705b261ecSmrg    PixmapPtr pMap;
110805b261ecSmrg    DrawablePtr pDraw;
110905b261ecSmrg    DepthPtr pDepth;
11104642e01fSmrg    int i, rc;
111105b261ecSmrg    ShmDescPtr shmdesc;
11124202a189Smrg    ShmScrPrivateRec *screen_priv;
111305b261ecSmrg    REQUEST(xShmCreatePixmapReq);
111405b261ecSmrg    unsigned int width, height, depth;
111505b261ecSmrg    unsigned long size;
111605b261ecSmrg
111705b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
111805b261ecSmrg    client->errorValue = stuff->pid;
111905b261ecSmrg    if (!sharedPixmaps)
112005b261ecSmrg	return BadImplementation;
112105b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
112205b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
11234642e01fSmrg			   DixGetAttrAccess);
112405b261ecSmrg    if (rc != Success)
112505b261ecSmrg	return rc;
112605b261ecSmrg
112705b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
112805b261ecSmrg
112905b261ecSmrg    width = stuff->width;
113005b261ecSmrg    height = stuff->height;
113105b261ecSmrg    depth = stuff->depth;
113205b261ecSmrg    if (!width || !height || !depth)
113305b261ecSmrg    {
113405b261ecSmrg	client->errorValue = 0;
113505b261ecSmrg        return BadValue;
113605b261ecSmrg    }
113705b261ecSmrg    if (width > 32767 || height > 32767)
113805b261ecSmrg	return BadAlloc;
113905b261ecSmrg
114005b261ecSmrg    if (stuff->depth != 1)
114105b261ecSmrg    {
114205b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
114305b261ecSmrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
114405b261ecSmrg	   if (pDepth->depth == stuff->depth)
114505b261ecSmrg               goto CreatePmap;
114605b261ecSmrg	client->errorValue = stuff->depth;
114705b261ecSmrg        return BadValue;
114805b261ecSmrg    }
114905b261ecSmrg
115005b261ecSmrgCreatePmap:
115105b261ecSmrg    size = PixmapBytePad(width, depth) * height;
115205b261ecSmrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
115305b261ecSmrg	if (size < width * height)
115405b261ecSmrg	    return BadAlloc;
115505b261ecSmrg    }
115605b261ecSmrg    /* thankfully, offset is unsigned */
115705b261ecSmrg    if (stuff->offset + size < size)
115805b261ecSmrg	return BadAlloc;
115905b261ecSmrg
116005b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
11614202a189Smrg    screen_priv = ShmGetScreenPriv(pDraw->pScreen);
11624202a189Smrg    pMap = (*screen_priv->shmFuncs->CreatePixmap)(
116305b261ecSmrg			    pDraw->pScreen, stuff->width,
116405b261ecSmrg			    stuff->height, stuff->depth,
116505b261ecSmrg			    shmdesc->addr + stuff->offset);
116605b261ecSmrg    if (pMap)
116705b261ecSmrg    {
11684642e01fSmrg	rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
11694642e01fSmrg		      pMap, RT_NONE, NULL, DixCreateAccess);
11704642e01fSmrg	if (rc != Success) {
11714642e01fSmrg	    pDraw->pScreen->DestroyPixmap(pMap);
11724642e01fSmrg	    return rc;
11734642e01fSmrg	}
11744202a189Smrg	dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc);
117505b261ecSmrg	shmdesc->refcnt++;
117605b261ecSmrg	pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
117705b261ecSmrg	pMap->drawable.id = stuff->pid;
117805b261ecSmrg	if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
117905b261ecSmrg	{
11804202a189Smrg	    return Success;
118105b261ecSmrg	}
11824642e01fSmrg	pDraw->pScreen->DestroyPixmap(pMap);
118305b261ecSmrg    }
11844202a189Smrg    return BadAlloc;
118505b261ecSmrg}
118605b261ecSmrg
118705b261ecSmrgstatic int
11884642e01fSmrgProcShmDispatch (ClientPtr client)
118905b261ecSmrg{
119005b261ecSmrg    REQUEST(xReq);
119105b261ecSmrg    switch (stuff->data)
119205b261ecSmrg    {
119305b261ecSmrg    case X_ShmQueryVersion:
119405b261ecSmrg	return ProcShmQueryVersion(client);
119505b261ecSmrg    case X_ShmAttach:
119605b261ecSmrg	return ProcShmAttach(client);
119705b261ecSmrg    case X_ShmDetach:
119805b261ecSmrg	return ProcShmDetach(client);
119905b261ecSmrg    case X_ShmPutImage:
120005b261ecSmrg#ifdef PANORAMIX
120105b261ecSmrg        if ( !noPanoramiXExtension )
120205b261ecSmrg	   return ProcPanoramiXShmPutImage(client);
120305b261ecSmrg#endif
120405b261ecSmrg	return ProcShmPutImage(client);
120505b261ecSmrg    case X_ShmGetImage:
120605b261ecSmrg#ifdef PANORAMIX
120705b261ecSmrg        if ( !noPanoramiXExtension )
120805b261ecSmrg	   return ProcPanoramiXShmGetImage(client);
120905b261ecSmrg#endif
121005b261ecSmrg	return ProcShmGetImage(client);
121105b261ecSmrg    case X_ShmCreatePixmap:
121205b261ecSmrg#ifdef PANORAMIX
121305b261ecSmrg        if ( !noPanoramiXExtension )
121405b261ecSmrg	   return ProcPanoramiXShmCreatePixmap(client);
121505b261ecSmrg#endif
121605b261ecSmrg	   return ProcShmCreatePixmap(client);
121705b261ecSmrg    default:
121805b261ecSmrg	return BadRequest;
121905b261ecSmrg    }
122005b261ecSmrg}
122105b261ecSmrg
122205b261ecSmrgstatic void
12234642e01fSmrgSShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to)
122405b261ecSmrg{
122505b261ecSmrg    to->type = from->type;
122605b261ecSmrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
122705b261ecSmrg    cpswapl(from->drawable, to->drawable);
122805b261ecSmrg    cpswaps(from->minorEvent, to->minorEvent);
122905b261ecSmrg    to->majorEvent = from->majorEvent;
123005b261ecSmrg    cpswapl(from->shmseg, to->shmseg);
123105b261ecSmrg    cpswapl(from->offset, to->offset);
123205b261ecSmrg}
123305b261ecSmrg
123405b261ecSmrgstatic int
12354642e01fSmrgSProcShmQueryVersion(ClientPtr client)
123605b261ecSmrg{
12374642e01fSmrg    int n;
123805b261ecSmrg    REQUEST(xShmQueryVersionReq);
123905b261ecSmrg
124005b261ecSmrg    swaps(&stuff->length, n);
124105b261ecSmrg    return ProcShmQueryVersion(client);
124205b261ecSmrg}
124305b261ecSmrg
124405b261ecSmrgstatic int
12454642e01fSmrgSProcShmAttach(ClientPtr client)
124605b261ecSmrg{
12474642e01fSmrg    int n;
124805b261ecSmrg    REQUEST(xShmAttachReq);
124905b261ecSmrg    swaps(&stuff->length, n);
125005b261ecSmrg    REQUEST_SIZE_MATCH(xShmAttachReq);
125105b261ecSmrg    swapl(&stuff->shmseg, n);
125205b261ecSmrg    swapl(&stuff->shmid, n);
125305b261ecSmrg    return ProcShmAttach(client);
125405b261ecSmrg}
125505b261ecSmrg
125605b261ecSmrgstatic int
12574642e01fSmrgSProcShmDetach(ClientPtr client)
125805b261ecSmrg{
12594642e01fSmrg    int n;
126005b261ecSmrg    REQUEST(xShmDetachReq);
126105b261ecSmrg    swaps(&stuff->length, n);
126205b261ecSmrg    REQUEST_SIZE_MATCH(xShmDetachReq);
126305b261ecSmrg    swapl(&stuff->shmseg, n);
126405b261ecSmrg    return ProcShmDetach(client);
126505b261ecSmrg}
126605b261ecSmrg
126705b261ecSmrgstatic int
12684642e01fSmrgSProcShmPutImage(ClientPtr client)
126905b261ecSmrg{
12704642e01fSmrg    int n;
127105b261ecSmrg    REQUEST(xShmPutImageReq);
127205b261ecSmrg    swaps(&stuff->length, n);
127305b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
127405b261ecSmrg    swapl(&stuff->drawable, n);
127505b261ecSmrg    swapl(&stuff->gc, n);
127605b261ecSmrg    swaps(&stuff->totalWidth, n);
127705b261ecSmrg    swaps(&stuff->totalHeight, n);
127805b261ecSmrg    swaps(&stuff->srcX, n);
127905b261ecSmrg    swaps(&stuff->srcY, n);
128005b261ecSmrg    swaps(&stuff->srcWidth, n);
128105b261ecSmrg    swaps(&stuff->srcHeight, n);
128205b261ecSmrg    swaps(&stuff->dstX, n);
128305b261ecSmrg    swaps(&stuff->dstY, n);
128405b261ecSmrg    swapl(&stuff->shmseg, n);
128505b261ecSmrg    swapl(&stuff->offset, n);
128605b261ecSmrg    return ProcShmPutImage(client);
128705b261ecSmrg}
128805b261ecSmrg
128905b261ecSmrgstatic int
12904642e01fSmrgSProcShmGetImage(ClientPtr client)
129105b261ecSmrg{
12924642e01fSmrg    int n;
129305b261ecSmrg    REQUEST(xShmGetImageReq);
129405b261ecSmrg    swaps(&stuff->length, n);
129505b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
129605b261ecSmrg    swapl(&stuff->drawable, n);
129705b261ecSmrg    swaps(&stuff->x, n);
129805b261ecSmrg    swaps(&stuff->y, n);
129905b261ecSmrg    swaps(&stuff->width, n);
130005b261ecSmrg    swaps(&stuff->height, n);
130105b261ecSmrg    swapl(&stuff->planeMask, n);
130205b261ecSmrg    swapl(&stuff->shmseg, n);
130305b261ecSmrg    swapl(&stuff->offset, n);
130405b261ecSmrg    return ProcShmGetImage(client);
130505b261ecSmrg}
130605b261ecSmrg
130705b261ecSmrgstatic int
13084642e01fSmrgSProcShmCreatePixmap(ClientPtr client)
130905b261ecSmrg{
13104642e01fSmrg    int n;
131105b261ecSmrg    REQUEST(xShmCreatePixmapReq);
131205b261ecSmrg    swaps(&stuff->length, n);
131305b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
131405b261ecSmrg    swapl(&stuff->pid, n);
131505b261ecSmrg    swapl(&stuff->drawable, n);
131605b261ecSmrg    swaps(&stuff->width, n);
131705b261ecSmrg    swaps(&stuff->height, n);
131805b261ecSmrg    swapl(&stuff->shmseg, n);
131905b261ecSmrg    swapl(&stuff->offset, n);
132005b261ecSmrg    return ProcShmCreatePixmap(client);
132105b261ecSmrg}
132205b261ecSmrg
132305b261ecSmrgstatic int
13244642e01fSmrgSProcShmDispatch (ClientPtr client)
132505b261ecSmrg{
132605b261ecSmrg    REQUEST(xReq);
132705b261ecSmrg    switch (stuff->data)
132805b261ecSmrg    {
132905b261ecSmrg    case X_ShmQueryVersion:
133005b261ecSmrg	return SProcShmQueryVersion(client);
133105b261ecSmrg    case X_ShmAttach:
133205b261ecSmrg	return SProcShmAttach(client);
133305b261ecSmrg    case X_ShmDetach:
133405b261ecSmrg	return SProcShmDetach(client);
133505b261ecSmrg    case X_ShmPutImage:
133605b261ecSmrg	return SProcShmPutImage(client);
133705b261ecSmrg    case X_ShmGetImage:
133805b261ecSmrg	return SProcShmGetImage(client);
133905b261ecSmrg    case X_ShmCreatePixmap:
134005b261ecSmrg	return SProcShmCreatePixmap(client);
134105b261ecSmrg    default:
134205b261ecSmrg	return BadRequest;
134305b261ecSmrg    }
134405b261ecSmrg}
1345