xref: /OK3568_Linux_fs/external/xserver/dix/property.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /***********************************************************
2*4882a593Smuzhiyun 
3*4882a593Smuzhiyun Copyright 1987, 1998  The Open Group
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun the above copyright notice appear in all copies and that both that
8*4882a593Smuzhiyun copyright notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation.
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun The above copyright notice and this permission notice shall be included in
12*4882a593Smuzhiyun all copies or substantial portions of the Software.
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*4882a593Smuzhiyun IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*4882a593Smuzhiyun FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17*4882a593Smuzhiyun OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18*4882a593Smuzhiyun AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19*4882a593Smuzhiyun CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun Except as contained in this notice, the name of The Open Group shall not be
22*4882a593Smuzhiyun used in advertising or otherwise to promote the sale, use or other dealings
23*4882a593Smuzhiyun in this Software without prior written authorization from The Open Group.
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun                         All Rights Reserved
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this software and its
30*4882a593Smuzhiyun documentation for any purpose and without fee is hereby granted,
31*4882a593Smuzhiyun provided that the above copyright notice appear in all copies and that
32*4882a593Smuzhiyun both that copyright notice and this permission notice appear in
33*4882a593Smuzhiyun supporting documentation, and that the name of Digital not be
34*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution of the
35*4882a593Smuzhiyun software without specific, written prior permission.
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38*4882a593Smuzhiyun ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39*4882a593Smuzhiyun DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40*4882a593Smuzhiyun ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41*4882a593Smuzhiyun WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42*4882a593Smuzhiyun ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43*4882a593Smuzhiyun SOFTWARE.
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun ******************************************************************/
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
48*4882a593Smuzhiyun #include <dix-config.h>
49*4882a593Smuzhiyun #endif
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #include <X11/X.h>
52*4882a593Smuzhiyun #include <X11/Xproto.h>
53*4882a593Smuzhiyun #include "windowstr.h"
54*4882a593Smuzhiyun #include "propertyst.h"
55*4882a593Smuzhiyun #include "dixstruct.h"
56*4882a593Smuzhiyun #include "dispatch.h"
57*4882a593Smuzhiyun #include "swaprep.h"
58*4882a593Smuzhiyun #include "xace.h"
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /*****************************************************************
61*4882a593Smuzhiyun  * Property Stuff
62*4882a593Smuzhiyun  *
63*4882a593Smuzhiyun  *    dixLookupProperty, dixChangeProperty, DeleteProperty
64*4882a593Smuzhiyun  *
65*4882a593Smuzhiyun  *   Properties belong to windows.  The list of properties should not be
66*4882a593Smuzhiyun  *   traversed directly.  Instead, use the three functions listed above.
67*4882a593Smuzhiyun  *
68*4882a593Smuzhiyun  *****************************************************************/
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun #ifdef notdef
71*4882a593Smuzhiyun static void
PrintPropertys(WindowPtr pWin)72*4882a593Smuzhiyun PrintPropertys(WindowPtr pWin)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun     PropertyPtr pProp;
75*4882a593Smuzhiyun     int j;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun     pProp = pWin->userProps;
78*4882a593Smuzhiyun     while (pProp) {
79*4882a593Smuzhiyun         ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type);
80*4882a593Smuzhiyun         ErrorF("[dix] property format: %d\n", pProp->format);
81*4882a593Smuzhiyun         ErrorF("[dix] property data: \n");
82*4882a593Smuzhiyun         for (j = 0; j < (pProp->format / 8) * pProp->size; j++)
83*4882a593Smuzhiyun             ErrorF("[dix] %c\n", pProp->data[j]);
84*4882a593Smuzhiyun         pProp = pProp->next;
85*4882a593Smuzhiyun     }
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun #endif
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun int
dixLookupProperty(PropertyPtr * result,WindowPtr pWin,Atom propertyName,ClientPtr client,Mask access_mode)90*4882a593Smuzhiyun dixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
91*4882a593Smuzhiyun                   ClientPtr client, Mask access_mode)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun     PropertyPtr pProp;
94*4882a593Smuzhiyun     int rc = BadMatch;
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun     client->errorValue = propertyName;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
99*4882a593Smuzhiyun         if (pProp->propertyName == propertyName)
100*4882a593Smuzhiyun             break;
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun     if (pProp)
103*4882a593Smuzhiyun         rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode);
104*4882a593Smuzhiyun     *result = pProp;
105*4882a593Smuzhiyun     return rc;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun CallbackListPtr PropertyStateCallback;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun static void
deliverPropertyNotifyEvent(WindowPtr pWin,int state,PropertyPtr pProp)111*4882a593Smuzhiyun deliverPropertyNotifyEvent(WindowPtr pWin, int state, PropertyPtr pProp)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun     xEvent event;
114*4882a593Smuzhiyun     PropertyStateRec rec = {
115*4882a593Smuzhiyun         .win = pWin,
116*4882a593Smuzhiyun         .prop = pProp,
117*4882a593Smuzhiyun         .state = state
118*4882a593Smuzhiyun     };
119*4882a593Smuzhiyun     UpdateCurrentTimeIf();
120*4882a593Smuzhiyun     event = (xEvent) {
121*4882a593Smuzhiyun         .u.property.window = pWin->drawable.id,
122*4882a593Smuzhiyun         .u.property.state = state,
123*4882a593Smuzhiyun         .u.property.atom = pProp->propertyName,
124*4882a593Smuzhiyun         .u.property.time = currentTime.milliseconds,
125*4882a593Smuzhiyun     };
126*4882a593Smuzhiyun     event.u.u.type = PropertyNotify;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun     CallCallbacks(&PropertyStateCallback, &rec);
129*4882a593Smuzhiyun     DeliverEvents(pWin, &event, 1, (WindowPtr) NULL);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun int
ProcRotateProperties(ClientPtr client)133*4882a593Smuzhiyun ProcRotateProperties(ClientPtr client)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun     int i, j, delta, rc;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     REQUEST(xRotatePropertiesReq);
138*4882a593Smuzhiyun     WindowPtr pWin;
139*4882a593Smuzhiyun     Atom *atoms;
140*4882a593Smuzhiyun     PropertyPtr *props;         /* array of pointer */
141*4882a593Smuzhiyun     PropertyPtr pProp, saved;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
144*4882a593Smuzhiyun     UpdateCurrentTime();
145*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
146*4882a593Smuzhiyun     if (rc != Success || stuff->nAtoms <= 0)
147*4882a593Smuzhiyun         return rc;
148*4882a593Smuzhiyun 
149*4882a593Smuzhiyun     atoms = (Atom *) &stuff[1];
150*4882a593Smuzhiyun     props = xallocarray(stuff->nAtoms, sizeof(PropertyPtr));
151*4882a593Smuzhiyun     saved = xallocarray(stuff->nAtoms, sizeof(PropertyRec));
152*4882a593Smuzhiyun     if (!props || !saved) {
153*4882a593Smuzhiyun         rc = BadAlloc;
154*4882a593Smuzhiyun         goto out;
155*4882a593Smuzhiyun     }
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun     for (i = 0; i < stuff->nAtoms; i++) {
158*4882a593Smuzhiyun         if (!ValidAtom(atoms[i])) {
159*4882a593Smuzhiyun             rc = BadAtom;
160*4882a593Smuzhiyun             client->errorValue = atoms[i];
161*4882a593Smuzhiyun             goto out;
162*4882a593Smuzhiyun         }
163*4882a593Smuzhiyun         for (j = i + 1; j < stuff->nAtoms; j++)
164*4882a593Smuzhiyun             if (atoms[j] == atoms[i]) {
165*4882a593Smuzhiyun                 rc = BadMatch;
166*4882a593Smuzhiyun                 goto out;
167*4882a593Smuzhiyun             }
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun         rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
170*4882a593Smuzhiyun                                DixReadAccess | DixWriteAccess);
171*4882a593Smuzhiyun         if (rc != Success)
172*4882a593Smuzhiyun             goto out;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun         props[i] = pProp;
175*4882a593Smuzhiyun         saved[i] = *pProp;
176*4882a593Smuzhiyun     }
177*4882a593Smuzhiyun     delta = stuff->nPositions;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun     /* If the rotation is a complete 360 degrees, then moving the properties
180*4882a593Smuzhiyun        around and generating PropertyNotify events should be skipped. */
181*4882a593Smuzhiyun 
182*4882a593Smuzhiyun     if (abs(delta) % stuff->nAtoms) {
183*4882a593Smuzhiyun         while (delta < 0)       /* faster if abs value is small */
184*4882a593Smuzhiyun             delta += stuff->nAtoms;
185*4882a593Smuzhiyun         for (i = 0; i < stuff->nAtoms; i++) {
186*4882a593Smuzhiyun             j = (i + delta) % stuff->nAtoms;
187*4882a593Smuzhiyun             deliverPropertyNotifyEvent(pWin, PropertyNewValue, props[i]);
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun             /* Preserve name and devPrivates */
190*4882a593Smuzhiyun             props[j]->type = saved[i].type;
191*4882a593Smuzhiyun             props[j]->format = saved[i].format;
192*4882a593Smuzhiyun             props[j]->size = saved[i].size;
193*4882a593Smuzhiyun             props[j]->data = saved[i].data;
194*4882a593Smuzhiyun         }
195*4882a593Smuzhiyun     }
196*4882a593Smuzhiyun  out:
197*4882a593Smuzhiyun     free(saved);
198*4882a593Smuzhiyun     free(props);
199*4882a593Smuzhiyun     return rc;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun int
ProcChangeProperty(ClientPtr client)203*4882a593Smuzhiyun ProcChangeProperty(ClientPtr client)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun     WindowPtr pWin;
206*4882a593Smuzhiyun     char format, mode;
207*4882a593Smuzhiyun     unsigned long len;
208*4882a593Smuzhiyun     int sizeInBytes, totalSize, err;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun     REQUEST(xChangePropertyReq);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
213*4882a593Smuzhiyun     UpdateCurrentTime();
214*4882a593Smuzhiyun     format = stuff->format;
215*4882a593Smuzhiyun     mode = stuff->mode;
216*4882a593Smuzhiyun     if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
217*4882a593Smuzhiyun         (mode != PropModePrepend)) {
218*4882a593Smuzhiyun         client->errorValue = mode;
219*4882a593Smuzhiyun         return BadValue;
220*4882a593Smuzhiyun     }
221*4882a593Smuzhiyun     if ((format != 8) && (format != 16) && (format != 32)) {
222*4882a593Smuzhiyun         client->errorValue = format;
223*4882a593Smuzhiyun         return BadValue;
224*4882a593Smuzhiyun     }
225*4882a593Smuzhiyun     len = stuff->nUnits;
226*4882a593Smuzhiyun     if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq)))
227*4882a593Smuzhiyun         return BadLength;
228*4882a593Smuzhiyun     sizeInBytes = format >> 3;
229*4882a593Smuzhiyun     totalSize = len * sizeInBytes;
230*4882a593Smuzhiyun     REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun     err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
233*4882a593Smuzhiyun     if (err != Success)
234*4882a593Smuzhiyun         return err;
235*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
236*4882a593Smuzhiyun         client->errorValue = stuff->property;
237*4882a593Smuzhiyun         return BadAtom;
238*4882a593Smuzhiyun     }
239*4882a593Smuzhiyun     if (!ValidAtom(stuff->type)) {
240*4882a593Smuzhiyun         client->errorValue = stuff->type;
241*4882a593Smuzhiyun         return BadAtom;
242*4882a593Smuzhiyun     }
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun     err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
245*4882a593Smuzhiyun                                   (int) format, (int) mode, len, &stuff[1],
246*4882a593Smuzhiyun                                   TRUE);
247*4882a593Smuzhiyun     if (err != Success)
248*4882a593Smuzhiyun         return err;
249*4882a593Smuzhiyun     else
250*4882a593Smuzhiyun         return Success;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun int
dixChangeWindowProperty(ClientPtr pClient,WindowPtr pWin,Atom property,Atom type,int format,int mode,unsigned long len,void * value,Bool sendevent)254*4882a593Smuzhiyun dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
255*4882a593Smuzhiyun                         Atom type, int format, int mode, unsigned long len,
256*4882a593Smuzhiyun                         void *value, Bool sendevent)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun     PropertyPtr pProp;
259*4882a593Smuzhiyun     PropertyRec savedProp;
260*4882a593Smuzhiyun     int sizeInBytes, totalSize, rc;
261*4882a593Smuzhiyun     unsigned char *data;
262*4882a593Smuzhiyun     Mask access_mode;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun     sizeInBytes = format >> 3;
265*4882a593Smuzhiyun     totalSize = len * sizeInBytes;
266*4882a593Smuzhiyun     access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun     /* first see if property already exists */
269*4882a593Smuzhiyun     rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun     if (rc == BadMatch) {       /* just add to list */
272*4882a593Smuzhiyun         if (!pWin->optional && !MakeWindowOptional(pWin))
273*4882a593Smuzhiyun             return BadAlloc;
274*4882a593Smuzhiyun         pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
275*4882a593Smuzhiyun         if (!pProp)
276*4882a593Smuzhiyun             return BadAlloc;
277*4882a593Smuzhiyun         data = malloc(totalSize);
278*4882a593Smuzhiyun         if (!data && len) {
279*4882a593Smuzhiyun             dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
280*4882a593Smuzhiyun             return BadAlloc;
281*4882a593Smuzhiyun         }
282*4882a593Smuzhiyun         memcpy(data, value, totalSize);
283*4882a593Smuzhiyun         pProp->propertyName = property;
284*4882a593Smuzhiyun         pProp->type = type;
285*4882a593Smuzhiyun         pProp->format = format;
286*4882a593Smuzhiyun         pProp->data = data;
287*4882a593Smuzhiyun         pProp->size = len;
288*4882a593Smuzhiyun         rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
289*4882a593Smuzhiyun                                     DixCreateAccess | DixWriteAccess);
290*4882a593Smuzhiyun         if (rc != Success) {
291*4882a593Smuzhiyun             free(data);
292*4882a593Smuzhiyun             dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
293*4882a593Smuzhiyun             pClient->errorValue = property;
294*4882a593Smuzhiyun             return rc;
295*4882a593Smuzhiyun         }
296*4882a593Smuzhiyun         pProp->next = pWin->optional->userProps;
297*4882a593Smuzhiyun         pWin->optional->userProps = pProp;
298*4882a593Smuzhiyun     }
299*4882a593Smuzhiyun     else if (rc == Success) {
300*4882a593Smuzhiyun         /* To append or prepend to a property the request format and type
301*4882a593Smuzhiyun            must match those of the already defined property.  The
302*4882a593Smuzhiyun            existing format and type are irrelevant when using the mode
303*4882a593Smuzhiyun            "PropModeReplace" since they will be written over. */
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun         if ((format != pProp->format) && (mode != PropModeReplace))
306*4882a593Smuzhiyun             return BadMatch;
307*4882a593Smuzhiyun         if ((pProp->type != type) && (mode != PropModeReplace))
308*4882a593Smuzhiyun             return BadMatch;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun         /* save the old values for later */
311*4882a593Smuzhiyun         savedProp = *pProp;
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun         if (mode == PropModeReplace) {
314*4882a593Smuzhiyun             data = malloc(totalSize);
315*4882a593Smuzhiyun             if (!data && len)
316*4882a593Smuzhiyun                 return BadAlloc;
317*4882a593Smuzhiyun             memcpy(data, value, totalSize);
318*4882a593Smuzhiyun             pProp->data = data;
319*4882a593Smuzhiyun             pProp->size = len;
320*4882a593Smuzhiyun             pProp->type = type;
321*4882a593Smuzhiyun             pProp->format = format;
322*4882a593Smuzhiyun         }
323*4882a593Smuzhiyun         else if (len == 0) {
324*4882a593Smuzhiyun             /* do nothing */
325*4882a593Smuzhiyun         }
326*4882a593Smuzhiyun         else if (mode == PropModeAppend) {
327*4882a593Smuzhiyun             data = xallocarray(pProp->size + len, sizeInBytes);
328*4882a593Smuzhiyun             if (!data)
329*4882a593Smuzhiyun                 return BadAlloc;
330*4882a593Smuzhiyun             memcpy(data, pProp->data, pProp->size * sizeInBytes);
331*4882a593Smuzhiyun             memcpy(data + pProp->size * sizeInBytes, value, totalSize);
332*4882a593Smuzhiyun             pProp->data = data;
333*4882a593Smuzhiyun             pProp->size += len;
334*4882a593Smuzhiyun         }
335*4882a593Smuzhiyun         else if (mode == PropModePrepend) {
336*4882a593Smuzhiyun             data = xallocarray(len + pProp->size, sizeInBytes);
337*4882a593Smuzhiyun             if (!data)
338*4882a593Smuzhiyun                 return BadAlloc;
339*4882a593Smuzhiyun             memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
340*4882a593Smuzhiyun             memcpy(data, value, totalSize);
341*4882a593Smuzhiyun             pProp->data = data;
342*4882a593Smuzhiyun             pProp->size += len;
343*4882a593Smuzhiyun         }
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun         /* Allow security modules to check the new content */
346*4882a593Smuzhiyun         access_mode |= DixPostAccess;
347*4882a593Smuzhiyun         rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode);
348*4882a593Smuzhiyun         if (rc == Success) {
349*4882a593Smuzhiyun             if (savedProp.data != pProp->data)
350*4882a593Smuzhiyun                 free(savedProp.data);
351*4882a593Smuzhiyun         }
352*4882a593Smuzhiyun         else {
353*4882a593Smuzhiyun             if (savedProp.data != pProp->data)
354*4882a593Smuzhiyun                 free(pProp->data);
355*4882a593Smuzhiyun             *pProp = savedProp;
356*4882a593Smuzhiyun             return rc;
357*4882a593Smuzhiyun         }
358*4882a593Smuzhiyun     }
359*4882a593Smuzhiyun     else
360*4882a593Smuzhiyun         return rc;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun     if (sendevent)
363*4882a593Smuzhiyun         deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp);
364*4882a593Smuzhiyun 
365*4882a593Smuzhiyun     return Success;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun int
DeleteProperty(ClientPtr client,WindowPtr pWin,Atom propName)369*4882a593Smuzhiyun DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
370*4882a593Smuzhiyun {
371*4882a593Smuzhiyun     PropertyPtr pProp, prevProp;
372*4882a593Smuzhiyun     int rc;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun     rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
375*4882a593Smuzhiyun     if (rc == BadMatch)
376*4882a593Smuzhiyun         return Success;         /* Succeed if property does not exist */
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun     if (rc == Success) {
379*4882a593Smuzhiyun         if (pWin->optional->userProps == pProp) {
380*4882a593Smuzhiyun             /* Takes care of head */
381*4882a593Smuzhiyun             if (!(pWin->optional->userProps = pProp->next))
382*4882a593Smuzhiyun                 CheckWindowOptionalNeed(pWin);
383*4882a593Smuzhiyun         }
384*4882a593Smuzhiyun         else {
385*4882a593Smuzhiyun             /* Need to traverse to find the previous element */
386*4882a593Smuzhiyun             prevProp = pWin->optional->userProps;
387*4882a593Smuzhiyun             while (prevProp->next != pProp)
388*4882a593Smuzhiyun                 prevProp = prevProp->next;
389*4882a593Smuzhiyun             prevProp->next = pProp->next;
390*4882a593Smuzhiyun         }
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun         deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
393*4882a593Smuzhiyun         free(pProp->data);
394*4882a593Smuzhiyun         dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
395*4882a593Smuzhiyun     }
396*4882a593Smuzhiyun     return rc;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun void
DeleteAllWindowProperties(WindowPtr pWin)400*4882a593Smuzhiyun DeleteAllWindowProperties(WindowPtr pWin)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun     PropertyPtr pProp, pNextProp;
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun     pProp = wUserProps(pWin);
405*4882a593Smuzhiyun     while (pProp) {
406*4882a593Smuzhiyun         deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
407*4882a593Smuzhiyun         pNextProp = pProp->next;
408*4882a593Smuzhiyun         free(pProp->data);
409*4882a593Smuzhiyun         dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
410*4882a593Smuzhiyun         pProp = pNextProp;
411*4882a593Smuzhiyun     }
412*4882a593Smuzhiyun 
413*4882a593Smuzhiyun     if (pWin->optional)
414*4882a593Smuzhiyun         pWin->optional->userProps = NULL;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun 
417*4882a593Smuzhiyun static int
NullPropertyReply(ClientPtr client,ATOM propertyType,int format)418*4882a593Smuzhiyun NullPropertyReply(ClientPtr client, ATOM propertyType, int format)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun     xGetPropertyReply reply = {
421*4882a593Smuzhiyun         .type = X_Reply,
422*4882a593Smuzhiyun         .format = format,
423*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
424*4882a593Smuzhiyun         .length = 0,
425*4882a593Smuzhiyun         .propertyType = propertyType,
426*4882a593Smuzhiyun         .bytesAfter = 0,
427*4882a593Smuzhiyun         .nItems = 0
428*4882a593Smuzhiyun     };
429*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xGenericReply), &reply);
430*4882a593Smuzhiyun     return Success;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun /*****************
434*4882a593Smuzhiyun  * GetProperty
435*4882a593Smuzhiyun  *    If type Any is specified, returns the property from the specified
436*4882a593Smuzhiyun  *    window regardless of its type.  If a type is specified, returns the
437*4882a593Smuzhiyun  *    property only if its type equals the specified type.
438*4882a593Smuzhiyun  *    If delete is True and a property is returned, the property is also
439*4882a593Smuzhiyun  *    deleted from the window and a PropertyNotify event is generated on the
440*4882a593Smuzhiyun  *    window.
441*4882a593Smuzhiyun  *****************/
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun int
ProcGetProperty(ClientPtr client)444*4882a593Smuzhiyun ProcGetProperty(ClientPtr client)
445*4882a593Smuzhiyun {
446*4882a593Smuzhiyun     PropertyPtr pProp, prevProp;
447*4882a593Smuzhiyun     unsigned long n, len, ind;
448*4882a593Smuzhiyun     int rc;
449*4882a593Smuzhiyun     WindowPtr pWin;
450*4882a593Smuzhiyun     xGetPropertyReply reply;
451*4882a593Smuzhiyun     Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun     REQUEST(xGetPropertyReq);
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xGetPropertyReq);
456*4882a593Smuzhiyun     if (stuff->delete) {
457*4882a593Smuzhiyun         UpdateCurrentTime();
458*4882a593Smuzhiyun         win_mode |= DixSetPropAccess;
459*4882a593Smuzhiyun         prop_mode |= DixDestroyAccess;
460*4882a593Smuzhiyun     }
461*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
462*4882a593Smuzhiyun     if (rc != Success)
463*4882a593Smuzhiyun         return rc;
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
466*4882a593Smuzhiyun         client->errorValue = stuff->property;
467*4882a593Smuzhiyun         return BadAtom;
468*4882a593Smuzhiyun     }
469*4882a593Smuzhiyun     if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) {
470*4882a593Smuzhiyun         client->errorValue = stuff->delete;
471*4882a593Smuzhiyun         return BadValue;
472*4882a593Smuzhiyun     }
473*4882a593Smuzhiyun     if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) {
474*4882a593Smuzhiyun         client->errorValue = stuff->type;
475*4882a593Smuzhiyun         return BadAtom;
476*4882a593Smuzhiyun     }
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun     rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
479*4882a593Smuzhiyun     if (rc == BadMatch)
480*4882a593Smuzhiyun         return NullPropertyReply(client, None, 0);
481*4882a593Smuzhiyun     else if (rc != Success)
482*4882a593Smuzhiyun         return rc;
483*4882a593Smuzhiyun 
484*4882a593Smuzhiyun     /* If the request type and actual type don't match. Return the
485*4882a593Smuzhiyun        property information, but not the data. */
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun     if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType))
488*4882a593Smuzhiyun         ) {
489*4882a593Smuzhiyun         reply = (xGetPropertyReply) {
490*4882a593Smuzhiyun             .type = X_Reply,
491*4882a593Smuzhiyun             .sequenceNumber = client->sequence,
492*4882a593Smuzhiyun             .bytesAfter = pProp->size,
493*4882a593Smuzhiyun             .format = pProp->format,
494*4882a593Smuzhiyun             .length = 0,
495*4882a593Smuzhiyun             .nItems = 0,
496*4882a593Smuzhiyun             .propertyType = pProp->type
497*4882a593Smuzhiyun         };
498*4882a593Smuzhiyun         WriteReplyToClient(client, sizeof(xGenericReply), &reply);
499*4882a593Smuzhiyun         return Success;
500*4882a593Smuzhiyun     }
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun /*
503*4882a593Smuzhiyun  *  Return type, format, value to client
504*4882a593Smuzhiyun  */
505*4882a593Smuzhiyun     n = (pProp->format / 8) * pProp->size;      /* size (bytes) of prop */
506*4882a593Smuzhiyun     ind = stuff->longOffset << 2;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun     /* If longOffset is invalid such that it causes "len" to
509*4882a593Smuzhiyun        be negative, it's a value error. */
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun     if (n < ind) {
512*4882a593Smuzhiyun         client->errorValue = stuff->longOffset;
513*4882a593Smuzhiyun         return BadValue;
514*4882a593Smuzhiyun     }
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun     len = min(n - ind, 4 * stuff->longLength);
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun     reply = (xGetPropertyReply) {
519*4882a593Smuzhiyun         .type = X_Reply,
520*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
521*4882a593Smuzhiyun         .bytesAfter = n - (ind + len),
522*4882a593Smuzhiyun         .format = pProp->format,
523*4882a593Smuzhiyun         .length = bytes_to_int32(len),
524*4882a593Smuzhiyun         .nItems = len / (pProp->format / 8),
525*4882a593Smuzhiyun         .propertyType = pProp->type
526*4882a593Smuzhiyun     };
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun     if (stuff->delete && (reply.bytesAfter == 0))
529*4882a593Smuzhiyun         deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp);
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xGenericReply), &reply);
532*4882a593Smuzhiyun     if (len) {
533*4882a593Smuzhiyun         switch (reply.format) {
534*4882a593Smuzhiyun         case 32:
535*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write;
536*4882a593Smuzhiyun             break;
537*4882a593Smuzhiyun         case 16:
538*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write;
539*4882a593Smuzhiyun             break;
540*4882a593Smuzhiyun         default:
541*4882a593Smuzhiyun             client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient;
542*4882a593Smuzhiyun             break;
543*4882a593Smuzhiyun         }
544*4882a593Smuzhiyun         WriteSwappedDataToClient(client, len, (char *) pProp->data + ind);
545*4882a593Smuzhiyun     }
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun     if (stuff->delete && (reply.bytesAfter == 0)) {
548*4882a593Smuzhiyun         /* Delete the Property */
549*4882a593Smuzhiyun         if (pWin->optional->userProps == pProp) {
550*4882a593Smuzhiyun             /* Takes care of head */
551*4882a593Smuzhiyun             if (!(pWin->optional->userProps = pProp->next))
552*4882a593Smuzhiyun                 CheckWindowOptionalNeed(pWin);
553*4882a593Smuzhiyun         }
554*4882a593Smuzhiyun         else {
555*4882a593Smuzhiyun             /* Need to traverse to find the previous element */
556*4882a593Smuzhiyun             prevProp = pWin->optional->userProps;
557*4882a593Smuzhiyun             while (prevProp->next != pProp)
558*4882a593Smuzhiyun                 prevProp = prevProp->next;
559*4882a593Smuzhiyun             prevProp->next = pProp->next;
560*4882a593Smuzhiyun         }
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun         free(pProp->data);
563*4882a593Smuzhiyun         dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
564*4882a593Smuzhiyun     }
565*4882a593Smuzhiyun     return Success;
566*4882a593Smuzhiyun }
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun int
ProcListProperties(ClientPtr client)569*4882a593Smuzhiyun ProcListProperties(ClientPtr client)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun     Atom *pAtoms = NULL, *temppAtoms;
572*4882a593Smuzhiyun     xListPropertiesReply xlpr;
573*4882a593Smuzhiyun     int rc, numProps = 0;
574*4882a593Smuzhiyun     WindowPtr pWin;
575*4882a593Smuzhiyun     PropertyPtr pProp, realProp;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun     REQUEST(xResourceReq);
578*4882a593Smuzhiyun 
579*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xResourceReq);
580*4882a593Smuzhiyun     rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
581*4882a593Smuzhiyun     if (rc != Success)
582*4882a593Smuzhiyun         return rc;
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
585*4882a593Smuzhiyun         numProps++;
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun     if (numProps && !(pAtoms = xallocarray(numProps, sizeof(Atom))))
588*4882a593Smuzhiyun         return BadAlloc;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun     numProps = 0;
591*4882a593Smuzhiyun     temppAtoms = pAtoms;
592*4882a593Smuzhiyun     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
593*4882a593Smuzhiyun         realProp = pProp;
594*4882a593Smuzhiyun         rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
595*4882a593Smuzhiyun         if (rc == Success && realProp == pProp) {
596*4882a593Smuzhiyun             *temppAtoms++ = pProp->propertyName;
597*4882a593Smuzhiyun             numProps++;
598*4882a593Smuzhiyun         }
599*4882a593Smuzhiyun     }
600*4882a593Smuzhiyun 
601*4882a593Smuzhiyun     xlpr = (xListPropertiesReply) {
602*4882a593Smuzhiyun         .type = X_Reply,
603*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
604*4882a593Smuzhiyun         .length = bytes_to_int32(numProps * sizeof(Atom)),
605*4882a593Smuzhiyun         .nProperties = numProps
606*4882a593Smuzhiyun     };
607*4882a593Smuzhiyun     WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
608*4882a593Smuzhiyun     if (numProps) {
609*4882a593Smuzhiyun         client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
610*4882a593Smuzhiyun         WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
611*4882a593Smuzhiyun     }
612*4882a593Smuzhiyun     free(pAtoms);
613*4882a593Smuzhiyun     return Success;
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun 
616*4882a593Smuzhiyun int
ProcDeleteProperty(ClientPtr client)617*4882a593Smuzhiyun ProcDeleteProperty(ClientPtr client)
618*4882a593Smuzhiyun {
619*4882a593Smuzhiyun     WindowPtr pWin;
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun     REQUEST(xDeletePropertyReq);
622*4882a593Smuzhiyun     int result;
623*4882a593Smuzhiyun 
624*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xDeletePropertyReq);
625*4882a593Smuzhiyun     UpdateCurrentTime();
626*4882a593Smuzhiyun     result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
627*4882a593Smuzhiyun     if (result != Success)
628*4882a593Smuzhiyun         return result;
629*4882a593Smuzhiyun     if (!ValidAtom(stuff->property)) {
630*4882a593Smuzhiyun         client->errorValue = stuff->property;
631*4882a593Smuzhiyun         return BadAtom;
632*4882a593Smuzhiyun     }
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun     return DeleteProperty(client, pWin, stuff->property);
635*4882a593Smuzhiyun }
636