Use system metrics values in TOOLBAR_DrawPattern instead of hardcoded
[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)GetWindowLongA( hwndOwner,
113                                                        GWL_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             {
139             STARTUPINFOA si ;
140             PROCESS_INFORMATION pi ;
141
142             si.cb = sizeof (STARTUPINFOA) ;
143             si.lpReserved = NULL ;
144             si.lpDesktop = NULL ;
145             si.lpTitle = NULL ;
146             si.dwX = 0 ;
147             si.dwY = 0 ;
148             si.dwXSize = 0 ;
149             si.dwYSize = 0 ;
150             si.dwXCountChars = 0 ;
151             si.dwYCountChars = 0 ;
152             si.dwFillAttribute = 0 ;
153             si.dwFlags = 0 ;
154             si.cbReserved2 = 0 ;
155             si.lpReserved2 = NULL ;
156
157             switch (LOWORD (wParam))
158                 {
159                 case IDOK :
160                     {
161                     HWND htxt = NULL ;
162                     if ((ic = GetWindowTextLengthA (htxt = GetDlgItem (hwnd, 12298))))
163                         {
164                         psz = malloc (ic + 2) ;
165                         GetWindowTextA (htxt, psz, ic + 1) ;
166
167                         if (!CreateProcessA (NULL, psz, NULL, NULL, TRUE,
168                             NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
169                             {
170                             char *pszSysMsg = NULL ;
171                             FormatMessageA (
172                                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
173                                 FORMAT_MESSAGE_FROM_SYSTEM |
174                                 FORMAT_MESSAGE_IGNORE_INSERTS,
175                                 NULL, GetLastError (),
176                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
177                                 (LPSTR)&pszSysMsg, 0, NULL
178                                 ) ;
179                             sprintf (szMsg, "Error: %s", pszSysMsg) ;
180                             LocalFree ((HLOCAL)pszSysMsg) ;
181                             MessageBoxA (hwnd, szMsg, "Nix", MB_OK | MB_ICONEXCLAMATION) ;
182
183                             free (psz) ;
184                             SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
185                             return TRUE ;
186                             }
187                         FillList (htxt, psz) ;
188                         free (psz) ;
189                         EndDialog (hwnd, 0) ;
190                         }
191                     }
192
193                 case IDCANCEL :
194                     EndDialog (hwnd, 0) ;
195                     return TRUE ;
196
197                 case 12288 :
198                     {
199                     HMODULE hComdlg = NULL ;
200                     LPFNOFN ofnProc = NULL ;
201                     static char szFName[1024] = "", szFileTitle[256] = "", szInitDir[768] = "" ;
202                     static OPENFILENAMEA ofn =
203                         {
204                         sizeof (OPENFILENAMEA),
205                         NULL,
206                         NULL,
207                         "Executable Files\0*.exe\0All Files\0*.*\0\0\0\0",
208                         NULL,
209                         0,
210                         0,
211                         szFName,
212                         1023,
213                         szFileTitle,
214                         255,
215                         (LPCSTR)szInitDir,
216                         "Browse",
217                         OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST,
218                         0,
219                         0,
220                         NULL,
221                         0,
222                         (LPOFNHOOKPROC)NULL,
223                         NULL
224                         } ;
225
226                     ofn.hwndOwner = hwnd ;
227
228                     if (NULL == (hComdlg = LoadLibraryExA ("comdlg32", NULL, 0)))
229                         {
230                         MessageBoxA (hwnd, "Unable to display dialog box (LoadLibraryEx) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
231                         return TRUE ;
232                         }
233
234                     if ((LPFNOFN)NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameA")))
235                         {
236                         MessageBoxA (hwnd, "Unable to display dialog box (GetProcAddress) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
237                         return TRUE ;
238                         }
239
240                     ofnProc (&ofn) ;
241
242                     SetFocus (GetDlgItem (hwnd, IDOK)) ;
243                     SetWindowTextA (GetDlgItem (hwnd, 12298), szFName) ;
244                     SendMessageA (GetDlgItem (hwnd, 12298), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
245                     SetFocus (GetDlgItem (hwnd, IDOK)) ;
246
247                     FreeLibrary (hComdlg) ;
248
249                     return TRUE ;
250                     }
251                 }
252             return TRUE ;
253             }
254         }
255     return FALSE ;
256     }
257
258 /* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */
259 void FillList (HWND hCb, char *pszLatest)
260     {
261     HKEY hkey ;
262 /*    char szDbgMsg[256] = "" ; */
263     char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ;
264     DWORD icList = 0, icCmd = 0 ;
265     UINT Nix ;
266
267     SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ;
268
269     if (ERROR_SUCCESS != RegCreateKeyExA (
270         HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU",
271         0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL))
272         MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ;
273
274     RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ;
275
276     if (icList > 0)
277         {
278         pszList = malloc (icList) ;
279         if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, pszList, &icList))
280             MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ;
281         }
282     else
283         {
284         pszList = malloc (icList = 1) ;
285         pszList[0] = 0 ;
286         }
287
288     for (Nix = 0 ; Nix < icList - 1 ; Nix++)
289         {
290         if (pszList[Nix] > cMax)
291             cMax = pszList[Nix] ;
292
293         szIndex[0] = pszList[Nix] ;
294
295         if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd))
296             MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ;
297         pszCmd = realloc (pszCmd, icCmd) ;
298         if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, pszCmd, &icCmd))
299             MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ;
300
301         if (NULL != pszLatest)
302             {
303             if (!strcasecmp (pszCmd, pszLatest))
304                 {
305                 /*
306                 sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ;
307                 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
308                 */
309                 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ;
310                 SetWindowTextA (hCb, pszCmd) ;
311                 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
312
313                 cMatch = pszList[Nix] ;
314                 memmove (&pszList[1], pszList, Nix) ;
315                 pszList[0] = cMatch ;
316                 continue ;
317                 }
318             }
319
320         if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest)
321             {
322             /*
323             sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ;
324             MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
325             */
326             SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ;
327             if (!Nix)
328                 {
329                 SetWindowTextA (hCb, pszCmd) ;
330                 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
331                 }
332
333             }
334         else
335             {
336             /*
337             sprintf (szDbgMsg, "Doing loop thing.\n") ;
338             MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
339             */
340             SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
341             SetWindowTextA (hCb, pszLatest) ;
342             SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
343
344             cMatch = pszList[Nix] ;
345             memmove (&pszList[1], pszList, Nix) ;
346             pszList[0] = cMatch ;
347             szIndex[0] = cMatch ;
348             RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ;
349             }
350         }
351
352     if (!cMatch && NULL != pszLatest)
353         {
354         /*
355         sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ;
356         MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
357         */
358         SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
359         SetWindowTextA (hCb, pszLatest) ;
360         SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
361
362         cMatch = ++cMax ;
363         pszList = realloc (pszList, ++icList) ;
364         memmove (&pszList[1], pszList, icList - 1) ;
365         pszList[0] = cMatch ;
366         szIndex[0] = cMatch ;
367         RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ;
368         }
369
370     RegSetValueExA (hkey, "MRUList", 0, REG_SZ, pszList, strlen (pszList) + 1) ;
371
372     free (pszCmd) ;
373     free (pszList) ;
374     }
375
376
377 /*************************************************************************
378  * ConfirmDialog                                [internal]
379  *
380  * Put up a confirm box, return TRUE if the user confirmed
381  */
382 static BOOL ConfirmDialog(HWND hWndOwner, UINT PromptId, UINT TitleId)
383 {
384   WCHAR Prompt[256];
385   WCHAR Title[256];
386
387   LoadStringW(shell32_hInstance, PromptId, Prompt, sizeof(Prompt) / sizeof(WCHAR));
388   LoadStringW(shell32_hInstance, TitleId, Title, sizeof(Title) / sizeof(WCHAR));
389   return MessageBoxW(hWndOwner, Prompt, Title, MB_YESNO|MB_ICONQUESTION) == IDYES;
390 }
391
392
393 /*************************************************************************
394  * RestartDialogEx                              [SHELL32.730]
395  */
396
397 int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason)
398 {
399     TRACE("(%p)\n", hWndOwner);
400
401     /*FIXME: use uReason */
402
403     if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE))
404     {
405         HANDLE hToken;
406         TOKEN_PRIVILEGES npr;
407
408         /* enable shutdown privilege for current process */
409         if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
410         {
411             LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
412             npr.PrivilegeCount = 1;
413             npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
414             AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
415             CloseHandle(hToken);
416         }
417         ExitWindowsEx(EWX_REBOOT, 0);
418     }
419
420     return 0;
421 }
422
423
424 /*************************************************************************
425  * RestartDialog                                [SHELL32.59]
426  */
427
428 int WINAPI RestartDialog(HWND hWndOwner, LPCWSTR lpstrReason, DWORD uFlags)
429 {
430     return RestartDialogEx(hWndOwner, lpstrReason, uFlags, 0);
431 }
432
433
434 /*************************************************************************
435  * ExitWindowsDialog                            [SHELL32.60]
436  *
437  * NOTES
438  *     exported by ordinal
439  */
440 void WINAPI ExitWindowsDialog (HWND hWndOwner)
441 {
442     TRACE("(%p)\n", hWndOwner);
443
444     if (ConfirmDialog(hWndOwner, IDS_SHUTDOWN_PROMPT, IDS_SHUTDOWN_TITLE))
445     {
446         HANDLE hToken;
447         TOKEN_PRIVILEGES npr;
448
449         /* enable shutdown privilege for current process */
450         if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
451         {
452             LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
453             npr.PrivilegeCount = 1;
454             npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
455             AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
456             CloseHandle(hToken);
457         }
458         ExitWindowsEx(EWX_SHUTDOWN, 0);
459     }
460 }