user32: Don't flush window surfaces while waiting for a sent message reply.
[wine] / dlls / user32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 "winuser.h"
30 #include "wine/unicode.h"
31 #include "wine/server.h"
32
33 /* size of buffer needed to store an atom string */
34 #define ATOM_BUFFER_SIZE 256
35
36
37 /***********************************************************************
38  *              get_properties
39  *
40  * Retrieve the list of properties of a given window.
41  * Returned buffer must be freed by caller.
42  */
43 static property_data_t *get_properties( HWND hwnd, int *count )
44 {
45     property_data_t *data;
46     int total = 32;
47
48     while (total)
49     {
50         int res = 0;
51         if (!(data = HeapAlloc( GetProcessHeap(), 0, total * sizeof(*data) ))) break;
52         *count = 0;
53         SERVER_START_REQ( get_window_properties )
54         {
55             req->window = wine_server_user_handle( hwnd );
56             wine_server_set_reply( req, data, total * sizeof(*data) );
57             if (!wine_server_call( req )) res = reply->total;
58         }
59         SERVER_END_REQ;
60         if (res && res <= total)
61         {
62             *count = res;
63             return data;
64         }
65         HeapFree( GetProcessHeap(), 0, data );
66         total = res;  /* restart with larger buffer */
67     }
68     return NULL;
69 }
70
71
72 /***********************************************************************
73  *              EnumPropsA_relay
74  *
75  * relay to call the EnumProps callback function from EnumPropsEx
76  */
77 static BOOL CALLBACK EnumPropsA_relay( HWND hwnd, LPSTR str, HANDLE handle, ULONG_PTR lparam )
78 {
79     PROPENUMPROCA func = (PROPENUMPROCA)lparam;
80     return func( hwnd, str, handle );
81 }
82
83
84 /***********************************************************************
85  *              EnumPropsW_relay
86  *
87  * relay to call the EnumProps callback function from EnumPropsEx
88  */
89 static BOOL CALLBACK EnumPropsW_relay( HWND hwnd, LPWSTR str, HANDLE handle, ULONG_PTR lparam )
90 {
91     PROPENUMPROCW func = (PROPENUMPROCW)lparam;
92     return func( hwnd, str, handle );
93 }
94
95
96 /***********************************************************************
97  *              EnumPropsA   (USER32.@)
98  */
99 INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func )
100 {
101     return EnumPropsExA( hwnd, EnumPropsA_relay, (LPARAM)func );
102 }
103
104
105 /***********************************************************************
106  *              EnumPropsW   (USER32.@)
107  */
108 INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func )
109 {
110     return EnumPropsExW( hwnd, EnumPropsW_relay, (LPARAM)func );
111 }
112
113
114 /***********************************************************************
115  *              GetPropA   (USER32.@)
116  */
117 HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
118 {
119     WCHAR buffer[ATOM_BUFFER_SIZE];
120
121     if (IS_INTRESOURCE(str)) return GetPropW( hwnd, (LPCWSTR)str );
122     if (!MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, ATOM_BUFFER_SIZE )) return 0;
123     return GetPropW( hwnd, buffer );
124 }
125
126
127 /***********************************************************************
128  *              GetPropW   (USER32.@)
129  */
130 HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
131 {
132     ULONG_PTR ret = 0;
133
134     SERVER_START_REQ( get_window_property )
135     {
136         req->window = wine_server_user_handle( hwnd );
137         if (IS_INTRESOURCE(str)) req->atom = LOWORD(str);
138         else wine_server_add_data( req, str, strlenW(str) * sizeof(WCHAR) );
139         if (!wine_server_call_err( req )) ret = reply->data;
140     }
141     SERVER_END_REQ;
142     return (HANDLE)ret;
143 }
144
145
146 /***********************************************************************
147  *              SetPropA   (USER32.@)
148  */
149 BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
150 {
151     WCHAR buffer[ATOM_BUFFER_SIZE];
152
153     if (IS_INTRESOURCE(str)) return SetPropW( hwnd, (LPCWSTR)str, handle );
154     if (!MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, ATOM_BUFFER_SIZE )) return FALSE;
155     return SetPropW( hwnd, buffer, handle );
156 }
157
158
159 /***********************************************************************
160  *              SetPropW   (USER32.@)
161  */
162 BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
163 {
164     BOOL ret;
165
166     SERVER_START_REQ( set_window_property )
167     {
168         req->window = wine_server_user_handle( hwnd );
169         req->data   = (ULONG_PTR)handle;
170         if (IS_INTRESOURCE(str)) req->atom = LOWORD(str);
171         else wine_server_add_data( req, str, strlenW(str) * sizeof(WCHAR) );
172         ret = !wine_server_call_err( req );
173     }
174     SERVER_END_REQ;
175     return ret;
176 }
177
178
179 /***********************************************************************
180  *              RemovePropA   (USER32.@)
181  */
182 HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str )
183 {
184     WCHAR buffer[ATOM_BUFFER_SIZE];
185
186     if (IS_INTRESOURCE(str)) return RemovePropW( hwnd, (LPCWSTR)str );
187     if (!MultiByteToWideChar( CP_ACP, 0, str, -1, buffer, ATOM_BUFFER_SIZE )) return 0;
188     return RemovePropW( hwnd, buffer );
189 }
190
191
192 /***********************************************************************
193  *              RemovePropW   (USER32.@)
194  */
195 HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
196 {
197     ULONG_PTR ret = 0;
198
199     SERVER_START_REQ( remove_window_property )
200     {
201         req->window = wine_server_user_handle( hwnd );
202         if (IS_INTRESOURCE(str)) req->atom = LOWORD(str);
203         else wine_server_add_data( req, str, strlenW(str) * sizeof(WCHAR) );
204         if (!wine_server_call_err( req )) ret = reply->data;
205     }
206     SERVER_END_REQ;
207
208     return (HANDLE)ret;
209 }
210
211
212 /***********************************************************************
213  *              EnumPropsExA   (USER32.@)
214  */
215 INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
216 {
217     int ret = -1, i, count;
218     property_data_t *list = get_properties( hwnd, &count );
219
220     if (list)
221     {
222         for (i = 0; i < count; i++)
223         {
224             char string[ATOM_BUFFER_SIZE];
225             if (!GlobalGetAtomNameA( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
226             if (!(ret = func( hwnd, string, (HANDLE)(ULONG_PTR)list[i].data, lParam ))) break;
227         }
228         HeapFree( GetProcessHeap(), 0, list );
229     }
230     return ret;
231 }
232
233
234 /***********************************************************************
235  *              EnumPropsExW   (USER32.@)
236  */
237 INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
238 {
239     int ret = -1, i, count;
240     property_data_t *list = get_properties( hwnd, &count );
241
242     if (list)
243     {
244         for (i = 0; i < count; i++)
245         {
246             WCHAR string[ATOM_BUFFER_SIZE];
247             if (!GlobalGetAtomNameW( list[i].atom, string, ATOM_BUFFER_SIZE )) continue;
248             if (!(ret = func( hwnd, string, (HANDLE)(ULONG_PTR)list[i].data, lParam ))) break;
249         }
250         HeapFree( GetProcessHeap(), 0, list );
251     }
252     return ret;
253 }