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