d7bb1d611d5e51e7c3bf1450db7fd0819e906e43
[reactos.git] / reactos / base / system / userinit / livecd.c
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 static VOID
15 InitImageInfo(PIMGINFO ImgInfo)
16 {
17 BITMAP bitmap;
18
19 ZeroMemory(ImgInfo, sizeof(*ImgInfo));
20
21 ImgInfo->hBitmap = LoadImage(hInstance,
22 MAKEINTRESOURCE(IDB_ROSLOGO),
23 IMAGE_BITMAP,
24 0,
25 0,
26 LR_DEFAULTCOLOR);
27
28 if (ImgInfo->hBitmap != NULL)
29 {
30 GetObject(ImgInfo->hBitmap, sizeof(BITMAP), &bitmap);
31
32 ImgInfo->cxSource = bitmap.bmWidth;
33 ImgInfo->cySource = bitmap.bmHeight;
34 }
35 }
36
37
38 BOOL
39 IsLiveCD(VOID)
40 {
41 HKEY ControlKey = NULL;
42 LPWSTR SystemStartOptions = NULL;
43 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
44 LONG rc;
45 BOOL ret = FALSE;
46
47 TRACE("IsLiveCD()\n");
48
49 rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
50 REGSTR_PATH_CURRENT_CONTROL_SET,
51 0,
52 KEY_QUERY_VALUE,
53 &ControlKey);
54 if (rc != ERROR_SUCCESS)
55 {
56 WARN("RegOpenKeyEx() failed with error %lu\n", rc);
57 goto cleanup;
58 }
59
60 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
61 if (rc != ERROR_SUCCESS)
62 {
63 WARN("ReadRegSzKey() failed with error %lu\n", rc);
64 goto cleanup;
65 }
66
67 /* Check for CONSOLE switch in SystemStartOptions */
68 CurrentOption = SystemStartOptions;
69 while (CurrentOption)
70 {
71 NextOption = wcschr(CurrentOption, L' ');
72 if (NextOption)
73 *NextOption = L'\0';
74 if (_wcsicmp(CurrentOption, L"MININT") == 0)
75 {
76 TRACE("Found 'MININT' boot option\n");
77 ret = TRUE;
78 goto cleanup;
79 }
80 CurrentOption = NextOption ? NextOption + 1 : NULL;
81 }
82
83 cleanup:
84 if (ControlKey != NULL)
85 RegCloseKey(ControlKey);
86 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
87
88 TRACE("IsLiveCD() returning %d\n", ret);
89
90 return ret;
91 }
92
93
94 static BOOL CALLBACK
95 LocalesEnumProc(LPTSTR lpLocale)
96 {
97 LCID lcid;
98 WCHAR lang[255];
99 INT index;
100 BOOL bNoShow = FALSE;
101
102 lcid = wcstoul(lpLocale, NULL, 16);
103
104 /* Display only languages with installed support */
105 if (!IsValidLocale(lcid, LCID_INSTALLED))
106 return TRUE;
107
108 if (lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH), SORT_DEFAULT) ||
109 lcid == MAKELCID(MAKELANGID(LANG_SPANISH, SUBLANG_SPANISH_MODERN), SORT_DEFAULT))
110 {
111 if (bSpain == FALSE)
112 {
113 LoadStringW(hInstance, IDS_SPAIN, lang, 255);
114 bSpain = TRUE;
115 }
116 else
117 {
118 bNoShow = TRUE;
119 }
120 }
121 else
122 {
123 GetLocaleInfoW(lcid, LOCALE_SLANGUAGE, lang, sizeof(lang)/sizeof(WCHAR));
124 }
125
126 if (bNoShow == FALSE)
127 {
128 index = SendMessageW(hList,
129 CB_ADDSTRING,
130 0,
131 (LPARAM)lang);
132
133 SendMessageW(hList,
134 CB_SETITEMDATA,
135 index,
136 (LPARAM)lcid);
137 }
138
139 return TRUE;
140 }
141
142
143 static VOID
144 CreateLanguagesList(HWND hwnd)
145 {
146 WCHAR langSel[255];
147
148 hList = hwnd;
149 bSpain = FALSE;
150 EnumSystemLocalesW(LocalesEnumProc, LCID_SUPPORTED);
151
152 /* Select current locale */
153 /* or should it be System and not user? */
154 GetLocaleInfoW(GetUserDefaultLCID(), LOCALE_SLANGUAGE, langSel, sizeof(langSel)/sizeof(WCHAR));
155
156 SendMessageW(hList,
157 CB_SELECTSTRING,
158 -1,
159 (LPARAM)langSel);
160 }
161
162
163 static
164 BOOL
165 GetLayoutName(
166 LPCWSTR szLCID,
167 LPWSTR szName)
168 {
169 HKEY hKey;
170 DWORD dwBufLen;
171 WCHAR szBuf[MAX_PATH], szDispName[MAX_PATH], szIndex[MAX_PATH], szPath[MAX_PATH];
172 HANDLE hLib;
173 unsigned i, j, k;
174
175 wsprintf(szBuf, L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", szLCID);
176
177 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, (LPCTSTR)szBuf, 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
178 {
179 dwBufLen = sizeof(szBuf);
180
181 if (RegQueryValueExW(hKey, L"Layout Display Name", NULL, NULL, (LPBYTE)szDispName, &dwBufLen) == ERROR_SUCCESS)
182 {
183 if (szDispName[0] == '@')
184 {
185 for (i = 0; i < wcslen(szDispName); i++)
186 {
187 if ((szDispName[i] == ',') && (szDispName[i + 1] == '-'))
188 {
189 for (j = i + 2, k = 0; j < wcslen(szDispName)+1; j++, k++)
190 {
191 szIndex[k] = szDispName[j];
192 }
193 szDispName[i - 1] = '\0';
194 break;
195 }
196 else
197 szDispName[i] = szDispName[i + 1];
198 }
199
200 if (ExpandEnvironmentStringsW(szDispName, szPath, MAX_PATH))
201 {
202 hLib = LoadLibraryW(szPath);
203 if (hLib)
204 {
205 if (LoadStringW(hLib, _wtoi(szIndex), szPath, sizeof(szPath) / sizeof(WCHAR)) != 0)
206 {
207 wcscpy(szName, szPath);
208 RegCloseKey(hKey);
209 return TRUE;
210 }
211 FreeLibrary(hLib);
212 }
213 }
214 }
215 }
216
217 dwBufLen = sizeof(szBuf);
218
219 if (RegQueryValueExW(hKey, L"Layout Text", NULL, NULL, (LPBYTE)szName, &dwBufLen) == ERROR_SUCCESS)
220 {
221 RegCloseKey(hKey);
222 return TRUE;
223 }
224 }
225
226 return FALSE;
227 }
228
229
230 static
231 VOID
232 SetKeyboardLayout(
233 HWND hwnd)
234 {
235 INT iCurSel;
236 ULONG ulLayoutId;
237 HKL hKl;
238 WCHAR szLayoutId[9];
239
240 iCurSel = SendMessageW(hwnd, CB_GETCURSEL, 0, 0);
241 if (iCurSel == CB_ERR)
242 return;
243
244 ulLayoutId = (ULONG)SendMessageW(hwnd, CB_GETITEMDATA, iCurSel, 0);
245 if (ulLayoutId == (ULONG)CB_ERR)
246 return;
247
248 swprintf(szLayoutId, L"%08lx", ulLayoutId);
249
250 hKl = LoadKeyboardLayoutW(szLayoutId, KLF_ACTIVATE | KLF_REPLACELANG | KLF_SETFORPROCESS);
251 SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG, 0, &hKl, SPIF_SENDWININICHANGE);
252 }
253
254
255 static
256 VOID
257 SelectKeyboardForLanguage(
258 HWND hwnd,
259 LCID lcid)
260 {
261 INT i, nCount;
262 LCID LayoutId;
263
264 TRACE("LCID: %08lx\n", lcid);
265 TRACE("LangID: %04lx\n", LANGIDFROMLCID(lcid));
266
267 nCount = SendMessageW(hwnd, CB_GETCOUNT, 0, 0);
268
269 for (i = 0; i < nCount; i++)
270 {
271 LayoutId = (LCID)SendMessageW(hwnd, CB_GETITEMDATA, i, 0);
272 TRACE("Layout: %08lx\n", LayoutId);
273
274 if (LANGIDFROMLCID(LayoutId) == LANGIDFROMLCID(lcid))
275 {
276 TRACE("Found 1: %08lx --> %08lx\n", LayoutId, lcid);
277 SendMessageW(hwnd, CB_SETCURSEL, i, 0);
278 return;
279 }
280 }
281
282 for (i = 0; i < nCount; i++)
283 {
284 LayoutId = (LCID)SendMessageW(hwnd, CB_GETITEMDATA, i, 0);
285 TRACE("Layout: %08lx\n", LayoutId);
286
287 if (PRIMARYLANGID(LayoutId) == PRIMARYLANGID(lcid))
288 {
289 TRACE("Found 2: %08lx --> %08lx\n", LayoutId, lcid);
290 SendMessageW(hwnd, CB_SETCURSEL, i, 0);
291 return;
292 }
293 }
294
295 TRACE("No match found!\n");
296 }
297
298
299 static
300 VOID
301 CreateKeyboardLayoutList(
302 HWND hItemsList)
303 {
304 HKEY hKey;
305 WCHAR szLayoutID[9], KeyName[MAX_PATH];
306 DWORD dwIndex = 0;
307 DWORD dwSize;
308 INT iIndex;
309 LONG lError;
310 ULONG ulLayoutID;
311
312 lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
313 L"System\\CurrentControlSet\\Control\\Keyboard Layouts",
314 0,
315 KEY_ENUMERATE_SUB_KEYS,
316 &hKey);
317 if (lError != ERROR_SUCCESS)
318 return;
319
320 while (TRUE)
321 {
322 dwSize = sizeof(szLayoutID) / sizeof(WCHAR);
323
324 lError = RegEnumKeyExW(hKey,
325 dwIndex,
326 szLayoutID,
327 &dwSize,
328 NULL,
329 NULL,
330 NULL,
331 NULL);
332 if (lError != ERROR_SUCCESS)
333 break;
334
335 GetLayoutName(szLayoutID, KeyName);
336
337 iIndex = (INT)SendMessageW(hItemsList, CB_ADDSTRING, 0, (LPARAM)KeyName);
338
339 ulLayoutID = wcstoul(szLayoutID, NULL, 16);
340 SendMessageW(hItemsList, CB_SETITEMDATA, iIndex, (LPARAM)ulLayoutID);
341
342 // FIXME!
343 if (wcscmp(szLayoutID, L"00000409") == 0)
344 {
345 SendMessageW(hItemsList, CB_SETCURSEL, (WPARAM)iIndex, (LPARAM)0);
346 }
347
348 dwIndex++;
349 }
350
351 RegCloseKey(hKey);
352 }
353
354
355 static
356 VOID
357 InitializeDefaultUserLocale(
358 PLCID pNewLcid)
359 {
360 WCHAR szBuffer[80];
361 PWSTR ptr;
362 HKEY hLocaleKey;
363 DWORD ret;
364 DWORD dwSize;
365 LCID lcid;
366 INT i;
367
368 struct {LCTYPE LCType; PWSTR pValue;} LocaleData[] = {
369 /* Number */
370 {LOCALE_SDECIMAL, L"sDecimal"},
371 {LOCALE_STHOUSAND, L"sThousand"},
372 {LOCALE_SNEGATIVESIGN, L"sNegativeSign"},
373 {LOCALE_SPOSITIVESIGN, L"sPositiveSign"},
374 {LOCALE_SGROUPING, L"sGrouping"},
375 {LOCALE_SLIST, L"sList"},
376 {LOCALE_SNATIVEDIGITS, L"sNativeDigits"},
377 {LOCALE_INEGNUMBER, L"iNegNumber"},
378 {LOCALE_IDIGITS, L"iDigits"},
379 {LOCALE_ILZERO, L"iLZero"},
380 {LOCALE_IMEASURE, L"iMeasure"},
381 {LOCALE_IDIGITSUBSTITUTION, L"NumShape"},
382
383 /* Currency */
384 {LOCALE_SCURRENCY, L"sCurrency"},
385 {LOCALE_SMONDECIMALSEP, L"sMonDecimalSep"},
386 {LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep"},
387 {LOCALE_SMONGROUPING, L"sMonGrouping"},
388 {LOCALE_ICURRENCY, L"iCurrency"},
389 {LOCALE_INEGCURR, L"iNegCurr"},
390 {LOCALE_ICURRDIGITS, L"iCurrDigits"},
391
392 /* Time */
393 {LOCALE_STIMEFORMAT, L"sTimeFormat"},
394 {LOCALE_STIME, L"sTime"},
395 {LOCALE_S1159, L"s1159"},
396 {LOCALE_S2359, L"s2359"},
397 {LOCALE_ITIME, L"iTime"},
398 {LOCALE_ITIMEMARKPOSN, L"iTimePrefix"},
399 {LOCALE_ITLZERO, L"iTLZero"},
400
401 /* Date */
402 {LOCALE_SLONGDATE, L"sLongDate"},
403 {LOCALE_SSHORTDATE, L"sShortDate"},
404 {LOCALE_SDATE, L"sDate"},
405 {LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek"},
406 {LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear"},
407 {LOCALE_IDATE, L"iDate"},
408 {LOCALE_ICALENDARTYPE, L"iCalendarType"},
409
410 /* Misc */
411 {LOCALE_SCOUNTRY, L"sCountry"},
412 {LOCALE_SLANGUAGE, L"sLanguage"},
413 {LOCALE_ICOUNTRY, L"iCountry"},
414 {0, NULL}};
415
416 ret = RegOpenKeyExW(HKEY_USERS,
417 L".DEFAULT\\Control Panel\\International",
418 0,
419 KEY_READ | KEY_WRITE,
420 &hLocaleKey);
421 if (ret != ERROR_SUCCESS)
422 {
423 return;
424 }
425
426 if (pNewLcid == NULL)
427 {
428 dwSize = 9 * sizeof(WCHAR);
429 ret = RegQueryValueExW(hLocaleKey,
430 L"Locale",
431 NULL,
432 NULL,
433 (PBYTE)szBuffer,
434 &dwSize);
435 if (ret != ERROR_SUCCESS)
436 goto done;
437
438 lcid = (LCID)wcstoul(szBuffer, &ptr, 16);
439 if (lcid == 0)
440 goto done;
441 }
442 else
443 {
444 lcid = *pNewLcid;
445
446 swprintf(szBuffer, L"%08lx", lcid);
447 RegSetValueExW(hLocaleKey,
448 L"Locale",
449 0,
450 REG_SZ,
451 (PBYTE)szBuffer,
452 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
453 }
454
455 i = 0;
456 while (LocaleData[i].pValue != NULL)
457 {
458 if (GetLocaleInfo(lcid,
459 LocaleData[i].LCType | LOCALE_NOUSEROVERRIDE,
460 szBuffer,
461 sizeof(szBuffer) / sizeof(WCHAR)))
462 {
463 RegSetValueExW(hLocaleKey,
464 LocaleData[i].pValue,
465 0,
466 REG_SZ,
467 (PBYTE)szBuffer,
468 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
469 }
470
471 i++;
472 }
473
474 done:
475 RegCloseKey(hLocaleKey);
476 }
477
478
479 VOID
480 CenterWindow(HWND hWnd)
481 {
482 HWND hWndParent;
483 RECT rcParent;
484 RECT rcWindow;
485
486 hWndParent = GetParent(hWnd);
487 if (hWndParent == NULL)
488 hWndParent = GetDesktopWindow();
489
490 GetWindowRect(hWndParent, &rcParent);
491 GetWindowRect(hWnd, &rcWindow);
492
493 SetWindowPos(hWnd,
494 HWND_TOP,
495 ((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
496 ((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
497 0,
498 0,
499 SWP_NOSIZE);
500 }
501
502
503 static
504 VOID
505 OnDrawItem(
506 LPDRAWITEMSTRUCT lpDrawItem,
507 PSTATE pState,
508 UINT uCtlID)
509 {
510 HDC hdcMem;
511 LONG left;
512
513 if (lpDrawItem->CtlID == uCtlID)
514 {
515 /* position image in centre of dialog */
516 left = (lpDrawItem->rcItem.right - pState->ImageInfo.cxSource) / 2;
517
518 hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
519 if (hdcMem != NULL)
520 {
521 SelectObject(hdcMem, pState->ImageInfo.hBitmap);
522 BitBlt(lpDrawItem->hDC,
523 left,
524 lpDrawItem->rcItem.top,
525 lpDrawItem->rcItem.right - lpDrawItem->rcItem.left,
526 lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top,
527 hdcMem,
528 0,
529 0,
530 SRCCOPY);
531 DeleteDC(hdcMem);
532 }
533 }
534 }
535
536
537 static
538 INT_PTR
539 CALLBACK
540 LocaleDlgProc(
541 HWND hwndDlg,
542 UINT uMsg,
543 WPARAM wParam,
544 LPARAM lParam)
545 {
546 PSTATE pState;
547
548 /* Retrieve pointer to the state */
549 pState = (PSTATE)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
550
551 switch (uMsg)
552 {
553 case WM_INITDIALOG:
554 /* Save pointer to the global state */
555 pState = (PSTATE)lParam;
556 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pState);
557
558 /* Center the dialog window */
559 CenterWindow (hwndDlg);
560
561 /* Fill the language and keyboard layout lists */
562 CreateLanguagesList(GetDlgItem(hwndDlg, IDC_LANGUAGELIST));
563 CreateKeyboardLayoutList(GetDlgItem(hwndDlg, IDC_LAYOUTLIST));
564
565 /* Disable the 'Cancel' button*/
566 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
567 return FALSE;
568
569 case WM_DRAWITEM:
570 OnDrawItem((LPDRAWITEMSTRUCT)lParam,
571 pState,
572 IDC_LOCALELOGO);
573 return TRUE;
574
575 case WM_COMMAND:
576 switch (LOWORD(wParam))
577 {
578 case IDC_LANGUAGELIST:
579 if (HIWORD(wParam) == CBN_SELCHANGE)
580 {
581 LCID NewLcid;
582 INT iCurSel;
583
584 iCurSel = SendDlgItemMessageW(hwndDlg,
585 IDC_LANGUAGELIST,
586 CB_GETCURSEL,
587 0,
588 0);
589 if (iCurSel == CB_ERR)
590 break;
591
592 NewLcid = SendDlgItemMessageW(hwndDlg,
593 IDC_LANGUAGELIST,
594 CB_GETITEMDATA,
595 iCurSel,
596 0);
597 if (NewLcid == (LCID)CB_ERR)
598 break;
599
600 TRACE("LCID: 0x%08lx\n", NewLcid);
601 SelectKeyboardForLanguage(GetDlgItem(hwndDlg, IDC_LAYOUTLIST),
602 NewLcid);
603 }
604 break;
605
606 case IDOK:
607 if (HIWORD(wParam) == BN_CLICKED)
608 {
609 LCID NewLcid;
610 INT iCurSel;
611
612 iCurSel = SendDlgItemMessageW(hwndDlg,
613 IDC_LANGUAGELIST,
614 CB_GETCURSEL,
615 0,
616 0);
617 if (iCurSel == CB_ERR)
618 break;
619
620 NewLcid = SendDlgItemMessageW(hwndDlg,
621 IDC_LANGUAGELIST,
622 CB_GETITEMDATA,
623 iCurSel,
624 0);
625 if (NewLcid == (LCID)CB_ERR)
626 break;
627
628 /* Set the locale for the current thread */
629 NtSetDefaultLocale(TRUE, NewLcid);
630
631 /* Store the locale setings in the registry */
632 InitializeDefaultUserLocale(&NewLcid);
633
634 SetKeyboardLayout(GetDlgItem(hwndDlg, IDC_LAYOUTLIST));
635
636 pState->NextPage = STARTPAGE;
637 EndDialog(hwndDlg, 0);
638 }
639 break;
640
641 default:
642 break;
643 }
644 break;
645
646 default:
647 break;
648 }
649
650 return FALSE;
651 }
652
653
654 static
655 INT_PTR
656 CALLBACK
657 StartDlgProc(
658 HWND hwndDlg,
659 UINT uMsg,
660 WPARAM wParam,
661 LPARAM lParam)
662 {
663 PSTATE pState;
664
665 /* Retrieve pointer to the state */
666 pState = (PSTATE)GetWindowLongPtr (hwndDlg, GWL_USERDATA);
667
668 switch (uMsg)
669 {
670 case WM_INITDIALOG:
671 /* Save pointer to the state */
672 pState = (PSTATE)lParam;
673 SetWindowLongPtr(hwndDlg, GWL_USERDATA, (DWORD_PTR)pState);
674
675 /* Center the dialog window */
676 CenterWindow(hwndDlg);
677
678 EnableWindow(GetDlgItem(hwndDlg, IDCANCEL), FALSE);
679 return FALSE;
680
681 case WM_DRAWITEM:
682 OnDrawItem((LPDRAWITEMSTRUCT)lParam,
683 pState,
684 IDC_STARTLOGO);
685 return TRUE;
686
687 case WM_COMMAND:
688 if (HIWORD(wParam) == BN_CLICKED)
689 {
690 switch (LOWORD(wParam))
691 {
692 case IDC_RUN:
693 pState->NextPage = DONE;
694 pState->Run = SHELL;
695 EndDialog(hwndDlg, 0);
696 break;
697
698 case IDC_INSTALL:
699 pState->NextPage = DONE;
700 pState->Run = INSTALLER;
701 EndDialog(hwndDlg, 0);
702 break;
703
704 case IDOK:
705 pState->NextPage = LOCALEPAGE;
706 EndDialog(hwndDlg, 0);
707 break;
708
709 default:
710 break;
711 }
712 }
713 break;
714
715 default:
716 break;
717 }
718
719 return FALSE;
720 }
721
722
723 VOID
724 RunLiveCD(
725 PSTATE pState)
726 {
727 InitImageInfo(&pState->ImageInfo);
728
729 while (pState->NextPage != DONE)
730 {
731 switch (pState->NextPage)
732 {
733 case LOCALEPAGE:
734 DialogBoxParam(hInstance,
735 MAKEINTRESOURCE(IDD_LOCALEPAGE),
736 NULL,
737 LocaleDlgProc,
738 (LPARAM)pState);
739 break;
740
741 case STARTPAGE:
742 DialogBoxParam(hInstance,
743 MAKEINTRESOURCE(IDD_STARTPAGE),
744 NULL,
745 StartDlgProc,
746 (LPARAM)pState);
747 break;
748
749 default:
750 break;
751 }
752 }
753
754 DeleteObject(pState->ImageInfo.hBitmap);
755 }
756
757 /* EOF */