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