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