Add support for .gnu_debuglink.
[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 "config.h"
22 #include "wine/port.h"
23
24 #include <stdarg.h>
25 #include <string.h>
26
27 #include "windef.h"
28 #include "winbase.h"
29 #include "wingdi.h"
30 #include "wownt32.h"
31 #include "wine/winuser16.h"
32 #include "wine/server.h"
33 #include "win.h"
34
35 /* size of buffer needed to store an atom string */
36 #define ATOM_BUFFER_SIZE 256
37
38
39 /***********************************************************************
40  *              get_properties
41  *
42  * Retrieve the list of properties of a given window.
43  * Returned buffer must be freed by caller.
44  */
45 static property_data_t *get_properties( HWND hwnd, int *count )
46 {
47     property_data_t *data;
48     int total = 32;
49
50     while (total)
51     {
52         int res = 0;
53         if (!(data = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*data) ))) break;
54         *count = 0;
55         SERVER_START_REQ( get_window_properties )
56         {
57             req->window = hwnd;
58             wine_server_add_data( req, data, total * sizeof(*data) );
59             if (!wine_server_call( req )) res = reply->total;
60         }
61         SERVER_END_REQ;
62         if (res && res <= total)
63         {
64             *count = res;
65             return data;
66         }
67         HeapFree( GetProcessHeap(), 0, data );
68         total = res;  /* restart with larger buffer */
69     }
70     return NULL;
71 }
72
73
74 /***********************************************************************
75  *              EnumPropsA_relay
76  *
77  * relay to call the EnumProps callback function from EnumPropsEx
78  */
79 static BOOL CALLBACK EnumPropsA_relay( HWND hwnd, LPCSTR str, HANDLE handle, ULONG_PTR lparam )
80 {
81     PROPENUMPROCA func = (PROPENUMPROCA)lparam;
82     return func( hwnd, str, handle );
83 }
84
85
86 /***********************************************************************
87  *              EnumPropsW_relay
88  *
89  * relay to call the EnumProps callback function from EnumPropsEx
90  */
91 static BOOL CALLBACK EnumPropsW_relay( HWND hwnd, LPCWSTR str, HANDLE handle, ULONG_PTR lparam )
92 {
93     PROPENUMPROCW func = (PROPENUMPROCW)lparam;
94     return func( hwnd, str, handle );
95 }
96
97
98 /***********************************************************************
99  *              EnumPropsA   (USER32.@)
100  */
101 INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func )
102 {
103     return EnumPropsExA( hwnd, EnumPropsA_relay, (LPARAM)func );
104 }
105
106
107 /***********************************************************************
108  *              EnumPropsW   (USER32.@)
109  */
110 INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func )
111 {
112     return EnumPropsExW( hwnd, EnumPropsW_relay, (LPARAM)func );
113 }
114
115
116 /***********************************************************************
117  *              GetPropA   (USER32.@)
118  */
119 HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
120 {
121     ATOM atom;
122     HANDLE ret = 0;
123
124     if (!HIWORD(str)) atom = LOWORD(str);
125     else if (!(atom = GlobalFindAtomA( str ))) return 0;
126
127     SERVER_START_REQ( get_window_property )
128     {
129         req->window = hwnd;
130         req->atom = atom;
131         if (!wine_server_call_err( req )) ret = reply->handle;
132     }
133     SERVER_END_REQ;
134     return ret;
135 }
136
137
138 /***********************************************************************
139  *              GetPropW   (USER32.@)
140  */
141 HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
142 {
143     ATOM atom;
144     HANDLE ret = 0;
145
146     if (!HIWORD(str)) atom = LOWORD(str);
147     else if (!(atom = GlobalFindAtomW( str ))) return 0;
148
149     SERVER_START_REQ( get_window_property )
150     {
151         req->window = hwnd;
152         req->atom = atom;
153         if (!wine_server_call_err( req )) ret = reply->handle;
154     }
155     SERVER_END_REQ;
156     return ret;
157 }
158
159
160 /***********************************************************************
161  *              SetPropA   (USER32.@)
162  */
163 BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
164 {
165     ATOM atom;
166     BOOL ret;
167
168     if (!HIWORD(str)) atom = LOWORD(str);
169     else if (!(atom = GlobalAddAtomA( str ))) return FALSE;
170
171     SERVER_START_REQ( set_window_property )
172     {
173         req->window = hwnd;
174         req->atom   = atom;
175         req->string = (HIWORD(str) != 0);
176         req->handle = handle;
177         ret = !wine_server_call_err( req );
178     }
179     SERVER_END_REQ;
180
181     if (HIWORD(str)) GlobalDeleteAtom( atom );
182     return ret;
183 }
184
185
186 /***********************************************************************
187  *              SetPropW   (USER32.@)
188  */
189 BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
190 {
191     ATOM atom;
192     BOOL ret;
193
194     if (!HIWORD(str)) atom = LOWORD(str);
195     else if (!(atom = GlobalAddAtomW( str ))) return FALSE;
196
197     SERVER_START_REQ( set_window_property )
198     {
199         req->window = hwnd;
200         req->atom   = atom;
201         req->string = (HIWORD(str) != 0);
202         req->handle = handle;
203         ret = !wine_server_call_err( req );
204     }
205     SERVER_END_REQ;
206
207     if (HIWORD(str)) GlobalDeleteAtom( atom );
208     return ret;
209 }
210
211
212 /***********************************************************************
213  *              RemovePropA   (USER32.@)
214  */
215 HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str )
216 {
217     ATOM atom;
218     HANDLE ret = 0;
219
220     if (!HIWORD(str)) return RemovePropW( hwnd, MAKEINTATOMW(LOWORD(str)) );
221
222     if ((atom = GlobalAddAtomA( str )))
223     {
224         ret = RemovePropW( hwnd, MAKEINTATOMW(atom) );
225         GlobalDeleteAtom( atom );
226     }
227     return ret;
228 }
229
230
231 /***********************************************************************
232  *              RemovePropW   (USER32.@)
233  */
234 HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
235 {
236     ATOM atom;
237     HANDLE ret = 0;
238
239     if (!HIWORD(str)) atom = LOWORD(str);
240     else if (!(atom = GlobalAddAtomW( str ))) return 0;
241
242     SERVER_START_REQ( remove_window_property )
243     {
244         req->window = hwnd;
245         req->atom   = atom;
246         if (!wine_server_call_err( req )) ret = reply->handle;
247     }
248     SERVER_END_REQ;
249
250     if (HIWORD(str)) GlobalDeleteAtom( atom );
251     return ret;
252 }
253
254
255 /***********************************************************************
256  *              EnumPropsExA   (USER32.@)
257  */
258 INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
259 {
260     int ret = -1, i, count;
261     property_data_t *list = get_properties( hwnd, &count );
262
263     if (list)
264     {
265         for (i = 0; i < count; i++)
266         {
267             char string[ATOM_BUFFER_SIZE];
268             if (!GlobalGetAtomNameA( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
269             if (!(ret = func( hwnd, string, list[i].handle, lParam ))) break;
270         }
271         HeapFree( GetProcessHeap(), 0, list );
272     }
273     return ret;
274 }
275
276
277 /***********************************************************************
278  *              EnumPropsExW   (USER32.@)
279  */
280 INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
281 {
282     int ret = -1, i, count;
283     property_data_t *list = get_properties( hwnd, &count );
284
285     if (list)
286     {
287         for (i = 0; i < count; i++)
288         {
289             WCHAR string[ATOM_BUFFER_SIZE];
290             if (!GlobalGetAtomNameW( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
291             if (!(ret = func( hwnd, string, list[i].handle, lParam ))) break;
292         }
293         HeapFree( GetProcessHeap(), 0, list );
294     }
295     return ret;
296 }
297
298
299 /***********************************************************************
300  *              EnumProps   (USER.27)
301  */
302 INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
303 {
304     int ret = -1, i, count;
305     property_data_t *list = get_properties( HWND_32(hwnd), &count );
306
307     if (list)
308     {
309         char string[ATOM_BUFFER_SIZE];
310         SEGPTR segptr = MapLS( string );
311         WORD args[4];
312         DWORD result;
313
314         for (i = 0; i < count; i++)
315         {
316             if (list[i].string)  /* it was a string originally */
317             {
318                 if (!GlobalGetAtomNameA( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
319                 args[3] = hwnd;
320                 args[2] = SELECTOROF(segptr);
321                 args[1] = OFFSETOF(segptr);
322                 args[0] = LOWORD(list[i].handle);
323             }
324             else
325             {
326                 args[3] = hwnd;
327                 args[2] = 0;
328                 args[1] = list[i].atom;
329                 args[0] = LOWORD(list[i].handle);
330             }
331             WOWCallback16Ex( (DWORD)func, WCB16_PASCAL, sizeof(args), args, &result );
332             if (!(ret = LOWORD(result))) break;
333         }
334         UnMapLS( segptr );
335         HeapFree( GetProcessHeap(), 0, list );
336     }
337     return ret;
338 }