Call GetProcessHeap() instead of passing its address.
[wine] / dlls / shell32 / dialogs.c
1 /*
2  *      common shell dialogs
3  *
4  * Copyright 2000 Juergen Schmied
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 #include "config.h"
22 #include "wine/port.h"
23
24 #include <string.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27 #include "winerror.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "commdlg.h"
34 #include "wine/debug.h"
35
36 #include "shellapi.h"
37 #include "shlobj.h"
38 #include "shell32_main.h"
39 #include "shresdef.h"
40 #include "undocshell.h"
41
42 typedef struct
43     {
44         HWND hwndOwner ;
45         HICON hIcon ;
46         LPCSTR lpstrDirectory ;
47         LPCSTR lpstrTitle ;
48         LPCSTR lpstrDescription ;
49         UINT uFlags ;
50     } RUNFILEDLGPARAMS ;
51
52 typedef BOOL (*LPFNOFN) (OPENFILENAMEA *) ;
53
54 WINE_DEFAULT_DEBUG_CHANNEL(shell);
55 INT_PTR CALLBACK RunDlgProc (HWND, UINT, WPARAM, LPARAM) ;
56 void FillList (HWND, char *) ;
57
58
59 /*************************************************************************
60  * PickIconDlg                                  [SHELL32.62]
61  *
62  */
63 BOOL WINAPI PickIconDlg(
64         HWND hwndOwner,
65         LPSTR lpstrFile,
66         DWORD nMaxFile,
67         LPDWORD lpdwIconIndex)
68 {
69         FIXME("(%p,%s,%08lx,%p):stub.\n",
70           hwndOwner, lpstrFile, nMaxFile,lpdwIconIndex);
71         return 0xffffffff;
72 }
73
74 /*************************************************************************
75  * RunFileDlg                                   [SHELL32.61]
76  *
77  * NOTES
78  *     Original name: RunFileDlg (exported by ordinal)
79  */
80 void WINAPI RunFileDlg(
81         HWND hwndOwner,
82         HICON hIcon,
83         LPCSTR lpstrDirectory,
84         LPCSTR lpstrTitle,
85         LPCSTR lpstrDescription,
86         UINT uFlags)
87 {
88
89     RUNFILEDLGPARAMS rfdp;
90     HRSRC hRes;
91     LPVOID template;
92     TRACE("\n");
93
94     rfdp.hwndOwner        = hwndOwner;
95     rfdp.hIcon            = hIcon;
96     rfdp.lpstrDirectory   = lpstrDirectory;
97     rfdp.lpstrTitle       = lpstrTitle;
98     rfdp.lpstrDescription = lpstrDescription;
99     rfdp.uFlags           = uFlags;
100
101     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_RUN_DLG", (LPSTR)RT_DIALOG)))
102         {
103         MessageBoxA (hwndOwner, "Couldn't find dialog.", "Nix", MB_OK) ;
104         return;
105         }
106     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
107         {
108         MessageBoxA (hwndOwner, "Couldn't load dialog.", "Nix", MB_OK) ;
109         return;
110         }
111
112     DialogBoxIndirectParamA((HINSTANCE)GetWindowLongPtrW( hwndOwner,
113                                                        GWLP_HINSTANCE ),
114                             template, hwndOwner, RunDlgProc, (LPARAM)&rfdp);
115
116 }
117
118 /* Dialog procedure for RunFileDlg */
119 INT_PTR CALLBACK RunDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
120     {
121     int ic ;
122     char *psz, szMsg[256] ;
123     static RUNFILEDLGPARAMS *prfdp = NULL ;
124
125     switch (message)
126         {
127         case WM_INITDIALOG :
128             prfdp = (RUNFILEDLGPARAMS *)lParam ;
129             SetWindowTextA (hwnd, prfdp->lpstrTitle) ;
130             SetClassLongA (hwnd, GCL_HICON, (LPARAM)prfdp->hIcon) ;
131             SendMessageA (GetDlgItem (hwnd, 12297), STM_SETICON,
132                           (WPARAM)LoadIconA (NULL, (LPSTR)IDI_WINLOGO), 0);
133             FillList (GetDlgItem (hwnd, 12298), NULL) ;
134             SetFocus (GetDlgItem (hwnd, 12298)) ;
135             return TRUE ;
136
137         case WM_COMMAND :
138             switch (LOWORD (wParam))
139                 {
140                 case IDOK :
141                     {
142                     HWND htxt = NULL ;
143                     if ((ic = GetWindowTextLengthA (htxt = GetDlgItem (hwnd, 12298))))
144                         {
145                         psz = HeapAlloc( GetProcessHeap(), 0, (ic + 2) );
146                         GetWindowTextA (htxt, psz, ic + 1) ;
147
148                         if (ShellExecuteA(NULL, "open", psz, NULL, NULL, SW_SHOWNORMAL) < (HINSTANCE)33)
149                             {
150                             char *pszSysMsg = NULL ;
151                             FormatMessageA (
152                                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
153                                 FORMAT_MESSAGE_FROM_SYSTEM |
154                                 FORMAT_MESSAGE_IGNORE_INSERTS,
155                                 NULL, GetLastError (),
156                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
157                                 (LPSTR)&pszSysMsg, 0, NULL
158                                 ) ;
159                             sprintf (szMsg, "Error: %s", pszSysMsg) ;
160                             LocalFree ((HLOCAL)pszSysMsg) ;
161                             MessageBoxA (hwnd, szMsg, "Nix", MB_OK | MB_ICONEXCLAMATION) ;
162
163                             HeapFree(GetProcessHeap(), 0, psz);
164                             SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
165                             return TRUE ;
166                             }
167                         FillList (htxt, psz) ;
168                         HeapFree(GetProcessHeap(), 0, psz);
169                         EndDialog (hwnd, 0) ;
170                         }
171                     }
172
173                 case IDCANCEL :
174                     EndDialog (hwnd, 0) ;
175                     return TRUE ;
176
177                 case 12288 :
178                     {
179                     HMODULE hComdlg = NULL ;
180                     LPFNOFN ofnProc = NULL ;
181                     static char szFName[1024] = "", szFileTitle[256] = "", szInitDir[768] = "" ;
182                     static OPENFILENAMEA ofn =
183                         {
184                         sizeof (OPENFILENAMEA),
185                         NULL,
186                         NULL,
187                         "Executable Files\0*.exe\0All Files\0*.*\0\0\0\0",
188                         NULL,
189                         0,
190                         0,
191                         szFName,
192                         1023,
193                         szFileTitle,
194                         255,
195                         (LPCSTR)szInitDir,
196                         "Browse",
197                         OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST,
198                         0,
199                         0,
200                         NULL,
201                         0,
202                         (LPOFNHOOKPROC)NULL,
203                         NULL
204                         } ;
205
206                     ofn.hwndOwner = hwnd ;
207
208                     if (NULL == (hComdlg = LoadLibraryExA ("comdlg32", NULL, 0)))
209                         {
210                         MessageBoxA (hwnd, "Unable to display dialog box (LoadLibraryEx) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
211                         return TRUE ;
212                         }
213
214                     if ((LPFNOFN)NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameA")))
215                         {
216                         MessageBoxA (hwnd, "Unable to display dialog box (GetProcAddress) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
217                         return TRUE ;
218                         }
219
220                     ofnProc (&ofn) ;
221
222                     SetFocus (GetDlgItem (hwnd, IDOK)) ;
223                     SetWindowTextA (GetDlgItem (hwnd, 12298), szFName) ;
224                     SendMessageA (GetDlgItem (hwnd, 12298), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
225                     SetFocus (GetDlgItem (hwnd, IDOK)) ;
226
227                     FreeLibrary (hComdlg) ;
228
229                     return TRUE ;
230                     }
231                 }
232             return TRUE ;
233         }
234     return FALSE ;
235     }
236
237 /* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */
238 void FillList (HWND hCb, char *pszLatest)
239     {
240     HKEY hkey ;
241 /*    char szDbgMsg[256] = "" ; */
242     char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ;
243     DWORD icList = 0, icCmd = 0 ;
244     UINT Nix ;
245
246     SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ;
247
248     if (ERROR_SUCCESS != RegCreateKeyExA (
249         HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU",
250         0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL))
251         MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ;
252
253     RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ;
254
255     if (icList > 0)
256         {
257         pszList = HeapAlloc( GetProcessHeap(), 0, icList) ;
258         if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, pszList, &icList))
259             MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ;
260         }
261     else
262         {
263         icList = 1 ;
264         pszList = HeapAlloc( GetProcessHeap(), 0, icList) ;
265         pszList[0] = 0 ;
266         }
267
268     for (Nix = 0 ; Nix < icList - 1 ; Nix++)
269         {
270         if (pszList[Nix] > cMax)
271             cMax = pszList[Nix] ;
272
273         szIndex[0] = pszList[Nix] ;
274
275         if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd))
276             MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ;
277         if( pszCmd )
278             pszCmd = HeapReAlloc(GetProcessHeap(), 0, pszCmd, icCmd) ;
279         else
280             pszCmd = HeapAlloc(GetProcessHeap(), 0, icCmd) ;
281         if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, pszCmd, &icCmd))
282             MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ;
283
284         if (NULL != pszLatest)
285             {
286             if (!strcasecmp (pszCmd, pszLatest))
287                 {
288                 /*
289                 sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ;
290                 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
291                 */
292                 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ;
293                 SetWindowTextA (hCb, pszCmd) ;
294                 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
295
296                 cMatch = pszList[Nix] ;
297                 memmove (&pszList[1], pszList, Nix) ;
298                 pszList[0] = cMatch ;
299                 continue ;
300                 }
301             }
302
303         if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest)
304             {
305             /*
306             sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ;
307             MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
308             */
309             SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ;
310             if (!Nix)
311                 {
312                 SetWindowTextA (hCb, pszCmd) ;
313                 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
314                 }
315
316             }
317         else
318             {
319             /*
320             sprintf (szDbgMsg, "Doing loop thing.\n") ;
321             MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
322             */
323             SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
324             SetWindowTextA (hCb, pszLatest) ;
325             SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
326
327             cMatch = pszList[Nix] ;
328             memmove (&pszList[1], pszList, Nix) ;
329             pszList[0] = cMatch ;
330             szIndex[0] = cMatch ;
331             RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ;
332             }
333         }
334
335     if (!cMatch && NULL != pszLatest)
336         {
337         /*
338         sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ;
339         MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
340         */
341         SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
342         SetWindowTextA (hCb, pszLatest) ;
343         SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
344
345         cMatch = ++cMax ;
346         if( pszList )
347             pszList = HeapReAlloc(GetProcessHeap(), 0, pszList, ++icList) ;
348         else
349             pszList = HeapAlloc(GetProcessHeap(), 0, ++icList) ;
350         memmove (&pszList[1], pszList, icList - 1) ;
351         pszList[0] = cMatch ;
352         szIndex[0] = cMatch ;
353         RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ;
354         }
355
356     RegSetValueExA (hkey, "MRUList", 0, REG_SZ, pszList, strlen (pszList) + 1) ;
357
358     HeapFree( GetProcessHeap(), 0, pszCmd) ;
359     HeapFree( GetProcessHeap(), 0, pszList) ;
360     }
361
362
363 /*************************************************************************
364  * ConfirmDialog                                [internal]
365  *
366  * Put up a confirm box, return TRUE if the user confirmed
367  */
368 static BOOL ConfirmDialog(HWND hWndOwner, UINT PromptId, UINT TitleId)
369 {
370   WCHAR Prompt[256];
371   WCHAR Title[256];
372
373   LoadStringW(shell32_hInstance, PromptId, Prompt, sizeof(Prompt) / sizeof(WCHAR));
374   LoadStringW(shell32_hInstance, TitleId, Title, sizeof(Title) / sizeof(WCHAR));
375   return MessageBoxW(hWndOwner, Prompt, Title, MB_YESNO|MB_ICONQUESTION) == IDYES;
376 }
377
378
379 /*************************************************************************
380  * RestartDialogEx                              [SHELL32.730]
381  */
382
383 int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason)
384 {
385     TRACE("(%p)\n", hWndOwner);
386
387     /*FIXME: use uReason */
388
389     if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE))
390     {
391         HANDLE hToken;
392         TOKEN_PRIVILEGES npr;
393
394         /* enable shutdown privilege for current process */
395         if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
396         {
397             LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
398             npr.PrivilegeCount = 1;
399             npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
400             AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
401             CloseHandle(hToken);
402         }
403         ExitWindowsEx(EWX_REBOOT, 0);
404     }
405
406     return 0;
407 }
408
409
410 /*************************************************************************
411  * RestartDialog                                [SHELL32.59]
412  */
413
414 int WINAPI RestartDialog(HWND hWndOwner, LPCWSTR lpstrReason, DWORD uFlags)
415 {
416     return RestartDialogEx(hWndOwner, lpstrReason, uFlags, 0);
417 }
418
419
420 /*************************************************************************
421  * ExitWindowsDialog                            [SHELL32.60]
422  *
423  * NOTES
424  *     exported by ordinal
425  */
426 void WINAPI ExitWindowsDialog (HWND hWndOwner)
427 {
428     TRACE("(%p)\n", hWndOwner);
429
430     if (ConfirmDialog(hWndOwner, IDS_SHUTDOWN_PROMPT, IDS_SHUTDOWN_TITLE))
431     {
432         HANDLE hToken;
433         TOKEN_PRIVILEGES npr;
434
435         /* enable shutdown privilege for current process */
436         if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
437         {
438             LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
439             npr.PrivilegeCount = 1;
440             npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
441             AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
442             CloseHandle(hToken);
443         }
444         ExitWindowsEx(EWX_SHUTDOWN, 0);
445     }
446 }