xref: /reactos/dll/win32/shlwapi/msgbox.c (revision d3fd5bdd)
1 /*
2  * SHLWAPI message box functions
3  *
4  * Copyright 2004 Jon Griffiths
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "config.h"
22 #include "wine/port.h"
23 
24 #include <stdarg.h>
25 #include <string.h>
26 
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "shlwapi.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
34 #include "resource.h"
35 
36 
37 WINE_DEFAULT_DEBUG_CHANNEL(shell);
38 
39 extern HINSTANCE shlwapi_hInstance; /* in shlwapi_main.c */
40 
41 static const WCHAR szDontShowKey[] = { 'S','o','f','t','w','a','r','e','\\',
42   'M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\',
43   'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
44   'E','x','p','l','o','r','e','r','\\','D','o','n','t','S','h','o','w',
45   'M','e','T','h','i','s','D','i','a','l','o','g','A','g','a','i','n','\0'
46 };
47 
48 INT_PTR WINAPI SHMessageBoxCheckExW(HWND,HINSTANCE,LPCWSTR,DLGPROC,LPARAM,INT_PTR,LPCWSTR);
49 INT_PTR WINAPI SHMessageBoxCheckW(HWND,LPCWSTR,LPCWSTR,DWORD,INT_PTR,LPCWSTR);
50 
51 /* Data held by each general message boxes */
52 typedef struct tagDLGDATAEX
53 {
54   DLGPROC dlgProc;   /* User supplied DlgProc */
55   LPARAM  lParam;    /* User supplied LPARAM for dlgProc */
56   LPCWSTR lpszId;    /* Name of reg key holding whether to skip */
57 } DLGDATAEX;
58 
59 /* Dialogue procedure for general message boxes */
SHDlgProcEx(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)60 static INT_PTR CALLBACK SHDlgProcEx(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
61 {
62   DLGDATAEX *d = (DLGDATAEX *)GetWindowLongPtrW(hDlg, DWLP_USER);
63 
64   TRACE("(%p,%u,%ld,%ld) data %p\n", hDlg, uMsg, wParam, lParam, d);
65 
66   switch (uMsg)
67   {
68   case WM_INITDIALOG:
69   {
70     /* FIXME: Not sure where native stores its lParam */
71     SetWindowLongPtrW(hDlg, DWLP_USER, lParam);
72     d = (DLGDATAEX *)lParam;
73     TRACE("WM_INITDIALOG: %p, %s,%p,%p\n", hDlg, debugstr_w(d->lpszId),
74           d->dlgProc, (void*)d->lParam);
75     if (d->dlgProc)
76       return d->dlgProc(hDlg, uMsg, wParam, d->lParam);
77     return TRUE;
78   }
79 
80   case WM_COMMAND:
81     switch (LOWORD(wParam))
82     {
83       case IDYES:
84         wParam = MAKELONG(IDOK, HIWORD(wParam));
85         /* Fall through ... */
86       case IDNO:
87         if (LOWORD(wParam) == IDNO)
88           wParam = MAKELONG(IDCANCEL, HIWORD(wParam));
89         /* Fall through ... */
90       case IDOK:
91       case IDCANCEL:
92 
93         TRACE("WM_COMMAND: id=%s data=%p\n",
94               LOWORD(wParam) == IDOK ? "IDOK" : "IDCANCEL", d);
95 
96         if (SendMessageW(GetDlgItem(hDlg, IDC_ERR_DONT_SHOW), BM_GETCHECK, 0L, 0L))
97         {
98           DWORD dwZero = 0;
99 
100           /* The user clicked 'don't show again', so set the key */
101           SHRegSetUSValueW(szDontShowKey, d->lpszId, REG_DWORD, &dwZero,
102                            sizeof(dwZero), SHREGSET_DEFAULT);
103         }
104         if (!d->dlgProc || !d->dlgProc(hDlg, uMsg, wParam, lParam))
105           EndDialog(hDlg, wParam);
106         return TRUE;
107     }
108     break;
109 
110   default:
111     break;
112   }
113 
114   if (d && d->dlgProc)
115     return d->dlgProc(hDlg, uMsg, wParam, lParam);
116   return FALSE;
117 }
118 
119 /*************************************************************************
120  * @ [SHLWAPI.291]
121  *
122  * Pop up a 'Don't show this message again' dialogue box.
123  *
124  * PARAMS
125  *  hWnd     [I] Window to be the dialogues' parent
126  *  hInst    [I] Instance of the module holding the dialogue resource
127  *  lpszName [I] Resource Id of the dialogue resource
128  *  dlgProc  [I] Dialog procedure, or NULL for default handling
129  *  lParam   [I] LPARAM to pass to dlgProc
130  *  iRet     [I] Value to return if dialogue is not shown
131  *  lpszId   [I] Name of registry subkey which determines whether to show the dialog
132  *
133  * RETURNS
134  *  Success: The value returned from the dialogue procedure.
135  *  Failure: iRet, if the dialogue resource could not be loaded or the dialogue
136  *           should not be shown.
137  *
138  * NOTES
139  *  Both lpszName and lpszId must be less than MAX_PATH in length.
140  */
SHMessageBoxCheckExA(HWND hWnd,HINSTANCE hInst,LPCSTR lpszName,DLGPROC dlgProc,LPARAM lParam,INT_PTR iRet,LPCSTR lpszId)141 INT_PTR WINAPI SHMessageBoxCheckExA(HWND hWnd, HINSTANCE hInst, LPCSTR lpszName,
142                                     DLGPROC dlgProc, LPARAM lParam, INT_PTR iRet,
143                                     LPCSTR lpszId)
144 {
145   WCHAR szNameBuff[MAX_PATH], szIdBuff[MAX_PATH];
146   LPCWSTR szName = szNameBuff;
147 
148   if (IS_INTRESOURCE(lpszName))
149     szName = (LPCWSTR)lpszName; /* Resource Id or NULL */
150   else
151     MultiByteToWideChar(CP_ACP, 0, lpszName, -1, szNameBuff, MAX_PATH);
152 
153   MultiByteToWideChar(CP_ACP, 0, lpszId, -1, szIdBuff, MAX_PATH);
154 
155   return SHMessageBoxCheckExW(hWnd, hInst, szName, dlgProc, lParam, iRet, szIdBuff);
156 }
157 
158 /*************************************************************************
159  * @ [SHLWAPI.292]
160  *
161  * Unicode version of SHMessageBoxCheckExW.
162  */
SHMessageBoxCheckExW(HWND hWnd,HINSTANCE hInst,LPCWSTR lpszName,DLGPROC dlgProc,LPARAM lParam,INT_PTR iRet,LPCWSTR lpszId)163 INT_PTR WINAPI SHMessageBoxCheckExW(HWND hWnd, HINSTANCE hInst, LPCWSTR lpszName,
164                                     DLGPROC dlgProc, LPARAM lParam, INT_PTR iRet, LPCWSTR lpszId)
165 {
166   DLGDATAEX d;
167 
168   if (!SHRegGetBoolUSValueW(szDontShowKey, lpszId, FALSE, TRUE))
169     return iRet;
170 
171   d.dlgProc = dlgProc;
172   d.lParam = lParam;
173   d.lpszId = lpszId;
174   return DialogBoxParamW(hInst, lpszName, hWnd, SHDlgProcEx, (LPARAM)&d);
175 }
176 
177 /* Data held by each shlwapi message box */
178 typedef struct tagDLGDATA
179 {
180   LPCWSTR lpszTitle; /* User supplied message title */
181   LPCWSTR lpszText;  /* User supplied message text */
182   DWORD   dwType;    /* Message box type */
183 } DLGDATA;
184 
185 /* Dialogue procedure for shlwapi message boxes */
SHDlgProc(HWND hDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)186 static INT_PTR CALLBACK SHDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
187 {
188   TRACE("(%p,%u,%ld,%ld)\n", hDlg, uMsg, wParam, lParam);
189 
190   switch (uMsg)
191   {
192   case WM_INITDIALOG:
193   {
194     DLGDATA *d = (DLGDATA *)lParam;
195     TRACE("WM_INITDIALOG: %p, %s,%s,%d\n", hDlg, debugstr_w(d->lpszTitle),
196           debugstr_w(d->lpszText), d->dwType);
197 
198     SetWindowTextW(hDlg, d->lpszTitle);
199     SetWindowTextW(GetDlgItem(hDlg, IDS_ERR_USER_MSG), d->lpszText);
200 
201     /* Set buttons according to dwType */
202     switch (d->dwType)
203     {
204     case 0:
205       ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_HIDE);
206       /* FIXME: Move OK button to position of the Cancel button (cosmetic) */
207     case 1:
208       ShowWindow(GetDlgItem(hDlg, IDYES), SW_HIDE);
209       ShowWindow(GetDlgItem(hDlg, IDNO), SW_HIDE);
210       break;
211     default:
212       ShowWindow(GetDlgItem(hDlg, IDOK), SW_HIDE);
213       ShowWindow(GetDlgItem(hDlg, IDCANCEL), SW_HIDE);
214       break;
215     }
216     return TRUE;
217   }
218   default:
219     break;
220   }
221   return FALSE;
222 }
223 
224 /*************************************************************************
225  * @ [SHLWAPI.185]
226  *
227  * Pop up a 'Don't show this message again' dialogue box.
228  *
229  * PARAMS
230  *  hWnd      [I] Window to be the dialogues' parent
231  *  lpszText  [I] Text of the message to show
232  *  lpszTitle [I] Title of the dialogue box
233  *  dwType    [I] Type of dialogue buttons (See below)
234  *  iRet      [I] Value to return if dialogue is not shown
235  *  lpszId    [I] Name of registry subkey which determines whether to show the dialog
236  *
237  * RETURNS
238  *  Success: The value returned from the dialogue procedure (e.g. IDOK).
239  *  Failure: iRet, if the default dialogue resource could not be loaded or the
240  *           dialogue should not be shown.
241  *
242  * NOTES
243  *  - Both lpszTitle and lpszId must be less than MAX_PATH in length.
244  *  - Possible values for dwType are:
245  *| Value     Buttons
246  *| -----     -------
247  *|   0       OK
248  *|   1       OK/Cancel
249  *|   2       Yes/No
250  */
SHMessageBoxCheckA(HWND hWnd,LPCSTR lpszText,LPCSTR lpszTitle,DWORD dwType,INT_PTR iRet,LPCSTR lpszId)251 INT_PTR WINAPI SHMessageBoxCheckA(HWND hWnd, LPCSTR lpszText, LPCSTR lpszTitle,
252                                   DWORD dwType, INT_PTR iRet, LPCSTR lpszId)
253 {
254   WCHAR szTitleBuff[MAX_PATH], szIdBuff[MAX_PATH];
255   WCHAR *szTextBuff = NULL;
256   int iLen;
257   INT_PTR iRetVal;
258 
259   if (lpszTitle)
260     MultiByteToWideChar(CP_ACP, 0, lpszTitle, -1, szTitleBuff, MAX_PATH);
261 
262   if (lpszText)
263   {
264     iLen = MultiByteToWideChar(CP_ACP, 0, lpszText, -1, NULL, 0);
265     szTextBuff = HeapAlloc(GetProcessHeap(), 0, iLen * sizeof(WCHAR));
266     MultiByteToWideChar(CP_ACP, 0, lpszText, -1, szTextBuff, iLen);
267   }
268 
269   MultiByteToWideChar(CP_ACP, 0, lpszId, -1, szIdBuff, MAX_PATH);
270 
271   iRetVal = SHMessageBoxCheckW(hWnd, szTextBuff, lpszTitle ? szTitleBuff : NULL,
272                                dwType, iRet, szIdBuff);
273   HeapFree(GetProcessHeap(), 0, szTextBuff);
274   return iRetVal;
275 }
276 
277 /*************************************************************************
278  * @ [SHLWAPI.191]
279  *
280  * Unicode version of SHMessageBoxCheckA.
281  */
SHMessageBoxCheckW(HWND hWnd,LPCWSTR lpszText,LPCWSTR lpszTitle,DWORD dwType,INT_PTR iRet,LPCWSTR lpszId)282 INT_PTR WINAPI SHMessageBoxCheckW(HWND hWnd, LPCWSTR lpszText, LPCWSTR lpszTitle,
283                                   DWORD dwType, INT_PTR iRet, LPCWSTR lpszId)
284 {
285   DLGDATA d;
286 
287   d.lpszTitle = lpszTitle;
288   d.lpszText = lpszText;
289   d.dwType = dwType;
290 
291   return SHMessageBoxCheckExW(hWnd, shlwapi_hInstance, (LPCWSTR)IDD_ERR_DIALOG,
292                                SHDlgProc, (LPARAM)&d, iRet, lpszId);
293 }
294