shm.c revision 4642e01f
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#define NEED_REPLIES 4205b261ecSmrg#define NEED_EVENTS 4305b261ecSmrg#include <X11/X.h> 4405b261ecSmrg#include <X11/Xproto.h> 4505b261ecSmrg#include "misc.h" 4605b261ecSmrg#include "os.h" 4705b261ecSmrg#include "dixstruct.h" 4805b261ecSmrg#include "resource.h" 4905b261ecSmrg#include "scrnintstr.h" 5005b261ecSmrg#include "windowstr.h" 5105b261ecSmrg#include "pixmapstr.h" 5205b261ecSmrg#include "gcstruct.h" 5305b261ecSmrg#include "extnsionst.h" 5405b261ecSmrg#include "servermd.h" 554642e01fSmrg#include "shmint.h" 564642e01fSmrg#include "xace.h" 5705b261ecSmrg#define _XSHM_SERVER_ 5805b261ecSmrg#include <X11/extensions/shmstr.h> 5905b261ecSmrg#include <X11/Xfuncproto.h> 6005b261ecSmrg 614642e01fSmrg/* Needed for Solaris cross-zone shared memory extension */ 624642e01fSmrg#ifdef HAVE_SHMCTL64 634642e01fSmrg#include <sys/ipc_impl.h> 644642e01fSmrg#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) 654642e01fSmrg#define SHMSTAT_TYPE struct shmid_ds64 664642e01fSmrg#define SHMPERM_TYPE struct ipc_perm64 674642e01fSmrg#define SHM_PERM(buf) buf.shmx_perm 684642e01fSmrg#define SHM_SEGSZ(buf) buf.shmx_segsz 694642e01fSmrg#define SHMPERM_UID(p) p->ipcx_uid 704642e01fSmrg#define SHMPERM_CUID(p) p->ipcx_cuid 714642e01fSmrg#define SHMPERM_GID(p) p->ipcx_gid 724642e01fSmrg#define SHMPERM_CGID(p) p->ipcx_cgid 734642e01fSmrg#define SHMPERM_MODE(p) p->ipcx_mode 744642e01fSmrg#define SHMPERM_ZONEID(p) p->ipcx_zoneid 754642e01fSmrg#else 764642e01fSmrg#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) 774642e01fSmrg#define SHMSTAT_TYPE struct shmid_ds 784642e01fSmrg#define SHMPERM_TYPE struct ipc_perm 794642e01fSmrg#define SHM_PERM(buf) buf.shm_perm 804642e01fSmrg#define SHM_SEGSZ(buf) buf.shm_segsz 814642e01fSmrg#define SHMPERM_UID(p) p->uid 824642e01fSmrg#define SHMPERM_CUID(p) p->cuid 834642e01fSmrg#define SHMPERM_GID(p) p->gid 844642e01fSmrg#define SHMPERM_CGID(p) p->cgid 854642e01fSmrg#define SHMPERM_MODE(p) p->mode 864642e01fSmrg#endif 874642e01fSmrg 8805b261ecSmrg#ifdef PANORAMIX 8905b261ecSmrg#include "panoramiX.h" 9005b261ecSmrg#include "panoramiXsrv.h" 9105b261ecSmrg#endif 9205b261ecSmrg 9305b261ecSmrg#include "modinit.h" 9405b261ecSmrg 9505b261ecSmrgtypedef struct _ShmDesc { 9605b261ecSmrg struct _ShmDesc *next; 9705b261ecSmrg int shmid; 9805b261ecSmrg int refcnt; 9905b261ecSmrg char *addr; 10005b261ecSmrg Bool writable; 10105b261ecSmrg unsigned long size; 10205b261ecSmrg} ShmDescRec, *ShmDescPtr; 10305b261ecSmrg 10405b261ecSmrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); 10505b261ecSmrgstatic int ShmDetachSegment( 10605b261ecSmrg pointer /* value */, 10705b261ecSmrg XID /* shmseg */ 10805b261ecSmrg ); 10905b261ecSmrgstatic void ShmResetProc( 11005b261ecSmrg ExtensionEntry * /* extEntry */ 11105b261ecSmrg ); 11205b261ecSmrgstatic void SShmCompletionEvent( 11305b261ecSmrg xShmCompletionEvent * /* from */, 11405b261ecSmrg xShmCompletionEvent * /* to */ 11505b261ecSmrg ); 11605b261ecSmrg 11705b261ecSmrgstatic Bool ShmDestroyPixmap (PixmapPtr pPixmap); 11805b261ecSmrg 11905b261ecSmrgstatic DISPATCH_PROC(ProcShmAttach); 12005b261ecSmrgstatic DISPATCH_PROC(ProcShmCreatePixmap); 12105b261ecSmrgstatic DISPATCH_PROC(ProcShmDetach); 12205b261ecSmrgstatic DISPATCH_PROC(ProcShmDispatch); 12305b261ecSmrgstatic DISPATCH_PROC(ProcShmGetImage); 12405b261ecSmrgstatic DISPATCH_PROC(ProcShmPutImage); 12505b261ecSmrgstatic DISPATCH_PROC(ProcShmQueryVersion); 12605b261ecSmrgstatic DISPATCH_PROC(SProcShmAttach); 12705b261ecSmrgstatic DISPATCH_PROC(SProcShmCreatePixmap); 12805b261ecSmrgstatic DISPATCH_PROC(SProcShmDetach); 12905b261ecSmrgstatic DISPATCH_PROC(SProcShmDispatch); 13005b261ecSmrgstatic DISPATCH_PROC(SProcShmGetImage); 13105b261ecSmrgstatic DISPATCH_PROC(SProcShmPutImage); 13205b261ecSmrgstatic DISPATCH_PROC(SProcShmQueryVersion); 13305b261ecSmrg 13405b261ecSmrgstatic unsigned char ShmReqCode; 13505b261ecSmrg_X_EXPORT int ShmCompletionCode; 13605b261ecSmrg_X_EXPORT int BadShmSegCode; 13705b261ecSmrg_X_EXPORT RESTYPE ShmSegType; 13805b261ecSmrgstatic ShmDescPtr Shmsegs; 13905b261ecSmrgstatic Bool sharedPixmaps; 14005b261ecSmrgstatic ShmFuncsPtr shmFuncs[MAXSCREENS]; 14105b261ecSmrgstatic DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; 1424642e01fSmrgstatic int shmPixmapPrivateIndex; 1434642e01fSmrgstatic DevPrivateKey shmPixmapPrivate = &shmPixmapPrivateIndex; 1444642e01fSmrgstatic ShmFuncs miFuncs = {NULL, NULL}; 1454642e01fSmrgstatic ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL}; 14605b261ecSmrg 14705b261ecSmrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ 14805b261ecSmrg{ \ 14905b261ecSmrg shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ 15005b261ecSmrg if (!shmdesc) \ 15105b261ecSmrg { \ 15205b261ecSmrg client->errorValue = shmseg; \ 15305b261ecSmrg return BadShmSegCode; \ 15405b261ecSmrg } \ 15505b261ecSmrg} 15605b261ecSmrg 15705b261ecSmrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ 15805b261ecSmrg{ \ 15905b261ecSmrg VERIFY_SHMSEG(shmseg, shmdesc, client); \ 16005b261ecSmrg if ((offset & 3) || (offset > shmdesc->size)) \ 16105b261ecSmrg { \ 16205b261ecSmrg client->errorValue = offset; \ 16305b261ecSmrg return BadValue; \ 16405b261ecSmrg } \ 16505b261ecSmrg if (needwrite && !shmdesc->writable) \ 16605b261ecSmrg return BadAccess; \ 16705b261ecSmrg} 16805b261ecSmrg 16905b261ecSmrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ 17005b261ecSmrg{ \ 17105b261ecSmrg if ((offset + len) > shmdesc->size) \ 17205b261ecSmrg { \ 17305b261ecSmrg return BadAccess; \ 17405b261ecSmrg } \ 17505b261ecSmrg} 17605b261ecSmrg 17705b261ecSmrg 17805b261ecSmrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) 17905b261ecSmrg#include <sys/signal.h> 18005b261ecSmrg 18105b261ecSmrgstatic Bool badSysCall = FALSE; 18205b261ecSmrg 18305b261ecSmrgstatic void 1844642e01fSmrgSigSysHandler(int signo) 18505b261ecSmrg{ 18605b261ecSmrg badSysCall = TRUE; 18705b261ecSmrg} 18805b261ecSmrg 1894642e01fSmrgstatic Bool CheckForShmSyscall(void) 19005b261ecSmrg{ 19105b261ecSmrg void (*oldHandler)(); 19205b261ecSmrg int shmid = -1; 19305b261ecSmrg 19405b261ecSmrg /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 19505b261ecSmrg oldHandler = signal(SIGSYS, SigSysHandler); 19605b261ecSmrg 19705b261ecSmrg badSysCall = FALSE; 19805b261ecSmrg shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 19905b261ecSmrg 20005b261ecSmrg if (shmid != -1) 20105b261ecSmrg { 20205b261ecSmrg /* Successful allocation - clean up */ 20305b261ecSmrg shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); 20405b261ecSmrg } 20505b261ecSmrg else 20605b261ecSmrg { 20705b261ecSmrg /* Allocation failed */ 20805b261ecSmrg badSysCall = TRUE; 20905b261ecSmrg } 21005b261ecSmrg signal(SIGSYS, oldHandler); 21105b261ecSmrg return(!badSysCall); 21205b261ecSmrg} 21305b261ecSmrg 21405b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL 21505b261ecSmrg 21605b261ecSmrg#endif 21705b261ecSmrg 21805b261ecSmrgvoid 21905b261ecSmrgShmExtensionInit(INITARGS) 22005b261ecSmrg{ 22105b261ecSmrg ExtensionEntry *extEntry; 22205b261ecSmrg int i; 22305b261ecSmrg 22405b261ecSmrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL 22505b261ecSmrg if (!CheckForShmSyscall()) 22605b261ecSmrg { 22705b261ecSmrg ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); 22805b261ecSmrg return; 22905b261ecSmrg } 23005b261ecSmrg#endif 23105b261ecSmrg 23205b261ecSmrg sharedPixmaps = xFalse; 23305b261ecSmrg { 23405b261ecSmrg sharedPixmaps = xTrue; 23505b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 23605b261ecSmrg { 23705b261ecSmrg if (!shmFuncs[i]) 23805b261ecSmrg shmFuncs[i] = &miFuncs; 23905b261ecSmrg if (!shmFuncs[i]->CreatePixmap) 24005b261ecSmrg sharedPixmaps = xFalse; 24105b261ecSmrg } 24205b261ecSmrg if (sharedPixmaps) 24305b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 24405b261ecSmrg { 24505b261ecSmrg destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; 24605b261ecSmrg screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; 24705b261ecSmrg } 24805b261ecSmrg } 24905b261ecSmrg ShmSegType = CreateNewResourceType(ShmDetachSegment); 25005b261ecSmrg if (ShmSegType && 25105b261ecSmrg (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, 25205b261ecSmrg ProcShmDispatch, SProcShmDispatch, 25305b261ecSmrg ShmResetProc, StandardMinorOpcode))) 25405b261ecSmrg { 25505b261ecSmrg ShmReqCode = (unsigned char)extEntry->base; 25605b261ecSmrg ShmCompletionCode = extEntry->eventBase; 25705b261ecSmrg BadShmSegCode = extEntry->errorBase; 25805b261ecSmrg EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; 25905b261ecSmrg } 26005b261ecSmrg} 26105b261ecSmrg 26205b261ecSmrg/*ARGSUSED*/ 26305b261ecSmrgstatic void 2644642e01fSmrgShmResetProc(ExtensionEntry *extEntry) 26505b261ecSmrg{ 26605b261ecSmrg int i; 26705b261ecSmrg 26805b261ecSmrg for (i = 0; i < MAXSCREENS; i++) 26905b261ecSmrg { 27005b261ecSmrg shmFuncs[i] = (ShmFuncsPtr)NULL; 27105b261ecSmrg } 27205b261ecSmrg} 27305b261ecSmrg 2744642e01fSmrg_X_EXPORT void 2754642e01fSmrgShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) 27605b261ecSmrg{ 27705b261ecSmrg shmFuncs[pScreen->myNum] = funcs; 27805b261ecSmrg} 27905b261ecSmrg 28005b261ecSmrgstatic Bool 28105b261ecSmrgShmDestroyPixmap (PixmapPtr pPixmap) 28205b261ecSmrg{ 28305b261ecSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 28405b261ecSmrg Bool ret; 28505b261ecSmrg if (pPixmap->refcnt == 1) 28605b261ecSmrg { 28705b261ecSmrg ShmDescPtr shmdesc; 2884642e01fSmrg shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates, 2894642e01fSmrg shmPixmapPrivate); 29005b261ecSmrg if (shmdesc) 29105b261ecSmrg ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); 29205b261ecSmrg } 29305b261ecSmrg 29405b261ecSmrg pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; 29505b261ecSmrg ret = (*pScreen->DestroyPixmap) (pPixmap); 29605b261ecSmrg destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; 29705b261ecSmrg pScreen->DestroyPixmap = ShmDestroyPixmap; 29805b261ecSmrg return ret; 29905b261ecSmrg} 30005b261ecSmrg 3014642e01fSmrg_X_EXPORT void 3024642e01fSmrgShmRegisterFbFuncs(ScreenPtr pScreen) 30305b261ecSmrg{ 30405b261ecSmrg shmFuncs[pScreen->myNum] = &fbFuncs; 30505b261ecSmrg} 30605b261ecSmrg 30705b261ecSmrgstatic int 3084642e01fSmrgProcShmQueryVersion(ClientPtr client) 30905b261ecSmrg{ 31005b261ecSmrg xShmQueryVersionReply rep; 3114642e01fSmrg int n; 31205b261ecSmrg 31305b261ecSmrg REQUEST_SIZE_MATCH(xShmQueryVersionReq); 31405b261ecSmrg rep.type = X_Reply; 31505b261ecSmrg rep.length = 0; 31605b261ecSmrg rep.sequenceNumber = client->sequence; 31705b261ecSmrg rep.sharedPixmaps = sharedPixmaps; 3184642e01fSmrg rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0; 31905b261ecSmrg rep.majorVersion = SHM_MAJOR_VERSION; 32005b261ecSmrg rep.minorVersion = SHM_MINOR_VERSION; 32105b261ecSmrg rep.uid = geteuid(); 32205b261ecSmrg rep.gid = getegid(); 32305b261ecSmrg if (client->swapped) { 32405b261ecSmrg swaps(&rep.sequenceNumber, n); 32505b261ecSmrg swapl(&rep.length, n); 32605b261ecSmrg swaps(&rep.majorVersion, n); 32705b261ecSmrg swaps(&rep.minorVersion, n); 32805b261ecSmrg swaps(&rep.uid, n); 32905b261ecSmrg swaps(&rep.gid, n); 33005b261ecSmrg } 33105b261ecSmrg WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); 33205b261ecSmrg return (client->noClientException); 33305b261ecSmrg} 33405b261ecSmrg 33505b261ecSmrg/* 33605b261ecSmrg * Simulate the access() system call for a shared memory segement, 33705b261ecSmrg * using the credentials from the client if available 33805b261ecSmrg */ 33905b261ecSmrgstatic int 3404642e01fSmrgshm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) 34105b261ecSmrg{ 34205b261ecSmrg int uid, gid; 34305b261ecSmrg mode_t mask; 3444642e01fSmrg int uidset = 0, gidset = 0; 3454642e01fSmrg LocalClientCredRec *lcc; 3464642e01fSmrg 3474642e01fSmrg if (GetLocalClientCreds(client, &lcc) != -1) { 34805b261ecSmrg 3494642e01fSmrg if (lcc->fieldsSet & LCC_UID_SET) { 3504642e01fSmrg uid = lcc->euid; 3514642e01fSmrg uidset = 1; 3524642e01fSmrg } 3534642e01fSmrg if (lcc->fieldsSet & LCC_GID_SET) { 3544642e01fSmrg gid = lcc->egid; 3554642e01fSmrg gidset = 1; 3564642e01fSmrg } 3574642e01fSmrg 3584642e01fSmrg#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) 3594642e01fSmrg if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) 3604642e01fSmrg || (lcc->zoneid != SHMPERM_ZONEID(perm))) { 3614642e01fSmrg uidset = 0; 3624642e01fSmrg gidset = 0; 36305b261ecSmrg } 3644642e01fSmrg#endif 3654642e01fSmrg FreeLocalClientCreds(lcc); 3664642e01fSmrg 3674642e01fSmrg if (uidset) { 3684642e01fSmrg /* User id 0 always gets access */ 3694642e01fSmrg if (uid == 0) { 3704642e01fSmrg return 0; 3714642e01fSmrg } 3724642e01fSmrg /* Check the owner */ 3734642e01fSmrg if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { 3744642e01fSmrg mask = S_IRUSR; 3754642e01fSmrg if (!readonly) { 3764642e01fSmrg mask |= S_IWUSR; 3774642e01fSmrg } 3784642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 37905b261ecSmrg } 38005b261ecSmrg } 3814642e01fSmrg 3824642e01fSmrg if (gidset) { 3834642e01fSmrg /* Check the group */ 3844642e01fSmrg if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { 3854642e01fSmrg mask = S_IRGRP; 3864642e01fSmrg if (!readonly) { 3874642e01fSmrg mask |= S_IWGRP; 3884642e01fSmrg } 3894642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 39005b261ecSmrg } 39105b261ecSmrg } 39205b261ecSmrg } 39305b261ecSmrg /* Otherwise, check everyone else */ 39405b261ecSmrg mask = S_IROTH; 39505b261ecSmrg if (!readonly) { 39605b261ecSmrg mask |= S_IWOTH; 39705b261ecSmrg } 3984642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 39905b261ecSmrg} 40005b261ecSmrg 40105b261ecSmrgstatic int 4024642e01fSmrgProcShmAttach(ClientPtr client) 40305b261ecSmrg{ 4044642e01fSmrg SHMSTAT_TYPE buf; 40505b261ecSmrg ShmDescPtr shmdesc; 40605b261ecSmrg REQUEST(xShmAttachReq); 40705b261ecSmrg 40805b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 40905b261ecSmrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 41005b261ecSmrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) 41105b261ecSmrg { 41205b261ecSmrg client->errorValue = stuff->readOnly; 41305b261ecSmrg return(BadValue); 41405b261ecSmrg } 41505b261ecSmrg for (shmdesc = Shmsegs; 41605b261ecSmrg shmdesc && (shmdesc->shmid != stuff->shmid); 41705b261ecSmrg shmdesc = shmdesc->next) 41805b261ecSmrg ; 41905b261ecSmrg if (shmdesc) 42005b261ecSmrg { 42105b261ecSmrg if (!stuff->readOnly && !shmdesc->writable) 42205b261ecSmrg return BadAccess; 42305b261ecSmrg shmdesc->refcnt++; 42405b261ecSmrg } 42505b261ecSmrg else 42605b261ecSmrg { 42705b261ecSmrg shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); 42805b261ecSmrg if (!shmdesc) 42905b261ecSmrg return BadAlloc; 43005b261ecSmrg shmdesc->addr = shmat(stuff->shmid, 0, 43105b261ecSmrg stuff->readOnly ? SHM_RDONLY : 0); 43205b261ecSmrg if ((shmdesc->addr == ((char *)-1)) || 4334642e01fSmrg SHMSTAT(stuff->shmid, &buf)) 43405b261ecSmrg { 43505b261ecSmrg xfree(shmdesc); 43605b261ecSmrg return BadAccess; 43705b261ecSmrg } 43805b261ecSmrg 43905b261ecSmrg /* The attach was performed with root privs. We must 44005b261ecSmrg * do manual checking of access rights for the credentials 44105b261ecSmrg * of the client */ 44205b261ecSmrg 4434642e01fSmrg if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { 44405b261ecSmrg shmdt(shmdesc->addr); 44505b261ecSmrg xfree(shmdesc); 44605b261ecSmrg return BadAccess; 44705b261ecSmrg } 44805b261ecSmrg 44905b261ecSmrg shmdesc->shmid = stuff->shmid; 45005b261ecSmrg shmdesc->refcnt = 1; 45105b261ecSmrg shmdesc->writable = !stuff->readOnly; 4524642e01fSmrg shmdesc->size = SHM_SEGSZ(buf); 45305b261ecSmrg shmdesc->next = Shmsegs; 45405b261ecSmrg Shmsegs = shmdesc; 45505b261ecSmrg } 45605b261ecSmrg if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) 45705b261ecSmrg return BadAlloc; 45805b261ecSmrg return(client->noClientException); 45905b261ecSmrg} 46005b261ecSmrg 46105b261ecSmrg/*ARGSUSED*/ 46205b261ecSmrgstatic int 4634642e01fSmrgShmDetachSegment(pointer value, /* must conform to DeleteType */ 4644642e01fSmrg XID shmseg) 46505b261ecSmrg{ 46605b261ecSmrg ShmDescPtr shmdesc = (ShmDescPtr)value; 46705b261ecSmrg ShmDescPtr *prev; 46805b261ecSmrg 46905b261ecSmrg if (--shmdesc->refcnt) 47005b261ecSmrg return TRUE; 47105b261ecSmrg shmdt(shmdesc->addr); 47205b261ecSmrg for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) 47305b261ecSmrg ; 47405b261ecSmrg *prev = shmdesc->next; 47505b261ecSmrg xfree(shmdesc); 47605b261ecSmrg return Success; 47705b261ecSmrg} 47805b261ecSmrg 47905b261ecSmrgstatic int 4804642e01fSmrgProcShmDetach(ClientPtr client) 48105b261ecSmrg{ 48205b261ecSmrg ShmDescPtr shmdesc; 48305b261ecSmrg REQUEST(xShmDetachReq); 48405b261ecSmrg 48505b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 48605b261ecSmrg VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); 48705b261ecSmrg FreeResource(stuff->shmseg, RT_NONE); 48805b261ecSmrg return(client->noClientException); 48905b261ecSmrg} 49005b261ecSmrg 4914642e01fSmrg/* 4924642e01fSmrg * If the given request doesn't exactly match PutImage's constraints, 4934642e01fSmrg * wrap the image in a scratch pixmap header and let CopyArea sort it out. 4944642e01fSmrg */ 49505b261ecSmrgstatic void 4964642e01fSmrgdoShmPutImage(DrawablePtr dst, GCPtr pGC, 4974642e01fSmrg int depth, unsigned int format, 4984642e01fSmrg int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, 4994642e01fSmrg char *data) 50005b261ecSmrg{ 5014642e01fSmrg PixmapPtr pPixmap; 5024642e01fSmrg 5034642e01fSmrg pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, 5044642e01fSmrg BitsPerPixel(depth), 5054642e01fSmrg PixmapBytePad(w, depth), 5064642e01fSmrg data); 5074642e01fSmrg if (!pPixmap) 50805b261ecSmrg return; 5094642e01fSmrg pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy); 5104642e01fSmrg FreeScratchPixmapHeader(pPixmap); 51105b261ecSmrg} 51205b261ecSmrg 51305b261ecSmrg#ifdef PANORAMIX 51405b261ecSmrgstatic int 5154642e01fSmrgProcPanoramiXShmPutImage(ClientPtr client) 51605b261ecSmrg{ 51705b261ecSmrg int j, result = 0, orig_x, orig_y; 51805b261ecSmrg PanoramiXRes *draw, *gc; 51905b261ecSmrg Bool sendEvent, isRoot; 52005b261ecSmrg 52105b261ecSmrg REQUEST(xShmPutImageReq); 52205b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 52305b261ecSmrg 52405b261ecSmrg if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( 52505b261ecSmrg client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess))) 52605b261ecSmrg return BadDrawable; 52705b261ecSmrg 52805b261ecSmrg if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( 52905b261ecSmrg client, stuff->gc, XRT_GC, DixReadAccess))) 53005b261ecSmrg return BadGC; 53105b261ecSmrg 53205b261ecSmrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 53305b261ecSmrg 53405b261ecSmrg orig_x = stuff->dstX; 53505b261ecSmrg orig_y = stuff->dstY; 53605b261ecSmrg sendEvent = stuff->sendEvent; 53705b261ecSmrg stuff->sendEvent = 0; 53805b261ecSmrg FOR_NSCREENS(j) { 53905b261ecSmrg if(!j) stuff->sendEvent = sendEvent; 54005b261ecSmrg stuff->drawable = draw->info[j].id; 54105b261ecSmrg stuff->gc = gc->info[j].id; 54205b261ecSmrg if (isRoot) { 54305b261ecSmrg stuff->dstX = orig_x - panoramiXdataPtr[j].x; 54405b261ecSmrg stuff->dstY = orig_y - panoramiXdataPtr[j].y; 54505b261ecSmrg } 54605b261ecSmrg result = ProcShmPutImage(client); 54705b261ecSmrg if(result != client->noClientException) break; 54805b261ecSmrg } 54905b261ecSmrg return(result); 55005b261ecSmrg} 55105b261ecSmrg 55205b261ecSmrgstatic int 55305b261ecSmrgProcPanoramiXShmGetImage(ClientPtr client) 55405b261ecSmrg{ 55505b261ecSmrg PanoramiXRes *draw; 55605b261ecSmrg DrawablePtr drawables[MAXSCREENS]; 55705b261ecSmrg DrawablePtr pDraw; 55805b261ecSmrg xShmGetImageReply xgi; 55905b261ecSmrg ShmDescPtr shmdesc; 56005b261ecSmrg int i, x, y, w, h, format, rc; 56105b261ecSmrg Mask plane = 0, planemask; 56205b261ecSmrg long lenPer = 0, length, widthBytesLine; 56305b261ecSmrg Bool isRoot; 56405b261ecSmrg 56505b261ecSmrg REQUEST(xShmGetImageReq); 56605b261ecSmrg 56705b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 56805b261ecSmrg 56905b261ecSmrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 57005b261ecSmrg client->errorValue = stuff->format; 57105b261ecSmrg return(BadValue); 57205b261ecSmrg } 57305b261ecSmrg 57405b261ecSmrg if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( 57505b261ecSmrg client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess))) 57605b261ecSmrg return BadDrawable; 57705b261ecSmrg 57805b261ecSmrg if (draw->type == XRT_PIXMAP) 57905b261ecSmrg return ProcShmGetImage(client); 58005b261ecSmrg 58105b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 5824642e01fSmrg DixReadAccess); 58305b261ecSmrg if (rc != Success) 58405b261ecSmrg return rc; 58505b261ecSmrg 58605b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 58705b261ecSmrg 58805b261ecSmrg x = stuff->x; 58905b261ecSmrg y = stuff->y; 59005b261ecSmrg w = stuff->width; 59105b261ecSmrg h = stuff->height; 59205b261ecSmrg format = stuff->format; 59305b261ecSmrg planemask = stuff->planeMask; 59405b261ecSmrg 59505b261ecSmrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 59605b261ecSmrg 59705b261ecSmrg if(isRoot) { 59805b261ecSmrg if( /* check for being onscreen */ 59905b261ecSmrg x < 0 || x + w > PanoramiXPixWidth || 60005b261ecSmrg y < 0 || y + h > PanoramiXPixHeight ) 60105b261ecSmrg return(BadMatch); 60205b261ecSmrg } else { 60305b261ecSmrg if( /* check for being onscreen */ 60405b261ecSmrg panoramiXdataPtr[0].x + pDraw->x + x < 0 || 60505b261ecSmrg panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || 60605b261ecSmrg panoramiXdataPtr[0].y + pDraw->y + y < 0 || 60705b261ecSmrg panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || 60805b261ecSmrg /* check for being inside of border */ 60905b261ecSmrg x < - wBorderWidth((WindowPtr)pDraw) || 61005b261ecSmrg x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || 61105b261ecSmrg y < -wBorderWidth((WindowPtr)pDraw) || 61205b261ecSmrg y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) 61305b261ecSmrg return(BadMatch); 61405b261ecSmrg } 61505b261ecSmrg 61605b261ecSmrg drawables[0] = pDraw; 61705b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 61805b261ecSmrg rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, 6194642e01fSmrg DixReadAccess); 62005b261ecSmrg if (rc != Success) 62105b261ecSmrg return rc; 62205b261ecSmrg } 62305b261ecSmrg 62405b261ecSmrg xgi.visual = wVisual(((WindowPtr)pDraw)); 62505b261ecSmrg xgi.type = X_Reply; 62605b261ecSmrg xgi.length = 0; 62705b261ecSmrg xgi.sequenceNumber = client->sequence; 62805b261ecSmrg xgi.depth = pDraw->depth; 62905b261ecSmrg 63005b261ecSmrg if(format == ZPixmap) { 63105b261ecSmrg widthBytesLine = PixmapBytePad(w, pDraw->depth); 63205b261ecSmrg length = widthBytesLine * h; 63305b261ecSmrg } else { 63405b261ecSmrg widthBytesLine = PixmapBytePad(w, 1); 63505b261ecSmrg lenPer = widthBytesLine * h; 63605b261ecSmrg plane = ((Mask)1) << (pDraw->depth - 1); 63705b261ecSmrg length = lenPer * Ones(planemask & (plane | (plane - 1))); 63805b261ecSmrg } 63905b261ecSmrg 64005b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 64105b261ecSmrg xgi.size = length; 64205b261ecSmrg 64305b261ecSmrg if (length == 0) {/* nothing to do */ } 64405b261ecSmrg else if (format == ZPixmap) { 64505b261ecSmrg XineramaGetImageData(drawables, x, y, w, h, format, planemask, 64605b261ecSmrg shmdesc->addr + stuff->offset, 64705b261ecSmrg widthBytesLine, isRoot); 64805b261ecSmrg } else { 64905b261ecSmrg 65005b261ecSmrg length = stuff->offset; 65105b261ecSmrg for (; plane; plane >>= 1) { 65205b261ecSmrg if (planemask & plane) { 65305b261ecSmrg XineramaGetImageData(drawables, x, y, w, h, 65405b261ecSmrg format, plane, shmdesc->addr + length, 65505b261ecSmrg widthBytesLine, isRoot); 65605b261ecSmrg length += lenPer; 65705b261ecSmrg } 65805b261ecSmrg } 65905b261ecSmrg } 66005b261ecSmrg 66105b261ecSmrg if (client->swapped) { 6624642e01fSmrg int n; 66305b261ecSmrg swaps(&xgi.sequenceNumber, n); 66405b261ecSmrg swapl(&xgi.length, n); 66505b261ecSmrg swapl(&xgi.visual, n); 66605b261ecSmrg swapl(&xgi.size, n); 66705b261ecSmrg } 66805b261ecSmrg WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); 66905b261ecSmrg 67005b261ecSmrg return(client->noClientException); 67105b261ecSmrg} 67205b261ecSmrg 67305b261ecSmrgstatic int 6744642e01fSmrgProcPanoramiXShmCreatePixmap(ClientPtr client) 67505b261ecSmrg{ 67605b261ecSmrg ScreenPtr pScreen = NULL; 67705b261ecSmrg PixmapPtr pMap = NULL; 67805b261ecSmrg DrawablePtr pDraw; 67905b261ecSmrg DepthPtr pDepth; 68005b261ecSmrg int i, j, result, rc; 68105b261ecSmrg ShmDescPtr shmdesc; 68205b261ecSmrg REQUEST(xShmCreatePixmapReq); 68305b261ecSmrg unsigned int width, height, depth; 68405b261ecSmrg unsigned long size; 68505b261ecSmrg PanoramiXRes *newPix; 68605b261ecSmrg 68705b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 68805b261ecSmrg client->errorValue = stuff->pid; 68905b261ecSmrg if (!sharedPixmaps) 69005b261ecSmrg return BadImplementation; 69105b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 69205b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 6934642e01fSmrg DixGetAttrAccess); 69405b261ecSmrg if (rc != Success) 69505b261ecSmrg return rc; 69605b261ecSmrg 69705b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 69805b261ecSmrg 69905b261ecSmrg width = stuff->width; 70005b261ecSmrg height = stuff->height; 70105b261ecSmrg depth = stuff->depth; 70205b261ecSmrg if (!width || !height || !depth) 70305b261ecSmrg { 70405b261ecSmrg client->errorValue = 0; 70505b261ecSmrg return BadValue; 70605b261ecSmrg } 70705b261ecSmrg if (width > 32767 || height > 32767) 70805b261ecSmrg return BadAlloc; 70905b261ecSmrg 71005b261ecSmrg if (stuff->depth != 1) 71105b261ecSmrg { 71205b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 71305b261ecSmrg for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) 71405b261ecSmrg if (pDepth->depth == stuff->depth) 71505b261ecSmrg goto CreatePmap; 71605b261ecSmrg client->errorValue = stuff->depth; 71705b261ecSmrg return BadValue; 71805b261ecSmrg } 71905b261ecSmrg 72005b261ecSmrgCreatePmap: 72105b261ecSmrg size = PixmapBytePad(width, depth) * height; 72205b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 72305b261ecSmrg if (size < width * height) 72405b261ecSmrg return BadAlloc; 72505b261ecSmrg } 72605b261ecSmrg /* thankfully, offset is unsigned */ 72705b261ecSmrg if (stuff->offset + size < size) 72805b261ecSmrg return BadAlloc; 72905b261ecSmrg 73005b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 73105b261ecSmrg 73205b261ecSmrg if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) 73305b261ecSmrg return BadAlloc; 73405b261ecSmrg 73505b261ecSmrg newPix->type = XRT_PIXMAP; 73605b261ecSmrg newPix->u.pix.shared = TRUE; 73705b261ecSmrg newPix->info[0].id = stuff->pid; 73805b261ecSmrg for(j = 1; j < PanoramiXNumScreens; j++) 73905b261ecSmrg newPix->info[j].id = FakeClientID(client->index); 74005b261ecSmrg 74105b261ecSmrg result = (client->noClientException); 74205b261ecSmrg 74305b261ecSmrg FOR_NSCREENS(j) { 74405b261ecSmrg pScreen = screenInfo.screens[j]; 74505b261ecSmrg 74605b261ecSmrg pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, 74705b261ecSmrg stuff->width, stuff->height, stuff->depth, 74805b261ecSmrg shmdesc->addr + stuff->offset); 74905b261ecSmrg 75005b261ecSmrg if (pMap) { 7514642e01fSmrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); 75205b261ecSmrg shmdesc->refcnt++; 75305b261ecSmrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 75405b261ecSmrg pMap->drawable.id = newPix->info[j].id; 75505b261ecSmrg if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { 75605b261ecSmrg (*pScreen->DestroyPixmap)(pMap); 75705b261ecSmrg result = BadAlloc; 75805b261ecSmrg break; 75905b261ecSmrg } 76005b261ecSmrg } else { 76105b261ecSmrg result = BadAlloc; 76205b261ecSmrg break; 76305b261ecSmrg } 76405b261ecSmrg } 76505b261ecSmrg 76605b261ecSmrg if(result == BadAlloc) { 76705b261ecSmrg while(j--) { 76805b261ecSmrg (*pScreen->DestroyPixmap)(pMap); 76905b261ecSmrg FreeResource(newPix->info[j].id, RT_NONE); 77005b261ecSmrg } 77105b261ecSmrg xfree(newPix); 77205b261ecSmrg } else 77305b261ecSmrg AddResource(stuff->pid, XRT_PIXMAP, newPix); 77405b261ecSmrg 77505b261ecSmrg return result; 77605b261ecSmrg} 77705b261ecSmrg 77805b261ecSmrg#endif 77905b261ecSmrg 78005b261ecSmrgstatic int 7814642e01fSmrgProcShmPutImage(ClientPtr client) 78205b261ecSmrg{ 78305b261ecSmrg GCPtr pGC; 78405b261ecSmrg DrawablePtr pDraw; 78505b261ecSmrg long length; 78605b261ecSmrg ShmDescPtr shmdesc; 78705b261ecSmrg REQUEST(xShmPutImageReq); 78805b261ecSmrg 78905b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 7904642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 79105b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); 79205b261ecSmrg if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) 79305b261ecSmrg return BadValue; 79405b261ecSmrg if (stuff->format == XYBitmap) 79505b261ecSmrg { 79605b261ecSmrg if (stuff->depth != 1) 79705b261ecSmrg return BadMatch; 79805b261ecSmrg length = PixmapBytePad(stuff->totalWidth, 1); 79905b261ecSmrg } 80005b261ecSmrg else if (stuff->format == XYPixmap) 80105b261ecSmrg { 80205b261ecSmrg if (pDraw->depth != stuff->depth) 80305b261ecSmrg return BadMatch; 80405b261ecSmrg length = PixmapBytePad(stuff->totalWidth, 1); 80505b261ecSmrg length *= stuff->depth; 80605b261ecSmrg } 80705b261ecSmrg else if (stuff->format == ZPixmap) 80805b261ecSmrg { 80905b261ecSmrg if (pDraw->depth != stuff->depth) 81005b261ecSmrg return BadMatch; 81105b261ecSmrg length = PixmapBytePad(stuff->totalWidth, stuff->depth); 81205b261ecSmrg } 81305b261ecSmrg else 81405b261ecSmrg { 81505b261ecSmrg client->errorValue = stuff->format; 81605b261ecSmrg return BadValue; 81705b261ecSmrg } 81805b261ecSmrg 81905b261ecSmrg /* 82005b261ecSmrg * There's a potential integer overflow in this check: 82105b261ecSmrg * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, 82205b261ecSmrg * client); 82305b261ecSmrg * the version below ought to avoid it 82405b261ecSmrg */ 82505b261ecSmrg if (stuff->totalHeight != 0 && 82605b261ecSmrg length > (shmdesc->size - stuff->offset)/stuff->totalHeight) { 82705b261ecSmrg client->errorValue = stuff->totalWidth; 82805b261ecSmrg return BadValue; 82905b261ecSmrg } 83005b261ecSmrg if (stuff->srcX > stuff->totalWidth) 83105b261ecSmrg { 83205b261ecSmrg client->errorValue = stuff->srcX; 83305b261ecSmrg return BadValue; 83405b261ecSmrg } 83505b261ecSmrg if (stuff->srcY > stuff->totalHeight) 83605b261ecSmrg { 83705b261ecSmrg client->errorValue = stuff->srcY; 83805b261ecSmrg return BadValue; 83905b261ecSmrg } 84005b261ecSmrg if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) 84105b261ecSmrg { 84205b261ecSmrg client->errorValue = stuff->srcWidth; 84305b261ecSmrg return BadValue; 84405b261ecSmrg } 84505b261ecSmrg if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) 84605b261ecSmrg { 84705b261ecSmrg client->errorValue = stuff->srcHeight; 84805b261ecSmrg return BadValue; 84905b261ecSmrg } 85005b261ecSmrg 85105b261ecSmrg if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || 85205b261ecSmrg ((stuff->format != ZPixmap) && 85305b261ecSmrg (stuff->srcX < screenInfo.bitmapScanlinePad) && 85405b261ecSmrg ((stuff->format == XYBitmap) || 85505b261ecSmrg ((stuff->srcY == 0) && 85605b261ecSmrg (stuff->srcHeight == stuff->totalHeight))))) && 85705b261ecSmrg ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) 85805b261ecSmrg (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, 85905b261ecSmrg stuff->dstX, stuff->dstY, 86005b261ecSmrg stuff->totalWidth, stuff->srcHeight, 86105b261ecSmrg stuff->srcX, stuff->format, 86205b261ecSmrg shmdesc->addr + stuff->offset + 86305b261ecSmrg (stuff->srcY * length)); 86405b261ecSmrg else 8654642e01fSmrg doShmPutImage(pDraw, pGC, stuff->depth, stuff->format, 8664642e01fSmrg stuff->totalWidth, stuff->totalHeight, 8674642e01fSmrg stuff->srcX, stuff->srcY, 8684642e01fSmrg stuff->srcWidth, stuff->srcHeight, 8694642e01fSmrg stuff->dstX, stuff->dstY, 8704642e01fSmrg shmdesc->addr + stuff->offset); 87105b261ecSmrg 87205b261ecSmrg if (stuff->sendEvent) 87305b261ecSmrg { 87405b261ecSmrg xShmCompletionEvent ev; 87505b261ecSmrg 87605b261ecSmrg ev.type = ShmCompletionCode; 87705b261ecSmrg ev.drawable = stuff->drawable; 87805b261ecSmrg ev.sequenceNumber = client->sequence; 87905b261ecSmrg ev.minorEvent = X_ShmPutImage; 88005b261ecSmrg ev.majorEvent = ShmReqCode; 88105b261ecSmrg ev.shmseg = stuff->shmseg; 88205b261ecSmrg ev.offset = stuff->offset; 88305b261ecSmrg WriteEventsToClient(client, 1, (xEvent *) &ev); 88405b261ecSmrg } 88505b261ecSmrg 88605b261ecSmrg return (client->noClientException); 88705b261ecSmrg} 88805b261ecSmrg 88905b261ecSmrg 89005b261ecSmrg 89105b261ecSmrgstatic int 8924642e01fSmrgProcShmGetImage(ClientPtr client) 89305b261ecSmrg{ 89405b261ecSmrg DrawablePtr pDraw; 89505b261ecSmrg long lenPer = 0, length; 89605b261ecSmrg Mask plane = 0; 89705b261ecSmrg xShmGetImageReply xgi; 89805b261ecSmrg ShmDescPtr shmdesc; 89905b261ecSmrg int n, rc; 90005b261ecSmrg 90105b261ecSmrg REQUEST(xShmGetImageReq); 90205b261ecSmrg 90305b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 90405b261ecSmrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) 90505b261ecSmrg { 90605b261ecSmrg client->errorValue = stuff->format; 90705b261ecSmrg return(BadValue); 90805b261ecSmrg } 90905b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 9104642e01fSmrg DixReadAccess); 91105b261ecSmrg if (rc != Success) 91205b261ecSmrg return rc; 91305b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 91405b261ecSmrg if (pDraw->type == DRAWABLE_WINDOW) 91505b261ecSmrg { 91605b261ecSmrg if( /* check for being viewable */ 91705b261ecSmrg !((WindowPtr) pDraw)->realized || 91805b261ecSmrg /* check for being on screen */ 91905b261ecSmrg pDraw->x + stuff->x < 0 || 92005b261ecSmrg pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || 92105b261ecSmrg pDraw->y + stuff->y < 0 || 92205b261ecSmrg pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || 92305b261ecSmrg /* check for being inside of border */ 92405b261ecSmrg stuff->x < - wBorderWidth((WindowPtr)pDraw) || 92505b261ecSmrg stuff->x + (int)stuff->width > 92605b261ecSmrg wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || 92705b261ecSmrg stuff->y < -wBorderWidth((WindowPtr)pDraw) || 92805b261ecSmrg stuff->y + (int)stuff->height > 92905b261ecSmrg wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height 93005b261ecSmrg ) 93105b261ecSmrg return(BadMatch); 93205b261ecSmrg xgi.visual = wVisual(((WindowPtr)pDraw)); 93305b261ecSmrg } 93405b261ecSmrg else 93505b261ecSmrg { 93605b261ecSmrg if (stuff->x < 0 || 93705b261ecSmrg stuff->x+(int)stuff->width > pDraw->width || 93805b261ecSmrg stuff->y < 0 || 93905b261ecSmrg stuff->y+(int)stuff->height > pDraw->height 94005b261ecSmrg ) 94105b261ecSmrg return(BadMatch); 94205b261ecSmrg xgi.visual = None; 94305b261ecSmrg } 94405b261ecSmrg xgi.type = X_Reply; 94505b261ecSmrg xgi.length = 0; 94605b261ecSmrg xgi.sequenceNumber = client->sequence; 94705b261ecSmrg xgi.depth = pDraw->depth; 94805b261ecSmrg if(stuff->format == ZPixmap) 94905b261ecSmrg { 95005b261ecSmrg length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; 95105b261ecSmrg } 95205b261ecSmrg else 95305b261ecSmrg { 95405b261ecSmrg lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; 95505b261ecSmrg plane = ((Mask)1) << (pDraw->depth - 1); 95605b261ecSmrg /* only planes asked for */ 95705b261ecSmrg length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); 95805b261ecSmrg } 95905b261ecSmrg 96005b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 96105b261ecSmrg xgi.size = length; 96205b261ecSmrg 96305b261ecSmrg if (length == 0) 96405b261ecSmrg { 96505b261ecSmrg /* nothing to do */ 96605b261ecSmrg } 96705b261ecSmrg else if (stuff->format == ZPixmap) 96805b261ecSmrg { 96905b261ecSmrg (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, 97005b261ecSmrg stuff->width, stuff->height, 97105b261ecSmrg stuff->format, stuff->planeMask, 97205b261ecSmrg shmdesc->addr + stuff->offset); 97305b261ecSmrg } 97405b261ecSmrg else 97505b261ecSmrg { 97605b261ecSmrg 97705b261ecSmrg length = stuff->offset; 97805b261ecSmrg for (; plane; plane >>= 1) 97905b261ecSmrg { 98005b261ecSmrg if (stuff->planeMask & plane) 98105b261ecSmrg { 98205b261ecSmrg (*pDraw->pScreen->GetImage)(pDraw, 98305b261ecSmrg stuff->x, stuff->y, 98405b261ecSmrg stuff->width, stuff->height, 98505b261ecSmrg stuff->format, plane, 98605b261ecSmrg shmdesc->addr + length); 98705b261ecSmrg length += lenPer; 98805b261ecSmrg } 98905b261ecSmrg } 99005b261ecSmrg } 99105b261ecSmrg 99205b261ecSmrg if (client->swapped) { 99305b261ecSmrg swaps(&xgi.sequenceNumber, n); 99405b261ecSmrg swapl(&xgi.length, n); 99505b261ecSmrg swapl(&xgi.visual, n); 99605b261ecSmrg swapl(&xgi.size, n); 99705b261ecSmrg } 99805b261ecSmrg WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); 99905b261ecSmrg 100005b261ecSmrg return(client->noClientException); 100105b261ecSmrg} 100205b261ecSmrg 100305b261ecSmrgstatic PixmapPtr 10044642e01fSmrgfbShmCreatePixmap (ScreenPtr pScreen, 10054642e01fSmrg int width, int height, int depth, char *addr) 100605b261ecSmrg{ 10074642e01fSmrg PixmapPtr pPixmap; 100805b261ecSmrg 10094642e01fSmrg pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); 101005b261ecSmrg if (!pPixmap) 101105b261ecSmrg return NullPixmap; 101205b261ecSmrg 101305b261ecSmrg if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, 101405b261ecSmrg BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { 101505b261ecSmrg (*pScreen->DestroyPixmap)(pPixmap); 101605b261ecSmrg return NullPixmap; 101705b261ecSmrg } 101805b261ecSmrg return pPixmap; 101905b261ecSmrg} 102005b261ecSmrg 102105b261ecSmrgstatic int 10224642e01fSmrgProcShmCreatePixmap(ClientPtr client) 102305b261ecSmrg{ 102405b261ecSmrg PixmapPtr pMap; 102505b261ecSmrg DrawablePtr pDraw; 102605b261ecSmrg DepthPtr pDepth; 10274642e01fSmrg int i, rc; 102805b261ecSmrg ShmDescPtr shmdesc; 102905b261ecSmrg REQUEST(xShmCreatePixmapReq); 103005b261ecSmrg unsigned int width, height, depth; 103105b261ecSmrg unsigned long size; 103205b261ecSmrg 103305b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 103405b261ecSmrg client->errorValue = stuff->pid; 103505b261ecSmrg if (!sharedPixmaps) 103605b261ecSmrg return BadImplementation; 103705b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 103805b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 10394642e01fSmrg DixGetAttrAccess); 104005b261ecSmrg if (rc != Success) 104105b261ecSmrg return rc; 104205b261ecSmrg 104305b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 104405b261ecSmrg 104505b261ecSmrg width = stuff->width; 104605b261ecSmrg height = stuff->height; 104705b261ecSmrg depth = stuff->depth; 104805b261ecSmrg if (!width || !height || !depth) 104905b261ecSmrg { 105005b261ecSmrg client->errorValue = 0; 105105b261ecSmrg return BadValue; 105205b261ecSmrg } 105305b261ecSmrg if (width > 32767 || height > 32767) 105405b261ecSmrg return BadAlloc; 105505b261ecSmrg 105605b261ecSmrg if (stuff->depth != 1) 105705b261ecSmrg { 105805b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 105905b261ecSmrg for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) 106005b261ecSmrg if (pDepth->depth == stuff->depth) 106105b261ecSmrg goto CreatePmap; 106205b261ecSmrg client->errorValue = stuff->depth; 106305b261ecSmrg return BadValue; 106405b261ecSmrg } 106505b261ecSmrg 106605b261ecSmrgCreatePmap: 106705b261ecSmrg size = PixmapBytePad(width, depth) * height; 106805b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 106905b261ecSmrg if (size < width * height) 107005b261ecSmrg return BadAlloc; 107105b261ecSmrg } 107205b261ecSmrg /* thankfully, offset is unsigned */ 107305b261ecSmrg if (stuff->offset + size < size) 107405b261ecSmrg return BadAlloc; 107505b261ecSmrg 107605b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 107705b261ecSmrg pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( 107805b261ecSmrg pDraw->pScreen, stuff->width, 107905b261ecSmrg stuff->height, stuff->depth, 108005b261ecSmrg shmdesc->addr + stuff->offset); 108105b261ecSmrg if (pMap) 108205b261ecSmrg { 10834642e01fSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 10844642e01fSmrg pMap, RT_NONE, NULL, DixCreateAccess); 10854642e01fSmrg if (rc != Success) { 10864642e01fSmrg pDraw->pScreen->DestroyPixmap(pMap); 10874642e01fSmrg return rc; 10884642e01fSmrg } 10894642e01fSmrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); 109005b261ecSmrg shmdesc->refcnt++; 109105b261ecSmrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 109205b261ecSmrg pMap->drawable.id = stuff->pid; 109305b261ecSmrg if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) 109405b261ecSmrg { 109505b261ecSmrg return(client->noClientException); 109605b261ecSmrg } 10974642e01fSmrg pDraw->pScreen->DestroyPixmap(pMap); 109805b261ecSmrg } 109905b261ecSmrg return (BadAlloc); 110005b261ecSmrg} 110105b261ecSmrg 110205b261ecSmrgstatic int 11034642e01fSmrgProcShmDispatch (ClientPtr client) 110405b261ecSmrg{ 110505b261ecSmrg REQUEST(xReq); 110605b261ecSmrg switch (stuff->data) 110705b261ecSmrg { 110805b261ecSmrg case X_ShmQueryVersion: 110905b261ecSmrg return ProcShmQueryVersion(client); 111005b261ecSmrg case X_ShmAttach: 111105b261ecSmrg return ProcShmAttach(client); 111205b261ecSmrg case X_ShmDetach: 111305b261ecSmrg return ProcShmDetach(client); 111405b261ecSmrg case X_ShmPutImage: 111505b261ecSmrg#ifdef PANORAMIX 111605b261ecSmrg if ( !noPanoramiXExtension ) 111705b261ecSmrg return ProcPanoramiXShmPutImage(client); 111805b261ecSmrg#endif 111905b261ecSmrg return ProcShmPutImage(client); 112005b261ecSmrg case X_ShmGetImage: 112105b261ecSmrg#ifdef PANORAMIX 112205b261ecSmrg if ( !noPanoramiXExtension ) 112305b261ecSmrg return ProcPanoramiXShmGetImage(client); 112405b261ecSmrg#endif 112505b261ecSmrg return ProcShmGetImage(client); 112605b261ecSmrg case X_ShmCreatePixmap: 112705b261ecSmrg#ifdef PANORAMIX 112805b261ecSmrg if ( !noPanoramiXExtension ) 112905b261ecSmrg return ProcPanoramiXShmCreatePixmap(client); 113005b261ecSmrg#endif 113105b261ecSmrg return ProcShmCreatePixmap(client); 113205b261ecSmrg default: 113305b261ecSmrg return BadRequest; 113405b261ecSmrg } 113505b261ecSmrg} 113605b261ecSmrg 113705b261ecSmrgstatic void 11384642e01fSmrgSShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to) 113905b261ecSmrg{ 114005b261ecSmrg to->type = from->type; 114105b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 114205b261ecSmrg cpswapl(from->drawable, to->drawable); 114305b261ecSmrg cpswaps(from->minorEvent, to->minorEvent); 114405b261ecSmrg to->majorEvent = from->majorEvent; 114505b261ecSmrg cpswapl(from->shmseg, to->shmseg); 114605b261ecSmrg cpswapl(from->offset, to->offset); 114705b261ecSmrg} 114805b261ecSmrg 114905b261ecSmrgstatic int 11504642e01fSmrgSProcShmQueryVersion(ClientPtr client) 115105b261ecSmrg{ 11524642e01fSmrg int n; 115305b261ecSmrg REQUEST(xShmQueryVersionReq); 115405b261ecSmrg 115505b261ecSmrg swaps(&stuff->length, n); 115605b261ecSmrg return ProcShmQueryVersion(client); 115705b261ecSmrg} 115805b261ecSmrg 115905b261ecSmrgstatic int 11604642e01fSmrgSProcShmAttach(ClientPtr client) 116105b261ecSmrg{ 11624642e01fSmrg int n; 116305b261ecSmrg REQUEST(xShmAttachReq); 116405b261ecSmrg swaps(&stuff->length, n); 116505b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 116605b261ecSmrg swapl(&stuff->shmseg, n); 116705b261ecSmrg swapl(&stuff->shmid, n); 116805b261ecSmrg return ProcShmAttach(client); 116905b261ecSmrg} 117005b261ecSmrg 117105b261ecSmrgstatic int 11724642e01fSmrgSProcShmDetach(ClientPtr client) 117305b261ecSmrg{ 11744642e01fSmrg int n; 117505b261ecSmrg REQUEST(xShmDetachReq); 117605b261ecSmrg swaps(&stuff->length, n); 117705b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 117805b261ecSmrg swapl(&stuff->shmseg, n); 117905b261ecSmrg return ProcShmDetach(client); 118005b261ecSmrg} 118105b261ecSmrg 118205b261ecSmrgstatic int 11834642e01fSmrgSProcShmPutImage(ClientPtr client) 118405b261ecSmrg{ 11854642e01fSmrg int n; 118605b261ecSmrg REQUEST(xShmPutImageReq); 118705b261ecSmrg swaps(&stuff->length, n); 118805b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 118905b261ecSmrg swapl(&stuff->drawable, n); 119005b261ecSmrg swapl(&stuff->gc, n); 119105b261ecSmrg swaps(&stuff->totalWidth, n); 119205b261ecSmrg swaps(&stuff->totalHeight, n); 119305b261ecSmrg swaps(&stuff->srcX, n); 119405b261ecSmrg swaps(&stuff->srcY, n); 119505b261ecSmrg swaps(&stuff->srcWidth, n); 119605b261ecSmrg swaps(&stuff->srcHeight, n); 119705b261ecSmrg swaps(&stuff->dstX, n); 119805b261ecSmrg swaps(&stuff->dstY, n); 119905b261ecSmrg swapl(&stuff->shmseg, n); 120005b261ecSmrg swapl(&stuff->offset, n); 120105b261ecSmrg return ProcShmPutImage(client); 120205b261ecSmrg} 120305b261ecSmrg 120405b261ecSmrgstatic int 12054642e01fSmrgSProcShmGetImage(ClientPtr client) 120605b261ecSmrg{ 12074642e01fSmrg int n; 120805b261ecSmrg REQUEST(xShmGetImageReq); 120905b261ecSmrg swaps(&stuff->length, n); 121005b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 121105b261ecSmrg swapl(&stuff->drawable, n); 121205b261ecSmrg swaps(&stuff->x, n); 121305b261ecSmrg swaps(&stuff->y, n); 121405b261ecSmrg swaps(&stuff->width, n); 121505b261ecSmrg swaps(&stuff->height, n); 121605b261ecSmrg swapl(&stuff->planeMask, n); 121705b261ecSmrg swapl(&stuff->shmseg, n); 121805b261ecSmrg swapl(&stuff->offset, n); 121905b261ecSmrg return ProcShmGetImage(client); 122005b261ecSmrg} 122105b261ecSmrg 122205b261ecSmrgstatic int 12234642e01fSmrgSProcShmCreatePixmap(ClientPtr client) 122405b261ecSmrg{ 12254642e01fSmrg int n; 122605b261ecSmrg REQUEST(xShmCreatePixmapReq); 122705b261ecSmrg swaps(&stuff->length, n); 122805b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 122905b261ecSmrg swapl(&stuff->pid, n); 123005b261ecSmrg swapl(&stuff->drawable, n); 123105b261ecSmrg swaps(&stuff->width, n); 123205b261ecSmrg swaps(&stuff->height, n); 123305b261ecSmrg swapl(&stuff->shmseg, n); 123405b261ecSmrg swapl(&stuff->offset, n); 123505b261ecSmrg return ProcShmCreatePixmap(client); 123605b261ecSmrg} 123705b261ecSmrg 123805b261ecSmrgstatic int 12394642e01fSmrgSProcShmDispatch (ClientPtr client) 124005b261ecSmrg{ 124105b261ecSmrg REQUEST(xReq); 124205b261ecSmrg switch (stuff->data) 124305b261ecSmrg { 124405b261ecSmrg case X_ShmQueryVersion: 124505b261ecSmrg return SProcShmQueryVersion(client); 124605b261ecSmrg case X_ShmAttach: 124705b261ecSmrg return SProcShmAttach(client); 124805b261ecSmrg case X_ShmDetach: 124905b261ecSmrg return SProcShmDetach(client); 125005b261ecSmrg case X_ShmPutImage: 125105b261ecSmrg return SProcShmPutImage(client); 125205b261ecSmrg case X_ShmGetImage: 125305b261ecSmrg return SProcShmGetImage(client); 125405b261ecSmrg case X_ShmCreatePixmap: 125505b261ecSmrg return SProcShmCreatePixmap(client); 125605b261ecSmrg default: 125705b261ecSmrg return BadRequest; 125805b261ecSmrg } 125905b261ecSmrg} 1260