property.c revision 35c4bbdf
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
2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
2605b261ecSmrg
2705b261ecSmrg                        All Rights Reserved
2805b261ecSmrg
2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its
3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted,
3105b261ecSmrgprovided that the above copyright notice appear in all copies and that
3235c4bbdfSmrgboth that copyright notice and this permission notice appear in
3305b261ecSmrgsupporting documentation, and that the name of Digital not be
3405b261ecSmrgused in advertising or publicity pertaining to distribution of the
3535c4bbdfSmrgsoftware without specific, written prior permission.
3605b261ecSmrg
3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
4305b261ecSmrgSOFTWARE.
4405b261ecSmrg
4505b261ecSmrg******************************************************************/
4605b261ecSmrg
4705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
4805b261ecSmrg#include <dix-config.h>
4905b261ecSmrg#endif
5005b261ecSmrg
5105b261ecSmrg#include <X11/X.h>
5205b261ecSmrg#include <X11/Xproto.h>
5305b261ecSmrg#include "windowstr.h"
5405b261ecSmrg#include "propertyst.h"
5505b261ecSmrg#include "dixstruct.h"
5605b261ecSmrg#include "dispatch.h"
5705b261ecSmrg#include "swaprep.h"
5805b261ecSmrg#include "xace.h"
5905b261ecSmrg
6005b261ecSmrg/*****************************************************************
6105b261ecSmrg * Property Stuff
6205b261ecSmrg *
634642e01fSmrg *    dixLookupProperty, dixChangeProperty, DeleteProperty
6405b261ecSmrg *
654642e01fSmrg *   Properties belong to windows.  The list of properties should not be
664642e01fSmrg *   traversed directly.  Instead, use the three functions listed above.
6705b261ecSmrg *
6805b261ecSmrg *****************************************************************/
6905b261ecSmrg
7005b261ecSmrg#ifdef notdef
7105b261ecSmrgstatic void
7205b261ecSmrgPrintPropertys(WindowPtr pWin)
7305b261ecSmrg{
7405b261ecSmrg    PropertyPtr pProp;
7505b261ecSmrg    int j;
7605b261ecSmrg
7705b261ecSmrg    pProp = pWin->userProps;
7835c4bbdfSmrg    while (pProp) {
794642e01fSmrg        ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type);
804642e01fSmrg        ErrorF("[dix] property format: %d\n", pProp->format);
814642e01fSmrg        ErrorF("[dix] property data: \n");
8235c4bbdfSmrg        for (j = 0; j < (pProp->format / 8) * pProp->size; j++)
8335c4bbdfSmrg            ErrorF("[dix] %c\n", pProp->data[j]);
8405b261ecSmrg        pProp = pProp->next;
8505b261ecSmrg    }
8605b261ecSmrg}
8705b261ecSmrg#endif
8805b261ecSmrg
896747b715Smrgint
904642e01fSmrgdixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
9135c4bbdfSmrg                  ClientPtr client, Mask access_mode)
924642e01fSmrg{
934642e01fSmrg    PropertyPtr pProp;
944642e01fSmrg    int rc = BadMatch;
9535c4bbdfSmrg
964642e01fSmrg    client->errorValue = propertyName;
974642e01fSmrg
984642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
9935c4bbdfSmrg        if (pProp->propertyName == propertyName)
10035c4bbdfSmrg            break;
1014642e01fSmrg
1024642e01fSmrg    if (pProp)
10335c4bbdfSmrg        rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode);
1044642e01fSmrg    *result = pProp;
1054642e01fSmrg    return rc;
1064642e01fSmrg}
1074642e01fSmrg
10805b261ecSmrgstatic void
10905b261ecSmrgdeliverPropertyNotifyEvent(WindowPtr pWin, int state, Atom atom)
11005b261ecSmrg{
11135c4bbdfSmrg    xEvent event = {
11235c4bbdfSmrg        .u.property.window = pWin->drawable.id,
11335c4bbdfSmrg        .u.property.state = state,
11435c4bbdfSmrg        .u.property.atom = atom,
11535c4bbdfSmrg        .u.property.time = currentTime.milliseconds
11635c4bbdfSmrg    };
11705b261ecSmrg    event.u.u.type = PropertyNotify;
11835c4bbdfSmrg    DeliverEvents(pWin, &event, 1, (WindowPtr) NULL);
11905b261ecSmrg}
12005b261ecSmrg
12105b261ecSmrgint
12205b261ecSmrgProcRotateProperties(ClientPtr client)
12305b261ecSmrg{
12435c4bbdfSmrg    int i, j, delta, rc;
12535c4bbdfSmrg
12605b261ecSmrg    REQUEST(xRotatePropertiesReq);
12705b261ecSmrg    WindowPtr pWin;
12835c4bbdfSmrg    Atom *atoms;
12935c4bbdfSmrg    PropertyPtr *props;         /* array of pointer */
1304642e01fSmrg    PropertyPtr pProp, saved;
13105b261ecSmrg
13205b261ecSmrg    REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
13305b261ecSmrg    UpdateCurrentTime();
1344642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
1354642e01fSmrg    if (rc != Success || stuff->nAtoms <= 0)
13605b261ecSmrg        return rc;
1374642e01fSmrg
13835c4bbdfSmrg    atoms = (Atom *) &stuff[1];
13935c4bbdfSmrg    props = xallocarray(stuff->nAtoms, sizeof(PropertyPtr));
14035c4bbdfSmrg    saved = xallocarray(stuff->nAtoms, sizeof(PropertyRec));
1414642e01fSmrg    if (!props || !saved) {
14235c4bbdfSmrg        rc = BadAlloc;
14335c4bbdfSmrg        goto out;
1444642e01fSmrg    }
1454642e01fSmrg
14635c4bbdfSmrg    for (i = 0; i < stuff->nAtoms; i++) {
1474642e01fSmrg        if (!ValidAtom(atoms[i])) {
14835c4bbdfSmrg            rc = BadAtom;
14935c4bbdfSmrg            client->errorValue = atoms[i];
15035c4bbdfSmrg            goto out;
15105b261ecSmrg        }
15205b261ecSmrg        for (j = i + 1; j < stuff->nAtoms; j++)
15335c4bbdfSmrg            if (atoms[j] == atoms[i]) {
15435c4bbdfSmrg                rc = BadMatch;
15535c4bbdfSmrg                goto out;
15605b261ecSmrg            }
1574642e01fSmrg
15835c4bbdfSmrg        rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
15935c4bbdfSmrg                               DixReadAccess | DixWriteAccess);
16035c4bbdfSmrg        if (rc != Success)
16135c4bbdfSmrg            goto out;
1624642e01fSmrg
16305b261ecSmrg        props[i] = pProp;
16435c4bbdfSmrg        saved[i] = *pProp;
16505b261ecSmrg    }
16605b261ecSmrg    delta = stuff->nPositions;
16705b261ecSmrg
16805b261ecSmrg    /* If the rotation is a complete 360 degrees, then moving the properties
16935c4bbdfSmrg       around and generating PropertyNotify events should be skipped. */
17005b261ecSmrg
17135c4bbdfSmrg    if (abs(delta) % stuff->nAtoms) {
17235c4bbdfSmrg        while (delta < 0)       /* faster if abs value is small */
17305b261ecSmrg            delta += stuff->nAtoms;
17435c4bbdfSmrg        for (i = 0; i < stuff->nAtoms; i++) {
17535c4bbdfSmrg            j = (i + delta) % stuff->nAtoms;
17635c4bbdfSmrg            deliverPropertyNotifyEvent(pWin, PropertyNewValue, atoms[i]);
17735c4bbdfSmrg
17835c4bbdfSmrg            /* Preserve name and devPrivates */
17935c4bbdfSmrg            props[j]->type = saved[i].type;
18035c4bbdfSmrg            props[j]->format = saved[i].format;
18135c4bbdfSmrg            props[j]->size = saved[i].size;
18235c4bbdfSmrg            props[j]->data = saved[i].data;
18335c4bbdfSmrg        }
18405b261ecSmrg    }
18535c4bbdfSmrg out:
1866747b715Smrg    free(saved);
1876747b715Smrg    free(props);
1884642e01fSmrg    return rc;
18905b261ecSmrg}
19005b261ecSmrg
19135c4bbdfSmrgint
19205b261ecSmrgProcChangeProperty(ClientPtr client)
19335c4bbdfSmrg{
19405b261ecSmrg    WindowPtr pWin;
19505b261ecSmrg    char format, mode;
19605b261ecSmrg    unsigned long len;
19705b261ecSmrg    int sizeInBytes, totalSize, err;
19835c4bbdfSmrg
19905b261ecSmrg    REQUEST(xChangePropertyReq);
20005b261ecSmrg
20105b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
20205b261ecSmrg    UpdateCurrentTime();
20305b261ecSmrg    format = stuff->format;
20405b261ecSmrg    mode = stuff->mode;
20505b261ecSmrg    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
20635c4bbdfSmrg        (mode != PropModePrepend)) {
20735c4bbdfSmrg        client->errorValue = mode;
20835c4bbdfSmrg        return BadValue;
20905b261ecSmrg    }
21035c4bbdfSmrg    if ((format != 8) && (format != 16) && (format != 32)) {
21135c4bbdfSmrg        client->errorValue = format;
21205b261ecSmrg        return BadValue;
21305b261ecSmrg    }
21405b261ecSmrg    len = stuff->nUnits;
2156747b715Smrg    if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq)))
21635c4bbdfSmrg        return BadLength;
21735c4bbdfSmrg    sizeInBytes = format >> 3;
21805b261ecSmrg    totalSize = len * sizeInBytes;
21905b261ecSmrg    REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
22005b261ecSmrg
2214642e01fSmrg    err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
22205b261ecSmrg    if (err != Success)
22335c4bbdfSmrg        return err;
22435c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
22535c4bbdfSmrg        client->errorValue = stuff->property;
22635c4bbdfSmrg        return BadAtom;
22705b261ecSmrg    }
22835c4bbdfSmrg    if (!ValidAtom(stuff->type)) {
22935c4bbdfSmrg        client->errorValue = stuff->type;
23035c4bbdfSmrg        return BadAtom;
23105b261ecSmrg    }
23205b261ecSmrg
2334642e01fSmrg    err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
23435c4bbdfSmrg                                  (int) format, (int) mode, len, &stuff[1],
23535c4bbdfSmrg                                  TRUE);
23605b261ecSmrg    if (err != Success)
23735c4bbdfSmrg        return err;
23805b261ecSmrg    else
23935c4bbdfSmrg        return Success;
24005b261ecSmrg}
24105b261ecSmrg
2426747b715Smrgint
2434642e01fSmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
24435c4bbdfSmrg                        Atom type, int format, int mode, unsigned long len,
24535c4bbdfSmrg                        void *value, Bool sendevent)
24605b261ecSmrg{
24705b261ecSmrg    PropertyPtr pProp;
2486747b715Smrg    PropertyRec savedProp;
2494642e01fSmrg    int sizeInBytes, totalSize, rc;
2506747b715Smrg    unsigned char *data;
2514642e01fSmrg    Mask access_mode;
25205b261ecSmrg
25335c4bbdfSmrg    sizeInBytes = format >> 3;
25405b261ecSmrg    totalSize = len * sizeInBytes;
2554642e01fSmrg    access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
25605b261ecSmrg
25705b261ecSmrg    /* first see if property already exists */
2584642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
25905b261ecSmrg
26035c4bbdfSmrg    if (rc == BadMatch) {       /* just add to list */
26135c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin))
26235c4bbdfSmrg            return BadAlloc;
26335c4bbdfSmrg        pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
26435c4bbdfSmrg        if (!pProp)
26535c4bbdfSmrg            return BadAlloc;
2666747b715Smrg        data = malloc(totalSize);
26735c4bbdfSmrg        if (!data && len) {
26835c4bbdfSmrg            dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
26935c4bbdfSmrg            return BadAlloc;
27035c4bbdfSmrg        }
2716747b715Smrg        memcpy(data, value, totalSize);
27205b261ecSmrg        pProp->propertyName = property;
27305b261ecSmrg        pProp->type = type;
27405b261ecSmrg        pProp->format = format;
27505b261ecSmrg        pProp->data = data;
27635c4bbdfSmrg        pProp->size = len;
27735c4bbdfSmrg        rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
27835c4bbdfSmrg                                    DixCreateAccess | DixWriteAccess);
27935c4bbdfSmrg        if (rc != Success) {
28035c4bbdfSmrg            free(data);
28135c4bbdfSmrg            dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
28235c4bbdfSmrg            pClient->errorValue = property;
28335c4bbdfSmrg            return rc;
28435c4bbdfSmrg        }
28505b261ecSmrg        pProp->next = pWin->optional->userProps;
28605b261ecSmrg        pWin->optional->userProps = pProp;
28705b261ecSmrg    }
28835c4bbdfSmrg    else if (rc == Success) {
28935c4bbdfSmrg        /* To append or prepend to a property the request format and type
29035c4bbdfSmrg           must match those of the already defined property.  The
29135c4bbdfSmrg           existing format and type are irrelevant when using the mode
29235c4bbdfSmrg           "PropModeReplace" since they will be written over. */
29305b261ecSmrg
29405b261ecSmrg        if ((format != pProp->format) && (mode != PropModeReplace))
29535c4bbdfSmrg            return BadMatch;
29605b261ecSmrg        if ((pProp->type != type) && (mode != PropModeReplace))
2976747b715Smrg            return BadMatch;
2986747b715Smrg
29935c4bbdfSmrg        /* save the old values for later */
30035c4bbdfSmrg        savedProp = *pProp;
30135c4bbdfSmrg
30235c4bbdfSmrg        if (mode == PropModeReplace) {
30335c4bbdfSmrg            data = malloc(totalSize);
30435c4bbdfSmrg            if (!data && len)
30535c4bbdfSmrg                return BadAlloc;
30635c4bbdfSmrg            memcpy(data, value, totalSize);
30735c4bbdfSmrg            pProp->data = data;
30835c4bbdfSmrg            pProp->size = len;
30935c4bbdfSmrg            pProp->type = type;
31035c4bbdfSmrg            pProp->format = format;
31135c4bbdfSmrg        }
31235c4bbdfSmrg        else if (len == 0) {
31335c4bbdfSmrg            /* do nothing */
31435c4bbdfSmrg        }
31535c4bbdfSmrg        else if (mode == PropModeAppend) {
31635c4bbdfSmrg            data = xallocarray(pProp->size + len, sizeInBytes);
31735c4bbdfSmrg            if (!data)
31835c4bbdfSmrg                return BadAlloc;
31935c4bbdfSmrg            memcpy(data, pProp->data, pProp->size * sizeInBytes);
32035c4bbdfSmrg            memcpy(data + pProp->size * sizeInBytes, value, totalSize);
32105b261ecSmrg            pProp->data = data;
32205b261ecSmrg            pProp->size += len;
32335c4bbdfSmrg        }
32435c4bbdfSmrg        else if (mode == PropModePrepend) {
32535c4bbdfSmrg            data = xallocarray(len + pProp->size, sizeInBytes);
32635c4bbdfSmrg            if (!data)
32735c4bbdfSmrg                return BadAlloc;
3286747b715Smrg            memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
3296747b715Smrg            memcpy(data, value, totalSize);
33005b261ecSmrg            pProp->data = data;
33105b261ecSmrg            pProp->size += len;
33235c4bbdfSmrg        }
33335c4bbdfSmrg
33435c4bbdfSmrg        /* Allow security modules to check the new content */
33535c4bbdfSmrg        access_mode |= DixPostAccess;
33635c4bbdfSmrg        rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode);
33735c4bbdfSmrg        if (rc == Success) {
33835c4bbdfSmrg            if (savedProp.data != pProp->data)
33935c4bbdfSmrg                free(savedProp.data);
34035c4bbdfSmrg        }
34135c4bbdfSmrg        else {
34235c4bbdfSmrg            if (savedProp.data != pProp->data)
34335c4bbdfSmrg                free(pProp->data);
34435c4bbdfSmrg            *pProp = savedProp;
34535c4bbdfSmrg            return rc;
34635c4bbdfSmrg        }
34705b261ecSmrg    }
3484642e01fSmrg    else
34935c4bbdfSmrg        return rc;
35005b261ecSmrg
35105b261ecSmrg    if (sendevent)
35235c4bbdfSmrg        deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
35305b261ecSmrg
3546747b715Smrg    return Success;
35505b261ecSmrg}
35605b261ecSmrg
3576747b715Smrgint
35835c4bbdfSmrgChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format,
35935c4bbdfSmrg                     int mode, unsigned long len, void *value, Bool sendevent)
3604642e01fSmrg{
3614642e01fSmrg    return dixChangeWindowProperty(serverClient, pWin, property, type, format,
36235c4bbdfSmrg                                   mode, len, value, sendevent);
3634642e01fSmrg}
3644642e01fSmrg
36505b261ecSmrgint
3664642e01fSmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
36705b261ecSmrg{
36805b261ecSmrg    PropertyPtr pProp, prevProp;
3694642e01fSmrg    int rc;
37005b261ecSmrg
3714642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
3724642e01fSmrg    if (rc == BadMatch)
37335c4bbdfSmrg        return Success;         /* Succeed if property does not exist */
3744642e01fSmrg
3754642e01fSmrg    if (rc == Success) {
37635c4bbdfSmrg        if (pWin->optional->userProps == pProp) {
37735c4bbdfSmrg            /* Takes care of head */
37805b261ecSmrg            if (!(pWin->optional->userProps = pProp->next))
37935c4bbdfSmrg                CheckWindowOptionalNeed(pWin);
38035c4bbdfSmrg        }
38135c4bbdfSmrg        else {
38235c4bbdfSmrg            /* Need to traverse to find the previous element */
38335c4bbdfSmrg            prevProp = pWin->optional->userProps;
38435c4bbdfSmrg            while (prevProp->next != pProp)
38535c4bbdfSmrg                prevProp = prevProp->next;
38635c4bbdfSmrg            prevProp->next = pProp->next;
38735c4bbdfSmrg        }
38835c4bbdfSmrg
38935c4bbdfSmrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
39035c4bbdfSmrg        free(pProp->data);
39135c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
39205b261ecSmrg    }
3934642e01fSmrg    return rc;
39405b261ecSmrg}
39505b261ecSmrg
39605b261ecSmrgvoid
39705b261ecSmrgDeleteAllWindowProperties(WindowPtr pWin)
39805b261ecSmrg{
39905b261ecSmrg    PropertyPtr pProp, pNextProp;
40005b261ecSmrg
40135c4bbdfSmrg    pProp = wUserProps(pWin);
40235c4bbdfSmrg    while (pProp) {
40335c4bbdfSmrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
40435c4bbdfSmrg        pNextProp = pProp->next;
4056747b715Smrg        free(pProp->data);
40635c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
40735c4bbdfSmrg        pProp = pNextProp;
40805b261ecSmrg    }
4099ace9065Smrg
4109ace9065Smrg    if (pWin->optional)
4119ace9065Smrg        pWin->optional->userProps = NULL;
41205b261ecSmrg}
41305b261ecSmrg
41405b261ecSmrgstatic int
41535c4bbdfSmrgNullPropertyReply(ClientPtr client, ATOM propertyType, int format)
41605b261ecSmrg{
41735c4bbdfSmrg    xGetPropertyReply reply = {
41835c4bbdfSmrg        .type = X_Reply,
41935c4bbdfSmrg        .format = format,
42035c4bbdfSmrg        .sequenceNumber = client->sequence,
42135c4bbdfSmrg        .length = 0,
42235c4bbdfSmrg        .propertyType = propertyType,
42335c4bbdfSmrg        .bytesAfter = 0,
42435c4bbdfSmrg        .nItems = 0
42535c4bbdfSmrg    };
42635c4bbdfSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
4276747b715Smrg    return Success;
42805b261ecSmrg}
42905b261ecSmrg
43005b261ecSmrg/*****************
43105b261ecSmrg * GetProperty
43205b261ecSmrg *    If type Any is specified, returns the property from the specified
43305b261ecSmrg *    window regardless of its type.  If a type is specified, returns the
43405b261ecSmrg *    property only if its type equals the specified type.
43505b261ecSmrg *    If delete is True and a property is returned, the property is also
43605b261ecSmrg *    deleted from the window and a PropertyNotify event is generated on the
43705b261ecSmrg *    window.
43805b261ecSmrg *****************/
43905b261ecSmrg
44005b261ecSmrgint
44105b261ecSmrgProcGetProperty(ClientPtr client)
44205b261ecSmrg{
44305b261ecSmrg    PropertyPtr pProp, prevProp;
4444642e01fSmrg    unsigned long n, len, ind;
4454642e01fSmrg    int rc;
44605b261ecSmrg    WindowPtr pWin;
44705b261ecSmrg    xGetPropertyReply reply;
4484642e01fSmrg    Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
44935c4bbdfSmrg
45005b261ecSmrg    REQUEST(xGetPropertyReq);
45105b261ecSmrg
45205b261ecSmrg    REQUEST_SIZE_MATCH(xGetPropertyReq);
4534642e01fSmrg    if (stuff->delete) {
45435c4bbdfSmrg        UpdateCurrentTime();
45535c4bbdfSmrg        win_mode |= DixSetPropAccess;
45635c4bbdfSmrg        prop_mode |= DixDestroyAccess;
4574642e01fSmrg    }
4584642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
45905b261ecSmrg    if (rc != Success)
46035c4bbdfSmrg        return rc;
46105b261ecSmrg
46235c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
46335c4bbdfSmrg        client->errorValue = stuff->property;
46435c4bbdfSmrg        return BadAtom;
46505b261ecSmrg    }
46635c4bbdfSmrg    if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) {
46735c4bbdfSmrg        client->errorValue = stuff->delete;
46835c4bbdfSmrg        return BadValue;
46905b261ecSmrg    }
47035c4bbdfSmrg    if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) {
47135c4bbdfSmrg        client->errorValue = stuff->type;
47235c4bbdfSmrg        return BadAtom;
47305b261ecSmrg    }
47405b261ecSmrg
4754642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
4764642e01fSmrg    if (rc == BadMatch)
47735c4bbdfSmrg        return NullPropertyReply(client, None, 0);
4784642e01fSmrg    else if (rc != Success)
47935c4bbdfSmrg        return rc;
48005b261ecSmrg
48105b261ecSmrg    /* If the request type and actual type don't match. Return the
48235c4bbdfSmrg       property information, but not the data. */
48335c4bbdfSmrg
48435c4bbdfSmrg    if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType))
48535c4bbdfSmrg        ) {
48635c4bbdfSmrg        reply = (xGetPropertyReply) {
48735c4bbdfSmrg            .type = X_Reply,
48835c4bbdfSmrg            .sequenceNumber = client->sequence,
48935c4bbdfSmrg            .bytesAfter = pProp->size,
49035c4bbdfSmrg            .format = pProp->format,
49135c4bbdfSmrg            .length = 0,
49235c4bbdfSmrg            .nItems = 0,
49335c4bbdfSmrg            .propertyType = pProp->type
49435c4bbdfSmrg        };
49535c4bbdfSmrg        WriteReplyToClient(client, sizeof(xGenericReply), &reply);
49635c4bbdfSmrg        return Success;
49705b261ecSmrg    }
49805b261ecSmrg
49905b261ecSmrg/*
50005b261ecSmrg *  Return type, format, value to client
50105b261ecSmrg */
50235c4bbdfSmrg    n = (pProp->format / 8) * pProp->size;      /* size (bytes) of prop */
50335c4bbdfSmrg    ind = stuff->longOffset << 2;
50405b261ecSmrg
50535c4bbdfSmrg    /* If longOffset is invalid such that it causes "len" to
50635c4bbdfSmrg       be negative, it's a value error. */
50705b261ecSmrg
50835c4bbdfSmrg    if (n < ind) {
50935c4bbdfSmrg        client->errorValue = stuff->longOffset;
51035c4bbdfSmrg        return BadValue;
51105b261ecSmrg    }
51205b261ecSmrg
51305b261ecSmrg    len = min(n - ind, 4 * stuff->longLength);
51405b261ecSmrg
51535c4bbdfSmrg    reply = (xGetPropertyReply) {
51635c4bbdfSmrg        .type = X_Reply,
51735c4bbdfSmrg        .sequenceNumber = client->sequence,
51835c4bbdfSmrg        .bytesAfter = n - (ind + len),
51935c4bbdfSmrg        .format = pProp->format,
52035c4bbdfSmrg        .length = bytes_to_int32(len),
52135c4bbdfSmrg        .nItems = len / (pProp->format / 8),
52235c4bbdfSmrg        .propertyType = pProp->type
52335c4bbdfSmrg    };
52405b261ecSmrg
52505b261ecSmrg    if (stuff->delete && (reply.bytesAfter == 0))
52635c4bbdfSmrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
52705b261ecSmrg
52805b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
52935c4bbdfSmrg    if (len) {
53035c4bbdfSmrg        switch (reply.format) {
53135c4bbdfSmrg        case 32:
53235c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
53335c4bbdfSmrg            break;
53435c4bbdfSmrg        case 16:
53535c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
53635c4bbdfSmrg            break;
53735c4bbdfSmrg        default:
53835c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
53935c4bbdfSmrg            break;
54035c4bbdfSmrg        }
54135c4bbdfSmrg        WriteSwappedDataToClient(client, len, (char *) pProp->data + ind);
54205b261ecSmrg    }
54305b261ecSmrg
5444642e01fSmrg    if (stuff->delete && (reply.bytesAfter == 0)) {
54535c4bbdfSmrg        /* Delete the Property */
54635c4bbdfSmrg        if (pWin->optional->userProps == pProp) {
54735c4bbdfSmrg            /* Takes care of head */
5484642e01fSmrg            if (!(pWin->optional->userProps = pProp->next))
54935c4bbdfSmrg                CheckWindowOptionalNeed(pWin);
55035c4bbdfSmrg        }
55135c4bbdfSmrg        else {
55235c4bbdfSmrg            /* Need to traverse to find the previous element */
55335c4bbdfSmrg            prevProp = pWin->optional->userProps;
55435c4bbdfSmrg            while (prevProp->next != pProp)
55535c4bbdfSmrg                prevProp = prevProp->next;
55635c4bbdfSmrg            prevProp->next = pProp->next;
55735c4bbdfSmrg        }
55835c4bbdfSmrg
55935c4bbdfSmrg        free(pProp->data);
56035c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
56105b261ecSmrg    }
5626747b715Smrg    return Success;
56305b261ecSmrg}
56405b261ecSmrg
56505b261ecSmrgint
56605b261ecSmrgProcListProperties(ClientPtr client)
56705b261ecSmrg{
56805b261ecSmrg    Atom *pAtoms = NULL, *temppAtoms;
56905b261ecSmrg    xListPropertiesReply xlpr;
57035c4bbdfSmrg    int rc, numProps = 0;
57105b261ecSmrg    WindowPtr pWin;
5724642e01fSmrg    PropertyPtr pProp, realProp;
57335c4bbdfSmrg
57405b261ecSmrg    REQUEST(xResourceReq);
57505b261ecSmrg
57605b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
5774642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
57805b261ecSmrg    if (rc != Success)
57905b261ecSmrg        return rc;
58005b261ecSmrg
5814642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
58235c4bbdfSmrg        numProps++;
5834642e01fSmrg
58435c4bbdfSmrg    if (numProps && !(pAtoms = xallocarray(numProps, sizeof(Atom))))
58535c4bbdfSmrg        return BadAlloc;
5864642e01fSmrg
5874642e01fSmrg    numProps = 0;
5884642e01fSmrg    temppAtoms = pAtoms;
5894642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
59035c4bbdfSmrg        realProp = pProp;
59135c4bbdfSmrg        rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
59235c4bbdfSmrg        if (rc == Success && realProp == pProp) {
59335c4bbdfSmrg            *temppAtoms++ = pProp->propertyName;
59435c4bbdfSmrg            numProps++;
59535c4bbdfSmrg        }
59605b261ecSmrg    }
59705b261ecSmrg
59835c4bbdfSmrg    xlpr = (xListPropertiesReply) {
59935c4bbdfSmrg        .type = X_Reply,
60035c4bbdfSmrg        .sequenceNumber = client->sequence,
60135c4bbdfSmrg        .length = bytes_to_int32(numProps * sizeof(Atom)),
60235c4bbdfSmrg        .nProperties = numProps
60335c4bbdfSmrg    };
60405b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
60535c4bbdfSmrg    if (numProps) {
60635c4bbdfSmrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
60705b261ecSmrg        WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
60805b261ecSmrg    }
6096747b715Smrg    free(pAtoms);
6106747b715Smrg    return Success;
61105b261ecSmrg}
61205b261ecSmrg
61335c4bbdfSmrgint
61405b261ecSmrgProcDeleteProperty(ClientPtr client)
61505b261ecSmrg{
61605b261ecSmrg    WindowPtr pWin;
61735c4bbdfSmrg
61805b261ecSmrg    REQUEST(xDeletePropertyReq);
61905b261ecSmrg    int result;
62035c4bbdfSmrg
62105b261ecSmrg    REQUEST_SIZE_MATCH(xDeletePropertyReq);
62205b261ecSmrg    UpdateCurrentTime();
6234642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
62405b261ecSmrg    if (result != Success)
62505b261ecSmrg        return result;
62635c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
62735c4bbdfSmrg        client->errorValue = stuff->property;
62835c4bbdfSmrg        return BadAtom;
62905b261ecSmrg    }
63005b261ecSmrg
6316747b715Smrg    return DeleteProperty(client, pWin, stuff->property);
63205b261ecSmrg}
633