property.c revision 1b5d61b8
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
1081b5d61b8SmrgCallbackListPtr PropertyStateCallback;
1091b5d61b8Smrg
11005b261ecSmrgstatic void
1111b5d61b8SmrgdeliverPropertyNotifyEvent(WindowPtr pWin, int state, PropertyPtr pProp)
11205b261ecSmrg{
1131b5d61b8Smrg    xEvent event;
1141b5d61b8Smrg    PropertyStateRec rec = {
1151b5d61b8Smrg        .win = pWin,
1161b5d61b8Smrg        .prop = pProp,
1171b5d61b8Smrg        .state = state
1181b5d61b8Smrg    };
1191b5d61b8Smrg    UpdateCurrentTimeIf();
1201b5d61b8Smrg    event = (xEvent) {
12135c4bbdfSmrg        .u.property.window = pWin->drawable.id,
12235c4bbdfSmrg        .u.property.state = state,
1231b5d61b8Smrg        .u.property.atom = pProp->propertyName,
1241b5d61b8Smrg        .u.property.time = currentTime.milliseconds,
12535c4bbdfSmrg    };
12605b261ecSmrg    event.u.u.type = PropertyNotify;
1271b5d61b8Smrg
1281b5d61b8Smrg    CallCallbacks(&PropertyStateCallback, &rec);
12935c4bbdfSmrg    DeliverEvents(pWin, &event, 1, (WindowPtr) NULL);
13005b261ecSmrg}
13105b261ecSmrg
13205b261ecSmrgint
13305b261ecSmrgProcRotateProperties(ClientPtr client)
13405b261ecSmrg{
13535c4bbdfSmrg    int i, j, delta, rc;
13635c4bbdfSmrg
13705b261ecSmrg    REQUEST(xRotatePropertiesReq);
13805b261ecSmrg    WindowPtr pWin;
13935c4bbdfSmrg    Atom *atoms;
14035c4bbdfSmrg    PropertyPtr *props;         /* array of pointer */
1414642e01fSmrg    PropertyPtr pProp, saved;
14205b261ecSmrg
14305b261ecSmrg    REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
14405b261ecSmrg    UpdateCurrentTime();
1454642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
1464642e01fSmrg    if (rc != Success || stuff->nAtoms <= 0)
14705b261ecSmrg        return rc;
1484642e01fSmrg
14935c4bbdfSmrg    atoms = (Atom *) &stuff[1];
15035c4bbdfSmrg    props = xallocarray(stuff->nAtoms, sizeof(PropertyPtr));
15135c4bbdfSmrg    saved = xallocarray(stuff->nAtoms, sizeof(PropertyRec));
1524642e01fSmrg    if (!props || !saved) {
15335c4bbdfSmrg        rc = BadAlloc;
15435c4bbdfSmrg        goto out;
1554642e01fSmrg    }
1564642e01fSmrg
15735c4bbdfSmrg    for (i = 0; i < stuff->nAtoms; i++) {
1584642e01fSmrg        if (!ValidAtom(atoms[i])) {
15935c4bbdfSmrg            rc = BadAtom;
16035c4bbdfSmrg            client->errorValue = atoms[i];
16135c4bbdfSmrg            goto out;
16205b261ecSmrg        }
16305b261ecSmrg        for (j = i + 1; j < stuff->nAtoms; j++)
16435c4bbdfSmrg            if (atoms[j] == atoms[i]) {
16535c4bbdfSmrg                rc = BadMatch;
16635c4bbdfSmrg                goto out;
16705b261ecSmrg            }
1684642e01fSmrg
16935c4bbdfSmrg        rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
17035c4bbdfSmrg                               DixReadAccess | DixWriteAccess);
17135c4bbdfSmrg        if (rc != Success)
17235c4bbdfSmrg            goto out;
1734642e01fSmrg
17405b261ecSmrg        props[i] = pProp;
17535c4bbdfSmrg        saved[i] = *pProp;
17605b261ecSmrg    }
17705b261ecSmrg    delta = stuff->nPositions;
17805b261ecSmrg
17905b261ecSmrg    /* If the rotation is a complete 360 degrees, then moving the properties
18035c4bbdfSmrg       around and generating PropertyNotify events should be skipped. */
18105b261ecSmrg
18235c4bbdfSmrg    if (abs(delta) % stuff->nAtoms) {
18335c4bbdfSmrg        while (delta < 0)       /* faster if abs value is small */
18405b261ecSmrg            delta += stuff->nAtoms;
18535c4bbdfSmrg        for (i = 0; i < stuff->nAtoms; i++) {
18635c4bbdfSmrg            j = (i + delta) % stuff->nAtoms;
1871b5d61b8Smrg            deliverPropertyNotifyEvent(pWin, PropertyNewValue, props[i]);
18835c4bbdfSmrg
18935c4bbdfSmrg            /* Preserve name and devPrivates */
19035c4bbdfSmrg            props[j]->type = saved[i].type;
19135c4bbdfSmrg            props[j]->format = saved[i].format;
19235c4bbdfSmrg            props[j]->size = saved[i].size;
19335c4bbdfSmrg            props[j]->data = saved[i].data;
19435c4bbdfSmrg        }
19505b261ecSmrg    }
19635c4bbdfSmrg out:
1976747b715Smrg    free(saved);
1986747b715Smrg    free(props);
1994642e01fSmrg    return rc;
20005b261ecSmrg}
20105b261ecSmrg
20235c4bbdfSmrgint
20305b261ecSmrgProcChangeProperty(ClientPtr client)
20435c4bbdfSmrg{
20505b261ecSmrg    WindowPtr pWin;
20605b261ecSmrg    char format, mode;
20705b261ecSmrg    unsigned long len;
20805b261ecSmrg    int sizeInBytes, totalSize, err;
20935c4bbdfSmrg
21005b261ecSmrg    REQUEST(xChangePropertyReq);
21105b261ecSmrg
21205b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
21305b261ecSmrg    UpdateCurrentTime();
21405b261ecSmrg    format = stuff->format;
21505b261ecSmrg    mode = stuff->mode;
21605b261ecSmrg    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
21735c4bbdfSmrg        (mode != PropModePrepend)) {
21835c4bbdfSmrg        client->errorValue = mode;
21935c4bbdfSmrg        return BadValue;
22005b261ecSmrg    }
22135c4bbdfSmrg    if ((format != 8) && (format != 16) && (format != 32)) {
22235c4bbdfSmrg        client->errorValue = format;
22305b261ecSmrg        return BadValue;
22405b261ecSmrg    }
22505b261ecSmrg    len = stuff->nUnits;
2266747b715Smrg    if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq)))
22735c4bbdfSmrg        return BadLength;
22835c4bbdfSmrg    sizeInBytes = format >> 3;
22905b261ecSmrg    totalSize = len * sizeInBytes;
23005b261ecSmrg    REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
23105b261ecSmrg
2324642e01fSmrg    err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
23305b261ecSmrg    if (err != Success)
23435c4bbdfSmrg        return err;
23535c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
23635c4bbdfSmrg        client->errorValue = stuff->property;
23735c4bbdfSmrg        return BadAtom;
23805b261ecSmrg    }
23935c4bbdfSmrg    if (!ValidAtom(stuff->type)) {
24035c4bbdfSmrg        client->errorValue = stuff->type;
24135c4bbdfSmrg        return BadAtom;
24205b261ecSmrg    }
24305b261ecSmrg
2444642e01fSmrg    err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
24535c4bbdfSmrg                                  (int) format, (int) mode, len, &stuff[1],
24635c4bbdfSmrg                                  TRUE);
24705b261ecSmrg    if (err != Success)
24835c4bbdfSmrg        return err;
24905b261ecSmrg    else
25035c4bbdfSmrg        return Success;
25105b261ecSmrg}
25205b261ecSmrg
2536747b715Smrgint
2544642e01fSmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
25535c4bbdfSmrg                        Atom type, int format, int mode, unsigned long len,
25635c4bbdfSmrg                        void *value, Bool sendevent)
25705b261ecSmrg{
25805b261ecSmrg    PropertyPtr pProp;
2596747b715Smrg    PropertyRec savedProp;
2604642e01fSmrg    int sizeInBytes, totalSize, rc;
2616747b715Smrg    unsigned char *data;
2624642e01fSmrg    Mask access_mode;
26305b261ecSmrg
26435c4bbdfSmrg    sizeInBytes = format >> 3;
26505b261ecSmrg    totalSize = len * sizeInBytes;
2664642e01fSmrg    access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
26705b261ecSmrg
26805b261ecSmrg    /* first see if property already exists */
2694642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
27005b261ecSmrg
27135c4bbdfSmrg    if (rc == BadMatch) {       /* just add to list */
27235c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin))
27335c4bbdfSmrg            return BadAlloc;
27435c4bbdfSmrg        pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
27535c4bbdfSmrg        if (!pProp)
27635c4bbdfSmrg            return BadAlloc;
2776747b715Smrg        data = malloc(totalSize);
27835c4bbdfSmrg        if (!data && len) {
27935c4bbdfSmrg            dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
28035c4bbdfSmrg            return BadAlloc;
28135c4bbdfSmrg        }
2826747b715Smrg        memcpy(data, value, totalSize);
28305b261ecSmrg        pProp->propertyName = property;
28405b261ecSmrg        pProp->type = type;
28505b261ecSmrg        pProp->format = format;
28605b261ecSmrg        pProp->data = data;
28735c4bbdfSmrg        pProp->size = len;
28835c4bbdfSmrg        rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
28935c4bbdfSmrg                                    DixCreateAccess | DixWriteAccess);
29035c4bbdfSmrg        if (rc != Success) {
29135c4bbdfSmrg            free(data);
29235c4bbdfSmrg            dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
29335c4bbdfSmrg            pClient->errorValue = property;
29435c4bbdfSmrg            return rc;
29535c4bbdfSmrg        }
29605b261ecSmrg        pProp->next = pWin->optional->userProps;
29705b261ecSmrg        pWin->optional->userProps = pProp;
29805b261ecSmrg    }
29935c4bbdfSmrg    else if (rc == Success) {
30035c4bbdfSmrg        /* To append or prepend to a property the request format and type
30135c4bbdfSmrg           must match those of the already defined property.  The
30235c4bbdfSmrg           existing format and type are irrelevant when using the mode
30335c4bbdfSmrg           "PropModeReplace" since they will be written over. */
30405b261ecSmrg
30505b261ecSmrg        if ((format != pProp->format) && (mode != PropModeReplace))
30635c4bbdfSmrg            return BadMatch;
30705b261ecSmrg        if ((pProp->type != type) && (mode != PropModeReplace))
3086747b715Smrg            return BadMatch;
3096747b715Smrg
31035c4bbdfSmrg        /* save the old values for later */
31135c4bbdfSmrg        savedProp = *pProp;
31235c4bbdfSmrg
31335c4bbdfSmrg        if (mode == PropModeReplace) {
31435c4bbdfSmrg            data = malloc(totalSize);
31535c4bbdfSmrg            if (!data && len)
31635c4bbdfSmrg                return BadAlloc;
31735c4bbdfSmrg            memcpy(data, value, totalSize);
31835c4bbdfSmrg            pProp->data = data;
31935c4bbdfSmrg            pProp->size = len;
32035c4bbdfSmrg            pProp->type = type;
32135c4bbdfSmrg            pProp->format = format;
32235c4bbdfSmrg        }
32335c4bbdfSmrg        else if (len == 0) {
32435c4bbdfSmrg            /* do nothing */
32535c4bbdfSmrg        }
32635c4bbdfSmrg        else if (mode == PropModeAppend) {
32735c4bbdfSmrg            data = xallocarray(pProp->size + len, sizeInBytes);
32835c4bbdfSmrg            if (!data)
32935c4bbdfSmrg                return BadAlloc;
33035c4bbdfSmrg            memcpy(data, pProp->data, pProp->size * sizeInBytes);
33135c4bbdfSmrg            memcpy(data + pProp->size * sizeInBytes, value, totalSize);
33205b261ecSmrg            pProp->data = data;
33305b261ecSmrg            pProp->size += len;
33435c4bbdfSmrg        }
33535c4bbdfSmrg        else if (mode == PropModePrepend) {
33635c4bbdfSmrg            data = xallocarray(len + pProp->size, sizeInBytes);
33735c4bbdfSmrg            if (!data)
33835c4bbdfSmrg                return BadAlloc;
3396747b715Smrg            memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
3406747b715Smrg            memcpy(data, value, totalSize);
34105b261ecSmrg            pProp->data = data;
34205b261ecSmrg            pProp->size += len;
34335c4bbdfSmrg        }
34435c4bbdfSmrg
34535c4bbdfSmrg        /* Allow security modules to check the new content */
34635c4bbdfSmrg        access_mode |= DixPostAccess;
34735c4bbdfSmrg        rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode);
34835c4bbdfSmrg        if (rc == Success) {
34935c4bbdfSmrg            if (savedProp.data != pProp->data)
35035c4bbdfSmrg                free(savedProp.data);
35135c4bbdfSmrg        }
35235c4bbdfSmrg        else {
35335c4bbdfSmrg            if (savedProp.data != pProp->data)
35435c4bbdfSmrg                free(pProp->data);
35535c4bbdfSmrg            *pProp = savedProp;
35635c4bbdfSmrg            return rc;
35735c4bbdfSmrg        }
35805b261ecSmrg    }
3594642e01fSmrg    else
36035c4bbdfSmrg        return rc;
36105b261ecSmrg
36205b261ecSmrg    if (sendevent)
3631b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp);
36405b261ecSmrg
3656747b715Smrg    return Success;
36605b261ecSmrg}
36705b261ecSmrg
36805b261ecSmrgint
3694642e01fSmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
37005b261ecSmrg{
37105b261ecSmrg    PropertyPtr pProp, prevProp;
3724642e01fSmrg    int rc;
37305b261ecSmrg
3744642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
3754642e01fSmrg    if (rc == BadMatch)
37635c4bbdfSmrg        return Success;         /* Succeed if property does not exist */
3774642e01fSmrg
3784642e01fSmrg    if (rc == Success) {
37935c4bbdfSmrg        if (pWin->optional->userProps == pProp) {
38035c4bbdfSmrg            /* Takes care of head */
38105b261ecSmrg            if (!(pWin->optional->userProps = pProp->next))
38235c4bbdfSmrg                CheckWindowOptionalNeed(pWin);
38335c4bbdfSmrg        }
38435c4bbdfSmrg        else {
38535c4bbdfSmrg            /* Need to traverse to find the previous element */
38635c4bbdfSmrg            prevProp = pWin->optional->userProps;
38735c4bbdfSmrg            while (prevProp->next != pProp)
38835c4bbdfSmrg                prevProp = prevProp->next;
38935c4bbdfSmrg            prevProp->next = pProp->next;
39035c4bbdfSmrg        }
39135c4bbdfSmrg
3921b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
39335c4bbdfSmrg        free(pProp->data);
39435c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
39505b261ecSmrg    }
3964642e01fSmrg    return rc;
39705b261ecSmrg}
39805b261ecSmrg
39905b261ecSmrgvoid
40005b261ecSmrgDeleteAllWindowProperties(WindowPtr pWin)
40105b261ecSmrg{
40205b261ecSmrg    PropertyPtr pProp, pNextProp;
40305b261ecSmrg
40435c4bbdfSmrg    pProp = wUserProps(pWin);
40535c4bbdfSmrg    while (pProp) {
4061b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
40735c4bbdfSmrg        pNextProp = pProp->next;
4086747b715Smrg        free(pProp->data);
40935c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
41035c4bbdfSmrg        pProp = pNextProp;
41105b261ecSmrg    }
4129ace9065Smrg
4139ace9065Smrg    if (pWin->optional)
4149ace9065Smrg        pWin->optional->userProps = NULL;
41505b261ecSmrg}
41605b261ecSmrg
41705b261ecSmrgstatic int
41835c4bbdfSmrgNullPropertyReply(ClientPtr client, ATOM propertyType, int format)
41905b261ecSmrg{
42035c4bbdfSmrg    xGetPropertyReply reply = {
42135c4bbdfSmrg        .type = X_Reply,
42235c4bbdfSmrg        .format = format,
42335c4bbdfSmrg        .sequenceNumber = client->sequence,
42435c4bbdfSmrg        .length = 0,
42535c4bbdfSmrg        .propertyType = propertyType,
42635c4bbdfSmrg        .bytesAfter = 0,
42735c4bbdfSmrg        .nItems = 0
42835c4bbdfSmrg    };
42935c4bbdfSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
4306747b715Smrg    return Success;
43105b261ecSmrg}
43205b261ecSmrg
43305b261ecSmrg/*****************
43405b261ecSmrg * GetProperty
43505b261ecSmrg *    If type Any is specified, returns the property from the specified
43605b261ecSmrg *    window regardless of its type.  If a type is specified, returns the
43705b261ecSmrg *    property only if its type equals the specified type.
43805b261ecSmrg *    If delete is True and a property is returned, the property is also
43905b261ecSmrg *    deleted from the window and a PropertyNotify event is generated on the
44005b261ecSmrg *    window.
44105b261ecSmrg *****************/
44205b261ecSmrg
44305b261ecSmrgint
44405b261ecSmrgProcGetProperty(ClientPtr client)
44505b261ecSmrg{
44605b261ecSmrg    PropertyPtr pProp, prevProp;
4474642e01fSmrg    unsigned long n, len, ind;
4484642e01fSmrg    int rc;
44905b261ecSmrg    WindowPtr pWin;
45005b261ecSmrg    xGetPropertyReply reply;
4514642e01fSmrg    Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
45235c4bbdfSmrg
45305b261ecSmrg    REQUEST(xGetPropertyReq);
45405b261ecSmrg
45505b261ecSmrg    REQUEST_SIZE_MATCH(xGetPropertyReq);
4564642e01fSmrg    if (stuff->delete) {
45735c4bbdfSmrg        UpdateCurrentTime();
45835c4bbdfSmrg        win_mode |= DixSetPropAccess;
45935c4bbdfSmrg        prop_mode |= DixDestroyAccess;
4604642e01fSmrg    }
4614642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
46205b261ecSmrg    if (rc != Success)
46335c4bbdfSmrg        return rc;
46405b261ecSmrg
46535c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
46635c4bbdfSmrg        client->errorValue = stuff->property;
46735c4bbdfSmrg        return BadAtom;
46805b261ecSmrg    }
46935c4bbdfSmrg    if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) {
47035c4bbdfSmrg        client->errorValue = stuff->delete;
47135c4bbdfSmrg        return BadValue;
47205b261ecSmrg    }
47335c4bbdfSmrg    if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) {
47435c4bbdfSmrg        client->errorValue = stuff->type;
47535c4bbdfSmrg        return BadAtom;
47605b261ecSmrg    }
47705b261ecSmrg
4784642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
4794642e01fSmrg    if (rc == BadMatch)
48035c4bbdfSmrg        return NullPropertyReply(client, None, 0);
4814642e01fSmrg    else if (rc != Success)
48235c4bbdfSmrg        return rc;
48305b261ecSmrg
48405b261ecSmrg    /* If the request type and actual type don't match. Return the
48535c4bbdfSmrg       property information, but not the data. */
48635c4bbdfSmrg
48735c4bbdfSmrg    if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType))
48835c4bbdfSmrg        ) {
48935c4bbdfSmrg        reply = (xGetPropertyReply) {
49035c4bbdfSmrg            .type = X_Reply,
49135c4bbdfSmrg            .sequenceNumber = client->sequence,
49235c4bbdfSmrg            .bytesAfter = pProp->size,
49335c4bbdfSmrg            .format = pProp->format,
49435c4bbdfSmrg            .length = 0,
49535c4bbdfSmrg            .nItems = 0,
49635c4bbdfSmrg            .propertyType = pProp->type
49735c4bbdfSmrg        };
49835c4bbdfSmrg        WriteReplyToClient(client, sizeof(xGenericReply), &reply);
49935c4bbdfSmrg        return Success;
50005b261ecSmrg    }
50105b261ecSmrg
50205b261ecSmrg/*
50305b261ecSmrg *  Return type, format, value to client
50405b261ecSmrg */
50535c4bbdfSmrg    n = (pProp->format / 8) * pProp->size;      /* size (bytes) of prop */
50635c4bbdfSmrg    ind = stuff->longOffset << 2;
50705b261ecSmrg
50835c4bbdfSmrg    /* If longOffset is invalid such that it causes "len" to
50935c4bbdfSmrg       be negative, it's a value error. */
51005b261ecSmrg
51135c4bbdfSmrg    if (n < ind) {
51235c4bbdfSmrg        client->errorValue = stuff->longOffset;
51335c4bbdfSmrg        return BadValue;
51405b261ecSmrg    }
51505b261ecSmrg
51605b261ecSmrg    len = min(n - ind, 4 * stuff->longLength);
51705b261ecSmrg
51835c4bbdfSmrg    reply = (xGetPropertyReply) {
51935c4bbdfSmrg        .type = X_Reply,
52035c4bbdfSmrg        .sequenceNumber = client->sequence,
52135c4bbdfSmrg        .bytesAfter = n - (ind + len),
52235c4bbdfSmrg        .format = pProp->format,
52335c4bbdfSmrg        .length = bytes_to_int32(len),
52435c4bbdfSmrg        .nItems = len / (pProp->format / 8),
52535c4bbdfSmrg        .propertyType = pProp->type
52635c4bbdfSmrg    };
52705b261ecSmrg
52805b261ecSmrg    if (stuff->delete && (reply.bytesAfter == 0))
5291b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
53005b261ecSmrg
53105b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
53235c4bbdfSmrg    if (len) {
53335c4bbdfSmrg        switch (reply.format) {
53435c4bbdfSmrg        case 32:
53535c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
53635c4bbdfSmrg            break;
53735c4bbdfSmrg        case 16:
53835c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
53935c4bbdfSmrg            break;
54035c4bbdfSmrg        default:
54135c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
54235c4bbdfSmrg            break;
54335c4bbdfSmrg        }
54435c4bbdfSmrg        WriteSwappedDataToClient(client, len, (char *) pProp->data + ind);
54505b261ecSmrg    }
54605b261ecSmrg
5474642e01fSmrg    if (stuff->delete && (reply.bytesAfter == 0)) {
54835c4bbdfSmrg        /* Delete the Property */
54935c4bbdfSmrg        if (pWin->optional->userProps == pProp) {
55035c4bbdfSmrg            /* Takes care of head */
5514642e01fSmrg            if (!(pWin->optional->userProps = pProp->next))
55235c4bbdfSmrg                CheckWindowOptionalNeed(pWin);
55335c4bbdfSmrg        }
55435c4bbdfSmrg        else {
55535c4bbdfSmrg            /* Need to traverse to find the previous element */
55635c4bbdfSmrg            prevProp = pWin->optional->userProps;
55735c4bbdfSmrg            while (prevProp->next != pProp)
55835c4bbdfSmrg                prevProp = prevProp->next;
55935c4bbdfSmrg            prevProp->next = pProp->next;
56035c4bbdfSmrg        }
56135c4bbdfSmrg
56235c4bbdfSmrg        free(pProp->data);
56335c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
56405b261ecSmrg    }
5656747b715Smrg    return Success;
56605b261ecSmrg}
56705b261ecSmrg
56805b261ecSmrgint
56905b261ecSmrgProcListProperties(ClientPtr client)
57005b261ecSmrg{
57105b261ecSmrg    Atom *pAtoms = NULL, *temppAtoms;
57205b261ecSmrg    xListPropertiesReply xlpr;
57335c4bbdfSmrg    int rc, numProps = 0;
57405b261ecSmrg    WindowPtr pWin;
5754642e01fSmrg    PropertyPtr pProp, realProp;
57635c4bbdfSmrg
57705b261ecSmrg    REQUEST(xResourceReq);
57805b261ecSmrg
57905b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
5804642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
58105b261ecSmrg    if (rc != Success)
58205b261ecSmrg        return rc;
58305b261ecSmrg
5844642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
58535c4bbdfSmrg        numProps++;
5864642e01fSmrg
58735c4bbdfSmrg    if (numProps && !(pAtoms = xallocarray(numProps, sizeof(Atom))))
58835c4bbdfSmrg        return BadAlloc;
5894642e01fSmrg
5904642e01fSmrg    numProps = 0;
5914642e01fSmrg    temppAtoms = pAtoms;
5924642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
59335c4bbdfSmrg        realProp = pProp;
59435c4bbdfSmrg        rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
59535c4bbdfSmrg        if (rc == Success && realProp == pProp) {
59635c4bbdfSmrg            *temppAtoms++ = pProp->propertyName;
59735c4bbdfSmrg            numProps++;
59835c4bbdfSmrg        }
59905b261ecSmrg    }
60005b261ecSmrg
60135c4bbdfSmrg    xlpr = (xListPropertiesReply) {
60235c4bbdfSmrg        .type = X_Reply,
60335c4bbdfSmrg        .sequenceNumber = client->sequence,
60435c4bbdfSmrg        .length = bytes_to_int32(numProps * sizeof(Atom)),
60535c4bbdfSmrg        .nProperties = numProps
60635c4bbdfSmrg    };
60705b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
60835c4bbdfSmrg    if (numProps) {
60935c4bbdfSmrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
61005b261ecSmrg        WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
61105b261ecSmrg    }
6126747b715Smrg    free(pAtoms);
6136747b715Smrg    return Success;
61405b261ecSmrg}
61505b261ecSmrg
61635c4bbdfSmrgint
61705b261ecSmrgProcDeleteProperty(ClientPtr client)
61805b261ecSmrg{
61905b261ecSmrg    WindowPtr pWin;
62035c4bbdfSmrg
62105b261ecSmrg    REQUEST(xDeletePropertyReq);
62205b261ecSmrg    int result;
62335c4bbdfSmrg
62405b261ecSmrg    REQUEST_SIZE_MATCH(xDeletePropertyReq);
62505b261ecSmrg    UpdateCurrentTime();
6264642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
62705b261ecSmrg    if (result != Success)
62805b261ecSmrg        return result;
62935c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
63035c4bbdfSmrg        client->errorValue = stuff->property;
63135c4bbdfSmrg        return BadAtom;
63205b261ecSmrg    }
63305b261ecSmrg
6346747b715Smrg    return DeleteProperty(client, pWin, stuff->property);
63505b261ecSmrg}
636