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