update for HEAD-2003091401
[reactos.git] / lib / user32 / windows / window.c
1 /* $Id$
2  *
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS user32.dll
5  * FILE:            lib/user32/windows/window.c
6  * PURPOSE:         Window management
7  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
8  * UPDATE HISTORY:
9  *      06-06-2001  CSH  Created
10  */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <windows.h>
15 #include <user32.h>
16 #include <window.h>
17 #include <string.h>
18 #include <user32/callback.h>
19 #include <user32/regcontrol.h>
20
21 #define NDEBUG
22 #include <debug.h>
23
24 static BOOL ControlsInitCalled = FALSE;
25
26 /* FUNCTIONS *****************************************************************/
27 ULONG
28 WinHasThickFrameStyle(ULONG Style, ULONG ExStyle)
29 {
30   return((Style & WS_THICKFRAME) &&
31          (!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
32 }
33
34
35 NTSTATUS STDCALL
36 User32SendNCCALCSIZEMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
37 {
38   PSENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS CallbackArgs;
39   SENDNCCALCSIZEMESSAGE_CALLBACK_RESULT Result;
40   WNDPROC Proc;
41
42   DPRINT("User32SendNCCALCSIZEMessageForKernel.\n");
43   CallbackArgs = (PSENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS)Arguments;
44   if (ArgumentLength != sizeof(SENDNCCALCSIZEMESSAGE_CALLBACK_ARGUMENTS))
45     {
46       DPRINT("Wrong length.\n");
47       return(STATUS_INFO_LENGTH_MISMATCH);
48     }
49   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
50   DPRINT("Proc %X\n", Proc);
51   /* Call the window procedure; notice kernel messages are always unicode. */
52   if (CallbackArgs->Validate)
53     {
54       Result.Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_NCCALCSIZE, 
55                                       TRUE, 
56                                       (LPARAM)&CallbackArgs->Params);
57       Result.Params = CallbackArgs->Params;
58     }
59   else
60     {
61       Result.Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_NCCALCSIZE,
62                                       FALSE, (LPARAM)&CallbackArgs->Rect);
63       Result.Rect = CallbackArgs->Rect;
64     }
65   DPRINT("Returning result %d.\n", Result);
66   return(ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS));
67 }
68
69
70 NTSTATUS STDCALL
71 User32SendGETMINMAXINFOMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
72 {
73   PSENDGETMINMAXINFO_CALLBACK_ARGUMENTS CallbackArgs;
74   SENDGETMINMAXINFO_CALLBACK_RESULT Result;
75   WNDPROC Proc;
76
77   DPRINT("User32SendGETMINAXINFOMessageForKernel.\n");
78   CallbackArgs = (PSENDGETMINMAXINFO_CALLBACK_ARGUMENTS)Arguments;
79   if (ArgumentLength != sizeof(SENDGETMINMAXINFO_CALLBACK_ARGUMENTS))
80     {
81       DPRINT("Wrong length.\n");
82       return(STATUS_INFO_LENGTH_MISMATCH);
83     }
84   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
85   DPRINT("Proc %X\n", Proc);
86   /* Call the window procedure; notice kernel messages are always unicode. */
87   Result.Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_GETMINMAXINFO, 
88                                   0, (LPARAM)&CallbackArgs->MinMaxInfo);
89   Result.MinMaxInfo = CallbackArgs->MinMaxInfo;
90   DPRINT("Returning result %d.\n", Result);
91   return(ZwCallbackReturn(&Result, sizeof(Result), STATUS_SUCCESS));
92 }
93
94
95 NTSTATUS STDCALL
96 User32SendCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
97 {
98   PSENDCREATEMESSAGE_CALLBACK_ARGUMENTS CallbackArgs;
99   WNDPROC Proc;
100   LRESULT Result;
101
102   DPRINT("User32SendCREATEMessageForKernel.\n");
103   CallbackArgs = (PSENDCREATEMESSAGE_CALLBACK_ARGUMENTS)Arguments;
104   if (ArgumentLength != sizeof(SENDCREATEMESSAGE_CALLBACK_ARGUMENTS))
105     {
106       DPRINT("Wrong length.\n");
107       return(STATUS_INFO_LENGTH_MISMATCH);
108     }
109   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
110   DPRINT("Proc %X\n", Proc);
111   /* Call the window procedure; notice kernel messages are always unicode. */
112   Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_CREATE, 0, 
113                            (LPARAM)&CallbackArgs->CreateStruct);
114   DPRINT("Returning result %d.\n", Result);
115   return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
116 }
117
118
119 NTSTATUS STDCALL
120 User32SendNCCREATEMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
121 {
122   PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS CallbackArgs;
123   WNDPROC Proc;
124   LRESULT Result;
125
126   DPRINT("User32SendNCCREATEMessageForKernel.\n");
127   CallbackArgs = (PSENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS)Arguments;
128   if (ArgumentLength != sizeof(SENDNCCREATEMESSAGE_CALLBACK_ARGUMENTS))
129     {
130       DPRINT("Wrong length.\n");
131       return(STATUS_INFO_LENGTH_MISMATCH);
132     }
133   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
134   DPRINT("Proc %X\n", Proc);
135   /* Call the window procedure; notice kernel messages are always unicode. */
136   Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_NCCREATE, 0, 
137                            (LPARAM)&CallbackArgs->CreateStruct);
138   DPRINT("Returning result %d.\n", Result);
139   return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
140 }
141
142
143 NTSTATUS STDCALL
144 User32SendWINDOWPOSCHANGINGMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
145 {
146   PSENDWINDOWPOSCHANGING_CALLBACK_ARGUMENTS CallbackArgs;
147   WNDPROC Proc;
148   LRESULT Result;
149
150   DPRINT("User32SendWINDOWPOSCHANGINGMessageForKernel.\n");
151   CallbackArgs = (PSENDWINDOWPOSCHANGING_CALLBACK_ARGUMENTS)Arguments;
152   if (ArgumentLength != sizeof(SENDWINDOWPOSCHANGING_CALLBACK_ARGUMENTS))
153     {
154       DPRINT("Wrong length.\n");
155       return(STATUS_INFO_LENGTH_MISMATCH);
156     }
157   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
158   DPRINT("Proc %X\n", Proc);
159   /* Call the window procedure; notice kernel messages are always unicode. */
160   Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_WINDOWPOSCHANGING, 0, 
161                            (LPARAM)&CallbackArgs->WindowPos);
162   DPRINT("Returning result %d.\n", Result);
163   return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
164 }
165
166
167 NTSTATUS STDCALL
168 User32SendWINDOWPOSCHANGEDMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
169 {
170   PSENDWINDOWPOSCHANGED_CALLBACK_ARGUMENTS CallbackArgs;
171   WNDPROC Proc;
172   LRESULT Result;
173
174   DPRINT("User32SendWINDOWPOSCHANGEDMessageForKernel.\n");
175   CallbackArgs = (PSENDWINDOWPOSCHANGED_CALLBACK_ARGUMENTS)Arguments;
176   if (ArgumentLength != sizeof(SENDWINDOWPOSCHANGED_CALLBACK_ARGUMENTS))
177     {
178       DPRINT("Wrong length.\n");
179       return(STATUS_INFO_LENGTH_MISMATCH);
180     }
181   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
182   DPRINT("Proc %X\n", Proc);
183   /* Call the window procedure; notice kernel messages are always unicode. */
184   Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_WINDOWPOSCHANGED, 0, 
185                            (LPARAM)&CallbackArgs->WindowPos);
186   DPRINT("Returning result %d.\n", Result);
187   return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
188 }
189
190
191 NTSTATUS STDCALL
192 User32SendSTYLECHANGINGMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
193 {
194   PSENDSTYLECHANGING_CALLBACK_ARGUMENTS CallbackArgs;
195   WNDPROC Proc;
196   LRESULT Result;
197
198   DPRINT("User32SendSTYLECHANGINGMessageForKernel.\n");
199   CallbackArgs = (PSENDSTYLECHANGING_CALLBACK_ARGUMENTS)Arguments;
200   if (ArgumentLength != sizeof(SENDSTYLECHANGING_CALLBACK_ARGUMENTS))
201     {
202       DPRINT("Wrong length.\n");
203       return(STATUS_INFO_LENGTH_MISMATCH);
204     }
205   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
206   DPRINT("Proc %X\n", Proc);
207   /* Call the window procedure; notice kernel messages are always unicode. */
208   Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_STYLECHANGING, CallbackArgs->WhichStyle,
209                            (LPARAM)&CallbackArgs->Style);
210   DPRINT("Returning result %d.\n", Result);
211   return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
212 }
213
214
215 NTSTATUS STDCALL
216 User32SendSTYLECHANGEDMessageForKernel(PVOID Arguments, ULONG ArgumentLength)
217 {
218   PSENDSTYLECHANGED_CALLBACK_ARGUMENTS CallbackArgs;
219   WNDPROC Proc;
220   LRESULT Result;
221
222   DPRINT("User32SendSTYLECHANGEDGMessageForKernel.\n");
223   CallbackArgs = (PSENDSTYLECHANGED_CALLBACK_ARGUMENTS)Arguments;
224   if (ArgumentLength != sizeof(SENDSTYLECHANGED_CALLBACK_ARGUMENTS))
225     {
226       DPRINT("Wrong length.\n");
227       return(STATUS_INFO_LENGTH_MISMATCH);
228     }
229   Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
230   DPRINT("Proc %X\n", Proc);
231   /* Call the window procedure; notice kernel messages are always unicode. */
232   Result = CallWindowProcW(Proc, CallbackArgs->Wnd, WM_STYLECHANGED, CallbackArgs->WhichStyle,
233                            (LPARAM)&CallbackArgs->Style);
234   DPRINT("Returning result %d.\n", Result);
235   return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
236 }
237
238
239 NTSTATUS STDCALL
240 User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength)
241 {
242   PSENDASYNCPROC_CALLBACK_ARGUMENTS CallbackArgs;
243
244   DPRINT("User32CallSendAsyncProcKernel()\n");
245   CallbackArgs = (PSENDASYNCPROC_CALLBACK_ARGUMENTS)Arguments;
246   if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS))
247     {
248       return(STATUS_INFO_LENGTH_MISMATCH);
249     }
250   CallbackArgs->Callback(CallbackArgs->Wnd, CallbackArgs->Msg,
251                          CallbackArgs->Context, CallbackArgs->Result);
252   return(STATUS_SUCCESS);
253 }
254
255
256 NTSTATUS STDCALL
257 User32CallWindowProcFromKernel(PVOID Arguments, ULONG ArgumentLength)
258 {
259   PWINDOWPROC_CALLBACK_ARGUMENTS CallbackArgs;
260   LRESULT Result;
261
262   CallbackArgs = (PWINDOWPROC_CALLBACK_ARGUMENTS)Arguments;
263   if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS))
264     {
265       return(STATUS_INFO_LENGTH_MISMATCH);
266     }
267   if (CallbackArgs->Proc == NULL)
268     {
269       CallbackArgs->Proc = (WNDPROC)NtUserGetWindowLong(CallbackArgs->Wnd, GWL_WNDPROC, FALSE);
270     }
271   Result = CallWindowProcW(CallbackArgs->Proc, CallbackArgs->Wnd, 
272                            CallbackArgs->Msg, CallbackArgs->wParam, 
273                            CallbackArgs->lParam);
274   return(ZwCallbackReturn(&Result, sizeof(LRESULT), STATUS_SUCCESS));
275 }
276
277
278 static void NC_AdjustRectOuter95 (LPRECT rect, DWORD style, BOOL menu, DWORD exStyle)
279 {
280     int adjust;
281     if(style & WS_ICONIC) return;
282
283     if ((exStyle & (WS_EX_STATICEDGE|WS_EX_DLGMODALFRAME)) ==
284         WS_EX_STATICEDGE)
285     {
286         adjust = 1; /* for the outer frame always present */
287     }
288     else
289     {
290         adjust = 0;
291         if ((exStyle & WS_EX_DLGMODALFRAME) ||
292             (style & (WS_THICKFRAME|WS_DLGFRAME))) adjust = 2; /* outer */
293     }
294     if (style & WS_THICKFRAME)
295         adjust +=  ( GetSystemMetrics (SM_CXFRAME)
296                    - GetSystemMetrics (SM_CXDLGFRAME)); /* The resize border */
297     if ((style & (WS_BORDER|WS_DLGFRAME)) ||
298         (exStyle & WS_EX_DLGMODALFRAME))
299         adjust++; /* The other border */
300
301     InflateRect (rect, adjust, adjust);
302
303     if ((style & WS_CAPTION) == WS_CAPTION)
304     {
305         if (exStyle & WS_EX_TOOLWINDOW)
306             rect->top -= GetSystemMetrics(SM_CYSMCAPTION);
307         else
308             rect->top -= GetSystemMetrics(SM_CYCAPTION);
309     }
310     if (menu) rect->top -= GetSystemMetrics(SM_CYMENU);
311 }
312
313
314 static void
315 NC_AdjustRectInner95 (LPRECT rect, DWORD style, DWORD exStyle)
316 {
317     if(style & WS_ICONIC) return;
318
319     if (exStyle & WS_EX_CLIENTEDGE)
320         InflateRect(rect, GetSystemMetrics(SM_CXEDGE), GetSystemMetrics(SM_CYEDGE));
321
322     if (style & WS_VSCROLL)
323     {
324         if((exStyle & WS_EX_LEFTSCROLLBAR) != 0)
325             rect->left  -= GetSystemMetrics(SM_CXVSCROLL);
326         else
327             rect->right += GetSystemMetrics(SM_CXVSCROLL);
328     }
329     if (style & WS_HSCROLL) rect->bottom += GetSystemMetrics(SM_CYHSCROLL);
330 }
331
332
333 /*
334  * @implemented
335  */
336 WINBOOL STDCALL
337 AdjustWindowRectEx(LPRECT lpRect, 
338                    DWORD dwStyle, 
339                    WINBOOL bMenu, 
340                    DWORD dwExStyle)
341 {
342     dwStyle &= (WS_DLGFRAME | WS_BORDER | WS_THICKFRAME | WS_CHILD);
343     dwExStyle &= (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE |
344                 WS_EX_STATICEDGE | WS_EX_TOOLWINDOW);
345     if (dwExStyle & WS_EX_DLGMODALFRAME) dwStyle &= ~WS_THICKFRAME;
346
347     NC_AdjustRectOuter95( lpRect, dwStyle, bMenu, dwExStyle );
348     NC_AdjustRectInner95( lpRect, dwStyle, dwExStyle );
349     lpRect->right += 2;
350     lpRect->bottom += 2;
351     return TRUE;
352 }
353
354
355 /*
356  * @implemented
357  */
358 WINBOOL STDCALL
359 AdjustWindowRect(LPRECT lpRect,
360                  DWORD dwStyle,
361                  WINBOOL bMenu)
362 {
363   return(AdjustWindowRectEx(lpRect, dwStyle, bMenu, 0));
364 }
365
366
367 /*
368  * @unimplemented
369  */
370 WINBOOL STDCALL
371 AllowSetForegroundWindow(DWORD dwProcessId)
372 {
373   UNIMPLEMENTED;
374   return(FALSE);
375 }
376
377
378 /*
379  * @unimplemented
380  */
381 UINT STDCALL
382 ArrangeIconicWindows(HWND hWnd)
383 {
384   UNIMPLEMENTED;
385   return 0;
386 }
387
388
389 /*
390  * @unimplemented
391  */
392 HDWP STDCALL
393 BeginDeferWindowPos(int nNumWindows)
394 {
395   UNIMPLEMENTED;
396   return (HDWP)0;
397 }
398
399
400 /*
401  * @unimplemented
402  */
403 WINBOOL STDCALL
404 BringWindowToTop(HWND hWnd)
405 {
406   UNIMPLEMENTED;
407   return FALSE;
408 }
409
410
411 /*
412  * @unimplemented
413  */
414 WORD STDCALL
415 CascadeWindows(HWND hwndParent,
416                UINT wHow,
417                CONST RECT *lpRect,
418                UINT cKids,
419                const HWND *lpKids)
420 {
421   UNIMPLEMENTED;
422   return 0;
423 }
424
425
426 /*
427  * @unimplemented
428  */
429 HWND STDCALL
430 ChildWindowFromPoint(HWND hWndParent,
431                      POINT Point)
432 {
433   UNIMPLEMENTED;
434   return (HWND)0;
435 }
436
437
438 /*
439  * @unimplemented
440  */
441 HWND STDCALL
442 ChildWindowFromPointEx(HWND hwndParent,
443                        POINT pt,
444                        UINT uFlags)
445 {
446   UNIMPLEMENTED;
447   return (HWND)0;
448 }
449
450
451 /*
452  * @implemented
453  */
454 WINBOOL STDCALL
455 CloseWindow(HWND hWnd)
456 {
457     SendMessageA(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
458
459     return (WINBOOL)(hWnd);
460 }
461
462 /*
463  * @implemented
464  */
465 HWND STDCALL
466 CreateWindowExA(DWORD dwExStyle,
467                 LPCSTR lpClassName,
468                 LPCSTR lpWindowName,
469                 DWORD dwStyle,
470                 int x,
471                 int y,
472                 int nWidth,
473                 int nHeight,
474                 HWND hWndParent,
475                 HMENU hMenu,
476                 HINSTANCE hInstance,
477                 LPVOID lpParam)
478 {
479   UNICODE_STRING WindowName;
480   UNICODE_STRING ClassName;
481   WNDCLASSEXA wce;
482   HWND Handle;
483   INT sw;
484
485 #if 0
486   DbgPrint("[window] CreateWindowExA style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent);
487 #endif
488
489   /* Register built-in controls if not already done */
490   if (! ControlsInitCalled)
491     {
492       ControlsInit();
493       ControlsInitCalled = TRUE;
494     }
495
496   if (IS_ATOM(lpClassName))
497     {
498       RtlInitUnicodeString(&ClassName, NULL);
499       ClassName.Buffer = (LPWSTR)lpClassName;
500     }
501   else
502     {
503       if (!RtlCreateUnicodeStringFromAsciiz(&(ClassName), (PCSZ)lpClassName))
504         {
505           SetLastError(ERROR_OUTOFMEMORY);
506           return (HWND)0;
507         }
508     }
509
510   if (!RtlCreateUnicodeStringFromAsciiz(&WindowName, (PCSZ)lpWindowName))
511     {
512       if (!IS_ATOM(lpClassName))
513         {
514           RtlFreeUnicodeString(&ClassName);
515         }
516       SetLastError(ERROR_OUTOFMEMORY);
517       return (HWND)0;
518     }
519
520   /* Fixup default coordinates. */
521   sw = SW_SHOW;
522   if (x == (LONG) CW_USEDEFAULT || nWidth == (LONG) CW_USEDEFAULT)
523     {
524       if (dwStyle & (WS_CHILD | WS_POPUP))
525         {
526           if (x == (LONG) CW_USEDEFAULT)
527             {
528               x = y = 0;
529             }
530           if (nWidth == (LONG) CW_USEDEFAULT)
531             {
532               nWidth = nHeight = 0;
533             }
534         }
535       else
536         {
537           STARTUPINFOA info;
538
539           GetStartupInfoA(&info);
540
541           if (x == (LONG) CW_USEDEFAULT)
542             {
543               if (y != (LONG) CW_USEDEFAULT)
544                 {
545                   sw = y;
546                 }
547               x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
548               y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
549             }
550           
551           if (nWidth == (LONG) CW_USEDEFAULT)
552             {
553               if (info.dwFlags & STARTF_USESIZE)
554                 {
555                   nWidth = info.dwXSize;
556                   nHeight = info.dwYSize;
557                 }
558               else
559                 {
560                   RECT r;
561
562                   SystemParametersInfoA(SPI_GETWORKAREA, 0, &r, 0);
563                   nWidth = (((r.right - r.left) * 3) / 4) - x;
564                   nHeight = (((r.bottom - r.top) * 3) / 4) - y;
565                 }
566             }
567         }
568     }
569     
570   if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP)))
571   {
572     wce.cbSize = sizeof(WNDCLASSEXA);
573     if(GetClassInfoExA(hInstance, lpClassName, &wce) && wce.lpszMenuName)
574     {
575       hMenu = LoadMenuA(hInstance, wce.lpszMenuName);
576     }
577   }
578
579   Handle = NtUserCreateWindowEx(dwExStyle,
580                                 &ClassName,
581                                 &WindowName,
582                                 dwStyle,
583                                 x,
584                                 y,
585                                 nWidth,
586                                 nHeight,
587                                 hWndParent,
588                                 hMenu,
589                                 hInstance,
590                                 lpParam,
591                                 sw);
592
593 #if 0
594   DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle);
595 #endif
596
597   RtlFreeUnicodeString(&WindowName);
598
599   if (!IS_ATOM(lpClassName)) 
600     {
601       RtlFreeUnicodeString(&ClassName);
602     }
603   
604   return Handle;
605 }
606
607
608 /*
609  * @implemented
610  */
611 HWND STDCALL
612 CreateWindowExW(DWORD dwExStyle,
613                 LPCWSTR lpClassName,
614                 LPCWSTR lpWindowName,
615                 DWORD dwStyle,
616                 int x,
617                 int y,
618                 int nWidth,
619                 int nHeight,
620                 HWND hWndParent,
621                 HMENU hMenu,
622                 HINSTANCE hInstance,
623                 LPVOID lpParam)
624 {
625   UNICODE_STRING WindowName;
626   UNICODE_STRING ClassName;
627   WNDCLASSEXW wce;
628   HANDLE Handle;
629   UINT sw;
630
631   /* Register built-in controls if not already done */
632   if (! ControlsInitCalled)
633     {
634       ControlsInit();
635       ControlsInitCalled = TRUE;
636     }
637
638   if (IS_ATOM(lpClassName)) 
639     {
640       RtlInitUnicodeString(&ClassName, NULL);
641       ClassName.Buffer = (LPWSTR)lpClassName;
642     } 
643   else 
644     {
645       RtlInitUnicodeString(&ClassName, lpClassName);
646     }
647
648   RtlInitUnicodeString(&WindowName, lpWindowName);
649
650   /* Fixup default coordinates. */
651   sw = SW_SHOW;
652   if (x == (LONG) CW_USEDEFAULT || nWidth == (LONG) CW_USEDEFAULT)
653     {
654       if (dwStyle & (WS_CHILD | WS_POPUP))
655         {
656           if (x == (LONG) CW_USEDEFAULT)
657             {
658               x = y = 0;
659             }
660           if (nWidth == (LONG) CW_USEDEFAULT)
661             {
662               nWidth = nHeight = 0;
663             }
664         }
665       else
666         {
667           STARTUPINFOW info;
668
669           GetStartupInfoW(&info);
670
671           if (x == (LONG) CW_USEDEFAULT)
672             {
673               if (y != (LONG) CW_USEDEFAULT)
674                 {
675                   sw = y;
676                 }
677               x = (info.dwFlags & STARTF_USEPOSITION) ? info.dwX : 0;
678               y = (info.dwFlags & STARTF_USEPOSITION) ? info.dwY : 0;
679             }
680           
681           if (nWidth == (LONG) CW_USEDEFAULT)
682             {
683               if (info.dwFlags & STARTF_USESIZE)
684                 {
685                   nWidth = info.dwXSize;
686                   nHeight = info.dwYSize;
687                 }
688               else
689                 {
690                   RECT r;
691
692                   SystemParametersInfoW(SPI_GETWORKAREA, 0, &r, 0);
693                   nWidth = (((r.right - r.left) * 3) / 4) - x;
694                   nHeight = (((r.bottom - r.top) * 3) / 4) - y;
695                 }
696             }
697         }
698     }
699
700   if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP)))
701   {
702     wce.cbSize = sizeof(WNDCLASSEXW);
703     if(GetClassInfoExW(hInstance, lpClassName, &wce) && wce.lpszMenuName)
704     {
705       hMenu = LoadMenuW(hInstance, wce.lpszMenuName);
706     }
707   }
708
709   Handle = NtUserCreateWindowEx(dwExStyle,
710                                 &ClassName,
711                                 &WindowName,
712                                 dwStyle,
713                                 x,
714                                 y,
715                                 nWidth,
716                                 nHeight,
717                                 hWndParent,
718                                 hMenu,
719                                 hInstance,
720                                 lpParam,
721                                 sw);
722
723   return (HWND)Handle;
724 }
725
726
727 /*
728  * @unimplemented
729  */
730 HDWP STDCALL
731 DeferWindowPos(HDWP hWinPosInfo,
732                HWND hWnd,
733                HWND hWndInsertAfter,
734                int x,
735                int y,
736                int cx,
737                int cy,
738                UINT uFlags)
739 {
740   return NtUserDeferWindowPos(hWinPosInfo, hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
741 }
742
743
744 /*
745  * @implemented
746  */
747 WINBOOL STDCALL
748 DestroyWindow(HWND hWnd)
749 {
750   return NtUserDestroyWindow(hWnd);
751 }
752
753
754 /*
755  * @unimplemented
756  */
757 WINBOOL STDCALL
758 EndDeferWindowPos(HDWP hWinPosInfo)
759 {
760   UNIMPLEMENTED;
761   return FALSE;
762 }
763
764
765 /*
766  * @implemented
767  */
768 HWND STDCALL
769 GetDesktopWindow(VOID)
770 {
771         return NtUserGetDesktopWindow();
772 }
773
774
775 /*
776  * @unimplemented
777  */
778 HWND STDCALL
779 GetForegroundWindow(VOID)
780 {
781   UNIMPLEMENTED;
782   return (HWND)0;
783 }
784
785
786 WINBOOL
787 STATIC
788 User32EnumWindows (
789         HDESK hDesktop,
790         HWND hWndparent,
791         ENUMWINDOWSPROC lpfn,
792         LPARAM lParam,
793         DWORD dwThreadId,
794         BOOL bChildren )
795 {
796   DWORD i, dwCount = 0;
797   HWND* pHwnd = NULL;
798   HANDLE hHeap;
799
800   if ( !lpfn )
801     {
802       SetLastError ( ERROR_INVALID_PARAMETER );
803       return FALSE;
804     }
805
806   /* FIXME instead of always making two calls, should we use some
807      sort of persistent buffer and only grow it ( requiring a 2nd
808      call ) when the buffer wasn't already big enough? */
809   /* first get how many window entries there are */
810   SetLastError(0);
811   dwCount = NtUserBuildHwndList (
812     hDesktop, hWndparent, bChildren, dwThreadId, lParam, NULL, 0 );
813   if ( !dwCount || GetLastError() )
814     return FALSE;
815
816   /* allocate buffer to receive HWND handles */
817   hHeap = GetProcessHeap();
818   pHwnd = HeapAlloc ( hHeap, 0, sizeof(HWND)*(dwCount+1) );
819   if ( !pHwnd )
820     {
821       SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
822       return FALSE;
823     }
824
825   /* now call kernel again to fill the buffer this time */
826   dwCount = NtUserBuildHwndList (
827     hDesktop, hWndparent, bChildren, dwThreadId, lParam, pHwnd, dwCount );
828   if ( !dwCount || GetLastError() )
829     {
830       if ( pHwnd )
831         HeapFree ( hHeap, 0, pHwnd );
832       return FALSE;
833     }
834
835   /* call the user's callback function until we're done or
836      they tell us to quit */
837   for ( i = 0; i < dwCount; i++ )
838   {
839     /* FIXME I'm only getting NULLs from Thread Enumeration, and it's
840      * probably because I'm not doing it right in NtUserBuildHwndList.
841      * Once that's fixed, we shouldn't have to check for a NULL HWND
842      * here
843      */
844     if ( !(ULONG)pHwnd[i] ) /* don't enumerate a NULL HWND */
845       continue;
846     if ( !(*lpfn)( pHwnd[i], lParam ) )
847       break;
848   }
849   if ( pHwnd )
850     HeapFree ( hHeap, 0, pHwnd );
851   return TRUE;
852 }
853
854
855 /*
856  * @implemented
857  */
858 WINBOOL
859 STDCALL
860 EnumChildWindows(
861         HWND hWndParent,
862         ENUMWINDOWSPROC lpEnumFunc,
863         LPARAM lParam)
864 {
865   if ( !hWndParent )
866     hWndParent = GetDesktopWindow();
867   return User32EnumWindows ( NULL, hWndParent, lpEnumFunc, lParam, 0, FALSE );
868 }
869
870
871 /*
872  * @implemented
873  */
874 WINBOOL
875 STDCALL
876 EnumThreadWindows(DWORD dwThreadId,
877                   ENUMWINDOWSPROC lpfn,
878                   LPARAM lParam)
879 {
880   if ( !dwThreadId )
881     dwThreadId = GetCurrentThreadId();
882   return User32EnumWindows ( NULL, NULL, lpfn, lParam, dwThreadId, FALSE );
883 }
884
885
886 /*
887  * @implemented
888  */
889 WINBOOL STDCALL
890 EnumWindows(ENUMWINDOWSPROC lpEnumFunc,
891             LPARAM lParam)
892 {
893   return User32EnumWindows ( NULL, NULL, lpEnumFunc, lParam, 0, FALSE );
894 }
895
896
897 /*
898  * @implemented
899  */
900 WINBOOL
901 STDCALL
902 EnumDesktopWindows(
903         HDESK hDesktop,
904         ENUMWINDOWSPROC lpfn,
905         LPARAM lParam)
906 {
907   return User32EnumWindows ( hDesktop, NULL, lpfn, lParam, 0, FALSE );
908 }
909
910
911 /*
912  * @unimplemented
913  */
914 HWND STDCALL
915 FindWindowExA(HWND hwndParent,
916               HWND hwndChildAfter,
917               LPCSTR lpszClass,
918               LPCSTR lpszWindow)
919 {
920   UNIMPLEMENTED;
921   return (HWND)0;
922 }
923
924
925 /*
926  * @implemented
927  */
928 HWND STDCALL
929 FindWindowExW(HWND hwndParent,
930               HWND hwndChildAfter,
931               LPCWSTR lpszClass,
932               LPCWSTR lpszWindow)
933 {
934         UNICODE_STRING ucClassName;
935         UNICODE_STRING ucWindowName;
936
937         if (IS_ATOM(lpszClass)) 
938         {
939                 RtlInitUnicodeString(&ucClassName, NULL);
940                 ucClassName.Buffer = (LPWSTR)lpszClass;
941     } 
942         else 
943     {
944                 RtlInitUnicodeString(&ucClassName, lpszClass);
945     }
946
947         // Window names can't be atoms, and if lpszWindow = NULL,
948         // RtlInitUnicodeString will clear it
949         
950         RtlInitUnicodeString(&ucWindowName, lpszWindow);
951
952
953         return NtUserFindWindowEx(hwndParent, hwndChildAfter, &ucClassName, &ucWindowName);
954 }
955
956
957 /*
958  * @implemented
959  */
960 HWND STDCALL
961 FindWindowA(LPCSTR lpClassName, LPCSTR lpWindowName)
962 {
963   //FIXME: FindWindow does not search children, but FindWindowEx does.
964   //       what should we do about this?
965   return FindWindowExA (NULL, NULL, lpClassName, lpWindowName);
966 }
967
968
969 /*
970  * @implemented
971  */
972 HWND STDCALL
973 FindWindowW(LPCWSTR lpClassName, LPCWSTR lpWindowName)
974 {
975   /* 
976   
977   There was a FIXME here earlier, but I think it is just a documentation unclarity.
978
979   FindWindow only searches top level windows. What they mean is that child 
980   windows of other windows than the desktop can be searched. 
981   FindWindowExW never does a recursive search.
982   
983         / Joakim
984   */
985
986   return FindWindowExW (NULL, NULL, lpClassName, lpWindowName);
987 }
988
989
990
991 /*
992  * @unimplemented
993  */
994 WINBOOL STDCALL
995 GetAltTabInfoA(HWND hwnd,
996                int iItem,
997                PALTTABINFO pati,
998                LPSTR pszItemText,
999                UINT cchItemText)
1000 {
1001   UNIMPLEMENTED;
1002   return FALSE;
1003 }
1004
1005
1006 /*
1007  * @unimplemented
1008  */
1009 WINBOOL STDCALL
1010 GetAltTabInfoW(HWND hwnd,
1011                int iItem,
1012                PALTTABINFO pati,
1013                LPWSTR pszItemText,
1014                UINT cchItemText)
1015 {
1016   UNIMPLEMENTED;
1017   return FALSE;
1018 }
1019
1020
1021 /*
1022  * @implemented
1023  */
1024 HWND STDCALL
1025 GetAncestor(HWND hwnd, UINT gaFlags)
1026 {
1027   return(NtUserGetAncestor(hwnd, gaFlags));
1028 }
1029
1030
1031 /*
1032  * @implemented
1033  */
1034 WINBOOL STDCALL
1035 GetClientRect(HWND hWnd, LPRECT lpRect)
1036 {
1037   return(NtUserGetClientRect(hWnd, lpRect));
1038 }
1039
1040
1041 /*
1042  * @unimplemented
1043  */
1044 WINBOOL STDCALL
1045 GetGUIThreadInfo(DWORD idThread,
1046                  LPGUITHREADINFO lpgui)
1047 {
1048   UNIMPLEMENTED;
1049   return FALSE;
1050 }
1051
1052
1053 /*
1054  * @unimplemented
1055  */
1056 HWND STDCALL
1057 GetLastActivePopup(HWND hWnd)
1058 {
1059   return NtUserGetLastActivePopup(hWnd);
1060 }
1061
1062
1063 /*
1064  * @implemented
1065  */
1066 HWND STDCALL
1067 GetParent(HWND hWnd)
1068 {
1069   return NtUserGetParent(hWnd);
1070 }
1071
1072
1073 /*
1074  * @unimplemented
1075  */
1076 WINBOOL STDCALL
1077 GetProcessDefaultLayout(DWORD *pdwDefaultLayout)
1078 {
1079   UNIMPLEMENTED;
1080   return FALSE;
1081 }
1082
1083
1084 /*
1085  * @unimplemented
1086  */
1087 WINBOOL STDCALL
1088 GetTitleBarInfo(HWND hwnd,
1089                 PTITLEBARINFO pti)
1090 {
1091   UNIMPLEMENTED;
1092   return FALSE;
1093 }
1094
1095
1096 /*
1097  * @implemented
1098  */
1099 HWND STDCALL
1100 GetWindow(HWND hWnd,
1101           UINT uCmd)
1102 {
1103   return NtUserGetWindow(hWnd, uCmd);
1104 }
1105
1106
1107 /*
1108  * @implemented
1109  */
1110 HWND STDCALL
1111 GetTopWindow(HWND hWnd)
1112 {
1113   if (!hWnd) hWnd = GetDesktopWindow();
1114   return GetWindow( hWnd, GW_CHILD );
1115 }
1116
1117
1118 /*
1119  * @unimplemented
1120  */
1121 WINBOOL STDCALL
1122 GetWindowInfo(HWND hwnd,
1123               PWINDOWINFO pwi)
1124 {
1125   UNIMPLEMENTED;
1126   return FALSE;
1127 }
1128
1129
1130 /*
1131  * @unimplemented
1132  */
1133 UINT STDCALL
1134 GetWindowModuleFileName(HWND hwnd,
1135                         LPSTR lpszFileName,
1136                         UINT cchFileNameMax)
1137 {
1138   UNIMPLEMENTED;
1139   return 0;
1140 }
1141
1142
1143 /*
1144  * @unimplemented
1145  */
1146 UINT STDCALL
1147 GetWindowModuleFileNameA(HWND hwnd,
1148                          LPSTR lpszFileName,
1149                          UINT cchFileNameMax)
1150 {
1151   UNIMPLEMENTED;
1152   return 0;
1153 }
1154
1155
1156 /*
1157  * @unimplemented
1158  */
1159 UINT STDCALL
1160 GetWindowModuleFileNameW(HWND hwnd,
1161                          LPWSTR lpszFileName,
1162                          UINT cchFileNameMax)
1163 {
1164   UNIMPLEMENTED;
1165   return 0;
1166 }
1167
1168
1169 /*
1170  * @unimplemented
1171  */
1172 WINBOOL STDCALL
1173 GetWindowPlacement(HWND hWnd,
1174                    WINDOWPLACEMENT *lpwndpl)
1175 {
1176   UNIMPLEMENTED;
1177   return FALSE;
1178 }
1179
1180
1181 /*
1182  * @implemented
1183  */
1184 WINBOOL STDCALL
1185 GetWindowRect(HWND hWnd,
1186               LPRECT lpRect)
1187 {
1188   return(NtUserGetWindowRect(hWnd, lpRect));
1189 }
1190
1191
1192 /*
1193  * @implemented
1194  */
1195 int STDCALL
1196 GetWindowTextA(HWND hWnd, LPSTR lpString, int nMaxCount)
1197 {
1198   return(SendMessageA(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString));
1199 }
1200
1201
1202 /*
1203  * @implemented
1204  */
1205 int STDCALL
1206 GetWindowTextLengthA(HWND hWnd)
1207 {
1208   return(SendMessageA(hWnd, WM_GETTEXTLENGTH, 0, 0));
1209 }
1210
1211
1212 /*
1213  * @implemented
1214  */
1215 int STDCALL
1216 GetWindowTextLengthW(HWND hWnd)
1217 {
1218   return(SendMessageW(hWnd, WM_GETTEXTLENGTH, 0, 0));
1219 }
1220
1221
1222 /*
1223  * @implemented
1224  */
1225 int STDCALL
1226 GetWindowTextW(
1227         HWND hWnd,
1228         LPWSTR lpString,
1229         int nMaxCount)
1230 {
1231   return(SendMessageW(hWnd, WM_GETTEXT, nMaxCount, (LPARAM)lpString));
1232 }
1233
1234 DWORD STDCALL
1235 GetWindowThreadProcessId(HWND hWnd,
1236                          LPDWORD lpdwProcessId)
1237 {
1238    return NtUserGetWindowThreadProcessId(hWnd, lpdwProcessId);
1239 }
1240
1241
1242 /*
1243  * @implemented
1244  */
1245 WINBOOL STDCALL
1246 IsChild(HWND hWndParent,
1247         HWND hWnd)
1248 {
1249     // Untested
1250     return ((HWND)NtUserGetWindowLong(hWnd, GWL_HWNDPARENT, FALSE)) == hWndParent;
1251 }
1252
1253
1254 /*
1255  * @implemented
1256  */
1257 WINBOOL STDCALL
1258 IsIconic(HWND hWnd)
1259 {
1260   return (NtUserGetWindowLong( hWnd, GWL_STYLE, FALSE) & WS_MINIMIZE) != 0;  
1261 }
1262
1263
1264 /*
1265  * @implemented
1266  */
1267 WINBOOL STDCALL
1268 IsWindow(HWND hWnd)
1269 {
1270   DWORD WndProc = NtUserGetWindowLong(hWnd, GWL_WNDPROC, FALSE);
1271   return (0 != WndProc || ERROR_INVALID_HANDLE != GetLastError());
1272 }
1273
1274
1275 /*
1276  * @implemented
1277  */
1278 WINBOOL STDCALL
1279 IsWindowUnicode(HWND hWnd)
1280 {
1281         return (WINBOOL)NtUserCallOneParam((DWORD)hWnd,ONEPARAM_ROUTINE_ISWINDOWUNICODE);
1282 }
1283
1284
1285 /*
1286  * @implemented
1287  */
1288 WINBOOL STDCALL
1289 IsWindowVisible(HWND hWnd)
1290 {
1291   while (NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE) & WS_CHILD)
1292     {
1293       if (!(NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE) & WS_VISIBLE))
1294         {
1295           return(FALSE);
1296         }
1297       hWnd = GetAncestor(hWnd, GA_PARENT);
1298     }
1299   return(NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE) & WS_VISIBLE);
1300 }
1301
1302
1303 /*
1304  * @implemented
1305  */
1306 WINBOOL
1307 STDCALL
1308 IsWindowEnabled(
1309   HWND hWnd)
1310 {
1311     // AG: I don't know if child windows are affected if the parent is
1312     // disabled. I think they stop processing messages but stay appearing
1313     // as enabled.
1314     
1315     return (! (NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE) & WS_DISABLED));
1316 }
1317
1318
1319 /*
1320  * @implemented
1321  */
1322 WINBOOL STDCALL
1323 IsZoomed(HWND hWnd)
1324 {
1325   return NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE) & WS_MAXIMIZE;
1326 }
1327
1328
1329 /*
1330  * @unimplemented
1331  */
1332 WINBOOL STDCALL
1333 LockSetForegroundWindow(UINT uLockCode)
1334 {
1335   UNIMPLEMENTED;
1336   return FALSE;
1337 }
1338
1339
1340 /*
1341  * @implemented
1342  */
1343 WINBOOL STDCALL
1344 MoveWindow(HWND hWnd,
1345            int X,
1346            int Y,
1347            int nWidth,
1348            int nHeight,
1349            WINBOOL bRepaint)
1350 {
1351   return NtUserMoveWindow(hWnd, X, Y, nWidth, nHeight, bRepaint);
1352 }
1353
1354
1355 /*
1356  * @implemented
1357  */
1358 WINBOOL STDCALL
1359 AnimateWindow(HWND hwnd,
1360               DWORD dwTime,
1361               DWORD dwFlags)
1362 {
1363   /* FIXME Add animation code */
1364
1365   /* If trying to show/hide and it's already   *
1366    * shown/hidden or invalid window, fail with *
1367    * invalid parameter                         */
1368    
1369   BOOL visible;
1370   visible = IsWindowVisible(hwnd);
1371 //  if(!IsWindow(hwnd) ||
1372 //    (visible && !(dwFlags & AW_HIDE)) ||
1373 //    (!visible && (dwFlags & AW_HIDE)))
1374   {
1375     SetLastError(ERROR_INVALID_PARAMETER);
1376     return FALSE;
1377   }
1378
1379 //  ShowWindow(hwnd, (dwFlags & AW_HIDE) ? SW_HIDE : ((dwFlags & AW_ACTIVATE) ? SW_SHOW : SW_SHOWNA));
1380
1381   return TRUE;
1382 }
1383
1384
1385 /*
1386  * @unimplemented
1387  */
1388 WINBOOL STDCALL
1389 OpenIcon(HWND hWnd)
1390 {
1391     if (! NtUserGetWindowLong(hWnd, GWL_STYLE, FALSE) & WS_MINIMIZE)
1392     {
1393         // Not minimized - error?
1394         return FALSE;
1395     }
1396     
1397     if (! SendMessageA(hWnd, WM_QUERYOPEN, 0, 0))
1398     {
1399         // Window doesn't want to be opened - error?
1400         return FALSE;
1401     }
1402     
1403     // Now we need to do the actual opening of the window, which is something
1404     // I'll leave to someone more capable :)
1405
1406     UNIMPLEMENTED;
1407     return FALSE;
1408 }
1409
1410
1411 /*
1412  * @unimplemented
1413  */
1414 HWND STDCALL
1415 RealChildWindowFromPoint(HWND hwndParent,
1416                          POINT ptParentClientCoords)
1417 {
1418   UNIMPLEMENTED;
1419   return (HWND)0;
1420 }
1421
1422 /*
1423  * @unimplemented
1424  */
1425 WINBOOL STDCALL
1426 SetForegroundWindow(HWND hWnd)
1427 {
1428   UNIMPLEMENTED;
1429   return FALSE;
1430 }
1431
1432
1433 /*
1434  * @unimplemented
1435  */
1436 WINBOOL STDCALL
1437 SetLayeredWindowAttributes(HWND hwnd,
1438                            COLORREF crKey,
1439                            BYTE bAlpha,
1440                            DWORD dwFlags)
1441 {
1442   UNIMPLEMENTED;
1443   return FALSE;
1444 }
1445
1446
1447 /*
1448  * @unimplemented
1449  */
1450 HWND STDCALL
1451 SetParent(HWND hWndChild,
1452           HWND hWndNewParent)
1453 {
1454   return NtUserSetParent(hWndChild, hWndNewParent);
1455 }
1456
1457
1458 /*
1459  * @unimplemented
1460  */
1461 WINBOOL STDCALL
1462 SetProcessDefaultLayout(DWORD dwDefaultLayout)
1463 {
1464   UNIMPLEMENTED;
1465   return FALSE;
1466 }
1467
1468
1469 /*
1470  * @unimplemented
1471  */
1472 WINBOOL STDCALL
1473 SetWindowPlacement(HWND hWnd,
1474                    CONST WINDOWPLACEMENT *lpwndpl)
1475 {
1476   UNIMPLEMENTED;
1477   return FALSE;
1478 }
1479
1480
1481 /*
1482  * @implemented
1483  */
1484 WINBOOL STDCALL
1485 SetWindowPos(HWND hWnd,
1486              HWND hWndInsertAfter,
1487              int X,
1488              int Y,
1489              int cx,
1490              int cy,
1491              UINT uFlags)
1492 {
1493   return NtUserSetWindowPos(hWnd,hWndInsertAfter, X, Y, cx, cy, uFlags);
1494 }
1495
1496
1497 /*
1498  * @implemented
1499  */
1500 WINBOOL STDCALL
1501 SetWindowTextA(HWND hWnd,
1502                LPCSTR lpString)
1503 {
1504   return SendMessageA(hWnd, WM_SETTEXT, 0, (LPARAM)lpString);
1505 }
1506
1507
1508 /*
1509  * @implemented
1510  */
1511 WINBOOL STDCALL
1512 SetWindowTextW(HWND hWnd,
1513                LPCWSTR lpString)
1514 {
1515   return SendMessageW(hWnd, WM_SETTEXT, 0, (LPARAM)lpString);
1516 }
1517
1518
1519 /*
1520  * @unimplemented
1521  */
1522 WINBOOL STDCALL
1523 ShowOwnedPopups(HWND hWnd,
1524                 WINBOOL fShow)
1525 {
1526   UNIMPLEMENTED;
1527   return FALSE;
1528 }
1529
1530
1531 /*
1532  * @implemented
1533  */
1534 WINBOOL STDCALL
1535 ShowWindow(HWND hWnd,
1536            int nCmdShow)
1537 {
1538   return NtUserShowWindow(hWnd, nCmdShow);
1539 }
1540
1541
1542 /*
1543  * @unimplemented
1544  */
1545 WINBOOL STDCALL
1546 ShowWindowAsync(HWND hWnd,
1547                 int nCmdShow)
1548 {
1549   UNIMPLEMENTED;
1550   return FALSE;
1551 }
1552
1553
1554 /*
1555  * @unimplemented
1556  */
1557 WORD STDCALL
1558 TileWindows(HWND hwndParent,
1559             UINT wHow,
1560             CONST RECT *lpRect,
1561             UINT cKids,
1562             const HWND *lpKids)
1563 {
1564   UNIMPLEMENTED;
1565   return 0;
1566 }
1567
1568
1569 /*
1570  * @unimplemented
1571  */
1572 WINBOOL STDCALL
1573 UpdateLayeredWindow(HWND hwnd,
1574                     HDC hdcDst,
1575                     POINT *pptDst,
1576                     SIZE *psize,
1577                     HDC hdcSrc,
1578                     POINT *pptSrc,
1579                     COLORREF crKey,
1580                     BLENDFUNCTION *pblend,
1581                     DWORD dwFlags)
1582 {
1583   UNIMPLEMENTED;
1584   return FALSE;
1585 }
1586
1587
1588 /*
1589  * @unimplemented
1590  */
1591 HWND STDCALL
1592 WindowFromPoint(POINT Point)
1593 {
1594   UNIMPLEMENTED;
1595   return (HWND)0;
1596 }
1597
1598
1599 /*
1600  * @implemented
1601  */
1602 int STDCALL
1603 MapWindowPoints(HWND hWndFrom, HWND hWndTo, LPPOINT lpPoints, UINT cPoints)
1604 {
1605   POINT FromOffset, ToOffset;
1606   LONG XMove, YMove;
1607   ULONG i;
1608
1609   NtUserGetClientOrigin(hWndFrom, &FromOffset);
1610   NtUserGetClientOrigin(hWndTo, &ToOffset);
1611   XMove = FromOffset.x - ToOffset.x;
1612   YMove = FromOffset.y - ToOffset.y;
1613
1614   for (i = 0; i < cPoints; i++)
1615     {
1616       lpPoints[i].x += XMove;
1617       lpPoints[i].y += YMove;
1618     }
1619   return(MAKELONG(LOWORD(XMove), LOWORD(YMove)));
1620 }
1621
1622
1623 /*
1624  * @implemented
1625  */
1626 WINBOOL STDCALL 
1627 ScreenToClient(HWND hWnd, LPPOINT lpPoint)
1628 {
1629   return(MapWindowPoints(NULL, hWnd, lpPoint, 1));
1630 }
1631
1632
1633 /*
1634  * @implemented
1635  */
1636 WINBOOL STDCALL
1637 ClientToScreen(HWND hWnd, LPPOINT lpPoint)
1638 {
1639     return (MapWindowPoints( hWnd, NULL, lpPoint, 1 ));
1640 }
1641
1642
1643 /*
1644  * @implemented
1645  */
1646 WINBOOL
1647 STDCALL
1648 SetWindowContextHelpId(HWND hwnd,
1649           DWORD dwContextHelpId)
1650 {
1651   return (WINBOOL)NtUserCallTwoParam((DWORD)hwnd, (DWORD)dwContextHelpId, 
1652                                      TWOPARAM_ROUTINE_SETWNDCONTEXTHLPID);
1653 }
1654
1655
1656 /*
1657  * @implemented
1658  */
1659 DWORD
1660 STDCALL
1661 GetWindowContextHelpId(HWND hwnd)
1662 {
1663   return NtUserCallOneParam((DWORD)hwnd, ONEPARAM_ROUTINE_GETWNDCONTEXTHLPID);
1664 }
1665
1666 /*
1667  * @implemented
1668  */
1669 DWORD
1670 STDCALL
1671 InternalGetWindowText(HWND hWnd, LPWSTR lpString, int nMaxCount)
1672 {
1673   DWORD res = 0;
1674   LPWSTR lps = NULL;
1675   if(lpString && (nMaxCount > 0))
1676   {
1677     lps = RtlAllocateHeap(RtlGetProcessHeap(), 0, nMaxCount * sizeof(WCHAR));
1678     if(!lps)
1679     {
1680       SetLastError(ERROR_OUTOFMEMORY);
1681       return 0;
1682     }
1683   }
1684   
1685   res = NtUserInternalGetWindowText(hWnd, lps, nMaxCount);
1686   
1687   if(lps)
1688   {
1689     RtlCopyMemory(lpString, lps, res * sizeof(WCHAR));
1690     lpString[res] = (WCHAR)"\0";  /* null-terminate the string */
1691     
1692     RtlFreeHeap(RtlGetProcessHeap(), 0, lps);
1693   }
1694   
1695   return res;
1696 }
1697
1698 /*
1699  * @unimplemented
1700  */
1701 WINBOOL
1702 STDCALL
1703 IsHungAppWindow(HWND hwnd)
1704 {
1705   /* FIXME: ReactOS doesnt identify hung app windows yet */
1706   return FALSE;
1707 }
1708
1709 /*
1710  * @implemented
1711  */
1712 VOID
1713 STDCALL
1714 SetLastErrorEx(DWORD dwErrCode, DWORD dwType)
1715 {
1716   SetLastError(dwErrCode);
1717 }
1718
1719 /*
1720  * @implemented
1721  */
1722 WINBOOL
1723 STDCALL
1724 SetSystemMenu (
1725   HWND hwnd, 
1726   HMENU hMenu)
1727 {
1728   if(!hwnd)
1729   {
1730     SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1731     return FALSE;
1732   }
1733   if(!hMenu)
1734   {
1735     SetLastError(ERROR_INVALID_MENU_HANDLE);
1736     return FALSE;
1737   }
1738   return NtUserSetSystemMenu(hwnd, hMenu);
1739 }
1740
1741 /*
1742  * @implemented
1743  */
1744 HMENU
1745 STDCALL
1746 GetSystemMenu(
1747   HWND hWnd,
1748   WINBOOL bRevert)
1749 {
1750   if(!hWnd)
1751   {
1752     SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1753     return (HMENU)0;
1754   }
1755   return NtUserGetSystemMenu(hWnd, bRevert);
1756 }
1757
1758 /* EOF */