xref: /reactos/win32ss/user/user32/windows/dialog.c (revision d5b576b2)
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /*
20  * PROJECT:         ReactOS user32.dll
21  * FILE:            win32ss/user/user32/windows/dialog.c
22  * PURPOSE:         Input
23  * PROGRAMMER:      Casper S. Hornstrup (chorns@users.sourceforge.net)
24  *                  Thomas Weidenmueller (w3seek@users.sourceforge.net)
25  *                  Steven Edwards (Steven_Ed4153@yahoo.com)
26  * UPDATE HISTORY:
27  *      07-26-2003  Code ported from wine
28  *      09-05-2001  CSH  Created
29  */
30 
31 #include <user32.h>
32 
33 WINE_DEFAULT_DEBUG_CHANNEL(user32);
34 
35 /* MACROS/DEFINITIONS ********************************************************/
36 
37 #define DF_END  0x0001
38 #define DF_DIALOGACTIVE 0x4000 // ReactOS
39 #define DWLP_ROS_DIALOGINFO (DWLP_USER+sizeof(ULONG_PTR))
40 #define GETDLGINFO(hwnd) DIALOG_get_info(hwnd, FALSE)
41 #define SETDLGINFO(hwnd, info) SetWindowLongPtrW((hwnd), DWLP_ROS_DIALOGINFO, (LONG_PTR)(info))
42 #define GET_WORD(ptr)  (*(WORD *)(ptr))
43 #define GET_DWORD(ptr) (*(DWORD *)(ptr))
44 #define DLG_ISANSI 2
45 
46 /* INTERNAL STRUCTS **********************************************************/
47 
48 /* Dialog info structure */
49 typedef struct
50 {
51     HWND      hwndFocus;   /* Current control with focus */
52     HFONT     hUserFont;   /* Dialog font */
53     HMENU     hMenu;       /* Dialog menu */
54     UINT      xBaseUnit;   /* Dialog units (depends on the font) */
55     UINT      yBaseUnit;
56     INT       idResult;    /* EndDialog() result / default pushbutton ID */
57     UINT      flags;       /* EndDialog() called for this dialog */
58 } DIALOGINFO;
59 
60 /* Dialog control information */
61 typedef struct
62 {
63     DWORD      style;
64     DWORD      exStyle;
65     DWORD      helpId;
66     short      x;
67     short      y;
68     short      cx;
69     short      cy;
70     UINT       id;
71     LPCWSTR    className;
72     LPCWSTR    windowName;
73     BOOL       windowNameFree; // ReactOS
74     LPCVOID    data;
75 } DLG_CONTROL_INFO;
76 
77 /* Dialog template */
78 typedef struct
79 {
80     DWORD      style;
81     DWORD      exStyle;
82     DWORD      helpId;
83     WORD       nbItems;
84     short      x;
85     short      y;
86     short      cx;
87     short      cy;
88     LPCWSTR    menuName;
89     LPCWSTR    className;
90     LPCWSTR    caption;
91     WORD       pointSize;
92     WORD       weight;
93     BOOL       italic;
94     LPCWSTR    faceName;
95     BOOL       dialogEx;
96 } DLG_TEMPLATE;
97 
98 /* CheckRadioButton structure */
99 typedef struct
100 {
101   UINT firstID;
102   UINT lastID;
103   UINT checkID;
104 } RADIOGROUP;
105 
106 
107 /*********************************************************************
108  * dialog class descriptor
109  */
110 const struct builtin_class_descr DIALOG_builtin_class =
111 {
112     WC_DIALOG,       /* name */
113     CS_SAVEBITS | CS_DBLCLKS, /* style  */
114     DefDlgProcA,              /* procA */
115     DefDlgProcW,              /* procW */
116     DLGWINDOWEXTRA,           /* extra */
117     (LPCWSTR) IDC_ARROW,      /* cursor */
118     0                         /* brush */
119 };
120 
121 
122 /* INTERNAL FUNCTIONS ********************************************************/
123 
124 /***********************************************************************
125 *               DIALOG_get_info
126 *
127 * Get the DIALOGINFO structure of a window, allocating it if needed
128 * and 'create' is TRUE.
129 *
130 * ReactOS
131 */
132 DIALOGINFO *DIALOG_get_info( HWND hWnd, BOOL create )
133 {
134     PWND pWindow;
135     DIALOGINFO* dlgInfo;
136 
137     pWindow = ValidateHwnd( hWnd );
138     if (!pWindow)
139     {
140        return NULL;
141     }
142 
143     dlgInfo = (DIALOGINFO *)GetWindowLongPtrW( hWnd, DWLP_ROS_DIALOGINFO );
144 
145     if (!dlgInfo && create)
146     {
147         if (pWindow && pWindow->cbwndExtra >= DLGWINDOWEXTRA)
148         {
149             if (!(dlgInfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dlgInfo) )))
150                 return NULL;
151 
152             dlgInfo->idResult = IDOK;
153             SETDLGINFO( hWnd, dlgInfo );
154        }
155        else
156        {
157            return NULL;
158        }
159     }
160 
161     if (dlgInfo)
162     {
163         if (!(pWindow->state & WNDS_DIALOGWINDOW))
164         {
165            NtUserxSetDialogPointer( hWnd, dlgInfo );
166         }
167     }
168     return dlgInfo;
169 }
170 
171 /***********************************************************************
172  *           DIALOG_GetControl32
173  *
174  * Return the class and text of the control pointed to by ptr,
175  * fill the header structure and return a pointer to the next control.
176  */
177 static const WORD *DIALOG_GetControl32( const WORD *p, DLG_CONTROL_INFO *info,
178                                         BOOL dialogEx )
179 {
180     if (dialogEx)
181     {
182         info->helpId  = GET_DWORD(p); p += 2;
183         info->exStyle = GET_DWORD(p); p += 2;
184         info->style   = GET_DWORD(p); p += 2;
185     }
186     else
187     {
188         info->helpId  = 0;
189         info->style   = GET_DWORD(p); p += 2;
190         info->exStyle = GET_DWORD(p); p += 2;
191     }
192     info->x       = GET_WORD(p); p++;
193     info->y       = GET_WORD(p); p++;
194     info->cx      = GET_WORD(p); p++;
195     info->cy      = GET_WORD(p); p++;
196 
197     if (dialogEx)
198     {
199         /* id is a DWORD for DIALOGEX */
200         info->id = GET_DWORD(p);
201         p += 2;
202     }
203     else
204     {
205         info->id = GET_WORD(p);
206         p++;
207     }
208 
209     if (GET_WORD(p) == 0xffff)
210     {
211         static const WCHAR class_names[6][10] =
212         {
213             { 'B','u','t','t','o','n', },             /* 0x80 */
214             { 'E','d','i','t', },                     /* 0x81 */
215             { 'S','t','a','t','i','c', },             /* 0x82 */
216             { 'L','i','s','t','B','o','x', },         /* 0x83 */
217             { 'S','c','r','o','l','l','B','a','r', }, /* 0x84 */
218             { 'C','o','m','b','o','B','o','x', }      /* 0x85 */
219         };
220         WORD id = GET_WORD(p+1);
221         /* Windows treats dialog control class ids 0-5 same way as 0x80-0x85 */
222         if ((id >= 0x80) && (id <= 0x85)) id -= 0x80;
223         if (id <= 5)
224         {
225             info->className = class_names[id];
226         }
227         else
228         {
229             info->className = NULL;
230             /* FIXME: load other classes here? */
231             ERR("Unknown built-in class id %04x\n", id );
232         }
233         p += 2;
234     }
235     else
236     {
237         info->className = (LPCWSTR)p;
238         p += strlenW( info->className ) + 1;
239     }
240 
241     if (GET_WORD(p) == 0xffff)  /* Is it an integer id? */
242     {
243 //// ReactOS Rev 6478
244         info->windowName = HeapAlloc( GetProcessHeap(), 0, sizeof(L"#65535") );
245         if (info->windowName != NULL)
246         {
247             wsprintf((LPWSTR)info->windowName, L"#%u", GET_WORD(p + 1));
248             info->windowNameFree = TRUE;
249         }
250         else
251         {
252             info->windowNameFree = FALSE;
253         }
254         p += 2;
255     }
256     else
257     {
258         info->windowName = (LPCWSTR)p;
259         info->windowNameFree = FALSE;
260         p += strlenW( info->windowName ) + 1;
261     }
262 
263     TRACE("    %s %s %ld, %d, %d, %d, %d, %08x, %08x, %08x\n",
264           debugstr_w( info->className ), debugstr_w( info->windowName ),
265           info->id, info->x, info->y, info->cx, info->cy,
266           info->style, info->exStyle, info->helpId );
267 
268     if (GET_WORD(p))
269     {
270         info->data = p;
271         p += GET_WORD(p) / sizeof(WORD);
272     }
273     else info->data = NULL;
274     p++;
275 
276     /* Next control is on dword boundary */
277     return (const WORD *)(((UINT_PTR)p + 3) & ~3);
278 }
279 
280 
281 /***********************************************************************
282  *           DIALOG_CreateControls32
283  *
284  * Create the control windows for a dialog.
285  */
286 static BOOL DIALOG_CreateControls32( HWND hwnd, LPCSTR template, const DLG_TEMPLATE *dlgTemplate,
287                                      HINSTANCE hInst, BOOL unicode )
288 {
289     DIALOGINFO * dlgInfo;
290     DLG_CONTROL_INFO info;
291     HWND hwndCtrl, hwndDefButton = 0;
292     INT items = dlgTemplate->nbItems;
293 
294     if (!(dlgInfo = GETDLGINFO(hwnd))) return FALSE;
295 
296     TRACE(" BEGIN\n" );
297     while (items--)
298     {
299         template = (LPCSTR)DIALOG_GetControl32( (const WORD *)template, &info,
300                                                 dlgTemplate->dialogEx );
301         info.style &= ~WS_POPUP;
302         info.style |= WS_CHILD;
303 
304         if (info.style & WS_BORDER)
305         {
306             info.style &= ~WS_BORDER;
307             info.exStyle |= WS_EX_CLIENTEDGE;
308         }
309 
310         if (unicode)
311         {
312             hwndCtrl = CreateWindowExW( info.exStyle | WS_EX_NOPARENTNOTIFY,
313                                         info.className, info.windowName,
314                                         info.style | WS_CHILD,
315                                         MulDiv(info.x, dlgInfo->xBaseUnit, 4),
316                                         MulDiv(info.y, dlgInfo->yBaseUnit, 8),
317                                         MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
318                                         MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
319                                         hwnd, (HMENU)(ULONG_PTR)info.id,
320                                         hInst, (LPVOID)info.data );
321         }
322         else
323         {
324             LPSTR class = (LPSTR)info.className;
325             LPSTR caption = (LPSTR)info.windowName;
326 
327             if (!IS_INTRESOURCE(class))
328             {
329                 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.className, -1, NULL, 0, NULL, NULL );
330                 class = HeapAlloc( GetProcessHeap(), 0, len );
331                 if (class != NULL)
332                     WideCharToMultiByte( CP_ACP, 0, info.className, -1, class, len, NULL, NULL );
333             }
334             if (!IS_INTRESOURCE(caption))
335             {
336                 DWORD len = WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, NULL, 0, NULL, NULL );
337                 caption = HeapAlloc( GetProcessHeap(), 0, len );
338                 if (caption != NULL)
339                     WideCharToMultiByte( CP_ACP, 0, info.windowName, -1, caption, len, NULL, NULL );
340             }
341 
342             if (class != NULL && caption != NULL)
343             {
344                 hwndCtrl = CreateWindowExA( info.exStyle | WS_EX_NOPARENTNOTIFY,
345                                             class, caption, info.style | WS_CHILD,
346                                             MulDiv(info.x, dlgInfo->xBaseUnit, 4),
347                                             MulDiv(info.y, dlgInfo->yBaseUnit, 8),
348                                             MulDiv(info.cx, dlgInfo->xBaseUnit, 4),
349                                             MulDiv(info.cy, dlgInfo->yBaseUnit, 8),
350                                             hwnd, (HMENU)(ULONG_PTR)info.id,
351                                             hInst, (LPVOID)info.data );
352             }
353             else
354                 hwndCtrl = NULL;
355             if (!IS_INTRESOURCE(class)) HeapFree( GetProcessHeap(), 0, class );
356             if (!IS_INTRESOURCE(caption)) HeapFree( GetProcessHeap(), 0, caption );
357         }
358 
359         if (info.windowNameFree)
360         {
361             HeapFree( GetProcessHeap(), 0, (LPVOID)info.windowName );
362         }
363 
364         if (!hwndCtrl)
365         {
366             WARN("control %s %s creation failed\n", debugstr_w(info.className),
367                   debugstr_w(info.windowName));
368             if (dlgTemplate->style & DS_NOFAILCREATE) continue;
369             return FALSE;
370         }
371 
372         /* Send initialisation messages to the control */
373         if (dlgInfo->hUserFont) SendMessageW( hwndCtrl, WM_SETFONT,
374                                              (WPARAM)dlgInfo->hUserFont, 0 );
375         if (SendMessageW(hwndCtrl, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON)
376         {
377             /* If there's already a default push-button, set it back */
378             /* to normal and use this one instead. */
379             if (hwndDefButton)
380                 SendMessageW( hwndDefButton, BM_SETSTYLE, BS_PUSHBUTTON, FALSE );
381             hwndDefButton = hwndCtrl;
382             dlgInfo->idResult = GetWindowLongPtrA( hwndCtrl, GWLP_ID );
383         }
384     }
385     TRACE(" END\n" );
386     return TRUE;
387 }
388 
389 
390  /***********************************************************************
391   *           DIALOG_IsAccelerator
392   */
393 static BOOL DIALOG_IsAccelerator( HWND hwnd, HWND hwndDlg, WPARAM wParam )
394 {
395     HWND hwndControl = hwnd;
396     HWND hwndNext;
397     INT dlgCode;
398     WCHAR buffer[128];
399 
400     do
401     {
402         DWORD style = GetWindowLongPtrW( hwndControl, GWL_STYLE );
403         if ((style & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE)
404         {
405             dlgCode = SendMessageW( hwndControl, WM_GETDLGCODE, 0, 0 );
406             if ( (dlgCode & (DLGC_BUTTON | DLGC_STATIC)) &&
407                  GetWindowTextW( hwndControl, buffer, sizeof(buffer)/sizeof(WCHAR) ))
408             {
409                 /* find the accelerator key */
410                 LPWSTR p = buffer - 2;
411 
412                 do
413                 {
414                     p = strchrW( p + 2, '&' );
415                 }
416                 while (p != NULL && p[1] == '&');
417 
418                 /* and check if it's the one we're looking for */
419                 if (p != NULL && toupperW( p[1] ) == toupperW( wParam ) )
420                 {
421                     if ((dlgCode & DLGC_STATIC) || (style & 0x0f) == BS_GROUPBOX )
422                     {
423                         /* set focus to the control */
424                         SendMessageW( hwndDlg, WM_NEXTDLGCTL, (WPARAM)hwndControl, 1);
425                         /* and bump it on to next */
426                         SendMessageW( hwndDlg, WM_NEXTDLGCTL, 0, 0);
427                     }
428                     else if (dlgCode & DLGC_BUTTON)
429                     {
430                         /* send BM_CLICK message to the control */
431                         SendMessageW( hwndControl, BM_CLICK, 0, 0 );
432                     }
433                     return TRUE;
434                 }
435             }
436             hwndNext = GetWindow( hwndControl, GW_CHILD );
437         }
438         else hwndNext = 0;
439 
440         if (!hwndNext) hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
441 
442         while (!hwndNext && hwndControl)
443         {
444             hwndControl = GetParent( hwndControl );
445             if (hwndControl == hwndDlg)
446             {
447                 if(hwnd==hwndDlg)   /* prevent endless loop */
448                 {
449                     hwndNext=hwnd;
450                     break;
451                 }
452                 hwndNext = GetWindow( hwndDlg, GW_CHILD );
453             }
454             else
455                 hwndNext = GetWindow( hwndControl, GW_HWNDNEXT );
456         }
457         hwndControl = hwndNext;
458     }
459     while (hwndControl && (hwndControl != hwnd));
460 
461     return FALSE;
462 }
463 
464  /***********************************************************************
465   *           DIALOG_FindMsgDestination
466   *
467   * The messages that IsDialogMessage sends may not go to the dialog
468   * calling IsDialogMessage if that dialog is a child, and it has the
469   * DS_CONTROL style set.
470   * We propagate up until we hit one that does not have DS_CONTROL, or
471   * whose parent is not a dialog.
472   *
473   * This is undocumented behaviour.
474   */
475 static HWND DIALOG_FindMsgDestination( HWND hwndDlg )
476 {
477     while (GetWindowLongA(hwndDlg, GWL_STYLE) & DS_CONTROL)
478     {
479         PWND pWnd;
480         HWND hParent = GetParent(hwndDlg);
481         if (!hParent) break;
482 // ReactOS
483         if (!IsWindow(hParent)) break;
484 
485         pWnd = ValidateHwnd(hParent);
486         // FIXME: Use pWnd->fnid == FNID_DESKTOP
487         if (!pWnd || !TestWindowProcess(pWnd) || hParent == GetDesktopWindow()) break;
488 
489         if (!(pWnd->state & WNDS_DIALOGWINDOW))
490         {
491             break;
492         }
493 
494         hwndDlg = hParent;
495     }
496 
497     return hwndDlg;
498 }
499 
500  /***********************************************************************
501  *           DIALOG_DoDialogBox
502  */
503 INT DIALOG_DoDialogBox( HWND hwnd, HWND owner )
504 {
505     DIALOGINFO * dlgInfo;
506     MSG msg;
507     INT retval;
508     BOOL bFirstEmpty;
509     PWND pWnd;
510 
511     pWnd = ValidateHwnd(hwnd);
512     if (!pWnd) return -1;
513 
514     if (!(dlgInfo = GETDLGINFO(hwnd))) return -1;
515 
516     bFirstEmpty = TRUE;
517     if (!(dlgInfo->flags & DF_END)) /* was EndDialog called in WM_INITDIALOG ? */
518     {
519         for (;;)
520         {
521             if (!PeekMessageW( &msg, 0, 0, 0, PM_REMOVE ))
522             {
523                 if (bFirstEmpty)
524                 {
525                     /* ShowWindow the first time the queue goes empty */
526                     ShowWindow( hwnd, SW_SHOWNORMAL );
527                     bFirstEmpty = FALSE;
528                 }
529                 if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & DS_NOIDLEMSG))
530                {
531                     /* No message present -> send ENTERIDLE and wait */
532                     SendMessageW( owner, WM_ENTERIDLE, MSGF_DIALOGBOX, (LPARAM)hwnd );
533                 }
534                 GetMessageW( &msg, 0, 0, 0 );
535             }
536 
537             if (msg.message == WM_QUIT)
538             {
539                 PostQuitMessage( msg.wParam );
540                 if (!IsWindow( hwnd )) return 0;
541                 break;
542             }
543 
544             /*
545              * If the user is pressing Ctrl+C, send a WM_COPY message.
546              * Guido Pola, CORE-4829, Is there another way to check if the Dialog is a MessageBox?
547              */
548             if (msg.message == WM_KEYDOWN &&
549                 pWnd->state & WNDS_MSGBOX && // Yes!
550                 GetForegroundWindow() == hwnd)
551             {
552                 if (msg.wParam == L'C' && GetKeyState(VK_CONTROL) < 0)
553                     SendMessageW(hwnd, WM_COPY, 0, 0);
554             }
555 
556             if (!IsWindow( hwnd )) return 0;
557             if (!(dlgInfo->flags & DF_END) && !IsDialogMessageW( hwnd, &msg))
558             {
559                 TranslateMessage( &msg );
560                 DispatchMessageW( &msg );
561             }
562             if (!IsWindow( hwnd )) return 0;
563             if (dlgInfo->flags & DF_END) break;
564 
565             if (bFirstEmpty && msg.message == WM_TIMER)
566             {
567                 ShowWindow( hwnd, SW_SHOWNORMAL );
568                 bFirstEmpty = FALSE;
569             }
570         }
571     }
572     retval = dlgInfo->idResult;
573     DestroyWindow( hwnd );
574     return retval;
575 }
576 
577  /***********************************************************************
578  *           DIALOG_ParseTemplate32
579  *
580  * Fill a DLG_TEMPLATE structure from the dialog template, and return
581  * a pointer to the first control.
582  */
583 static LPCSTR DIALOG_ParseTemplate32( LPCSTR template, DLG_TEMPLATE * result )
584 {
585     const WORD *p = (const WORD *)template;
586     WORD signature;
587     WORD dlgver;
588 
589     dlgver = GET_WORD(p); p++;
590     signature = GET_WORD(p); p++;
591 
592     if (dlgver == 1 && signature == 0xffff)  /* DIALOGEX resource */
593     {
594         result->dialogEx = TRUE;
595         result->helpId   = GET_DWORD(p); p += 2;
596         result->exStyle  = GET_DWORD(p); p += 2;
597         result->style    = GET_DWORD(p); p += 2;
598     }
599     else
600     {
601         result->style = GET_DWORD(p - 2);
602         result->dialogEx = FALSE;
603         result->helpId   = 0;
604         result->exStyle  = GET_DWORD(p); p += 2;
605     }
606     result->nbItems = GET_WORD(p); p++;
607     result->x       = GET_WORD(p); p++;
608     result->y       = GET_WORD(p); p++;
609     result->cx      = GET_WORD(p); p++;
610     result->cy      = GET_WORD(p); p++;
611     TRACE("DIALOG%s %d, %d, %d, %d, %d\n",
612            result->dialogEx ? "EX" : "", result->x, result->y,
613            result->cx, result->cy, result->helpId );
614     TRACE(" STYLE 0x%08x\n", result->style );
615     TRACE(" EXSTYLE 0x%08x\n", result->exStyle );
616 
617     /* Get the menu name */
618 
619     switch(GET_WORD(p))
620     {
621         case 0x0000:
622             result->menuName = NULL;
623             p++;
624             break;
625         case 0xffff:
626             result->menuName = (LPCWSTR)(UINT_PTR)GET_WORD( p + 1 );
627             p += 2;
628             TRACE(" MENU %04x\n", LOWORD(result->menuName) );
629             break;
630         default:
631             result->menuName = (LPCWSTR)p;
632             TRACE(" MENU %s\n", debugstr_w(result->menuName) );
633             p += strlenW( result->menuName ) + 1;
634             break;
635     }
636 
637     /* Get the class name */
638 
639     switch(GET_WORD(p))
640     {
641         case 0x0000:
642             result->className = WC_DIALOG;
643             p++;
644             break;
645         case 0xffff:
646             result->className = (LPCWSTR)(UINT_PTR)GET_WORD( p + 1 );
647             p += 2;
648             TRACE(" CLASS %04x\n", LOWORD(result->className) );
649             break;
650         default:
651             result->className = (LPCWSTR)p;
652             TRACE(" CLASS %s\n", debugstr_w( result->className ));
653             p += strlenW( result->className ) + 1;
654             break;
655     }
656 
657     /* Get the window caption */
658 
659     result->caption = (LPCWSTR)p;
660     p += strlenW( result->caption ) + 1;
661     TRACE(" CAPTION %s\n", debugstr_w( result->caption ) );
662 
663     /* Get the font name */
664 
665     result->pointSize = 0;
666     result->faceName = NULL;
667     result->weight = FW_DONTCARE;
668     result->italic = FALSE;
669 
670     if (result->style & DS_SETFONT)
671     {
672         result->pointSize = GET_WORD(p);
673         p++;
674 
675         /* If pointSize is 0x7fff, it means that we need to use the font
676          * in NONCLIENTMETRICSW.lfMessageFont, and NOT read the weight,
677          * italic, and facename from the dialog template.
678          */
679         if (result->pointSize == 0x7fff)
680         {
681             /* We could call SystemParametersInfo here, but then we'd have
682              * to convert from pixel size to point size (which can be
683              * imprecise).
684              */
685             TRACE(" FONT: Using message box font\n");
686         }
687         else
688         {
689             if (result->dialogEx)
690             {
691                 result->weight = GET_WORD(p); p++;
692                 result->italic = LOBYTE(GET_WORD(p)); p++;
693             }
694             result->faceName = (LPCWSTR)p;
695             p += strlenW( result->faceName ) + 1;
696 
697             TRACE(" FONT %d, %s, %d, %s\n",
698                   result->pointSize, debugstr_w( result->faceName ),
699                   result->weight, result->italic ? "TRUE" : "FALSE" );
700         }
701     }
702 
703     /* First control is on dword boundary */
704     return (LPCSTR)((((UINT_PTR)p) + 3) & ~3);
705 }
706 
707 /***********************************************************************
708  *           DEFDLG_SetFocus
709  *
710  * Set the focus to a control of the dialog, selecting the text if
711  * the control is an edit dialog that has DLGC_HASSETSEL.
712  */
713 static void DEFDLG_SetFocus( HWND hwndCtrl )
714 {
715     if (SendMessageW( hwndCtrl, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
716         SendMessageW( hwndCtrl, EM_SETSEL, 0, -1 );
717     SetFocus( hwndCtrl );
718 }
719 
720 
721 /***********************************************************************
722  *           DEFDLG_SaveFocus
723  */
724 static void DEFDLG_SaveFocus( HWND hwnd )
725 {
726     DIALOGINFO *infoPtr;
727     HWND hwndFocus = GetFocus();
728 
729     if (!hwndFocus || !IsChild( hwnd, hwndFocus )) return;
730     if (!(infoPtr = GETDLGINFO(hwnd))) return;
731     infoPtr->hwndFocus = hwndFocus;
732     /* Remove default button */
733 }
734 
735 
736 /***********************************************************************
737  *           DEFDLG_RestoreFocus
738  */
739 static void DEFDLG_RestoreFocus( HWND hwnd, BOOL justActivate )
740 {
741     DIALOGINFO *infoPtr;
742 
743     if (IsIconic( hwnd )) return;
744     if (!(infoPtr = GETDLGINFO(hwnd))) return;
745     /* Don't set the focus back to controls if EndDialog is already called.*/
746     if (infoPtr->flags & DF_END) return;
747     if (!IsWindow(infoPtr->hwndFocus) || infoPtr->hwndFocus == hwnd) {
748         if (justActivate) return;
749         /* If no saved focus control exists, set focus to the first visible,
750            non-disabled, WS_TABSTOP control in the dialog */
751         infoPtr->hwndFocus = GetNextDlgTabItem( hwnd, 0, FALSE );
752         /* If there are no WS_TABSTOP controls, set focus to the first visible,
753            non-disabled control in the dialog */
754         if (!infoPtr->hwndFocus) infoPtr->hwndFocus = GetNextDlgGroupItem( hwnd, 0, FALSE );
755         if (!IsWindow( infoPtr->hwndFocus )) return;
756     }
757     if (justActivate)
758         SetFocus( infoPtr->hwndFocus );
759     else
760         DEFDLG_SetFocus( infoPtr->hwndFocus );
761 
762     infoPtr->hwndFocus = NULL;
763 }
764 
765 /***********************************************************************
766  *           DIALOG_CreateIndirect
767  *       Creates a dialog box window
768  *
769  *       modal = TRUE if we are called from a modal dialog box.
770  *       (it's more compatible to do it here, as under Windows the owner
771  *       is never disabled if the dialog fails because of an invalid template)
772  */
773 static HWND DIALOG_CreateIndirect( HINSTANCE hInst, LPCVOID dlgTemplate,
774                                    HWND owner, DLGPROC dlgProc, LPARAM param,
775                                    BOOL unicode, HWND *modal_owner )
776 {
777     HWND hwnd;
778     RECT rect;
779     POINT pos;
780     SIZE size;
781     DLG_TEMPLATE template;
782     DIALOGINFO * dlgInfo = NULL;
783     DWORD units = GetDialogBaseUnits();
784     HWND disabled_owner = NULL;
785     HMENU hMenu = 0;
786     HFONT hUserFont = 0;
787     UINT flags = 0;
788     UINT xBaseUnit = LOWORD(units);
789     UINT yBaseUnit = HIWORD(units);
790 
791       /* Parse dialog template */
792 
793     if (!dlgTemplate) return 0;
794     dlgTemplate = DIALOG_ParseTemplate32( dlgTemplate, &template );
795 
796       /* Load menu */
797 
798     if (template.menuName) hMenu = LoadMenuW( hInst, template.menuName );
799 
800       /* Create custom font if needed */
801 
802     if (template.style & DS_SETFONT)
803     {
804         HDC dc = GetDC(0);
805 
806         if (template.pointSize == 0x7fff)
807         {
808             /* We get the message font from the non-client metrics */
809             NONCLIENTMETRICSW ncMetrics;
810 
811             ncMetrics.cbSize = sizeof(NONCLIENTMETRICSW);
812             if (SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
813                                       sizeof(NONCLIENTMETRICSW), &ncMetrics, 0))
814             {
815                 hUserFont = CreateFontIndirectW( &ncMetrics.lfMessageFont );
816             }
817         }
818         else
819         {
820             /* We convert the size to pixels and then make it -ve.  This works
821              * for both +ve and -ve template.pointSize */
822             int pixels = MulDiv(template.pointSize, GetDeviceCaps(dc , LOGPIXELSY), 72);
823             hUserFont = CreateFontW( -pixels, 0, 0, 0, template.weight,
824                                               template.italic, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
825                                               PROOF_QUALITY, FF_DONTCARE,
826                                               template.faceName );
827         }
828 
829         if (hUserFont)
830         {
831             SIZE charSize;
832             HFONT hOldFont = SelectObject( dc, hUserFont );
833             charSize.cx = GdiGetCharDimensions( dc, NULL, &charSize.cy );
834             if (charSize.cx)
835             {
836                 xBaseUnit = charSize.cx;
837                 yBaseUnit = charSize.cy;
838             }
839             SelectObject( dc, hOldFont );
840         }
841         ReleaseDC(0, dc);
842         TRACE("units = %d,%d\n", xBaseUnit, yBaseUnit );
843     }
844 
845     /* Create dialog main window */
846 
847     SetRect(&rect, 0, 0, MulDiv(template.cx, xBaseUnit, 4), MulDiv(template.cy, yBaseUnit, 8));
848     if (template.style & DS_CONTROL)
849         template.style &= ~(WS_CAPTION|WS_SYSMENU);
850     template.style |= DS_3DLOOK;
851     if (template.style & DS_MODALFRAME)
852         template.exStyle |= WS_EX_DLGMODALFRAME;
853     if ((template.style & DS_CONTROL) || !(template.style & WS_CHILD))
854         template.exStyle |= WS_EX_CONTROLPARENT;
855     AdjustWindowRectEx( &rect, template.style, (hMenu != 0), template.exStyle );
856     pos.x = rect.left;
857     pos.y = rect.top;
858     size.cx = rect.right - rect.left;
859     size.cy = rect.bottom - rect.top;
860 
861     if (template.x == CW_USEDEFAULT16)
862     {
863         pos.x = pos.y = CW_USEDEFAULT;
864     }
865     else
866     {
867         HMONITOR monitor = 0;
868         MONITORINFO mon_info;
869 
870         mon_info.cbSize = sizeof(mon_info);
871         if (template.style & DS_CENTER)
872         {
873             monitor = MonitorFromWindow( owner ? owner : GetActiveWindow(), MONITOR_DEFAULTTOPRIMARY );
874             GetMonitorInfoW( monitor, &mon_info );
875             pos.x = (mon_info.rcWork.left + mon_info.rcWork.right - size.cx) / 2;
876             pos.y = (mon_info.rcWork.top + mon_info.rcWork.bottom - size.cy) / 2;
877         }
878         else if (template.style & DS_CENTERMOUSE)
879         {
880             GetCursorPos( &pos );
881             monitor = MonitorFromPoint( pos, MONITOR_DEFAULTTOPRIMARY );
882             GetMonitorInfoW( monitor, &mon_info );
883         }
884         else
885         {
886             pos.x += MulDiv(template.x, xBaseUnit, 4);
887             pos.y += MulDiv(template.y, yBaseUnit, 8);
888             //
889             // REACTOS : Need an owner to be passed!!!
890             //
891             if (!(template.style & (WS_CHILD|DS_ABSALIGN)) && owner ) ClientToScreen( owner, &pos );
892         }
893         if ( !(template.style & WS_CHILD) )
894         {
895             INT dX, dY;
896 
897             /* try to fit it into the desktop */
898 
899             if (!monitor)
900             {
901                 SetRect( &rect, pos.x, pos.y, pos.x + size.cx, pos.y + size.cy );
902                 monitor = MonitorFromRect( &rect, MONITOR_DEFAULTTOPRIMARY );
903                 GetMonitorInfoW( monitor, &mon_info );
904             }
905             if ((dX = pos.x + size.cx + GetSystemMetrics(SM_CXDLGFRAME) - mon_info.rcWork.right) > 0)
906                 pos.x -= dX;
907             if ((dY = pos.y + size.cy + GetSystemMetrics(SM_CYDLGFRAME) - mon_info.rcWork.bottom) > 0)
908                 pos.y -= dY;
909             if( pos.x < mon_info.rcWork.left ) pos.x = mon_info.rcWork.left;
910             if( pos.y < mon_info.rcWork.top ) pos.y = mon_info.rcWork.top;
911         }
912     }
913 
914     if (modal_owner && owner)
915     {
916         HWND parent = NULL;
917         /*
918          * Owner needs to be top level window. We need to duplicate the logic from server,
919          * because we need to disable it before creating dialog window. Note that we do that
920          * even if dialog has WS_CHILD, but only for modal dialogs, which matched what
921          * Windows does.
922          */
923         while ((GetWindowLongW( owner, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD)
924         {
925             parent = GetParent( owner );
926             if (!parent || parent == GetDesktopWindow()) break;
927             owner = parent;
928         }
929         ////// Wine'ie babies need to fix your code!!!! CORE-11633
930         if (!parent) parent = GetAncestor( owner, GA_ROOT );
931 
932         if (parent)
933         {
934            owner = parent;
935 
936            if (IsWindowEnabled( owner ))
937            {
938                disabled_owner = owner;
939                EnableWindow( disabled_owner, FALSE );
940            }
941         }
942         *modal_owner = owner;
943     }
944 
945     if (unicode)
946     {
947         hwnd = CreateWindowExW(template.exStyle, template.className, template.caption,
948                                template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy,
949                                owner, hMenu, hInst, NULL );
950     }
951     else
952     {
953         LPCSTR class = (LPCSTR)template.className;
954         LPCSTR caption = (LPCSTR)template.caption;
955         LPSTR class_tmp = NULL;
956         LPSTR caption_tmp = NULL;
957 
958         if (!IS_INTRESOURCE(class))
959         {
960             DWORD len = WideCharToMultiByte( CP_ACP, 0, template.className, -1, NULL, 0, NULL, NULL );
961             class_tmp = HeapAlloc( GetProcessHeap(), 0, len );
962             WideCharToMultiByte( CP_ACP, 0, template.className, -1, class_tmp, len, NULL, NULL );
963             class = class_tmp;
964         }
965         if (!IS_INTRESOURCE(caption))
966         {
967             DWORD len = WideCharToMultiByte( CP_ACP, 0, template.caption, -1, NULL, 0, NULL, NULL );
968             caption_tmp = HeapAlloc( GetProcessHeap(), 0, len );
969             WideCharToMultiByte( CP_ACP, 0, template.caption, -1, caption_tmp, len, NULL, NULL );
970             caption = caption_tmp;
971         }
972         hwnd = CreateWindowExA(template.exStyle, class, caption,
973                                template.style & ~WS_VISIBLE, pos.x, pos.y, size.cx, size.cy,
974                                owner, hMenu, hInst, NULL );
975         HeapFree( GetProcessHeap(), 0, class_tmp );
976         HeapFree( GetProcessHeap(), 0, caption_tmp );
977     }
978 
979     if (!hwnd)
980     {
981         if (hUserFont) DeleteObject( hUserFont );
982         if (hMenu) DestroyMenu( hMenu );
983         if (disabled_owner) EnableWindow( disabled_owner, TRUE );
984         return 0;
985     }
986 
987     /* moved this from the top of the method to here as DIALOGINFO structure
988     will be valid only after WM_CREATE message has been handled in DefDlgProc
989     All the members of the structure get filled here using temp variables */
990     dlgInfo = DIALOG_get_info( hwnd, TRUE );
991     // ReactOS
992     if (dlgInfo == NULL)
993     {
994         if (hUserFont) DeleteObject( hUserFont );
995         if (hMenu) DestroyMenu( hMenu );
996         if (disabled_owner) EnableWindow( disabled_owner, TRUE );
997         return 0;
998     }
999     //
1000     dlgInfo->hwndFocus   = 0;
1001     dlgInfo->hUserFont   = hUserFont;
1002     dlgInfo->hMenu       = hMenu;
1003     dlgInfo->xBaseUnit   = xBaseUnit;
1004     dlgInfo->yBaseUnit   = yBaseUnit;
1005     dlgInfo->flags       = flags;
1006 
1007     if (template.helpId) SetWindowContextHelpId( hwnd, template.helpId );
1008 
1009     if (unicode) SetWindowLongPtrW( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
1010     else SetWindowLongPtrA( hwnd, DWLP_DLGPROC, (ULONG_PTR)dlgProc );
1011 
1012     if (dlgProc && dlgInfo->hUserFont)
1013         SendMessageW( hwnd, WM_SETFONT, (WPARAM)dlgInfo->hUserFont, 0 );
1014 
1015     /* Create controls */
1016 
1017     if (DIALOG_CreateControls32( hwnd, dlgTemplate, &template, hInst, unicode ))
1018     {
1019         /* Send initialisation messages and set focus */
1020 
1021         if (dlgProc)
1022         {
1023             HWND focus = GetNextDlgTabItem( hwnd, 0, FALSE );
1024             if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE );
1025             if (SendMessageW( hwnd, WM_INITDIALOG, (WPARAM)focus, param ) && IsWindow( hwnd ) &&
1026                 ((~template.style & DS_CONTROL) || (template.style & WS_VISIBLE)))
1027             {
1028                 /* By returning TRUE, app has requested a default focus assignment.
1029                  * WM_INITDIALOG may have changed the tab order, so find the first
1030                  * tabstop control again. */
1031                 focus = GetNextDlgTabItem( hwnd, 0, FALSE );
1032                 if (!focus) focus = GetNextDlgGroupItem( hwnd, 0, FALSE );
1033                 if (focus)
1034                 {
1035                     if (SendMessageW( focus, WM_GETDLGCODE, 0, 0 ) & DLGC_HASSETSEL)
1036                         SendMessageW( focus, EM_SETSEL, 0, MAXLONG );
1037                     SetFocus( focus );
1038                 }
1039             }
1040 //// ReactOS see 43396, Fixes setting focus on Open and Close dialogs to the FileName edit control in OpenOffice.
1041 //// This now breaks test_SaveRestoreFocus.
1042             //DEFDLG_SaveFocus( hwnd );
1043 ////
1044         }
1045 //// ReactOS Rev 30613 & 30644
1046         if (!(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_CHILD))
1047             SendMessageW( hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, 0), 0);
1048 ////
1049         if (template.style & WS_VISIBLE && !(GetWindowLongPtrW( hwnd, GWL_STYLE ) & WS_VISIBLE))
1050         {
1051            ShowWindow( hwnd, SW_SHOWNORMAL );   /* SW_SHOW doesn't always work */
1052            UpdateWindow( hwnd );
1053            IntNotifyWinEvent(EVENT_SYSTEM_DIALOGSTART, hwnd, OBJID_WINDOW, CHILDID_SELF, 0);
1054         }
1055         return hwnd;
1056     }
1057     if (disabled_owner) EnableWindow( disabled_owner, TRUE );
1058     IntNotifyWinEvent(EVENT_SYSTEM_DIALOGEND, hwnd, OBJID_WINDOW, CHILDID_SELF, 0);
1059     if( IsWindow(hwnd) )
1060     {
1061       DestroyWindow( hwnd );
1062       //// ReactOS
1063       if (owner)
1064       {  ERR("DIALOG_CreateIndirect 1\n");
1065          if ( NtUserGetThreadState(THREADSTATE_FOREGROUNDTHREAD) && // Rule #1.
1066              !NtUserQueryWindow(owner, QUERY_WINDOW_FOREGROUND) )
1067          { ERR("DIALOG_CreateIndirect SFW\n");
1068             SetForegroundWindow(owner);
1069          }
1070       }
1071       ////
1072     }
1073     return 0;
1074 }
1075 
1076 
1077 /***********************************************************************
1078  *           DEFDLG_FindDefButton
1079  *
1080  * Find the current default push-button.
1081  */
1082 static HWND DEFDLG_FindDefButton( HWND hwndDlg )
1083 {
1084     HWND hwndChild, hwndTmp;
1085 
1086     hwndChild = GetWindow( hwndDlg, GW_CHILD );
1087     while (hwndChild)
1088     {
1089         if (SendMessageW( hwndChild, WM_GETDLGCODE, 0, 0 ) & DLGC_DEFPUSHBUTTON)
1090             break;
1091 
1092         /* Recurse into WS_EX_CONTROLPARENT controls */
1093         if (GetWindowLongPtrW( hwndChild, GWL_EXSTYLE ) & WS_EX_CONTROLPARENT)
1094         {
1095             LONG dsStyle = GetWindowLongPtrW( hwndChild, GWL_STYLE );
1096             if ((dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED) &&
1097                 (hwndTmp = DEFDLG_FindDefButton(hwndChild)) != NULL)
1098            return hwndTmp;
1099         }
1100         hwndChild = GetWindow( hwndChild, GW_HWNDNEXT );
1101     }
1102     return hwndChild;
1103 }
1104 
1105 
1106 /***********************************************************************
1107  *           DEFDLG_SetDefId
1108  *
1109  * Set the default button id.
1110  */
1111 static BOOL DEFDLG_SetDefId( HWND hwndDlg, DIALOGINFO *dlgInfo, WPARAM wParam)
1112 {
1113     DWORD dlgcode=0; /* initialize just to avoid a warning */
1114     HWND hwndOld, hwndNew = GetDlgItem(hwndDlg, wParam);
1115     INT old_id = dlgInfo->idResult;
1116 
1117     dlgInfo->idResult = wParam;
1118     if (hwndNew &&
1119         !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
1120             & (DLGC_UNDEFPUSHBUTTON | DLGC_BUTTON)))
1121         return FALSE;  /* Destination is not a push button */
1122 
1123     /* Make sure the old default control is a valid push button ID */
1124     hwndOld = GetDlgItem( hwndDlg, old_id );
1125     if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
1126         hwndOld = DEFDLG_FindDefButton( hwndDlg );
1127     if (hwndOld && hwndOld != hwndNew)
1128         SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
1129 
1130     if (hwndNew)
1131     {
1132         if(dlgcode & DLGC_UNDEFPUSHBUTTON)
1133             SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
1134     }
1135     return TRUE;
1136 }
1137 
1138 
1139 /***********************************************************************
1140  *           DEFDLG_SetDefButton
1141  *
1142  * Set the new default button to be hwndNew.
1143  */
1144 static BOOL DEFDLG_SetDefButton( HWND hwndDlg, DIALOGINFO *dlgInfo, HWND hwndNew )
1145 {
1146     DWORD dlgcode=0; /* initialize just to avoid a warning */
1147     HWND hwndOld = GetDlgItem( hwndDlg, dlgInfo->idResult );
1148 
1149     if (hwndNew &&
1150         !((dlgcode=SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 ))
1151             & (DLGC_UNDEFPUSHBUTTON | DLGC_DEFPUSHBUTTON)))
1152     {
1153         /**
1154          * Need to draw only default push button rectangle.
1155          * Since the next control is not a push button, need to draw the push
1156          * button rectangle for the default control.
1157          */
1158         hwndNew = hwndOld;
1159         dlgcode = SendMessageW(hwndNew, WM_GETDLGCODE, 0, 0 );
1160     }
1161 
1162     /* Make sure the old default control is a valid push button ID */
1163     if (!hwndOld || !(SendMessageW( hwndOld, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
1164         hwndOld = DEFDLG_FindDefButton( hwndDlg );
1165     if (hwndOld && hwndOld != hwndNew)
1166         SendMessageW( hwndOld, BM_SETSTYLE, BS_PUSHBUTTON, TRUE );
1167 
1168     if (hwndNew)
1169     {
1170         if(dlgcode & DLGC_UNDEFPUSHBUTTON)
1171             SendMessageW( hwndNew, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE );
1172     }
1173     return TRUE;
1174 }
1175 
1176 
1177 /***********************************************************************
1178  *           DEFDLG_Proc
1179  *
1180  * Implementation of DefDlgProc(). Only handle messages that need special
1181  * handling for dialogs.
1182  */
1183 static LRESULT DEFDLG_Proc( HWND hwnd, UINT msg, WPARAM wParam,
1184                             LPARAM lParam, DIALOGINFO *dlgInfo )
1185 {
1186     switch(msg)
1187     {
1188         case WM_ERASEBKGND:
1189         {
1190             HBRUSH brush = GetControlColor( hwnd, hwnd, (HDC)wParam, WM_CTLCOLORDLG);
1191             if (brush)
1192             {
1193                 RECT rect;
1194                 HDC hdc = (HDC)wParam;
1195                 GetClientRect( hwnd, &rect );
1196                 DPtoLP( hdc, (LPPOINT)&rect, 2 );
1197                 FillRect( hdc, &rect, brush );
1198             }
1199             return 1;
1200         }
1201         case WM_NCDESTROY:
1202 //// ReactOS
1203             if ((dlgInfo = (DIALOGINFO *)SetWindowLongPtrW( hwnd, DWLP_ROS_DIALOGINFO, 0 )))
1204             {
1205                 if (dlgInfo->hUserFont) DeleteObject( dlgInfo->hUserFont );
1206                 if (dlgInfo->hMenu) DestroyMenu( dlgInfo->hMenu );
1207                 HeapFree( GetProcessHeap(), 0, dlgInfo );
1208                 NtUserSetThreadState(0,DF_DIALOGACTIVE);
1209                 NtUserxSetDialogPointer( hwnd, 0 );
1210             }
1211              /* Window clean-up */
1212             return DefWindowProcA( hwnd, msg, wParam, lParam );
1213 
1214         case WM_SHOWWINDOW:
1215             if (!wParam) DEFDLG_SaveFocus( hwnd );
1216             return DefWindowProcA( hwnd, msg, wParam, lParam );
1217 
1218         case WM_ACTIVATE:
1219             { // ReactOS
1220                DWORD dwSetFlag;
1221                HWND hwndparent = DIALOG_FindMsgDestination( hwnd );
1222                // if WA_CLICK/ACTIVE ? set dialog is active.
1223                dwSetFlag = wParam ? DF_DIALOGACTIVE : 0;
1224                if (hwndparent != hwnd) NtUserSetThreadState(dwSetFlag, DF_DIALOGACTIVE);
1225             }
1226             if (wParam) DEFDLG_RestoreFocus( hwnd, TRUE );
1227             else DEFDLG_SaveFocus( hwnd );
1228             return 0;
1229 
1230         case WM_SETFOCUS:
1231             DEFDLG_RestoreFocus( hwnd, FALSE );
1232             return 0;
1233 
1234         case DM_SETDEFID:
1235             if (dlgInfo && !(dlgInfo->flags & DF_END))
1236                 DEFDLG_SetDefId( hwnd, dlgInfo, wParam );
1237             return 1;
1238 
1239         case DM_GETDEFID:
1240             if (dlgInfo && !(dlgInfo->flags & DF_END))
1241             {
1242                 HWND hwndDefId;
1243                 if (dlgInfo->idResult)
1244                     return MAKELONG( dlgInfo->idResult, DC_HASDEFID );
1245                 if ((hwndDefId = DEFDLG_FindDefButton( hwnd )))
1246                     return MAKELONG( GetDlgCtrlID( hwndDefId ), DC_HASDEFID);
1247             }
1248             return 0;
1249 
1250         case WM_NEXTDLGCTL:
1251             if (dlgInfo)
1252             {
1253                 HWND hwndDest = (HWND)wParam;
1254                 if (!lParam)
1255                     hwndDest = GetNextDlgTabItem(hwnd, GetFocus(), wParam);
1256                 if (hwndDest) DEFDLG_SetFocus( hwndDest );
1257                 DEFDLG_SetDefButton( hwnd, dlgInfo, hwndDest );
1258             }
1259             return 0;
1260 
1261         case WM_ENTERMENULOOP:
1262         case WM_LBUTTONDOWN:
1263         case WM_NCLBUTTONDOWN:
1264             {
1265                 HWND hwndFocus = GetFocus();
1266                 if (hwndFocus)
1267                 {
1268                     /* always make combo box hide its listbox control */
1269                     if (!SendMessageW( hwndFocus, CB_SHOWDROPDOWN, FALSE, 0 ))
1270                         SendMessageW( GetParent(hwndFocus), CB_SHOWDROPDOWN, FALSE, 0 );
1271                 }
1272             }
1273             return DefWindowProcA( hwnd, msg, wParam, lParam );
1274 
1275         case WM_GETFONT:
1276             return dlgInfo ? (LRESULT)dlgInfo->hUserFont : 0;
1277 
1278         case WM_CLOSE:
1279             PostMessageA( hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL, BN_CLICKED),
1280                             (LPARAM)GetDlgItem( hwnd, IDCANCEL ) );
1281             return 0;
1282     }
1283     return 0;
1284 }
1285 
1286 /***********************************************************************
1287  *           DEFDLG_Epilog
1288  */
1289 static LRESULT DEFDLG_Epilog(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL fResult, BOOL fAnsi)
1290 {
1291     if ((msg >= WM_CTLCOLORMSGBOX && msg <= WM_CTLCOLORSTATIC) ||
1292          msg == WM_CTLCOLOR)
1293        {
1294           if (fResult) return fResult;
1295 
1296           return fAnsi ? DefWindowProcA(hwnd, msg, wParam, lParam):
1297                          DefWindowProcW(hwnd, msg, wParam, lParam);
1298        }
1299     if ( msg == WM_COMPAREITEM ||
1300          msg == WM_VKEYTOITEM || msg == WM_CHARTOITEM ||
1301          msg == WM_QUERYDRAGICON || msg == WM_INITDIALOG)
1302         return fResult;
1303 
1304     return GetWindowLongPtrW( hwnd, DWLP_MSGRESULT );
1305 }
1306 
1307 /***********************************************************************
1308  *           DIALOG_GetNextTabItem
1309  *
1310  * Helper for GetNextDlgTabItem
1311  */
1312 static HWND DIALOG_GetNextTabItem( HWND hwndMain, HWND hwndDlg, HWND hwndCtrl, BOOL fPrevious )
1313 {
1314     LONG dsStyle;
1315     LONG exStyle;
1316     UINT wndSearch = fPrevious ? GW_HWNDPREV : GW_HWNDNEXT;
1317     HWND retWnd = 0;
1318     HWND hChildFirst = 0;
1319 
1320     if(!hwndCtrl)
1321     {
1322         hChildFirst = GetWindow(hwndDlg,GW_CHILD);
1323         if(fPrevious) hChildFirst = GetWindow(hChildFirst,GW_HWNDLAST);
1324     }
1325     else if (IsChild( hwndMain, hwndCtrl ))
1326     {
1327         hChildFirst = GetWindow(hwndCtrl,wndSearch);
1328         if(!hChildFirst)
1329         {
1330             if(GetParent(hwndCtrl) != hwndMain)
1331                 /* i.e. if we are not at the top level of the recursion */
1332                 hChildFirst = GetWindow(GetParent(hwndCtrl),wndSearch);
1333             else
1334                 hChildFirst = GetWindow(hwndCtrl, fPrevious ? GW_HWNDLAST : GW_HWNDFIRST);
1335         }
1336     }
1337 
1338     while(hChildFirst)
1339     {
1340         dsStyle = GetWindowLongPtrA(hChildFirst,GWL_STYLE);
1341         exStyle = GetWindowLongPtrA(hChildFirst,GWL_EXSTYLE);
1342         if( (exStyle & WS_EX_CONTROLPARENT) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1343         {
1344             HWND retWnd;
1345             retWnd = DIALOG_GetNextTabItem(hwndMain,hChildFirst,NULL,fPrevious );
1346             if (retWnd) return (retWnd);
1347         }
1348         else if( (dsStyle & WS_TABSTOP) && (dsStyle & WS_VISIBLE) && !(dsStyle & WS_DISABLED))
1349         {
1350             return (hChildFirst);
1351         }
1352         hChildFirst = GetWindow(hChildFirst,wndSearch);
1353     }
1354     if(hwndCtrl)
1355     {
1356         HWND hParent = GetParent(hwndCtrl);
1357         while(hParent)
1358         {
1359             if(hParent == hwndMain) break;
1360             retWnd = DIALOG_GetNextTabItem(hwndMain,GetParent(hParent),hParent,fPrevious );
1361             if(retWnd) break;
1362             hParent = GetParent(hParent);
1363         }
1364         if(!retWnd)
1365             retWnd = DIALOG_GetNextTabItem(hwndMain,hwndMain,NULL,fPrevious );
1366     }
1367     return retWnd ? retWnd : hwndCtrl;
1368 }
1369 
1370 
1371 /**********************************************************************
1372  *	    DIALOG_DlgDirListW
1373  *
1374  * Helper function for DlgDirList*W
1375  */
1376 static INT DIALOG_DlgDirListW( HWND hDlg, LPWSTR spec, INT idLBox,
1377                                 INT idStatic, UINT attrib, BOOL combo )
1378 {
1379     HWND hwnd;
1380     LPWSTR orig_spec = spec;
1381     WCHAR any[] = {'*','.','*',0};
1382 
1383 #define SENDMSG(msg,wparam,lparam) \
1384     ((attrib & DDL_POSTMSGS) ? PostMessageW( hwnd, msg, wparam, lparam ) \
1385                              : SendMessageW( hwnd, msg, wparam, lparam ))
1386 
1387     TRACE("%p %s %d %d %04x\n", hDlg, debugstr_w(spec), idLBox, idStatic, attrib );
1388 
1389     /* If the path exists and is a directory, chdir to it */
1390     if (!spec || !spec[0] || SetCurrentDirectoryW( spec )) spec = any;
1391     else
1392     {
1393         WCHAR *p, *p2;
1394         p = spec;
1395         if ((p2 = strchrW( p, ':' ))) p = p2 + 1;
1396         if ((p2 = strrchrW( p, '\\' ))) p = p2;
1397         if ((p2 = strrchrW( p, '/' ))) p = p2;
1398         if (p != spec)
1399         {
1400             WCHAR sep = *p;
1401             *p = 0;
1402             if (!SetCurrentDirectoryW( spec ))
1403             {
1404                 *p = sep;  /* Restore the original spec */
1405                 return FALSE;
1406             }
1407             spec = p + 1;
1408         }
1409     }
1410 
1411     TRACE( "mask=%s\n", spec );
1412 
1413     if (idLBox && ((hwnd = GetDlgItem( hDlg, idLBox )) != 0))
1414     {
1415         if (attrib == DDL_DRIVES) attrib |= DDL_EXCLUSIVE;
1416 
1417         SENDMSG( combo ? CB_RESETCONTENT : LB_RESETCONTENT, 0, 0 );
1418         if (attrib & DDL_DIRECTORY)
1419         {
1420             if (!(attrib & DDL_EXCLUSIVE))
1421             {
1422                 SENDMSG( combo ? CB_DIR : LB_DIR,
1423                          attrib & ~(DDL_DIRECTORY | DDL_DRIVES),
1424                          (LPARAM)spec );
1425             }
1426             SENDMSG( combo ? CB_DIR : LB_DIR,
1427                    (attrib & (DDL_DIRECTORY | DDL_DRIVES)) | DDL_EXCLUSIVE,
1428                    (LPARAM)any );
1429         }
1430         else
1431         {
1432             SENDMSG( combo ? CB_DIR : LB_DIR, attrib, (LPARAM)spec );
1433         }
1434     }
1435 
1436     /* Convert path specification to uppercase */
1437     if (spec) CharUpperW(spec);
1438 
1439     if (idStatic && ((hwnd = GetDlgItem( hDlg, idStatic )) != 0))
1440     {
1441         WCHAR temp[MAX_PATH];
1442         GetCurrentDirectoryW( sizeof(temp)/sizeof(WCHAR), temp );
1443         CharLowerW( temp );
1444         /* Can't use PostMessage() here, because the string is on the stack */
1445         SetDlgItemTextW( hDlg, idStatic, temp );
1446     }
1447 
1448     if (orig_spec && (spec != orig_spec))
1449     {
1450         /* Update the original file spec */
1451         WCHAR *p = spec;
1452         while ((*orig_spec++ = *p++));
1453     }
1454 
1455     return TRUE;
1456 #undef SENDMSG
1457 }
1458 
1459 
1460 /**********************************************************************
1461  *	    DIALOG_DlgDirListA
1462  *
1463  * Helper function for DlgDirList*A
1464  */
1465 static INT DIALOG_DlgDirListA( HWND hDlg, LPSTR spec, INT idLBox,
1466                                INT idStatic, UINT attrib, BOOL combo )
1467 {
1468     if (spec)
1469     {
1470         INT ret, len = MultiByteToWideChar( CP_ACP, 0, spec, -1, NULL, 0 );
1471         LPWSTR specW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
1472         if (specW == NULL)
1473             return FALSE;
1474         MultiByteToWideChar( CP_ACP, 0, spec, -1, specW, len );
1475         ret = DIALOG_DlgDirListW( hDlg, specW, idLBox, idStatic, attrib, combo );
1476         WideCharToMultiByte( CP_ACP, 0, specW, -1, spec, 0x7fffffff, NULL, NULL );
1477         HeapFree( GetProcessHeap(), 0, specW );
1478         return ret;
1479     }
1480     return DIALOG_DlgDirListW( hDlg, NULL, idLBox, idStatic, attrib, combo );
1481 }
1482 
1483 /**********************************************************************
1484  *           DIALOG_DlgDirSelect
1485  *
1486  * Helper function for DlgDirSelect*
1487  */
1488 static BOOL DIALOG_DlgDirSelect( HWND hwnd, LPWSTR str, INT len,
1489                                  INT id, BOOL unicode, BOOL combo )
1490 {
1491     WCHAR *buffer, *ptr;
1492     INT item, size;
1493     BOOL ret;
1494     HWND listbox = GetDlgItem( hwnd, id );
1495 
1496     TRACE("%p %s %d\n", hwnd, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str), id );
1497     if (!listbox) return FALSE;
1498 
1499     item = SendMessageW(listbox, combo ? CB_GETCURSEL : LB_GETCURSEL, 0, 0 );
1500     if (item == LB_ERR) return FALSE;
1501 
1502     size = SendMessageW(listbox, combo ? CB_GETLBTEXTLEN : LB_GETTEXTLEN, item, 0 );
1503     if (size == LB_ERR) return FALSE;
1504 
1505     if (!(buffer = HeapAlloc( GetProcessHeap(), 0, (size+2) * sizeof(WCHAR) ))) return FALSE;
1506 
1507     SendMessageW( listbox, combo ? CB_GETLBTEXT : LB_GETTEXT, item, (LPARAM)buffer );
1508 
1509     if ((ret = (buffer[0] == '[')))  /* drive or directory */
1510     {
1511         if (buffer[1] == '-')  /* drive */
1512         {
1513             buffer[3] = ':';
1514             buffer[4] = 0;
1515             ptr = buffer + 2;
1516         }
1517         else
1518         {
1519             buffer[strlenW(buffer)-1] = '\\';
1520             ptr = buffer + 1;
1521         }
1522     }
1523     else
1524     {
1525         /* Filenames without a dot extension must have one tacked at the end */
1526         if (strchrW(buffer, '.') == NULL)
1527         {
1528             buffer[strlenW(buffer)+1] = '\0';
1529             buffer[strlenW(buffer)] = '.';
1530         }
1531         ptr = buffer;
1532     }
1533 
1534     if (!unicode)
1535     {
1536         if (len > 0 && !WideCharToMultiByte( CP_ACP, 0, ptr, -1, (LPSTR)str, len, 0, 0 ))
1537             ((LPSTR)str)[len-1] = 0;
1538     }
1539     else lstrcpynW( str, ptr, len );
1540     HeapFree( GetProcessHeap(), 0, buffer );
1541     TRACE("Returning %d %s\n", ret, unicode ? debugstr_w(str) : debugstr_a((LPSTR)str) );
1542     return ret;
1543 }
1544 
1545 
1546 /* FUNCTIONS *****************************************************************/
1547 
1548 /*
1549  * @implemented
1550  */
1551 HWND
1552 WINAPI
1553 CreateDialogIndirectParamAorW(
1554   HINSTANCE hInstance,
1555   LPCDLGTEMPLATE lpTemplate,
1556   HWND hWndParent,
1557   DLGPROC lpDialogFunc,
1558   LPARAM lParamInit,
1559   DWORD Flags)
1560 {
1561 /* FIXME:
1562  *   This function might be obsolete since I don't think it is exported by NT
1563  *   Also wine has one more parameter identifying weather it should call
1564  *   the function with unicode or not
1565  */
1566   return DIALOG_CreateIndirect( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit , Flags == DLG_ISANSI ? FALSE : TRUE, NULL );
1567 }
1568 
1569 
1570 /*
1571  * @implemented
1572  */
1573 HWND
1574 WINAPI
1575 CreateDialogIndirectParamA(
1576   HINSTANCE hInstance,
1577   LPCDLGTEMPLATE lpTemplate,
1578   HWND hWndParent,
1579   DLGPROC lpDialogFunc,
1580   LPARAM lParamInit)
1581 {
1582   return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, DLG_ISANSI);
1583 }
1584 
1585 
1586 /*
1587  * @implemented
1588  */
1589 HWND
1590 WINAPI
1591 CreateDialogIndirectParamW(
1592   HINSTANCE hInstance,
1593   LPCDLGTEMPLATE lpTemplate,
1594   HWND hWndParent,
1595   DLGPROC lpDialogFunc,
1596   LPARAM lParamInit)
1597 {
1598   return CreateDialogIndirectParamAorW( hInstance, lpTemplate, hWndParent, lpDialogFunc, lParamInit, 0);
1599 }
1600 
1601 
1602 /*
1603  * @implemented
1604  */
1605 HWND
1606 WINAPI
1607 CreateDialogParamA(
1608   HINSTANCE hInstance,
1609   LPCSTR lpTemplateName,
1610   HWND hWndParent,
1611   DLGPROC lpDialogFunc,
1612   LPARAM dwInitParam)
1613 {
1614 	HRSRC hrsrc;
1615 	LPCDLGTEMPLATE ptr;
1616 
1617     if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG ))) return 0;
1618     if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1619 	return CreateDialogIndirectParamA( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1620 }
1621 
1622 
1623 /*
1624  * @implemented
1625  */
1626 HWND
1627 WINAPI
1628 CreateDialogParamW(
1629   HINSTANCE hInstance,
1630   LPCWSTR lpTemplateName,
1631   HWND hWndParent,
1632   DLGPROC lpDialogFunc,
1633   LPARAM dwInitParam)
1634 {
1635 	HRSRC hrsrc;
1636 	LPCDLGTEMPLATE ptr;
1637 
1638 	if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG ))) return 0;
1639 	if (!(ptr = (LPCDLGTEMPLATE)LoadResource(hInstance, hrsrc))) return 0;
1640 	return CreateDialogIndirectParamW( hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam );
1641 }
1642 
1643 
1644 /*
1645  * @implemented
1646  */
1647 LRESULT
1648 WINAPI
1649 DefDlgProcA(
1650   HWND hDlg,
1651   UINT Msg,
1652   WPARAM wParam,
1653   LPARAM lParam)
1654 {
1655     DIALOGINFO *dlgInfo;
1656     WNDPROC dlgproc;
1657     BOOL result = FALSE;
1658 
1659     /* Perform DIALOGINFO initialization if not done */
1660     if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass.
1661 
1662     SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 );
1663 
1664     if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC )))
1665     {
1666         /* Call dialog procedure */
1667         result = CallWindowProcA( dlgproc, hDlg, Msg, wParam, lParam );
1668     }
1669 
1670     if (!result && IsWindow(hDlg))
1671     {
1672         /* callback didn't process this message */
1673 
1674         switch(Msg)
1675         {
1676             case WM_ERASEBKGND:
1677             case WM_SHOWWINDOW:
1678             case WM_ACTIVATE:
1679             case WM_SETFOCUS:
1680             case DM_SETDEFID:
1681             case DM_GETDEFID:
1682             case WM_NEXTDLGCTL:
1683             case WM_GETFONT:
1684             case WM_CLOSE:
1685             case WM_NCDESTROY:
1686             case WM_ENTERMENULOOP:
1687             case WM_LBUTTONDOWN:
1688             case WM_NCLBUTTONDOWN:
1689                  return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1690             case WM_INITDIALOG:
1691             case WM_VKEYTOITEM:
1692             case WM_COMPAREITEM:
1693             case WM_CHARTOITEM:
1694                  break;
1695 
1696             default:
1697                  return DefWindowProcA( hDlg, Msg, wParam, lParam );
1698         }
1699     }
1700     return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, TRUE);
1701 }
1702 
1703 
1704 /*
1705  * @implemented
1706  */
1707 LRESULT
1708 WINAPI
1709 DefDlgProcW(
1710   HWND hDlg,
1711   UINT Msg,
1712   WPARAM wParam,
1713   LPARAM lParam)
1714 {
1715     DIALOGINFO *dlgInfo;
1716     WNDPROC dlgproc;
1717     BOOL result = FALSE;
1718 
1719     /* Perform DIALOGINFO initialization if not done */
1720     if(!(dlgInfo = DIALOG_get_info( hDlg, TRUE ))) return 0; //// REACTOS : Always TRUE! See RealGetWindowClass.
1721 
1722     SetWindowLongPtrW( hDlg, DWLP_MSGRESULT, 0 );
1723 
1724     if ((dlgproc = (WNDPROC)GetWindowLongPtrW( hDlg, DWLP_DLGPROC )))
1725     {
1726         /* Call dialog procedure */
1727         result = CallWindowProcW( dlgproc, hDlg, Msg, wParam, lParam );
1728     }
1729 
1730     if (!result && IsWindow(hDlg))
1731     {
1732         /* callback didn't process this message */
1733 
1734         switch(Msg)
1735         {
1736             case WM_ERASEBKGND:
1737             case WM_SHOWWINDOW:
1738             case WM_ACTIVATE:
1739             case WM_SETFOCUS:
1740             case DM_SETDEFID:
1741             case DM_GETDEFID:
1742             case WM_NEXTDLGCTL:
1743             case WM_GETFONT:
1744             case WM_CLOSE:
1745             case WM_NCDESTROY:
1746             case WM_ENTERMENULOOP:
1747             case WM_LBUTTONDOWN:
1748             case WM_NCLBUTTONDOWN:
1749                  return DEFDLG_Proc( hDlg, Msg, wParam, lParam, dlgInfo );
1750             case WM_INITDIALOG:
1751             case WM_VKEYTOITEM:
1752             case WM_COMPAREITEM:
1753             case WM_CHARTOITEM:
1754                  break;
1755 
1756             default:
1757                  return DefWindowProcW( hDlg, Msg, wParam, lParam );
1758         }
1759     }
1760     return DEFDLG_Epilog(hDlg, Msg, wParam, lParam, result, FALSE);
1761 }
1762 
1763 
1764 /*
1765  * @implemented
1766  */
1767 INT_PTR
1768 WINAPI
1769 DialogBoxIndirectParamAorW(
1770   HINSTANCE hInstance,
1771   LPCDLGTEMPLATE hDialogTemplate,
1772   HWND hWndParent,
1773   DLGPROC lpDialogFunc,
1774   LPARAM dwInitParam,
1775   DWORD Flags)
1776 {
1777 /* FIXME:
1778  *  This function might be obsolete since I don't think it is exported by NT
1779  *  Also wine has one more parameter identifying weather it should call
1780  *  the function with unicode or not
1781  */
1782   HWND hWnd = DIALOG_CreateIndirect( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, Flags == DLG_ISANSI ? FALSE : TRUE, &hWndParent );
1783   if (hWnd) return DIALOG_DoDialogBox( hWnd, hWndParent );
1784   return -1;
1785 }
1786 
1787 
1788 /*
1789  * @implemented
1790  */
1791 INT_PTR
1792 WINAPI
1793 DialogBoxIndirectParamA(
1794   HINSTANCE hInstance,
1795   LPCDLGTEMPLATE hDialogTemplate,
1796   HWND hWndParent,
1797   DLGPROC lpDialogFunc,
1798   LPARAM dwInitParam)
1799 {
1800   return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, DLG_ISANSI);
1801 }
1802 
1803 
1804 /*
1805  * @implemented
1806  */
1807 INT_PTR
1808 WINAPI
1809 DialogBoxIndirectParamW(
1810   HINSTANCE hInstance,
1811   LPCDLGTEMPLATE hDialogTemplate,
1812   HWND hWndParent,
1813   DLGPROC lpDialogFunc,
1814   LPARAM dwInitParam)
1815 {
1816   return DialogBoxIndirectParamAorW( hInstance, hDialogTemplate, hWndParent, lpDialogFunc, dwInitParam, 0);
1817 }
1818 
1819 
1820 /*
1821  * @implemented
1822  */
1823 INT_PTR
1824 WINAPI
1825 DialogBoxParamA(
1826   HINSTANCE hInstance,
1827   LPCSTR lpTemplateName,
1828   HWND hWndParent,
1829   DLGPROC lpDialogFunc,
1830   LPARAM dwInitParam)
1831 {
1832     HWND hwnd;
1833     HRSRC hrsrc;
1834     LPCDLGTEMPLATE ptr;
1835 //// ReactOS rev 33532
1836     if (!(hrsrc = FindResourceA( hInstance, lpTemplateName, (LPCSTR)RT_DIALOG )) ||
1837         !(ptr = LoadResource(hInstance, hrsrc)))
1838     {
1839         SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
1840         return -1;
1841     }
1842     if (hWndParent != NULL && !IsWindow(hWndParent))
1843     {
1844         SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1845         return 0;
1846     }
1847     hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, FALSE, &hWndParent );
1848     if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1849     return -1;
1850 }
1851 
1852 
1853 /*
1854  * @implemented
1855  */
1856 INT_PTR
1857 WINAPI
1858 DialogBoxParamW(
1859   HINSTANCE hInstance,
1860   LPCWSTR lpTemplateName,
1861   HWND hWndParent,
1862   DLGPROC lpDialogFunc,
1863   LPARAM dwInitParam)
1864 {
1865     HWND hwnd;
1866     HRSRC hrsrc;
1867     LPCDLGTEMPLATE ptr;
1868 //// ReactOS rev 33532
1869     if (!(hrsrc = FindResourceW( hInstance, lpTemplateName, (LPCWSTR)RT_DIALOG )) ||
1870         !(ptr = LoadResource(hInstance, hrsrc)))
1871     {
1872         SetLastError(ERROR_RESOURCE_NAME_NOT_FOUND);
1873         return -1;
1874     }
1875     if (hWndParent != NULL && !IsWindow(hWndParent))
1876     {
1877         SetLastError(ERROR_INVALID_WINDOW_HANDLE);
1878         return 0;
1879     }
1880     hwnd = DIALOG_CreateIndirect(hInstance, ptr, hWndParent, lpDialogFunc, dwInitParam, TRUE, &hWndParent );
1881     if (hwnd) return DIALOG_DoDialogBox(hwnd, hWndParent);
1882     return -1;
1883 }
1884 
1885 
1886 /*
1887  * @implemented
1888  */
1889 int
1890 WINAPI
1891 DlgDirListA(
1892   HWND hDlg,
1893   LPSTR lpPathSpec,
1894   int nIDListBox,
1895   int nIDStaticPath,
1896   UINT uFileType)
1897 {
1898     return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
1899 }
1900 
1901 
1902 /*
1903  * @implemented
1904  */
1905 int
1906 WINAPI
1907 DlgDirListComboBoxA(
1908   HWND hDlg,
1909   LPSTR lpPathSpec,
1910   int nIDComboBox,
1911   int nIDStaticPath,
1912   UINT uFiletype)
1913 {
1914   return DIALOG_DlgDirListA( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE );
1915 }
1916 
1917 
1918 /*
1919  * @implemented
1920  */
1921 int
1922 WINAPI
1923 DlgDirListComboBoxW(
1924   HWND hDlg,
1925   LPWSTR lpPathSpec,
1926   int nIDComboBox,
1927   int nIDStaticPath,
1928   UINT uFiletype)
1929 {
1930   return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDComboBox, nIDStaticPath, uFiletype, TRUE );
1931 }
1932 
1933 
1934 /*
1935  * @implemented
1936  */
1937 int
1938 WINAPI
1939 DlgDirListW(
1940   HWND hDlg,
1941   LPWSTR lpPathSpec,
1942   int nIDListBox,
1943   int nIDStaticPath,
1944   UINT uFileType)
1945 {
1946   return DIALOG_DlgDirListW( hDlg, lpPathSpec, nIDListBox, nIDStaticPath, uFileType, FALSE );
1947 }
1948 
1949 
1950 /*
1951  * @implemented
1952  */
1953 BOOL
1954 WINAPI
1955 DlgDirSelectComboBoxExA(
1956   HWND hDlg,
1957   LPSTR lpString,
1958   int nCount,
1959   int nIDComboBox)
1960 {
1961   return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, FALSE, TRUE );
1962 }
1963 
1964 
1965 /*
1966  * @implemented
1967  */
1968 BOOL
1969 WINAPI
1970 DlgDirSelectComboBoxExW(
1971   HWND hDlg,
1972   LPWSTR lpString,
1973   int nCount,
1974   int nIDComboBox)
1975 {
1976   return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDComboBox, TRUE, TRUE );
1977 }
1978 
1979 
1980 /*
1981  * @implemented
1982  */
1983 BOOL
1984 WINAPI
1985 DlgDirSelectExA(
1986   HWND hDlg,
1987   LPSTR lpString,
1988   int nCount,
1989   int nIDListBox)
1990 {
1991   return DIALOG_DlgDirSelect( hDlg, (LPWSTR)lpString, nCount, nIDListBox, FALSE, FALSE );
1992 }
1993 
1994 
1995 /*
1996  * @implemented
1997  */
1998 BOOL
1999 WINAPI
2000 DlgDirSelectExW(
2001   HWND hDlg,
2002   LPWSTR lpString,
2003   int nCount,
2004   int nIDListBox)
2005 {
2006   return DIALOG_DlgDirSelect( hDlg, lpString, nCount, nIDListBox, TRUE, FALSE );
2007 }
2008 
2009 
2010 /*
2011  * @implemented Modified for ReactOS. Do not Port Sync!!!
2012  */
2013 BOOL
2014 WINAPI
2015 EndDialog(
2016   HWND hwnd,
2017   INT_PTR retval)
2018 {
2019     DIALOGINFO * dlgInfo;
2020     HWND owner;
2021     BOOL wasActive;
2022 
2023     TRACE("%p %ld\n", hwnd, retval );
2024 
2025     if (!(dlgInfo = GETDLGINFO(hwnd)))
2026     {
2027         ERR("got invalid window handle (%p); buggy app !?\n", hwnd);
2028         return FALSE;
2029     }
2030     wasActive = (hwnd == GetActiveWindow());
2031     dlgInfo->idResult = retval;
2032     dlgInfo->flags |= DF_END;
2033 
2034     if ((GetWindowLongW( hwnd, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) == WS_CHILD)
2035     {
2036        owner = GetAncestor( hwnd, GA_PARENT);
2037     }
2038     else
2039        owner = GetWindow( hwnd, GW_OWNER );
2040 
2041     if (owner)
2042         EnableWindow( owner, TRUE );
2043 
2044     /* Windows sets the focus to the dialog itself in EndDialog */
2045 
2046     if (wasActive && IsChild(hwnd, GetFocus()))
2047        SetFocus( hwnd );
2048 
2049     /* Don't have to send a ShowWindow(SW_HIDE), just do
2050        SetWindowPos with SWP_HIDEWINDOW as done in Windows */
2051 
2052     SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE
2053                  | SWP_NOZORDER | SWP_NOACTIVATE | SWP_HIDEWINDOW);
2054 
2055     if (wasActive && owner)
2056     {
2057         /* If this dialog was given an owner then set the focus to that owner. */
2058         SetActiveWindow(owner);
2059     }
2060     else if (hwnd == GetActiveWindow()) // Check it again!
2061     {
2062         NtUserCallNoParam(NOPARAM_ROUTINE_ZAPACTIVEANDFOUS);
2063     }
2064 
2065     /* unblock dialog loop */
2066     PostMessageA(hwnd, WM_NULL, 0, 0);
2067     return TRUE;
2068 }
2069 
2070 
2071 /*
2072  * @implemented
2073  */
2074 LONG
2075 WINAPI
2076 GetDialogBaseUnits(VOID)
2077 {
2078     static DWORD units;
2079 
2080     if (!units)
2081     {
2082         HDC hdc;
2083         SIZE size;
2084 
2085         if ((hdc = GetDC(0)))
2086         {
2087             size.cx = GdiGetCharDimensions( hdc, NULL, &size.cy );
2088             if (size.cx) units = MAKELONG( size.cx, size.cy );
2089             ReleaseDC( 0, hdc );
2090         }
2091     }
2092     return units;
2093 }
2094 
2095 
2096 /*
2097  * @implemented
2098  */
2099 int
2100 WINAPI
2101 GetDlgCtrlID(
2102   HWND hwndCtl)
2103 {
2104 	return GetWindowLongPtrW( hwndCtl, GWLP_ID );
2105 }
2106 
2107 
2108 /*
2109  * @implemented
2110  */
2111 HWND
2112 WINAPI
2113 GetDlgItem(
2114   HWND hDlg,
2115   int nIDDlgItem)
2116 {
2117     int i;
2118     HWND *list;
2119     HWND ret = 0;
2120 
2121     if (!hDlg) return 0;
2122 
2123     list = WIN_ListChildren(hDlg);
2124     if (!list) return 0;
2125 
2126     for (i = 0; list[i]; i++) if (GetWindowLongPtrW(list[i], GWLP_ID) == nIDDlgItem) break;
2127     ret = list[i];
2128     HeapFree(GetProcessHeap(), 0, list);
2129 //    if (!ret) SetLastError(ERROR_CONTROL_ID_NOT_FOUND);
2130     return ret;
2131 }
2132 
2133 
2134 /*
2135  * @implemented
2136  */
2137 UINT
2138 WINAPI
2139 GetDlgItemInt(
2140   HWND hDlg,
2141   int nIDDlgItem,
2142   BOOL *lpTranslated,
2143   BOOL bSigned)
2144 {
2145     char str[30];
2146     char * endptr;
2147     LONG_PTR result = 0;
2148 
2149     if (lpTranslated) *lpTranslated = FALSE;
2150     if (!SendDlgItemMessageA(hDlg, nIDDlgItem, WM_GETTEXT, sizeof(str), (LPARAM)str))
2151         return 0;
2152     if (bSigned)
2153     {
2154         result = strtol( str, &endptr, 10 );
2155         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
2156             return 0;
2157         if (((result == LONG_MIN) || (result == LONG_MAX)))
2158             return 0;
2159     }
2160     else
2161     {
2162         result = strtoul( str, &endptr, 10 );
2163         if (!endptr || (endptr == str))  /* Conversion was unsuccessful */
2164             return 0;
2165         if (result == ULONG_MAX) return 0;
2166     }
2167     if (lpTranslated) *lpTranslated = TRUE;
2168     return (UINT)result;
2169 }
2170 
2171 
2172 /*
2173  * @implemented
2174  */
2175 UINT
2176 WINAPI
2177 GetDlgItemTextA(
2178   HWND hDlg,
2179   int nIDDlgItem,
2180   LPSTR lpString,
2181   int nMaxCount)
2182 {
2183   HWND hWnd = GetDlgItem(hDlg, nIDDlgItem);
2184   if ( hWnd ) return GetWindowTextA(hWnd, lpString, nMaxCount);
2185   if ( nMaxCount ) lpString[0] = '\0';
2186   return 0;
2187 }
2188 
2189 
2190 /*
2191  * @implemented
2192  */
2193 UINT
2194 WINAPI
2195 GetDlgItemTextW(
2196   HWND hDlg,
2197   int nIDDlgItem,
2198   LPWSTR lpString,
2199   int nMaxCount)
2200 {
2201   HWND hWnd = GetDlgItem(hDlg, nIDDlgItem);
2202   if ( hWnd ) return GetWindowTextW(hWnd, lpString, nMaxCount);
2203   if ( nMaxCount ) lpString[0] = '\0';
2204   return 0;
2205 }
2206 
2207 /*
2208  * @implemented
2209  */
2210 HWND
2211 WINAPI
2212 GetNextDlgGroupItem(
2213   HWND hDlg,
2214   HWND hCtl,
2215   BOOL bPrevious)
2216 {
2217     HWND hwnd, hwndNext, retvalue, hwndLastGroup = 0;
2218     BOOL fLooped=FALSE;
2219     BOOL fSkipping=FALSE;
2220 
2221     if (hDlg == hCtl) hCtl = NULL;
2222     if (!hCtl && bPrevious) return 0;
2223 
2224         /* if the hwndCtrl is the child of the control in the hwndDlg,
2225          * then the hwndDlg has to be the parent of the hwndCtrl */
2226 
2227     if (hCtl)
2228     {
2229         if (!IsChild (hDlg, hCtl)) return 0;
2230         /* Make sure hwndCtrl is a top-level child */
2231 
2232     }
2233     else
2234     {
2235         /* No ctrl specified -> start from the beginning */
2236         if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
2237         /* MSDN is wrong. fPrevious does not result in the last child */
2238 
2239         /* No ctrl specified -> start from the beginning */
2240         if (!(hCtl = GetWindow( hDlg, GW_CHILD ))) return 0;
2241 
2242         /* MSDN is wrong. fPrevious does not result in the last child */
2243 
2244         /* Maybe that first one is valid.  If so then we don't want to skip it*/
2245         if ((GetWindowLongPtrW( hCtl, GWL_STYLE ) & (WS_VISIBLE|WS_DISABLED)) == WS_VISIBLE)
2246         {
2247             return hCtl;
2248         }
2249 
2250     }
2251 
2252     /* Always go forward around the group and list of controls; for the
2253      * previous control keep track; for the next break when you find one
2254      */
2255     retvalue = hCtl;
2256     hwnd = hCtl;
2257     while (hwndNext = GetWindow (hwnd, GW_HWNDNEXT),
2258            1)
2259     {
2260         while (!hwndNext)
2261         {
2262             /* Climb out until there is a next sibling of the ancestor or we
2263              * reach the top (in which case we loop back to the start)
2264              */
2265             if (hDlg == GetParent (hwnd))
2266             {
2267                 /* Wrap around to the beginning of the list, within the same
2268                  * group. (Once only)
2269                  */
2270                 if (fLooped) goto end;
2271                 fLooped = TRUE;
2272                 hwndNext = GetWindow (hDlg, GW_CHILD);
2273             }
2274             else
2275             {
2276                 hwnd = GetParent (hwnd);
2277                 hwndNext = GetWindow (hwnd, GW_HWNDNEXT);
2278             }
2279         }
2280         hwnd = hwndNext;
2281 
2282         /* Wander down the leading edge of controlparents */
2283         while ( (GetWindowLongPtrW (hwnd, GWL_EXSTYLE) & WS_EX_CONTROLPARENT) &&
2284                 ((GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE | WS_DISABLED)) == WS_VISIBLE) &&
2285                 (hwndNext = GetWindow (hwnd, GW_CHILD)))
2286             hwnd = hwndNext;
2287         /* Question.  If the control is a control parent but either has no
2288          * children or is not visible/enabled then if it has a WS_GROUP does
2289          * it count?  For that matter does it count anyway?
2290          * I believe it doesn't count.
2291          */
2292 
2293         if ((GetWindowLongPtrW (hwnd, GWL_STYLE) & WS_GROUP))
2294         {
2295             hwndLastGroup = hwnd;
2296             if (!fSkipping)
2297             {
2298                 /* Look for the beginning of the group */
2299                 fSkipping = TRUE;
2300             }
2301         }
2302 
2303         if (hwnd == hCtl)
2304         {
2305             if (!fSkipping) break;
2306             if (hwndLastGroup == hwnd) break;
2307             hwnd = hwndLastGroup;
2308             fSkipping = FALSE;
2309             fLooped = FALSE;
2310         }
2311 
2312         if (!fSkipping &&
2313             (GetWindowLongPtrW (hwnd, GWL_STYLE) & (WS_VISIBLE|WS_DISABLED)) ==
2314              WS_VISIBLE)
2315         {
2316             retvalue = hwnd;
2317             if (!bPrevious) break;
2318         }
2319     }
2320 end:
2321     return retvalue;
2322 }
2323 
2324 
2325 /*
2326  * @implemented
2327  */
2328 HWND
2329 WINAPI
2330 GetNextDlgTabItem(
2331   HWND hDlg,
2332   HWND hCtl,
2333   BOOL bPrevious)
2334 {
2335     PWND pWindow;
2336 
2337     pWindow = ValidateHwnd( hDlg );
2338     if (!pWindow) return NULL;
2339     if (hCtl)
2340     {
2341        pWindow = ValidateHwnd( hCtl );
2342        if (!pWindow) return NULL;
2343     }
2344 
2345     /* Undocumented but tested under Win2000 and WinME */
2346     if (hDlg == hCtl) hCtl = NULL;
2347 
2348     /* Contrary to MSDN documentation, tested under Win2000 and WinME
2349      * NB GetLastError returns whatever was set before the function was
2350      * called.
2351      */
2352     if (!hCtl && bPrevious) return 0;
2353 
2354     return DIALOG_GetNextTabItem(hDlg, hDlg, hCtl, bPrevious);
2355 }
2356 
2357 
2358 #if 0
2359 BOOL
2360 WINAPI
2361 IsDialogMessage(
2362   HWND hDlg,
2363   LPMSG lpMsg)
2364 {
2365 	return IsDialogMessageW(hDlg, lpMsg);
2366 }
2367 #endif
2368 
2369 /***********************************************************************
2370  *              DIALOG_FixOneChildOnChangeFocus
2371  *
2372  * Callback helper for DIALOG_FixChildrenOnChangeFocus
2373  */
2374 
2375 static BOOL CALLBACK DIALOG_FixOneChildOnChangeFocus (HWND hwndChild,
2376         LPARAM lParam)
2377 {
2378     /* If a default pushbutton then no longer default */
2379     if (DLGC_DEFPUSHBUTTON & SendMessageW (hwndChild, WM_GETDLGCODE, 0, 0))
2380         SendMessageW (hwndChild, BM_SETSTYLE, BS_PUSHBUTTON, TRUE);
2381     return TRUE;
2382 }
2383 
2384 /***********************************************************************
2385  *              DIALOG_FixChildrenOnChangeFocus
2386  *
2387  * Following the change of focus that occurs for example after handling
2388  * a WM_KEYDOWN VK_TAB in IsDialogMessage, some tidying of the dialog's
2389  * children may be required.
2390  */
2391 static void DIALOG_FixChildrenOnChangeFocus (HWND hwndDlg, HWND hwndNext)
2392 {
2393     INT dlgcode_next = SendMessageW (hwndNext, WM_GETDLGCODE, 0, 0);
2394     /* INT dlgcode_dlg  = SendMessageW (hwndDlg, WM_GETDLGCODE, 0, 0); */
2395     /* Windows does ask for this.  I don't know why yet */
2396 
2397     EnumChildWindows (hwndDlg, DIALOG_FixOneChildOnChangeFocus, 0);
2398 
2399     /* If the button that is getting the focus WAS flagged as the default
2400      * pushbutton then ask the dialog what it thinks the default is and
2401      * set that in the default style.
2402      */
2403     if (dlgcode_next & DLGC_DEFPUSHBUTTON)
2404     {
2405         DWORD def_id = SendMessageW (hwndDlg, DM_GETDEFID, 0, 0);
2406         if (HIWORD(def_id) == DC_HASDEFID)
2407         {
2408             HWND hwndDef;
2409             def_id = LOWORD(def_id);
2410             hwndDef = GetDlgItem (hwndDlg, def_id);
2411             if (hwndDef)
2412             {
2413                 INT dlgcode_def = SendMessageW (hwndDef, WM_GETDLGCODE, 0, 0);
2414                 /* I know that if it is a button then it should already be a
2415                  * UNDEFPUSHBUTTON, since we have just told the buttons to
2416                  * change style.  But maybe they ignored our request
2417                  */
2418                 if ((dlgcode_def & DLGC_BUTTON) &&
2419                         (dlgcode_def &  DLGC_UNDEFPUSHBUTTON))
2420                 {
2421                     SendMessageW (hwndDef, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
2422                 }
2423             }
2424         }
2425     }
2426     else if ((dlgcode_next & DLGC_BUTTON) && (dlgcode_next & DLGC_UNDEFPUSHBUTTON))
2427     {
2428         SendMessageW (hwndNext, BM_SETSTYLE, BS_DEFPUSHBUTTON, TRUE);
2429         /* I wonder why it doesn't send a DM_SETDEFID */
2430     }
2431 }
2432 
2433 /***********************************************************************
2434  *           DIALOG_IdToHwnd
2435  *
2436  * A recursive version of GetDlgItem
2437  *
2438  * RETURNS
2439  *  The HWND for a Child ID.
2440  */
2441 static HWND DIALOG_IdToHwnd( HWND hwndDlg, INT id )
2442 {
2443     int i;
2444     HWND *list = WIN_ListChildren( hwndDlg );
2445     HWND ret = 0;
2446 
2447     if (!list) return 0;
2448 
2449     for (i = 0; list[i]; i++)
2450     {
2451         if (GetWindowLongPtrW( list[i], GWLP_ID ) == id)
2452         {
2453             ret = list[i];
2454             break;
2455         }
2456 
2457         /* Recurse into every child */
2458         if ((ret = DIALOG_IdToHwnd( list[i], id ))) break;
2459     }
2460 
2461     HeapFree( GetProcessHeap(), 0, list );
2462     return ret;
2463 }
2464 
2465 
2466 /*
2467  * @implemented
2468  */
2469 BOOL
2470 WINAPI
2471 IsDialogMessageW(
2472   HWND hDlg,
2473   LPMSG lpMsg)
2474 {
2475     INT dlgCode = 0;
2476 
2477     if (!IsWindow( hDlg ))
2478         return FALSE;
2479 
2480     if (CallMsgFilterW( lpMsg, MSGF_DIALOGBOX )) return TRUE;
2481 
2482     if (hDlg == GetDesktopWindow()) return FALSE;
2483     if ((hDlg != lpMsg->hwnd) && !IsChild( hDlg, lpMsg->hwnd )) return FALSE;
2484 
2485      hDlg = DIALOG_FindMsgDestination(hDlg);
2486 
2487      switch(lpMsg->message)
2488      {
2489      case WM_KEYDOWN:
2490         dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2491          if (dlgCode & DLGC_WANTMESSAGE) break;
2492 
2493          switch(lpMsg->wParam)
2494          {
2495          case VK_TAB:
2496             if (!(dlgCode & DLGC_WANTTAB))
2497             {
2498                 BOOL fIsDialog = TRUE;
2499                 WND *pWnd = ValidateHwnd(hDlg);
2500 
2501                 if (pWnd && TestWindowProcess(pWnd))
2502                 {
2503                     fIsDialog = (GETDLGINFO(hDlg) != NULL);
2504                 }
2505 
2506                 SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEFOCUS), 0);
2507 
2508                 /* I am not sure under which circumstances the TAB is handled
2509                  * each way.  All I do know is that it does not always simply
2510                  * send WM_NEXTDLGCTL.  (Personally I have never yet seen it
2511                  * do so but I presume someone has)
2512                  */
2513                 if (fIsDialog)
2514                     SendMessageW( hDlg, WM_NEXTDLGCTL, (GetKeyState(VK_SHIFT) & 0x8000), 0 );
2515                 else
2516                 {
2517                     /* It would appear that GetNextDlgTabItem can handle being
2518                      * passed hwndDlg rather than NULL but that is undocumented
2519                      * so let's do it properly
2520                      */
2521                     HWND hwndFocus = GetFocus();
2522                     HWND hwndNext = GetNextDlgTabItem (hDlg,
2523                             hwndFocus == hDlg ? NULL : hwndFocus,
2524                             GetKeyState (VK_SHIFT) & 0x8000);
2525                     if (hwndNext)
2526                     {
2527                         dlgCode = SendMessageW (hwndNext, WM_GETDLGCODE,
2528                                 lpMsg->wParam, (LPARAM)lpMsg);
2529                         if (dlgCode & DLGC_HASSETSEL)
2530                         {
2531                             INT maxlen = 1 + SendMessageW (hwndNext, WM_GETTEXTLENGTH, 0, 0);
2532                             WCHAR *buffer = HeapAlloc (GetProcessHeap(), 0, maxlen * sizeof(WCHAR));
2533                             if (buffer)
2534                             {
2535                                 INT length;
2536                                 SendMessageW (hwndNext, WM_GETTEXT, maxlen, (LPARAM) buffer);
2537                                 length = strlenW (buffer);
2538                                 HeapFree (GetProcessHeap(), 0, buffer);
2539                                 SendMessageW (hwndNext, EM_SETSEL, 0, length);
2540                             }
2541                         }
2542                         SetFocus (hwndNext);
2543                         DIALOG_FixChildrenOnChangeFocus (hDlg, hwndNext);
2544                     }
2545                     else
2546                         return FALSE;
2547                 }
2548                 return TRUE;
2549             }
2550             break;
2551 
2552          case VK_RIGHT:
2553          case VK_DOWN:
2554          case VK_LEFT:
2555          case VK_UP:
2556              if (!(dlgCode & DLGC_WANTARROWS))
2557              {
2558                  BOOL fPrevious = (lpMsg->wParam == VK_LEFT || lpMsg->wParam == VK_UP);
2559                  HWND hwndNext = GetNextDlgGroupItem (hDlg, GetFocus(), fPrevious );
2560                  SendMessageW( hDlg, WM_NEXTDLGCTL, (WPARAM)hwndNext, 1 );
2561                  return TRUE;
2562              }
2563              break;
2564 
2565          case VK_CANCEL:
2566          case VK_ESCAPE:
2567              SendMessageW( hDlg, WM_COMMAND, IDCANCEL, (LPARAM)GetDlgItem( hDlg, IDCANCEL ) );
2568              return TRUE;
2569 
2570          case VK_EXECUTE:
2571          case VK_RETURN:
2572               {
2573                  DWORD dw;
2574                  if ((GetFocus() == lpMsg->hwnd) &&
2575                      (SendMessageW (lpMsg->hwnd, WM_GETDLGCODE, 0, 0) & DLGC_DEFPUSHBUTTON))
2576                  {
2577                      SendMessageW (hDlg, WM_COMMAND, MAKEWPARAM (GetDlgCtrlID(lpMsg->hwnd),BN_CLICKED), (LPARAM)lpMsg->hwnd);
2578                  }
2579                  else if (DC_HASDEFID == HIWORD(dw = SendMessageW (hDlg, DM_GETDEFID, 0, 0)))
2580                  {
2581                     HWND hwndDef = DIALOG_IdToHwnd(hDlg, LOWORD(dw));
2582                     if (!hwndDef || IsWindowEnabled(hwndDef))
2583                         SendMessageW( hDlg, WM_COMMAND, MAKEWPARAM( LOWORD(dw), BN_CLICKED ), (LPARAM)hwndDef);
2584                  }
2585                  else
2586                  {
2587                      SendMessageW( hDlg, WM_COMMAND, IDOK, (LPARAM)GetDlgItem( hDlg, IDOK ) );
2588 
2589                  }
2590              }
2591              return TRUE;
2592          }
2593          break;
2594 
2595      case WM_CHAR:
2596          /* FIXME Under what circumstances does WM_GETDLGCODE get sent?
2597           * It does NOT get sent in the test program I have
2598           */
2599          dlgCode = SendMessageW( lpMsg->hwnd, WM_GETDLGCODE, lpMsg->wParam, (LPARAM)lpMsg );
2600          if (dlgCode & (DLGC_WANTCHARS|DLGC_WANTMESSAGE)) break;
2601          if (lpMsg->wParam == '\t' && (dlgCode & DLGC_WANTTAB)) break;
2602          /* drop through */
2603 
2604      case WM_SYSCHAR:
2605          if (DIALOG_IsAccelerator( lpMsg->hwnd, hDlg, lpMsg->wParam ))
2606          {
2607              /* don't translate or dispatch */
2608              return TRUE;
2609          }
2610          break;
2611 //// ReactOS
2612      case WM_SYSKEYDOWN:
2613          /* If the ALT key is being pressed display the keyboard cues */
2614          if ( HIWORD(lpMsg->lParam) & KF_ALTDOWN &&
2615              !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) )
2616              SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0);
2617          break;
2618 
2619      case WM_SYSCOMMAND:
2620          /* If the ALT key is being pressed display the keyboard cues */
2621          if ( lpMsg->wParam == SC_KEYMENU &&
2622              !(gpsi->dwSRVIFlags & SRVINFO_KBDPREF) && !(gpsi->PUSIFlags & PUSIF_KEYBOARDCUES) )
2623          {
2624             SendMessageW(hDlg, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL | UISF_HIDEFOCUS), 0);
2625          }
2626          break;
2627      }
2628 
2629      TranslateMessage( lpMsg );
2630      DispatchMessageW( lpMsg );
2631      return TRUE;
2632 }
2633 
2634 
2635 /*
2636  * @implemented
2637  */
2638 UINT
2639 WINAPI
2640 IsDlgButtonChecked(
2641   HWND hDlg,
2642   int nIDButton)
2643 {
2644   return (UINT)SendDlgItemMessageW( hDlg, nIDButton, BM_GETCHECK, 0, 0 );
2645 }
2646 
2647 
2648 /*
2649  * @implemented
2650  */
2651 BOOL
2652 WINAPI
2653 MapDialogRect(
2654   HWND hDlg,
2655   LPRECT lpRect)
2656 {
2657 	DIALOGINFO * dlgInfo;
2658 	if (!(dlgInfo = GETDLGINFO(hDlg))) return FALSE;
2659 	lpRect->left   = MulDiv(lpRect->left, dlgInfo->xBaseUnit, 4);
2660 	lpRect->right  = MulDiv(lpRect->right, dlgInfo->xBaseUnit, 4);
2661 	lpRect->top    = MulDiv(lpRect->top, dlgInfo->yBaseUnit, 8);
2662 	lpRect->bottom = MulDiv(lpRect->bottom, dlgInfo->yBaseUnit, 8);
2663 	return TRUE;
2664 }
2665 
2666 
2667 /*
2668  * @implemented
2669  */
2670 LRESULT
2671 WINAPI
2672 SendDlgItemMessageA(
2673   HWND hDlg,
2674   int nIDDlgItem,
2675   UINT Msg,
2676   WPARAM wParam,
2677   LPARAM lParam)
2678 {
2679 	HWND hwndCtrl;
2680 	if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS
2681 	hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2682 	if (hwndCtrl) return SendMessageA( hwndCtrl, Msg, wParam, lParam );
2683 	else return 0;
2684 }
2685 
2686 
2687 /*
2688  * @implemented
2689  */
2690 LRESULT
2691 WINAPI
2692 SendDlgItemMessageW(
2693   HWND hDlg,
2694   int nIDDlgItem,
2695   UINT Msg,
2696   WPARAM wParam,
2697   LPARAM lParam)
2698 {
2699 	HWND hwndCtrl;
2700 	if ( hDlg == HWND_TOPMOST || hDlg == HWND_BROADCAST ) return 0; // ReactOS
2701 	hwndCtrl = GetDlgItem( hDlg, nIDDlgItem );
2702 	if (hwndCtrl) return SendMessageW( hwndCtrl, Msg, wParam, lParam );
2703 	else return 0;
2704 }
2705 
2706 
2707 /*
2708  * @implemented
2709  */
2710 BOOL
2711 WINAPI
2712 SetDlgItemInt(
2713   HWND hDlg,
2714   int nIDDlgItem,
2715   UINT uValue,
2716   BOOL bSigned)
2717 {
2718 	char str[20];
2719 
2720 	if (bSigned) sprintf( str, "%d", (INT)uValue );
2721 	else sprintf( str, "%u", uValue );
2722 	SendDlgItemMessageA( hDlg, nIDDlgItem, WM_SETTEXT, 0, (LPARAM)str );
2723 	return TRUE;
2724 }
2725 
2726 
2727 /*
2728  * @implemented
2729  */
2730 BOOL
2731 WINAPI
2732 SetDlgItemTextA(
2733   HWND hDlg,
2734   int nIDDlgItem,
2735   LPCSTR lpString)
2736 {
2737   HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes
2738   if (hwndCtrl) return SetWindowTextA( hwndCtrl, lpString );
2739   return FALSE;
2740 }
2741 
2742 
2743 /*
2744  * @implemented
2745  */
2746 BOOL
2747 WINAPI
2748 SetDlgItemTextW(
2749   HWND hDlg,
2750   int nIDDlgItem,
2751   LPCWSTR lpString)
2752 {
2753   HWND hwndCtrl = GetDlgItem( hDlg, nIDDlgItem ); // ReactOS Themes
2754   if (hwndCtrl) return SetWindowTextW( hwndCtrl, lpString );
2755   return FALSE;
2756 }
2757 
2758 
2759 /*
2760  * @implemented
2761  */
2762 BOOL
2763 WINAPI
2764 CheckDlgButton(
2765   HWND hDlg,
2766   int nIDButton,
2767   UINT uCheck)
2768 {
2769 	SendDlgItemMessageW( hDlg, nIDButton, BM_SETCHECK, uCheck, 0 );
2770 	return TRUE;
2771 }
2772 
2773 static BOOL CALLBACK CheckRB(HWND hwnd, LPARAM lParam)
2774 {
2775   LONG lChildID = GetWindowLongPtrW(hwnd, GWLP_ID);
2776   RADIOGROUP *lpRadioGroup = (RADIOGROUP *)lParam;
2777 
2778   if((lChildID >= lpRadioGroup->firstID) &&
2779      (lChildID <= lpRadioGroup->lastID))
2780   {
2781     if (lChildID == lpRadioGroup->checkID)
2782     {
2783       SendMessageW(hwnd, BM_SETCHECK, BST_CHECKED, 0);
2784     }
2785     else
2786     {
2787       SendMessageW(hwnd, BM_SETCHECK, BST_UNCHECKED, 0);
2788     }
2789   }
2790 
2791    return TRUE;
2792 }
2793 
2794 /*
2795  * @implemented
2796  */
2797 BOOL
2798 WINAPI
2799 CheckRadioButton(
2800   HWND hDlg,
2801   int nIDFirstButton,
2802   int nIDLastButton,
2803   int nIDCheckButton)
2804 {
2805   RADIOGROUP radioGroup;
2806 
2807   radioGroup.firstID = nIDFirstButton;
2808   radioGroup.lastID = nIDLastButton;
2809   radioGroup.checkID = nIDCheckButton;
2810 
2811   return EnumChildWindows(hDlg, CheckRB, (LPARAM)&radioGroup);
2812 }
2813