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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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