Matthias Kupfer (matthias DOT kupfer AT informatik DOT tu-chemnitz DOT de)
[reactos.git] / reactos / dll / win32 / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 #include "shlwapi.h"
42
43 typedef struct
44 {
45 HWND hwndOwner ;
46 HICON hIcon ;
47 LPCSTR lpstrDirectory ;
48 LPCSTR lpstrTitle ;
49 LPCSTR lpstrDescription ;
50 UINT uFlags ;
51 } RUNFILEDLGPARAMS ;
52
53 typedef BOOL (*LPFNOFN) (OPENFILENAMEA *) ;
54
55 WINE_DEFAULT_DEBUG_CHANNEL(shell);
56 static INT_PTR CALLBACK RunDlgProc (HWND, UINT, WPARAM, LPARAM) ;
57 static void FillList (HWND, char *) ;
58
59
60 /*************************************************************************
61 * PickIconDlg [SHELL32.62]
62 *
63 */
64
65 typedef struct
66 {
67 HMODULE hLibrary;
68 HWND hDlgCtrl;
69 WCHAR szName[MAX_PATH];
70 INT Index;
71 }PICK_ICON_CONTEXT, *PPICK_ICON_CONTEXT;
72
73 BOOL CALLBACK EnumPickIconResourceProc(HMODULE hModule,
74 LPCWSTR lpszType,
75 LPWSTR lpszName,
76 LONG_PTR lParam
77 )
78 {
79 WCHAR szName[100];
80 int index;
81 HICON hIcon;
82 PPICK_ICON_CONTEXT pIconContext = (PPICK_ICON_CONTEXT)lParam;
83
84 if (IS_INTRESOURCE(lpszName))
85 swprintf(szName, L"%u\n", lpszName);
86 else
87 wcscpy(szName, (WCHAR*)lpszName);
88
89
90 hIcon = LoadIconW(pIconContext->hLibrary, (LPCWSTR)lpszName);
91 if (hIcon == NULL)
92 return TRUE;
93
94 index = SendMessageW(pIconContext->hDlgCtrl, LB_ADDSTRING, 0, (LPARAM)szName);
95 if (index != LB_ERR)
96 SendMessageW(pIconContext->hDlgCtrl, LB_SETITEMDATA, index, (LPARAM)hIcon);
97
98 return TRUE;
99 }
100
101 void
102 DestroyIconList(HWND hDlgCtrl)
103 {
104 int count;
105 int index;
106
107 count = SendMessage(hDlgCtrl, LB_GETCOUNT, 0, 0);
108 if (count == LB_ERR)
109 return;
110
111 for(index = 0; index < count; index++)
112 {
113 HICON hIcon = (HICON)SendMessageW(hDlgCtrl, LB_GETITEMDATA, index, 0);
114 DestroyIcon(hIcon);
115 }
116 }
117
118 INT_PTR CALLBACK PickIconProc(HWND hwndDlg,
119 UINT uMsg,
120 WPARAM wParam,
121 LPARAM lParam
122 )
123 {
124 LPMEASUREITEMSTRUCT lpmis;
125 LPDRAWITEMSTRUCT lpdis;
126 HICON hIcon;
127 INT index;
128 WCHAR szText[MAX_PATH], szTitle[100], szFilter[100];
129 OPENFILENAMEW ofn = {0};
130
131 PPICK_ICON_CONTEXT pIconContext = (PPICK_ICON_CONTEXT)GetWindowLong(hwndDlg, DWLP_USER);
132
133 switch(uMsg)
134 {
135 case WM_INITDIALOG:
136 pIconContext = (PPICK_ICON_CONTEXT)lParam;
137 SetWindowLong(hwndDlg, DWLP_USER, (LONG)pIconContext);
138 pIconContext->hDlgCtrl = GetDlgItem(hwndDlg, IDC_PICKICON_LIST);
139 EnumResourceNamesW(pIconContext->hLibrary, MAKEINTRESOURCEW(RT_ICON), EnumPickIconResourceProc, (LPARAM)pIconContext);
140 if (PathUnExpandEnvStringsW(pIconContext->szName, szText, MAX_PATH))
141 SendDlgItemMessageW(hwndDlg, IDC_EDIT_PATH, WM_SETTEXT, 0, (LPARAM)szText);
142 else
143 SendDlgItemMessageW(hwndDlg, IDC_EDIT_PATH, WM_SETTEXT, 0, (LPARAM)pIconContext->szName);
144
145 swprintf(szText, L"%u", pIconContext->Index);
146 index = SendMessageW(pIconContext->hDlgCtrl, LB_FINDSTRING, -1, (LPARAM)szText);
147 if (index != LB_ERR)
148 SendMessageW(pIconContext->hDlgCtrl, LB_SETCURSEL, index, 0);
149 return TRUE;
150 case WM_COMMAND:
151 switch(LOWORD(wParam))
152 {
153 case IDOK:
154 index = SendMessageW(pIconContext->hDlgCtrl, LB_GETCURSEL, 0, 0);
155 SendMessageW(pIconContext->hDlgCtrl, LB_GETTEXT, index, (LPARAM)szText);
156 pIconContext->Index = _wtoi(szText);
157 SendDlgItemMessageW(hwndDlg, IDC_EDIT_PATH, WM_GETTEXT, MAX_PATH, (LPARAM)pIconContext->szName);
158 DestroyIconList(pIconContext->hDlgCtrl);
159 EndDialog(hwndDlg, 1);
160 break;
161 case IDCANCEL:
162 DestroyIconList(pIconContext->hDlgCtrl);
163 EndDialog(hwndDlg, 0);
164 break;
165 case IDC_PICKICON_LIST:
166 if (HIWORD(wParam) == LBN_SELCHANGE)
167 InvalidateRect((HWND)lParam, NULL, TRUE); // FIXME USE UPDATE RECT
168 break;
169 case IDC_BUTTON_PATH:
170 szText[0] = 0;
171 szTitle[0] = 0;
172 szFilter[0] = 0;
173 ofn.lStructSize = sizeof(ofn);
174 ofn.hwndOwner = hwndDlg;
175 ofn.lpstrFile = szText;
176 ofn.nMaxFile = MAX_PATH;
177 LoadStringW(shell32_hInstance, IDS_PICK_ICON_TITLE, szTitle, sizeof(szTitle) / sizeof(WCHAR));
178 ofn.lpstrTitle = szTitle;
179 LoadStringW(shell32_hInstance, IDS_PICK_ICON_FILTER, szFilter, sizeof(szFilter) / sizeof(WCHAR));
180 ofn.lpstrFilter = szFilter;
181 if (GetOpenFileNameW(&ofn))
182 {
183 HMODULE hLibrary;
184
185 if (!wcsicmp(pIconContext->szName, szText))
186 break;
187
188 DestroyIconList(pIconContext->hDlgCtrl);
189
190 hLibrary = LoadLibraryExW(szText, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
191 if (hLibrary == NULL)
192 break;
193 FreeLibrary(pIconContext->hLibrary);
194 pIconContext->hLibrary = hLibrary;
195 wcscpy(pIconContext->szName, szText);
196 EnumResourceNamesW(pIconContext->hLibrary, MAKEINTRESOURCEW(RT_ICON), EnumPickIconResourceProc, (LPARAM)pIconContext);
197 if (PathUnExpandEnvStringsW(pIconContext->szName, szText, MAX_PATH))
198 SendDlgItemMessageW(hwndDlg, IDC_EDIT_PATH, WM_SETTEXT, 0, (LPARAM)szText);
199 else
200 SendDlgItemMessageW(hwndDlg, IDC_EDIT_PATH, WM_SETTEXT, 0, (LPARAM)pIconContext->szName);
201
202 SendMessageW(pIconContext->hDlgCtrl, LB_SETCURSEL, 0, 0);
203 }
204 break;
205 }
206 break;
207 case WM_MEASUREITEM:
208 lpmis = (LPMEASUREITEMSTRUCT) lParam;
209 lpmis->itemHeight = 32;
210 lpmis->itemWidth = 64;
211 return TRUE;
212 case WM_DRAWITEM:
213 lpdis = (LPDRAWITEMSTRUCT) lParam;
214 if (lpdis->itemID == -1)
215 {
216 break;
217 }
218 switch (lpdis->itemAction)
219 {
220 case ODA_SELECT:
221 case ODA_DRAWENTIRE:
222 index = SendMessageW(pIconContext->hDlgCtrl, LB_GETCURSEL, 0, 0);
223 hIcon =(HICON)SendMessage(lpdis->hwndItem, LB_GETITEMDATA, lpdis->itemID, (LPARAM) 0);
224
225 if (lpdis->itemID == index)
226 {
227 HBRUSH hBrush;
228 hBrush = CreateSolidBrush(RGB(0, 0, 255));
229 FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
230 DeleteObject(hBrush);
231 }
232 else
233 {
234 HBRUSH hBrush;
235 hBrush = CreateSolidBrush(RGB(255, 255, 255));
236 FillRect(lpdis->hDC, &lpdis->rcItem, hBrush);
237 DeleteObject(hBrush);
238 }
239 DrawIconEx(lpdis->hDC, lpdis->rcItem.left,lpdis->rcItem.top, hIcon,
240 0,
241 0,
242 0,
243 NULL,
244 DI_NORMAL);
245 break;
246 }
247 }
248
249 return FALSE;
250 }
251
252 BOOL WINAPI PickIconDlg(
253 HWND hwndOwner,
254 LPWSTR lpstrFile,
255 UINT nMaxFile,
256 INT* lpdwIconIndex)
257 {
258 HMODULE hLibrary;
259 int res;
260 PICK_ICON_CONTEXT IconContext;
261
262 hLibrary = LoadLibraryExW(lpstrFile, NULL, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
263 IconContext.hLibrary = hLibrary;
264 IconContext.Index = *lpdwIconIndex;
265 wcscpy(IconContext.szName, lpstrFile);
266
267 res = DialogBoxParamW(shell32_hInstance, MAKEINTRESOURCEW(IDD_PICK_ICON_DIALOG), hwndOwner, PickIconProc, (LPARAM)&IconContext);
268 if (res)
269 {
270 wcscpy(lpstrFile, IconContext.szName);
271 *lpdwIconIndex = IconContext.Index;
272 }
273
274 FreeLibrary(hLibrary);
275 return res;
276 }
277
278 /*************************************************************************
279 * RunFileDlg [SHELL32.61]
280 *
281 * NOTES
282 * Original name: RunFileDlg (exported by ordinal)
283 */
284 void WINAPI RunFileDlg(
285 HWND hwndOwner,
286 HICON hIcon,
287 LPCSTR lpstrDirectory,
288 LPCSTR lpstrTitle,
289 LPCSTR lpstrDescription,
290 UINT uFlags)
291 {
292
293 RUNFILEDLGPARAMS rfdp;
294 HRSRC hRes;
295 LPVOID template;
296 TRACE("\n");
297
298 rfdp.hwndOwner = hwndOwner;
299 rfdp.hIcon = hIcon;
300 rfdp.lpstrDirectory = lpstrDirectory;
301 rfdp.lpstrTitle = lpstrTitle;
302 rfdp.lpstrDescription = lpstrDescription;
303 rfdp.uFlags = uFlags;
304
305 if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_RUN_DLG", (LPSTR)RT_DIALOG)))
306 {
307 MessageBoxA (hwndOwner, "Couldn't find dialog.", "Nix", MB_OK) ;
308 return;
309 }
310 if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
311 {
312 MessageBoxA (hwndOwner, "Couldn't load dialog.", "Nix", MB_OK) ;
313 return;
314 }
315
316 DialogBoxIndirectParamA((HINSTANCE)GetWindowLongPtrW( hwndOwner,
317 GWLP_HINSTANCE ),
318 template, hwndOwner, RunDlgProc, (LPARAM)&rfdp);
319
320 }
321
322 /* Dialog procedure for RunFileDlg */
323 static INT_PTR CALLBACK RunDlgProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
324 {
325 int ic ;
326 char *psz, *pdir, szMsg[256];
327 static RUNFILEDLGPARAMS *prfdp = NULL ;
328
329 switch (message)
330 {
331 case WM_INITDIALOG :
332 prfdp = (RUNFILEDLGPARAMS *)lParam ;
333
334 if (prfdp->lpstrTitle)
335 SetWindowTextA (hwnd, prfdp->lpstrTitle) ;
336
337 SetClassLongPtrW (hwnd, GCLP_HICON, (LPARAM)prfdp->hIcon) ;
338 SendMessageW (GetDlgItem (hwnd, 12297), STM_SETICON,
339 (WPARAM)LoadIconW (NULL, (LPCWSTR)IDI_WINLOGO), 0);
340 FillList (GetDlgItem (hwnd, 12298), NULL) ;
341 SetFocus (GetDlgItem (hwnd, 12298)) ;
342 return TRUE ;
343
344 case WM_COMMAND :
345 switch (LOWORD (wParam))
346 {
347 case IDOK :
348 {
349 HWND htxt = NULL ;
350 if ((ic = GetWindowTextLengthA (htxt = GetDlgItem (hwnd, 12298))))
351 {
352 psz = HeapAlloc( GetProcessHeap(), 0, (ic + 2) );
353 GetWindowTextA (htxt, psz, ic + 1) ;
354 pdir = HeapAlloc( GetProcessHeap(), 0, (ic + 2) );
355 if (pdir)
356 {
357 char * ptr;
358 strcpy(pdir, psz);
359 ptr = strrchr(pdir, '\\');
360 if(ptr)
361 ptr[0] = '\0';
362 }
363 if (ShellExecuteA(NULL, "open", psz, NULL, pdir, SW_SHOWNORMAL) < (HINSTANCE)33)
364 {
365 char *pszSysMsg = NULL ;
366 FormatMessageA (
367 FORMAT_MESSAGE_ALLOCATE_BUFFER |
368 FORMAT_MESSAGE_FROM_SYSTEM |
369 FORMAT_MESSAGE_IGNORE_INSERTS,
370 NULL, GetLastError (),
371 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
372 (LPSTR)&pszSysMsg, 0, NULL
373 ) ;
374 sprintf (szMsg, "Error: %s", pszSysMsg) ;
375 LocalFree ((HLOCAL)pszSysMsg) ;
376 MessageBoxA (hwnd, szMsg, "Nix", MB_OK | MB_ICONEXCLAMATION) ;
377
378 HeapFree(GetProcessHeap(), 0, psz);
379 HeapFree(GetProcessHeap(), 0, pdir);
380 SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
381 return TRUE ;
382 }
383 FillList (htxt, psz) ;
384 HeapFree(GetProcessHeap(), 0, psz);
385 HeapFree(GetProcessHeap(), 0, pdir);
386 EndDialog (hwnd, 0) ;
387 }
388 }
389
390 case IDCANCEL :
391 EndDialog (hwnd, 0) ;
392 return TRUE ;
393
394 case 12288 :
395 {
396 HMODULE hComdlg = NULL ;
397 LPFNOFN ofnProc = NULL ;
398 static char szFName[1024] = "", szFileTitle[256] = "", szInitDir[768] = "" ;
399 static OPENFILENAMEA ofn =
400 {
401 sizeof (OPENFILENAMEA),
402 NULL,
403 NULL,
404 "Executable Files\0*.exe\0All Files\0*.*\0\0\0\0",
405 NULL,
406 0,
407 0,
408 szFName,
409 1023,
410 szFileTitle,
411 255,
412 (LPCSTR)szInitDir,
413 "Browse",
414 OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST,
415 0,
416 0,
417 NULL,
418 0,
419 (LPOFNHOOKPROC)NULL,
420 NULL
421 } ;
422
423 ofn.hwndOwner = hwnd ;
424
425 if (NULL == (hComdlg = LoadLibraryExA ("comdlg32", NULL, 0)))
426 {
427 MessageBoxA (hwnd, "Unable to display dialog box (LoadLibraryEx) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
428 return TRUE ;
429 }
430
431 if ((LPFNOFN)NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameA")))
432 {
433 MessageBoxA (hwnd, "Unable to display dialog box (GetProcAddress) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
434 return TRUE ;
435 }
436
437 ofnProc (&ofn) ;
438
439 SetFocus (GetDlgItem (hwnd, IDOK)) ;
440 SetWindowTextA (GetDlgItem (hwnd, 12298), szFName) ;
441 SendMessageA (GetDlgItem (hwnd, 12298), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
442 SetFocus (GetDlgItem (hwnd, IDOK)) ;
443
444 FreeLibrary (hComdlg) ;
445
446 return TRUE ;
447 }
448 }
449 return TRUE ;
450 }
451 return FALSE ;
452 }
453
454 /* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */
455 static void FillList (HWND hCb, char *pszLatest)
456 {
457 HKEY hkey ;
458 /* char szDbgMsg[256] = "" ; */
459 char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ;
460 DWORD icList = 0, icCmd = 0 ;
461 UINT Nix ;
462
463 SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ;
464
465 if (ERROR_SUCCESS != RegCreateKeyExA (
466 HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU",
467 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL))
468 MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ;
469
470 RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ;
471
472 if (icList > 0)
473 {
474 pszList = HeapAlloc( GetProcessHeap(), 0, icList) ;
475 if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, (LPBYTE)pszList, &icList))
476 MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ;
477 }
478 else
479 {
480 icList = 1 ;
481 pszList = HeapAlloc( GetProcessHeap(), 0, icList) ;
482 pszList[0] = 0 ;
483 }
484
485 for (Nix = 0 ; Nix < icList - 1 ; Nix++)
486 {
487 if (pszList[Nix] > cMax)
488 cMax = pszList[Nix] ;
489
490 szIndex[0] = pszList[Nix] ;
491
492 if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd))
493 MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ;
494 if( pszCmd )
495 pszCmd = HeapReAlloc(GetProcessHeap(), 0, pszCmd, icCmd) ;
496 else
497 pszCmd = HeapAlloc(GetProcessHeap(), 0, icCmd) ;
498 if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, (LPBYTE)pszCmd, &icCmd))
499 MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ;
500
501 if (NULL != pszLatest)
502 {
503 if (!lstrcmpiA(pszCmd, pszLatest))
504 {
505 /*
506 sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ;
507 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
508 */
509 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ;
510 SetWindowTextA (hCb, pszCmd) ;
511 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
512
513 cMatch = pszList[Nix] ;
514 memmove (&pszList[1], pszList, Nix) ;
515 pszList[0] = cMatch ;
516 continue ;
517 }
518 }
519
520 if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest)
521 {
522 /*
523 sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ;
524 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
525 */
526 SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ;
527 if (!Nix)
528 {
529 SetWindowTextA (hCb, pszCmd) ;
530 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
531 }
532
533 }
534 else
535 {
536 /*
537 sprintf (szDbgMsg, "Doing loop thing.\n") ;
538 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
539 */
540 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
541 SetWindowTextA (hCb, pszLatest) ;
542 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
543
544 cMatch = pszList[Nix] ;
545 memmove (&pszList[1], pszList, Nix) ;
546 pszList[0] = cMatch ;
547 szIndex[0] = cMatch ;
548 RegSetValueExA (hkey, szIndex, 0, REG_SZ, (LPBYTE)pszLatest, strlen (pszLatest) + 1) ;
549 }
550 }
551
552 if (!cMatch && NULL != pszLatest)
553 {
554 /*
555 sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ;
556 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
557 */
558 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
559 SetWindowTextA (hCb, pszLatest) ;
560 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
561
562 cMatch = ++cMax ;
563 if( pszList )
564 pszList = HeapReAlloc(GetProcessHeap(), 0, pszList, ++icList) ;
565 else
566 pszList = HeapAlloc(GetProcessHeap(), 0, ++icList) ;
567 memmove (&pszList[1], pszList, icList - 1) ;
568 pszList[0] = cMatch ;
569 szIndex[0] = cMatch ;
570 RegSetValueExA (hkey, szIndex, 0, REG_SZ, (LPBYTE)pszLatest, strlen (pszLatest) + 1) ;
571 }
572
573 RegSetValueExA (hkey, "MRUList", 0, REG_SZ, (LPBYTE)pszList, strlen (pszList) + 1) ;
574
575 HeapFree( GetProcessHeap(), 0, pszCmd) ;
576 HeapFree( GetProcessHeap(), 0, pszList) ;
577 }
578
579
580 /*************************************************************************
581 * ConfirmDialog [internal]
582 *
583 * Put up a confirm box, return TRUE if the user confirmed
584 */
585 static BOOL ConfirmDialog(HWND hWndOwner, UINT PromptId, UINT TitleId)
586 {
587 WCHAR Prompt[256];
588 WCHAR Title[256];
589
590 LoadStringW(shell32_hInstance, PromptId, Prompt, sizeof(Prompt) / sizeof(WCHAR));
591 LoadStringW(shell32_hInstance, TitleId, Title, sizeof(Title) / sizeof(WCHAR));
592 return MessageBoxW(hWndOwner, Prompt, Title, MB_YESNO|MB_ICONQUESTION) == IDYES;
593 }
594
595
596 /*************************************************************************
597 * RestartDialogEx [SHELL32.730]
598 */
599
600 int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason)
601 {
602 TRACE("(%p)\n", hWndOwner);
603
604 /* FIXME: use lpwstrReason */
605 if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE))
606 {
607 HANDLE hToken;
608 TOKEN_PRIVILEGES npr;
609
610 /* enable the shutdown privilege for the current process */
611 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
612 {
613 LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
614 npr.PrivilegeCount = 1;
615 npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
616 AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
617 CloseHandle(hToken);
618 }
619 ExitWindowsEx(EWX_REBOOT, uReason);
620 }
621
622 return 0;
623 }
624
625 /*************************************************************************
626 * LogoffWindowsDialog [SHELL32.54]
627 */
628
629 int WINAPI LogoffWindowsDialog(DWORD uFlags)
630 {
631 UNIMPLEMENTED;
632 ExitWindowsEx(EWX_LOGOFF, 0);
633 return 0;
634 }
635
636 /*************************************************************************
637 * RestartDialog [SHELL32.59]
638 */
639
640 int WINAPI RestartDialog(HWND hWndOwner, LPCWSTR lpstrReason, DWORD uFlags)
641 {
642 return RestartDialogEx(hWndOwner, lpstrReason, uFlags, 0);
643 }
644
645
646 /*************************************************************************
647 * ExitWindowsDialog [SHELL32.60]
648 *
649 * NOTES
650 * exported by ordinal
651 */
652 void WINAPI ExitWindowsDialog (HWND hWndOwner)
653 {
654 TRACE("(%p)\n", hWndOwner);
655
656 if (ConfirmDialog(hWndOwner, IDS_SHUTDOWN_PROMPT, IDS_SHUTDOWN_TITLE))
657 {
658 HANDLE hToken;
659 TOKEN_PRIVILEGES npr;
660
661 /* enable shutdown privilege for current process */
662 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
663 {
664 LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
665 npr.PrivilegeCount = 1;
666 npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
667 AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
668 CloseHandle(hToken);
669 }
670 ExitWindowsEx(EWX_SHUTDOWN, 0);
671 }
672 }