1 /*
2 * Window related functions
3 *
4 * Copyright 1993, 1994 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 <assert.h>
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
32 #include "wownt32.h"
33 #include "wine/server.h"
34 #include "wine/unicode.h"
35 #include "win.h"
36 #include "user_private.h"
37 #include "controls.h"
38 #include "winerror.h"
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(win);
42
43 #define NB_USER_HANDLES ((LAST_USER_HANDLE - FIRST_USER_HANDLE + 1) >> 1)
44 #define USER_HANDLE_TO_INDEX(hwnd) ((LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1)
45
46 /**********************************************************************/
47
48 /* helper for Get/SetWindowLong */
49 static inline LONG_PTR get_win_data( const void *ptr, UINT size )
50 {
51 if (size == sizeof(WORD))
52 {
53 WORD ret;
54 memcpy( &ret, ptr, sizeof(ret) );
55 return ret;
56 }
57 else if (size == sizeof(DWORD))
58 {
59 DWORD ret;
60 memcpy( &ret, ptr, sizeof(ret) );
61 return ret;
62 }
63 else
64 {
65 LONG_PTR ret;
66 memcpy( &ret, ptr, sizeof(ret) );
67 return ret;
68 }
69 }
70
71 /* helper for Get/SetWindowLong */
72 static inline void set_win_data( void *ptr, LONG_PTR val, UINT size )
73 {
74 if (size == sizeof(WORD))
75 {
76 WORD newval = val;
77 memcpy( ptr, &newval, sizeof(newval) );
78 }
79 else if (size == sizeof(DWORD))
80 {
81 DWORD newval = val;
82 memcpy( ptr, &newval, sizeof(newval) );
83 }
84 else
85 {
86 memcpy( ptr, &val, sizeof(val) );
87 }
88 }
89
90
91 static void *user_handles[NB_USER_HANDLES];
92
93 /***********************************************************************
94 * create_window_handle
95 *
96 * Create a window handle with the server.
97 */
98 static WND *create_window_handle( HWND parent, HWND owner, LPCWSTR name,
99 HINSTANCE instance, BOOL unicode )
100 {
101 WORD index;
102 WND *win;
103 HWND full_parent = 0, full_owner = 0;
104 struct tagCLASS *class = NULL;
105 user_handle_t handle = 0;
106 int extra_bytes = 0;
107
108 /* if 16-bit instance, map to module handle */
109 if (instance && !HIWORD(instance))
110 instance = HINSTANCE_32(GetExePtr(HINSTANCE_16(instance)));
111
112 SERVER_START_REQ( create_window )
113 {
114 req->parent = parent;
115 req->owner = owner;
116 req->instance = instance;
117 if (!(req->atom = get_int_atom_value( name )) && name)
118 wine_server_add_data( req, name, strlenW(name)*sizeof(WCHAR) );
119 if (!wine_server_call_err( req ))
120 {
121 handle = reply->handle;
122 full_parent = reply->parent;
123 full_owner = reply->owner;
124 extra_bytes = reply->extra;
125 class = reply->class_ptr;
126 }
127 }
128 SERVER_END_REQ;
129
130 if (!handle)
131 {
132 WARN( "error %d creating window\n", GetLastError() );
133 return NULL;
134 }
135
136 if (!(win = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
137 sizeof(WND) + extra_bytes - sizeof(win->wExtra) )))
138 {
139 SERVER_START_REQ( destroy_window )
140 {
141 req->handle = handle;
142 wine_server_call( req );
143 }
144 SERVER_END_REQ;
145 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
146 return NULL;
147 }
148
149 if (!parent) /* if parent is 0 we don't have a desktop window yet */
150 {
151 struct user_thread_info *thread_info = get_user_thread_info();
152
153 if (!thread_info->desktop) thread_info->desktop = full_parent ? full_parent : handle;
154 else assert( full_parent == thread_info->desktop );
155 if (full_parent && !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
156 ERR( "failed to create desktop window\n" );
157 }
158
159 USER_Lock();
160
161 index = USER_HANDLE_TO_INDEX(handle);
162 assert( index < NB_USER_HANDLES );
163 user_handles[index] = win;
164 win->hwndSelf = handle;
165 win->parent = full_parent;
166 win->owner = full_owner;
167 win->class = class;
168 win->winproc = get_class_winproc( class );
169 win->dwMagic = WND_MAGIC;
170 win->cbWndExtra = extra_bytes;
171 if (WINPROC_IsUnicode( win->winproc, unicode )) win->flags |= WIN_ISUNICODE;
172 return win;
173 }
174
175
176 /***********************************************************************
177 * free_window_handle
178 *
179 * Free a window handle.
180 */
181 static WND *free_window_handle( HWND hwnd )
182 {
183 WND *ptr;
184 WORD index = USER_HANDLE_TO_INDEX(hwnd);
185
186 if (index >= NB_USER_HANDLES) return NULL;
187 USER_Lock();
188 if ((ptr = user_handles[index]))
189 {
190 SERVER_START_REQ( destroy_window )
191 {
192 req->handle = hwnd;
193 if (!wine_server_call_err( req ))
194 {
195 user_handles[index] = NULL;
196 ptr->dwMagic = 0;
197 }
198 else
199 ptr = NULL;
200 }
201 SERVER_END_REQ;
202 }
203 USER_Unlock();
204 HeapFree( GetProcessHeap(), 0, ptr );
205 return ptr;
206 }
207
208
209 /*******************************************************************
210 * list_window_children
211 *
212 * Build an array of the children of a given window. The array must be
213 * freed with HeapFree. Returns NULL when no windows are found.
214 */
215 static HWND *list_window_children( HDESK desktop, HWND hwnd, LPCWSTR class, DWORD tid )
216 {
217 HWND *list;
218 int size = 128;
219
220 for (;;)
221 {
222 int count = 0;
223
224 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) break;
225
226 SERVER_START_REQ( get_window_children )
227 {
228 req->desktop = desktop;
229 req->parent = hwnd;
230 req->tid = tid;
231 if (!(req->atom = get_int_atom_value( class )) && class)
232 wine_server_add_data( req, class, strlenW(class)*sizeof(WCHAR) );
233 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
234 if (!wine_server_call( req )) count = reply->count;
235 }
236 SERVER_END_REQ;
237 if (count && count < size)
238 {
239 list[count] = 0;
240 return list;
241 }
242 HeapFree( GetProcessHeap(), 0, list );
243 if (!count) break;
244 size = count + 1; /* restart with a large enough buffer */
245 }
246 return NULL;
247 }
248
249
250 /*******************************************************************
251 * list_window_parents
252 *
253 * Build an array of all parents of a given window, starting with
254 * the immediate parent. The array must be freed with HeapFree.
255 */
256 static HWND *list_window_parents( HWND hwnd )
257 {
258 WND *win;
259 HWND current, *list;
260 int pos = 0, size = 16, count = 0;
261
262 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
263
264 current = hwnd;
265 for (;;)
266 {
267 if (!(win = WIN_GetPtr( current ))) goto empty;
268 if (win == WND_OTHER_PROCESS) break; /* need to do it the hard way */
269 if (win == WND_DESKTOP)
270 {
271 if (!pos) goto empty;
272 list[pos] = 0;
273 return list;
274 }
275 list[pos] = current = win->parent;
276 WIN_ReleasePtr( win );
277 if (!current) return list;
278 if (++pos == size - 1)
279 {
280 /* need to grow the list */
281 HWND *new_list = HeapReAlloc( GetProcessHeap(), 0, list, (size+16) * sizeof(HWND) );
282 if (!new_list) goto empty;
283 list = new_list;
284 size += 16;
285 }
286 }
287
288 /* at least one parent belongs to another process, have to query the server */
289
290 for (;;)
291 {
292 count = 0;
293 SERVER_START_REQ( get_window_parents )
294 {
295 req->handle = hwnd;
296 wine_server_set_reply( req, list, (size-1) * sizeof(HWND) );
297 if (!wine_server_call( req )) count = reply->count;
298 }
299 SERVER_END_REQ;
300 if (!count) goto empty;
301 if (size > count)
302 {
303 list[count] = 0;
304 return list;
305 }
306 HeapFree( GetProcessHeap(), 0, list );
307 size = count + 1;
308 if (!(list = HeapAlloc( GetProcessHeap(), 0, size * sizeof(HWND) ))) return NULL;
309 }
310
311 empty:
312 HeapFree( GetProcessHeap(), 0, list );
313 return NULL;
314 }
315
316
317 /*******************************************************************
318 * send_parent_notify
319 */
320 static void send_parent_notify( HWND hwnd, UINT msg )
321 {
322 if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_CHILD | WS_POPUP)) == WS_CHILD &&
323 !(GetWindowLongW( hwnd, GWL_EXSTYLE ) & WS_EX_NOPARENTNOTIFY))
324 {
325 HWND parent = GetParent(hwnd);
326 if (parent && parent != GetDesktopWindow())
327 SendMessageW( parent, WM_PARENTNOTIFY,
328 MAKEWPARAM( msg, GetWindowLongPtrW( hwnd, GWLP_ID )), (LPARAM)hwnd );
329 }
330 }
331
332
333 /*******************************************************************
334 * get_server_window_text
335 *
336 * Retrieve the window text from the server.
337 */
338 static void get_server_window_text( HWND hwnd, LPWSTR text, INT count )
339 {
340 size_t len = 0;
341
342 SERVER_START_REQ( get_window_text )
343 {
344 req->handle = hwnd;
345 wine_server_set_reply( req, text, (count - 1) * sizeof(WCHAR) );
346 if (!wine_server_call_err( req )) len = wine_server_reply_size(reply);
347 }
348 SERVER_END_REQ;
349 text[len / sizeof(WCHAR)] = 0;
350 }
351
352
353 /***********************************************************************
354 * WIN_GetPtr
355 *
356 * Return a pointer to the WND structure if local to the process,
357 * or WND_OTHER_PROCESS if handle may be valid in other process.
358 * If ret value is a valid pointer, it must be released with WIN_ReleasePtr.
359 */
360 WND *WIN_GetPtr( HWND hwnd )
361 {
362 WND * ptr;
363 WORD index = USER_HANDLE_TO_INDEX(hwnd);
364
365 if (index >= NB_USER_HANDLES) return NULL;
366
367 USER_Lock();
368 if ((ptr = user_handles[index]))
369 {
370 if (ptr->dwMagic == WND_MAGIC &&
371 (hwnd == ptr->hwndSelf || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff))
372 return ptr;
373 ptr = NULL;
374 }
375 else if (index == USER_HANDLE_TO_INDEX(GetDesktopWindow()))
376 {
377 if (hwnd == GetDesktopWindow() || !HIWORD(hwnd) || HIWORD(hwnd) == 0xffff) ptr = WND_DESKTOP;
378 else ptr = NULL;
379 }
380 else ptr = WND_OTHER_PROCESS;
381 USER_Unlock();
382 return ptr;
383 }
384
385
386 /***********************************************************************
387 * WIN_IsCurrentProcess
388 *
389 * Check whether a given window belongs to the current process (and return the full handle).
390 */
391 HWND WIN_IsCurrentProcess( HWND hwnd )
392 {
393 WND *ptr;
394 HWND ret;
395
396 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
397 ret = ptr->hwndSelf;
398 WIN_ReleasePtr( ptr );
399 return ret;
400 }
401
402
403 /***********************************************************************
404 * WIN_IsCurrentThread
405 *
406 * Check whether a given window belongs to the current thread (and return the full handle).
407 */
408 HWND WIN_IsCurrentThread( HWND hwnd )
409 {
410 WND *ptr;
411 HWND ret = 0;
412
413 if (!(ptr = WIN_GetPtr( hwnd )) || ptr == WND_OTHER_PROCESS || ptr == WND_DESKTOP) return 0;
414 if (ptr->tid == GetCurrentThreadId()) ret = ptr->hwndSelf;
415 WIN_ReleasePtr( ptr );
416 return ret;
417 }
418
419
420 /***********************************************************************
421 * WIN_Handle32
422 *
423 * Convert a 16-bit window handle to a full 32-bit handle.
424 */
425 HWND WIN_Handle32( HWND16 hwnd16 )
426 {
427 WND *ptr;
428 HWND hwnd = (HWND)(ULONG_PTR)hwnd16;
429
430 if (hwnd16 <= 1 || hwnd16 == 0xffff) return hwnd;
431 /* do sign extension for -2 and -3 */
432 if (hwnd16 >= (HWND16)-3) return (HWND)(LONG_PTR)(INT16)hwnd16;
433
434 if (!(ptr = WIN_GetPtr( hwnd ))) return hwnd;
435
436 if (ptr == WND_DESKTOP) return GetDesktopWindow();
437
438 if (ptr != WND_OTHER_PROCESS)
439 {
440 hwnd = ptr->hwndSelf;
441 WIN_ReleasePtr( ptr );
442 }
443 else /* may belong to another process */
444 {
445 SERVER_START_REQ( get_window_info )
446 {
447 req->handle = hwnd;
448 if (!wine_server_call_err( req )) hwnd = reply->full_handle;
449 }
450 SERVER_END_REQ;
451 }
452 return hwnd;
453 }
454
455
456 /***********************************************************************
457 * WIN_SetOwner
458 *
459 * Change the owner of a window.
460 */
461 HWND WIN_SetOwner( HWND hwnd, HWND owner )
462 {
463 WND *win = WIN_GetPtr( hwnd );
464 HWND ret = 0;
465
466 if (!win || win == WND_DESKTOP) return 0;
467 if (win == WND_OTHER_PROCESS)
468 {
469 if (IsWindow(hwnd)) ERR( "cannot set owner %p on other process window %p\n", owner, hwnd );
470 return 0;
471 }
472 SERVER_START_REQ( set_window_owner )
473 {
474 req->handle = hwnd;
475 req->owner = owner;
476 if (!wine_server_call( req ))
477 {
478 win->owner = reply->full_owner;
479 ret = reply->prev_owner;
480 }
481 }
482 SERVER_END_REQ;
483 WIN_ReleasePtr( win );
484 return ret;
485 }
486
487
488 /***********************************************************************
489 * WIN_SetStyle
490 *
491 * Change the style of a window.
492 */
493 ULONG WIN_SetStyle( HWND hwnd, ULONG set_bits, ULONG clear_bits )
494 {
495 BOOL ok;
496 ULONG new_style, old_style = 0;
497 WND *win = WIN_GetPtr( hwnd );
498
499 if (!win || win == WND_DESKTOP) return 0;
500 if (win == WND_OTHER_PROCESS)
501 {
502 if (IsWindow(hwnd))
503 ERR( "cannot set style %x/%x on other process window %p\n",
504 set_bits, clear_bits, hwnd );
505 return 0;
506 }
507 new_style = (win->dwStyle | set_bits) & ~clear_bits;
508 if (new_style == win->dwStyle)
509 {
510 WIN_ReleasePtr( win );
511 return new_style;
512 }
513 SERVER_START_REQ( set_window_info )
514 {
515 req->handle = hwnd;
516 req->flags = SET_WIN_STYLE;
517 req->style = new_style;
518 req->extra_offset = -1;
519 if ((ok = !wine_server_call( req )))
520 {
521 old_style = reply->old_style;
522 win->dwStyle = new_style;
523 }
524 }
525 SERVER_END_REQ;
526 WIN_ReleasePtr( win );
527 if (ok)
528 {
529 USER_Driver->pSetWindowStyle( hwnd, old_style );
530 if ((old_style ^ new_style) & WS_VISIBLE) invalidate_dce( hwnd, NULL );
531 }
532 return old_style;
533 }
534
535
536 /***********************************************************************
537 * WIN_GetRectangles
538 *
539 * Get the window and client rectangles.
540 */
541 BOOL WIN_GetRectangles( HWND hwnd, RECT *rectWindow, RECT *rectClient )
542 {
543 WND *win = WIN_GetPtr( hwnd );
544 BOOL ret = TRUE;
545
546 if (!win) return FALSE;
547 if (win == WND_DESKTOP)
548 {
549 RECT rect;
550 rect.left = rect.top = 0;
551 rect.right = GetSystemMetrics(SM_CXSCREEN);
552 rect.bottom = GetSystemMetrics(SM_CYSCREEN);
553 if (rectWindow) *rectWindow = rect;
554 if (rectClient) *rectClient = rect;
555 }
556 else if (win == WND_OTHER_PROCESS)
557 {
558 SERVER_START_REQ( get_window_rectangles )
559 {
560 req->handle = hwnd;
561 if ((ret = !wine_server_call( req )))
562 {
563 if (rectWindow)
564 {
565 rectWindow->left = reply->window.left;
566 rectWindow->top = reply->window.top;
567 rectWindow->right = reply->window.right;
568 rectWindow->bottom = reply->window.bottom;
569 }
570 if (rectClient)
571 {
572 rectClient->left = reply->client.left;
573 rectClient->top = reply->client.top;
574 rectClient->right = reply->client.right;
575 rectClient->bottom = reply->client.bottom;
576 }
577 }
578 }
579 SERVER_END_REQ;
580 }
581 else
582 {
583 if (rectWindow) *rectWindow = win->rectWindow;
584 if (rectClient) *rectClient = win->rectClient;
585 WIN_ReleasePtr( win );
586 }
587 return ret;
588 }
589
590
591 /***********************************************************************
592 * WIN_DestroyWindow
593 *
594 * Destroy storage associated to a window. "Internals" p.358
595 */
596 LRESULT WIN_DestroyWindow( HWND hwnd )
597 {
598 WND *wndPtr;
599 HWND *list;
600 HMENU menu = 0, sys_menu;
601 HWND icon_title;
602
603 TRACE("%p\n", hwnd );
604
605 /* free child windows */
606 if ((list = WIN_ListChildren( hwnd )))
607 {
608 int i;
609 for (i = 0; list[i]; i++)
610 {
611 if (WIN_IsCurrentThread( list[i] )) WIN_DestroyWindow( list[i] );
612 else SendMessageW( list[i], WM_WINE_DESTROYWINDOW, 0, 0 );
613 }
614 HeapFree( GetProcessHeap(), 0, list );
615 }
616
617 /* Unlink now so we won't bother with the children later on */
618 SERVER_START_REQ( set_parent )
619 {
620 req->handle = hwnd;
621 req->parent = 0;
622 wine_server_call( req );
623 }
624 SERVER_END_REQ;
625
626 /*
627 * Send the WM_NCDESTROY to the window being destroyed.
628 */
629 SendMessageW( hwnd, WM_NCDESTROY, 0, 0 );
630
631 /* FIXME: do we need to fake QS_MOUSEMOVE wakebit? */
632
633 /* free resources associated with the window */
634
635 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
636 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
637 menu = (HMENU)wndPtr->wIDmenu;
638 sys_menu = wndPtr->hSysMenu;
639 free_dce( wndPtr->dce, hwnd );
640 wndPtr->dce = NULL;
641 icon_title = wndPtr->icon_title;
642 WIN_ReleasePtr( wndPtr );
643
644 if (icon_title) DestroyWindow( icon_title );
645 if (menu) DestroyMenu( menu );
646 if (sys_menu) DestroyMenu( sys_menu );
647
648 USER_Driver->pDestroyWindow( hwnd );
649
650 free_window_handle( hwnd );
651 return 0;
652 }
653
654 /***********************************************************************
655 * WIN_DestroyThreadWindows
656 *
657 * Destroy all children of 'wnd' owned by the current thread.
658 */
659 void WIN_DestroyThreadWindows( HWND hwnd )
660 {
661 HWND *list;
662 int i;
663
664 if (!(list = WIN_ListChildren( hwnd ))) return;
665 for (i = 0; list[i]; i++)
666 {
667 if (WIN_IsCurrentThread( list[i] ))
668 DestroyWindow( list[i] );
669 else
670 WIN_DestroyThreadWindows( list[i] );
671 }
672 HeapFree( GetProcessHeap(), 0, list );
673 }
674
675
676 /***********************************************************************
677 * WIN_FixCoordinates
678 *
679 * Fix the coordinates - Helper for WIN_CreateWindowEx.
680 * returns default show mode in sw.
681 */
682 static void WIN_FixCoordinates( CREATESTRUCTA *cs, INT *sw)
683 {
684 #define IS_DEFAULT(x) ((x) == CW_USEDEFAULT || (x) == CW_USEDEFAULT16)
685 POINT pos[2];
686
687 if (cs->dwExStyle & WS_EX_MDICHILD)
688 {
689 UINT id = 0;
690
691 MDI_CalcDefaultChildPos(cs->hwndParent, -1, pos, 0, &id);
692 if (!(cs->style & WS_POPUP)) cs->hMenu = ULongToHandle(id);
693
694 TRACE("MDI child id %04x\n", id);
695 }
696
697 if (cs->style & (WS_CHILD | WS_POPUP))
698 {
699 if (cs->dwExStyle & WS_EX_MDICHILD)
700 {
701 if (IS_DEFAULT(cs->x))
702 {
703 cs->x = pos[0].x;
704 cs->y = pos[0].y;
705 }
706 if (IS_DEFAULT(cs->cx) || !cs->cx) cs->cx = pos[1].x;
707 if (IS_DEFAULT(cs->cy) || !cs->cy) cs->cy = pos[1].y;
708 }
709 else
710 {
711 if (IS_DEFAULT(cs->x)) cs->x = cs->y = 0;
712 if (IS_DEFAULT(cs->cx)) cs->cx = cs->cy = 0;
713 }
714 }
715 else /* overlapped window */
716 {
717 HMONITOR monitor;
718 MONITORINFO mon_info;
719 STARTUPINFOW info;
720
721 if (!IS_DEFAULT(cs->x) && !IS_DEFAULT(cs->cx) && !IS_DEFAULT(cs->cy)) return;
722
723 monitor = MonitorFromWindow( cs->hwndParent, MONITOR_DEFAULTTOPRIMARY );
724 mon_info.cbSize = sizeof(mon_info);
725 GetMonitorInfoW( monitor, &mon_info );
726 GetStartupInfoW( &info );
727
728 if (IS_DEFAULT(cs->x))
729 {
730 if (!IS_DEFAULT(cs->y)) *sw = cs->y;
731 cs->x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : mon_info.rcWork.left;
732 cs->y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : mon_info.rcWork.top;
733 }
734
735 if (IS_DEFAULT(cs->cx))
736 {
737 if (info.dwFlags & STARTF_USESIZE)
738 {
739 cs->cx = info.dwXSize;
740 cs->cy = info.dwYSize;
741 }
742 else
743 {
744 cs->cx = (mon_info.rcWork.right - mon_info.rcWork.left) * 3 / 4 - cs->x;
745 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
746 }
747 }
748 /* neither x nor cx are default. Check the y values .
749 * In the trace we see Outlook and Outlook Express using
750 * cy set to CW_USEDEFAULT when opening the address book.
751 */
752 else if (IS_DEFAULT(cs->cy))
753 {
754 FIXME("Strange use of CW_USEDEFAULT in nHeight\n");
755 cs->cy = (mon_info.rcWork.bottom - mon_info.rcWork.top) * 3 / 4 - cs->y;
756 }
757 }
758 #undef IS_DEFAULT
759 }
760
761 /***********************************************************************
762 * dump_window_styles
763 */
764 static void dump_window_styles( DWORD style, DWORD exstyle )
765 {
766 TRACE( "style:" );
767 if(style & WS_POPUP) TRACE(" WS_POPUP");
768 if(style & WS_CHILD) TRACE(" WS_CHILD");
769 if(style & WS_MINIMIZE) TRACE(" WS_MINIMIZE");
770 if(style & WS_VISIBLE) TRACE(" WS_VISIBLE");
771 if(style & WS_DISABLED) TRACE(" WS_DISABLED");
772 if(style & WS_CLIPSIBLINGS) TRACE(" WS_CLIPSIBLINGS");
773 if(style & WS_CLIPCHILDREN) TRACE(" WS_CLIPCHILDREN");
774 if(style & WS_MAXIMIZE) TRACE(" WS_MAXIMIZE");
775 if((style & WS_CAPTION) == WS_CAPTION) TRACE(" WS_CAPTION");
776 else
777 {
778 if(style & WS_BORDER) TRACE(" WS_BORDER");
779 if(style & WS_DLGFRAME) TRACE(" WS_DLGFRAME");
780 }
781 if(style & WS_VSCROLL) TRACE(" WS_VSCROLL");
782 if(style & WS_HSCROLL) TRACE(" WS_HSCROLL");
783 if(style & WS_SYSMENU) TRACE(" WS_SYSMENU");
784 if(style & WS_THICKFRAME) TRACE(" WS_THICKFRAME");
785 if (style & WS_CHILD)
786 {
787 if(style & WS_GROUP) TRACE(" WS_GROUP");
788 if(style & WS_TABSTOP) TRACE(" WS_TABSTOP");
789 }
790 else
791 {
792 if(style & WS_MINIMIZEBOX) TRACE(" WS_MINIMIZEBOX");
793 if(style & WS_MAXIMIZEBOX) TRACE(" WS_MAXIMIZEBOX");
794 }
795
796 /* FIXME: Add dumping of BS_/ES_/SBS_/LBS_/CBS_/DS_/etc. styles */
797 #define DUMPED_STYLES \
798 (WS_POPUP | \
799 WS_CHILD | \
800 WS_MINIMIZE | \
801 WS_VISIBLE | \
802 WS_DISABLED | \
803 WS_CLIPSIBLINGS | \
804 WS_CLIPCHILDREN | \
805 WS_MAXIMIZE | \
806 WS_BORDER | \
807 WS_DLGFRAME | \
808 WS_VSCROLL | \
809 WS_HSCROLL | \
810 WS_SYSMENU | \
811 WS_THICKFRAME | \
812 WS_GROUP | \
813 WS_TABSTOP | \
814 WS_MINIMIZEBOX | \
815 WS_MAXIMIZEBOX)
816
817 if(style & ~DUMPED_STYLES) TRACE(" %08lx", style & ~DUMPED_STYLES);
818 TRACE("\n");
819 #undef DUMPED_STYLES
820
821 TRACE( "exstyle:" );
822 if(exstyle & WS_EX_DLGMODALFRAME) TRACE(" WS_EX_DLGMODALFRAME");
823 if(exstyle & WS_EX_DRAGDETECT) TRACE(" WS_EX_DRAGDETECT");
824 if(exstyle & WS_EX_NOPARENTNOTIFY) TRACE(" WS_EX_NOPARENTNOTIFY");
825 if(exstyle & WS_EX_TOPMOST) TRACE(" WS_EX_TOPMOST");
826 if(exstyle & WS_EX_ACCEPTFILES) TRACE(" WS_EX_ACCEPTFILES");
827 if(exstyle & WS_EX_TRANSPARENT) TRACE(" WS_EX_TRANSPARENT");
828 if(exstyle & WS_EX_MDICHILD) TRACE(" WS_EX_MDICHILD");
829 if(exstyle & WS_EX_TOOLWINDOW) TRACE(" WS_EX_TOOLWINDOW");
830 if(exstyle & WS_EX_WINDOWEDGE) TRACE(" WS_EX_WINDOWEDGE");
831 if(exstyle & WS_EX_CLIENTEDGE) TRACE(" WS_EX_CLIENTEDGE");
832 if(exstyle & WS_EX_CONTEXTHELP) TRACE(" WS_EX_CONTEXTHELP");
833 if(exstyle & WS_EX_RIGHT) TRACE(" WS_EX_RIGHT");
834 if(exstyle & WS_EX_RTLREADING) TRACE(" WS_EX_RTLREADING");
835 if(exstyle & WS_EX_LEFTSCROLLBAR) TRACE(" WS_EX_LEFTSCROLLBAR");
836 if(exstyle & WS_EX_CONTROLPARENT) TRACE(" WS_EX_CONTROLPARENT");
837 if(exstyle & WS_EX_STATICEDGE) TRACE(" WS_EX_STATICEDGE");
838 if(exstyle & WS_EX_APPWINDOW) TRACE(" WS_EX_APPWINDOW");
839 if(exstyle & WS_EX_LAYERED) TRACE(" WS_EX_LAYERED");
840
841 #define DUMPED_EX_STYLES \
842 (WS_EX_DLGMODALFRAME | \
843 WS_EX_DRAGDETECT | \
844 WS_EX_NOPARENTNOTIFY | \
845 WS_EX_TOPMOST | \
846 WS_EX_ACCEPTFILES | \
847 WS_EX_TRANSPARENT | \
848 WS_EX_MDICHILD | \
849 WS_EX_TOOLWINDOW | \
850 WS_EX_WINDOWEDGE | \
851 WS_EX_CLIENTEDGE | \
852 WS_EX_CONTEXTHELP | \
853 WS_EX_RIGHT | \
854 WS_EX_RTLREADING | \
855 WS_EX_LEFTSCROLLBAR | \
856 WS_EX_CONTROLPARENT | \
857 WS_EX_STATICEDGE | \
858 WS_EX_APPWINDOW | \
859 WS_EX_LAYERED)
860
861 if(exstyle & ~DUMPED_EX_STYLES) TRACE(" %08lx", exstyle & ~DUMPED_EX_STYLES);
862 TRACE("\n");
863 #undef DUMPED_EX_STYLES
864 }
865
866
867 /***********************************************************************
868 * WIN_CreateWindowEx
869 *
870 * Implementation of CreateWindowEx().
871 */
872 static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, LPCWSTR className, UINT flags )
873 {
874 INT cx, cy, style, sw = SW_SHOW;
875 LRESULT result;
876 RECT rect;
877 WND *wndPtr;
878 HWND hwnd, parent, owner, top_child = 0;
879 BOOL unicode = (flags & WIN_ISUNICODE) != 0;
880 MDICREATESTRUCTA mdi_cs;
881 CBT_CREATEWNDA cbtc;
882 CREATESTRUCTA cbcs;
883
884 TRACE("%s %s ex=%08x style=%08x %d,%d %dx%d parent=%p menu=%p inst=%p params=%p\n",
885 unicode ? debugstr_w((LPCWSTR)cs->lpszName) : debugstr_a(cs->lpszName),
886 debugstr_w(className),
887 cs->dwExStyle, cs->style, cs->x, cs->y, cs->cx, cs->cy,
888 cs->hwndParent, cs->hMenu, cs->hInstance, cs->lpCreateParams );
889 if(TRACE_ON(win)) dump_window_styles( cs->style, cs->dwExStyle );
890
891 /* Fix the styles for MDI children */
892 if (cs->dwExStyle & WS_EX_MDICHILD)
893 {
894 UINT flags = 0;
895
896 wndPtr = WIN_GetPtr(cs->hwndParent);
897 if (wndPtr && wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
898 {
899 flags = wndPtr->flags;
900 WIN_ReleasePtr(wndPtr);
901 }
902
903 if (!(flags & WIN_ISMDICLIENT))
904 {
905 WARN("WS_EX_MDICHILD, but parent %p is not MDIClient\n", cs->hwndParent);
906 return 0;
907 }
908
909 /* cs->lpCreateParams of WM_[NC]CREATE is different for MDI children.
910 * MDICREATESTRUCT members have the originally passed values.
911 *
912 * Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
913 * have the same layout.
914 */
915 mdi_cs.szClass = cs->lpszClass;
916 mdi_cs.szTitle = cs->lpszName;
917 mdi_cs.hOwner = cs->hInstance;
918 mdi_cs.x = cs->x;
919 mdi_cs.y = cs->y;
920 mdi_cs.cx = cs->cx;
921 mdi_cs.cy = cs->cy;
922 mdi_cs.style = cs->style;
923 mdi_cs.lParam = (LPARAM)cs->lpCreateParams;
924
925 cs->lpCreateParams = (LPVOID)&mdi_cs;
926
927 if (GetWindowLongW(cs->hwndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
928 {
929 if (cs->style & WS_POPUP)
930 {
931 TRACE("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
932 return 0;
933 }
934 cs->style |= WS_CHILD | WS_CLIPSIBLINGS;
935 }
936 else
937 {
938 cs->style &= ~WS_POPUP;
939 cs->style |= WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
940 WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
941 }
942
943 top_child = GetWindow(cs->hwndParent, GW_CHILD);
944
945 if (top_child)
946 {
947 /* Restore current maximized child */
948 if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
949 {
950 TRACE("Restoring current maximized child %p\n", top_child);
951 SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
952 ShowWindow( top_child, SW_SHOWNORMAL );
953 SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
954 }
955 }
956 }
957
958 /* Find the parent window */
959
960 parent = cs->hwndParent;
961 owner = 0;
962
963 if (cs->hwndParent == HWND_MESSAGE)
964 {
965 /* native ole32.OleInitialize uses HWND_MESSAGE to create the
966 * message window (style: WS_POPUP|WS_DISABLED)
967 */
968 FIXME("Parent is HWND_MESSAGE\n");
969 parent = GetDesktopWindow();
970 }
971 else if (cs->hwndParent)
972 {
973 if ((cs->style & (WS_CHILD|WS_POPUP)) != WS_CHILD)
974 {
975 parent = GetDesktopWindow();
976 owner = cs->hwndParent;
977 }
978 }
979 else
980 {
981 if ((cs->style & (WS_CHILD|WS_POPUP)) == WS_CHILD)
982 {
983 WARN("No parent for child window\n" );
984 SetLastError(ERROR_TLW_WITH_WSCHILD);
985 return 0; /* WS_CHILD needs a parent, but WS_POPUP doesn't */
986 }
987 if (className != (LPCWSTR)DESKTOP_CLASS_ATOM) /* are we creating the desktop itself? */
988 parent = GetDesktopWindow();
989 }
990
991 WIN_FixCoordinates(cs, &sw); /* fix default coordinates */
992
993 if ((cs->dwExStyle & WS_EX_DLGMODALFRAME) ||
994 ((!(cs->dwExStyle & WS_EX_STATICEDGE)) &&
995 (cs->style & (WS_DLGFRAME | WS_THICKFRAME))))
996 cs->dwExStyle |= WS_EX_WINDOWEDGE;
997 else
998 cs->dwExStyle &= ~WS_EX_WINDOWEDGE;
999
1000 /* Create the window structure */
1001
1002 if (!(wndPtr = create_window_handle( parent, owner, className, cs->hInstance, unicode )))
1003 return 0;
1004 hwnd = wndPtr->hwndSelf;
1005
1006 /* Fill the window structure */
1007
1008 wndPtr->tid = GetCurrentThreadId();
1009 wndPtr->hInstance = cs->hInstance;
1010 wndPtr->text = NULL;
1011 wndPtr->dwStyle = cs->style & ~WS_VISIBLE;
1012 wndPtr->dwExStyle = cs->dwExStyle;
1013 wndPtr->wIDmenu = 0;
1014 wndPtr->helpContext = 0;
1015 wndPtr->pVScroll = NULL;
1016 wndPtr->pHScroll = NULL;
1017 wndPtr->userdata = 0;
1018 wndPtr->hIcon = 0;
1019 wndPtr->hIconSmall = 0;
1020 wndPtr->hSysMenu = 0;
1021 wndPtr->flags |= (flags & WIN_ISWIN32);
1022
1023 if (wndPtr->dwStyle & WS_SYSMENU) SetSystemMenu( hwnd, 0 );
1024
1025 /*
1026 * Correct the window styles.
1027 *
1028 * It affects only the style loaded into the WIN structure.
1029 */
1030
1031 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1032 {
1033 wndPtr->dwStyle |= WS_CLIPSIBLINGS;
1034 if (!(wndPtr->dwStyle & WS_POPUP))
1035 wndPtr->dwStyle |= WS_CAPTION;
1036 }
1037
1038 /*
1039 * WS_EX_WINDOWEDGE appears to be enforced based on the other styles, so
1040 * why does the user get to set it?
1041 */
1042
1043 if ((wndPtr->dwExStyle & WS_EX_DLGMODALFRAME) ||
1044 (wndPtr->dwStyle & (WS_DLGFRAME | WS_THICKFRAME)))
1045 wndPtr->dwExStyle |= WS_EX_WINDOWEDGE;
1046 else
1047 wndPtr->dwExStyle &= ~WS_EX_WINDOWEDGE;
1048
1049 if (!(wndPtr->dwStyle & (WS_CHILD | WS_POPUP)))
1050 wndPtr->flags |= WIN_NEED_SIZE;
1051
1052 SERVER_START_REQ( set_window_info )
1053 {
1054 req->handle = hwnd;
1055 req->flags = SET_WIN_STYLE | SET_WIN_EXSTYLE | SET_WIN_INSTANCE | SET_WIN_UNICODE;
1056 req->style = wndPtr->dwStyle;
1057 req->ex_style = wndPtr->dwExStyle;
1058 req->instance = (void *)wndPtr->hInstance;
1059 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
1060 req->extra_offset = -1;
1061 wine_server_call( req );
1062 }
1063 SERVER_END_REQ;
1064
1065 /* Set the window menu */
1066
1067 if ((wndPtr->dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
1068 {
1069 if (cs->hMenu)
1070 {
1071 if (!MENU_SetMenu(hwnd, cs->hMenu))
1072 {
1073 WIN_ReleasePtr( wndPtr );
1074 free_window_handle( hwnd );
1075 return 0;
1076 }
1077 }
1078 else
1079 {
1080 LPCSTR menuName = (LPCSTR)GetClassLongPtrA( hwnd, GCLP_MENUNAME );
1081 if (menuName)
1082 {
1083 if (!cs->hInstance || HIWORD(cs->hInstance))
1084 cs->hMenu = LoadMenuA(cs->hInstance,menuName);
1085 else
1086 cs->hMenu = HMENU_32(LoadMenu16(HINSTANCE_16(cs->hInstance),menuName));
1087
1088 if (cs->hMenu) MENU_SetMenu( hwnd, cs->hMenu );
1089 }
1090 }
1091 }
1092 else SetWindowLongPtrW( hwnd, GWLP_ID, (ULONG_PTR)cs->hMenu );
1093
1094 /* call the WH_CBT hook */
1095
1096 /* the window style passed to the hook must be the real window style,
1097 * rather than just the window style that the caller to CreateWindowEx
1098 * passed in, so we have to copy the original CREATESTRUCT and get the
1099 * the real style. */
1100 cbcs = *cs;
1101 cbcs.style = wndPtr->dwStyle;
1102 cbtc.lpcs = &cbcs;
1103 cbtc.hwndInsertAfter = HWND_TOP;
1104 WIN_ReleasePtr( wndPtr );
1105 if (HOOK_CallHooks( WH_CBT, HCBT_CREATEWND, (WPARAM)hwnd, (LPARAM)&cbtc, unicode )) goto failed;
1106
1107 /* send the WM_GETMINMAXINFO message and fix the size if needed */
1108
1109 cx = cs->cx;
1110 cy = cs->cy;
1111 if ((cs->style & WS_THICKFRAME) || !(cs->style & (WS_POPUP | WS_CHILD)))
1112 {
1113 POINT maxSize, maxPos, minTrack, maxTrack;
1114 WINPOS_GetMinMaxInfo( hwnd, &maxSize, &maxPos, &minTrack, &maxTrack);
1115 if (maxTrack.x < cx) cx = maxTrack.x;
1116 if (maxTrack.y < cy) cy = maxTrack.y;
1117 if (minTrack.x > cx) cx = minTrack.x;
1118 if (minTrack.y > cy) cy = minTrack.y;
1119 }
1120
1121 if (cx < 0) cx = 0;
1122 if (cy < 0) cy = 0;
1123 SetRect( &rect, cs->x, cs->y, cs->x + cx, cs->y + cy );
1124 /* check for wraparound */
1125 if (cs->x + cx < cs->x) rect.right = 0x7fffffff;
1126 if (cs->y + cy < cs->y) rect.bottom = 0x7fffffff;
1127 if (!set_window_pos( hwnd, 0, SWP_NOZORDER | SWP_NOACTIVATE, &rect, &rect, NULL )) goto failed;
1128
1129 /* send WM_NCCREATE */
1130
1131 TRACE( "hwnd %p cs %d,%d %dx%d\n", hwnd, cs->x, cs->y, cx, cy );
1132 if (unicode)
1133 result = SendMessageW( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1134 else
1135 result = SendMessageA( hwnd, WM_NCCREATE, 0, (LPARAM)cs );
1136 if (!result)
1137 {
1138 WARN( "%p: aborted by WM_NCCREATE\n", hwnd );
1139 goto failed;
1140 }
1141
1142 /* send WM_NCCALCSIZE */
1143
1144 if ((wndPtr = WIN_GetPtr(hwnd)))
1145 {
1146 /* yes, even if the CBT hook was called with HWND_TOP */
1147 POINT pt;
1148 HWND insert_after = (wndPtr->dwStyle & WS_CHILD) ? HWND_BOTTOM : HWND_TOP;
1149 RECT window_rect = wndPtr->rectWindow;
1150 RECT client_rect = window_rect;
1151 WIN_ReleasePtr( wndPtr );
1152
1153 /* the rectangle is in screen coords for WM_NCCALCSIZE when wparam is FALSE */
1154 pt.x = pt.y = 0;
1155 MapWindowPoints( parent, 0, &pt, 1 );
1156 OffsetRect( &client_rect, pt.x, pt.y );
1157 SendMessageW( hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&client_rect );
1158 OffsetRect( &client_rect, -pt.x, -pt.y );
1159 set_window_pos( hwnd, insert_after, SWP_NOACTIVATE, &window_rect, &client_rect, NULL );
1160 }
1161 else return 0;
1162
1163 /* send WM_CREATE */
1164
1165 if (unicode)
1166 result = SendMessageW( hwnd, WM_CREATE, 0, (LPARAM)cs );
1167 else
1168 result = SendMessageA( hwnd, WM_CREATE, 0, (LPARAM)cs );
1169 if (result == -1) goto failed;
1170
1171 /* call the driver */
1172
1173 if (!USER_Driver->pCreateWindow( hwnd )) goto failed;
1174
1175 NotifyWinEvent(EVENT_OBJECT_CREATE, hwnd, OBJID_WINDOW, 0);
1176
1177 /* send the size messages */
1178
1179 if (!(wndPtr = WIN_GetPtr(hwnd))) return 0;
1180 if (!(wndPtr->flags & WIN_NEED_SIZE))
1181 {
1182 rect = wndPtr->rectClient;
1183 WIN_ReleasePtr( wndPtr );
1184 SendMessageW( hwnd, WM_SIZE, SIZE_RESTORED,
1185 MAKELONG(rect.right-rect.left, rect.bottom-rect.top));
1186 SendMessageW( hwnd, WM_MOVE, 0, MAKELONG( rect.left, rect.top ) );
1187 }
1188 else WIN_ReleasePtr( wndPtr );
1189
1190 /* Show the window, maximizing or minimizing if needed */
1191
1192 style = WIN_SetStyle( hwnd, 0, WS_MAXIMIZE | WS_MINIMIZE );
1193 if (style & (WS_MINIMIZE | WS_MAXIMIZE))
1194 {
1195 RECT newPos;
1196 UINT swFlag = (style & WS_MINIMIZE) ? SW_MINIMIZE : SW_MAXIMIZE;
1197
1198 swFlag = WINPOS_MinMaximize( hwnd, swFlag, &newPos );
1199 swFlag |= SWP_FRAMECHANGED; /* Frame always gets changed */
1200 if (!(style & WS_VISIBLE) || (style & WS_CHILD) || GetActiveWindow()) swFlag |= SWP_NOACTIVATE;
1201 SetWindowPos( hwnd, 0, newPos.left, newPos.top, newPos.right, newPos.bottom, swFlag );
1202 }
1203
1204 /* Notify the parent window only */
1205
1206 send_parent_notify( hwnd, WM_CREATE );
1207 if (!IsWindow( hwnd )) return 0;
1208
1209 if (cs->style & WS_VISIBLE)
1210 {
1211 if (cs->style & WS_MAXIMIZE)
1212 sw = SW_SHOW;
1213 else if (cs->style & WS_MINIMIZE)
1214 sw = SW_SHOWMINIMIZED;
1215
1216 ShowWindow( hwnd, sw );
1217 if (cs->dwExStyle & WS_EX_MDICHILD)
1218 {
1219 SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
1220 /* ShowWindow won't activate child windows */
1221 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
1222 }
1223 }
1224
1225 /* Call WH_SHELL hook */
1226
1227 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
1228 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWCREATED, (WPARAM)hwnd, 0, TRUE );
1229
1230 TRACE("created window %p\n", hwnd);
1231 return hwnd;
1232
1233 failed:
1234 WIN_DestroyWindow( hwnd );
1235 return 0;
1236 }
1237
1238
1239 /***********************************************************************
1240 * CreateWindow (USER.41)
1241 */
1242 HWND16 WINAPI CreateWindow16( LPCSTR className, LPCSTR windowName,
1243 DWORD style, INT16 x, INT16 y, INT16 width,
1244 INT16 height, HWND16 parent, HMENU16 menu,
1245 HINSTANCE16 instance, LPVOID data )
1246 {
1247 return CreateWindowEx16( 0, className, windowName, style,
1248 x, y, width, height, parent, menu, instance, data );
1249 }
1250
1251
1252 /***********************************************************************
1253 * CreateWindowEx (USER.452)
1254 */
1255 HWND16 WINAPI CreateWindowEx16( DWORD exStyle, LPCSTR className,
1256 LPCSTR windowName, DWORD style, INT16 x,
1257 INT16 y, INT16 width, INT16 height,
1258 HWND16 parent, HMENU16 menu,
1259 HINSTANCE16 instance, LPVOID data )
1260 {
1261 CREATESTRUCTA cs;
1262 char buffer[256];
1263
1264 /* Fix the coordinates */
1265
1266 cs.x = (x == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)x;
1267 cs.y = (y == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)y;
1268 cs.cx = (width == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)width;
1269 cs.cy = (height == CW_USEDEFAULT16) ? CW_USEDEFAULT : (INT)height;
1270
1271 /* Create the window */
1272
1273 cs.lpCreateParams = data;
1274 cs.hInstance = HINSTANCE_32(instance);
1275 cs.hMenu = HMENU_32(menu);
1276 cs.hwndParent = WIN_Handle32( parent );
1277 cs.style = style;
1278 cs.lpszName = windowName;
1279 cs.lpszClass = className;
1280 cs.dwExStyle = exStyle;
1281
1282 if (!IS_INTRESOURCE(className))
1283 {
1284 WCHAR bufferW[256];
1285
1286 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1287 return 0;
1288 return HWND_16( WIN_CreateWindowEx( &cs, bufferW, 0 ));
1289 }
1290 else
1291 {
1292 if (!GlobalGetAtomNameA( LOWORD(className), buffer, sizeof(buffer) ))
1293 {
1294 ERR( "bad atom %x\n", LOWORD(className));
1295 return 0;
1296 }
1297 cs.lpszClass = buffer;
1298 return HWND_16( WIN_CreateWindowEx( &cs, (LPCWSTR)className, 0 ));
1299 }
1300 }
1301
1302
1303 /***********************************************************************
1304 * CreateWindowExA (USER32.@)
1305 */
1306 HWND WINAPI CreateWindowExA( DWORD exStyle, LPCSTR className,
1307 LPCSTR windowName, DWORD style, INT x,
1308 INT y, INT width, INT height,
1309 HWND parent, HMENU menu,
1310 HINSTANCE instance, LPVOID data )
1311 {
1312 CREATESTRUCTA cs;
1313
1314 cs.lpCreateParams = data;
1315 cs.hInstance = instance;
1316 cs.hMenu = menu;
1317 cs.hwndParent = parent;
1318 cs.x = x;
1319 cs.y = y;
1320 cs.cx = width;
1321 cs.cy = height;
1322 cs.style = style;
1323 cs.lpszName = windowName;
1324 cs.lpszClass = className;
1325 cs.dwExStyle = exStyle;
1326
1327 if (!IS_INTRESOURCE(className))
1328 {
1329 WCHAR bufferW[256];
1330 if (!MultiByteToWideChar( CP_ACP, 0, className, -1, bufferW, sizeof(bufferW)/sizeof(WCHAR) ))
1331 return 0;
1332 return WIN_CreateWindowEx( &cs, bufferW, WIN_ISWIN32 );
1333 }
1334 return WIN_CreateWindowEx( &cs, (LPCWSTR)className, WIN_ISWIN32 );
1335 }
1336
1337
1338 /***********************************************************************
1339 * CreateWindowExW (USER32.@)
1340 */
1341 HWND WINAPI CreateWindowExW( DWORD exStyle, LPCWSTR className,
1342 LPCWSTR windowName, DWORD style, INT x,
1343 INT y, INT width, INT height,
1344 HWND parent, HMENU menu,
1345 HINSTANCE instance, LPVOID data )
1346 {
1347 CREATESTRUCTW cs;
1348
1349 cs.lpCreateParams = data;
1350 cs.hInstance = instance;
1351 cs.hMenu = menu;
1352 cs.hwndParent = parent;
1353 cs.x = x;
1354 cs.y = y;
1355 cs.cx = width;
1356 cs.cy = height;
1357 cs.style = style;
1358 cs.lpszName = windowName;
1359 cs.lpszClass = className;
1360 cs.dwExStyle = exStyle;
1361
1362 /* Note: we rely on the fact that CREATESTRUCTA and */
1363 /* CREATESTRUCTW have the same layout. */
1364 return WIN_CreateWindowEx( (CREATESTRUCTA *)&cs, className, WIN_ISWIN32 | WIN_ISUNICODE );
1365 }
1366
1367
1368 /***********************************************************************
1369 * WIN_SendDestroyMsg
1370 */
1371 static void WIN_SendDestroyMsg( HWND hwnd )
1372 {
1373 GUITHREADINFO info;
1374
1375 if (GetGUIThreadInfo( GetCurrentThreadId(), &info ))
1376 {
1377 if (hwnd == info.hwndCaret) DestroyCaret();
1378 if (hwnd == info.hwndActive) WINPOS_ActivateOtherWindow( hwnd );
1379 }
1380
1381 /*
1382 * Send the WM_DESTROY to the window.
1383 */
1384 SendMessageW( hwnd, WM_DESTROY, 0, 0);
1385
1386 /*
1387 * This WM_DESTROY message can trigger re-entrant calls to DestroyWindow
1388 * make sure that the window still exists when we come back.
1389 */
1390 if (IsWindow(hwnd))
1391 {
1392 HWND* pWndArray;
1393 int i;
1394
1395 if (!(pWndArray = WIN_ListChildren( hwnd ))) return;
1396
1397 for (i = 0; pWndArray[i]; i++)
1398 {
1399 if (IsWindow( pWndArray[i] )) WIN_SendDestroyMsg( pWndArray[i] );
1400 }
1401 HeapFree( GetProcessHeap(), 0, pWndArray );
1402 }
1403 else
1404 WARN("\tdestroyed itself while in WM_DESTROY!\n");
1405 }
1406
1407
1408 /***********************************************************************
1409 * DestroyWindow (USER32.@)
1410 */
1411 BOOL WINAPI DestroyWindow( HWND hwnd )
1412 {
1413 BOOL is_child;
1414
1415 if (!(hwnd = WIN_IsCurrentThread( hwnd )) || (hwnd == GetDesktopWindow()))
1416 {
1417 SetLastError( ERROR_ACCESS_DENIED );
1418 return FALSE;
1419 }
1420
1421 TRACE("(%p)\n", hwnd);
1422
1423 /* Call hooks */
1424
1425 if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
1426
1427 if (MENU_IsMenuActive() == hwnd)
1428 EndMenu();
1429
1430 is_child = (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) != 0;
1431
1432 if (is_child)
1433 {
1434 if (!USER_IsExitingThread( GetCurrentThreadId() ))
1435 send_parent_notify( hwnd, WM_DESTROY );
1436 }
1437 else if (!GetWindow( hwnd, GW_OWNER ))
1438 {
1439 HOOK_CallHooks( WH_SHELL, HSHELL_WINDOWDESTROYED, (WPARAM)hwnd, 0L, TRUE );
1440 /* FIXME: clean up palette - see "Internals" p.352 */
1441 }
1442
1443 if (!IsWindow(hwnd)) return TRUE;
1444
1445 /* Hide the window */
1446 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)
1447 {
1448 /* Only child windows receive WM_SHOWWINDOW in DestroyWindow() */
1449 if (is_child)
1450 ShowWindow( hwnd, SW_HIDE );
1451 else
1452 SetWindowPos( hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE |
1453 SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW );
1454 }
1455
1456 if (!IsWindow(hwnd)) return TRUE;
1457
1458 /* Recursively destroy owned windows */
1459
1460 if (!is_child)
1461 {
1462 for (;;)
1463 {
1464 int i, got_one = 0;
1465 HWND *list = WIN_ListChildren( GetDesktopWindow() );
1466 if (list)
1467 {
1468 for (i = 0; list[i]; i++)
1469 {
1470 if (GetWindow( list[i], GW_OWNER ) != hwnd) continue;
1471 if (WIN_IsCurrentThread( list[i] ))
1472 {
1473 DestroyWindow( list[i] );
1474 got_one = 1;
1475 continue;
1476 }
1477 WIN_SetOwner( list[i], 0 );
1478 }
1479 HeapFree( GetProcessHeap(), 0, list );
1480 }
1481 if (!got_one) break;
1482 }
1483 }
1484
1485 /* Send destroy messages */
1486
1487 WIN_SendDestroyMsg( hwnd );
1488 if (!IsWindow( hwnd )) return TRUE;
1489
1490 if (GetClipboardOwner() == hwnd)
1491 CLIPBOARD_ReleaseOwner();
1492
1493 /* Destroy the window storage */
1494
1495 WIN_DestroyWindow( hwnd );
1496 return TRUE;
1497 }
1498
1499
1500 /***********************************************************************
1501 * CloseWindow (USER32.@)
1502 */
1503 BOOL WINAPI CloseWindow( HWND hwnd )
1504 {
1505 if (GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) return FALSE;
1506 ShowWindow( hwnd, SW_MINIMIZE );
1507 return TRUE;
1508 }
1509
1510
1511 /***********************************************************************
1512 * OpenIcon (USER32.@)
1513 */
1514 BOOL WINAPI OpenIcon( HWND hwnd )
1515 {
1516 if (!IsIconic( hwnd )) return FALSE;
1517 ShowWindow( hwnd, SW_SHOWNORMAL );
1518 return TRUE;
1519 }
1520
1521
1522 /***********************************************************************
1523 * FindWindowExW (USER32.@)
1524 */
1525 HWND WINAPI FindWindowExW( HWND parent, HWND child, LPCWSTR className, LPCWSTR title )
1526 {
1527 HWND *list = NULL;
1528 HWND retvalue = 0;
1529 int i = 0, len = 0;
1530 WCHAR *buffer = NULL;
1531
1532 if (!parent) parent = GetDesktopWindow();
1533 if (title)
1534 {
1535 len = strlenW(title) + 1; /* one extra char to check for chars beyond the end */
1536 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) ))) return 0;
1537 }
1538
1539 if (!(list = list_window_children( 0, parent, className, 0 ))) goto done;
1540
1541 if (child)
1542 {
1543 child = WIN_GetFullHandle( child );
1544 while (list[i] && list[i] != child) i++;
1545 if (!list[i]) goto done;
1546 i++; /* start from next window */
1547 }
1548
1549 if (title)
1550 {
1551 while (list[i])
1552 {
1553 if (GetWindowTextW( list[i], buffer, len + 1 ) && !strcmpiW( buffer, title )) break;
1554 i++;
1555 }
1556 }
1557 retvalue = list[i];
1558
1559 done:
1560 HeapFree( GetProcessHeap(), 0, list );
1561 HeapFree( GetProcessHeap(), 0, buffer );
1562 return retvalue;
1563 }
1564
1565
1566
1567 /***********************************************************************
1568 * FindWindowA (USER32.@)
1569 */
1570 HWND WINAPI FindWindowA( LPCSTR className, LPCSTR title )
1571 {
1572 HWND ret = FindWindowExA( 0, 0, className, title );
1573 if (!ret) SetLastError (ERROR_CANNOT_FIND_WND_CLASS);
1574 return ret;
1575 }
1576
1577
1578 /***********************************************************************
1579 * FindWindowExA (USER32.@)
1580 */
1581 HWND WINAPI FindWindowExA( HWND parent, HWND child, LPCSTR className, LPCSTR title )
1582 {
1583 LPWSTR titleW = NULL;
1584 HWND hwnd = 0;
1585
1586 if (title)
1587 {
1588 DWORD len = MultiByteToWideChar( CP_ACP, 0, title, -1, NULL, 0 );
1589 if (!(titleW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return 0;
1590 MultiByteToWideChar( CP_ACP, 0, title, -1, titleW, len );
1591 }
1592
1593 if (!IS_INTRESOURCE(className))
1594 {
1595 WCHAR classW[256];
1596 if (MultiByteToWideChar( CP_ACP, 0, className, -1, classW, sizeof(classW)/sizeof(WCHAR) ))
1597 hwnd = FindWindowExW( parent, child, classW, titleW );
1598 }
1599 else
1600 {
1601 hwnd = FindWindowExW( parent, child, (LPCWSTR)className, titleW );
1602 }
1603
1604 HeapFree( GetProcessHeap(), 0, titleW );
1605 return hwnd;
1606 }
1607
1608
1609 /***********************************************************************
1610 * FindWindowW (USER32.@)
1611 */
1612 HWND WINAPI FindWindowW( LPCWSTR className, LPCWSTR title )
1613 {
1614 return FindWindowExW( 0, 0, className, title );
1615 }
1616
1617
1618 /**********************************************************************
1619 * GetDesktopWindow (USER32.@)
1620 */
1621 HWND WINAPI GetDesktopWindow(void)
1622 {
1623 struct user_thread_info *thread_info = get_user_thread_info();
1624
1625 if (thread_info->desktop) return thread_info->desktop;
1626
1627 SERVER_START_REQ( get_desktop_window )
1628 {
1629 req->force = 0;
1630 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1631 }
1632 SERVER_END_REQ;
1633
1634 if (!thread_info->desktop)
1635 {
1636 USEROBJECTFLAGS flags;
1637 if (!GetUserObjectInformationW( GetProcessWindowStation(), UOI_FLAGS, &flags,
1638 sizeof(flags), NULL ) || (flags.dwFlags & WSF_VISIBLE))
1639 {
1640 static const WCHAR command_line[] = {'\\','e','x','p','l','o','r','e','r','.','e','x','e',' ','/','d','e','s','k','t','o','p',0};
1641 STARTUPINFOW si;
1642 PROCESS_INFORMATION pi;
1643 WCHAR cmdline[MAX_PATH + sizeof(command_line)/sizeof(WCHAR)];
1644
1645 memset( &si, 0, sizeof(si) );
1646 si.cb = sizeof(si);
1647 si.dwFlags = STARTF_USESTDHANDLES;
1648 si.hStdInput = 0;
1649 si.hStdOutput = 0;
1650 si.hStdError = GetStdHandle( STD_ERROR_HANDLE );
1651
1652 GetSystemDirectoryW( cmdline, MAX_PATH );
1653 lstrcatW( cmdline, command_line );
1654 if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
1655 NULL, NULL, &si, &pi ))
1656 {
1657 TRACE( "started explorer pid %04x tid %04x\n", pi.dwProcessId, pi.dwThreadId );
1658 WaitForInputIdle( pi.hProcess, 10000 );
1659 CloseHandle( pi.hThread );
1660 CloseHandle( pi.hProcess );
1661 }
1662 else WARN( "failed to start explorer, err %d\n", GetLastError() );
1663 }
1664 else TRACE( "not starting explorer since winstation is not visible\n" );
1665
1666 SERVER_START_REQ( get_desktop_window )
1667 {
1668 req->force = 1;
1669 if (!wine_server_call( req )) thread_info->desktop = reply->handle;
1670 }
1671 SERVER_END_REQ;
1672 }
1673
1674 if (!thread_info->desktop || !USER_Driver->pCreateDesktopWindow( thread_info->desktop ))
1675 ERR( "failed to create desktop window\n" );
1676
1677 return thread_info->desktop;
1678 }
1679
1680
1681 /*******************************************************************
1682 * EnableWindow (USER32.@)
1683 */
1684 BOOL WINAPI EnableWindow( HWND hwnd, BOOL enable )
1685 {
1686 BOOL retvalue;
1687 HWND full_handle;
1688
1689 if (is_broadcast(hwnd))
1690 {
1691 SetLastError( ERROR_INVALID_PARAMETER );
1692 return FALSE;
1693 }
1694
1695 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
1696 return SendMessageW( hwnd, WM_WINE_ENABLEWINDOW, enable, 0 );
1697
1698 hwnd = full_handle;
1699
1700 TRACE("( %p, %d )\n", hwnd, enable);
1701
1702 retvalue = !IsWindowEnabled( hwnd );
1703
1704 if (enable && retvalue)
1705 {
1706 WIN_SetStyle( hwnd, 0, WS_DISABLED );
1707 SendMessageW( hwnd, WM_ENABLE, TRUE, 0 );
1708 }
1709 else if (!enable && !retvalue)
1710 {
1711 HWND capture_wnd;
1712
1713 SendMessageW( hwnd, WM_CANCELMODE, 0, 0);
1714
1715 WIN_SetStyle( hwnd, WS_DISABLED, 0 );
1716
1717 if (hwnd == GetFocus())
1718 SetFocus( 0 ); /* A disabled window can't have the focus */
1719
1720 capture_wnd = GetCapture();
1721 if (hwnd == capture_wnd || IsChild(hwnd, capture_wnd))
1722 ReleaseCapture(); /* A disabled window can't capture the mouse */
1723
1724 SendMessageW( hwnd, WM_ENABLE, FALSE, 0 );
1725 }
1726 return retvalue;
1727 }
1728
1729
1730 /***********************************************************************
1731 * IsWindowEnabled (USER32.@)
1732 */
1733 BOOL WINAPI IsWindowEnabled(HWND hWnd)
1734 {
1735 return !(GetWindowLongW( hWnd, GWL_STYLE ) & WS_DISABLED);
1736 }
1737
1738
1739 /***********************************************************************
1740 * IsWindowUnicode (USER32.@)
1741 */
1742 BOOL WINAPI IsWindowUnicode( HWND hwnd )
1743 {
1744 WND * wndPtr;
1745 BOOL retvalue = FALSE;
1746
1747 if (!(wndPtr = WIN_GetPtr(hwnd))) return FALSE;
1748
1749 if (wndPtr == WND_DESKTOP) return TRUE;
1750
1751 if (wndPtr != WND_OTHER_PROCESS)
1752 {
1753 retvalue = (wndPtr->flags & WIN_ISUNICODE) != 0;
1754 WIN_ReleasePtr( wndPtr );
1755 }
1756 else
1757 {
1758 SERVER_START_REQ( get_window_info )
1759 {
1760 req->handle = hwnd;
1761 if (!wine_server_call_err( req )) retvalue = reply->is_unicode;
1762 }
1763 SERVER_END_REQ;
1764 }
1765 return retvalue;
1766 }
1767
1768
1769 /**********************************************************************
1770 * WIN_GetWindowLong
1771 *
1772 * Helper function for GetWindowLong().
1773 */
1774 static LONG_PTR WIN_GetWindowLong( HWND hwnd, INT offset, UINT size, BOOL unicode )
1775 {
1776 LONG_PTR retvalue = 0;
1777 WND *wndPtr;
1778
1779 if (offset == GWLP_HWNDPARENT)
1780 {
1781 HWND parent = GetAncestor( hwnd, GA_PARENT );
1782 if (parent == GetDesktopWindow()) parent = GetWindow( hwnd, GW_OWNER );
1783 return (ULONG_PTR)parent;
1784 }
1785
1786 if (!(wndPtr = WIN_GetPtr( hwnd )))
1787 {
1788 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1789 return 0;
1790 }
1791
1792 if (wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP)
1793 {
1794 if (offset == GWLP_WNDPROC)
1795 {
1796 SetLastError( ERROR_ACCESS_DENIED );
1797 return 0;
1798 }
1799 SERVER_START_REQ( set_window_info )
1800 {
1801 req->handle = hwnd;
1802 req->flags = 0; /* don't set anything, just retrieve */
1803 req->extra_offset = (offset >= 0) ? offset : -1;
1804 req->extra_size = (offset >= 0) ? size : 0;
1805 if (!wine_server_call_err( req ))
1806 {
1807 switch(offset)
1808 {
1809 case GWL_STYLE: retvalue = reply->old_style; break;
1810 case GWL_EXSTYLE: retvalue = reply->old_ex_style; break;
1811 case GWLP_ID: retvalue = reply->old_id; break;
1812 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)reply->old_instance; break;
1813 case GWLP_USERDATA: retvalue = reply->old_user_data; break;
1814 default:
1815 if (offset >= 0) retvalue = get_win_data( &reply->old_extra_value, size );
1816 else SetLastError( ERROR_INVALID_INDEX );
1817 break;
1818 }
1819 }
1820 }
1821 SERVER_END_REQ;
1822 return retvalue;
1823 }
1824
1825 /* now we have a valid wndPtr */
1826
1827 if (offset >= 0)
1828 {
1829 if (offset > (int)(wndPtr->cbWndExtra - size))
1830 {
1831 WARN("Invalid offset %d\n", offset );
1832 WIN_ReleasePtr( wndPtr );
1833 SetLastError( ERROR_INVALID_INDEX );
1834 return 0;
1835 }
1836 retvalue = get_win_data( (char *)wndPtr->wExtra + offset, size );
1837
1838 /* Special case for dialog window procedure */
1839 if ((offset == DWLP_DLGPROC) && (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1840 retvalue = (LONG_PTR)WINPROC_GetProc( (WNDPROC)retvalue, unicode );
1841 WIN_ReleasePtr( wndPtr );
1842 return retvalue;
1843 }
1844
1845 switch(offset)
1846 {
1847 case GWLP_USERDATA: retvalue = wndPtr->userdata; break;
1848 case GWL_STYLE: retvalue = wndPtr->dwStyle; break;
1849 case GWL_EXSTYLE: retvalue = wndPtr->dwExStyle; break;
1850 case GWLP_ID: retvalue = wndPtr->wIDmenu; break;
1851 case GWLP_HINSTANCE: retvalue = (ULONG_PTR)wndPtr->hInstance; break;
1852 case GWLP_WNDPROC:
1853 /* This looks like a hack only for the edit control (see tests). This makes these controls
1854 * more tolerant to A/W mismatches. The lack of W->A->W conversion for such a mismatch suggests
1855 * that the hack is in GetWindowLongPtr[AW], not in winprocs.
1856 */
1857 if (wndPtr->winproc == EDIT_winproc_handle && (!unicode != !(wndPtr->flags & WIN_ISUNICODE)))
1858 retvalue = (ULONG_PTR)wndPtr->winproc;
1859 else
1860 retvalue = (ULONG_PTR)WINPROC_GetProc( wndPtr->winproc, unicode );
1861 break;
1862 default:
1863 WARN("Unknown offset %d\n", offset );
1864 SetLastError( ERROR_INVALID_INDEX );
1865 break;
1866 }
1867 WIN_ReleasePtr(wndPtr);
1868 return retvalue;
1869 }
1870
1871
1872 /**********************************************************************
1873 * WIN_SetWindowLong
1874 *
1875 * Helper function for SetWindowLong().
1876 *
1877 * 0 is the failure code. However, in the case of failure SetLastError
1878 * must be set to distinguish between a 0 return value and a failure.
1879 */
1880 LONG_PTR WIN_SetWindowLong( HWND hwnd, INT offset, UINT size, LONG_PTR newval, BOOL unicode )
1881 {
1882 STYLESTRUCT style;
1883 BOOL ok;
1884 LONG_PTR retval = 0;
1885 WND *wndPtr;
1886
1887 TRACE( "%p %d %lx %c\n", hwnd, offset, newval, unicode ? 'W' : 'A' );
1888
1889 if (is_broadcast(hwnd))
1890 {
1891 SetLastError( ERROR_INVALID_PARAMETER );
1892 return FALSE;
1893 }
1894
1895 if (!(wndPtr = WIN_GetPtr( hwnd )))
1896 {
1897 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
1898 return 0;
1899 }
1900 if (wndPtr == WND_DESKTOP)
1901 {
1902 /* can't change anything on the desktop window */
1903 SetLastError( ERROR_ACCESS_DENIED );
1904 return 0;
1905 }
1906 if (wndPtr == WND_OTHER_PROCESS)
1907 {
1908 if (offset == GWLP_WNDPROC)
1909 {
1910 SetLastError( ERROR_ACCESS_DENIED );
1911 return 0;
1912 }
1913 if (offset > 32767 || offset < -32767)
1914 {
1915 SetLastError( ERROR_INVALID_INDEX );
1916 return 0;
1917 }
1918 return SendMessageW( hwnd, WM_WINE_SETWINDOWLONG, MAKEWPARAM( offset, size ), newval );
1919 }
1920
1921 /* first some special cases */
1922 switch( offset )
1923 {
1924 case GWL_STYLE:
1925 case GWL_EXSTYLE:
1926 style.styleOld =
1927 offset == GWL_STYLE ? wndPtr->dwStyle : wndPtr->dwExStyle;
1928 style.styleNew = newval;
1929 WIN_ReleasePtr( wndPtr );
1930 SendMessageW( hwnd, WM_STYLECHANGING, offset, (LPARAM)&style );
1931 if (!(wndPtr = WIN_GetPtr( hwnd )) || wndPtr == WND_OTHER_PROCESS) return 0;
1932 newval = style.styleNew;
1933 break;
1934 case GWLP_HWNDPARENT:
1935 if (wndPtr->parent == GetDesktopWindow())
1936 {
1937 WIN_ReleasePtr( wndPtr );
1938 return (ULONG_PTR)WIN_SetOwner( hwnd, (HWND)newval );
1939 }
1940 else
1941 {
1942 WIN_ReleasePtr( wndPtr );
1943 return (ULONG_PTR)SetParent( hwnd, (HWND)newval );
1944 }
1945 case GWLP_WNDPROC:
1946 {
1947 WNDPROC proc;
1948 UINT old_flags = wndPtr->flags;
1949 retval = WIN_GetWindowLong( hwnd, offset, size, unicode );
1950 if (unicode) proc = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1951 else proc = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1952 if (proc) wndPtr->winproc = proc;
1953 if (WINPROC_IsUnicode( proc, unicode )) wndPtr->flags |= WIN_ISUNICODE;
1954 else wndPtr->flags &= ~WIN_ISUNICODE;
1955 if (!((old_flags ^ wndPtr->flags) & WIN_ISUNICODE))
1956 {
1957 WIN_ReleasePtr( wndPtr );
1958 return retval;
1959 }
1960 /* update is_unicode flag on the server side */
1961 break;
1962 }
1963 case GWLP_ID:
1964 case GWLP_HINSTANCE:
1965 case GWLP_USERDATA:
1966 break;
1967 case DWLP_DLGPROC:
1968 if ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
1969 (size == sizeof(LONG_PTR)) && (wndPtr->flags & WIN_ISDIALOG))
1970 {
1971 WNDPROC *ptr = (WNDPROC *)((char *)wndPtr->wExtra + DWLP_DLGPROC);
1972 retval = (ULONG_PTR)WINPROC_GetProc( *ptr, unicode );
1973 if (unicode) *ptr = WINPROC_AllocProc( NULL, (WNDPROC)newval );
1974 else *ptr = WINPROC_AllocProc( (WNDPROC)newval, NULL );
1975 WIN_ReleasePtr( wndPtr );
1976 return retval;
1977 }
1978 /* fall through */
1979 default:
1980 if (offset < 0 || offset > (int)(wndPtr->cbWndExtra - size))
1981 {
1982 WARN("Invalid offset %d\n", offset );
1983 WIN_ReleasePtr( wndPtr );
1984 SetLastError( ERROR_INVALID_INDEX );
1985 return 0;
1986 }
1987 else if (get_win_data( (char *)wndPtr->wExtra + offset, size ) == newval)
1988 {
1989 /* already set to the same value */
1990 WIN_ReleasePtr( wndPtr );
1991 return newval;
1992 }
1993 break;
1994 }
1995
1996 SERVER_START_REQ( set_window_info )
1997 {
1998 req->handle = hwnd;
1999 req->extra_offset = -1;
2000 switch(offset)
2001 {
2002 case GWL_STYLE:
2003 req->flags = SET_WIN_STYLE;
2004 req->style = newval;
2005 break;
2006 case GWL_EXSTYLE:
2007 req->flags = SET_WIN_EXSTYLE;
2008 /* WS_EX_TOPMOST can only be changed through SetWindowPos */
2009 newval = (newval & ~WS_EX_TOPMOST) | (wndPtr->dwExStyle & WS_EX_TOPMOST);
2010 req->ex_style = newval;
2011 break;
2012 case GWLP_ID:
2013 req->flags = SET_WIN_ID;
2014 req->id = newval;
2015 break;
2016 case GWLP_HINSTANCE:
2017 req->flags = SET_WIN_INSTANCE;
2018 req->instance = (void *)newval;
2019 break;
2020 case GWLP_WNDPROC:
2021 req->flags = SET_WIN_UNICODE;
2022 req->is_unicode = (wndPtr->flags & WIN_ISUNICODE) != 0;
2023 break;
2024 case GWLP_USERDATA:
2025 req->flags = SET_WIN_USERDATA;
2026 req->user_data = newval;
2027 break;
2028 default:
2029 req->flags = SET_WIN_EXTRA;
2030 req->extra_offset = offset;
2031 req->extra_size = size;
2032 set_win_data( &req->extra_value, newval, size );
2033 }
2034 if ((ok = !wine_server_call_err( req )))
2035 {
2036 switch(offset)
2037 {
2038 case GWL_STYLE:
2039 wndPtr->dwStyle = newval;
2040 retval = reply->old_style;
2041 break;
2042 case GWL_EXSTYLE:
2043 wndPtr->dwExStyle = newval;
2044 retval = reply->old_ex_style;
2045 break;
2046 case GWLP_ID:
2047 wndPtr->wIDmenu = newval;
2048 retval = reply->old_id;
2049 break;
2050 case GWLP_HINSTANCE:
2051 wndPtr->hInstance = (HINSTANCE)newval;
2052 retval = (ULONG_PTR)reply->old_instance;
2053 break;
2054 case GWLP_WNDPROC:
2055 break;
2056 case GWLP_USERDATA:
2057 wndPtr->userdata = newval;
2058 retval = reply->old_user_data;
2059 break;
2060 default:
2061 retval = get_win_data( (char *)wndPtr->wExtra + offset, size );
2062 set_win_data( (char *)wndPtr->wExtra + offset, newval, size );
2063 break;
2064 }
2065 }
2066 }
2067 SERVER_END_REQ;
2068 WIN_ReleasePtr( wndPtr );
2069
2070 if (!ok) return 0;
2071
2072 if (offset == GWL_STYLE) USER_Driver->pSetWindowStyle( hwnd, retval );
2073
2074 if (offset == GWL_STYLE || offset == GWL_EXSTYLE)
2075 SendMessageW( hwnd, WM_STYLECHANGED, offset, (LPARAM)&style );
2076
2077 return retval;
2078 }
2079
2080
2081 /**********************************************************************
2082 * GetWindowLong (USER.135)
2083 */
2084 LONG WINAPI GetWindowLong16( HWND16 hwnd, INT16 offset )
2085 {
2086 WND *wndPtr;
2087 LONG_PTR retvalue;
2088 BOOL is_winproc = (offset == GWLP_WNDPROC);
2089
2090 if (offset >= 0)
2091 {
2092 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2093 {
2094 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2095 return 0;
2096 }
2097 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2098 {
2099 if (offset > (int)(wndPtr->cbWndExtra - sizeof(LONG)))
2100 {
2101 /*
2102 * Some programs try to access last element from 16 bit
2103 * code using illegal offset value. Hopefully this is
2104 * what those programs really expect.
2105 */
2106 if (wndPtr->cbWndExtra >= 4 && offset == wndPtr->cbWndExtra - sizeof(WORD))
2107 {
2108 INT offset2 = wndPtr->cbWndExtra - sizeof(LONG);
2109 ERR( "- replaced invalid offset %d with %d\n", offset, offset2 );
2110 offset = offset2;
2111 }
2112 else
2113 {
2114 WARN("Invalid offset %d\n", offset );
2115 WIN_ReleasePtr( wndPtr );
2116 SetLastError( ERROR_INVALID_INDEX );
2117 return 0;
2118 }
2119 }
2120 is_winproc = ((offset == DWLP_DLGPROC) && (wndPtr->flags & WIN_ISDIALOG));
2121 WIN_ReleasePtr( wndPtr );
2122 }
2123 }
2124 retvalue = GetWindowLongA( WIN_Handle32(hwnd), offset );
2125 if (is_winproc) retvalue = (LONG_PTR)WINPROC_GetProc16( (WNDPROC)retvalue, FALSE );
2126 return retvalue;
2127 }
2128
2129
2130 /**********************************************************************
2131 * GetWindowWord (USER32.@)
2132 */
2133 WORD WINAPI GetWindowWord( HWND hwnd, INT offset )
2134 {
2135 switch(offset)
2136 {
2137 case GWLP_ID:
2138 case GWLP_HINSTANCE:
2139 case GWLP_HWNDPARENT:
2140 break;
2141 default:
2142 if (offset < 0)
2143 {
2144 WARN("Invalid offset %d\n", offset );
2145 SetLastError( ERROR_INVALID_INDEX );
2146 return 0;
2147 }
2148 break;
2149 }
2150 return WIN_GetWindowLong( hwnd, offset, sizeof(WORD), FALSE );
2151 }
2152
2153
2154 /**********************************************************************
2155 * GetWindowLongA (USER32.@)
2156 */
2157 LONG WINAPI GetWindowLongA( HWND hwnd, INT offset )
2158 {
2159 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), FALSE );
2160 }
2161
2162
2163 /**********************************************************************
2164 * GetWindowLongW (USER32.@)
2165 */
2166 LONG WINAPI GetWindowLongW( HWND hwnd, INT offset )
2167 {
2168 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG), TRUE );
2169 }
2170
2171
2172 /**********************************************************************
2173 * SetWindowLong (USER.136)
2174 */
2175 LONG WINAPI SetWindowLong16( HWND16 hwnd, INT16 offset, LONG newval )
2176 {
2177 WND *wndPtr;
2178 BOOL is_winproc = (offset == GWLP_WNDPROC);
2179
2180 if (offset == DWLP_DLGPROC)
2181 {
2182 if (!(wndPtr = WIN_GetPtr( WIN_Handle32(hwnd) )))
2183 {
2184 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2185 return 0;
2186 }
2187 if (wndPtr != WND_OTHER_PROCESS && wndPtr != WND_DESKTOP)
2188 {
2189 is_winproc = ((wndPtr->cbWndExtra - sizeof(LONG_PTR) >= DWLP_DLGPROC) &&
2190 (wndPtr->flags & WIN_ISDIALOG));
2191 WIN_ReleasePtr( wndPtr );
2192 }
2193 }
2194
2195 if (is_winproc)
2196 {
2197 WNDPROC new_proc = WINPROC_AllocProc16( (WNDPROC16)newval );
2198 WNDPROC old_proc = (WNDPROC)SetWindowLongPtrA( WIN_Handle32(hwnd), offset, (LONG_PTR)new_proc );
2199 return (LONG)WINPROC_GetProc16( old_proc, FALSE );
2200 }
2201 else return SetWindowLongA( WIN_Handle32(hwnd), offset, newval );
2202 }
2203
2204
2205 /**********************************************************************
2206 * SetWindowWord (USER32.@)
2207 */
2208 WORD WINAPI SetWindowWord( HWND hwnd, INT offset, WORD newval )
2209 {
2210 switch(offset)
2211 {
2212 case GWLP_ID:
2213 case GWLP_HINSTANCE:
2214 case GWLP_HWNDPARENT:
2215 break;
2216 default:
2217 if (offset < 0)
2218 {
2219 WARN("Invalid offset %d\n", offset );
2220 SetLastError( ERROR_INVALID_INDEX );
2221 return 0;
2222 }
2223 break;
2224 }
2225 return WIN_SetWindowLong( hwnd, offset, sizeof(WORD), newval, FALSE );
2226 }
2227
2228
2229 /**********************************************************************
2230 * SetWindowLongA (USER32.@)
2231 *
2232 * See SetWindowLongW.
2233 */
2234 LONG WINAPI SetWindowLongA( HWND hwnd, INT offset, LONG newval )
2235 {
2236 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, FALSE );
2237 }
2238
2239
2240 /**********************************************************************
2241 * SetWindowLongW (USER32.@) Set window attribute
2242 *
2243 * SetWindowLong() alters one of a window's attributes or sets a 32-bit (long)
2244 * value in a window's extra memory.
2245 *
2246 * The _hwnd_ parameter specifies the window. is the handle to a
2247 * window that has extra memory. The _newval_ parameter contains the
2248 * new attribute or extra memory value. If positive, the _offset_
2249 * parameter is the byte-addressed location in the window's extra
2250 * memory to set. If negative, _offset_ specifies the window
2251 * attribute to set, and should be one of the following values:
2252 *
2253 * GWL_EXSTYLE The window's extended window style
2254 *
2255 * GWL_STYLE The window's window style.
2256 *
2257 * GWLP_WNDPROC Pointer to the window's window procedure.
2258 *
2259 * GWLP_HINSTANCE The window's pplication instance handle.
2260 *
2261 * GWLP_ID The window's identifier.
2262 *
2263 * GWLP_USERDATA The window's user-specified data.
2264 *
2265 * If the window is a dialog box, the _offset_ parameter can be one of
2266 * the following values:
2267 *
2268 * DWLP_DLGPROC The address of the window's dialog box procedure.
2269 *
2270 * DWLP_MSGRESULT The return value of a message
2271 * that the dialog box procedure processed.
2272 *
2273 * DWLP_USER Application specific information.
2274 *
2275 * RETURNS
2276 *
2277 * If successful, returns the previous value located at _offset_. Otherwise,
2278 * returns 0.
2279 *
2280 * NOTES
2281 *
2282 * Extra memory for a window class is specified by a nonzero cbWndExtra
2283 * parameter of the WNDCLASS structure passed to RegisterClass() at the
2284 * time of class creation.
2285 *
2286 * Using GWL_WNDPROC to set a new window procedure effectively creates
2287 * a window subclass. Use CallWindowProc() in the new windows procedure
2288 * to pass messages to the superclass's window procedure.
2289 *
2290 * The user data is reserved for use by the application which created
2291 * the window.
2292 *
2293 * Do not use GWL_STYLE to change the window's WS_DISABLED style;
2294 * instead, call the EnableWindow() function to change the window's
2295 * disabled state.
2296 *
2297 * Do not use GWL_HWNDPARENT to reset the window's parent, use
2298 * SetParent() instead.
2299 *
2300 * Win95:
2301 * When offset is GWL_STYLE and the calling app's ver is 4.0,
2302 * it sends WM_STYLECHANGING before changing the settings
2303 * and WM_STYLECHANGED afterwards.
2304 * App ver 4.0 can't use SetWindowLong to change WS_EX_TOPMOST.
2305 */
2306 LONG WINAPI SetWindowLongW(
2307 HWND hwnd, /* [in] window to alter */
2308 INT offset, /* [in] offset, in bytes, of location to alter */
2309 LONG newval /* [in] new value of location */
2310 ) {
2311 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG), newval, TRUE );
2312 }
2313
2314
2315 /*******************************************************************
2316 * GetWindowTextA (USER32.@)
2317 */
2318 INT WINAPI GetWindowTextA( HWND hwnd, LPSTR lpString, INT nMaxCount )
2319 {
2320 WCHAR *buffer;
2321
2322 if (!lpString) return 0;
2323
2324 if (WIN_IsCurrentProcess( hwnd ))
2325 return (INT)SendMessageA( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2326
2327 /* when window belongs to other process, don't send a message */
2328 if (nMaxCount <= 0) return 0;
2329 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, nMaxCount * sizeof(WCHAR) ))) return 0;
2330 get_server_window_text( hwnd, buffer, nMaxCount );
2331 if (!WideCharToMultiByte( CP_ACP, 0, buffer, -1, lpString, nMaxCount, NULL, NULL ))
2332 lpString[nMaxCount-1] = 0;
2333 HeapFree( GetProcessHeap(), 0, buffer );
2334 return strlen(lpString);
2335 }
2336
2337
2338 /*******************************************************************
2339 * InternalGetWindowText (USER32.@)
2340 */
2341 INT WINAPI InternalGetWindowText(HWND hwnd,LPWSTR lpString,INT nMaxCount )
2342 {
2343 WND *win;
2344
2345 if (nMaxCount <= 0) return 0;
2346 if (!(win = WIN_GetPtr( hwnd ))) return 0;
2347 if (win == WND_DESKTOP) lpString[0] = 0;
2348 else if (win != WND_OTHER_PROCESS)
2349 {
2350 if (win->text) lstrcpynW( lpString, win->text, nMaxCount );
2351 else lpString[0] = 0;
2352 WIN_ReleasePtr( win );
2353 }
2354 else
2355 {
2356 get_server_window_text( hwnd, lpString, nMaxCount );
2357 }
2358 return strlenW(lpString);
2359 }
2360
2361
2362 /*******************************************************************
2363 * GetWindowTextW (USER32.@)
2364 */
2365 INT WINAPI GetWindowTextW( HWND hwnd, LPWSTR lpString, INT nMaxCount )
2366 {
2367 if (!lpString) return 0;
2368
2369 if (WIN_IsCurrentProcess( hwnd ))
2370 return (INT)SendMessageW( hwnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString );
2371
2372 /* when window belongs to other process, don't send a message */
2373 if (nMaxCount <= 0) return 0;
2374 get_server_window_text( hwnd, lpString, nMaxCount );
2375 return strlenW(lpString);
2376 }
2377
2378
2379 /*******************************************************************
2380 * SetWindowTextA (USER32.@)
2381 * SetWindowText (USER32.@)
2382 */
2383 BOOL WINAPI SetWindowTextA( HWND hwnd, LPCSTR lpString )
2384 {
2385 if (is_broadcast(hwnd))
2386 {
2387 SetLastError( ERROR_INVALID_PARAMETER );
2388 return FALSE;
2389 }
2390 if (!WIN_IsCurrentProcess( hwnd ))
2391 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2392 debugstr_a(lpString), hwnd );
2393 return (BOOL)SendMessageA( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2394 }
2395
2396
2397 /*******************************************************************
2398 * SetWindowTextW (USER32.@)
2399 */
2400 BOOL WINAPI SetWindowTextW( HWND hwnd, LPCWSTR lpString )
2401 {
2402 if (is_broadcast(hwnd))
2403 {
2404 SetLastError( ERROR_INVALID_PARAMETER );
2405 return FALSE;
2406 }
2407 if (!WIN_IsCurrentProcess( hwnd ))
2408 WARN( "setting text %s of other process window %p should not use SendMessage\n",
2409 debugstr_w(lpString), hwnd );
2410 return (BOOL)SendMessageW( hwnd, WM_SETTEXT, 0, (LPARAM)lpString );
2411 }
2412
2413
2414 /*******************************************************************
2415 * GetWindowTextLengthA (USER32.@)
2416 */
2417 INT WINAPI GetWindowTextLengthA( HWND hwnd )
2418 {
2419 return SendMessageA( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2420 }
2421
2422 /*******************************************************************
2423 * GetWindowTextLengthW (USER32.@)
2424 */
2425 INT WINAPI GetWindowTextLengthW( HWND hwnd )
2426 {
2427 return SendMessageW( hwnd, WM_GETTEXTLENGTH, 0, 0 );
2428 }
2429
2430
2431 /*******************************************************************
2432 * IsWindow (USER32.@)
2433 */
2434 BOOL WINAPI IsWindow( HWND hwnd )
2435 {
2436 WND *ptr;
2437 BOOL ret;
2438
2439 if (!(ptr = WIN_GetPtr( hwnd ))) return FALSE;
2440 if (ptr == WND_DESKTOP) return TRUE;
2441
2442 if (ptr != WND_OTHER_PROCESS)
2443 {
2444 WIN_ReleasePtr( ptr );
2445 return TRUE;
2446 }
2447
2448 /* check other processes */
2449 SERVER_START_REQ( get_window_info )
2450 {
2451 req->handle = hwnd;
2452 ret = !wine_server_call_err( req );
2453 }
2454 SERVER_END_REQ;
2455 return ret;
2456 }
2457
2458
2459 /***********************************************************************
2460 * GetWindowThreadProcessId (USER32.@)
2461 */
2462 DWORD WINAPI GetWindowThreadProcessId( HWND hwnd, LPDWORD process )
2463 {
2464 WND *ptr;
2465 DWORD tid = 0;
2466
2467 if (!(ptr = WIN_GetPtr( hwnd )))
2468 {
2469 SetLastError( ERROR_INVALID_WINDOW_HANDLE);
2470 return 0;
2471 }
2472
2473 if (ptr != WND_OTHER_PROCESS && ptr != WND_DESKTOP)
2474 {
2475 /* got a valid window */
2476 tid = ptr->tid;
2477 if (process) *process = GetCurrentProcessId();
2478 WIN_ReleasePtr( ptr );
2479 return tid;
2480 }
2481
2482 /* check other processes */
2483 SERVER_START_REQ( get_window_info )
2484 {
2485 req->handle = hwnd;
2486 if (!wine_server_call_err( req ))
2487 {
2488 tid = (DWORD)reply->tid;
2489 if (process) *process = (DWORD)reply->pid;
2490 }
2491 }
2492 SERVER_END_REQ;
2493 return tid;
2494 }
2495
2496
2497 /*****************************************************************
2498 * GetParent (USER32.@)
2499 */
2500 HWND WINAPI GetParent( HWND hwnd )
2501 {
2502 WND *wndPtr;
2503 HWND retvalue = 0;
2504
2505 if (!(wndPtr = WIN_GetPtr( hwnd )))
2506 {
2507 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2508 return 0;
2509 }
2510 if (wndPtr == WND_DESKTOP) return 0;
2511 if (wndPtr == WND_OTHER_PROCESS)
2512 {
2513 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2514 if (style & (WS_POPUP | WS_CHILD))
2515 {
2516 SERVER_START_REQ( get_window_tree )
2517 {
2518 req->handle = hwnd;
2519 if (!wine_server_call_err( req ))
2520 {
2521 if (style & WS_POPUP) retvalue = reply->owner;
2522 else if (style & WS_CHILD) retvalue = reply->parent;
2523 }
2524 }
2525 SERVER_END_REQ;
2526 }
2527 }
2528 else
2529 {
2530 if (wndPtr->dwStyle & WS_POPUP) retvalue = wndPtr->owner;
2531 else if (wndPtr->dwStyle & WS_CHILD) retvalue = wndPtr->parent;
2532 WIN_ReleasePtr( wndPtr );
2533 }
2534 return retvalue;
2535 }
2536
2537
2538 /*****************************************************************
2539 * GetAncestor (USER32.@)
2540 */
2541 HWND WINAPI GetAncestor( HWND hwnd, UINT type )
2542 {
2543 WND *win;
2544 HWND *list, ret = 0;
2545
2546 switch(type)
2547 {
2548 case GA_PARENT:
2549 if (!(win = WIN_GetPtr( hwnd )))
2550 {
2551 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2552 return 0;
2553 }
2554 if (win == WND_DESKTOP) return 0;
2555 if (win != WND_OTHER_PROCESS)
2556 {
2557 ret = win->parent;
2558 WIN_ReleasePtr( win );
2559 }
2560 else /* need to query the server */
2561 {
2562 SERVER_START_REQ( get_window_tree )
2563 {
2564 req->handle = hwnd;
2565 if (!wine_server_call_err( req )) ret = reply->parent;
2566 }
2567 SERVER_END_REQ;
2568 }
2569 break;
2570
2571 case GA_ROOT:
2572 if (!(list = list_window_parents( hwnd ))) return 0;
2573
2574 if (!list[0] || !list[1]) ret = WIN_GetFullHandle( hwnd ); /* top-level window */
2575 else
2576 {
2577 int count = 2;
2578 while (list[count]) count++;
2579 ret = list[count - 2]; /* get the one before the desktop */
2580 }
2581 HeapFree( GetProcessHeap(), 0, list );
2582 break;
2583
2584 case GA_ROOTOWNER:
2585 if ((ret = WIN_GetFullHandle( hwnd )) == GetDesktopWindow()) return 0;
2586 for (;;)
2587 {
2588 HWND parent = GetParent( ret );
2589 if (!parent) break;
2590 ret = parent;
2591 }
2592 break;
2593 }
2594 return ret;
2595 }
2596
2597
2598 /*****************************************************************
2599 * SetParent (USER32.@)
2600 */
2601 HWND WINAPI SetParent( HWND hwnd, HWND parent )
2602 {
2603 HWND full_handle;
2604 HWND old_parent = 0;
2605 BOOL was_visible;
2606 WND *wndPtr;
2607 BOOL ret;
2608
2609 if (is_broadcast(hwnd) || is_broadcast(parent))
2610 {
2611 SetLastError(ERROR_INVALID_PARAMETER);
2612 return 0;
2613 }
2614
2615 if (!parent) parent = GetDesktopWindow();
2616 else parent = WIN_GetFullHandle( parent );
2617
2618 if (!IsWindow( parent ))
2619 {
2620 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
2621 return 0;
2622 }
2623
2624 /* Some applications try to set a child as a parent */
2625 if (IsChild(hwnd, parent))
2626 {
2627 SetLastError( ERROR_INVALID_PARAMETER );
2628 return 0;
2629 }
2630
2631 if (!(full_handle = WIN_IsCurrentThread( hwnd )))
2632 return (HWND)SendMessageW( hwnd, WM_WINE_SETPARENT, (WPARAM)parent, 0 );
2633
2634 /* Windows hides the window first, then shows it again
2635 * including the WM_SHOWWINDOW messages and all */
2636 was_visible = ShowWindow( hwnd, SW_HIDE );
2637
2638 wndPtr = WIN_GetPtr( hwnd );
2639 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return 0;
2640
2641 SERVER_START_REQ( set_parent )
2642 {
2643 req->handle = hwnd;
2644 req->parent = parent;
2645 if ((ret = !wine_server_call( req )))
2646 {
2647 old_parent = reply->old_parent;
2648 wndPtr->parent = parent = reply->full_parent;
2649 }
2650
2651 }
2652 SERVER_END_REQ;
2653 WIN_ReleasePtr( wndPtr );
2654 if (!ret) return 0;
2655
2656 USER_Driver->pSetParent( full_handle, parent, old_parent );
2657
2658 /* SetParent additionally needs to make hwnd the topmost window
2659 in the x-order and send the expected WM_WINDOWPOSCHANGING and
2660 WM_WINDOWPOSCHANGED notification messages.
2661 */
2662 SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0,
2663 SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | (was_visible ? SWP_SHOWWINDOW : 0) );
2664 /* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
2665 * for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE */
2666
2667 return old_parent;
2668 }
2669
2670
2671 /*******************************************************************
2672 * IsChild (USER32.@)
2673 */
2674 BOOL WINAPI IsChild( HWND parent, HWND child )
2675 {
2676 HWND *list = list_window_parents( child );
2677 int i;
2678 BOOL ret;
2679
2680 if (!list) return FALSE;
2681 parent = WIN_GetFullHandle( parent );
2682 for (i = 0; list[i]; i++) if (list[i] == parent) break;
2683 ret = list[i] && list[i+1];
2684 HeapFree( GetProcessHeap(), 0, list );
2685 return ret;
2686 }
2687
2688
2689 /***********************************************************************
2690 * IsWindowVisible (USER32.@)
2691 */
2692 BOOL WINAPI IsWindowVisible( HWND hwnd )
2693 {
2694 HWND *list;
2695 BOOL retval = TRUE;
2696 int i;
2697
2698 if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_VISIBLE)) return FALSE;
2699 if (!(list = list_window_parents( hwnd ))) return TRUE;
2700 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2701 {
2702 for (i = 0; list[i+1]; i++)
2703 if (!(GetWindowLongW( list[i], GWL_STYLE ) & WS_VISIBLE)) break;
2704 retval = !list[i+1];
2705 }
2706 HeapFree( GetProcessHeap(), 0, list );
2707 return retval;
2708 }
2709
2710
2711 /***********************************************************************
2712 * WIN_IsWindowDrawable
2713 *
2714 * hwnd is drawable when it is visible, all parents are not
2715 * minimized, and it is itself not minimized unless we are
2716 * trying to draw its default class icon.
2717 */
2718 BOOL WIN_IsWindowDrawable( HWND hwnd, BOOL icon )
2719 {
2720 HWND *list;
2721 BOOL retval = TRUE;
2722 int i;
2723 LONG style = GetWindowLongW( hwnd, GWL_STYLE );
2724
2725 if (!(style & WS_VISIBLE)) return FALSE;
2726 if ((style & WS_MINIMIZE) && icon && GetClassLongPtrW( hwnd, GCLP_HICON )) return FALSE;
2727
2728 if (!(list = list_window_parents( hwnd ))) return TRUE;
2729 if (list[0] && list[1]) /* desktop window is considered always visible so we don't check it */
2730 {
2731 for (i = 0; list[i+1]; i++)
2732 if ((GetWindowLongW( list[i], GWL_STYLE ) & (WS_VISIBLE|WS_MINIMIZE)) != WS_VISIBLE)
2733 break;
2734 retval = !list[i+1];
2735 }
2736 HeapFree( GetProcessHeap(), 0, list );
2737 return retval;
2738 }
2739
2740
2741 /*******************************************************************
2742 * GetTopWindow (USER32.@)
2743 */
2744 HWND WINAPI GetTopWindow( HWND hwnd )
2745 {
2746 if (!hwnd) hwnd = GetDesktopWindow();
2747 return GetWindow( hwnd, GW_CHILD );
2748 }
2749
2750
2751 /*******************************************************************
2752 * GetWindow (USER32.@)
2753 */
2754 HWND WINAPI GetWindow( HWND hwnd, UINT rel )
2755 {
2756 HWND retval = 0;
2757
2758 if (rel == GW_OWNER) /* this one may be available locally */
2759 {
2760 WND *wndPtr = WIN_GetPtr( hwnd );
2761 if (!wndPtr)
2762 {
2763 SetLastError( ERROR_INVALID_HANDLE );
2764 return 0;
2765 }
2766 if (wndPtr == WND_DESKTOP) return 0;
2767 if (wndPtr != WND_OTHER_PROCESS)
2768 {
2769 retval = wndPtr->owner;
2770 WIN_ReleasePtr( wndPtr );
2771 return retval;
2772 }
2773 /* else fall through to server call */
2774 }
2775
2776 SERVER_START_REQ( get_window_tree )
2777 {
2778 req->handle = hwnd;
2779 if (!wine_server_call_err( req ))
2780 {
2781 switch(rel)
2782 {
2783 case GW_HWNDFIRST:
2784 retval = reply->first_sibling;
2785 break;
2786 case GW_HWNDLAST:
2787 retval = reply->last_sibling;
2788 break;
2789 case GW_HWNDNEXT:
2790 retval = reply->next_sibling;
2791 break;
2792 case GW_HWNDPREV:
2793 retval = reply->prev_sibling;
2794 break;
2795 case GW_OWNER:
2796 retval = reply->owner;
2797 break;
2798 case GW_CHILD:
2799 retval = reply->first_child;
2800 break;
2801 }
2802 }
2803 }
2804 SERVER_END_REQ;
2805 return retval;
2806 }
2807
2808
2809 /*******************************************************************
2810 * ShowOwnedPopups (USER32.@)
2811 */
2812 BOOL WINAPI ShowOwnedPopups( HWND owner, BOOL fShow )
2813 {
2814 int count = 0;
2815 WND *pWnd;
2816 HWND *win_array = WIN_ListChildren( GetDesktopWindow() );
2817
2818 if (!win_array) return TRUE;
2819
2820 while (win_array[count]) count++;
2821 while (--count >= 0)
2822 {
2823 if (GetWindow( win_array[count], GW_OWNER ) != owner) continue;
2824 if (!(pWnd = WIN_GetPtr( win_array[count] ))) continue;
2825 if (pWnd == WND_OTHER_PROCESS) continue;
2826 if (fShow)
2827 {
2828 if (pWnd->flags & WIN_NEEDS_SHOW_OWNEDPOPUP)
2829 {
2830 WIN_ReleasePtr( pWnd );
2831 /* In Windows, ShowOwnedPopups(TRUE) generates
2832 * WM_SHOWWINDOW messages with SW_PARENTOPENING,
2833 * regardless of the state of the owner
2834 */
2835 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_SHOWNORMAL, SW_PARENTOPENING);
2836 continue;
2837 }
2838 }
2839 else
2840 {
2841 if (pWnd->dwStyle & WS_VISIBLE)
2842 {
2843 WIN_ReleasePtr( pWnd );
2844 /* In Windows, ShowOwnedPopups(FALSE) generates
2845 * WM_SHOWWINDOW messages with SW_PARENTCLOSING,
2846 * regardless of the state of the owner
2847 */
2848 SendMessageW(win_array[count], WM_SHOWWINDOW, SW_HIDE, SW_PARENTCLOSING);
2849 continue;
2850 }
2851 }
2852 WIN_ReleasePtr( pWnd );
2853 }
2854 HeapFree( GetProcessHeap(), 0, win_array );
2855 return TRUE;
2856 }
2857
2858
2859 /*******************************************************************
2860 * GetLastActivePopup (USER32.@)
2861 */
2862 HWND WINAPI GetLastActivePopup( HWND hwnd )
2863 {
2864 HWND retval = hwnd;
2865
2866 SERVER_START_REQ( get_window_info )
2867 {
2868 req->handle = hwnd;
2869 if (!wine_server_call_err( req )) retval = reply->last_active;
2870 }
2871 SERVER_END_REQ;
2872 return retval;
2873 }
2874
2875
2876 /*******************************************************************
2877 * WIN_ListChildren
2878 *
2879 * Build an array of the children of a given window. The array must be
2880 * freed with HeapFree. Returns NULL when no windows are found.
2881 */
2882 HWND *WIN_ListChildren( HWND hwnd )
2883 {
2884 return list_window_children( 0, hwnd, NULL, 0 );
2885 }
2886
2887
2888 /*******************************************************************
2889 * EnumWindows (USER32.@)
2890 */
2891 BOOL WINAPI EnumWindows( WNDENUMPROC lpEnumFunc, LPARAM lParam )
2892 {
2893 HWND *list;
2894 BOOL ret = TRUE;
2895 int i;
2896
2897 USER_CheckNotLock();
2898
2899 /* We have to build a list of all windows first, to avoid */
2900 /* unpleasant side-effects, for instance if the callback */
2901 /* function changes the Z-order of the windows. */
2902
2903 if (!(list = WIN_ListChildren( GetDesktopWindow() ))) return TRUE;
2904
2905 /* Now call the callback function for every window */
2906
2907 for (i = 0; list[i]; i++)
2908 {
2909 /* Make sure that the window still exists */
2910 if (!IsWindow( list[i] )) continue;
2911 if (!(ret = lpEnumFunc( list[i], lParam ))) break;
2912 }
2913 HeapFree( GetProcessHeap(), 0, list );
2914 return ret;
2915 }
2916
2917
2918 /**********************************************************************
2919 * EnumThreadWindows (USER32.@)
2920 */
2921 BOOL WINAPI EnumThreadWindows( DWORD id, WNDENUMPROC func, LPARAM lParam )
2922 {
2923 HWND *list;
2924 int i;
2925
2926 USER_CheckNotLock();
2927
2928 if (!(list = list_window_children( 0, GetDesktopWindow(), NULL, id ))) return TRUE;
2929
2930 /* Now call the callback function for every window */
2931
2932 for (i = 0; list[i]; i++)
2933 if (!func( list[i], lParam )) break;
2934 HeapFree( GetProcessHeap(), 0, list );
2935 return TRUE;
2936 }
2937
2938
2939 /***********************************************************************
2940 * EnumDesktopWindows (USER32.@)
2941 */
2942 BOOL WINAPI EnumDesktopWindows( HDESK desktop, WNDENUMPROC func, LPARAM lparam )
2943 {
2944 HWND *list;
2945 int i;
2946
2947 USER_CheckNotLock();
2948
2949 if (!(list = list_window_children( desktop, 0, NULL, 0 ))) return TRUE;
2950
2951 for (i = 0; list[i]; i++)
2952 if (!func( list[i], lparam )) break;
2953 HeapFree( GetProcessHeap(), 0, list );
2954 return TRUE;
2955 }
2956
2957
2958 /**********************************************************************
2959 * WIN_EnumChildWindows
2960 *
2961 * Helper function for EnumChildWindows().
2962 */
2963 static BOOL WIN_EnumChildWindows( HWND *list, WNDENUMPROC func, LPARAM lParam )
2964 {
2965 HWND *childList;
2966 BOOL ret = FALSE;
2967
2968 for ( ; *list; list++)
2969 {
2970 /* Make sure that the window still exists */
2971 if (!IsWindow( *list )) continue;
2972 /* Build children list first */
2973 childList = WIN_ListChildren( *list );
2974
2975 ret = func( *list, lParam );
2976
2977 if (childList)
2978 {
2979 if (ret) ret = WIN_EnumChildWindows( childList, func, lParam );
2980 HeapFree( GetProcessHeap(), 0, childList );
2981 }
2982 if (!ret) return FALSE;
2983 }
2984 return TRUE;
2985 }
2986
2987
2988 /**********************************************************************
2989 * EnumChildWindows (USER32.@)
2990 */
2991 BOOL WINAPI EnumChildWindows( HWND parent, WNDENUMPROC func, LPARAM lParam )
2992 {
2993 HWND *list;
2994 BOOL ret;
2995
2996 USER_CheckNotLock();
2997
2998 if (!(list = WIN_ListChildren( parent ))) return FALSE;
2999 ret = WIN_EnumChildWindows( list, func, lParam );
3000 HeapFree( GetProcessHeap(), 0, list );
3001 return ret;
3002 }
3003
3004
3005 /*******************************************************************
3006 * AnyPopup (USER.52)
3007 */
3008 BOOL16 WINAPI AnyPopup16(void)
3009 {
3010 return AnyPopup();
3011 }
3012
3013
3014 /*******************************************************************
3015 * AnyPopup (USER32.@)
3016 */
3017 BOOL WINAPI AnyPopup(void)
3018 {
3019 int i;
3020 BOOL retvalue;
3021 HWND *list = WIN_ListChildren( GetDesktopWindow() );
3022
3023 if (!list) return FALSE;
3024 for (i = 0; list[i]; i++)
3025 {
3026 if (IsWindowVisible( list[i] ) && GetWindow( list[i], GW_OWNER )) break;
3027 }
3028 retvalue = (list[i] != 0);
3029 HeapFree( GetProcessHeap(), 0, list );
3030 return retvalue;
3031 }
3032
3033
3034 /*******************************************************************
3035 * FlashWindow (USER32.@)
3036 */
3037 BOOL WINAPI FlashWindow( HWND hWnd, BOOL bInvert )
3038 {
3039 WND *wndPtr;
3040
3041 TRACE("%p\n", hWnd);
3042
3043 if (IsIconic( hWnd ))
3044 {
3045 RedrawWindow( hWnd, 0, 0, RDW_INVALIDATE | RDW_ERASE | RDW_UPDATENOW | RDW_FRAME );
3046
3047 wndPtr = WIN_GetPtr(hWnd);
3048 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3049 if (bInvert && !(wndPtr->flags & WIN_NCACTIVATED))
3050 {
3051 wndPtr->flags |= WIN_NCACTIVATED;
3052 }
3053 else
3054 {
3055 wndPtr->flags &= ~WIN_NCACTIVATED;
3056 }
3057 WIN_ReleasePtr( wndPtr );
3058 return TRUE;
3059 }
3060 else
3061 {
3062 WPARAM wparam;
3063
3064 wndPtr = WIN_GetPtr(hWnd);
3065 if (!wndPtr || wndPtr == WND_OTHER_PROCESS || wndPtr == WND_DESKTOP) return FALSE;
3066 hWnd = wndPtr->hwndSelf; /* make it a full handle */
3067
3068 if (bInvert) wparam = !(wndPtr->flags & WIN_NCACTIVATED);
3069 else wparam = (hWnd == GetForegroundWindow());
3070
3071 WIN_ReleasePtr( wndPtr );
3072 SendMessageW( hWnd, WM_NCACTIVATE, wparam, (LPARAM)0 );
3073 return wparam;
3074 }
3075 }
3076
3077 /*******************************************************************
3078 * FlashWindowEx (USER32.@)
3079 */
3080 BOOL WINAPI FlashWindowEx( PFLASHWINFO pfwi )
3081 {
3082 FIXME("%p\n", pfwi);
3083 return TRUE;
3084 }
3085
3086 /*******************************************************************
3087 * GetWindowContextHelpId (USER32.@)
3088 */
3089 DWORD WINAPI GetWindowContextHelpId( HWND hwnd )
3090 {
3091 DWORD retval;
3092 WND *wnd = WIN_GetPtr( hwnd );
3093 if (!wnd || wnd == WND_DESKTOP) return 0;
3094 if (wnd == WND_OTHER_PROCESS)
3095 {
3096 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3097 return 0;
3098 }
3099 retval = wnd->helpContext;
3100 WIN_ReleasePtr( wnd );
3101 return retval;
3102 }
3103
3104
3105 /*******************************************************************
3106 * SetWindowContextHelpId (USER32.@)
3107 */
3108 BOOL WINAPI SetWindowContextHelpId( HWND hwnd, DWORD id )
3109 {
3110 WND *wnd = WIN_GetPtr( hwnd );
3111 if (!wnd || wnd == WND_DESKTOP) return FALSE;
3112 if (wnd == WND_OTHER_PROCESS)
3113 {
3114 if (IsWindow( hwnd )) FIXME( "not supported on other process window %p\n", hwnd );
3115 return 0;
3116 }
3117 wnd->helpContext = id;
3118 WIN_ReleasePtr( wnd );
3119 return TRUE;
3120 }
3121
3122
3123 /*******************************************************************
3124 * DragDetect (USER32.@)
3125 */
3126 BOOL WINAPI DragDetect( HWND hWnd, POINT pt )
3127 {
3128 MSG msg;
3129 RECT rect;
3130 WORD wDragWidth = GetSystemMetrics(SM_CXDRAG);
3131 WORD wDragHeight= GetSystemMetrics(SM_CYDRAG);
3132
3133 rect.left = pt.x - wDragWidth;
3134 rect.right = pt.x + wDragWidth;
3135
3136 rect.top = pt.y - wDragHeight;
3137 rect.bottom = pt.y + wDragHeight;
3138
3139 SetCapture(hWnd);
3140
3141 while(1)
3142 {
3143 while (PeekMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE ))
3144 {
3145 if( msg.message == WM_LBUTTONUP )
3146 {
3147 ReleaseCapture();
3148 return 0;
3149 }
3150 if( msg.message == WM_MOUSEMOVE )
3151 {
3152 POINT tmp;
3153 tmp.x = (short)LOWORD(msg.lParam);
3154 tmp.y = (short)HIWORD(msg.lParam);
3155 if( !PtInRect( &rect, tmp ))
3156 {
3157 ReleaseCapture();
3158 return 1;
3159 }
3160 }
3161 }
3162 WaitMessage();
3163 }
3164 return 0;
3165 }
3166
3167 /******************************************************************************
3168 * GetWindowModuleFileNameA (USER32.@)
3169 */
3170 UINT WINAPI GetWindowModuleFileNameA( HWND hwnd, LPSTR module, UINT size )
3171 {
3172 WND *win;
3173 HINSTANCE hinst;
3174
3175 TRACE( "%p, %p, %u\n", hwnd, module, size );
3176
3177 win = WIN_GetPtr( hwnd );
3178 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3179 {
3180 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3181 return 0;
3182 }
3183 hinst = win->hInstance;
3184 WIN_ReleasePtr( win );
3185
3186 return GetModuleFileNameA( hinst, module, size );
3187 }
3188
3189 /******************************************************************************
3190 * GetWindowModuleFileNameW (USER32.@)
3191 */
3192 UINT WINAPI GetWindowModuleFileNameW( HWND hwnd, LPWSTR module, UINT size )
3193 {
3194 WND *win;
3195 HINSTANCE hinst;
3196
3197 TRACE( "%p, %p, %u\n", hwnd, module, size );
3198
3199 win = WIN_GetPtr( hwnd );
3200 if (!win || win == WND_OTHER_PROCESS || win == WND_DESKTOP)
3201 {
3202 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
3203 return 0;
3204 }
3205 hinst = win->hInstance;
3206 WIN_ReleasePtr( win );
3207
3208 return GetModuleFileNameW( hinst, module, size );
3209 }
3210
3211 /******************************************************************************
3212 * GetWindowInfo (USER32.@)
3213 *
3214 * Note: tests show that Windows doesn't check cbSize of the structure.
3215 */
3216 BOOL WINAPI GetWindowInfo( HWND hwnd, PWINDOWINFO pwi)
3217 {
3218 if (!pwi) return FALSE;
3219 if (!IsWindow(hwnd)) return FALSE;
3220
3221 GetWindowRect(hwnd, &pwi->rcWindow);
3222 GetClientRect(hwnd, &pwi->rcClient);
3223 /* translate to screen coordinates */
3224 MapWindowPoints(hwnd, 0, (LPPOINT)&pwi->rcClient, 2);
3225
3226 pwi->dwStyle = GetWindowLongW(hwnd, GWL_STYLE);
3227 pwi->dwExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
3228 pwi->dwWindowStatus = ((GetActiveWindow() == hwnd) ? WS_ACTIVECAPTION : 0);
3229
3230 pwi->cxWindowBorders = pwi->rcClient.left - pwi->rcWindow.left;
3231 pwi->cyWindowBorders = pwi->rcWindow.bottom - pwi->rcClient.bottom;
3232
3233 pwi->atomWindowType = GetClassLongW( hwnd, GCW_ATOM );
3234 pwi->wCreatorVersion = 0x0400;
3235
3236 return TRUE;
3237 }
3238
3239 /******************************************************************************
3240 * SwitchDesktop (USER32.@)
3241 *
3242 * NOTES: Sets the current input or interactive desktop.
3243 */
3244 BOOL WINAPI SwitchDesktop( HDESK hDesktop)
3245 {
3246 FIXME("SwitchDesktop(hwnd %p) stub!\n", hDesktop);
3247 return TRUE;
3248 }
3249
3250 /*****************************************************************************
3251 * SetLayeredWindowAttributes (USER32.@)
3252 */
3253 BOOL WINAPI SetLayeredWindowAttributes( HWND hWnd, COLORREF rgbKey,
3254 BYTE bAlpha, DWORD dwFlags )
3255 {
3256 FIXME("(%p,0x%.8x,%d,%d): stub!\n", hWnd, rgbKey, bAlpha, dwFlags);
3257 return TRUE;
3258 }
3259
3260 /*****************************************************************************
3261 * GetLayeredWindowAttributes (USER32.@)
3262 */
3263 BOOL WINAPI GetLayeredWindowAttributes( HWND hWnd, COLORREF *prgbKey,
3264 BYTE *pbAlpha, DWORD *pdwFlags )
3265 {
3266 FIXME("(%p,%p,%p,%p): stub!\n", hWnd, prgbKey, pbAlpha, pdwFlags);
3267 return FALSE;
3268 }
3269
3270 /*****************************************************************************
3271 * UpdateLayeredWindow (USER32.@)
3272 */
3273 BOOL WINAPI UpdateLayeredWindow( HWND hwnd, HDC hdcDst, POINT *pptDst, SIZE *psize,
3274 HDC hdcSrc, POINT *pptSrc, COLORREF crKey, BLENDFUNCTION *pblend,
3275 DWORD dwFlags)
3276 {
3277 static int once;
3278 if (!once)
3279 {
3280 once = 1;
3281 FIXME("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%d): stub!\n",
3282 hwnd, hdcDst, pptDst, psize, hdcSrc, pptSrc, crKey, pblend, dwFlags);
3283 }
3284 return 0;
3285 }
3286
3287 /* 64bit versions */
3288
3289 #ifdef GetWindowLongPtrW
3290 #undef GetWindowLongPtrW
3291 #endif
3292
3293 #ifdef GetWindowLongPtrA
3294 #undef GetWindowLongPtrA
3295 #endif
3296
3297 #ifdef SetWindowLongPtrW
3298 #undef SetWindowLongPtrW
3299 #endif
3300
3301 #ifdef SetWindowLongPtrA
3302 #undef SetWindowLongPtrA
3303 #endif
3304
3305 /*****************************************************************************
3306 * GetWindowLongPtrW (USER32.@)
3307 */
3308 LONG_PTR WINAPI GetWindowLongPtrW( HWND hwnd, INT offset )
3309 {
3310 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), TRUE );
3311 }
3312
3313 /*****************************************************************************
3314 * GetWindowLongPtrA (USER32.@)
3315 */
3316 LONG_PTR WINAPI GetWindowLongPtrA( HWND hwnd, INT offset )
3317 {
3318 return WIN_GetWindowLong( hwnd, offset, sizeof(LONG_PTR), FALSE );
3319 }
3320
3321 /*****************************************************************************
3322 * SetWindowLongPtrW (USER32.@)
3323 */
3324 LONG_PTR WINAPI SetWindowLongPtrW( HWND hwnd, INT offset, LONG_PTR newval )
3325 {
3326 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, TRUE );
3327 }
3328
3329 /*****************************************************************************
3330 * SetWindowLongPtrA (USER32.@)
3331 */
3332 LONG_PTR WINAPI SetWindowLongPtrA( HWND hwnd, INT offset, LONG_PTR newval )
3333 {
3334 return WIN_SetWindowLong( hwnd, offset, sizeof(LONG_PTR), newval, FALSE );
3335 }
3336
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.