1706f2543Smrg/************************************************************
2706f2543Smrg
3706f2543SmrgCopyright 1989, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included in
12706f2543Smrgall copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20706f2543Smrg
21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
23706f2543Smrgin this Software without prior written authorization from The Open Group.
24706f2543Smrg
25706f2543Smrg********************************************************/
26706f2543Smrg
27706f2543Smrg/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */
28706f2543Smrg
29706f2543Smrg
30706f2543Smrg#define SHM
31706f2543Smrg
32706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
33706f2543Smrg#include <dix-config.h>
34706f2543Smrg#endif
35706f2543Smrg
36706f2543Smrg#include <sys/types.h>
37706f2543Smrg#include <sys/ipc.h>
38706f2543Smrg#include <sys/shm.h>
39706f2543Smrg#include <unistd.h>
40706f2543Smrg#include <sys/stat.h>
41706f2543Smrg#include <X11/X.h>
42706f2543Smrg#include <X11/Xproto.h>
43706f2543Smrg#include "misc.h"
44706f2543Smrg#include "os.h"
45706f2543Smrg#include "dixstruct.h"
46706f2543Smrg#include "resource.h"
47706f2543Smrg#include "scrnintstr.h"
48706f2543Smrg#include "windowstr.h"
49706f2543Smrg#include "pixmapstr.h"
50706f2543Smrg#include "gcstruct.h"
51706f2543Smrg#include "extnsionst.h"
52706f2543Smrg#include "servermd.h"
53706f2543Smrg#include "shmint.h"
54706f2543Smrg#include "xace.h"
55706f2543Smrg#include <X11/extensions/shmproto.h>
56706f2543Smrg#include <X11/Xfuncproto.h>
57706f2543Smrg#include "protocol-versions.h"
58706f2543Smrg
59706f2543Smrg/* Needed for Solaris cross-zone shared memory extension */
60706f2543Smrg#ifdef HAVE_SHMCTL64
61706f2543Smrg#include <sys/ipc_impl.h>
62706f2543Smrg#define SHMSTAT(id, buf)	shmctl64(id, IPC_STAT64, buf)
63706f2543Smrg#define SHMSTAT_TYPE 		struct shmid_ds64
64706f2543Smrg#define SHMPERM_TYPE 		struct ipc_perm64
65706f2543Smrg#define SHM_PERM(buf) 		buf.shmx_perm
66706f2543Smrg#define SHM_SEGSZ(buf)		buf.shmx_segsz
67706f2543Smrg#define SHMPERM_UID(p)		p->ipcx_uid
68706f2543Smrg#define SHMPERM_CUID(p)		p->ipcx_cuid
69706f2543Smrg#define SHMPERM_GID(p)		p->ipcx_gid
70706f2543Smrg#define SHMPERM_CGID(p)		p->ipcx_cgid
71706f2543Smrg#define SHMPERM_MODE(p)		p->ipcx_mode
72706f2543Smrg#define SHMPERM_ZONEID(p)	p->ipcx_zoneid
73706f2543Smrg#else
74706f2543Smrg#define SHMSTAT(id, buf) 	shmctl(id, IPC_STAT, buf)
75706f2543Smrg#define SHMSTAT_TYPE 		struct shmid_ds
76706f2543Smrg#define SHMPERM_TYPE 		struct ipc_perm
77706f2543Smrg#define SHM_PERM(buf) 		buf.shm_perm
78706f2543Smrg#define SHM_SEGSZ(buf)		buf.shm_segsz
79706f2543Smrg#define SHMPERM_UID(p)		p->uid
80706f2543Smrg#define SHMPERM_CUID(p)		p->cuid
81706f2543Smrg#define SHMPERM_GID(p)		p->gid
82706f2543Smrg#define SHMPERM_CGID(p)		p->cgid
83706f2543Smrg#define SHMPERM_MODE(p)		p->mode
84706f2543Smrg#endif
85706f2543Smrg
86706f2543Smrg#ifdef PANORAMIX
87706f2543Smrg#include "panoramiX.h"
88706f2543Smrg#include "panoramiXsrv.h"
89706f2543Smrg#endif
90706f2543Smrg
91706f2543Smrg#include "modinit.h"
92706f2543Smrg
93706f2543Smrgtypedef struct _ShmDesc {
94706f2543Smrg    struct _ShmDesc *next;
95706f2543Smrg    int shmid;
96706f2543Smrg    int refcnt;
97706f2543Smrg    char *addr;
98706f2543Smrg    Bool writable;
99706f2543Smrg    unsigned long size;
100706f2543Smrg} ShmDescRec, *ShmDescPtr;
101706f2543Smrg
102706f2543Smrgtypedef struct _ShmScrPrivateRec {
103706f2543Smrg    CloseScreenProcPtr CloseScreen;
104706f2543Smrg    ShmFuncsPtr shmFuncs;
105706f2543Smrg    DestroyPixmapProcPtr destroyPixmap;
106706f2543Smrg} ShmScrPrivateRec;
107706f2543Smrg
108706f2543Smrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS);
109706f2543Smrgstatic int ShmDetachSegment(
110706f2543Smrg    pointer		/* value */,
111706f2543Smrg    XID			/* shmseg */
112706f2543Smrg    );
113706f2543Smrgstatic void ShmResetProc(
114706f2543Smrg    ExtensionEntry *	/* extEntry */
115706f2543Smrg    );
116706f2543Smrgstatic void SShmCompletionEvent(
117706f2543Smrg    xShmCompletionEvent * /* from */,
118706f2543Smrg    xShmCompletionEvent * /* to */
119706f2543Smrg    );
120706f2543Smrg
121706f2543Smrgstatic Bool ShmDestroyPixmap (PixmapPtr pPixmap);
122706f2543Smrg
123706f2543Smrg
124706f2543Smrgstatic unsigned char ShmReqCode;
125706f2543Smrgint ShmCompletionCode;
126706f2543Smrgint BadShmSegCode;
127706f2543SmrgRESTYPE ShmSegType;
128706f2543Smrgstatic ShmDescPtr Shmsegs;
129706f2543Smrgstatic Bool sharedPixmaps;
130706f2543Smrgstatic DevPrivateKeyRec shmScrPrivateKeyRec;
131706f2543Smrg#define shmScrPrivateKey (&shmScrPrivateKeyRec)
132706f2543Smrgstatic DevPrivateKeyRec shmPixmapPrivateKeyRec;
133706f2543Smrg#define shmPixmapPrivateKey (&shmPixmapPrivateKeyRec)
134706f2543Smrgstatic ShmFuncs miFuncs = {NULL, NULL};
135706f2543Smrgstatic ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL};
136706f2543Smrg
137706f2543Smrg#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey))
138706f2543Smrg
139706f2543Smrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
140706f2543Smrg{ \
141706f2543Smrg    int rc; \
142706f2543Smrg    rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \
143706f2543Smrg                                 client, DixReadAccess); \
144706f2543Smrg    if (rc != Success) \
145706f2543Smrg	return rc; \
146706f2543Smrg}
147706f2543Smrg
148706f2543Smrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
149706f2543Smrg{ \
150706f2543Smrg    VERIFY_SHMSEG(shmseg, shmdesc, client); \
151706f2543Smrg    if ((offset & 3) || (offset > shmdesc->size)) \
152706f2543Smrg    { \
153706f2543Smrg	client->errorValue = offset; \
154706f2543Smrg	return BadValue; \
155706f2543Smrg    } \
156706f2543Smrg    if (needwrite && !shmdesc->writable) \
157706f2543Smrg	return BadAccess; \
158706f2543Smrg}
159706f2543Smrg
160706f2543Smrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
161706f2543Smrg{ \
162706f2543Smrg    if ((offset + len) > shmdesc->size) \
163706f2543Smrg    { \
164706f2543Smrg	return BadAccess; \
165706f2543Smrg    } \
166706f2543Smrg}
167706f2543Smrg
168706f2543Smrg
169706f2543Smrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
170706f2543Smrg#include <sys/signal.h>
171706f2543Smrg
172706f2543Smrgstatic Bool badSysCall = FALSE;
173706f2543Smrg
174706f2543Smrgstatic void
175706f2543SmrgSigSysHandler(int signo)
176706f2543Smrg{
177706f2543Smrg    badSysCall = TRUE;
178706f2543Smrg}
179706f2543Smrg
180706f2543Smrgstatic Bool CheckForShmSyscall(void)
181706f2543Smrg{
182706f2543Smrg    void (*oldHandler)();
183706f2543Smrg    int shmid = -1;
184706f2543Smrg
185706f2543Smrg    /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
186706f2543Smrg    oldHandler = signal(SIGSYS, SigSysHandler);
187706f2543Smrg
188706f2543Smrg    badSysCall = FALSE;
189706f2543Smrg    shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
190706f2543Smrg
191706f2543Smrg    if (shmid != -1)
192706f2543Smrg    {
193706f2543Smrg        /* Successful allocation - clean up */
194706f2543Smrg	shmctl(shmid, IPC_RMID, NULL);
195706f2543Smrg    }
196706f2543Smrg    else
197706f2543Smrg    {
198706f2543Smrg        /* Allocation failed */
199706f2543Smrg        badSysCall = TRUE;
200706f2543Smrg    }
201706f2543Smrg    signal(SIGSYS, oldHandler);
202706f2543Smrg    return !badSysCall;
203706f2543Smrg}
204706f2543Smrg
205706f2543Smrg#define MUST_CHECK_FOR_SHM_SYSCALL
206706f2543Smrg
207706f2543Smrg#endif
208706f2543Smrg
209706f2543Smrgstatic Bool
210706f2543SmrgShmCloseScreen(int i, ScreenPtr pScreen)
211706f2543Smrg{
212706f2543Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
213706f2543Smrg    pScreen->CloseScreen = screen_priv->CloseScreen;
214706f2543Smrg    dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL);
215706f2543Smrg    free(screen_priv);
216706f2543Smrg    return (*pScreen->CloseScreen) (i, pScreen);
217706f2543Smrg}
218706f2543Smrg
219706f2543Smrgstatic ShmScrPrivateRec *
220706f2543SmrgShmInitScreenPriv(ScreenPtr pScreen)
221706f2543Smrg{
222706f2543Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
223706f2543Smrg    if (!screen_priv)
224706f2543Smrg    {
225706f2543Smrg	screen_priv = calloc(1, sizeof (ShmScrPrivateRec));
226706f2543Smrg	screen_priv->CloseScreen = pScreen->CloseScreen;
227706f2543Smrg	dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv);
228706f2543Smrg	pScreen->CloseScreen = ShmCloseScreen;
229706f2543Smrg    }
230706f2543Smrg    return screen_priv;
231706f2543Smrg}
232706f2543Smrg
233706f2543Smrgstatic Bool
234706f2543SmrgShmRegisterPrivates(void)
235706f2543Smrg{
236706f2543Smrg    if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec, PRIVATE_SCREEN, 0))
237706f2543Smrg	return FALSE;
238706f2543Smrg    if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec, PRIVATE_PIXMAP, 0))
239706f2543Smrg	return FALSE;
240706f2543Smrg    return TRUE;
241706f2543Smrg}
242706f2543Smrg
243706f2543Smrg/*ARGSUSED*/
244706f2543Smrgstatic void
245706f2543SmrgShmResetProc(ExtensionEntry *extEntry)
246706f2543Smrg{
247706f2543Smrg    int i;
248706f2543Smrg    for (i = 0; i < screenInfo.numScreens; i++)
249706f2543Smrg	ShmRegisterFuncs(screenInfo.screens[i], NULL);
250706f2543Smrg}
251706f2543Smrg
252706f2543Smrgvoid
253706f2543SmrgShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs)
254706f2543Smrg{
255706f2543Smrg    if (!ShmRegisterPrivates())
256706f2543Smrg	return;
257706f2543Smrg    ShmInitScreenPriv(pScreen)->shmFuncs = funcs;
258706f2543Smrg}
259706f2543Smrg
260706f2543Smrgstatic Bool
261706f2543SmrgShmDestroyPixmap (PixmapPtr pPixmap)
262706f2543Smrg{
263706f2543Smrg    ScreenPtr	    pScreen = pPixmap->drawable.pScreen;
264706f2543Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
265706f2543Smrg    Bool	    ret;
266706f2543Smrg    if (pPixmap->refcnt == 1)
267706f2543Smrg    {
268706f2543Smrg	ShmDescPtr  shmdesc;
269706f2543Smrg	shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates,
270706f2543Smrg					       shmPixmapPrivateKey);
271706f2543Smrg	if (shmdesc)
272706f2543Smrg	    ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id);
273706f2543Smrg    }
274706f2543Smrg
275706f2543Smrg    pScreen->DestroyPixmap = screen_priv->destroyPixmap;
276706f2543Smrg    ret = (*pScreen->DestroyPixmap) (pPixmap);
277706f2543Smrg    screen_priv->destroyPixmap = pScreen->DestroyPixmap;
278706f2543Smrg    pScreen->DestroyPixmap = ShmDestroyPixmap;
279706f2543Smrg    return ret;
280706f2543Smrg}
281706f2543Smrg
282706f2543Smrgvoid
283706f2543SmrgShmRegisterFbFuncs(ScreenPtr pScreen)
284706f2543Smrg{
285706f2543Smrg    ShmRegisterFuncs(pScreen, &fbFuncs);
286706f2543Smrg}
287706f2543Smrg
288706f2543Smrgstatic int
289706f2543SmrgProcShmQueryVersion(ClientPtr client)
290706f2543Smrg{
291706f2543Smrg    xShmQueryVersionReply rep;
292706f2543Smrg    int n;
293706f2543Smrg
294706f2543Smrg    REQUEST_SIZE_MATCH(xShmQueryVersionReq);
295706f2543Smrg    memset(&rep, 0, sizeof(xShmQueryVersionReply));
296706f2543Smrg    rep.type = X_Reply;
297706f2543Smrg    rep.length = 0;
298706f2543Smrg    rep.sequenceNumber = client->sequence;
299706f2543Smrg    rep.sharedPixmaps = sharedPixmaps;
300706f2543Smrg    rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0;
301706f2543Smrg    rep.majorVersion = SERVER_SHM_MAJOR_VERSION;
302706f2543Smrg    rep.minorVersion = SERVER_SHM_MINOR_VERSION;
303706f2543Smrg    rep.uid = geteuid();
304706f2543Smrg    rep.gid = getegid();
305706f2543Smrg    if (client->swapped) {
306706f2543Smrg    	swaps(&rep.sequenceNumber, n);
307706f2543Smrg    	swapl(&rep.length, n);
308706f2543Smrg	swaps(&rep.majorVersion, n);
309706f2543Smrg	swaps(&rep.minorVersion, n);
310706f2543Smrg	swaps(&rep.uid, n);
311706f2543Smrg	swaps(&rep.gid, n);
312706f2543Smrg    }
313706f2543Smrg    WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep);
314706f2543Smrg    return Success;
315706f2543Smrg}
316706f2543Smrg
317706f2543Smrg/*
318706f2543Smrg * Simulate the access() system call for a shared memory segement,
319706f2543Smrg * using the credentials from the client if available
320706f2543Smrg */
321706f2543Smrgstatic int
322706f2543Smrgshm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly)
323706f2543Smrg{
324706f2543Smrg    int uid, gid;
325706f2543Smrg    mode_t mask;
326706f2543Smrg    int uidset = 0, gidset = 0;
327706f2543Smrg    LocalClientCredRec *lcc;
328706f2543Smrg
329706f2543Smrg    if (GetLocalClientCreds(client, &lcc) != -1) {
330706f2543Smrg
331706f2543Smrg	if (lcc->fieldsSet & LCC_UID_SET) {
332706f2543Smrg	    uid = lcc->euid;
333706f2543Smrg	    uidset = 1;
334706f2543Smrg	}
335706f2543Smrg	if (lcc->fieldsSet & LCC_GID_SET) {
336706f2543Smrg	    gid = lcc->egid;
337706f2543Smrg	    gidset = 1;
338706f2543Smrg	}
339706f2543Smrg
340706f2543Smrg#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID)
341706f2543Smrg	if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1)
342706f2543Smrg	     || (lcc->zoneid != SHMPERM_ZONEID(perm))) {
343706f2543Smrg		uidset = 0;
344706f2543Smrg		gidset = 0;
345706f2543Smrg	}
346706f2543Smrg#endif
347706f2543Smrg	FreeLocalClientCreds(lcc);
348706f2543Smrg
349706f2543Smrg	if (uidset) {
350706f2543Smrg	    /* User id 0 always gets access */
351706f2543Smrg	    if (uid == 0) {
352706f2543Smrg		return 0;
353706f2543Smrg	    }
354706f2543Smrg	    /* Check the owner */
355706f2543Smrg	    if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) {
356706f2543Smrg		mask = S_IRUSR;
357706f2543Smrg		if (!readonly) {
358706f2543Smrg		    mask |= S_IWUSR;
359706f2543Smrg		}
360706f2543Smrg		return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
361706f2543Smrg	    }
362706f2543Smrg	}
363706f2543Smrg
364706f2543Smrg	if (gidset) {
365706f2543Smrg	    /* Check the group */
366706f2543Smrg	    if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) {
367706f2543Smrg		mask = S_IRGRP;
368706f2543Smrg		if (!readonly) {
369706f2543Smrg		    mask |= S_IWGRP;
370706f2543Smrg		}
371706f2543Smrg		return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
372706f2543Smrg	    }
373706f2543Smrg	}
374706f2543Smrg    }
375706f2543Smrg    /* Otherwise, check everyone else */
376706f2543Smrg    mask = S_IROTH;
377706f2543Smrg    if (!readonly) {
378706f2543Smrg	mask |= S_IWOTH;
379706f2543Smrg    }
380706f2543Smrg    return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
381706f2543Smrg}
382706f2543Smrg
383706f2543Smrgstatic int
384706f2543SmrgProcShmAttach(ClientPtr client)
385706f2543Smrg{
386706f2543Smrg    SHMSTAT_TYPE buf;
387706f2543Smrg    ShmDescPtr shmdesc;
388706f2543Smrg    REQUEST(xShmAttachReq);
389706f2543Smrg
390706f2543Smrg    REQUEST_SIZE_MATCH(xShmAttachReq);
391706f2543Smrg    LEGAL_NEW_RESOURCE(stuff->shmseg, client);
392706f2543Smrg    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse))
393706f2543Smrg    {
394706f2543Smrg	client->errorValue = stuff->readOnly;
395706f2543Smrg        return BadValue;
396706f2543Smrg    }
397706f2543Smrg    for (shmdesc = Shmsegs;
398706f2543Smrg	 shmdesc && (shmdesc->shmid != stuff->shmid);
399706f2543Smrg	 shmdesc = shmdesc->next)
400706f2543Smrg	;
401706f2543Smrg    if (shmdesc)
402706f2543Smrg    {
403706f2543Smrg	if (!stuff->readOnly && !shmdesc->writable)
404706f2543Smrg	    return BadAccess;
405706f2543Smrg	shmdesc->refcnt++;
406706f2543Smrg    }
407706f2543Smrg    else
408706f2543Smrg    {
409706f2543Smrg	shmdesc = malloc(sizeof(ShmDescRec));
410706f2543Smrg	if (!shmdesc)
411706f2543Smrg	    return BadAlloc;
412706f2543Smrg	shmdesc->addr = shmat(stuff->shmid, 0,
413706f2543Smrg			      stuff->readOnly ? SHM_RDONLY : 0);
414706f2543Smrg	if ((shmdesc->addr == ((char *)-1)) ||
415706f2543Smrg	    SHMSTAT(stuff->shmid, &buf))
416706f2543Smrg	{
417706f2543Smrg	    free(shmdesc);
418706f2543Smrg	    return BadAccess;
419706f2543Smrg	}
420706f2543Smrg
421706f2543Smrg	/* The attach was performed with root privs. We must
422706f2543Smrg	 * do manual checking of access rights for the credentials
423706f2543Smrg	 * of the client */
424706f2543Smrg
425706f2543Smrg	if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) {
426706f2543Smrg	    shmdt(shmdesc->addr);
427706f2543Smrg	    free(shmdesc);
428706f2543Smrg	    return BadAccess;
429706f2543Smrg	}
430706f2543Smrg
431706f2543Smrg	shmdesc->shmid = stuff->shmid;
432706f2543Smrg	shmdesc->refcnt = 1;
433706f2543Smrg	shmdesc->writable = !stuff->readOnly;
434706f2543Smrg	shmdesc->size = SHM_SEGSZ(buf);
435706f2543Smrg	shmdesc->next = Shmsegs;
436706f2543Smrg	Shmsegs = shmdesc;
437706f2543Smrg    }
438706f2543Smrg    if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc))
439706f2543Smrg	return BadAlloc;
440706f2543Smrg    return Success;
441706f2543Smrg}
442706f2543Smrg
443706f2543Smrg/*ARGSUSED*/
444706f2543Smrgstatic int
445706f2543SmrgShmDetachSegment(pointer value, /* must conform to DeleteType */
446706f2543Smrg		 XID shmseg)
447706f2543Smrg{
448706f2543Smrg    ShmDescPtr shmdesc = (ShmDescPtr)value;
449706f2543Smrg    ShmDescPtr *prev;
450706f2543Smrg
451706f2543Smrg    if (--shmdesc->refcnt)
452706f2543Smrg	return TRUE;
453706f2543Smrg    shmdt(shmdesc->addr);
454706f2543Smrg    for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next)
455706f2543Smrg	;
456706f2543Smrg    *prev = shmdesc->next;
457706f2543Smrg    free(shmdesc);
458706f2543Smrg    return Success;
459706f2543Smrg}
460706f2543Smrg
461706f2543Smrgstatic int
462706f2543SmrgProcShmDetach(ClientPtr client)
463706f2543Smrg{
464706f2543Smrg    ShmDescPtr shmdesc;
465706f2543Smrg    REQUEST(xShmDetachReq);
466706f2543Smrg
467706f2543Smrg    REQUEST_SIZE_MATCH(xShmDetachReq);
468706f2543Smrg    VERIFY_SHMSEG(stuff->shmseg, shmdesc, client);
469706f2543Smrg    FreeResource(stuff->shmseg, RT_NONE);
470706f2543Smrg    return Success;
471706f2543Smrg}
472706f2543Smrg
473706f2543Smrg/*
474706f2543Smrg * If the given request doesn't exactly match PutImage's constraints,
475706f2543Smrg * wrap the image in a scratch pixmap header and let CopyArea sort it out.
476706f2543Smrg */
477706f2543Smrgstatic void
478706f2543SmrgdoShmPutImage(DrawablePtr dst, GCPtr pGC,
479706f2543Smrg	      int depth, unsigned int format,
480706f2543Smrg	      int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
481706f2543Smrg	      char *data)
482706f2543Smrg{
483706f2543Smrg    PixmapPtr pPixmap;
484706f2543Smrg
485706f2543Smrg    if (format == ZPixmap || (format == XYPixmap && depth == 1)) {
486706f2543Smrg	pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
487706f2543Smrg					 BitsPerPixel(depth),
488706f2543Smrg					 PixmapBytePad(w, depth),
489706f2543Smrg					 data);
490706f2543Smrg	if (!pPixmap)
491706f2543Smrg	    return;
492706f2543Smrg	pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy);
493706f2543Smrg	FreeScratchPixmapHeader(pPixmap);
494706f2543Smrg    } else {
495706f2543Smrg	GCPtr putGC = GetScratchGC(depth, dst->pScreen);
496706f2543Smrg
497706f2543Smrg	if (!putGC)
498706f2543Smrg	    return;
499706f2543Smrg
500706f2543Smrg	pPixmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth,
501706f2543Smrg						CREATE_PIXMAP_USAGE_SCRATCH);
502706f2543Smrg	if (!pPixmap) {
503706f2543Smrg	    FreeScratchGC(putGC);
504706f2543Smrg	    return;
505706f2543Smrg	}
506706f2543Smrg	ValidateGC(&pPixmap->drawable, putGC);
507706f2543Smrg	(*putGC->ops->PutImage)(&pPixmap->drawable, putGC, depth, -sx, -sy, w, h, 0,
508706f2543Smrg				(format == XYPixmap) ? XYPixmap : ZPixmap, data);
509706f2543Smrg	FreeScratchGC(putGC);
510706f2543Smrg	if (format == XYBitmap)
511706f2543Smrg	    (void)(*pGC->ops->CopyPlane)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
512706f2543Smrg					 dx, dy, 1L);
513706f2543Smrg	else
514706f2543Smrg	    (void)(*pGC->ops->CopyArea)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
515706f2543Smrg					dx, dy);
516706f2543Smrg	(*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
517706f2543Smrg    }
518706f2543Smrg}
519706f2543Smrg
520706f2543Smrgstatic int
521706f2543SmrgProcShmPutImage(ClientPtr client)
522706f2543Smrg{
523706f2543Smrg    GCPtr pGC;
524706f2543Smrg    DrawablePtr pDraw;
525706f2543Smrg    long length;
526706f2543Smrg    ShmDescPtr shmdesc;
527706f2543Smrg    REQUEST(xShmPutImageReq);
528706f2543Smrg
529706f2543Smrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
530706f2543Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
531706f2543Smrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);
532706f2543Smrg    if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
533706f2543Smrg	return BadValue;
534706f2543Smrg    if (stuff->format == XYBitmap)
535706f2543Smrg    {
536706f2543Smrg        if (stuff->depth != 1)
537706f2543Smrg            return BadMatch;
538706f2543Smrg        length = PixmapBytePad(stuff->totalWidth, 1);
539706f2543Smrg    }
540706f2543Smrg    else if (stuff->format == XYPixmap)
541706f2543Smrg    {
542706f2543Smrg        if (pDraw->depth != stuff->depth)
543706f2543Smrg            return BadMatch;
544706f2543Smrg        length = PixmapBytePad(stuff->totalWidth, 1);
545706f2543Smrg	length *= stuff->depth;
546706f2543Smrg    }
547706f2543Smrg    else if (stuff->format == ZPixmap)
548706f2543Smrg    {
549706f2543Smrg        if (pDraw->depth != stuff->depth)
550706f2543Smrg            return BadMatch;
551706f2543Smrg        length = PixmapBytePad(stuff->totalWidth, stuff->depth);
552706f2543Smrg    }
553706f2543Smrg    else
554706f2543Smrg    {
555706f2543Smrg	client->errorValue = stuff->format;
556706f2543Smrg        return BadValue;
557706f2543Smrg    }
558706f2543Smrg
559706f2543Smrg    /*
560706f2543Smrg     * There's a potential integer overflow in this check:
561706f2543Smrg     * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
562706f2543Smrg     *                client);
563706f2543Smrg     * the version below ought to avoid it
564706f2543Smrg     */
565706f2543Smrg    if (stuff->totalHeight != 0 &&
566706f2543Smrg	length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
567706f2543Smrg	client->errorValue = stuff->totalWidth;
568706f2543Smrg	return BadValue;
569706f2543Smrg    }
570706f2543Smrg    if (stuff->srcX > stuff->totalWidth)
571706f2543Smrg    {
572706f2543Smrg	client->errorValue = stuff->srcX;
573706f2543Smrg	return BadValue;
574706f2543Smrg    }
575706f2543Smrg    if (stuff->srcY > stuff->totalHeight)
576706f2543Smrg    {
577706f2543Smrg	client->errorValue = stuff->srcY;
578706f2543Smrg	return BadValue;
579706f2543Smrg    }
580706f2543Smrg    if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth)
581706f2543Smrg    {
582706f2543Smrg	client->errorValue = stuff->srcWidth;
583706f2543Smrg	return BadValue;
584706f2543Smrg    }
585706f2543Smrg    if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight)
586706f2543Smrg    {
587706f2543Smrg	client->errorValue = stuff->srcHeight;
588706f2543Smrg	return BadValue;
589706f2543Smrg    }
590706f2543Smrg
591706f2543Smrg    if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) ||
592706f2543Smrg	 ((stuff->format != ZPixmap) &&
593706f2543Smrg	  (stuff->srcX < screenInfo.bitmapScanlinePad) &&
594706f2543Smrg	  ((stuff->format == XYBitmap) ||
595706f2543Smrg	   ((stuff->srcY == 0) &&
596706f2543Smrg	    (stuff->srcHeight == stuff->totalHeight))))) &&
597706f2543Smrg	((stuff->srcX + stuff->srcWidth) == stuff->totalWidth))
598706f2543Smrg	(*pGC->ops->PutImage) (pDraw, pGC, stuff->depth,
599706f2543Smrg			       stuff->dstX, stuff->dstY,
600706f2543Smrg			       stuff->totalWidth, stuff->srcHeight,
601706f2543Smrg			       stuff->srcX, stuff->format,
602706f2543Smrg			       shmdesc->addr + stuff->offset +
603706f2543Smrg			       (stuff->srcY * length));
604706f2543Smrg    else
605706f2543Smrg	doShmPutImage(pDraw, pGC, stuff->depth, stuff->format,
606706f2543Smrg		      stuff->totalWidth, stuff->totalHeight,
607706f2543Smrg		      stuff->srcX, stuff->srcY,
608706f2543Smrg		      stuff->srcWidth, stuff->srcHeight,
609706f2543Smrg		      stuff->dstX, stuff->dstY,
610706f2543Smrg                      shmdesc->addr + stuff->offset);
611706f2543Smrg
612706f2543Smrg    if (stuff->sendEvent)
613706f2543Smrg    {
614706f2543Smrg	xShmCompletionEvent ev;
615706f2543Smrg
616706f2543Smrg	ev.type = ShmCompletionCode;
617706f2543Smrg	ev.drawable = stuff->drawable;
618706f2543Smrg	ev.minorEvent = X_ShmPutImage;
619706f2543Smrg	ev.majorEvent = ShmReqCode;
620706f2543Smrg	ev.shmseg = stuff->shmseg;
621706f2543Smrg	ev.offset = stuff->offset;
622706f2543Smrg	WriteEventsToClient(client, 1, (xEvent *) &ev);
623706f2543Smrg    }
624706f2543Smrg
625706f2543Smrg    return Success;
626706f2543Smrg}
627706f2543Smrg
628706f2543Smrgstatic int
629706f2543SmrgProcShmGetImage(ClientPtr client)
630706f2543Smrg{
631706f2543Smrg    DrawablePtr		pDraw;
632706f2543Smrg    long		lenPer = 0, length;
633706f2543Smrg    Mask		plane = 0;
634706f2543Smrg    xShmGetImageReply	xgi;
635706f2543Smrg    ShmDescPtr		shmdesc;
636706f2543Smrg    int			n, rc;
637706f2543Smrg
638706f2543Smrg    REQUEST(xShmGetImageReq);
639706f2543Smrg
640706f2543Smrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
641706f2543Smrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap))
642706f2543Smrg    {
643706f2543Smrg	client->errorValue = stuff->format;
644706f2543Smrg        return BadValue;
645706f2543Smrg    }
646706f2543Smrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
647706f2543Smrg			   DixReadAccess);
648706f2543Smrg    if (rc != Success)
649706f2543Smrg	return rc;
650706f2543Smrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
651706f2543Smrg    if (pDraw->type == DRAWABLE_WINDOW)
652706f2543Smrg    {
653706f2543Smrg      if( /* check for being viewable */
654706f2543Smrg	 !((WindowPtr) pDraw)->realized ||
655706f2543Smrg	  /* check for being on screen */
656706f2543Smrg         pDraw->x + stuff->x < 0 ||
657706f2543Smrg         pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width ||
658706f2543Smrg         pDraw->y + stuff->y < 0 ||
659706f2543Smrg         pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height ||
660706f2543Smrg          /* check for being inside of border */
661706f2543Smrg         stuff->x < - wBorderWidth((WindowPtr)pDraw) ||
662706f2543Smrg         stuff->x + (int)stuff->width >
663706f2543Smrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
664706f2543Smrg         stuff->y < -wBorderWidth((WindowPtr)pDraw) ||
665706f2543Smrg         stuff->y + (int)stuff->height >
666706f2543Smrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height
667706f2543Smrg        )
668706f2543Smrg	    return BadMatch;
669706f2543Smrg	xgi.visual = wVisual(((WindowPtr)pDraw));
670706f2543Smrg    }
671706f2543Smrg    else
672706f2543Smrg    {
673706f2543Smrg	if (stuff->x < 0 ||
674706f2543Smrg	    stuff->x+(int)stuff->width > pDraw->width ||
675706f2543Smrg	    stuff->y < 0 ||
676706f2543Smrg	    stuff->y+(int)stuff->height > pDraw->height
677706f2543Smrg	    )
678706f2543Smrg	    return BadMatch;
679706f2543Smrg	xgi.visual = None;
680706f2543Smrg    }
681706f2543Smrg    xgi.type = X_Reply;
682706f2543Smrg    xgi.length = 0;
683706f2543Smrg    xgi.sequenceNumber = client->sequence;
684706f2543Smrg    xgi.depth = pDraw->depth;
685706f2543Smrg    if(stuff->format == ZPixmap)
686706f2543Smrg    {
687706f2543Smrg	length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height;
688706f2543Smrg    }
689706f2543Smrg    else
690706f2543Smrg    {
691706f2543Smrg	lenPer = PixmapBytePad(stuff->width, 1) * stuff->height;
692706f2543Smrg	plane = ((Mask)1) << (pDraw->depth - 1);
693706f2543Smrg	/* only planes asked for */
694706f2543Smrg	length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1)));
695706f2543Smrg    }
696706f2543Smrg
697706f2543Smrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
698706f2543Smrg    xgi.size = length;
699706f2543Smrg
700706f2543Smrg    if (length == 0)
701706f2543Smrg    {
702706f2543Smrg	/* nothing to do */
703706f2543Smrg    }
704706f2543Smrg    else if (stuff->format == ZPixmap)
705706f2543Smrg    {
706706f2543Smrg	(*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y,
707706f2543Smrg				    stuff->width, stuff->height,
708706f2543Smrg				    stuff->format, stuff->planeMask,
709706f2543Smrg				    shmdesc->addr + stuff->offset);
710706f2543Smrg    }
711706f2543Smrg    else
712706f2543Smrg    {
713706f2543Smrg
714706f2543Smrg	length = stuff->offset;
715706f2543Smrg        for (; plane; plane >>= 1)
716706f2543Smrg	{
717706f2543Smrg	    if (stuff->planeMask & plane)
718706f2543Smrg	    {
719706f2543Smrg		(*pDraw->pScreen->GetImage)(pDraw,
720706f2543Smrg					    stuff->x, stuff->y,
721706f2543Smrg					    stuff->width, stuff->height,
722706f2543Smrg					    stuff->format, plane,
723706f2543Smrg					    shmdesc->addr + length);
724706f2543Smrg		length += lenPer;
725706f2543Smrg	    }
726706f2543Smrg	}
727706f2543Smrg    }
728706f2543Smrg
729706f2543Smrg    if (client->swapped) {
730706f2543Smrg	swaps(&xgi.sequenceNumber, n);
731706f2543Smrg	swapl(&xgi.length, n);
732706f2543Smrg	swapl(&xgi.visual, n);
733706f2543Smrg	swapl(&xgi.size, n);
734706f2543Smrg    }
735706f2543Smrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
736706f2543Smrg
737706f2543Smrg    return Success;
738706f2543Smrg}
739706f2543Smrg
740706f2543Smrg#ifdef PANORAMIX
741706f2543Smrgstatic int
742706f2543SmrgProcPanoramiXShmPutImage(ClientPtr client)
743706f2543Smrg{
744706f2543Smrg    int			 j, result, orig_x, orig_y;
745706f2543Smrg    PanoramiXRes	*draw, *gc;
746706f2543Smrg    Bool		 sendEvent, isRoot;
747706f2543Smrg
748706f2543Smrg    REQUEST(xShmPutImageReq);
749706f2543Smrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
750706f2543Smrg
751706f2543Smrg    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
752706f2543Smrg				      XRC_DRAWABLE, client, DixWriteAccess);
753706f2543Smrg    if (result != Success)
754706f2543Smrg        return (result == BadValue) ? BadDrawable : result;
755706f2543Smrg
756706f2543Smrg    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
757706f2543Smrg				     XRT_GC, client, DixReadAccess);
758706f2543Smrg    if (result != Success)
759706f2543Smrg        return result;
760706f2543Smrg
761706f2543Smrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
762706f2543Smrg
763706f2543Smrg    orig_x = stuff->dstX;
764706f2543Smrg    orig_y = stuff->dstY;
765706f2543Smrg    sendEvent = stuff->sendEvent;
766706f2543Smrg    stuff->sendEvent = 0;
767706f2543Smrg    FOR_NSCREENS(j) {
768706f2543Smrg	if(!j) stuff->sendEvent = sendEvent;
769706f2543Smrg	stuff->drawable = draw->info[j].id;
770706f2543Smrg	stuff->gc = gc->info[j].id;
771706f2543Smrg	if (isRoot) {
772706f2543Smrg	    stuff->dstX = orig_x - screenInfo.screens[j]->x;
773706f2543Smrg	    stuff->dstY = orig_y - screenInfo.screens[j]->y;
774706f2543Smrg	}
775706f2543Smrg	result = ProcShmPutImage(client);
776706f2543Smrg	if(result != Success) break;
777706f2543Smrg    }
778706f2543Smrg    return result;
779706f2543Smrg}
780706f2543Smrg
781706f2543Smrgstatic int
782706f2543SmrgProcPanoramiXShmGetImage(ClientPtr client)
783706f2543Smrg{
784706f2543Smrg    PanoramiXRes	*draw;
785706f2543Smrg    DrawablePtr 	*drawables;
786706f2543Smrg    DrawablePtr 	pDraw;
787706f2543Smrg    xShmGetImageReply	xgi;
788706f2543Smrg    ShmDescPtr		shmdesc;
789706f2543Smrg    int         	i, x, y, w, h, format, rc;
790706f2543Smrg    Mask		plane = 0, planemask;
791706f2543Smrg    long		lenPer = 0, length, widthBytesLine;
792706f2543Smrg    Bool		isRoot;
793706f2543Smrg
794706f2543Smrg    REQUEST(xShmGetImageReq);
795706f2543Smrg
796706f2543Smrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
797706f2543Smrg
798706f2543Smrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) {
799706f2543Smrg	client->errorValue = stuff->format;
800706f2543Smrg        return BadValue;
801706f2543Smrg    }
802706f2543Smrg
803706f2543Smrg    rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
804706f2543Smrg				  XRC_DRAWABLE, client, DixWriteAccess);
805706f2543Smrg    if (rc != Success)
806706f2543Smrg	return (rc == BadValue) ? BadDrawable : rc;
807706f2543Smrg
808706f2543Smrg    if (draw->type == XRT_PIXMAP)
809706f2543Smrg	return ProcShmGetImage(client);
810706f2543Smrg
811706f2543Smrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
812706f2543Smrg			   DixReadAccess);
813706f2543Smrg    if (rc != Success)
814706f2543Smrg	return rc;
815706f2543Smrg
816706f2543Smrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
817706f2543Smrg
818706f2543Smrg    x = stuff->x;
819706f2543Smrg    y = stuff->y;
820706f2543Smrg    w = stuff->width;
821706f2543Smrg    h = stuff->height;
822706f2543Smrg    format = stuff->format;
823706f2543Smrg    planemask = stuff->planeMask;
824706f2543Smrg
825706f2543Smrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
826706f2543Smrg
827706f2543Smrg    if(isRoot) {
828706f2543Smrg      if( /* check for being onscreen */
829706f2543Smrg	x < 0 || x + w > PanoramiXPixWidth ||
830706f2543Smrg	y < 0 || y + h > PanoramiXPixHeight )
831706f2543Smrg	    return BadMatch;
832706f2543Smrg    } else {
833706f2543Smrg      if( /* check for being onscreen */
834706f2543Smrg	screenInfo.screens[0]->x + pDraw->x + x < 0 ||
835706f2543Smrg	screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth ||
836706f2543Smrg	screenInfo.screens[0]->y + pDraw->y + y < 0 ||
837706f2543Smrg	screenInfo.screens[0]->y + pDraw->y + y + h > PanoramiXPixHeight ||
838706f2543Smrg	 /* check for being inside of border */
839706f2543Smrg       	x < - wBorderWidth((WindowPtr)pDraw) ||
840706f2543Smrg	x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
841706f2543Smrg	y < -wBorderWidth((WindowPtr)pDraw) ||
842706f2543Smrg	y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height)
843706f2543Smrg	    return BadMatch;
844706f2543Smrg    }
845706f2543Smrg
846706f2543Smrg    drawables = calloc(PanoramiXNumScreens, sizeof(DrawablePtr));
847706f2543Smrg    if(!drawables)
848706f2543Smrg	return BadAlloc;
849706f2543Smrg
850706f2543Smrg    drawables[0] = pDraw;
851706f2543Smrg    for(i = 1; i < PanoramiXNumScreens; i++) {
852706f2543Smrg	rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
853706f2543Smrg			       DixReadAccess);
854706f2543Smrg	if (rc != Success)
855706f2543Smrg	{
856706f2543Smrg	    free(drawables);
857706f2543Smrg	    return rc;
858706f2543Smrg	}
859706f2543Smrg    }
860706f2543Smrg
861706f2543Smrg    xgi.visual = wVisual(((WindowPtr)pDraw));
862706f2543Smrg    xgi.type = X_Reply;
863706f2543Smrg    xgi.length = 0;
864706f2543Smrg    xgi.sequenceNumber = client->sequence;
865706f2543Smrg    xgi.depth = pDraw->depth;
866706f2543Smrg
867706f2543Smrg    if(format == ZPixmap) {
868706f2543Smrg	widthBytesLine = PixmapBytePad(w, pDraw->depth);
869706f2543Smrg	length = widthBytesLine * h;
870706f2543Smrg    } else {
871706f2543Smrg	widthBytesLine = PixmapBytePad(w, 1);
872706f2543Smrg	lenPer = widthBytesLine * h;
873706f2543Smrg	plane = ((Mask)1) << (pDraw->depth - 1);
874706f2543Smrg	length = lenPer * Ones(planemask & (plane | (plane - 1)));
875706f2543Smrg    }
876706f2543Smrg
877706f2543Smrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
878706f2543Smrg    xgi.size = length;
879706f2543Smrg
880706f2543Smrg    if (length == 0) {/* nothing to do */ }
881706f2543Smrg    else if (format == ZPixmap) {
882706f2543Smrg	    XineramaGetImageData(drawables, x, y, w, h, format, planemask,
883706f2543Smrg					shmdesc->addr + stuff->offset,
884706f2543Smrg					widthBytesLine, isRoot);
885706f2543Smrg    } else {
886706f2543Smrg
887706f2543Smrg	length = stuff->offset;
888706f2543Smrg        for (; plane; plane >>= 1) {
889706f2543Smrg	    if (planemask & plane) {
890706f2543Smrg		XineramaGetImageData(drawables, x, y, w, h,
891706f2543Smrg				     format, plane, shmdesc->addr + length,
892706f2543Smrg				     widthBytesLine, isRoot);
893706f2543Smrg		length += lenPer;
894706f2543Smrg	    }
895706f2543Smrg	}
896706f2543Smrg    }
897706f2543Smrg    free(drawables);
898706f2543Smrg
899706f2543Smrg    if (client->swapped) {
900706f2543Smrg	int n;
901706f2543Smrg    	swaps(&xgi.sequenceNumber, n);
902706f2543Smrg    	swapl(&xgi.length, n);
903706f2543Smrg	swapl(&xgi.visual, n);
904706f2543Smrg	swapl(&xgi.size, n);
905706f2543Smrg    }
906706f2543Smrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
907706f2543Smrg
908706f2543Smrg    return Success;
909706f2543Smrg}
910706f2543Smrg
911706f2543Smrgstatic int
912706f2543SmrgProcPanoramiXShmCreatePixmap(ClientPtr client)
913706f2543Smrg{
914706f2543Smrg    ScreenPtr pScreen = NULL;
915706f2543Smrg    PixmapPtr pMap = NULL;
916706f2543Smrg    DrawablePtr pDraw;
917706f2543Smrg    DepthPtr pDepth;
918706f2543Smrg    int i, j, result, rc;
919706f2543Smrg    ShmDescPtr shmdesc;
920706f2543Smrg    REQUEST(xShmCreatePixmapReq);
921706f2543Smrg    unsigned int width, height, depth;
922706f2543Smrg    unsigned long size;
923706f2543Smrg    PanoramiXRes *newPix;
924706f2543Smrg
925706f2543Smrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
926706f2543Smrg    client->errorValue = stuff->pid;
927706f2543Smrg    if (!sharedPixmaps)
928706f2543Smrg	return BadImplementation;
929706f2543Smrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
930706f2543Smrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
931706f2543Smrg			   DixGetAttrAccess);
932706f2543Smrg    if (rc != Success)
933706f2543Smrg	return rc;
934706f2543Smrg
935706f2543Smrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
936706f2543Smrg
937706f2543Smrg    width = stuff->width;
938706f2543Smrg    height = stuff->height;
939706f2543Smrg    depth = stuff->depth;
940706f2543Smrg    if (!width || !height || !depth)
941706f2543Smrg    {
942706f2543Smrg	client->errorValue = 0;
943706f2543Smrg        return BadValue;
944706f2543Smrg    }
945706f2543Smrg    if (width > 32767 || height > 32767)
946706f2543Smrg        return BadAlloc;
947706f2543Smrg
948706f2543Smrg    if (stuff->depth != 1)
949706f2543Smrg    {
950706f2543Smrg        pDepth = pDraw->pScreen->allowedDepths;
951706f2543Smrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
952706f2543Smrg	   if (pDepth->depth == stuff->depth)
953706f2543Smrg               goto CreatePmap;
954706f2543Smrg	client->errorValue = stuff->depth;
955706f2543Smrg        return BadValue;
956706f2543Smrg    }
957706f2543Smrg
958706f2543SmrgCreatePmap:
959706f2543Smrg    size = PixmapBytePad(width, depth) * height;
960706f2543Smrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
961706f2543Smrg        if (size < width * height)
962706f2543Smrg            return BadAlloc;
963706f2543Smrg    }
964706f2543Smrg    /* thankfully, offset is unsigned */
965706f2543Smrg    if (stuff->offset + size < size)
966706f2543Smrg	return BadAlloc;
967706f2543Smrg
968706f2543Smrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
969706f2543Smrg
970706f2543Smrg    if(!(newPix = malloc(sizeof(PanoramiXRes))))
971706f2543Smrg	return BadAlloc;
972706f2543Smrg
973706f2543Smrg    newPix->type = XRT_PIXMAP;
974706f2543Smrg    newPix->u.pix.shared = TRUE;
975706f2543Smrg    newPix->info[0].id = stuff->pid;
976706f2543Smrg    for(j = 1; j < PanoramiXNumScreens; j++)
977706f2543Smrg	newPix->info[j].id = FakeClientID(client->index);
978706f2543Smrg
979706f2543Smrg    result = Success;
980706f2543Smrg
981706f2543Smrg    FOR_NSCREENS(j) {
982706f2543Smrg	ShmScrPrivateRec *screen_priv;
983706f2543Smrg	pScreen = screenInfo.screens[j];
984706f2543Smrg
985706f2543Smrg	screen_priv = ShmGetScreenPriv(pScreen);
986706f2543Smrg	pMap = (*screen_priv->shmFuncs->CreatePixmap)(pScreen,
987706f2543Smrg				stuff->width, stuff->height, stuff->depth,
988706f2543Smrg				shmdesc->addr + stuff->offset);
989706f2543Smrg
990706f2543Smrg	if (pMap) {
991706f2543Smrg	    dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc);
992706f2543Smrg            shmdesc->refcnt++;
993706f2543Smrg	    pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
994706f2543Smrg	    pMap->drawable.id = newPix->info[j].id;
995706f2543Smrg	    if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) {
996706f2543Smrg		result = BadAlloc;
997706f2543Smrg		break;
998706f2543Smrg	    }
999706f2543Smrg	} else {
1000706f2543Smrg	   result = BadAlloc;
1001706f2543Smrg	   break;
1002706f2543Smrg	}
1003706f2543Smrg    }
1004706f2543Smrg
1005706f2543Smrg    if(result == BadAlloc) {
1006706f2543Smrg	while(j--)
1007706f2543Smrg	    FreeResource(newPix->info[j].id, RT_NONE);
1008706f2543Smrg	free(newPix);
1009706f2543Smrg    } else
1010706f2543Smrg	AddResource(stuff->pid, XRT_PIXMAP, newPix);
1011706f2543Smrg
1012706f2543Smrg    return result;
1013706f2543Smrg}
1014706f2543Smrg#endif
1015706f2543Smrg
1016706f2543Smrgstatic PixmapPtr
1017706f2543SmrgfbShmCreatePixmap (ScreenPtr pScreen,
1018706f2543Smrg		   int width, int height, int depth, char *addr)
1019706f2543Smrg{
1020706f2543Smrg    PixmapPtr pPixmap;
1021706f2543Smrg
1022706f2543Smrg    pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
1023706f2543Smrg    if (!pPixmap)
1024706f2543Smrg	return NullPixmap;
1025706f2543Smrg
1026706f2543Smrg    if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
1027706f2543Smrg	    BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) {
1028706f2543Smrg	(*pScreen->DestroyPixmap)(pPixmap);
1029706f2543Smrg	return NullPixmap;
1030706f2543Smrg    }
1031706f2543Smrg    return pPixmap;
1032706f2543Smrg}
1033706f2543Smrg
1034706f2543Smrgstatic int
1035706f2543SmrgProcShmCreatePixmap(ClientPtr client)
1036706f2543Smrg{
1037706f2543Smrg    PixmapPtr pMap;
1038706f2543Smrg    DrawablePtr pDraw;
1039706f2543Smrg    DepthPtr pDepth;
1040706f2543Smrg    int i, rc;
1041706f2543Smrg    ShmDescPtr shmdesc;
1042706f2543Smrg    ShmScrPrivateRec *screen_priv;
1043706f2543Smrg    REQUEST(xShmCreatePixmapReq);
1044706f2543Smrg    unsigned int width, height, depth;
1045706f2543Smrg    unsigned long size;
1046706f2543Smrg
1047706f2543Smrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
1048706f2543Smrg    client->errorValue = stuff->pid;
1049706f2543Smrg    if (!sharedPixmaps)
1050706f2543Smrg	return BadImplementation;
1051706f2543Smrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
1052706f2543Smrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1053706f2543Smrg			   DixGetAttrAccess);
1054706f2543Smrg    if (rc != Success)
1055706f2543Smrg	return rc;
1056706f2543Smrg
1057706f2543Smrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
1058706f2543Smrg
1059706f2543Smrg    width = stuff->width;
1060706f2543Smrg    height = stuff->height;
1061706f2543Smrg    depth = stuff->depth;
1062706f2543Smrg    if (!width || !height || !depth)
1063706f2543Smrg    {
1064706f2543Smrg	client->errorValue = 0;
1065706f2543Smrg        return BadValue;
1066706f2543Smrg    }
1067706f2543Smrg    if (width > 32767 || height > 32767)
1068706f2543Smrg	return BadAlloc;
1069706f2543Smrg
1070706f2543Smrg    if (stuff->depth != 1)
1071706f2543Smrg    {
1072706f2543Smrg        pDepth = pDraw->pScreen->allowedDepths;
1073706f2543Smrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
1074706f2543Smrg	   if (pDepth->depth == stuff->depth)
1075706f2543Smrg               goto CreatePmap;
1076706f2543Smrg	client->errorValue = stuff->depth;
1077706f2543Smrg        return BadValue;
1078706f2543Smrg    }
1079706f2543Smrg
1080706f2543SmrgCreatePmap:
1081706f2543Smrg    size = PixmapBytePad(width, depth) * height;
1082706f2543Smrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
1083706f2543Smrg	if (size < width * height)
1084706f2543Smrg	    return BadAlloc;
1085706f2543Smrg    }
1086706f2543Smrg    /* thankfully, offset is unsigned */
1087706f2543Smrg    if (stuff->offset + size < size)
1088706f2543Smrg	return BadAlloc;
1089706f2543Smrg
1090706f2543Smrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
1091706f2543Smrg    screen_priv = ShmGetScreenPriv(pDraw->pScreen);
1092706f2543Smrg    pMap = (*screen_priv->shmFuncs->CreatePixmap)(
1093706f2543Smrg			    pDraw->pScreen, stuff->width,
1094706f2543Smrg			    stuff->height, stuff->depth,
1095706f2543Smrg			    shmdesc->addr + stuff->offset);
1096706f2543Smrg    if (pMap)
1097706f2543Smrg    {
1098706f2543Smrg	rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1099706f2543Smrg		      pMap, RT_NONE, NULL, DixCreateAccess);
1100706f2543Smrg	if (rc != Success) {
1101706f2543Smrg	    pDraw->pScreen->DestroyPixmap(pMap);
1102706f2543Smrg	    return rc;
1103706f2543Smrg	}
1104706f2543Smrg	dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc);
1105706f2543Smrg	shmdesc->refcnt++;
1106706f2543Smrg	pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1107706f2543Smrg	pMap->drawable.id = stuff->pid;
1108706f2543Smrg	if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
1109706f2543Smrg	{
1110706f2543Smrg	    return Success;
1111706f2543Smrg	}
1112706f2543Smrg    }
1113706f2543Smrg    return BadAlloc;
1114706f2543Smrg}
1115706f2543Smrg
1116706f2543Smrgstatic int
1117706f2543SmrgProcShmDispatch (ClientPtr client)
1118706f2543Smrg{
1119706f2543Smrg    REQUEST(xReq);
1120706f2543Smrg    switch (stuff->data)
1121706f2543Smrg    {
1122706f2543Smrg    case X_ShmQueryVersion:
1123706f2543Smrg	return ProcShmQueryVersion(client);
1124706f2543Smrg    case X_ShmAttach:
1125706f2543Smrg	return ProcShmAttach(client);
1126706f2543Smrg    case X_ShmDetach:
1127706f2543Smrg	return ProcShmDetach(client);
1128706f2543Smrg    case X_ShmPutImage:
1129706f2543Smrg#ifdef PANORAMIX
1130706f2543Smrg        if ( !noPanoramiXExtension )
1131706f2543Smrg	   return ProcPanoramiXShmPutImage(client);
1132706f2543Smrg#endif
1133706f2543Smrg	return ProcShmPutImage(client);
1134706f2543Smrg    case X_ShmGetImage:
1135706f2543Smrg#ifdef PANORAMIX
1136706f2543Smrg        if ( !noPanoramiXExtension )
1137706f2543Smrg	   return ProcPanoramiXShmGetImage(client);
1138706f2543Smrg#endif
1139706f2543Smrg	return ProcShmGetImage(client);
1140706f2543Smrg    case X_ShmCreatePixmap:
1141706f2543Smrg#ifdef PANORAMIX
1142706f2543Smrg        if ( !noPanoramiXExtension )
1143706f2543Smrg	   return ProcPanoramiXShmCreatePixmap(client);
1144706f2543Smrg#endif
1145706f2543Smrg	   return ProcShmCreatePixmap(client);
1146706f2543Smrg    default:
1147706f2543Smrg	return BadRequest;
1148706f2543Smrg    }
1149706f2543Smrg}
1150706f2543Smrg
1151706f2543Smrgstatic void
1152706f2543SmrgSShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to)
1153706f2543Smrg{
1154706f2543Smrg    to->type = from->type;
1155706f2543Smrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
1156706f2543Smrg    cpswapl(from->drawable, to->drawable);
1157706f2543Smrg    cpswaps(from->minorEvent, to->minorEvent);
1158706f2543Smrg    to->majorEvent = from->majorEvent;
1159706f2543Smrg    cpswapl(from->shmseg, to->shmseg);
1160706f2543Smrg    cpswapl(from->offset, to->offset);
1161706f2543Smrg}
1162706f2543Smrg
1163706f2543Smrgstatic int
1164706f2543SmrgSProcShmQueryVersion(ClientPtr client)
1165706f2543Smrg{
1166706f2543Smrg    int n;
1167706f2543Smrg    REQUEST(xShmQueryVersionReq);
1168706f2543Smrg
1169706f2543Smrg    swaps(&stuff->length, n);
1170706f2543Smrg    return ProcShmQueryVersion(client);
1171706f2543Smrg}
1172706f2543Smrg
1173706f2543Smrgstatic int
1174706f2543SmrgSProcShmAttach(ClientPtr client)
1175706f2543Smrg{
1176706f2543Smrg    int n;
1177706f2543Smrg    REQUEST(xShmAttachReq);
1178706f2543Smrg    swaps(&stuff->length, n);
1179706f2543Smrg    REQUEST_SIZE_MATCH(xShmAttachReq);
1180706f2543Smrg    swapl(&stuff->shmseg, n);
1181706f2543Smrg    swapl(&stuff->shmid, n);
1182706f2543Smrg    return ProcShmAttach(client);
1183706f2543Smrg}
1184706f2543Smrg
1185706f2543Smrgstatic int
1186706f2543SmrgSProcShmDetach(ClientPtr client)
1187706f2543Smrg{
1188706f2543Smrg    int n;
1189706f2543Smrg    REQUEST(xShmDetachReq);
1190706f2543Smrg    swaps(&stuff->length, n);
1191706f2543Smrg    REQUEST_SIZE_MATCH(xShmDetachReq);
1192706f2543Smrg    swapl(&stuff->shmseg, n);
1193706f2543Smrg    return ProcShmDetach(client);
1194706f2543Smrg}
1195706f2543Smrg
1196706f2543Smrgstatic int
1197706f2543SmrgSProcShmPutImage(ClientPtr client)
1198706f2543Smrg{
1199706f2543Smrg    int n;
1200706f2543Smrg    REQUEST(xShmPutImageReq);
1201706f2543Smrg    swaps(&stuff->length, n);
1202706f2543Smrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
1203706f2543Smrg    swapl(&stuff->drawable, n);
1204706f2543Smrg    swapl(&stuff->gc, n);
1205706f2543Smrg    swaps(&stuff->totalWidth, n);
1206706f2543Smrg    swaps(&stuff->totalHeight, n);
1207706f2543Smrg    swaps(&stuff->srcX, n);
1208706f2543Smrg    swaps(&stuff->srcY, n);
1209706f2543Smrg    swaps(&stuff->srcWidth, n);
1210706f2543Smrg    swaps(&stuff->srcHeight, n);
1211706f2543Smrg    swaps(&stuff->dstX, n);
1212706f2543Smrg    swaps(&stuff->dstY, n);
1213706f2543Smrg    swapl(&stuff->shmseg, n);
1214706f2543Smrg    swapl(&stuff->offset, n);
1215706f2543Smrg    return ProcShmPutImage(client);
1216706f2543Smrg}
1217706f2543Smrg
1218706f2543Smrgstatic int
1219706f2543SmrgSProcShmGetImage(ClientPtr client)
1220706f2543Smrg{
1221706f2543Smrg    int n;
1222706f2543Smrg    REQUEST(xShmGetImageReq);
1223706f2543Smrg    swaps(&stuff->length, n);
1224706f2543Smrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
1225706f2543Smrg    swapl(&stuff->drawable, n);
1226706f2543Smrg    swaps(&stuff->x, n);
1227706f2543Smrg    swaps(&stuff->y, n);
1228706f2543Smrg    swaps(&stuff->width, n);
1229706f2543Smrg    swaps(&stuff->height, n);
1230706f2543Smrg    swapl(&stuff->planeMask, n);
1231706f2543Smrg    swapl(&stuff->shmseg, n);
1232706f2543Smrg    swapl(&stuff->offset, n);
1233706f2543Smrg    return ProcShmGetImage(client);
1234706f2543Smrg}
1235706f2543Smrg
1236706f2543Smrgstatic int
1237706f2543SmrgSProcShmCreatePixmap(ClientPtr client)
1238706f2543Smrg{
1239706f2543Smrg    int n;
1240706f2543Smrg    REQUEST(xShmCreatePixmapReq);
1241706f2543Smrg    swaps(&stuff->length, n);
1242706f2543Smrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
1243706f2543Smrg    swapl(&stuff->pid, n);
1244706f2543Smrg    swapl(&stuff->drawable, n);
1245706f2543Smrg    swaps(&stuff->width, n);
1246706f2543Smrg    swaps(&stuff->height, n);
1247706f2543Smrg    swapl(&stuff->shmseg, n);
1248706f2543Smrg    swapl(&stuff->offset, n);
1249706f2543Smrg    return ProcShmCreatePixmap(client);
1250706f2543Smrg}
1251706f2543Smrg
1252706f2543Smrgstatic int
1253706f2543SmrgSProcShmDispatch (ClientPtr client)
1254706f2543Smrg{
1255706f2543Smrg    REQUEST(xReq);
1256706f2543Smrg    switch (stuff->data)
1257706f2543Smrg    {
1258706f2543Smrg    case X_ShmQueryVersion:
1259706f2543Smrg	return SProcShmQueryVersion(client);
1260706f2543Smrg    case X_ShmAttach:
1261706f2543Smrg	return SProcShmAttach(client);
1262706f2543Smrg    case X_ShmDetach:
1263706f2543Smrg	return SProcShmDetach(client);
1264706f2543Smrg    case X_ShmPutImage:
1265706f2543Smrg	return SProcShmPutImage(client);
1266706f2543Smrg    case X_ShmGetImage:
1267706f2543Smrg	return SProcShmGetImage(client);
1268706f2543Smrg    case X_ShmCreatePixmap:
1269706f2543Smrg	return SProcShmCreatePixmap(client);
1270706f2543Smrg    default:
1271706f2543Smrg	return BadRequest;
1272706f2543Smrg    }
1273706f2543Smrg}
1274706f2543Smrg
1275706f2543Smrgvoid
1276706f2543SmrgShmExtensionInit(INITARGS)
1277706f2543Smrg{
1278706f2543Smrg    ExtensionEntry *extEntry;
1279706f2543Smrg    int i;
1280706f2543Smrg
1281706f2543Smrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL
1282706f2543Smrg    if (!CheckForShmSyscall())
1283706f2543Smrg    {
1284706f2543Smrg	ErrorF("MIT-SHM extension disabled due to lack of kernel support\n");
1285706f2543Smrg	return;
1286706f2543Smrg    }
1287706f2543Smrg#endif
1288706f2543Smrg
1289706f2543Smrg    if (!ShmRegisterPrivates())
1290706f2543Smrg	return;
1291706f2543Smrg
1292706f2543Smrg    sharedPixmaps = xFalse;
1293706f2543Smrg    {
1294706f2543Smrg      sharedPixmaps = xTrue;
1295706f2543Smrg      for (i = 0; i < screenInfo.numScreens; i++)
1296706f2543Smrg      {
1297706f2543Smrg	ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]);
1298706f2543Smrg	if (!screen_priv->shmFuncs)
1299706f2543Smrg	    screen_priv->shmFuncs = &miFuncs;
1300706f2543Smrg	if (!screen_priv->shmFuncs->CreatePixmap)
1301706f2543Smrg	    sharedPixmaps = xFalse;
1302706f2543Smrg      }
1303706f2543Smrg      if (sharedPixmaps)
1304706f2543Smrg	for (i = 0; i < screenInfo.numScreens; i++)
1305706f2543Smrg	{
1306706f2543Smrg	    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]);
1307706f2543Smrg	    screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap;
1308706f2543Smrg	    screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap;
1309706f2543Smrg	}
1310706f2543Smrg    }
1311706f2543Smrg    ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg");
1312706f2543Smrg    if (ShmSegType &&
1313706f2543Smrg	(extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors,
1314706f2543Smrg				 ProcShmDispatch, SProcShmDispatch,
1315706f2543Smrg				 ShmResetProc, StandardMinorOpcode)))
1316706f2543Smrg    {
1317706f2543Smrg	ShmReqCode = (unsigned char)extEntry->base;
1318706f2543Smrg	ShmCompletionCode = extEntry->eventBase;
1319706f2543Smrg	BadShmSegCode = extEntry->errorBase;
1320706f2543Smrg	SetResourceTypeErrorValue(ShmSegType, BadShmSegCode);
1321706f2543Smrg	EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent;
1322706f2543Smrg    }
1323706f2543Smrg}
1324