- move CreateMyCompEnumList and CreateDesktopEnumList to their
[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 "undocshell.h"
40
41 typedef struct
42     {
43         HWND hwndOwner ;
44         HICON hIcon ;
45         LPCSTR lpstrDirectory ;
46         LPCSTR lpstrTitle ;
47         LPCSTR lpstrDescription ;
48         UINT uFlags ;
49     } RUNFILEDLGPARAMS ;
50
51 typedef BOOL (*LPFNOFN) (OPENFILENAMEA *) ;
52
53 WINE_DEFAULT_DEBUG_CHANNEL(shell);
54 INT_PTR CALLBACK RunDlgProc (HWND, UINT, WPARAM, LPARAM) ;
55 void FillList (HWND, char *) ;
56
57
58 /*************************************************************************
59  * PickIconDlg                                  [SHELL32.62]
60  *
61  */
62 BOOL WINAPI PickIconDlg(
63         HWND hwndOwner,
64         LPSTR lpstrFile,
65         DWORD nMaxFile,
66         LPDWORD lpdwIconIndex)
67 {
68         FIXME("(%p,%s,%08lx,%p):stub.\n",
69           hwndOwner, lpstrFile, nMaxFile,lpdwIconIndex);
70         return 0xffffffff;
71 }
72
73 /*************************************************************************
74  * RunFileDlg                                   [SHELL32.61]
75  *
76  * NOTES
77  *     Original name: RunFileDlg (exported by ordinal)
78  */
79 void WINAPI RunFileDlg(
80         HWND hwndOwner,
81         HICON hIcon,
82         LPCSTR lpstrDirectory,
83         LPCSTR lpstrTitle,
84         LPCSTR lpstrDescription,
85         UINT uFlags)
86 {
87
88     RUNFILEDLGPARAMS rfdp;
89     HRSRC hRes;
90     LPVOID template;
91     TRACE("\n");
92
93     rfdp.hwndOwner        = hwndOwner;
94     rfdp.hIcon            = hIcon;
95     rfdp.lpstrDirectory   = lpstrDirectory;
96     rfdp.lpstrTitle       = lpstrTitle;
97     rfdp.lpstrDescription = lpstrDescription;
98     rfdp.uFlags           = uFlags;
99
100     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_RUN_DLG", (LPSTR)RT_DIALOG)))
101         {
102         MessageBoxA (hwndOwner, "Couldn't find dialog.", "Nix", MB_OK) ;
103         return;
104         }
105     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
106         {
107         MessageBoxA (hwndOwner, "Couldn't load dialog.", "Nix", MB_OK) ;
108         return;
109         }
110
111     DialogBoxIndirectParamA((HINSTANCE)GetWindowLongA( hwndOwner,
112                                                        GWL_HINSTANCE ),
113                             template, hwndOwner, RunDlgProc, (LPARAM)&rfdp);
114
115 }
116
117 /* Dialog procedure for RunFileDlg */
118 INT_PTR CALLBACK RunDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
119     {
120     int ic ;
121     char *psz, szMsg[256] ;
122     static RUNFILEDLGPARAMS *prfdp = NULL ;
123
124     switch (message)
125         {
126         case WM_INITDIALOG :
127             prfdp = (RUNFILEDLGPARAMS *)lParam ;
128             SetWindowTextA (hwnd, prfdp->lpstrTitle) ;
129             SetClassLongA (hwnd, GCL_HICON, (LPARAM)prfdp->hIcon) ;
130             SendMessageA (GetDlgItem (hwnd, 12297), STM_SETICON,
131                           (WPARAM)LoadIconA (NULL, (LPSTR)IDI_WINLOGO), 0);
132             FillList (GetDlgItem (hwnd, 12298), NULL) ;
133             SetFocus (GetDlgItem (hwnd, 12298)) ;
134             return TRUE ;
135
136         case WM_COMMAND :
137             {
138             STARTUPINFOA si ;
139             PROCESS_INFORMATION pi ;
140
141             si.cb = sizeof (STARTUPINFOA) ;
142             si.lpReserved = NULL ;
143             si.lpDesktop = NULL ;
144             si.lpTitle = NULL ;
145             si.dwX = 0 ;
146             si.dwY = 0 ;
147             si.dwXSize = 0 ;
148             si.dwYSize = 0 ;
149             si.dwXCountChars = 0 ;
150             si.dwYCountChars = 0 ;
151             si.dwFillAttribute = 0 ;
152             si.dwFlags = 0 ;
153             si.cbReserved2 = 0 ;
154             si.lpReserved2 = NULL ;
155
156             switch (LOWORD (wParam))
157                 {
158                 case IDOK :
159                     {
160                     HWND htxt = NULL ;
161                     if ((ic = GetWindowTextLengthA (htxt = GetDlgItem (hwnd, 12298))))
162                         {
163                         psz = malloc (ic + 2) ;
164                         GetWindowTextA (htxt, psz, ic + 1) ;
165
166                         if (!CreateProcessA (NULL, psz, NULL, NULL, TRUE,
167                             NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi))
168                             {
169                             char *pszSysMsg = NULL ;
170                             FormatMessageA (
171                                 FORMAT_MESSAGE_ALLOCATE_BUFFER |
172                                 FORMAT_MESSAGE_FROM_SYSTEM |
173                                 FORMAT_MESSAGE_IGNORE_INSERTS,
174                                 NULL, GetLastError (),
175                                 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
176                                 (LPSTR)&pszSysMsg, 0, NULL
177                                 ) ;
178                             sprintf (szMsg, "Error: %s", pszSysMsg) ;
179                             LocalFree ((HLOCAL)pszSysMsg) ;
180                             MessageBoxA (hwnd, szMsg, "Nix", MB_OK | MB_ICONEXCLAMATION) ;
181
182                             free (psz) ;
183                             SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
184                             return TRUE ;
185                             }
186                         FillList (htxt, psz) ;
187                         free (psz) ;
188                         EndDialog (hwnd, 0) ;
189                         }
190                     }
191
192                 case IDCANCEL :
193                     EndDialog (hwnd, 0) ;
194                     return TRUE ;
195
196                 case 12288 :
197                     {
198                     HMODULE hComdlg = NULL ;
199                     LPFNOFN ofnProc = NULL ;
200                     static char szFName[1024] = "", szFileTitle[256] = "", szInitDir[768] = "" ;
201                     static OPENFILENAMEA ofn =
202                         {
203                         sizeof (OPENFILENAMEA),
204                         NULL,
205                         NULL,
206                         "Executable Files\0*.exe\0All Files\0*.*\0\0\0\0",
207                         NULL,
208                         0,
209                         0,
210                         szFName,
211                         1023,
212                         szFileTitle,
213                         255,
214                         (LPCSTR)szInitDir,
215                         "Browse",
216                         OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST,
217                         0,
218                         0,
219                         NULL,
220                         0,
221                         (LPOFNHOOKPROC)NULL,
222                         NULL
223                         } ;
224
225                     ofn.hwndOwner = hwnd ;
226
227                     if (NULL == (hComdlg = LoadLibraryExA ("comdlg32", NULL, 0)))
228                         {
229                         MessageBoxA (hwnd, "Unable to display dialog box (LoadLibraryEx) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
230                         return TRUE ;
231                         }
232
233                     if ((LPFNOFN)NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameA")))
234                         {
235                         MessageBoxA (hwnd, "Unable to display dialog box (GetProcAddress) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
236                         return TRUE ;
237                         }
238
239                     ofnProc (&ofn) ;
240
241                     SetFocus (GetDlgItem (hwnd, IDOK)) ;
242                     SetWindowTextA (GetDlgItem (hwnd, 12298), szFName) ;
243                     SendMessageA (GetDlgItem (hwnd, 12298), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
244                     SetFocus (GetDlgItem (hwnd, IDOK)) ;
245
246                     FreeLibrary (hComdlg) ;
247
248                     return TRUE ;
249                     }
250                 }
251             return TRUE ;
252             }
253         }
254     return FALSE ;
255     }
256
257 /* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */
258 void FillList (HWND hCb, char *pszLatest)
259     {
260     HKEY hkey ;
261 /*    char szDbgMsg[256] = "" ; */
262     char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ;
263     DWORD icList = 0, icCmd = 0 ;
264     UINT Nix ;
265
266     SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ;
267
268     if (ERROR_SUCCESS != RegCreateKeyExA (
269         HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU",
270         0, "", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL))
271         MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ;
272
273     RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ;
274
275     if (icList > 0)
276         {
277         pszList = malloc (icList) ;
278         if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, pszList, &icList))
279             MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ;
280         }
281     else
282         {
283         pszList = malloc (icList = 1) ;
284         pszList[0] = 0 ;
285         }
286
287     for (Nix = 0 ; Nix < icList - 1 ; Nix++)
288         {
289         if (pszList[Nix] > cMax)
290             cMax = pszList[Nix] ;
291
292         szIndex[0] = pszList[Nix] ;
293
294         if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd))
295             MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ;
296         pszCmd = realloc (pszCmd, icCmd) ;
297         if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, pszCmd, &icCmd))
298             MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ;
299
300         if (NULL != pszLatest)
301             {
302             if (!strcasecmp (pszCmd, pszLatest))
303                 {
304                 /*
305                 sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ;
306                 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
307                 */
308                 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ;
309                 SetWindowTextA (hCb, pszCmd) ;
310                 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
311
312                 cMatch = pszList[Nix] ;
313                 memmove (&pszList[1], pszList, Nix) ;
314                 pszList[0] = cMatch ;
315                 continue ;
316                 }
317             }
318
319         if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest)
320             {
321             /*
322             sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ;
323             MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
324             */
325             SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ;
326             if (!Nix)
327                 {
328                 SetWindowTextA (hCb, pszCmd) ;
329                 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
330                 }
331
332             }
333         else
334             {
335             /*
336             sprintf (szDbgMsg, "Doing loop thing.\n") ;
337             MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
338             */
339             SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
340             SetWindowTextA (hCb, pszLatest) ;
341             SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
342
343             cMatch = pszList[Nix] ;
344             memmove (&pszList[1], pszList, Nix) ;
345             pszList[0] = cMatch ;
346             szIndex[0] = cMatch ;
347             RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ;
348             }
349         }
350
351     if (!cMatch && NULL != pszLatest)
352         {
353         /*
354         sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ;
355         MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
356         */
357         SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
358         SetWindowTextA (hCb, pszLatest) ;
359         SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
360
361         cMatch = ++cMax ;
362         pszList = realloc (pszList, ++icList) ;
363         memmove (&pszList[1], pszList, icList - 1) ;
364         pszList[0] = cMatch ;
365         szIndex[0] = cMatch ;
366         RegSetValueExA (hkey, szIndex, 0, REG_SZ, pszLatest, strlen (pszLatest) + 1) ;
367         }
368
369     RegSetValueExA (hkey, "MRUList", 0, REG_SZ, pszList, strlen (pszList) + 1) ;
370
371     free (pszCmd) ;
372     free (pszList) ;
373     }
374
375 /*************************************************************************
376  * ExitWindowsDialog                            [SHELL32.60]
377  *
378  * NOTES
379  *     exported by ordinal
380  */
381 void WINAPI ExitWindowsDialog (HWND hWndOwner)
382 {
383         TRACE("(%p)\n", hWndOwner);
384         if (MessageBoxA( hWndOwner, "Do you want to exit WINE?", "Shutdown", MB_YESNO|MB_ICONQUESTION) == IDYES)
385         {
386           SendMessageA ( hWndOwner, WM_QUIT, 0, 0);
387         }
388 }