property.c revision 9ace9065
105b261ecSmrg/***********************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1987, 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
2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2705b261ecSmrg
2805b261ecSmrg                        All Rights Reserved
2905b261ecSmrg
3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its
3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted,
3205b261ecSmrgprovided that the above copyright notice appear in all copies and that
3305b261ecSmrgboth that copyright notice and this permission notice appear in
3405b261ecSmrgsupporting documentation, and that the name of Digital not be
3505b261ecSmrgused in advertising or publicity pertaining to distribution of the
3605b261ecSmrgsoftware without specific, written prior permission.
3705b261ecSmrg
3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4405b261ecSmrgSOFTWARE.
4505b261ecSmrg
4605b261ecSmrg******************************************************************/
4705b261ecSmrg
4805b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
4905b261ecSmrg#include <dix-config.h>
5005b261ecSmrg#endif
5105b261ecSmrg
5205b261ecSmrg#include <X11/X.h>
5305b261ecSmrg#include <X11/Xproto.h>
5405b261ecSmrg#include "windowstr.h"
5505b261ecSmrg#include "propertyst.h"
5605b261ecSmrg#include "dixstruct.h"
5705b261ecSmrg#include "dispatch.h"
5805b261ecSmrg#include "swaprep.h"
5905b261ecSmrg#include "xace.h"
6005b261ecSmrg
6105b261ecSmrg/*****************************************************************
6205b261ecSmrg * Property Stuff
6305b261ecSmrg *
644642e01fSmrg *    dixLookupProperty, dixChangeProperty, DeleteProperty
6505b261ecSmrg *
664642e01fSmrg *   Properties belong to windows.  The list of properties should not be
674642e01fSmrg *   traversed directly.  Instead, use the three functions listed above.
6805b261ecSmrg *
6905b261ecSmrg *****************************************************************/
7005b261ecSmrg
7105b261ecSmrg#ifdef notdef
7205b261ecSmrgstatic void
7305b261ecSmrgPrintPropertys(WindowPtr pWin)
7405b261ecSmrg{
7505b261ecSmrg    PropertyPtr pProp;
7605b261ecSmrg    int j;
7705b261ecSmrg
7805b261ecSmrg    pProp = pWin->userProps;
7905b261ecSmrg    while (pProp)
8005b261ecSmrg    {
814642e01fSmrg        ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type);
824642e01fSmrg        ErrorF("[dix] property format: %d\n", pProp->format);
834642e01fSmrg        ErrorF("[dix] property data: \n");
8405b261ecSmrg        for (j=0; j<(pProp->format/8)*pProp->size; j++)
854642e01fSmrg           ErrorF("[dix] %c\n", pProp->data[j]);
8605b261ecSmrg        pProp = pProp->next;
8705b261ecSmrg    }
8805b261ecSmrg}
8905b261ecSmrg#endif
9005b261ecSmrg
916747b715Smrgint
924642e01fSmrgdixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
934642e01fSmrg		  ClientPtr client, Mask access_mode)
944642e01fSmrg{
954642e01fSmrg    PropertyPtr pProp;
964642e01fSmrg    int rc = BadMatch;
974642e01fSmrg    client->errorValue = propertyName;
984642e01fSmrg
994642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
1004642e01fSmrg	if (pProp->propertyName == propertyName)
1014642e01fSmrg	    break;
1024642e01fSmrg
1034642e01fSmrg    if (pProp)
1044642e01fSmrg	rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode);
1054642e01fSmrg    *result = pProp;
1064642e01fSmrg    return rc;
1074642e01fSmrg}
1084642e01fSmrg
10905b261ecSmrgstatic void
11005b261ecSmrgdeliverPropertyNotifyEvent(WindowPtr pWin, int state, Atom atom)
11105b261ecSmrg{
11205b261ecSmrg    xEvent event;
11305b261ecSmrg
1146747b715Smrg    memset(&event, 0, sizeof(xEvent));
11505b261ecSmrg    event.u.u.type = PropertyNotify;
11605b261ecSmrg    event.u.property.window = pWin->drawable.id;
11705b261ecSmrg    event.u.property.state = state;
11805b261ecSmrg    event.u.property.atom = atom;
11905b261ecSmrg    event.u.property.time = currentTime.milliseconds;
12005b261ecSmrg    DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
12105b261ecSmrg}
12205b261ecSmrg
12305b261ecSmrgint
12405b261ecSmrgProcRotateProperties(ClientPtr client)
12505b261ecSmrg{
12605b261ecSmrg    int     i, j, delta, rc;
12705b261ecSmrg    REQUEST(xRotatePropertiesReq);
12805b261ecSmrg    WindowPtr pWin;
12905b261ecSmrg    Atom * atoms;
13005b261ecSmrg    PropertyPtr * props;               /* array of pointer */
1314642e01fSmrg    PropertyPtr pProp, saved;
13205b261ecSmrg
13305b261ecSmrg    REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
13405b261ecSmrg    UpdateCurrentTime();
1354642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
1364642e01fSmrg    if (rc != Success || stuff->nAtoms <= 0)
13705b261ecSmrg        return rc;
1384642e01fSmrg
13905b261ecSmrg    atoms = (Atom *) & stuff[1];
1406747b715Smrg    props = malloc(stuff->nAtoms * sizeof(PropertyPtr));
1416747b715Smrg    saved = malloc(stuff->nAtoms * sizeof(PropertyRec));
1424642e01fSmrg    if (!props || !saved) {
1434642e01fSmrg	rc = BadAlloc;
1444642e01fSmrg	goto out;
1454642e01fSmrg    }
1464642e01fSmrg
14705b261ecSmrg    for (i = 0; i < stuff->nAtoms; i++)
14805b261ecSmrg    {
1494642e01fSmrg        if (!ValidAtom(atoms[i])) {
1504642e01fSmrg	    rc = BadAtom;
15105b261ecSmrg	    client->errorValue = atoms[i];
1524642e01fSmrg	    goto out;
15305b261ecSmrg        }
15405b261ecSmrg        for (j = i + 1; j < stuff->nAtoms; j++)
15505b261ecSmrg            if (atoms[j] == atoms[i])
15605b261ecSmrg            {
1574642e01fSmrg		rc = BadMatch;
1584642e01fSmrg		goto out;
15905b261ecSmrg            }
1604642e01fSmrg
1614642e01fSmrg	rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
1624642e01fSmrg			       DixReadAccess|DixWriteAccess);
1634642e01fSmrg	if (rc != Success)
1644642e01fSmrg	    goto out;
1654642e01fSmrg
16605b261ecSmrg        props[i] = pProp;
1674642e01fSmrg	saved[i] = *pProp;
16805b261ecSmrg    }
16905b261ecSmrg    delta = stuff->nPositions;
17005b261ecSmrg
17105b261ecSmrg    /* If the rotation is a complete 360 degrees, then moving the properties
17205b261ecSmrg	around and generating PropertyNotify events should be skipped. */
17305b261ecSmrg
1744642e01fSmrg    if (abs(delta) % stuff->nAtoms)
17505b261ecSmrg    {
17605b261ecSmrg	while (delta < 0)                  /* faster if abs value is small */
17705b261ecSmrg            delta += stuff->nAtoms;
17805b261ecSmrg    	for (i = 0; i < stuff->nAtoms; i++)
17905b261ecSmrg 	{
1804642e01fSmrg	    j = (i + delta) % stuff->nAtoms;
1814642e01fSmrg	    deliverPropertyNotifyEvent(pWin, PropertyNewValue, atoms[i]);
1824642e01fSmrg
1834642e01fSmrg	    /* Preserve name and devPrivates */
1844642e01fSmrg	    props[j]->type = saved[i].type;
1854642e01fSmrg	    props[j]->format = saved[i].format;
1864642e01fSmrg	    props[j]->size = saved[i].size;
1874642e01fSmrg	    props[j]->data = saved[i].data;
18805b261ecSmrg	}
18905b261ecSmrg    }
1904642e01fSmrgout:
1916747b715Smrg    free(saved);
1926747b715Smrg    free(props);
1934642e01fSmrg    return rc;
19405b261ecSmrg}
19505b261ecSmrg
19605b261ecSmrgint
19705b261ecSmrgProcChangeProperty(ClientPtr client)
19805b261ecSmrg{
19905b261ecSmrg    WindowPtr pWin;
20005b261ecSmrg    char format, mode;
20105b261ecSmrg    unsigned long len;
20205b261ecSmrg    int sizeInBytes, totalSize, err;
20305b261ecSmrg    REQUEST(xChangePropertyReq);
20405b261ecSmrg
20505b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
20605b261ecSmrg    UpdateCurrentTime();
20705b261ecSmrg    format = stuff->format;
20805b261ecSmrg    mode = stuff->mode;
20905b261ecSmrg    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
21005b261ecSmrg	(mode != PropModePrepend))
21105b261ecSmrg    {
21205b261ecSmrg	client->errorValue = mode;
21305b261ecSmrg	return BadValue;
21405b261ecSmrg    }
21505b261ecSmrg    if ((format != 8) && (format != 16) && (format != 32))
21605b261ecSmrg    {
21705b261ecSmrg	client->errorValue = format;
21805b261ecSmrg        return BadValue;
21905b261ecSmrg    }
22005b261ecSmrg    len = stuff->nUnits;
2216747b715Smrg    if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq)))
22205b261ecSmrg	return BadLength;
22305b261ecSmrg    sizeInBytes = format>>3;
22405b261ecSmrg    totalSize = len * sizeInBytes;
22505b261ecSmrg    REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
22605b261ecSmrg
2274642e01fSmrg    err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
22805b261ecSmrg    if (err != Success)
22905b261ecSmrg	return err;
23005b261ecSmrg    if (!ValidAtom(stuff->property))
23105b261ecSmrg    {
23205b261ecSmrg	client->errorValue = stuff->property;
2336747b715Smrg	return BadAtom;
23405b261ecSmrg    }
23505b261ecSmrg    if (!ValidAtom(stuff->type))
23605b261ecSmrg    {
23705b261ecSmrg	client->errorValue = stuff->type;
2386747b715Smrg	return BadAtom;
23905b261ecSmrg    }
24005b261ecSmrg
2414642e01fSmrg    err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
2424642e01fSmrg				  (int)format, (int)mode, len, &stuff[1],
2434642e01fSmrg				  TRUE);
24405b261ecSmrg    if (err != Success)
24505b261ecSmrg	return err;
24605b261ecSmrg    else
2476747b715Smrg	return Success;
24805b261ecSmrg}
24905b261ecSmrg
2506747b715Smrgint
2514642e01fSmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
2524642e01fSmrg			Atom type, int format, int mode, unsigned long len,
2534642e01fSmrg			pointer value, Bool sendevent)
25405b261ecSmrg{
25505b261ecSmrg    PropertyPtr pProp;
2566747b715Smrg    PropertyRec savedProp;
2574642e01fSmrg    int sizeInBytes, totalSize, rc;
2586747b715Smrg    unsigned char *data;
2594642e01fSmrg    Mask access_mode;
26005b261ecSmrg
26105b261ecSmrg    sizeInBytes = format>>3;
26205b261ecSmrg    totalSize = len * sizeInBytes;
2634642e01fSmrg    access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
26405b261ecSmrg
26505b261ecSmrg    /* first see if property already exists */
2664642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
26705b261ecSmrg
2684642e01fSmrg    if (rc == BadMatch)   /* just add to list */
26905b261ecSmrg    {
27005b261ecSmrg	if (!pWin->optional && !MakeWindowOptional (pWin))
2716747b715Smrg	    return BadAlloc;
2726747b715Smrg	pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
27305b261ecSmrg	if (!pProp)
2746747b715Smrg	    return BadAlloc;
2756747b715Smrg        data = malloc(totalSize);
27605b261ecSmrg	if (!data && len)
27705b261ecSmrg	{
2786747b715Smrg	    dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
2796747b715Smrg	    return BadAlloc;
28005b261ecSmrg	}
2816747b715Smrg        memcpy(data, value, totalSize);
28205b261ecSmrg        pProp->propertyName = property;
28305b261ecSmrg        pProp->type = type;
28405b261ecSmrg        pProp->format = format;
28505b261ecSmrg        pProp->data = data;
28605b261ecSmrg	pProp->size = len;
2874642e01fSmrg	rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
2884642e01fSmrg				    DixCreateAccess|DixWriteAccess);
2894642e01fSmrg	if (rc != Success) {
2906747b715Smrg	    free(data);
2916747b715Smrg	    dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
2924642e01fSmrg	    pClient->errorValue = property;
2934642e01fSmrg	    return rc;
2944642e01fSmrg	}
29505b261ecSmrg        pProp->next = pWin->optional->userProps;
29605b261ecSmrg        pWin->optional->userProps = pProp;
29705b261ecSmrg    }
2984642e01fSmrg    else if (rc == Success)
29905b261ecSmrg    {
30005b261ecSmrg	/* To append or prepend to a property the request format and type
30105b261ecSmrg		must match those of the already defined property.  The
30205b261ecSmrg		existing format and type are irrelevant when using the mode
30305b261ecSmrg		"PropModeReplace" since they will be written over. */
30405b261ecSmrg
30505b261ecSmrg        if ((format != pProp->format) && (mode != PropModeReplace))
3066747b715Smrg	    return BadMatch;
30705b261ecSmrg        if ((pProp->type != type) && (mode != PropModeReplace))
3086747b715Smrg            return BadMatch;
3096747b715Smrg
3106747b715Smrg	/* save the old values for later */
3116747b715Smrg	savedProp = *pProp;
3126747b715Smrg
31305b261ecSmrg        if (mode == PropModeReplace)
31405b261ecSmrg        {
3156747b715Smrg	    data = malloc(totalSize);
3166747b715Smrg	    if (!data && len)
3176747b715Smrg		return BadAlloc;
3186747b715Smrg	    memcpy(data, value, totalSize);
3196747b715Smrg	    pProp->data = data;
32005b261ecSmrg	    pProp->size = len;
32105b261ecSmrg    	    pProp->type = type;
32205b261ecSmrg	    pProp->format = format;
32305b261ecSmrg	}
32405b261ecSmrg	else if (len == 0)
32505b261ecSmrg	{
32605b261ecSmrg	    /* do nothing */
32705b261ecSmrg	}
32805b261ecSmrg        else if (mode == PropModeAppend)
32905b261ecSmrg        {
3306747b715Smrg	    data = malloc((pProp->size + len) * sizeInBytes);
33105b261ecSmrg	    if (!data)
3326747b715Smrg		return BadAlloc;
3336747b715Smrg	    memcpy(data, pProp->data, pProp->size * sizeInBytes);
3346747b715Smrg	    memcpy(data + pProp->size * sizeInBytes, value, totalSize);
33505b261ecSmrg            pProp->data = data;
33605b261ecSmrg            pProp->size += len;
33705b261ecSmrg	}
33805b261ecSmrg        else if (mode == PropModePrepend)
33905b261ecSmrg        {
3406747b715Smrg            data = malloc(sizeInBytes * (len + pProp->size));
34105b261ecSmrg	    if (!data)
3426747b715Smrg		return BadAlloc;
3436747b715Smrg            memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
3446747b715Smrg            memcpy(data, value, totalSize);
34505b261ecSmrg            pProp->data = data;
34605b261ecSmrg            pProp->size += len;
34705b261ecSmrg	}
3486747b715Smrg
3496747b715Smrg	/* Allow security modules to check the new content */
3506747b715Smrg	access_mode |= DixPostAccess;
3516747b715Smrg	rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode);
3526747b715Smrg	if (rc == Success)
3536747b715Smrg	{
3546747b715Smrg	    if (savedProp.data != pProp->data)
3556747b715Smrg		free(savedProp.data);
3566747b715Smrg	}
3576747b715Smrg	else
3586747b715Smrg	{
3596747b715Smrg	    if (savedProp.data != pProp->data)
3606747b715Smrg		free(pProp->data);
3616747b715Smrg	    *pProp = savedProp;
3626747b715Smrg	    return rc;
3636747b715Smrg	}
36405b261ecSmrg    }
3654642e01fSmrg    else
3664642e01fSmrg	return rc;
36705b261ecSmrg
36805b261ecSmrg    if (sendevent)
36905b261ecSmrg	deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
37005b261ecSmrg
3716747b715Smrg    return Success;
37205b261ecSmrg}
37305b261ecSmrg
3746747b715Smrgint
3754642e01fSmrgChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format,
3764642e01fSmrg		     int mode, unsigned long len, pointer value,
3774642e01fSmrg		     Bool sendevent)
3784642e01fSmrg{
3794642e01fSmrg    return dixChangeWindowProperty(serverClient, pWin, property, type, format,
3804642e01fSmrg				   mode, len, value, sendevent);
3814642e01fSmrg}
3824642e01fSmrg
38305b261ecSmrgint
3844642e01fSmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
38505b261ecSmrg{
38605b261ecSmrg    PropertyPtr pProp, prevProp;
3874642e01fSmrg    int rc;
38805b261ecSmrg
3894642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
3904642e01fSmrg    if (rc == BadMatch)
3914642e01fSmrg	return Success; /* Succeed if property does not exist */
3924642e01fSmrg
3934642e01fSmrg    if (rc == Success) {
3944642e01fSmrg	if (pWin->optional->userProps == pProp) {
3954642e01fSmrg	    /* Takes care of head */
39605b261ecSmrg            if (!(pWin->optional->userProps = pProp->next))
39705b261ecSmrg		CheckWindowOptionalNeed (pWin);
3984642e01fSmrg	} else {
3994642e01fSmrg	    /* Need to traverse to find the previous element */
4004642e01fSmrg	    prevProp = pWin->optional->userProps;
4014642e01fSmrg	    while (prevProp->next != pProp)
4024642e01fSmrg		prevProp = prevProp->next;
4034642e01fSmrg	    prevProp->next = pProp->next;
4044642e01fSmrg	}
4054642e01fSmrg
40605b261ecSmrg	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
4076747b715Smrg	free(pProp->data);
4086747b715Smrg	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
40905b261ecSmrg    }
4104642e01fSmrg    return rc;
41105b261ecSmrg}
41205b261ecSmrg
41305b261ecSmrgvoid
41405b261ecSmrgDeleteAllWindowProperties(WindowPtr pWin)
41505b261ecSmrg{
41605b261ecSmrg    PropertyPtr pProp, pNextProp;
41705b261ecSmrg
41805b261ecSmrg    pProp = wUserProps (pWin);
41905b261ecSmrg    while (pProp)
42005b261ecSmrg    {
42105b261ecSmrg	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
42205b261ecSmrg	pNextProp = pProp->next;
4236747b715Smrg        free(pProp->data);
4246747b715Smrg	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
42505b261ecSmrg	pProp = pNextProp;
42605b261ecSmrg    }
4279ace9065Smrg
4289ace9065Smrg    if (pWin->optional)
4299ace9065Smrg        pWin->optional->userProps = NULL;
43005b261ecSmrg}
43105b261ecSmrg
43205b261ecSmrgstatic int
43305b261ecSmrgNullPropertyReply(
43405b261ecSmrg    ClientPtr client,
43505b261ecSmrg    ATOM propertyType,
43605b261ecSmrg    int format,
43705b261ecSmrg    xGetPropertyReply *reply)
43805b261ecSmrg{
43905b261ecSmrg    reply->nItems = 0;
44005b261ecSmrg    reply->length = 0;
44105b261ecSmrg    reply->bytesAfter = 0;
44205b261ecSmrg    reply->propertyType = propertyType;
44305b261ecSmrg    reply->format = format;
44405b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), reply);
4456747b715Smrg    return Success;
44605b261ecSmrg}
44705b261ecSmrg
44805b261ecSmrg/*****************
44905b261ecSmrg * GetProperty
45005b261ecSmrg *    If type Any is specified, returns the property from the specified
45105b261ecSmrg *    window regardless of its type.  If a type is specified, returns the
45205b261ecSmrg *    property only if its type equals the specified type.
45305b261ecSmrg *    If delete is True and a property is returned, the property is also
45405b261ecSmrg *    deleted from the window and a PropertyNotify event is generated on the
45505b261ecSmrg *    window.
45605b261ecSmrg *****************/
45705b261ecSmrg
45805b261ecSmrgint
45905b261ecSmrgProcGetProperty(ClientPtr client)
46005b261ecSmrg{
46105b261ecSmrg    PropertyPtr pProp, prevProp;
4624642e01fSmrg    unsigned long n, len, ind;
4634642e01fSmrg    int rc;
46405b261ecSmrg    WindowPtr pWin;
46505b261ecSmrg    xGetPropertyReply reply;
4664642e01fSmrg    Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
46705b261ecSmrg    REQUEST(xGetPropertyReq);
46805b261ecSmrg
46905b261ecSmrg    REQUEST_SIZE_MATCH(xGetPropertyReq);
4704642e01fSmrg    if (stuff->delete) {
47105b261ecSmrg	UpdateCurrentTime();
4724642e01fSmrg	win_mode |= DixSetPropAccess;
4734642e01fSmrg	prop_mode |= DixDestroyAccess;
4744642e01fSmrg    }
4754642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
47605b261ecSmrg    if (rc != Success)
4776747b715Smrg	return (rc == BadMatch) ? BadWindow : rc;
47805b261ecSmrg
47905b261ecSmrg    if (!ValidAtom(stuff->property))
48005b261ecSmrg    {
48105b261ecSmrg	client->errorValue = stuff->property;
4826747b715Smrg	return BadAtom;
48305b261ecSmrg    }
48405b261ecSmrg    if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
48505b261ecSmrg    {
48605b261ecSmrg	client->errorValue = stuff->delete;
4876747b715Smrg	return BadValue;
48805b261ecSmrg    }
48905b261ecSmrg    if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
49005b261ecSmrg    {
49105b261ecSmrg	client->errorValue = stuff->type;
4926747b715Smrg	return BadAtom;
49305b261ecSmrg    }
49405b261ecSmrg
4956747b715Smrg    memset(&reply, 0, sizeof(xGetPropertyReply));
49605b261ecSmrg    reply.type = X_Reply;
49705b261ecSmrg    reply.sequenceNumber = client->sequence;
49805b261ecSmrg
4994642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
5004642e01fSmrg    if (rc == BadMatch)
5014642e01fSmrg	return NullPropertyReply(client, None, 0, &reply);
5024642e01fSmrg    else if (rc != Success)
5034642e01fSmrg	return rc;
50405b261ecSmrg
50505b261ecSmrg    /* If the request type and actual type don't match. Return the
50605b261ecSmrg    property information, but not the data. */
50705b261ecSmrg
50805b261ecSmrg    if (((stuff->type != pProp->type) &&
50905b261ecSmrg	 (stuff->type != AnyPropertyType))
51005b261ecSmrg       )
51105b261ecSmrg    {
51205b261ecSmrg	reply.bytesAfter = pProp->size;
51305b261ecSmrg	reply.format = pProp->format;
51405b261ecSmrg	reply.length = 0;
51505b261ecSmrg	reply.nItems = 0;
51605b261ecSmrg	reply.propertyType = pProp->type;
51705b261ecSmrg	WriteReplyToClient(client, sizeof(xGenericReply), &reply);
5186747b715Smrg	return Success;
51905b261ecSmrg    }
52005b261ecSmrg
52105b261ecSmrg/*
52205b261ecSmrg *  Return type, format, value to client
52305b261ecSmrg */
52405b261ecSmrg    n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */
52505b261ecSmrg    ind = stuff->longOffset << 2;
52605b261ecSmrg
52705b261ecSmrg   /* If longOffset is invalid such that it causes "len" to
52805b261ecSmrg	    be negative, it's a value error. */
52905b261ecSmrg
53005b261ecSmrg    if (n < ind)
53105b261ecSmrg    {
53205b261ecSmrg	client->errorValue = stuff->longOffset;
53305b261ecSmrg	return BadValue;
53405b261ecSmrg    }
53505b261ecSmrg
53605b261ecSmrg    len = min(n - ind, 4 * stuff->longLength);
53705b261ecSmrg
53805b261ecSmrg    reply.bytesAfter = n - (ind + len);
53905b261ecSmrg    reply.format = pProp->format;
5406747b715Smrg    reply.length = bytes_to_int32(len);
54105b261ecSmrg    reply.nItems = len / (pProp->format / 8 );
54205b261ecSmrg    reply.propertyType = pProp->type;
54305b261ecSmrg
54405b261ecSmrg    if (stuff->delete && (reply.bytesAfter == 0))
54505b261ecSmrg	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
54605b261ecSmrg
54705b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
54805b261ecSmrg    if (len)
54905b261ecSmrg    {
55005b261ecSmrg	switch (reply.format) {
55105b261ecSmrg	case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
55205b261ecSmrg	case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
55305b261ecSmrg	default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
55405b261ecSmrg	}
55505b261ecSmrg	WriteSwappedDataToClient(client, len,
55605b261ecSmrg				 (char *)pProp->data + ind);
55705b261ecSmrg    }
55805b261ecSmrg
5594642e01fSmrg    if (stuff->delete && (reply.bytesAfter == 0)) {
5604642e01fSmrg	/* Delete the Property */
5614642e01fSmrg	if (pWin->optional->userProps == pProp) {
5624642e01fSmrg	    /* Takes care of head */
5634642e01fSmrg            if (!(pWin->optional->userProps = pProp->next))
56405b261ecSmrg		CheckWindowOptionalNeed (pWin);
5654642e01fSmrg	} else {
5664642e01fSmrg	    /* Need to traverse to find the previous element */
5674642e01fSmrg	    prevProp = pWin->optional->userProps;
5684642e01fSmrg	    while (prevProp->next != pProp)
5694642e01fSmrg		prevProp = prevProp->next;
57005b261ecSmrg	    prevProp->next = pProp->next;
5714642e01fSmrg	}
5724642e01fSmrg
5736747b715Smrg	free(pProp->data);
5746747b715Smrg	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
57505b261ecSmrg    }
5766747b715Smrg    return Success;
57705b261ecSmrg}
57805b261ecSmrg
57905b261ecSmrgint
58005b261ecSmrgProcListProperties(ClientPtr client)
58105b261ecSmrg{
58205b261ecSmrg    Atom *pAtoms = NULL, *temppAtoms;
58305b261ecSmrg    xListPropertiesReply xlpr;
58405b261ecSmrg    int	rc, numProps = 0;
58505b261ecSmrg    WindowPtr pWin;
5864642e01fSmrg    PropertyPtr pProp, realProp;
58705b261ecSmrg    REQUEST(xResourceReq);
58805b261ecSmrg
58905b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
5904642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
59105b261ecSmrg    if (rc != Success)
59205b261ecSmrg        return rc;
59305b261ecSmrg
5944642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
59505b261ecSmrg	numProps++;
5964642e01fSmrg
5976747b715Smrg    if (numProps && !(pAtoms = malloc(numProps * sizeof(Atom))))
5984642e01fSmrg	return BadAlloc;
5994642e01fSmrg
6004642e01fSmrg    numProps = 0;
6014642e01fSmrg    temppAtoms = pAtoms;
6024642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
6034642e01fSmrg	realProp = pProp;
6044642e01fSmrg	rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
6054642e01fSmrg	if (rc == Success && realProp == pProp) {
6064642e01fSmrg	    *temppAtoms++ = pProp->propertyName;
6074642e01fSmrg	    numProps++;
6084642e01fSmrg	}
60905b261ecSmrg    }
61005b261ecSmrg
61105b261ecSmrg    xlpr.type = X_Reply;
61205b261ecSmrg    xlpr.nProperties = numProps;
6136747b715Smrg    xlpr.length = bytes_to_int32(numProps * sizeof(Atom));
61405b261ecSmrg    xlpr.sequenceNumber = client->sequence;
61505b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
61605b261ecSmrg    if (numProps)
61705b261ecSmrg    {
61805b261ecSmrg        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
61905b261ecSmrg        WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
62005b261ecSmrg    }
6216747b715Smrg    free(pAtoms);
6226747b715Smrg    return Success;
62305b261ecSmrg}
62405b261ecSmrg
62505b261ecSmrgint
62605b261ecSmrgProcDeleteProperty(ClientPtr client)
62705b261ecSmrg{
62805b261ecSmrg    WindowPtr pWin;
62905b261ecSmrg    REQUEST(xDeletePropertyReq);
63005b261ecSmrg    int result;
63105b261ecSmrg
63205b261ecSmrg    REQUEST_SIZE_MATCH(xDeletePropertyReq);
63305b261ecSmrg    UpdateCurrentTime();
6344642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
63505b261ecSmrg    if (result != Success)
63605b261ecSmrg        return result;
63705b261ecSmrg    if (!ValidAtom(stuff->property))
63805b261ecSmrg    {
63905b261ecSmrg	client->errorValue = stuff->property;
6406747b715Smrg	return BadAtom;
64105b261ecSmrg    }
64205b261ecSmrg
6436747b715Smrg    return DeleteProperty(client, pWin, stuff->property);
64405b261ecSmrg}
645