property.c revision 706f2543
1706f2543Smrg/***********************************************************
2706f2543Smrg
3706f2543SmrgCopyright 1987, 1998  The Open Group
4706f2543Smrg
5706f2543SmrgPermission to use, copy, modify, distribute, and sell this software and its
6706f2543Smrgdocumentation for any purpose is hereby granted without fee, provided that
7706f2543Smrgthe above copyright notice appear in all copies and that both that
8706f2543Smrgcopyright notice and this permission notice appear in supporting
9706f2543Smrgdocumentation.
10706f2543Smrg
11706f2543SmrgThe above copyright notice and this permission notice shall be included in
12706f2543Smrgall copies or substantial portions of the Software.
13706f2543Smrg
14706f2543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15706f2543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16706f2543SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17706f2543SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18706f2543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19706f2543SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20706f2543Smrg
21706f2543SmrgExcept as contained in this notice, the name of The Open Group shall not be
22706f2543Smrgused in advertising or otherwise to promote the sale, use or other dealings
23706f2543Smrgin this Software without prior written authorization from The Open Group.
24706f2543Smrg
25706f2543Smrg
26706f2543SmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
27706f2543Smrg
28706f2543Smrg                        All Rights Reserved
29706f2543Smrg
30706f2543SmrgPermission to use, copy, modify, and distribute this software and its
31706f2543Smrgdocumentation for any purpose and without fee is hereby granted,
32706f2543Smrgprovided that the above copyright notice appear in all copies and that
33706f2543Smrgboth that copyright notice and this permission notice appear in
34706f2543Smrgsupporting documentation, and that the name of Digital not be
35706f2543Smrgused in advertising or publicity pertaining to distribution of the
36706f2543Smrgsoftware without specific, written prior permission.
37706f2543Smrg
38706f2543SmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39706f2543SmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40706f2543SmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41706f2543SmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42706f2543SmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43706f2543SmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
44706f2543SmrgSOFTWARE.
45706f2543Smrg
46706f2543Smrg******************************************************************/
47706f2543Smrg
48706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
49706f2543Smrg#include <dix-config.h>
50706f2543Smrg#endif
51706f2543Smrg
52706f2543Smrg#include <X11/X.h>
53706f2543Smrg#include <X11/Xproto.h>
54706f2543Smrg#include "windowstr.h"
55706f2543Smrg#include "propertyst.h"
56706f2543Smrg#include "dixstruct.h"
57706f2543Smrg#include "dispatch.h"
58706f2543Smrg#include "swaprep.h"
59706f2543Smrg#include "xace.h"
60706f2543Smrg
61706f2543Smrg/*****************************************************************
62706f2543Smrg * Property Stuff
63706f2543Smrg *
64706f2543Smrg *    dixLookupProperty, dixChangeProperty, DeleteProperty
65706f2543Smrg *
66706f2543Smrg *   Properties belong to windows.  The list of properties should not be
67706f2543Smrg *   traversed directly.  Instead, use the three functions listed above.
68706f2543Smrg *
69706f2543Smrg *****************************************************************/
70706f2543Smrg
71706f2543Smrg#ifdef notdef
72706f2543Smrgstatic void
73706f2543SmrgPrintPropertys(WindowPtr pWin)
74706f2543Smrg{
75706f2543Smrg    PropertyPtr pProp;
76706f2543Smrg    int j;
77706f2543Smrg
78706f2543Smrg    pProp = pWin->userProps;
79706f2543Smrg    while (pProp)
80706f2543Smrg    {
81706f2543Smrg        ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type);
82706f2543Smrg        ErrorF("[dix] property format: %d\n", pProp->format);
83706f2543Smrg        ErrorF("[dix] property data: \n");
84706f2543Smrg        for (j=0; j<(pProp->format/8)*pProp->size; j++)
85706f2543Smrg           ErrorF("[dix] %c\n", pProp->data[j]);
86706f2543Smrg        pProp = pProp->next;
87706f2543Smrg    }
88706f2543Smrg}
89706f2543Smrg#endif
90706f2543Smrg
91706f2543Smrgint
92706f2543SmrgdixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
93706f2543Smrg		  ClientPtr client, Mask access_mode)
94706f2543Smrg{
95706f2543Smrg    PropertyPtr pProp;
96706f2543Smrg    int rc = BadMatch;
97706f2543Smrg    client->errorValue = propertyName;
98706f2543Smrg
99706f2543Smrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
100706f2543Smrg	if (pProp->propertyName == propertyName)
101706f2543Smrg	    break;
102706f2543Smrg
103706f2543Smrg    if (pProp)
104706f2543Smrg	rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode);
105706f2543Smrg    *result = pProp;
106706f2543Smrg    return rc;
107706f2543Smrg}
108706f2543Smrg
109706f2543Smrgstatic void
110706f2543SmrgdeliverPropertyNotifyEvent(WindowPtr pWin, int state, Atom atom)
111706f2543Smrg{
112706f2543Smrg    xEvent event;
113706f2543Smrg
114706f2543Smrg    memset(&event, 0, sizeof(xEvent));
115706f2543Smrg    event.u.u.type = PropertyNotify;
116706f2543Smrg    event.u.property.window = pWin->drawable.id;
117706f2543Smrg    event.u.property.state = state;
118706f2543Smrg    event.u.property.atom = atom;
119706f2543Smrg    event.u.property.time = currentTime.milliseconds;
120706f2543Smrg    DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
121706f2543Smrg}
122706f2543Smrg
123706f2543Smrgint
124706f2543SmrgProcRotateProperties(ClientPtr client)
125706f2543Smrg{
126706f2543Smrg    int     i, j, delta, rc;
127706f2543Smrg    REQUEST(xRotatePropertiesReq);
128706f2543Smrg    WindowPtr pWin;
129706f2543Smrg    Atom * atoms;
130706f2543Smrg    PropertyPtr * props;               /* array of pointer */
131706f2543Smrg    PropertyPtr pProp, saved;
132706f2543Smrg
133706f2543Smrg    REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
134706f2543Smrg    UpdateCurrentTime();
135706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
136706f2543Smrg    if (rc != Success || stuff->nAtoms <= 0)
137706f2543Smrg        return rc;
138706f2543Smrg
139706f2543Smrg    atoms = (Atom *) & stuff[1];
140706f2543Smrg    props = malloc(stuff->nAtoms * sizeof(PropertyPtr));
141706f2543Smrg    saved = malloc(stuff->nAtoms * sizeof(PropertyRec));
142706f2543Smrg    if (!props || !saved) {
143706f2543Smrg	rc = BadAlloc;
144706f2543Smrg	goto out;
145706f2543Smrg    }
146706f2543Smrg
147706f2543Smrg    for (i = 0; i < stuff->nAtoms; i++)
148706f2543Smrg    {
149706f2543Smrg        if (!ValidAtom(atoms[i])) {
150706f2543Smrg	    rc = BadAtom;
151706f2543Smrg	    client->errorValue = atoms[i];
152706f2543Smrg	    goto out;
153706f2543Smrg        }
154706f2543Smrg        for (j = i + 1; j < stuff->nAtoms; j++)
155706f2543Smrg            if (atoms[j] == atoms[i])
156706f2543Smrg            {
157706f2543Smrg		rc = BadMatch;
158706f2543Smrg		goto out;
159706f2543Smrg            }
160706f2543Smrg
161706f2543Smrg	rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
162706f2543Smrg			       DixReadAccess|DixWriteAccess);
163706f2543Smrg	if (rc != Success)
164706f2543Smrg	    goto out;
165706f2543Smrg
166706f2543Smrg        props[i] = pProp;
167706f2543Smrg	saved[i] = *pProp;
168706f2543Smrg    }
169706f2543Smrg    delta = stuff->nPositions;
170706f2543Smrg
171706f2543Smrg    /* If the rotation is a complete 360 degrees, then moving the properties
172706f2543Smrg	around and generating PropertyNotify events should be skipped. */
173706f2543Smrg
174706f2543Smrg    if (abs(delta) % stuff->nAtoms)
175706f2543Smrg    {
176706f2543Smrg	while (delta < 0)                  /* faster if abs value is small */
177706f2543Smrg            delta += stuff->nAtoms;
178706f2543Smrg    	for (i = 0; i < stuff->nAtoms; i++)
179706f2543Smrg 	{
180706f2543Smrg	    j = (i + delta) % stuff->nAtoms;
181706f2543Smrg	    deliverPropertyNotifyEvent(pWin, PropertyNewValue, atoms[i]);
182706f2543Smrg
183706f2543Smrg	    /* Preserve name and devPrivates */
184706f2543Smrg	    props[j]->type = saved[i].type;
185706f2543Smrg	    props[j]->format = saved[i].format;
186706f2543Smrg	    props[j]->size = saved[i].size;
187706f2543Smrg	    props[j]->data = saved[i].data;
188706f2543Smrg	}
189706f2543Smrg    }
190706f2543Smrgout:
191706f2543Smrg    free(saved);
192706f2543Smrg    free(props);
193706f2543Smrg    return rc;
194706f2543Smrg}
195706f2543Smrg
196706f2543Smrgint
197706f2543SmrgProcChangeProperty(ClientPtr client)
198706f2543Smrg{
199706f2543Smrg    WindowPtr pWin;
200706f2543Smrg    char format, mode;
201706f2543Smrg    unsigned long len;
202706f2543Smrg    int sizeInBytes, totalSize, err;
203706f2543Smrg    REQUEST(xChangePropertyReq);
204706f2543Smrg
205706f2543Smrg    REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
206706f2543Smrg    UpdateCurrentTime();
207706f2543Smrg    format = stuff->format;
208706f2543Smrg    mode = stuff->mode;
209706f2543Smrg    if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
210706f2543Smrg	(mode != PropModePrepend))
211706f2543Smrg    {
212706f2543Smrg	client->errorValue = mode;
213706f2543Smrg	return BadValue;
214706f2543Smrg    }
215706f2543Smrg    if ((format != 8) && (format != 16) && (format != 32))
216706f2543Smrg    {
217706f2543Smrg	client->errorValue = format;
218706f2543Smrg        return BadValue;
219706f2543Smrg    }
220706f2543Smrg    len = stuff->nUnits;
221706f2543Smrg    if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq)))
222706f2543Smrg	return BadLength;
223706f2543Smrg    sizeInBytes = format>>3;
224706f2543Smrg    totalSize = len * sizeInBytes;
225706f2543Smrg    REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
226706f2543Smrg
227706f2543Smrg    err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
228706f2543Smrg    if (err != Success)
229706f2543Smrg	return err;
230706f2543Smrg    if (!ValidAtom(stuff->property))
231706f2543Smrg    {
232706f2543Smrg	client->errorValue = stuff->property;
233706f2543Smrg	return BadAtom;
234706f2543Smrg    }
235706f2543Smrg    if (!ValidAtom(stuff->type))
236706f2543Smrg    {
237706f2543Smrg	client->errorValue = stuff->type;
238706f2543Smrg	return BadAtom;
239706f2543Smrg    }
240706f2543Smrg
241706f2543Smrg    err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
242706f2543Smrg				  (int)format, (int)mode, len, &stuff[1],
243706f2543Smrg				  TRUE);
244706f2543Smrg    if (err != Success)
245706f2543Smrg	return err;
246706f2543Smrg    else
247706f2543Smrg	return Success;
248706f2543Smrg}
249706f2543Smrg
250706f2543Smrgint
251706f2543SmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
252706f2543Smrg			Atom type, int format, int mode, unsigned long len,
253706f2543Smrg			pointer value, Bool sendevent)
254706f2543Smrg{
255706f2543Smrg    PropertyPtr pProp;
256706f2543Smrg    PropertyRec savedProp;
257706f2543Smrg    int sizeInBytes, totalSize, rc;
258706f2543Smrg    unsigned char *data;
259706f2543Smrg    Mask access_mode;
260706f2543Smrg
261706f2543Smrg    sizeInBytes = format>>3;
262706f2543Smrg    totalSize = len * sizeInBytes;
263706f2543Smrg    access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
264706f2543Smrg
265706f2543Smrg    /* first see if property already exists */
266706f2543Smrg    rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
267706f2543Smrg
268706f2543Smrg    if (rc == BadMatch)   /* just add to list */
269706f2543Smrg    {
270706f2543Smrg	if (!pWin->optional && !MakeWindowOptional (pWin))
271706f2543Smrg	    return BadAlloc;
272706f2543Smrg	pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
273706f2543Smrg	if (!pProp)
274706f2543Smrg	    return BadAlloc;
275706f2543Smrg        data = malloc(totalSize);
276706f2543Smrg	if (!data && len)
277706f2543Smrg	{
278706f2543Smrg	    dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
279706f2543Smrg	    return BadAlloc;
280706f2543Smrg	}
281706f2543Smrg        memcpy(data, value, totalSize);
282706f2543Smrg        pProp->propertyName = property;
283706f2543Smrg        pProp->type = type;
284706f2543Smrg        pProp->format = format;
285706f2543Smrg        pProp->data = data;
286706f2543Smrg	pProp->size = len;
287706f2543Smrg	rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
288706f2543Smrg				    DixCreateAccess|DixWriteAccess);
289706f2543Smrg	if (rc != Success) {
290706f2543Smrg	    free(data);
291706f2543Smrg	    dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
292706f2543Smrg	    pClient->errorValue = property;
293706f2543Smrg	    return rc;
294706f2543Smrg	}
295706f2543Smrg        pProp->next = pWin->optional->userProps;
296706f2543Smrg        pWin->optional->userProps = pProp;
297706f2543Smrg    }
298706f2543Smrg    else if (rc == Success)
299706f2543Smrg    {
300706f2543Smrg	/* To append or prepend to a property the request format and type
301706f2543Smrg		must match those of the already defined property.  The
302706f2543Smrg		existing format and type are irrelevant when using the mode
303706f2543Smrg		"PropModeReplace" since they will be written over. */
304706f2543Smrg
305706f2543Smrg        if ((format != pProp->format) && (mode != PropModeReplace))
306706f2543Smrg	    return BadMatch;
307706f2543Smrg        if ((pProp->type != type) && (mode != PropModeReplace))
308706f2543Smrg            return BadMatch;
309706f2543Smrg
310706f2543Smrg	/* save the old values for later */
311706f2543Smrg	savedProp = *pProp;
312706f2543Smrg
313706f2543Smrg        if (mode == PropModeReplace)
314706f2543Smrg        {
315706f2543Smrg	    data = malloc(totalSize);
316706f2543Smrg	    if (!data && len)
317706f2543Smrg		return BadAlloc;
318706f2543Smrg	    memcpy(data, value, totalSize);
319706f2543Smrg	    pProp->data = data;
320706f2543Smrg	    pProp->size = len;
321706f2543Smrg    	    pProp->type = type;
322706f2543Smrg	    pProp->format = format;
323706f2543Smrg	}
324706f2543Smrg	else if (len == 0)
325706f2543Smrg	{
326706f2543Smrg	    /* do nothing */
327706f2543Smrg	}
328706f2543Smrg        else if (mode == PropModeAppend)
329706f2543Smrg        {
330706f2543Smrg	    data = malloc((pProp->size + len) * sizeInBytes);
331706f2543Smrg	    if (!data)
332706f2543Smrg		return BadAlloc;
333706f2543Smrg	    memcpy(data, pProp->data, pProp->size * sizeInBytes);
334706f2543Smrg	    memcpy(data + pProp->size * sizeInBytes, value, totalSize);
335706f2543Smrg            pProp->data = data;
336706f2543Smrg            pProp->size += len;
337706f2543Smrg	}
338706f2543Smrg        else if (mode == PropModePrepend)
339706f2543Smrg        {
340706f2543Smrg            data = malloc(sizeInBytes * (len + pProp->size));
341706f2543Smrg	    if (!data)
342706f2543Smrg		return BadAlloc;
343706f2543Smrg            memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
344706f2543Smrg            memcpy(data, value, totalSize);
345706f2543Smrg            pProp->data = data;
346706f2543Smrg            pProp->size += len;
347706f2543Smrg	}
348706f2543Smrg
349706f2543Smrg	/* Allow security modules to check the new content */
350706f2543Smrg	access_mode |= DixPostAccess;
351706f2543Smrg	rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode);
352706f2543Smrg	if (rc == Success)
353706f2543Smrg	{
354706f2543Smrg	    if (savedProp.data != pProp->data)
355706f2543Smrg		free(savedProp.data);
356706f2543Smrg	}
357706f2543Smrg	else
358706f2543Smrg	{
359706f2543Smrg	    if (savedProp.data != pProp->data)
360706f2543Smrg		free(pProp->data);
361706f2543Smrg	    *pProp = savedProp;
362706f2543Smrg	    return rc;
363706f2543Smrg	}
364706f2543Smrg    }
365706f2543Smrg    else
366706f2543Smrg	return rc;
367706f2543Smrg
368706f2543Smrg    if (sendevent)
369706f2543Smrg	deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
370706f2543Smrg
371706f2543Smrg    return Success;
372706f2543Smrg}
373706f2543Smrg
374706f2543Smrgint
375706f2543SmrgChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format,
376706f2543Smrg		     int mode, unsigned long len, pointer value,
377706f2543Smrg		     Bool sendevent)
378706f2543Smrg{
379706f2543Smrg    return dixChangeWindowProperty(serverClient, pWin, property, type, format,
380706f2543Smrg				   mode, len, value, sendevent);
381706f2543Smrg}
382706f2543Smrg
383706f2543Smrgint
384706f2543SmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
385706f2543Smrg{
386706f2543Smrg    PropertyPtr pProp, prevProp;
387706f2543Smrg    int rc;
388706f2543Smrg
389706f2543Smrg    rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
390706f2543Smrg    if (rc == BadMatch)
391706f2543Smrg	return Success; /* Succeed if property does not exist */
392706f2543Smrg
393706f2543Smrg    if (rc == Success) {
394706f2543Smrg	if (pWin->optional->userProps == pProp) {
395706f2543Smrg	    /* Takes care of head */
396706f2543Smrg            if (!(pWin->optional->userProps = pProp->next))
397706f2543Smrg		CheckWindowOptionalNeed (pWin);
398706f2543Smrg	} else {
399706f2543Smrg	    /* Need to traverse to find the previous element */
400706f2543Smrg	    prevProp = pWin->optional->userProps;
401706f2543Smrg	    while (prevProp->next != pProp)
402706f2543Smrg		prevProp = prevProp->next;
403706f2543Smrg	    prevProp->next = pProp->next;
404706f2543Smrg	}
405706f2543Smrg
406706f2543Smrg	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
407706f2543Smrg	free(pProp->data);
408706f2543Smrg	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
409706f2543Smrg    }
410706f2543Smrg    return rc;
411706f2543Smrg}
412706f2543Smrg
413706f2543Smrgvoid
414706f2543SmrgDeleteAllWindowProperties(WindowPtr pWin)
415706f2543Smrg{
416706f2543Smrg    PropertyPtr pProp, pNextProp;
417706f2543Smrg
418706f2543Smrg    pProp = wUserProps (pWin);
419706f2543Smrg    while (pProp)
420706f2543Smrg    {
421706f2543Smrg	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
422706f2543Smrg	pNextProp = pProp->next;
423706f2543Smrg        free(pProp->data);
424706f2543Smrg	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
425706f2543Smrg	pProp = pNextProp;
426706f2543Smrg    }
427706f2543Smrg
428706f2543Smrg    if (pWin->optional)
429706f2543Smrg        pWin->optional->userProps = NULL;
430706f2543Smrg}
431706f2543Smrg
432706f2543Smrgstatic int
433706f2543SmrgNullPropertyReply(
434706f2543Smrg    ClientPtr client,
435706f2543Smrg    ATOM propertyType,
436706f2543Smrg    int format,
437706f2543Smrg    xGetPropertyReply *reply)
438706f2543Smrg{
439706f2543Smrg    reply->nItems = 0;
440706f2543Smrg    reply->length = 0;
441706f2543Smrg    reply->bytesAfter = 0;
442706f2543Smrg    reply->propertyType = propertyType;
443706f2543Smrg    reply->format = format;
444706f2543Smrg    WriteReplyToClient(client, sizeof(xGenericReply), reply);
445706f2543Smrg    return Success;
446706f2543Smrg}
447706f2543Smrg
448706f2543Smrg/*****************
449706f2543Smrg * GetProperty
450706f2543Smrg *    If type Any is specified, returns the property from the specified
451706f2543Smrg *    window regardless of its type.  If a type is specified, returns the
452706f2543Smrg *    property only if its type equals the specified type.
453706f2543Smrg *    If delete is True and a property is returned, the property is also
454706f2543Smrg *    deleted from the window and a PropertyNotify event is generated on the
455706f2543Smrg *    window.
456706f2543Smrg *****************/
457706f2543Smrg
458706f2543Smrgint
459706f2543SmrgProcGetProperty(ClientPtr client)
460706f2543Smrg{
461706f2543Smrg    PropertyPtr pProp, prevProp;
462706f2543Smrg    unsigned long n, len, ind;
463706f2543Smrg    int rc;
464706f2543Smrg    WindowPtr pWin;
465706f2543Smrg    xGetPropertyReply reply;
466706f2543Smrg    Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
467706f2543Smrg    REQUEST(xGetPropertyReq);
468706f2543Smrg
469706f2543Smrg    REQUEST_SIZE_MATCH(xGetPropertyReq);
470706f2543Smrg    if (stuff->delete) {
471706f2543Smrg	UpdateCurrentTime();
472706f2543Smrg	win_mode |= DixSetPropAccess;
473706f2543Smrg	prop_mode |= DixDestroyAccess;
474706f2543Smrg    }
475706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
476706f2543Smrg    if (rc != Success)
477706f2543Smrg	return (rc == BadMatch) ? BadWindow : rc;
478706f2543Smrg
479706f2543Smrg    if (!ValidAtom(stuff->property))
480706f2543Smrg    {
481706f2543Smrg	client->errorValue = stuff->property;
482706f2543Smrg	return BadAtom;
483706f2543Smrg    }
484706f2543Smrg    if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
485706f2543Smrg    {
486706f2543Smrg	client->errorValue = stuff->delete;
487706f2543Smrg	return BadValue;
488706f2543Smrg    }
489706f2543Smrg    if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
490706f2543Smrg    {
491706f2543Smrg	client->errorValue = stuff->type;
492706f2543Smrg	return BadAtom;
493706f2543Smrg    }
494706f2543Smrg
495706f2543Smrg    memset(&reply, 0, sizeof(xGetPropertyReply));
496706f2543Smrg    reply.type = X_Reply;
497706f2543Smrg    reply.sequenceNumber = client->sequence;
498706f2543Smrg
499706f2543Smrg    rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
500706f2543Smrg    if (rc == BadMatch)
501706f2543Smrg	return NullPropertyReply(client, None, 0, &reply);
502706f2543Smrg    else if (rc != Success)
503706f2543Smrg	return rc;
504706f2543Smrg
505706f2543Smrg    /* If the request type and actual type don't match. Return the
506706f2543Smrg    property information, but not the data. */
507706f2543Smrg
508706f2543Smrg    if (((stuff->type != pProp->type) &&
509706f2543Smrg	 (stuff->type != AnyPropertyType))
510706f2543Smrg       )
511706f2543Smrg    {
512706f2543Smrg	reply.bytesAfter = pProp->size;
513706f2543Smrg	reply.format = pProp->format;
514706f2543Smrg	reply.length = 0;
515706f2543Smrg	reply.nItems = 0;
516706f2543Smrg	reply.propertyType = pProp->type;
517706f2543Smrg	WriteReplyToClient(client, sizeof(xGenericReply), &reply);
518706f2543Smrg	return Success;
519706f2543Smrg    }
520706f2543Smrg
521706f2543Smrg/*
522706f2543Smrg *  Return type, format, value to client
523706f2543Smrg */
524706f2543Smrg    n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */
525706f2543Smrg    ind = stuff->longOffset << 2;
526706f2543Smrg
527706f2543Smrg   /* If longOffset is invalid such that it causes "len" to
528706f2543Smrg	    be negative, it's a value error. */
529706f2543Smrg
530706f2543Smrg    if (n < ind)
531706f2543Smrg    {
532706f2543Smrg	client->errorValue = stuff->longOffset;
533706f2543Smrg	return BadValue;
534706f2543Smrg    }
535706f2543Smrg
536706f2543Smrg    len = min(n - ind, 4 * stuff->longLength);
537706f2543Smrg
538706f2543Smrg    reply.bytesAfter = n - (ind + len);
539706f2543Smrg    reply.format = pProp->format;
540706f2543Smrg    reply.length = bytes_to_int32(len);
541706f2543Smrg    reply.nItems = len / (pProp->format / 8 );
542706f2543Smrg    reply.propertyType = pProp->type;
543706f2543Smrg
544706f2543Smrg    if (stuff->delete && (reply.bytesAfter == 0))
545706f2543Smrg	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
546706f2543Smrg
547706f2543Smrg    WriteReplyToClient(client, sizeof(xGenericReply), &reply);
548706f2543Smrg    if (len)
549706f2543Smrg    {
550706f2543Smrg	switch (reply.format) {
551706f2543Smrg	case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
552706f2543Smrg	case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
553706f2543Smrg	default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
554706f2543Smrg	}
555706f2543Smrg	WriteSwappedDataToClient(client, len,
556706f2543Smrg				 (char *)pProp->data + ind);
557706f2543Smrg    }
558706f2543Smrg
559706f2543Smrg    if (stuff->delete && (reply.bytesAfter == 0)) {
560706f2543Smrg	/* Delete the Property */
561706f2543Smrg	if (pWin->optional->userProps == pProp) {
562706f2543Smrg	    /* Takes care of head */
563706f2543Smrg            if (!(pWin->optional->userProps = pProp->next))
564706f2543Smrg		CheckWindowOptionalNeed (pWin);
565706f2543Smrg	} else {
566706f2543Smrg	    /* Need to traverse to find the previous element */
567706f2543Smrg	    prevProp = pWin->optional->userProps;
568706f2543Smrg	    while (prevProp->next != pProp)
569706f2543Smrg		prevProp = prevProp->next;
570706f2543Smrg	    prevProp->next = pProp->next;
571706f2543Smrg	}
572706f2543Smrg
573706f2543Smrg	free(pProp->data);
574706f2543Smrg	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
575706f2543Smrg    }
576706f2543Smrg    return Success;
577706f2543Smrg}
578706f2543Smrg
579706f2543Smrgint
580706f2543SmrgProcListProperties(ClientPtr client)
581706f2543Smrg{
582706f2543Smrg    Atom *pAtoms = NULL, *temppAtoms;
583706f2543Smrg    xListPropertiesReply xlpr;
584706f2543Smrg    int	rc, numProps = 0;
585706f2543Smrg    WindowPtr pWin;
586706f2543Smrg    PropertyPtr pProp, realProp;
587706f2543Smrg    REQUEST(xResourceReq);
588706f2543Smrg
589706f2543Smrg    REQUEST_SIZE_MATCH(xResourceReq);
590706f2543Smrg    rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
591706f2543Smrg    if (rc != Success)
592706f2543Smrg        return rc;
593706f2543Smrg
594706f2543Smrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
595706f2543Smrg	numProps++;
596706f2543Smrg
597706f2543Smrg    if (numProps && !(pAtoms = malloc(numProps * sizeof(Atom))))
598706f2543Smrg	return BadAlloc;
599706f2543Smrg
600706f2543Smrg    numProps = 0;
601706f2543Smrg    temppAtoms = pAtoms;
602706f2543Smrg    for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
603706f2543Smrg	realProp = pProp;
604706f2543Smrg	rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
605706f2543Smrg	if (rc == Success && realProp == pProp) {
606706f2543Smrg	    *temppAtoms++ = pProp->propertyName;
607706f2543Smrg	    numProps++;
608706f2543Smrg	}
609706f2543Smrg    }
610706f2543Smrg
611706f2543Smrg    xlpr.type = X_Reply;
612706f2543Smrg    xlpr.nProperties = numProps;
613706f2543Smrg    xlpr.length = bytes_to_int32(numProps * sizeof(Atom));
614706f2543Smrg    xlpr.sequenceNumber = client->sequence;
615706f2543Smrg    WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
616706f2543Smrg    if (numProps)
617706f2543Smrg    {
618706f2543Smrg        client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
619706f2543Smrg        WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
620706f2543Smrg    }
621706f2543Smrg    free(pAtoms);
622706f2543Smrg    return Success;
623706f2543Smrg}
624706f2543Smrg
625706f2543Smrgint
626706f2543SmrgProcDeleteProperty(ClientPtr client)
627706f2543Smrg{
628706f2543Smrg    WindowPtr pWin;
629706f2543Smrg    REQUEST(xDeletePropertyReq);
630706f2543Smrg    int result;
631706f2543Smrg
632706f2543Smrg    REQUEST_SIZE_MATCH(xDeletePropertyReq);
633706f2543Smrg    UpdateCurrentTime();
634706f2543Smrg    result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
635706f2543Smrg    if (result != Success)
636706f2543Smrg        return result;
637706f2543Smrg    if (!ValidAtom(stuff->property))
638706f2543Smrg    {
639706f2543Smrg	client->errorValue = stuff->property;
640706f2543Smrg	return BadAtom;
641706f2543Smrg    }
642706f2543Smrg
643706f2543Smrg    return DeleteProperty(client, pWin, stuff->property);
644706f2543Smrg}
645