Ordinal 342 is really named SHInterlockedCompareExchange.
[wine] / dlls / user / property.c
1 /*
2  * Window properties
3  *
4  * Copyright 1995, 1996, 2001 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <string.h>
22
23 #include "windef.h"
24 #include "wingdi.h"
25 #include "wine/winuser16.h"
26 #include "wine/server.h"
27
28 /* size of buffer needed to store an atom string */
29 #define ATOM_BUFFER_SIZE 256
30
31 /* ### start build ### */
32 extern WORD CALLBACK PROP_CallTo16_word_wlw(PROPENUMPROC16,WORD,LONG,WORD);
33 /* ### stop build ### */
34
35 /***********************************************************************
36  *              get_properties
37  *
38  * Retrieve the list of properties of a given window.
39  * Returned buffer must be freed by caller.
40  */
41 static property_data_t *get_properties( HWND hwnd, int *count )
42 {
43     property_data_t *data;
44     int total = 32;
45
46     while (total)
47     {
48         int res = 0;
49         if (!(data = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*data) ))) break;
50         *count = 0;
51         SERVER_START_REQ( get_window_properties )
52         {
53             req->window = hwnd;
54             wine_server_add_data( req, data, total * sizeof(*data) );
55             if (!wine_server_call( req )) res = reply->total;
56         }
57         SERVER_END_REQ;
58         if (res && res <= total)
59         {
60             *count = res;
61             return data;
62         }
63         HeapFree( GetProcessHeap(), 0, data );
64         total = res;  /* restart with larger buffer */
65     }
66     return NULL;
67 }
68
69
70 /***********************************************************************
71  *              EnumPropsA_relay
72  *
73  * relay to call the EnumProps callback function from EnumPropsEx
74  */
75 static BOOL CALLBACK EnumPropsA_relay( HWND hwnd, LPCSTR str, HANDLE handle, ULONG_PTR lparam )
76 {
77     PROPENUMPROCA func = (PROPENUMPROCA)lparam;
78     return func( hwnd, str, handle );
79 }
80
81
82 /***********************************************************************
83  *              EnumPropsW_relay
84  *
85  * relay to call the EnumProps callback function from EnumPropsEx
86  */
87 static BOOL CALLBACK EnumPropsW_relay( HWND hwnd, LPCWSTR str, HANDLE handle, ULONG_PTR lparam )
88 {
89     PROPENUMPROCW func = (PROPENUMPROCW)lparam;
90     return func( hwnd, str, handle );
91 }
92
93
94 /***********************************************************************
95  *              EnumPropsA   (USER32.@)
96  */
97 INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func )
98 {
99     return EnumPropsExA( hwnd, EnumPropsA_relay, (LPARAM)func );
100 }
101
102
103 /***********************************************************************
104  *              EnumPropsW   (USER32.@)
105  */
106 INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func )
107 {
108     return EnumPropsExW( hwnd, EnumPropsW_relay, (LPARAM)func );
109 }
110
111
112 /***********************************************************************
113  *              GetPropA   (USER32.@)
114  */
115 HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
116 {
117     ATOM atom;
118     HANDLE ret = 0;
119
120     if (!HIWORD(str)) atom = LOWORD(str);
121     else if (!(atom = GlobalFindAtomA( str ))) return 0;
122
123     SERVER_START_REQ( get_window_property )
124     {
125         req->window = hwnd;
126         req->atom = atom;
127         if (!wine_server_call_err( req )) ret = reply->handle;
128     }
129     SERVER_END_REQ;
130     return ret;
131 }
132
133
134 /***********************************************************************
135  *              GetPropW   (USER32.@)
136  */
137 HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
138 {
139     ATOM atom;
140     HANDLE ret = 0;
141
142     if (!HIWORD(str)) atom = LOWORD(str);
143     else if (!(atom = GlobalFindAtomW( str ))) return 0;
144
145     SERVER_START_REQ( get_window_property )
146     {
147         req->window = hwnd;
148         req->atom = atom;
149         if (!wine_server_call_err( req )) ret = reply->handle;
150     }
151     SERVER_END_REQ;
152     return ret;
153 }
154
155
156 /***********************************************************************
157  *              SetPropA   (USER32.@)
158  */
159 BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
160 {
161     ATOM atom;
162     BOOL ret;
163
164     if (!HIWORD(str)) atom = LOWORD(str);
165     else if (!(atom = GlobalAddAtomA( str ))) return FALSE;
166
167     SERVER_START_REQ( set_window_property )
168     {
169         req->window = hwnd;
170         req->atom   = atom;
171         req->string = (HIWORD(str) != 0);
172         req->handle = handle;
173         ret = !wine_server_call_err( req );
174     }
175     SERVER_END_REQ;
176
177     if (HIWORD(str)) GlobalDeleteAtom( atom );
178     return ret;
179 }
180
181
182 /***********************************************************************
183  *              SetPropW   (USER32.@)
184  */
185 BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
186 {
187     ATOM atom;
188     BOOL ret;
189
190     if (!HIWORD(str)) atom = LOWORD(str);
191     else if (!(atom = GlobalAddAtomW( str ))) return FALSE;
192
193     SERVER_START_REQ( set_window_property )
194     {
195         req->window = hwnd;
196         req->atom   = atom;
197         req->string = (HIWORD(str) != 0);
198         req->handle = handle;
199         ret = !wine_server_call_err( req );
200     }
201     SERVER_END_REQ;
202
203     if (HIWORD(str)) GlobalDeleteAtom( atom );
204     return ret;
205 }
206
207
208 /***********************************************************************
209  *              RemovePropA   (USER32.@)
210  */
211 HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str )
212 {
213     ATOM atom;
214     HANDLE ret = 0;
215
216     if (!HIWORD(str)) return RemovePropW( hwnd, MAKEINTATOMW(LOWORD(str)) );
217
218     if ((atom = GlobalAddAtomA( str )))
219     {
220         ret = RemovePropW( hwnd, MAKEINTATOMW(atom) );
221         GlobalDeleteAtom( atom );
222     }
223     return ret;
224 }
225
226
227 /***********************************************************************
228  *              RemovePropW   (USER32.@)
229  */
230 HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
231 {
232     ATOM atom;
233     HANDLE ret = 0;
234
235     if (!HIWORD(str)) atom = LOWORD(str);
236     else if (!(atom = GlobalAddAtomW( str ))) return 0;
237
238     SERVER_START_REQ( remove_window_property )
239     {
240         req->window = hwnd;
241         req->atom   = atom;
242         if (!wine_server_call_err( req )) ret = reply->handle;
243     }
244     SERVER_END_REQ;
245
246     if (HIWORD(str)) GlobalDeleteAtom( atom );
247     return ret;
248 }
249
250
251 /***********************************************************************
252  *              EnumPropsExA   (USER32.@)
253  */
254 INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
255 {
256     int ret = -1, i, count;
257     property_data_t *list = get_properties( hwnd, &count );
258
259     if (list)
260     {
261         for (i = 0; i < count; i++)
262         {
263             char string[ATOM_BUFFER_SIZE];
264             if (!GlobalGetAtomNameA( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
265             if (!(ret = func( hwnd, string, list[i].handle, lParam ))) break;
266         }
267         HeapFree( GetProcessHeap(), 0, list );
268     }
269     return ret;
270 }
271
272
273 /***********************************************************************
274  *              EnumPropsExW   (USER32.@)
275  */
276 INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
277 {
278     int ret = -1, i, count;
279     property_data_t *list = get_properties( hwnd, &count );
280
281     if (list)
282     {
283         for (i = 0; i < count; i++)
284         {
285             WCHAR string[ATOM_BUFFER_SIZE];
286             if (!GlobalGetAtomNameW( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
287             if (!(ret = func( hwnd, string, list[i].handle, lParam ))) break;
288         }
289         HeapFree( GetProcessHeap(), 0, list );
290     }
291     return ret;
292 }
293
294
295 /***********************************************************************
296  *              EnumProps   (USER.27)
297  */
298 INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
299 {
300     int ret = -1, i, count;
301     property_data_t *list = get_properties( hwnd, &count );
302
303     if (list)
304     {
305         char string[ATOM_BUFFER_SIZE];
306         SEGPTR segptr = MapLS( string );
307         for (i = 0; i < count; i++)
308         {
309             if (list[i].string)  /* it was a string originally */
310             {
311                 if (!GlobalGetAtomNameA( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
312                 ret = PROP_CallTo16_word_wlw( func, hwnd, segptr, list[i].handle );
313             }
314             else
315                 ret = PROP_CallTo16_word_wlw( func, hwnd, list[i].atom, list[i].handle );
316             if (!ret) break;
317         }
318         UnMapLS( segptr );
319         HeapFree( GetProcessHeap(), 0, list );
320     }
321     return ret;
322 }