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