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;
208c82838c1Smrg    int sizeInBytes, err;
209c82838c1Smrg    uint64_t totalSize;
21035c4bbdfSmrg
21105b261ecSmrg    REQUEST(xChangePropertyReq);
21205b261ecSmrg
21305b261ecSmrg    REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
21405b261ecSmrg    UpdateCurrentTime();
21505b261ecSmrg    format = stuff->format;
21605b261ecSmrg    mode = stuff->mode;
21705b261ecSmrg    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
21835c4bbdfSmrg        (mode != PropModePrepend)) {
21935c4bbdfSmrg        client->errorValue = mode;
22035c4bbdfSmrg        return BadValue;
22105b261ecSmrg    }
22235c4bbdfSmrg    if ((format != 8) && (format != 16) && (format != 32)) {
22335c4bbdfSmrg        client->errorValue = format;
22405b261ecSmrg        return BadValue;
22505b261ecSmrg    }
22605b261ecSmrg    len = stuff->nUnits;
2276747b715Smrg    if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq)))
22835c4bbdfSmrg        return BadLength;
22935c4bbdfSmrg    sizeInBytes = format >> 3;
23005b261ecSmrg    totalSize = len * sizeInBytes;
23105b261ecSmrg    REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
23205b261ecSmrg
2334642e01fSmrg    err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
23405b261ecSmrg    if (err != Success)
23535c4bbdfSmrg        return err;
23635c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
23735c4bbdfSmrg        client->errorValue = stuff->property;
23835c4bbdfSmrg        return BadAtom;
23905b261ecSmrg    }
24035c4bbdfSmrg    if (!ValidAtom(stuff->type)) {
24135c4bbdfSmrg        client->errorValue = stuff->type;
24235c4bbdfSmrg        return BadAtom;
24305b261ecSmrg    }
24405b261ecSmrg
2454642e01fSmrg    err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
24635c4bbdfSmrg                                  (int) format, (int) mode, len, &stuff[1],
24735c4bbdfSmrg                                  TRUE);
24805b261ecSmrg    if (err != Success)
24935c4bbdfSmrg        return err;
25005b261ecSmrg    else
25135c4bbdfSmrg        return Success;
25205b261ecSmrg}
25305b261ecSmrg
2546747b715Smrgint
2554642e01fSmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
25635c4bbdfSmrg                        Atom type, int format, int mode, unsigned long len,
257ed6184dfSmrg                        const void *value, Bool sendevent)
25805b261ecSmrg{
25905b261ecSmrg    PropertyPtr pProp;
2606747b715Smrg    PropertyRec savedProp;
2614642e01fSmrg    int sizeInBytes, totalSize, rc;
2626747b715Smrg    unsigned char *data;
2634642e01fSmrg    Mask access_mode;
26405b261ecSmrg
26535c4bbdfSmrg    sizeInBytes = format >> 3;
26605b261ecSmrg    totalSize = len * sizeInBytes;
2674642e01fSmrg    access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
26805b261ecSmrg
26905b261ecSmrg    /* first see if property already exists */
2704642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
27105b261ecSmrg
27235c4bbdfSmrg    if (rc == BadMatch) {       /* just add to list */
27335c4bbdfSmrg        if (!pWin->optional && !MakeWindowOptional(pWin))
27435c4bbdfSmrg            return BadAlloc;
27535c4bbdfSmrg        pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
27635c4bbdfSmrg        if (!pProp)
27735c4bbdfSmrg            return BadAlloc;
2786747b715Smrg        data = malloc(totalSize);
27958cf2af7Smrg        if (totalSize) {
28058cf2af7Smrg            if (!data) {
28158cf2af7Smrg                dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
28258cf2af7Smrg                return BadAlloc;
28358cf2af7Smrg            }
28458cf2af7Smrg            memcpy(data, value, totalSize);
28535c4bbdfSmrg        }
28605b261ecSmrg        pProp->propertyName = property;
28705b261ecSmrg        pProp->type = type;
28805b261ecSmrg        pProp->format = format;
28905b261ecSmrg        pProp->data = data;
29035c4bbdfSmrg        pProp->size = len;
29135c4bbdfSmrg        rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
29235c4bbdfSmrg                                    DixCreateAccess | DixWriteAccess);
29335c4bbdfSmrg        if (rc != Success) {
29435c4bbdfSmrg            free(data);
29535c4bbdfSmrg            dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
29635c4bbdfSmrg            pClient->errorValue = property;
29735c4bbdfSmrg            return rc;
29835c4bbdfSmrg        }
29905b261ecSmrg        pProp->next = pWin->optional->userProps;
30005b261ecSmrg        pWin->optional->userProps = pProp;
30105b261ecSmrg    }
30235c4bbdfSmrg    else if (rc == Success) {
30335c4bbdfSmrg        /* To append or prepend to a property the request format and type
30435c4bbdfSmrg           must match those of the already defined property.  The
30535c4bbdfSmrg           existing format and type are irrelevant when using the mode
30635c4bbdfSmrg           "PropModeReplace" since they will be written over. */
30705b261ecSmrg
30805b261ecSmrg        if ((format != pProp->format) && (mode != PropModeReplace))
30935c4bbdfSmrg            return BadMatch;
31005b261ecSmrg        if ((pProp->type != type) && (mode != PropModeReplace))
3116747b715Smrg            return BadMatch;
3126747b715Smrg
31335c4bbdfSmrg        /* save the old values for later */
31435c4bbdfSmrg        savedProp = *pProp;
31535c4bbdfSmrg
31635c4bbdfSmrg        if (mode == PropModeReplace) {
31735c4bbdfSmrg            data = malloc(totalSize);
31858cf2af7Smrg            if (totalSize) {
31958cf2af7Smrg                if (!data)
32058cf2af7Smrg                    return BadAlloc;
32158cf2af7Smrg                memcpy(data, value, totalSize);
32258cf2af7Smrg            }
32335c4bbdfSmrg            pProp->data = data;
32435c4bbdfSmrg            pProp->size = len;
32535c4bbdfSmrg            pProp->type = type;
32635c4bbdfSmrg            pProp->format = format;
32735c4bbdfSmrg        }
32835c4bbdfSmrg        else if (len == 0) {
32935c4bbdfSmrg            /* do nothing */
33035c4bbdfSmrg        }
33135c4bbdfSmrg        else if (mode == PropModeAppend) {
33235c4bbdfSmrg            data = xallocarray(pProp->size + len, sizeInBytes);
33335c4bbdfSmrg            if (!data)
33435c4bbdfSmrg                return BadAlloc;
33535c4bbdfSmrg            memcpy(data, pProp->data, pProp->size * sizeInBytes);
33635c4bbdfSmrg            memcpy(data + pProp->size * sizeInBytes, value, totalSize);
33705b261ecSmrg            pProp->data = data;
33805b261ecSmrg            pProp->size += len;
33935c4bbdfSmrg        }
34035c4bbdfSmrg        else if (mode == PropModePrepend) {
34135c4bbdfSmrg            data = xallocarray(len + pProp->size, sizeInBytes);
34235c4bbdfSmrg            if (!data)
34335c4bbdfSmrg                return BadAlloc;
3446747b715Smrg            memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
3456747b715Smrg            memcpy(data, value, totalSize);
34605b261ecSmrg            pProp->data = data;
34705b261ecSmrg            pProp->size += len;
34835c4bbdfSmrg        }
34935c4bbdfSmrg
35035c4bbdfSmrg        /* Allow security modules to check the new content */
35135c4bbdfSmrg        access_mode |= DixPostAccess;
35235c4bbdfSmrg        rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode);
35335c4bbdfSmrg        if (rc == Success) {
35435c4bbdfSmrg            if (savedProp.data != pProp->data)
35535c4bbdfSmrg                free(savedProp.data);
35635c4bbdfSmrg        }
35735c4bbdfSmrg        else {
35835c4bbdfSmrg            if (savedProp.data != pProp->data)
35935c4bbdfSmrg                free(pProp->data);
36035c4bbdfSmrg            *pProp = savedProp;
36135c4bbdfSmrg            return rc;
36235c4bbdfSmrg        }
36305b261ecSmrg    }
3644642e01fSmrg    else
36535c4bbdfSmrg        return rc;
36605b261ecSmrg
36705b261ecSmrg    if (sendevent)
3681b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp);
36905b261ecSmrg
3706747b715Smrg    return Success;
37105b261ecSmrg}
37205b261ecSmrg
37305b261ecSmrgint
3744642e01fSmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
37505b261ecSmrg{
37605b261ecSmrg    PropertyPtr pProp, prevProp;
3774642e01fSmrg    int rc;
37805b261ecSmrg
3794642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
3804642e01fSmrg    if (rc == BadMatch)
38135c4bbdfSmrg        return Success;         /* Succeed if property does not exist */
3824642e01fSmrg
3834642e01fSmrg    if (rc == Success) {
38435c4bbdfSmrg        if (pWin->optional->userProps == pProp) {
38535c4bbdfSmrg            /* Takes care of head */
38605b261ecSmrg            if (!(pWin->optional->userProps = pProp->next))
38735c4bbdfSmrg                CheckWindowOptionalNeed(pWin);
38835c4bbdfSmrg        }
38935c4bbdfSmrg        else {
39035c4bbdfSmrg            /* Need to traverse to find the previous element */
39135c4bbdfSmrg            prevProp = pWin->optional->userProps;
39235c4bbdfSmrg            while (prevProp->next != pProp)
39335c4bbdfSmrg                prevProp = prevProp->next;
39435c4bbdfSmrg            prevProp->next = pProp->next;
39535c4bbdfSmrg        }
39635c4bbdfSmrg
3971b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
39835c4bbdfSmrg        free(pProp->data);
39935c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
40005b261ecSmrg    }
4014642e01fSmrg    return rc;
40205b261ecSmrg}
40305b261ecSmrg
40405b261ecSmrgvoid
40505b261ecSmrgDeleteAllWindowProperties(WindowPtr pWin)
40605b261ecSmrg{
40705b261ecSmrg    PropertyPtr pProp, pNextProp;
40805b261ecSmrg
40935c4bbdfSmrg    pProp = wUserProps(pWin);
41035c4bbdfSmrg    while (pProp) {
4111b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
41235c4bbdfSmrg        pNextProp = pProp->next;
4136747b715Smrg        free(pProp->data);
41435c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
41535c4bbdfSmrg        pProp = pNextProp;
41605b261ecSmrg    }
4179ace9065Smrg
4189ace9065Smrg    if (pWin->optional)
4199ace9065Smrg        pWin->optional->userProps = NULL;
42005b261ecSmrg}
42105b261ecSmrg
42205b261ecSmrgstatic int
42335c4bbdfSmrgNullPropertyReply(ClientPtr client, ATOM propertyType, int format)
42405b261ecSmrg{
42535c4bbdfSmrg    xGetPropertyReply reply = {
42635c4bbdfSmrg        .type = X_Reply,
42735c4bbdfSmrg        .format = format,
42835c4bbdfSmrg        .sequenceNumber = client->sequence,
42935c4bbdfSmrg        .length = 0,
43035c4bbdfSmrg        .propertyType = propertyType,
43135c4bbdfSmrg        .bytesAfter = 0,
43235c4bbdfSmrg        .nItems = 0
43335c4bbdfSmrg    };
43435c4bbdfSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
4356747b715Smrg    return Success;
43605b261ecSmrg}
43705b261ecSmrg
43805b261ecSmrg/*****************
43905b261ecSmrg * GetProperty
44005b261ecSmrg *    If type Any is specified, returns the property from the specified
44105b261ecSmrg *    window regardless of its type.  If a type is specified, returns the
44205b261ecSmrg *    property only if its type equals the specified type.
44305b261ecSmrg *    If delete is True and a property is returned, the property is also
44405b261ecSmrg *    deleted from the window and a PropertyNotify event is generated on the
44505b261ecSmrg *    window.
44605b261ecSmrg *****************/
44705b261ecSmrg
44805b261ecSmrgint
44905b261ecSmrgProcGetProperty(ClientPtr client)
45005b261ecSmrg{
45105b261ecSmrg    PropertyPtr pProp, prevProp;
4524642e01fSmrg    unsigned long n, len, ind;
4534642e01fSmrg    int rc;
45405b261ecSmrg    WindowPtr pWin;
45505b261ecSmrg    xGetPropertyReply reply;
4564642e01fSmrg    Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
45735c4bbdfSmrg
45805b261ecSmrg    REQUEST(xGetPropertyReq);
45905b261ecSmrg
46005b261ecSmrg    REQUEST_SIZE_MATCH(xGetPropertyReq);
4614642e01fSmrg    if (stuff->delete) {
46235c4bbdfSmrg        UpdateCurrentTime();
46335c4bbdfSmrg        win_mode |= DixSetPropAccess;
46435c4bbdfSmrg        prop_mode |= DixDestroyAccess;
4654642e01fSmrg    }
4664642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
46705b261ecSmrg    if (rc != Success)
46835c4bbdfSmrg        return rc;
46905b261ecSmrg
47035c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
47135c4bbdfSmrg        client->errorValue = stuff->property;
47235c4bbdfSmrg        return BadAtom;
47305b261ecSmrg    }
47435c4bbdfSmrg    if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) {
47535c4bbdfSmrg        client->errorValue = stuff->delete;
47635c4bbdfSmrg        return BadValue;
47705b261ecSmrg    }
47835c4bbdfSmrg    if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) {
47935c4bbdfSmrg        client->errorValue = stuff->type;
48035c4bbdfSmrg        return BadAtom;
48105b261ecSmrg    }
48205b261ecSmrg
4834642e01fSmrg    rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
4844642e01fSmrg    if (rc == BadMatch)
48535c4bbdfSmrg        return NullPropertyReply(client, None, 0);
4864642e01fSmrg    else if (rc != Success)
48735c4bbdfSmrg        return rc;
48805b261ecSmrg
48905b261ecSmrg    /* If the request type and actual type don't match. Return the
49035c4bbdfSmrg       property information, but not the data. */
49135c4bbdfSmrg
49235c4bbdfSmrg    if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType))
49335c4bbdfSmrg        ) {
49435c4bbdfSmrg        reply = (xGetPropertyReply) {
49535c4bbdfSmrg            .type = X_Reply,
49635c4bbdfSmrg            .sequenceNumber = client->sequence,
49735c4bbdfSmrg            .bytesAfter = pProp->size,
49835c4bbdfSmrg            .format = pProp->format,
49935c4bbdfSmrg            .length = 0,
50035c4bbdfSmrg            .nItems = 0,
50135c4bbdfSmrg            .propertyType = pProp->type
50235c4bbdfSmrg        };
50335c4bbdfSmrg        WriteReplyToClient(client, sizeof(xGenericReply), &reply);
50435c4bbdfSmrg        return Success;
50505b261ecSmrg    }
50605b261ecSmrg
50705b261ecSmrg/*
50805b261ecSmrg *  Return type, format, value to client
50905b261ecSmrg */
51035c4bbdfSmrg    n = (pProp->format / 8) * pProp->size;      /* size (bytes) of prop */
51135c4bbdfSmrg    ind = stuff->longOffset << 2;
51205b261ecSmrg
51335c4bbdfSmrg    /* If longOffset is invalid such that it causes "len" to
51435c4bbdfSmrg       be negative, it's a value error. */
51505b261ecSmrg
51635c4bbdfSmrg    if (n < ind) {
51735c4bbdfSmrg        client->errorValue = stuff->longOffset;
51835c4bbdfSmrg        return BadValue;
51905b261ecSmrg    }
52005b261ecSmrg
52105b261ecSmrg    len = min(n - ind, 4 * stuff->longLength);
52205b261ecSmrg
52335c4bbdfSmrg    reply = (xGetPropertyReply) {
52435c4bbdfSmrg        .type = X_Reply,
52535c4bbdfSmrg        .sequenceNumber = client->sequence,
52635c4bbdfSmrg        .bytesAfter = n - (ind + len),
52735c4bbdfSmrg        .format = pProp->format,
52835c4bbdfSmrg        .length = bytes_to_int32(len),
52935c4bbdfSmrg        .nItems = len / (pProp->format / 8),
53035c4bbdfSmrg        .propertyType = pProp->type
53135c4bbdfSmrg    };
53205b261ecSmrg
53305b261ecSmrg    if (stuff->delete && (reply.bytesAfter == 0))
5341b5d61b8Smrg        deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
53505b261ecSmrg
53605b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
53735c4bbdfSmrg    if (len) {
53835c4bbdfSmrg        switch (reply.format) {
53935c4bbdfSmrg        case 32:
54035c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
54135c4bbdfSmrg            break;
54235c4bbdfSmrg        case 16:
54335c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
54435c4bbdfSmrg            break;
54535c4bbdfSmrg        default:
54635c4bbdfSmrg            client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
54735c4bbdfSmrg            break;
54835c4bbdfSmrg        }
54935c4bbdfSmrg        WriteSwappedDataToClient(client, len, (char *) pProp->data + ind);
55005b261ecSmrg    }
55105b261ecSmrg
5524642e01fSmrg    if (stuff->delete && (reply.bytesAfter == 0)) {
55335c4bbdfSmrg        /* Delete the Property */
55435c4bbdfSmrg        if (pWin->optional->userProps == pProp) {
55535c4bbdfSmrg            /* Takes care of head */
5564642e01fSmrg            if (!(pWin->optional->userProps = pProp->next))
55735c4bbdfSmrg                CheckWindowOptionalNeed(pWin);
55835c4bbdfSmrg        }
55935c4bbdfSmrg        else {
56035c4bbdfSmrg            /* Need to traverse to find the previous element */
56135c4bbdfSmrg            prevProp = pWin->optional->userProps;
56235c4bbdfSmrg            while (prevProp->next != pProp)
56335c4bbdfSmrg                prevProp = prevProp->next;
56435c4bbdfSmrg            prevProp->next = pProp->next;
56535c4bbdfSmrg        }
56635c4bbdfSmrg
56735c4bbdfSmrg        free(pProp->data);
56835c4bbdfSmrg        dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
56905b261ecSmrg    }
5706747b715Smrg    return Success;
57105b261ecSmrg}
57205b261ecSmrg
57305b261ecSmrgint
57405b261ecSmrgProcListProperties(ClientPtr client)
57505b261ecSmrg{
57605b261ecSmrg    Atom *pAtoms = NULL, *temppAtoms;
57705b261ecSmrg    xListPropertiesReply xlpr;
57835c4bbdfSmrg    int rc, numProps = 0;
57905b261ecSmrg    WindowPtr pWin;
5804642e01fSmrg    PropertyPtr pProp, realProp;
58135c4bbdfSmrg
58205b261ecSmrg    REQUEST(xResourceReq);
58305b261ecSmrg
58405b261ecSmrg    REQUEST_SIZE_MATCH(xResourceReq);
5854642e01fSmrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
58605b261ecSmrg    if (rc != Success)
58705b261ecSmrg        return rc;
58805b261ecSmrg
5894642e01fSmrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
59035c4bbdfSmrg        numProps++;
5914642e01fSmrg
59258cf2af7Smrg    if (numProps) {
59358cf2af7Smrg        pAtoms = xallocarray(numProps, sizeof(Atom));
59458cf2af7Smrg        if (!pAtoms)
59558cf2af7Smrg            return BadAlloc;
59658cf2af7Smrg
59758cf2af7Smrg        numProps = 0;
59858cf2af7Smrg        temppAtoms = pAtoms;
59958cf2af7Smrg        for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
60058cf2af7Smrg            realProp = pProp;
60158cf2af7Smrg            rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
60258cf2af7Smrg            if (rc == Success && realProp == pProp) {
60358cf2af7Smrg                *temppAtoms++ = pProp->propertyName;
60458cf2af7Smrg                numProps++;
60558cf2af7Smrg            }
60635c4bbdfSmrg        }
60705b261ecSmrg    }
60805b261ecSmrg
60935c4bbdfSmrg    xlpr = (xListPropertiesReply) {
61035c4bbdfSmrg        .type = X_Reply,
61135c4bbdfSmrg        .sequenceNumber = client->sequence,
61235c4bbdfSmrg        .length = bytes_to_int32(numProps * sizeof(Atom)),
61335c4bbdfSmrg        .nProperties = numProps
61435c4bbdfSmrg    };
61505b261ecSmrg    WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
61635c4bbdfSmrg    if (numProps) {
61735c4bbdfSmrg        client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
61805b261ecSmrg        WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
61958cf2af7Smrg        free(pAtoms);
62005b261ecSmrg    }
6216747b715Smrg    return Success;
62205b261ecSmrg}
62305b261ecSmrg
62435c4bbdfSmrgint
62505b261ecSmrgProcDeleteProperty(ClientPtr client)
62605b261ecSmrg{
62705b261ecSmrg    WindowPtr pWin;
62835c4bbdfSmrg
62905b261ecSmrg    REQUEST(xDeletePropertyReq);
63005b261ecSmrg    int result;
63135c4bbdfSmrg
63205b261ecSmrg    REQUEST_SIZE_MATCH(xDeletePropertyReq);
63305b261ecSmrg    UpdateCurrentTime();
6344642e01fSmrg    result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
63505b261ecSmrg    if (result != Success)
63605b261ecSmrg        return result;
63735c4bbdfSmrg    if (!ValidAtom(stuff->property)) {
63835c4bbdfSmrg        client->errorValue = stuff->property;
63935c4bbdfSmrg        return BadAtom;
64005b261ecSmrg    }
64105b261ecSmrg
6426747b715Smrg    return DeleteProperty(client, pWin, stuff->property);
64305b261ecSmrg}
644