xref: /reactos/base/system/userinit/livecd.c (revision a1fc312a)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS Userinit Logon Application
4  * FILE:        base/system/userinit/livecd.c
5  * PROGRAMMERS: Eric Kohl
6  */
7 
8 #include "userinit.h"
9 
10 HWND hList;
11 HWND hLocaleList;
12 BOOL bSpain = FALSE;
13 
14 typedef struct _LIVECD_UNATTEND
15 {
16     BOOL bEnabled;
17     LCID LocaleID;
18 } LIVECD_UNATTEND;
19 
20 
21 /*
22  * Taken and adapted from dll/cpl/sysdm/general.c
23  */
24 static VOID
25 InitLogo(PIMGINFO pImgInfo, HWND hwndDlg)
26 {
27     BITMAP logoBitmap;
28     BITMAP maskBitmap;
29     BITMAPINFO bmpi;
30     HDC hDC = GetDC(hwndDlg);
31     HDC hDCLogo = CreateCompatibleDC(NULL);
32     HDC hDCMask = CreateCompatibleDC(NULL);
33     HBITMAP hMask, hLogo, hAlphaLogo = NULL;
34     COLORREF *pBits;
35     INT line, column;
36 
37     if (hDC == NULL || hDCLogo == NULL || hDCMask == NULL)
38         goto Cleanup;
39 
40     ZeroMemory(pImgInfo, sizeof(*pImgInfo));
41     ZeroMemory(&bmpi, sizeof(bmpi));
42 
43     hLogo = (HBITMAP)LoadImageW(hInstance, MAKEINTRESOURCEW(IDB_ROSLOGO), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
44     hMask = (HBITMAP)LoadImageW(hInstance, MAKEINTRESOURCEW(IDB_ROSMASK), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR);
45 
46     if (hLogo != NULL && hMask != NULL)
47     {
48         GetObject(hLogo, sizeof(logoBitmap), &logoBitmap);
49         GetObject(hMask, sizeof(maskBitmap), &maskBitmap);
50 
51         if (logoBitmap.bmHeight != maskBitmap.bmHeight || logoBitmap.bmWidth != maskBitmap.bmWidth)
52             goto Cleanup;
53 
54         bmpi.bmiHeader.biSize = sizeof(BITMAPINFO);
55         bmpi.bmiHeader.biWidth = logoBitmap.bmWidth;
56         bmpi.bmiHeader.biHeight = logoBitmap.bmHeight;
57         bmpi.bmiHeader.biPlanes = 1;
58         bmpi.bmiHeader.biBitCount = 32;
59         bmpi.bmiHeader.biCompression = BI_RGB;
60         bmpi.bmiHeader.biSizeImage = 4 * logoBitmap.bmWidth * logoBitmap.bmHeight;
61 
62         /* Create a premultiplied bitmap */
63         hAlphaLogo = CreateDIBSection(hDC, &bmpi, DIB_RGB_COLORS, (PVOID*)&pBits, 0, 0);
64         if (!hAlphaLogo)
65             goto Cleanup;
66 
67         SelectObject(hDCLogo, hLogo);
68         SelectObject(hDCMask, hMask);
69 
70         for (line = logoBitmap.bmHeight - 1; line >= 0; line--)
71         {
72             for (column = 0; column < logoBitmap.bmWidth; column++)
73             {
74                 COLORREF alpha = GetPixel(hDCMask, column, line) & 0xFF;
75                 COLORREF Color = GetPixel(hDCLogo, column, line);
76                 DWORD r, g, b;
77 
78                 r = GetRValue(Color) * alpha / 255;
79                 g = GetGValue(Color) * alpha / 255;
80                 b = GetBValue(Color) * alpha / 255;
81 
82                 *pBits++ = b | (g << 8) | (r << 16) | (alpha << 24);
83             }
84         }
85 
86         pImgInfo->hBitmap = hAlphaLogo;
87         pImgInfo->cxSource = logoBitmap.bmWidth;
88         pImgInfo->cySource = logoBitmap.bmHeight;
89         pImgInfo->iBits = logoBitmap.bmBitsPixel;
90         pImgInfo->iPlanes = logoBitmap.bmPlanes;
91     }
92 
93 Cleanup:
94     if (hMask != NULL) DeleteObject(hMask);
95     if (hLogo != NULL) DeleteObject(hLogo);
96     if (hDCMask != NULL) DeleteDC(hDCMask);
97     if (hDCLogo != NULL) DeleteDC(hDCLogo);
98     if (hDC != NULL) ReleaseDC(hwndDlg, hDC);
99 }
100 
101 
102 BOOL
103 IsLiveCD(VOID)
104 {
105     HKEY ControlKey = NULL;
106     LPWSTR SystemStartOptions = NULL;
107     LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
108     LONG rc;
109     BOOL ret = FALSE;
110 
111     TRACE("IsLiveCD()\n");
112 
113     rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
114                        REGSTR_PATH_CURRENT_CONTROL_SET,
115                        0,
116                        KEY_QUERY_VALUE,
117                        &ControlKey);
118     if (rc != ERROR_SUCCESS)
119     {
120         WARN("RegOpenKeyEx() failed with error %lu\n", rc);
121         goto cleanup;
122     }
123 
124     rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
125     if (rc != ERROR_SUCCESS)
126     {
127         WARN("ReadRegSzKey() failed with error %lu\n", rc);
128         goto cleanup;
129     }
130 
131     /* Check for CONSOLE switch in SystemStartOptions */
132     CurrentOption = SystemStartOptions;
133     while (CurrentOption)
134     {
135         NextOption = wcschr(CurrentOption, L' ');
136         if (NextOption)
137             *NextOption = L'\0';
138         if (_wcsicmp(CurrentOption, L"MININT") == 0)
139         {
140             TRACE("Found 'MININT' boot option\n");
141             ret = TRUE;
142             goto cleanup;
143         }
144         CurrentOption = NextOption ? NextOption + 1 : NULL;
145     }
146 
147 cleanup:
148     if (ControlKey != NULL)
149         RegCloseKey(ControlKey);
150     HeapFree(GetProcessHeap(), 0, SystemStartOptions);
151 
152     TRACE("IsLiveCD() returning %d\n", ret);
153 
154     return ret;
155 }
156 
157 
158 static BOOL CALLBACK
159 LocalesEnumProc(LPTSTR lpLocale)
160 {
161     LCID lcid;
162     WCHAR lang[255];
163     INT index;
164     BOOL bNoShow = FALSE;
165 
166     lcid = wcstoul(lpLocale, NULL, 16);
167 
168     /* Display only languages with installed support */
169     if (!IsValidLocale(lcid, LCID_INSTALLED))
170         return TRUE;
171 
172     // See http://archives.miloush.net/michkap/archive/2006/09/23/768178.html for why we handle spain differently
173     if (lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) ||
174         lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT))
175     {
176         if (bSpain == FALSE)
177         {
178             LoadStringW(hInstance, IDS_SPAIN, lang, ARRAYSIZE(lang));
179             bSpain = TRUE;
180         }
181         else
182         {
183             bNoShow = TRUE;
184         }
185     }
186     else
187     {
188         GetLocaleInfoW(lcid, LOCALE_SLANGUAGE, lang, ARRAYSIZE(lang));
189     }
190 
191     if (bNoShow == FALSE)
192     {
193         index = SendMessageW(hList,
194                              CB_ADDSTRING,
195                              0,
196                              (LPARAM)lang);
197 
198         SendMessageW(hList,
199                      CB_SETITEMDATA,
200                      index,
201                      (LPARAM)lcid);
202     }
203 
204     return TRUE;
205 }
206 
207 
208 static VOID
209 CreateLanguagesList(HWND hwnd, PSTATE pState)
210 {
211     WCHAR langSel[255];
212     LCID Locale = 0;
213 
214     hList = hwnd;
215     bSpain = FALSE;
216     EnumSystemLocalesW(LocalesEnumProc, LCID_SUPPORTED);
217 
218     if (pState->Unattend->bEnabled)
219         Locale = pState->Unattend->LocaleID;
220 
221     if (!Locale)
222     {
223         /* Select current locale */
224         /* or should it be System and not user? */
225         Locale = GetUserDefaultLCID();
226     }
227     GetLocaleInfoW(Locale, LOCALE_SLANGUAGE, langSel, ARRAYSIZE(langSel));
228 
229     SendMessageW(hList,
230                  CB_SELECTSTRING,
231                  -1,
232                  (LPARAM)langSel);
233 }
234 
235 
236 static
237 BOOL
238 GetLayoutName(
239     LPCWSTR szLCID,
240     LPWSTR szName)
241 {
242     HKEY hKey;
243     DWORD dwBufLen;
244     WCHAR szBuf[MAX_PATH], szDispName[MAX_PATH], szIndex[MAX_PATH], szPath[MAX_PATH];
245     HANDLE hLib;
246     UINT i, j, k;
247 
248     wsprintf(szBuf, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", szLCID);
249 
250     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCTSTR)szBuf, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
251     {
252         dwBufLen = sizeof(szDispName);
253 
254         if (RegQueryValueExW(hKey, L"Layout Display Name", NULL, NULL, (LPBYTE)szDispName, &dwBufLen) == ERROR_SUCCESS)
255         {
256             if (szDispName[0] == '@')
257             {
258                 for (i = 0; i < wcslen(szDispName); i++)
259                 {
260                     if ((szDispName[i] == ',') && (szDispName[i + 1] == '-'))
261                     {
262                         for (j = i + 2, k = 0; j < wcslen(szDispName)+1; j++, k++)
263                         {
264                             szIndex[k] = szDispName[j];
265                         }
266                         szDispName[i - 1] = '\0';
267                         break;
268                     }
269                     else
270                         szDispName[i] = szDispName[i + 1];
271                 }
272 
273                 if (ExpandEnvironmentStringsW(szDispName, szPath, ARRAYSIZE(szPath)))
274                 {
275                     hLib = LoadLibraryW(szPath);
276                     if (hLib)
277                     {
278                         if (LoadStringW(hLib, _wtoi(szIndex), szPath, ARRAYSIZE(szPath)) != 0)
279                         {
280                             wcscpy(szName, szPath);
281                             RegCloseKey(hKey);
282                             return TRUE;
283                         }
284                         FreeLibrary(hLib);
285                     }
286                 }
287             }
288         }
289 
290         dwBufLen = sizeof(szBuf);
291 
292         if (RegQueryValueExW(hKey, L"Layout Text", NULL, NULL, (LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
293         {
294             RegCloseKey(hKey);
295             return TRUE;
296         }
297     }
298 
299     return FALSE;
300 }
301 
302 
303 static
304 VOID
305 SetKeyboardLayout(
306     HWND hwnd)
307 {
308     INT iCurSel;
309     ULONG ulLayoutId;
310     HKL hKl;
311     WCHAR szLayoutId[9];
312 
313     iCurSel = SendMessageW(hwnd, CB_GETCURSEL, 0, 0);
314     if (iCurSel == CB_ERR)
315         return;
316 
317     ulLayoutId = (ULONG)SendMessageW(hwnd, CB_GETITEMDATA, iCurSel, 0);
318     if (ulLayoutId == (ULONG)CB_ERR)
319         return;
320 
321     swprintf(szLayoutId, L"%08lx", ulLayoutId);
322 
323     hKl = LoadKeyboardLayoutW(szLayoutId, KLF_ACTIVATE | KLF_REPLACELANG | KLF_SETFORPROCESS);
324     SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, 0, &hKl, SPIF_SENDCHANGE);
325 }
326 
327 
328 static
329 VOID
330 SelectKeyboardForLanguage(
331     HWND hwnd,
332     LCID lcid)
333 {
334     INT i, nCount;
335     LCID LayoutId;
336 
337     TRACE("LCID: %08lx\n", lcid);
338     TRACE("LangID: %04lx\n", LANGIDFROMLCID(lcid));
339 
340     nCount = SendMessageW(hwnd, CB_GETCOUNT, 0, 0);
341 
342     for (i = 0; i < nCount; i++)
343     {
344         LayoutId = (LCID)SendMessageW(hwnd, CB_GETITEMDATA, i, 0);
345         TRACE("Layout: %08lx\n", LayoutId);
346 
347         if (LANGIDFROMLCID(LayoutId) == LANGIDFROMLCID(lcid))
348         {
349             TRACE("Found 1: %08lx --> %08lx\n", LayoutId, lcid);
350             SendMessageW(hwnd, CB_SETCURSEL, i, 0);
351             return;
352         }
353     }
354 
355     for (i = 0; i < nCount; i++)
356     {
357         LayoutId = (LCID)SendMessageW(hwnd, CB_GETITEMDATA, i, 0);
358         TRACE("Layout: %08lx\n", LayoutId);
359 
360         if (PRIMARYLANGID(LayoutId) == PRIMARYLANGID(lcid))
361         {
362             TRACE("Found 2: %08lx --> %08lx\n", LayoutId, lcid);
363             SendMessageW(hwnd, CB_SETCURSEL, i, 0);
364             return;
365         }
366     }
367 
368     TRACE("No match found!\n");
369 }
370 
371 
372 static
373 VOID
374 CreateKeyboardLayoutList(
375     HWND hItemsList)
376 {
377     HKEY hKey;
378     WCHAR szLayoutId[9], szCurrentLayoutId[9];
379     WCHAR KeyName[MAX_PATH];
380     DWORD dwIndex = 0;
381     DWORD dwSize;
382     INT iIndex;
383     LONG lError;
384     ULONG ulLayoutId;
385 
386     if (!GetKeyboardLayoutNameW(szCurrentLayoutId))
387         wcscpy(szCurrentLayoutId, L"00000409");
388 
389     lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
390                            L"System\\CurrentControlSet\\Control\\Keyboard Layouts",
391                            0,
392                            KEY_ENUMERATE_SUB_KEYS,
393                            &hKey);
394     if (lError != ERROR_SUCCESS)
395         return;
396 
397     while (TRUE)
398     {
399         dwSize = ARRAYSIZE(szLayoutId);
400 
401         lError = RegEnumKeyExW(hKey,
402                                dwIndex,
403                                szLayoutId,
404                                &dwSize,
405                                NULL,
406                                NULL,
407                                NULL,
408                                NULL);
409         if (lError != ERROR_SUCCESS)
410             break;
411 
412         GetLayoutName(szLayoutId, KeyName);
413 
414         iIndex = (INT)SendMessageW(hItemsList, CB_ADDSTRING, 0, (LPARAM)KeyName);
415 
416         ulLayoutId = wcstoul(szLayoutId, NULL, 16);
417         SendMessageW(hItemsList, CB_SETITEMDATA, iIndex, (LPARAM)ulLayoutId);
418 
419         if (wcscmp(szLayoutId, szCurrentLayoutId) == 0)
420         {
421             SendMessageW(hItemsList, CB_SETCURSEL, (WPARAM)iIndex, (LPARAM)0);
422         }
423 
424         dwIndex++;
425     }
426 
427     RegCloseKey(hKey);
428 }
429 
430 
431 static
432 VOID
433 InitializeDefaultUserLocale(
434     PLCID pNewLcid)
435 {
436     WCHAR szBuffer[80];
437     PWSTR ptr;
438     HKEY hLocaleKey;
439     DWORD ret;
440     DWORD dwSize;
441     LCID lcid;
442     INT i;
443 
444     struct {LCTYPE LCType; PWSTR pValue;} LocaleData[] = {
445         /* Number */
446         {LOCALE_SDECIMAL, L"sDecimal"},
447         {LOCALE_STHOUSAND, L"sThousand"},
448         {LOCALE_SNEGATIVESIGN, L"sNegativeSign"},
449         {LOCALE_SPOSITIVESIGN, L"sPositiveSign"},
450         {LOCALE_SGROUPING, L"sGrouping"},
451         {LOCALE_SLIST, L"sList"},
452         {LOCALE_SNATIVEDIGITS, L"sNativeDigits"},
453         {LOCALE_INEGNUMBER, L"iNegNumber"},
454         {LOCALE_IDIGITS, L"iDigits"},
455         {LOCALE_ILZERO, L"iLZero"},
456         {LOCALE_IMEASURE, L"iMeasure"},
457         {LOCALE_IDIGITSUBSTITUTION, L"NumShape"},
458 
459         /* Currency */
460         {LOCALE_SCURRENCY, L"sCurrency"},
461         {LOCALE_SMONDECIMALSEP, L"sMonDecimalSep"},
462         {LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep"},
463         {LOCALE_SMONGROUPING, L"sMonGrouping"},
464         {LOCALE_ICURRENCY, L"iCurrency"},
465         {LOCALE_INEGCURR, L"iNegCurr"},
466         {LOCALE_ICURRDIGITS, L"iCurrDigits"},
467 
468         /* Time */
469         {LOCALE_STIMEFORMAT, L"sTimeFormat"},
470         {LOCALE_STIME, L"sTime"},
471         {LOCALE_S1159, L"s1159"},
472         {LOCALE_S2359, L"s2359"},
473         {LOCALE_ITIME, L"iTime"},
474         {LOCALE_ITIMEMARKPOSN, L"iTimePrefix"},
475         {LOCALE_ITLZERO, L"iTLZero"},
476 
477         /* Date */
478         {LOCALE_SLONGDATE, L"sLongDate"},
479         {LOCALE_SSHORTDATE, L"sShortDate"},
480         {LOCALE_SDATE, L"sDate"},
481         {LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek"},
482         {LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear"},
483         {LOCALE_IDATE, L"iDate"},
484         {LOCALE_ICALENDARTYPE, L"iCalendarType"},
485 
486         /* Misc */
487         {LOCALE_SCOUNTRY, L"sCountry"},
488         {LOCALE_SABBREVLANGNAME, L"sLanguage"},
489         {LOCALE_ICOUNTRY, L"iCountry"},
490         {0, NULL}};
491 
492     ret = RegOpenKeyExW(HKEY_USERS,
493                         L".DEFAULT\\Control Panel\\International",
494                         0,
495                         KEY_READ | KEY_WRITE,
496                         &hLocaleKey);
497     if (ret != ERROR_SUCCESS)
498     {
499         return;
500     }
501 
502     if (pNewLcid == NULL)
503     {
504         dwSize = 9 * sizeof(WCHAR);
505         ret = RegQueryValueExW(hLocaleKey,
506                                L"Locale",
507                                NULL,
508                                NULL,
509                                (PBYTE)szBuffer,
510                                &dwSize);
511         if (ret != ERROR_SUCCESS)
512             goto done;
513 
514         lcid = (LCID)wcstoul(szBuffer, &ptr, 16);
515         if (lcid == 0)
516             goto done;
517     }
518     else
519     {
520         lcid = *pNewLcid;
521 
522         swprintf(szBuffer, L"%08lx", lcid);
523         RegSetValueExW(hLocaleKey,
524                        L"Locale",
525                        0,
526                        REG_SZ,
527                        (PBYTE)szBuffer,
528                        (wcslen(szBuffer) + 1) * sizeof(WCHAR));
529     }
530 
531     i = 0;
532     while (LocaleData[i].pValue != NULL)
533     {
534         if (GetLocaleInfoW(lcid,
535                            LocaleData[i].LCType | LOCALE_NOUSEROVERRIDE,
536                            szBuffer,
537                            ARRAYSIZE(szBuffer)))
538         {
539             RegSetValueExW(hLocaleKey,
540                            LocaleData[i].pValue,
541                            0,
542                            REG_SZ,
543                            (PBYTE)szBuffer,
544                            (wcslen(szBuffer) + 1) * sizeof(WCHAR));
545         }
546 
547         i++;
548     }
549 
550 done:
551     RegCloseKey(hLocaleKey);
552 }
553 
554 
555 VOID
556 CenterWindow(HWND hWnd)
557 {
558     HWND hWndParent;
559     RECT rcParent;
560     RECT rcWindow;
561 
562     hWndParent = GetParent(hWnd);
563     if (hWndParent == NULL)
564         hWndParent = GetDesktopWindow();
565 
566     GetWindowRect(hWndParent, &rcParent);
567     GetWindowRect(hWnd, &rcWindow);
568 
569     SetWindowPos(hWnd,
570                  HWND_TOP,
571                  ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
572                  ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
573                  0,
574                  0,
575                  SWP_NOSIZE);
576 }
577 
578 
579 static
580 VOID
581 OnDrawItem(
582      LPDRAWITEMSTRUCT lpDrawItem,
583      PSTATE pState,
584      UINT uCtlID)
585 {
586     HDC hdcMem;
587     LONG left;
588 
589     if (lpDrawItem->CtlID == uCtlID)
590     {
591         /* Position image in centre of dialog */
592         left = (lpDrawItem->rcItem.right - pState->ImageInfo.cxSource) / 2;
593 
594         hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
595         if (hdcMem != NULL)
596         {
597             static BLENDFUNCTION BlendFunc = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
598 
599             SelectObject(hdcMem, pState->ImageInfo.hBitmap);
600             GdiAlphaBlend(lpDrawItem->hDC,
601                           left,
602                           lpDrawItem->rcItem.top,
603                           pState->ImageInfo.cxSource,
604                           pState->ImageInfo.cySource,
605                           hdcMem,
606                           0, 0,
607                           pState->ImageInfo.cxSource,
608                           pState->ImageInfo.cySource,
609                           BlendFunc);
610             DeleteDC(hdcMem);
611         }
612     }
613 }
614 
615 
616 static
617 INT_PTR
618 CALLBACK
619 LocaleDlgProc(
620     HWND hwndDlg,
621     UINT uMsg,
622     WPARAM wParam,
623     LPARAM lParam)
624 {
625     PSTATE pState;
626 
627     /* Retrieve pointer to the state */
628     pState = (PSTATE)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
629 
630     switch (uMsg)
631     {
632         case WM_INITDIALOG:
633             /* Save pointer to the global state */
634             pState = (PSTATE)lParam;
635             SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pState);
636 
637             /* Center the dialog window */
638             CenterWindow(hwndDlg);
639 
640             /* Fill the language and keyboard layout lists */
641             CreateLanguagesList(GetDlgItem(hwndDlg, IDC_LANGUAGELIST), pState);
642             CreateKeyboardLayoutList(GetDlgItem(hwndDlg, IDC_LAYOUTLIST));
643             if (pState->Unattend->bEnabled)
644             {
645                 // Advance to the next page
646                 PostMessageW(hwndDlg, WM_COMMAND, MAKELONG(IDOK, BN_CLICKED), 0L);
647             }
648             return FALSE;
649 
650         case WM_DRAWITEM:
651             OnDrawItem((LPDRAWITEMSTRUCT)lParam,
652                        pState,
653                        IDC_LOCALELOGO);
654             return TRUE;
655 
656         case WM_COMMAND:
657             switch (LOWORD(wParam))
658             {
659                 case IDC_LANGUAGELIST:
660                     if (HIWORD(wParam) == CBN_SELCHANGE)
661                     {
662                         LCID NewLcid;
663                         INT iCurSel;
664 
665                         iCurSel = SendDlgItemMessageW(hwndDlg,
666                                                      IDC_LANGUAGELIST,
667                                                      CB_GETCURSEL,
668                                                      0,
669                                                      0);
670                         if (iCurSel == CB_ERR)
671                             break;
672 
673                         NewLcid = SendDlgItemMessageW(hwndDlg,
674                                                       IDC_LANGUAGELIST,
675                                                       CB_GETITEMDATA,
676                                                       iCurSel,
677                                                       0);
678                         if (NewLcid == (LCID)CB_ERR)
679                             break;
680 
681                         TRACE("LCID: 0x%08lx\n", NewLcid);
682                         SelectKeyboardForLanguage(GetDlgItem(hwndDlg, IDC_LAYOUTLIST),
683                                                   NewLcid);
684                     }
685                     break;
686 
687                 case IDOK:
688                     if (HIWORD(wParam) == BN_CLICKED)
689                     {
690                         LCID NewLcid;
691                         INT iCurSel;
692 
693                         iCurSel = SendDlgItemMessageW(hwndDlg,
694                                                      IDC_LANGUAGELIST,
695                                                      CB_GETCURSEL,
696                                                      0,
697                                                      0);
698                         if (iCurSel == CB_ERR)
699                             break;
700 
701                         NewLcid = SendDlgItemMessageW(hwndDlg,
702                                                       IDC_LANGUAGELIST,
703                                                       CB_GETITEMDATA,
704                                                       iCurSel,
705                                                       0);
706                         if (NewLcid == (LCID)CB_ERR)
707                             break;
708 
709                         /* Set the locale for the current thread */
710                         NtSetDefaultLocale(TRUE, NewLcid);
711 
712                         /* Store the locale settings in the registry */
713                         InitializeDefaultUserLocale(&NewLcid);
714 
715                         SetKeyboardLayout(GetDlgItem(hwndDlg, IDC_LAYOUTLIST));
716 
717                         pState->NextPage = STARTPAGE;
718                         EndDialog(hwndDlg, LOWORD(wParam));
719                     }
720                     break;
721 
722                 case IDCANCEL:
723                     if (HIWORD(wParam) == BN_CLICKED)
724                     {
725                         static WCHAR szMsg[RC_STRING_MAX_SIZE];
726                         INT ret;
727                         LoadStringW(GetModuleHandle(NULL), IDS_CANCEL_CONFIRM, szMsg, ARRAYSIZE(szMsg));
728                         ret = MessageBoxW(hwndDlg, szMsg, L"ReactOS LiveCD", MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
729                         if (ret == IDOK || ret == IDYES)
730                         {
731                             pState->NextPage = DONE;
732                             pState->Run = REBOOT;
733                             EndDialog(hwndDlg, LOWORD(wParam));
734                         }
735                     }
736                     break;
737 
738                 default:
739                     break;
740             }
741             break;
742 
743         default:
744             break;
745     }
746 
747     return FALSE;
748 }
749 
750 
751 static
752 INT_PTR
753 CALLBACK
754 StartDlgProc(
755     HWND hwndDlg,
756     UINT uMsg,
757     WPARAM wParam,
758     LPARAM lParam)
759 {
760     PSTATE pState;
761 
762     /* Retrieve pointer to the state */
763     pState = (PSTATE)GetWindowLongPtrW(hwndDlg, GWLP_USERDATA);
764 
765     switch (uMsg)
766     {
767         case WM_INITDIALOG:
768             /* Save pointer to the state */
769             pState = (PSTATE)lParam;
770             SetWindowLongPtrW(hwndDlg, GWLP_USERDATA, (DWORD_PTR)pState);
771 
772             /* Center the dialog window */
773             CenterWindow(hwndDlg);
774 
775             if (pState->Unattend->bEnabled)
776             {
777                 // Click on the 'Run' button
778                 PostMessageW(hwndDlg, WM_COMMAND, MAKELONG(IDC_RUN, BN_CLICKED), 0L);
779             }
780 
781             return FALSE;
782 
783         case WM_DRAWITEM:
784             OnDrawItem((LPDRAWITEMSTRUCT)lParam,
785                        pState,
786                        IDC_STARTLOGO);
787             return TRUE;
788 
789         case WM_COMMAND:
790             if (HIWORD(wParam) == BN_CLICKED)
791             {
792                 switch (LOWORD(wParam))
793                 {
794                     case IDC_RUN:
795                         pState->NextPage = DONE;
796                         pState->Run = SHELL;
797                         EndDialog(hwndDlg, LOWORD(wParam));
798                         break;
799 
800                     case IDC_INSTALL:
801                         pState->NextPage = DONE;
802                         pState->Run = INSTALLER;
803                         EndDialog(hwndDlg, LOWORD(wParam));
804                         break;
805 
806                     case IDOK:
807                         pState->NextPage = LOCALEPAGE;
808                         EndDialog(hwndDlg, LOWORD(wParam));
809                         break;
810 
811                     case IDCANCEL:
812                         if (HIWORD(wParam) == BN_CLICKED)
813                         {
814                             static WCHAR szMsg[RC_STRING_MAX_SIZE];
815                             INT ret;
816                             LoadStringW(GetModuleHandle(NULL), IDS_CANCEL_CONFIRM, szMsg, ARRAYSIZE(szMsg));
817                             ret = MessageBoxW(hwndDlg, szMsg, L"ReactOS LiveCD", MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON2);
818                             if (ret == IDOK || ret == IDYES)
819                             {
820                                 pState->NextPage = DONE;
821                                 pState->Run = REBOOT;
822                                 EndDialog(hwndDlg, LOWORD(wParam));
823                             }
824                         }
825                         break;
826 
827                     default:
828                         break;
829                 }
830             }
831             break;
832 
833         default:
834             break;
835     }
836 
837     return FALSE;
838 }
839 
840 VOID ParseUnattend(LPCWSTR UnattendInf, LIVECD_UNATTEND* pUnattend)
841 {
842     WCHAR Buffer[MAX_PATH];
843 
844     pUnattend->bEnabled = FALSE;
845 
846     if (!GetPrivateProfileStringW(L"Unattend", L"Signature", L"", Buffer, _countof(Buffer), UnattendInf))
847     {
848         ERR("Unable to parse Signature\n");
849         return;
850     }
851 
852     if (_wcsicmp(Buffer, L"$ReactOS$") && _wcsicmp(Buffer, L"$Windows NT$"))
853     {
854         TRACE("Unknown signature: %S\n", Buffer);
855         return;
856     }
857 
858     if (!GetPrivateProfileStringW(L"Unattend", L"UnattendSetupEnabled", L"", Buffer, _countof(Buffer), UnattendInf))
859     {
860         ERR("Unable to parse UnattendSetupEnabled\n");
861         return;
862     }
863 
864     if (_wcsicmp(Buffer, L"yes"))
865     {
866         TRACE("Unattended setup is not enabled\n", Buffer);
867         return;
868     }
869 
870     pUnattend->bEnabled = TRUE;
871     pUnattend->LocaleID = 0;
872 
873     if (GetPrivateProfileStringW(L"Unattend", L"LocaleID", L"", Buffer, _countof(Buffer), UnattendInf) && Buffer[0])
874     {
875         pUnattend->LocaleID = wcstol(Buffer, NULL, 16);
876     }
877 }
878 
879 VOID
880 RunLiveCD(
881     PSTATE pState)
882 {
883     LIVECD_UNATTEND Unattend = {0};
884     WCHAR UnattendInf[MAX_PATH];
885 
886     InitLogo(&pState->ImageInfo, NULL);
887 
888     GetWindowsDirectoryW(UnattendInf, _countof(UnattendInf));
889     wcscat(UnattendInf, L"\\unattend.inf");
890     ParseUnattend(UnattendInf, &Unattend);
891     pState->Unattend = &Unattend;
892 
893     while (pState->NextPage != DONE)
894     {
895         switch (pState->NextPage)
896         {
897             case LOCALEPAGE:
898                 DialogBoxParamW(hInstance,
899                                 MAKEINTRESOURCEW(IDD_LOCALEPAGE),
900                                 NULL,
901                                 LocaleDlgProc,
902                                 (LPARAM)pState);
903                 break;
904 
905             case STARTPAGE:
906                 DialogBoxParamW(hInstance,
907                                 MAKEINTRESOURCEW(IDD_STARTPAGE),
908                                 NULL,
909                                 StartDlgProc,
910                                 (LPARAM)pState);
911                 break;
912 
913             default:
914                 break;
915         }
916     }
917 
918     DeleteObject(pState->ImageInfo.hBitmap);
919 }
920 
921 /* EOF */
922