xref: /reactos/dll/cpl/sysdm/startrec.c (revision 84ccccab)
1 /*
2  * PROJECT:     ReactOS System Control Panel Applet
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        dll/cpl/sysdm/startrec.c
5  * PURPOSE:     Computer settings for startup and recovery
6  * COPYRIGHT:   Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
7  *              Copyright 2006 Christoph von Wittich <Christoph@ApiViewer.de>
8  *              Copyright 2007 Johannes Anderwald <johannes.anderwald@reactos.org>
9  */
10 
11 #include "precomp.h"
12 
13 #include <shlwapi.h>
14 #include <setupapi.h>
15 
16 typedef struct _STARTINFO
17 {
18     WCHAR szFreeldrIni[MAX_PATH + 15];
19     WCHAR szDumpFile[MAX_PATH];
20     WCHAR szMinidumpDir[MAX_PATH];
21     DWORD dwCrashDumpEnabled;
22     INT iFreeLdrIni;
23 } STARTINFO, *PSTARTINFO;
24 
25 BOOL SaveRecoveryOptions;
26 
27 static VOID
28 SetTimeout(HWND hwndDlg, INT Timeout)
29 {
30     if (Timeout == 0)
31     {
32         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECLISTUPDWN), FALSE);
33         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECLISTEDIT), FALSE);
34     }
35     else
36     {
37         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECLISTUPDWN), TRUE);
38         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECLISTEDIT), TRUE);
39     }
40     SendDlgItemMessageW(hwndDlg, IDC_STRRECLISTUPDWN, UDM_SETRANGE, (WPARAM) 0, (LPARAM) MAKELONG((short) 999, 0));
41     SendDlgItemMessageW(hwndDlg, IDC_STRRECLISTUPDWN, UDM_SETPOS, (WPARAM) 0, (LPARAM) MAKELONG((short) Timeout, 0));
42 }
43 
44 static VOID
45 SetRecoveryTimeout(HWND hwndDlg, INT Timeout)
46 {
47     if (Timeout == 0)
48     {
49         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECRECUPDWN), FALSE);
50         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECRECEDIT), FALSE);
51     }
52     else
53     {
54         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECRECUPDWN), TRUE);
55         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECRECEDIT), TRUE);
56     }
57     SendDlgItemMessageW(hwndDlg, IDC_STRRECRECUPDWN, UDM_SETRANGE, (WPARAM) 0, (LPARAM) MAKELONG((short) 999, 0));
58     SendDlgItemMessageW(hwndDlg, IDC_STRRECRECUPDWN, UDM_SETPOS, (WPARAM) 0, (LPARAM) MAKELONG((short) Timeout, 0));
59 }
60 
61 
62 static DWORD
63 GetSystemDrive(WCHAR **szSystemDrive)
64 {
65     DWORD dwBufSize;
66 
67     /* Get Path to freeldr.ini or boot.ini */
68     *szSystemDrive = HeapAlloc(GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR));
69     if (*szSystemDrive != NULL)
70     {
71         dwBufSize = GetEnvironmentVariableW(L"SystemDrive", *szSystemDrive, MAX_PATH);
72         if (dwBufSize > MAX_PATH)
73         {
74             WCHAR *szTmp;
75             DWORD dwBufSize2;
76 
77             szTmp = HeapReAlloc(GetProcessHeap(), 0, *szSystemDrive, dwBufSize * sizeof(WCHAR));
78             if (szTmp == NULL)
79                 goto FailGetSysDrive;
80 
81             *szSystemDrive = szTmp;
82 
83             dwBufSize2 = GetEnvironmentVariableW(L"SystemDrive", *szSystemDrive, dwBufSize);
84             if (dwBufSize2 > dwBufSize || dwBufSize2 == 0)
85                 goto FailGetSysDrive;
86         }
87         else if (dwBufSize == 0)
88         {
89 FailGetSysDrive:
90             HeapFree(GetProcessHeap(), 0, *szSystemDrive);
91             *szSystemDrive = NULL;
92             return 0;
93         }
94 
95         return dwBufSize;
96     }
97 
98     return 0;
99 }
100 
101 static PBOOTRECORD
102 ReadFreeldrSection(HINF hInf, WCHAR *szSectionName)
103 {
104     PBOOTRECORD pRecord;
105     INFCONTEXT InfContext;
106     WCHAR szName[MAX_PATH];
107     WCHAR szValue[MAX_PATH];
108     DWORD LineLength;
109 
110     if (!SetupFindFirstLineW(hInf,
111                             szSectionName,
112                             NULL,
113                             &InfContext))
114     {
115         /* Failed to find section */
116         return NULL;
117     }
118 
119     pRecord = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOTRECORD));
120     if (pRecord == NULL)
121     {
122         return NULL;
123     }
124 
125     wcscpy(pRecord->szSectionName, szSectionName);
126 
127     do
128     {
129         if (!SetupGetStringFieldW(&InfContext,
130                                   0,
131                                   szName,
132                                   sizeof(szName) / sizeof(WCHAR),
133                                   &LineLength))
134         {
135             break;
136         }
137 
138         if (!SetupGetStringFieldW(&InfContext,
139                                   1,
140                                   szValue,
141                                   sizeof(szValue) / sizeof(WCHAR),
142                                   &LineLength))
143         {
144             break;
145         }
146 
147         if (!_wcsnicmp(szName, L"BootType", 8))
148         {
149             if (!_wcsnicmp(szValue, L"ReactOS", 7))
150             {
151                 // FIXME: Store as enum
152                 pRecord->BootType = 1;
153             }
154             else
155             {
156                 pRecord->BootType = 0;
157             }
158         }
159         else if (!_wcsnicmp(szName, L"SystemPath", 10))
160         {
161             wcscpy(pRecord->szBootPath, szValue);
162         }
163         else if (!_wcsnicmp(szName, L"Options", 7))
164         {
165             // FIXME: Store flags as values
166             wcscpy(pRecord->szOptions, szValue);
167         }
168 
169     }
170     while (SetupFindNextLine(&InfContext, &InfContext));
171 
172     return pRecord;
173 }
174 
175 
176 static INT
177 LoadFreeldrSettings(HINF hInf, HWND hwndDlg)
178 {
179     INFCONTEXT InfContext;
180     PBOOTRECORD pRecord;
181     WCHAR szDefaultOs[MAX_PATH];
182     WCHAR szName[MAX_PATH];
183     WCHAR szValue[MAX_PATH];
184     DWORD LineLength;
185     DWORD TimeOut;
186     LRESULT lResult;
187 
188     if (!SetupFindFirstLineW(hInf,
189                            L"FREELOADER",
190                            L"DefaultOS",
191                            &InfContext))
192     {
193         /* Failed to find default os */
194         return FALSE;
195     }
196 
197     if (!SetupGetStringFieldW(&InfContext,
198                              1,
199                              szDefaultOs,
200                              sizeof(szDefaultOs) / sizeof(WCHAR),
201                              &LineLength))
202     {
203         /* No key */
204         return FALSE;
205     }
206 
207     if (!SetupFindFirstLineW(hInf,
208                            L"FREELOADER",
209                            L"TimeOut",
210                            &InfContext))
211     {
212         /* Expected to find timeout value */
213         return FALSE;
214     }
215 
216 
217     if (!SetupGetIntField(&InfContext,
218                           1,
219                           (PINT)&TimeOut))
220     {
221         /* Failed to retrieve timeout */
222         return FALSE;
223     }
224 
225     if (!SetupFindFirstLineW(hInf,
226                            L"Operating Systems",
227                            NULL,
228                            &InfContext))
229     {
230        /* Expected list of operating systems */
231        return FALSE;
232     }
233 
234     do
235     {
236         if (!SetupGetStringFieldW(&InfContext,
237                                  0,
238                                  szName,
239                                  sizeof(szName) / sizeof(WCHAR),
240                                  &LineLength))
241         {
242             /* The ini file is messed up */
243             return FALSE;
244         }
245 
246         if (!SetupGetStringFieldW(&InfContext,
247                                  1,
248                                  szValue,
249                                  sizeof(szValue) / sizeof(WCHAR),
250                                  &LineLength))
251         {
252             /* The ini file is messed up */
253             return FALSE;
254         }
255 
256         pRecord = ReadFreeldrSection(hInf, szName);
257         if (pRecord)
258         {
259             lResult = SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValue);
260             if (lResult != CB_ERR)
261             {
262                 SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)pRecord);
263                 if (!wcscmp(szDefaultOs, szName))
264                 {
265                     /* We store the friendly name as key */
266                     wcscpy(szDefaultOs, szValue);
267                 }
268             }
269             else
270             {
271                HeapFree(GetProcessHeap(), 0, pRecord);
272             }
273         }
274     }
275     while (SetupFindNextLine(&InfContext, &InfContext));
276 
277     /* Find default os in list */
278     lResult = SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_FINDSTRING, (WPARAM)-1, (LPARAM)szDefaultOs);
279     if (lResult != CB_ERR)
280     {
281        /* Set cur sel */
282        SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
283     }
284 
285     if(TimeOut)
286     {
287         SendDlgItemMessageW(hwndDlg, IDC_STRECLIST, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
288     }
289 
290     SetTimeout(hwndDlg, TimeOut);
291 
292     return TRUE;
293 }
294 
295 static INT
296 LoadBootSettings(HINF hInf, HWND hwndDlg)
297 {
298     INFCONTEXT InfContext;
299     WCHAR szName[MAX_PATH];
300     WCHAR szValue[MAX_PATH];
301     DWORD LineLength;
302     DWORD TimeOut = 0;
303     WCHAR szDefaultOS[MAX_PATH];
304     WCHAR szOptions[MAX_PATH];
305     PBOOTRECORD pRecord;
306     LRESULT lResult;
307 
308     if(!SetupFindFirstLineW(hInf,
309                            L"boot loader",
310                            NULL,
311                            &InfContext))
312     {
313         return FALSE;
314     }
315 
316     do
317     {
318         if (!SetupGetStringFieldW(&InfContext,
319                                  0,
320                                  szName,
321                                  sizeof(szName) / sizeof(WCHAR),
322                                  &LineLength))
323         {
324             return FALSE;
325         }
326 
327         if (!SetupGetStringFieldW(&InfContext,
328                                  1,
329                                  szValue,
330                                  sizeof(szValue) / sizeof(WCHAR),
331                                  &LineLength))
332         {
333             return FALSE;
334         }
335 
336         if (!_wcsnicmp(szName, L"timeout", 7))
337         {
338             TimeOut = _wtoi(szValue);
339         }
340 
341         if (!_wcsnicmp(szName, L"default", 7))
342         {
343             wcscpy(szDefaultOS, szValue);
344         }
345 
346     }
347     while (SetupFindNextLine(&InfContext, &InfContext));
348 
349     if (!SetupFindFirstLineW(hInf,
350                             L"operating systems",
351                             NULL,
352                             &InfContext))
353     {
354         /* Failed to find operating systems section */
355         return FALSE;
356     }
357 
358     do
359     {
360         if (!SetupGetStringFieldW(&InfContext,
361                                  0,
362                                  szName,
363                                  sizeof(szName) / sizeof(WCHAR),
364                                  &LineLength))
365         {
366             return FALSE;
367         }
368 
369         if (!SetupGetStringFieldW(&InfContext,
370                                  1,
371                                  szValue,
372                                  sizeof(szValue) / sizeof(WCHAR),
373                                  &LineLength))
374         {
375             return FALSE;
376         }
377 
378         SetupGetStringFieldW(&InfContext,
379                             2,
380                             szOptions,
381                             sizeof(szOptions) / sizeof(WCHAR),
382                             &LineLength);
383 
384         pRecord = (PBOOTRECORD) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BOOTRECORD));
385         if (pRecord)
386         {
387             pRecord->BootType = 0;
388             wcscpy(pRecord->szBootPath, szName);
389             wcscpy(pRecord->szSectionName, szValue);
390             wcscpy(pRecord->szOptions, szOptions);
391 
392             if (!wcscmp(szName, szDefaultOS))
393             {
394                 /* ms boot ini stores the path not the friendly name */
395                 wcscpy(szDefaultOS, szValue);
396             }
397 
398             lResult = SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_ADDSTRING, (WPARAM)0, (LPARAM)szValue);
399             if (lResult != CB_ERR)
400             {
401                 SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_SETITEMDATA, (WPARAM)lResult, (LPARAM)pRecord);
402             }
403             else
404             {
405                HeapFree(GetProcessHeap(), 0, pRecord);
406             }
407         }
408 
409     }
410     while (SetupFindNextLine(&InfContext, &InfContext));
411 
412     /* Find default os in list */
413     lResult = SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_FINDSTRING, (WPARAM)0, (LPARAM)szDefaultOS);
414     if (lResult != CB_ERR)
415     {
416        /* Set cur sel */
417        SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_SETCURSEL, (WPARAM)lResult, (LPARAM)0);
418     }
419 
420     if(TimeOut)
421     {
422         SendDlgItemMessageW(hwndDlg, IDC_STRECLIST, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
423     }
424 
425     SetTimeout(hwndDlg, TimeOut);
426 
427     return TRUE;
428 }
429 
430 static VOID
431 DeleteBootRecords(HWND hwndDlg)
432 {
433     LRESULT lIndex;
434     LONG index;
435     PBOOTRECORD pRecord;
436 
437     lIndex = SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_GETCOUNT, (WPARAM)0, (LPARAM)0);
438     if (lIndex == CB_ERR)
439         return;
440 
441     for (index = 0; index <lIndex; index++)
442     {
443         pRecord = (PBOOTRECORD) SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_GETITEMDATA, (WPARAM)index, (LPARAM)0);
444         if ((INT_PTR)pRecord != CB_ERR)
445         {
446             HeapFree(GetProcessHeap(), 0, pRecord);
447         }
448     }
449 
450     SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_RESETCONTENT, (WPARAM)0, (LPARAM)0);
451 }
452 
453 static LRESULT
454 LoadOSList(HWND hwndDlg, PSTARTINFO pStartInfo)
455 {
456     DWORD dwBufSize;
457     WCHAR *szSystemDrive;
458     HINF hInf;
459 
460     dwBufSize = GetSystemDrive(&szSystemDrive);
461     if (dwBufSize == 0)
462         return FALSE;
463 
464     wcscpy(pStartInfo->szFreeldrIni, szSystemDrive);
465     wcscat(pStartInfo->szFreeldrIni, L"\\freeldr.ini");
466 
467     if (PathFileExistsW(pStartInfo->szFreeldrIni))
468     {
469         /* Free resource previously allocated by GetSystemDrive() */
470         HeapFree(GetProcessHeap(), 0, szSystemDrive);
471         /* freeldr.ini exists */
472         hInf = SetupOpenInfFileW(pStartInfo->szFreeldrIni,
473                                 NULL,
474                                 INF_STYLE_OLDNT,
475                                 NULL);
476 
477         if (hInf != INVALID_HANDLE_VALUE)
478         {
479             LoadFreeldrSettings(hInf, hwndDlg);
480             SetupCloseInfFile(hInf);
481             pStartInfo->iFreeLdrIni = 1;
482             return TRUE;
483         }
484         return FALSE;
485     }
486 
487     /* Try loading boot.ini settings */
488     wcscpy(pStartInfo->szFreeldrIni, szSystemDrive);
489     wcscat(pStartInfo->szFreeldrIni, L"\\boot.ini");
490 
491     /* Free resource previously allocated by GetSystemDrive() */
492     HeapFree(GetProcessHeap(), 0, szSystemDrive);
493 
494     if (PathFileExistsW(pStartInfo->szFreeldrIni))
495     {
496         /* Load boot.ini settings */
497         hInf = SetupOpenInfFileW(pStartInfo->szFreeldrIni,
498                                 NULL,
499                                 INF_STYLE_OLDNT,
500                                 NULL);
501 
502         if (hInf != INVALID_HANDLE_VALUE)
503         {
504             LoadBootSettings(hInf, hwndDlg);
505             SetupCloseInfFile(hInf);
506             pStartInfo->iFreeLdrIni = 2;
507             return TRUE;
508         }
509 
510         return FALSE;
511     }
512 
513     return FALSE;
514 }
515 
516 static VOID
517 SetCrashDlgItems(HWND hwnd, PSTARTINFO pStartInfo)
518 {
519     if (pStartInfo->dwCrashDumpEnabled == 0)
520     {
521         /* No crash information required */
522         EnableWindow(GetDlgItem(hwnd, IDC_STRRECDUMPFILE), FALSE);
523         EnableWindow(GetDlgItem(hwnd, IDC_STRRECOVERWRITE), FALSE);
524     }
525     else if (pStartInfo->dwCrashDumpEnabled == 3)
526     {
527         /* Minidump type */
528         EnableWindow(GetDlgItem(hwnd, IDC_STRRECDUMPFILE), TRUE);
529         EnableWindow(GetDlgItem(hwnd, IDC_STRRECOVERWRITE), FALSE);
530         SendMessageW(GetDlgItem(hwnd, IDC_STRRECDUMPFILE), WM_SETTEXT, (WPARAM)0, (LPARAM)pStartInfo->szMinidumpDir);
531     }
532     else if (pStartInfo->dwCrashDumpEnabled == 1 || pStartInfo->dwCrashDumpEnabled == 2)
533     {
534         /* Kernel or complete dump */
535         EnableWindow(GetDlgItem(hwnd, IDC_STRRECDUMPFILE), TRUE);
536         EnableWindow(GetDlgItem(hwnd, IDC_STRRECOVERWRITE), TRUE);
537         SendMessageW(GetDlgItem(hwnd, IDC_STRRECDUMPFILE), WM_SETTEXT, (WPARAM)0, (LPARAM)pStartInfo->szDumpFile);
538     }
539     SendDlgItemMessageW(hwnd, IDC_STRRECDEBUGCOMBO, CB_SETCURSEL, (WPARAM)pStartInfo->dwCrashDumpEnabled, (LPARAM)0);
540 }
541 
542 static VOID
543 WriteStartupRecoveryOptions(HWND hwndDlg, PSTARTINFO pStartInfo)
544 {
545     HKEY hKey;
546     DWORD lResult;
547 
548     lResult = (DWORD)RegCreateKeyExW(HKEY_LOCAL_MACHINE,
549                                     L"System\\CurrentControlSet\\Control\\CrashControl",
550                                     0,
551                                     NULL,
552                                     REG_OPTION_NON_VOLATILE,
553                                     KEY_WRITE,
554                                     NULL,
555                                     &hKey,
556                                     NULL);
557     if (lResult != ERROR_SUCCESS)
558     {
559          /* Failed to open key */
560         SetLastError(lResult);
561         ShowLastWin32Error(hwndDlg);
562 
563         return;
564     }
565 
566     lResult = (DWORD) SendDlgItemMessage(hwndDlg, IDC_STRRECWRITEEVENT, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
567     RegSetValueExW(hKey, L"LogEvent", 0, REG_DWORD, (LPBYTE)&lResult, sizeof(lResult));
568 
569     lResult = (DWORD) SendDlgItemMessage(hwndDlg, IDC_STRRECSENDALERT, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
570     RegSetValueExW(hKey, L"SendAlert", 0, REG_DWORD, (LPBYTE)&lResult, sizeof(lResult));
571 
572     lResult = (DWORD) SendDlgItemMessage(hwndDlg, IDC_STRRECRESTART, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
573     RegSetValueExW(hKey, L"AutoReboot", 0, REG_DWORD, (LPBYTE)&lResult, sizeof(lResult));
574 
575     lResult = (DWORD) SendDlgItemMessage(hwndDlg, IDC_STRRECOVERWRITE, BM_GETCHECK, (WPARAM)0, (LPARAM)0);
576     RegSetValueExW(hKey, L"Overwrite", 0, REG_DWORD, (LPBYTE)&lResult, sizeof(lResult));
577 
578 
579     if (pStartInfo->dwCrashDumpEnabled == 1 || pStartInfo->dwCrashDumpEnabled == 2)
580     {
581         SendDlgItemMessage(hwndDlg, IDC_STRRECDUMPFILE, WM_GETTEXT, (WPARAM)sizeof(pStartInfo->szDumpFile) / sizeof(WCHAR), (LPARAM)pStartInfo->szDumpFile);
582         RegSetValueExW(hKey, L"DumpFile", 0, REG_EXPAND_SZ, (LPBYTE)pStartInfo->szDumpFile, (wcslen(pStartInfo->szDumpFile) + 1) * sizeof(WCHAR));
583     }
584     else if (pStartInfo->dwCrashDumpEnabled == 3)
585     {
586         SendDlgItemMessage(hwndDlg, IDC_STRRECDUMPFILE, WM_GETTEXT, (WPARAM)sizeof(pStartInfo->szDumpFile) / sizeof(WCHAR), (LPARAM)pStartInfo->szDumpFile);
587         RegSetValueExW(hKey, L"MinidumpDir", 0, REG_EXPAND_SZ, (LPBYTE)pStartInfo->szDumpFile, (wcslen(pStartInfo->szDumpFile) + 1) * sizeof(WCHAR));
588     }
589 
590     RegSetValueExW(hKey, L"CrashDumpEnabled", 0, REG_DWORD, (LPBYTE)&pStartInfo->dwCrashDumpEnabled, sizeof(pStartInfo->dwCrashDumpEnabled));
591     RegCloseKey(hKey);
592 }
593 
594 static VOID
595 LoadRecoveryOptions(HWND hwndDlg, PSTARTINFO pStartInfo)
596 {
597     HKEY hKey;
598     WCHAR szName[MAX_PATH];
599     DWORD dwValue, dwValueLength, dwType, dwResult;
600 
601     dwResult = (DWORD)RegCreateKeyExW(HKEY_LOCAL_MACHINE,
602                                       L"System\\CurrentControlSet\\Control\\CrashControl",
603                                       0,
604                                       NULL,
605                                       REG_OPTION_NON_VOLATILE,
606                                       KEY_READ,
607                                       NULL,
608                                       &hKey,
609                                       NULL);
610     if (dwResult != ERROR_SUCCESS)
611     {
612         /* Failed to open key */
613         SetLastError(dwResult);
614         ShowLastWin32Error(hwndDlg);
615 
616         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECWRITEEVENT), FALSE);
617         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECSENDALERT), FALSE);
618         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECRESTART), FALSE);
619         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECDEBUGCOMBO), FALSE);
620         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECDUMPFILE), FALSE);
621         EnableWindow(GetDlgItem(hwndDlg, IDC_STRRECOVERWRITE), FALSE);
622 
623         SaveRecoveryOptions = FALSE;
624         return;
625     }
626 
627     dwValueLength = sizeof(DWORD);
628     if (RegQueryValueExW(hKey, L"LogEvent", NULL, &dwType, (LPBYTE)&dwValue, &dwValueLength) == ERROR_SUCCESS && dwType == REG_DWORD && dwValue)
629         SendDlgItemMessageW(hwndDlg, IDC_STRRECWRITEEVENT, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
630 
631     dwValueLength = sizeof(DWORD);
632     if (RegQueryValueExW(hKey, L"SendAlert", NULL, &dwType, (LPBYTE)&dwValue, &dwValueLength) == ERROR_SUCCESS && dwType == REG_DWORD && dwValue)
633         SendDlgItemMessageW(hwndDlg, IDC_STRRECSENDALERT, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
634 
635     dwValueLength = sizeof(DWORD);
636     if (RegQueryValueExW(hKey, L"AutoReboot", NULL, &dwType, (LPBYTE)&dwValue, &dwValueLength) == ERROR_SUCCESS && dwType == REG_DWORD && dwValue)
637         SendDlgItemMessageW(hwndDlg, IDC_STRRECRESTART, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
638 
639     dwValueLength = sizeof(DWORD);
640     if (RegQueryValueExW(hKey, L"Overwrite", NULL, &dwType, (LPBYTE)&dwValue, &dwValueLength) == ERROR_SUCCESS && dwType == REG_DWORD && dwValue)
641         SendDlgItemMessageW(hwndDlg, IDC_STRRECOVERWRITE, BM_SETCHECK, (WPARAM)BST_CHECKED, (LPARAM)0);
642 
643     dwValueLength = sizeof(DWORD);
644     if (RegQueryValueExW(hKey, L"CrashDumpEnabled", NULL, &dwType, (LPBYTE)&dwValue, &dwValueLength) == ERROR_SUCCESS && dwType == REG_DWORD && dwValue)
645         pStartInfo->dwCrashDumpEnabled = dwValue;
646 
647    dwValueLength = sizeof(pStartInfo->szDumpFile);
648    if (RegQueryValueExW(hKey, L"DumpFile", NULL, &dwType, (LPBYTE)pStartInfo->szDumpFile, &dwValueLength) != ERROR_SUCCESS)
649        pStartInfo->szDumpFile[0] = L'\0';
650 
651     dwValueLength = sizeof(pStartInfo->szMinidumpDir);
652     if (RegQueryValueExW(hKey, L"MinidumpDir", NULL, &dwType, (LPBYTE)pStartInfo->szMinidumpDir, &dwValueLength) != ERROR_SUCCESS)
653         pStartInfo->szMinidumpDir[0] = L'\0';
654 
655     if (LoadStringW(hApplet, IDS_NO_DUMP, szName, sizeof(szName) / sizeof(WCHAR)))
656     {
657         szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0';
658         SendDlgItemMessageW(hwndDlg, IDC_STRRECDEBUGCOMBO, CB_ADDSTRING, (WPARAM)0, (LPARAM) szName);
659     }
660 
661     if (LoadStringW(hApplet, IDS_FULL_DUMP, szName, sizeof(szName) / sizeof(WCHAR)))
662     {
663         szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0';
664         SendDlgItemMessageW(hwndDlg, IDC_STRRECDEBUGCOMBO, CB_ADDSTRING, (WPARAM)0, (LPARAM) szName);
665     }
666 
667     if (LoadStringW(hApplet, IDS_KERNEL_DUMP, szName, sizeof(szName) / sizeof(WCHAR)))
668     {
669         szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0';
670         SendDlgItemMessageW(hwndDlg, IDC_STRRECDEBUGCOMBO, CB_ADDSTRING, (WPARAM)0, (LPARAM) szName);
671     }
672 
673     if (LoadStringW(hApplet, IDS_MINI_DUMP, szName, sizeof(szName) / sizeof(WCHAR)))
674     {
675         szName[(sizeof(szName)/sizeof(WCHAR))-1] = L'\0';
676         SendDlgItemMessageW(hwndDlg, IDC_STRRECDEBUGCOMBO, CB_ADDSTRING, (WPARAM)0, (LPARAM) szName);
677     }
678 
679     SetCrashDlgItems(hwndDlg, pStartInfo);
680     RegCloseKey(hKey);
681 
682     SaveRecoveryOptions = TRUE;
683 }
684 
685 
686 /* Property page dialog callback */
687 INT_PTR CALLBACK
688 StartRecDlgProc(HWND hwndDlg,
689                 UINT uMsg,
690                 WPARAM wParam,
691                 LPARAM lParam)
692 {
693     PSTARTINFO pStartInfo;
694     PBOOTRECORD pRecord;
695     int iTimeout;
696     LRESULT lResult;
697     WCHAR szTimeout[10];
698 
699     UNREFERENCED_PARAMETER(lParam);
700 
701     pStartInfo = (PSTARTINFO)GetWindowLongPtr(hwndDlg, DWLP_USER);
702 
703     switch(uMsg)
704     {
705         case WM_INITDIALOG:
706             pStartInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(STARTINFO));
707             SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pStartInfo);
708 
709             LoadRecoveryOptions(hwndDlg, pStartInfo);
710             SetRecoveryTimeout(hwndDlg, 0);
711             return LoadOSList(hwndDlg, pStartInfo);
712 
713         case WM_DESTROY:
714             DeleteBootRecords(hwndDlg);
715             HeapFree(GetProcessHeap(), 0, pStartInfo);
716             break;
717 
718         case WM_COMMAND:
719             switch(LOWORD(wParam))
720             {
721                 case IDC_STRRECEDIT:
722                     ShellExecuteW(0, L"open", L"notepad", pStartInfo->szFreeldrIni, NULL, SW_SHOWNORMAL);
723                     // FIXME: Use CreateProcess and wait untill finished
724                     //  DeleteBootRecords(hwndDlg);
725                     //  LoadOSList(hwndDlg);
726                     break;
727 
728                 case IDOK:
729                     /* Save timeout */
730                     if (SendDlgItemMessage(hwndDlg, IDC_STRECLIST, BM_GETCHECK, (WPARAM)0, (LPARAM)0) == BST_CHECKED)
731                         iTimeout = SendDlgItemMessage(hwndDlg, IDC_STRRECLISTUPDWN, UDM_GETPOS, (WPARAM)0, (LPARAM)0);
732                     else
733                         iTimeout = 0;
734                     swprintf(szTimeout, L"%i", iTimeout);
735 
736                     lResult = SendDlgItemMessageW(hwndDlg, IDC_STRECOSCOMBO, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
737                     if (lResult == CB_ERR)
738                     {
739                         /* ? */
740                         DeleteBootRecords(hwndDlg);
741                         return TRUE;
742                     }
743 
744                     pRecord = (PBOOTRECORD) SendDlgItemMessage(hwndDlg, IDC_STRECOSCOMBO, CB_GETITEMDATA, (WPARAM)lResult, (LPARAM)0);
745 
746                     if ((INT_PTR)pRecord != CB_ERR)
747                     {
748                         if (pStartInfo->iFreeLdrIni == 1) // FreeLdrIni style
749                         {
750                             /* Set default timeout */
751                             WritePrivateProfileStringW(L"FREELOADER",
752                                                       L"TimeOut",
753                                                       szTimeout,
754                                                       pStartInfo->szFreeldrIni);
755                             /* Set default OS */
756                             WritePrivateProfileStringW(L"FREELOADER",
757                                                       L"DefaultOS",
758                                                       pRecord->szSectionName,
759                                                       pStartInfo->szFreeldrIni);
760 
761                         }
762                         else if (pStartInfo->iFreeLdrIni == 2) // BootIni style
763                         {
764                             /* Set default timeout */
765                             WritePrivateProfileStringW(L"boot loader",
766                                                       L"timeout",
767                                                       szTimeout,
768                                                       pStartInfo->szFreeldrIni);
769                             /* Set default OS */
770                             WritePrivateProfileStringW(L"boot loader",
771                                                       L"default",
772                                                       pRecord->szBootPath,
773                                                       pStartInfo->szFreeldrIni);
774 
775                         }
776                     }
777 
778                     if (SaveRecoveryOptions)
779                     {
780                         WriteStartupRecoveryOptions(hwndDlg, pStartInfo);
781                     }
782 
783                     EndDialog(hwndDlg,
784                               LOWORD(wParam));
785                     return TRUE;
786 
787                 case IDCANCEL:
788                     EndDialog(hwndDlg,
789                               LOWORD(wParam));
790                     return TRUE;
791 
792                 case IDC_STRECLIST:
793                     if (SendDlgItemMessage(hwndDlg, IDC_STRECLIST, BM_GETCHECK, (WPARAM)0, (LPARAM)0) == BST_CHECKED)
794                         SetTimeout(hwndDlg, 30);
795                     else
796                         SetTimeout(hwndDlg, 0);
797                     break;
798 
799                 case IDC_STRRECREC:
800                     if (SendDlgItemMessage(hwndDlg, IDC_STRRECREC, BM_GETCHECK, (WPARAM)0, (LPARAM)0) == BST_CHECKED)
801                         SetRecoveryTimeout(hwndDlg, 30);
802                     else
803                         SetRecoveryTimeout(hwndDlg, 0);
804                     break;
805 
806                 case IDC_STRRECDEBUGCOMBO:
807                     if (HIWORD(wParam) == CBN_SELCHANGE)
808                     {
809                         LRESULT lResult;
810 
811                         lResult = SendDlgItemMessage(hwndDlg, IDC_STRRECDEBUGCOMBO, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
812                         if (lResult != CB_ERR && lResult != (LRESULT)pStartInfo->dwCrashDumpEnabled)
813                         {
814                             if (pStartInfo->dwCrashDumpEnabled == 1 || pStartInfo->dwCrashDumpEnabled == 2)
815                             {
816                                 SendDlgItemMessageW(hwndDlg, IDC_STRRECDUMPFILE, WM_GETTEXT, (WPARAM)sizeof(pStartInfo->szDumpFile) / sizeof(WCHAR), (LPARAM)pStartInfo->szDumpFile);
817                             }
818                             else if (pStartInfo->dwCrashDumpEnabled == 3)
819                             {
820                                 SendDlgItemMessageW(hwndDlg, IDC_STRRECDUMPFILE, WM_GETTEXT, (WPARAM)sizeof(pStartInfo->szMinidumpDir) / sizeof(WCHAR), (LPARAM)pStartInfo->szMinidumpDir);
821                             }
822 
823                             pStartInfo->dwCrashDumpEnabled = (DWORD)lResult;
824                             SetCrashDlgItems(hwndDlg, pStartInfo);
825                         }
826                     }
827                     break;
828             }
829             break;
830     }
831 
832     return FALSE;
833 }
834