f55ef96854631796f34abacdf25819723343d678
[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 SetWindowTextA (hwnd, prfdp->lpstrTitle) ;
334 SetClassLongPtrW (hwnd, GCLP_HICON, (LPARAM)prfdp->hIcon) ;
335 SendMessageW (GetDlgItem (hwnd, 12297), STM_SETICON,
336 (WPARAM)LoadIconW (NULL, (LPCWSTR)IDI_WINLOGO), 0);
337 FillList (GetDlgItem (hwnd, 12298), NULL) ;
338 SetFocus (GetDlgItem (hwnd, 12298)) ;
339 return TRUE ;
340
341 case WM_COMMAND :
342 switch (LOWORD (wParam))
343 {
344 case IDOK :
345 {
346 HWND htxt = NULL ;
347 if ((ic = GetWindowTextLengthA (htxt = GetDlgItem (hwnd, 12298))))
348 {
349 psz = HeapAlloc( GetProcessHeap(), 0, (ic + 2) );
350 GetWindowTextA (htxt, psz, ic + 1) ;
351 pdir = HeapAlloc( GetProcessHeap(), 0, (ic + 2) );
352 if (pdir)
353 {
354 char * ptr;
355 strcpy(pdir, psz);
356 ptr = strrchr(pdir, '\\');
357 if(ptr)
358 ptr[0] = '\0';
359 }
360 if (ShellExecuteA(NULL, "open", psz, NULL, pdir, SW_SHOWNORMAL) < (HINSTANCE)33)
361 {
362 char *pszSysMsg = NULL ;
363 FormatMessageA (
364 FORMAT_MESSAGE_ALLOCATE_BUFFER |
365 FORMAT_MESSAGE_FROM_SYSTEM |
366 FORMAT_MESSAGE_IGNORE_INSERTS,
367 NULL, GetLastError (),
368 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
369 (LPSTR)&pszSysMsg, 0, NULL
370 ) ;
371 sprintf (szMsg, "Error: %s", pszSysMsg) ;
372 LocalFree ((HLOCAL)pszSysMsg) ;
373 MessageBoxA (hwnd, szMsg, "Nix", MB_OK | MB_ICONEXCLAMATION) ;
374
375 HeapFree(GetProcessHeap(), 0, psz);
376 HeapFree(GetProcessHeap(), 0, pdir);
377 SendMessageA (htxt, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
378 return TRUE ;
379 }
380 FillList (htxt, psz) ;
381 HeapFree(GetProcessHeap(), 0, psz);
382 HeapFree(GetProcessHeap(), 0, pdir);
383 EndDialog (hwnd, 0) ;
384 }
385 }
386
387 case IDCANCEL :
388 EndDialog (hwnd, 0) ;
389 return TRUE ;
390
391 case 12288 :
392 {
393 HMODULE hComdlg = NULL ;
394 LPFNOFN ofnProc = NULL ;
395 static char szFName[1024] = "", szFileTitle[256] = "", szInitDir[768] = "" ;
396 static OPENFILENAMEA ofn =
397 {
398 sizeof (OPENFILENAMEA),
399 NULL,
400 NULL,
401 "Executable Files\0*.exe\0All Files\0*.*\0\0\0\0",
402 NULL,
403 0,
404 0,
405 szFName,
406 1023,
407 szFileTitle,
408 255,
409 (LPCSTR)szInitDir,
410 "Browse",
411 OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_PATHMUSTEXIST,
412 0,
413 0,
414 NULL,
415 0,
416 (LPOFNHOOKPROC)NULL,
417 NULL
418 } ;
419
420 ofn.hwndOwner = hwnd ;
421
422 if (NULL == (hComdlg = LoadLibraryExA ("comdlg32", NULL, 0)))
423 {
424 MessageBoxA (hwnd, "Unable to display dialog box (LoadLibraryEx) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
425 return TRUE ;
426 }
427
428 if ((LPFNOFN)NULL == (ofnProc = (LPFNOFN)GetProcAddress (hComdlg, "GetOpenFileNameA")))
429 {
430 MessageBoxA (hwnd, "Unable to display dialog box (GetProcAddress) !", "Nix", MB_OK | MB_ICONEXCLAMATION) ;
431 return TRUE ;
432 }
433
434 ofnProc (&ofn) ;
435
436 SetFocus (GetDlgItem (hwnd, IDOK)) ;
437 SetWindowTextA (GetDlgItem (hwnd, 12298), szFName) ;
438 SendMessageA (GetDlgItem (hwnd, 12298), CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
439 SetFocus (GetDlgItem (hwnd, IDOK)) ;
440
441 FreeLibrary (hComdlg) ;
442
443 return TRUE ;
444 }
445 }
446 return TRUE ;
447 }
448 return FALSE ;
449 }
450
451 /* This grabs the MRU list from the registry and fills the combo for the "Run" dialog above */
452 static void FillList (HWND hCb, char *pszLatest)
453 {
454 HKEY hkey ;
455 /* char szDbgMsg[256] = "" ; */
456 char *pszList = NULL, *pszCmd = NULL, cMatch = 0, cMax = 0x60, szIndex[2] = "-" ;
457 DWORD icList = 0, icCmd = 0 ;
458 UINT Nix ;
459
460 SendMessageA (hCb, CB_RESETCONTENT, 0, 0) ;
461
462 if (ERROR_SUCCESS != RegCreateKeyExA (
463 HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU",
464 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL))
465 MessageBoxA (hCb, "Unable to open registry key !", "Nix", MB_OK) ;
466
467 RegQueryValueExA (hkey, "MRUList", NULL, NULL, NULL, &icList) ;
468
469 if (icList > 0)
470 {
471 pszList = HeapAlloc( GetProcessHeap(), 0, icList) ;
472 if (ERROR_SUCCESS != RegQueryValueExA (hkey, "MRUList", NULL, NULL, (LPBYTE)pszList, &icList))
473 MessageBoxA (hCb, "Unable to grab MRUList !", "Nix", MB_OK) ;
474 }
475 else
476 {
477 icList = 1 ;
478 pszList = HeapAlloc( GetProcessHeap(), 0, icList) ;
479 pszList[0] = 0 ;
480 }
481
482 for (Nix = 0 ; Nix < icList - 1 ; Nix++)
483 {
484 if (pszList[Nix] > cMax)
485 cMax = pszList[Nix] ;
486
487 szIndex[0] = pszList[Nix] ;
488
489 if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, NULL, &icCmd))
490 MessageBoxA (hCb, "Unable to grab size of index", "Nix", MB_OK) ;
491 if( pszCmd )
492 pszCmd = HeapReAlloc(GetProcessHeap(), 0, pszCmd, icCmd) ;
493 else
494 pszCmd = HeapAlloc(GetProcessHeap(), 0, icCmd) ;
495 if (ERROR_SUCCESS != RegQueryValueExA (hkey, szIndex, NULL, NULL, (LPBYTE)pszCmd, &icCmd))
496 MessageBoxA (hCb, "Unable to grab index", "Nix", MB_OK) ;
497
498 if (NULL != pszLatest)
499 {
500 if (!lstrcmpiA(pszCmd, pszLatest))
501 {
502 /*
503 sprintf (szDbgMsg, "Found existing (%d).\n", Nix) ;
504 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
505 */
506 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszCmd) ;
507 SetWindowTextA (hCb, pszCmd) ;
508 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
509
510 cMatch = pszList[Nix] ;
511 memmove (&pszList[1], pszList, Nix) ;
512 pszList[0] = cMatch ;
513 continue ;
514 }
515 }
516
517 if (26 != icList - 1 || icList - 2 != Nix || cMatch || NULL == pszLatest)
518 {
519 /*
520 sprintf (szDbgMsg, "Happily appending (%d).\n", Nix) ;
521 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
522 */
523 SendMessageA (hCb, CB_ADDSTRING, 0, (LPARAM)pszCmd) ;
524 if (!Nix)
525 {
526 SetWindowTextA (hCb, pszCmd) ;
527 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
528 }
529
530 }
531 else
532 {
533 /*
534 sprintf (szDbgMsg, "Doing loop thing.\n") ;
535 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
536 */
537 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
538 SetWindowTextA (hCb, pszLatest) ;
539 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
540
541 cMatch = pszList[Nix] ;
542 memmove (&pszList[1], pszList, Nix) ;
543 pszList[0] = cMatch ;
544 szIndex[0] = cMatch ;
545 RegSetValueExA (hkey, szIndex, 0, REG_SZ, (LPBYTE)pszLatest, strlen (pszLatest) + 1) ;
546 }
547 }
548
549 if (!cMatch && NULL != pszLatest)
550 {
551 /*
552 sprintf (szDbgMsg, "Simply inserting (increasing list).\n") ;
553 MessageBoxA (hCb, szDbgMsg, "Nix", MB_OK) ;
554 */
555 SendMessageA (hCb, CB_INSERTSTRING, 0, (LPARAM)pszLatest) ;
556 SetWindowTextA (hCb, pszLatest) ;
557 SendMessageA (hCb, CB_SETEDITSEL, 0, MAKELPARAM (0, -1)) ;
558
559 cMatch = ++cMax ;
560 if( pszList )
561 pszList = HeapReAlloc(GetProcessHeap(), 0, pszList, ++icList) ;
562 else
563 pszList = HeapAlloc(GetProcessHeap(), 0, ++icList) ;
564 memmove (&pszList[1], pszList, icList - 1) ;
565 pszList[0] = cMatch ;
566 szIndex[0] = cMatch ;
567 RegSetValueExA (hkey, szIndex, 0, REG_SZ, (LPBYTE)pszLatest, strlen (pszLatest) + 1) ;
568 }
569
570 RegSetValueExA (hkey, "MRUList", 0, REG_SZ, (LPBYTE)pszList, strlen (pszList) + 1) ;
571
572 HeapFree( GetProcessHeap(), 0, pszCmd) ;
573 HeapFree( GetProcessHeap(), 0, pszList) ;
574 }
575
576
577 /*************************************************************************
578 * ConfirmDialog [internal]
579 *
580 * Put up a confirm box, return TRUE if the user confirmed
581 */
582 static BOOL ConfirmDialog(HWND hWndOwner, UINT PromptId, UINT TitleId)
583 {
584 WCHAR Prompt[256];
585 WCHAR Title[256];
586
587 LoadStringW(shell32_hInstance, PromptId, Prompt, sizeof(Prompt) / sizeof(WCHAR));
588 LoadStringW(shell32_hInstance, TitleId, Title, sizeof(Title) / sizeof(WCHAR));
589 return MessageBoxW(hWndOwner, Prompt, Title, MB_YESNO|MB_ICONQUESTION) == IDYES;
590 }
591
592
593 /*************************************************************************
594 * RestartDialogEx [SHELL32.730]
595 */
596
597 int WINAPI RestartDialogEx(HWND hWndOwner, LPCWSTR lpwstrReason, DWORD uFlags, DWORD uReason)
598 {
599 TRACE("(%p)\n", hWndOwner);
600
601 /* FIXME: use lpwstrReason */
602 if (ConfirmDialog(hWndOwner, IDS_RESTART_PROMPT, IDS_RESTART_TITLE))
603 {
604 HANDLE hToken;
605 TOKEN_PRIVILEGES npr;
606
607 /* enable the shutdown privilege for the current process */
608 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
609 {
610 LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
611 npr.PrivilegeCount = 1;
612 npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
613 AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
614 CloseHandle(hToken);
615 }
616 ExitWindowsEx(EWX_REBOOT, uReason);
617 }
618
619 return 0;
620 }
621
622 /*************************************************************************
623 * LogoffWindowsDialog [SHELL32.54]
624 */
625
626 int WINAPI LogoffWindowsDialog(DWORD uFlags)
627 {
628 UNIMPLEMENTED;
629 ExitWindowsEx(EWX_LOGOFF, 0);
630 return 0;
631 }
632
633 /*************************************************************************
634 * RestartDialog [SHELL32.59]
635 */
636
637 int WINAPI RestartDialog(HWND hWndOwner, LPCWSTR lpstrReason, DWORD uFlags)
638 {
639 return RestartDialogEx(hWndOwner, lpstrReason, uFlags, 0);
640 }
641
642
643 /*************************************************************************
644 * ExitWindowsDialog [SHELL32.60]
645 *
646 * NOTES
647 * exported by ordinal
648 */
649 void WINAPI ExitWindowsDialog (HWND hWndOwner)
650 {
651 TRACE("(%p)\n", hWndOwner);
652
653 if (ConfirmDialog(hWndOwner, IDS_SHUTDOWN_PROMPT, IDS_SHUTDOWN_TITLE))
654 {
655 HANDLE hToken;
656 TOKEN_PRIVILEGES npr;
657
658 /* enable shutdown privilege for current process */
659 if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken))
660 {
661 LookupPrivilegeValueA(0, "SeShutdownPrivilege", &npr.Privileges[0].Luid);
662 npr.PrivilegeCount = 1;
663 npr.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
664 AdjustTokenPrivileges(hToken, FALSE, &npr, 0, 0, 0);
665 CloseHandle(hToken);
666 }
667 ExitWindowsEx(EWX_SHUTDOWN, 0);
668 }
669 }