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