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