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