Implementation of spawnl and spawnlp.
[wine] / windows / property.c
1 /*
2  * Window properties
3  *
4  * Copyright 1995, 1996 Alexandre Julliard
5  */
6
7 #include <string.h>
8
9 #include "windef.h"
10 #include "wingdi.h"
11 #include "wine/winuser16.h"
12 #include "win.h"
13 #include "heap.h"
14 #include "debugtools.h"
15
16 DEFAULT_DEBUG_CHANNEL(prop);
17
18
19 typedef struct tagPROPERTY
20 {
21     struct tagPROPERTY *next;     /* Next property in window list */
22     HANDLE            handle;   /* User's data */
23     LPSTR               string;   /* Property string (or atom) */
24 } PROPERTY;
25
26
27 /***********************************************************************
28  *           PROP_FindProp
29  */
30 static PROPERTY *PROP_FindProp( HWND hwnd, LPCSTR str )
31 {
32     ATOM atom;
33     PROPERTY *prop;
34     WND *pWnd = WIN_FindWndPtr( hwnd );
35
36     if (!pWnd) return NULL;
37     if (HIWORD(str))
38     {
39         atom = GlobalFindAtomA( str );
40         for (prop = pWnd->pProp; prop; prop = prop->next)
41         {
42             if (HIWORD(prop->string))
43             {
44                 if (!lstrcmpiA( prop->string, str )) goto END;
45             }
46             else if (LOWORD(prop->string) == atom) goto END;
47         }
48     }
49     else  /* atom */
50     {
51         atom = LOWORD(str);
52         for (prop = pWnd->pProp; (prop); prop = prop->next)
53         {
54             if (HIWORD(prop->string))
55             {
56                 if (GlobalFindAtomA( prop->string ) == atom) goto END;
57             }
58             else if (LOWORD(prop->string) == atom) goto END;
59         }
60     }
61     prop = NULL;
62 END:
63     WIN_ReleaseWndPtr(pWnd);
64     return prop;
65 }
66
67
68 /***********************************************************************
69  *              GetProp (USER.25)
70  */
71 HANDLE16 WINAPI GetProp16( HWND16 hwnd, LPCSTR str )
72 {
73     return (HANDLE16)GetPropA( hwnd, str );
74 }
75
76
77 /***********************************************************************
78  *              GetPropA (USER32.@)
79  */
80 HANDLE WINAPI GetPropA( HWND hwnd, LPCSTR str )
81 {
82     PROPERTY *prop = PROP_FindProp( hwnd, str );
83
84     if (HIWORD(str))
85         TRACE("(%08x,'%s'): returning %08x\n",
86                       hwnd, str, prop ? prop->handle : 0 );
87     else
88         TRACE("(%08x,#%04x): returning %08x\n",
89                       hwnd, LOWORD(str), prop ? prop->handle : 0 );
90
91     return prop ? prop->handle : 0;
92 }
93
94
95 /***********************************************************************
96  *              GetPropW (USER32.@)
97  */
98 HANDLE WINAPI GetPropW( HWND hwnd, LPCWSTR str )
99 {
100     LPSTR strA;
101     HANDLE ret;
102
103     if (!HIWORD(str)) return GetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str) );
104     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
105     ret = GetPropA( hwnd, strA );
106     HeapFree( GetProcessHeap(), 0, strA );
107     return ret;
108 }
109
110
111 /***********************************************************************
112  *              SetProp (USER.26)
113  */
114 BOOL16 WINAPI SetProp16( HWND16 hwnd, LPCSTR str, HANDLE16 handle )
115 {
116     return (BOOL16)SetPropA( hwnd, str, handle );
117 }
118
119
120 /***********************************************************************
121  *              SetPropA (USER32.@)
122  */
123 BOOL WINAPI SetPropA( HWND hwnd, LPCSTR str, HANDLE handle )
124 {
125     PROPERTY *prop;
126
127     if (HIWORD(str))
128         TRACE("%04x '%s' %08x\n", hwnd, str, handle );
129     else
130         TRACE("%04x #%04x %08x\n",
131                       hwnd, LOWORD(str), handle );
132
133     if (!(prop = PROP_FindProp( hwnd, str )))
134     {
135         /* We need to create it */
136         WND *pWnd = WIN_FindWndPtr( hwnd );
137         if (!pWnd) return FALSE;
138         if (!(prop = HeapAlloc( GetProcessHeap(), 0, sizeof(*prop) )))
139         {
140             WIN_ReleaseWndPtr(pWnd);
141             return FALSE;
142         }
143         if (!(prop->string = SEGPTR_STRDUP(str)))
144         {
145             HeapFree( GetProcessHeap(), 0, prop );
146             WIN_ReleaseWndPtr(pWnd);
147             return FALSE;
148
149         }
150         prop->next  = pWnd->pProp;
151         pWnd->pProp = prop;
152         WIN_ReleaseWndPtr(pWnd);
153     }
154     prop->handle = handle;
155     return TRUE;
156 }
157
158
159 /***********************************************************************
160  *              SetPropW (USER32.@)
161  */
162 BOOL WINAPI SetPropW( HWND hwnd, LPCWSTR str, HANDLE handle )
163 {
164     BOOL ret;
165     LPSTR strA;
166
167     if (!HIWORD(str))
168         return SetPropA( hwnd, (LPCSTR)(UINT)LOWORD(str), handle );
169     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
170     ret = SetPropA( hwnd, strA, handle );
171     HeapFree( GetProcessHeap(), 0, strA );
172     return ret;
173 }
174
175
176 /***********************************************************************
177  *              RemoveProp (USER.24)
178  */
179 HANDLE16 WINAPI RemoveProp16( HWND16 hwnd, LPCSTR str )
180 {
181     return (HANDLE16)RemovePropA( hwnd, str );
182 }
183
184
185 /***********************************************************************
186  *              RemovePropA (USER32.@)
187  */
188 HANDLE WINAPI RemovePropA( HWND hwnd, LPCSTR str )
189 {
190     ATOM atom;
191     HANDLE handle;
192     PROPERTY **pprop, *prop;
193     WND *pWnd = WIN_FindWndPtr( hwnd );
194
195     if (HIWORD(str))
196       TRACE("%04x '%s'\n", hwnd, str );
197     else
198       TRACE("%04x #%04x\n", hwnd, LOWORD(str));
199
200
201     if (!pWnd) return (HANDLE)0;
202     if (HIWORD(str))
203     {
204         atom = GlobalFindAtomA( str );
205         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
206         {
207             if (HIWORD((*pprop)->string))
208             {
209                 if (!lstrcmpiA( (*pprop)->string, str )) break;
210             }
211             else if (LOWORD((*pprop)->string) == atom) break;
212         }
213     }
214     else  /* atom */
215     {
216         atom = LOWORD(str);
217         for (pprop=(PROPERTY**)&pWnd->pProp; (*pprop); pprop = &(*pprop)->next)
218         {
219             if (HIWORD((*pprop)->string))
220             {
221                 if (GlobalFindAtomA( (*pprop)->string ) == atom) break;
222             }
223             else if (LOWORD((*pprop)->string) == atom) break;
224         }
225     }
226     WIN_ReleaseWndPtr(pWnd);
227     if (!*pprop) return 0;
228     prop   = *pprop;
229     handle = prop->handle;
230     *pprop = prop->next;
231     SEGPTR_FREE(prop->string);
232     HeapFree( GetProcessHeap(), 0, prop );
233     return handle;
234 }
235
236
237 /***********************************************************************
238  *              RemovePropW (USER32.@)
239  */
240 HANDLE WINAPI RemovePropW( HWND hwnd, LPCWSTR str )
241 {
242     LPSTR strA;
243     HANDLE ret;
244
245     if (!HIWORD(str))
246         return RemovePropA( hwnd, (LPCSTR)(UINT)LOWORD(str) );
247     strA = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
248     ret = RemovePropA( hwnd, strA );
249     HeapFree( GetProcessHeap(), 0, strA );
250     return ret;
251 }
252
253
254 /***********************************************************************
255  *           PROPERTY_RemoveWindowProps
256  *
257  * Remove all properties of a window.
258  */
259 void PROPERTY_RemoveWindowProps( WND *pWnd )
260 {
261     PROPERTY *prop, *next;
262
263     for (prop = pWnd->pProp; (prop); prop = next)
264     {
265         next = prop->next;
266         SEGPTR_FREE( prop->string );
267         HeapFree( GetProcessHeap(), 0, prop );
268     }
269     pWnd->pProp = NULL;
270 }
271
272
273 /***********************************************************************
274  *              EnumProps (USER.27)
275  */
276 INT16 WINAPI EnumProps16( HWND16 hwnd, PROPENUMPROC16 func )
277 {
278     PROPERTY *prop, *next;
279     WND *pWnd;
280     INT16 ret = -1;
281
282     TRACE("%04x %08x\n", hwnd, (UINT)func );
283     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
284     for (prop = pWnd->pProp; (prop); prop = next)
285     {
286         /* Already get the next in case the callback */
287         /* function removes the current property.    */
288         next = prop->next;
289
290         /* SDK docu seems to suggest that EnumProps16 does not retrieve
291          * the string in case of an atom handle, in contrast to Win32 */
292
293         TRACE("  Callback: handle=%08x str=%s\n",
294               prop->handle, debugstr_a(prop->string) );
295         ret = func( hwnd, SEGPTR_GET(prop->string), prop->handle );
296         if (!ret) break;
297     }
298     WIN_ReleaseWndPtr(pWnd);
299     return ret;
300 }
301
302
303 #define MAX_ATOM_LEN              255
304 static INT PROPS_EnumPropsA( HWND hwnd, PROPENUMPROCA func, LPARAM lParam, BOOL ex )
305 {
306     PROPERTY *prop, *next;
307     WND *pWnd;
308     INT ret = -1;
309     char atomStr[MAX_ATOM_LEN+1];
310     char *pStr;
311
312     TRACE("%04x %08x %08lx%s\n",
313                   hwnd, (UINT)func, lParam, ex ? " [Ex]" : "" );
314     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
315     for (prop = pWnd->pProp; (prop); prop = next)
316     {
317         /* Already get the next in case the callback */
318         /* function removes the current property.    */
319         next = prop->next;
320
321         if (!HIWORD(prop->string))
322         { /* get "real" string the atom points to.
323            * This seems to be done for Win32 only */
324             if (!(GlobalGetAtomNameA((ATOM)LOWORD(prop->string), atomStr, MAX_ATOM_LEN+1)))
325             {
326                 ERR("huh ? Atom %04x not an atom ??\n",
327                     (ATOM)LOWORD(prop->string));
328                 atomStr[0] = '\0';
329             }
330             pStr = atomStr;
331         }
332         else
333             pStr = prop->string;
334
335         TRACE("  Callback: handle=%08x str='%s'\n",
336             prop->handle, prop->string );
337
338         if (ex) /* EnumPropsEx has an additional lParam !! */
339             ret = func( hwnd, pStr, prop->handle, lParam );
340         else
341             ret = func( hwnd, pStr, prop->handle );
342         if (!ret) break;
343     }
344     WIN_ReleaseWndPtr(pWnd);
345     return ret;
346 }
347
348
349 /***********************************************************************
350  *              EnumPropsA (USER32.@)
351  */
352 INT WINAPI EnumPropsA( HWND hwnd, PROPENUMPROCA func )
353 {
354     return PROPS_EnumPropsA(hwnd, func, 0, FALSE);
355 }
356
357
358 /***********************************************************************
359  *              EnumPropsExA (USER32.@)
360  */
361 INT WINAPI EnumPropsExA(HWND hwnd, PROPENUMPROCEXA func, LPARAM lParam)
362 {
363     return PROPS_EnumPropsA(hwnd, (PROPENUMPROCA)func, lParam, TRUE);
364 }
365
366
367 static INT PROPS_EnumPropsW( HWND hwnd, PROPENUMPROCW func, LPARAM lParam, BOOL ex )
368 {
369     PROPERTY *prop, *next;
370     WND *pWnd;
371     INT ret = -1;
372     char atomStr[MAX_ATOM_LEN+1];
373     char *pStr;
374     LPWSTR strW;
375
376     TRACE("%04x %08x %08lx%s\n",
377                   hwnd, (UINT)func, lParam, ex ? " [Ex]" : "" );
378     if (!(pWnd = WIN_FindWndPtr( hwnd ))) return -1;
379     for (prop = pWnd->pProp; (prop); prop = next)
380     {
381         /* Already get the next in case the callback */
382         /* function removes the current property.    */
383         next = prop->next;
384
385         if (!HIWORD(prop->string))
386         { /* get "real" string the atom points to.
387            * This seems to be done for Win32 only */
388             if (!(GlobalGetAtomNameA((ATOM)LOWORD(prop->string), atomStr, MAX_ATOM_LEN+1)))
389             {
390                 ERR("huh ? Atom %04x not an atom ??\n",
391                     (ATOM)LOWORD(prop->string));
392                 atomStr[0] = '\0';
393             }
394             pStr = atomStr;
395         }
396         else
397             pStr = prop->string;
398
399         TRACE("  Callback: handle=%08x str='%s'\n",
400             prop->handle, prop->string );
401
402         strW = HEAP_strdupAtoW( GetProcessHeap(), 0, pStr );
403
404         if (ex) /* EnumPropsEx has an additional lParam !! */
405             ret = func( hwnd, strW, prop->handle, lParam );
406         else
407             ret = func( hwnd, strW, prop->handle );
408         HeapFree( GetProcessHeap(), 0, strW );
409         if (!ret) break;
410     }
411     WIN_ReleaseWndPtr(pWnd);
412     return ret;
413 }
414
415
416 /***********************************************************************
417  *              EnumPropsW (USER32.@)
418  */
419 INT WINAPI EnumPropsW( HWND hwnd, PROPENUMPROCW func )
420 {
421     return PROPS_EnumPropsW(hwnd, func, 0, FALSE);
422 }
423
424 /***********************************************************************
425  *              EnumPropsExW (USER32.@)
426  */
427 INT WINAPI EnumPropsExW(HWND hwnd, PROPENUMPROCEXW func, LPARAM lParam)
428 {
429     return PROPS_EnumPropsW(hwnd, (PROPENUMPROCW)func, 0, TRUE);
430 }