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
14 typedef struct _LIVECD_UNATTEND
22 * Taken and adapted from dll/cpl/sysdm/general.c
25 InitLogo(PIMGINFO pImgInfo
, HWND hwndDlg
)
30 HDC hDC
, hDCLogo
, hDCMask
;
31 HBITMAP hMask
= NULL
, hLogo
= NULL
;
32 HBITMAP hAlphaLogo
= NULL
;
37 hDCLogo
= CreateCompatibleDC(NULL
);
38 hDCMask
= CreateCompatibleDC(NULL
);
40 if (hDC
== NULL
|| hDCLogo
== NULL
|| hDCMask
== NULL
)
43 ZeroMemory(pImgInfo
, sizeof(*pImgInfo
));
44 ZeroMemory(&bmpi
, sizeof(bmpi
));
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
);
49 if (hLogo
== NULL
|| hMask
== NULL
)
52 GetObject(hLogo
, sizeof(logoBitmap
), &logoBitmap
);
53 GetObject(hMask
, sizeof(maskBitmap
), &maskBitmap
);
55 if (logoBitmap
.bmHeight
!= maskBitmap
.bmHeight
|| logoBitmap
.bmWidth
!= maskBitmap
.bmWidth
)
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
;
66 /* Create a premultiplied bitmap */
67 hAlphaLogo
= CreateDIBSection(hDC
, &bmpi
, DIB_RGB_COLORS
, (PVOID
*)&pBits
, 0, 0);
71 SelectObject(hDCLogo
, hLogo
);
72 SelectObject(hDCMask
, hMask
);
74 for (line
= logoBitmap
.bmHeight
- 1; line
>= 0; line
--)
76 for (column
= 0; column
< logoBitmap
.bmWidth
; column
++)
78 COLORREF alpha
= GetPixel(hDCMask
, column
, line
) & 0xFF;
79 COLORREF Color
= GetPixel(hDCLogo
, column
, line
);
82 r
= GetRValue(Color
) * alpha
/ 255;
83 g
= GetGValue(Color
) * alpha
/ 255;
84 b
= GetBValue(Color
) * alpha
/ 255;
86 *pBits
++ = b
| (g
<< 8) | (r
<< 16) | (alpha
<< 24);
90 pImgInfo
->hBitmap
= hAlphaLogo
;
91 pImgInfo
->cxSource
= logoBitmap
.bmWidth
;
92 pImgInfo
->cySource
= logoBitmap
.bmHeight
;
93 pImgInfo
->iBits
= logoBitmap
.bmBitsPixel
;
94 pImgInfo
->iPlanes
= logoBitmap
.bmPlanes
;
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
);
108 HKEY ControlKey
= NULL
;
109 LPWSTR SystemStartOptions
= NULL
;
110 LPWSTR CurrentOption
, NextOption
; /* Pointers into SystemStartOptions */
114 TRACE("IsLiveCD()\n");
116 rc
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
117 REGSTR_PATH_CURRENT_CONTROL_SET
,
121 if (rc
!= ERROR_SUCCESS
)
123 WARN("RegOpenKeyEx() failed with error %lu\n", rc
);
127 rc
= ReadRegSzKey(ControlKey
, L
"SystemStartOptions", &SystemStartOptions
);
128 if (rc
!= ERROR_SUCCESS
)
130 WARN("ReadRegSzKey() failed with error %lu\n", rc
);
134 /* Check for CONSOLE switch in SystemStartOptions */
135 CurrentOption
= SystemStartOptions
;
136 while (CurrentOption
)
138 NextOption
= wcschr(CurrentOption
, L
' ');
141 if (_wcsicmp(CurrentOption
, L
"MININT") == 0)
143 TRACE("Found 'MININT' boot option\n");
147 CurrentOption
= NextOption
? NextOption
+ 1 : NULL
;
151 if (ControlKey
!= NULL
)
152 RegCloseKey(ControlKey
);
153 HeapFree(GetProcessHeap(), 0, SystemStartOptions
);
155 TRACE("IsLiveCD() returning %d\n", ret
);
162 LocalesEnumProc(LPTSTR lpLocale
)
167 BOOL bNoShow
= FALSE
;
169 lcid
= wcstoul(lpLocale
, NULL
, 16);
171 /* Display only languages with installed support */
172 if (!IsValidLocale(lcid
, LCID_INSTALLED
))
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
))
181 LoadStringW(hInstance
, IDS_SPAIN
, lang
, ARRAYSIZE(lang
));
191 GetLocaleInfoW(lcid
, LOCALE_SLANGUAGE
, lang
, ARRAYSIZE(lang
));
194 if (bNoShow
== FALSE
)
196 index
= SendMessageW(hList
,
212 CreateLanguagesList(HWND hwnd
, PSTATE pState
)
219 EnumSystemLocalesW(LocalesEnumProc
, LCID_SUPPORTED
);
221 if (pState
->Unattend
->bEnabled
)
222 Locale
= pState
->Unattend
->LocaleID
;
226 /* Select current locale */
227 /* or should it be System and not user? */
228 Locale
= GetUserDefaultLCID();
230 GetLocaleInfoW(Locale
, LOCALE_SLANGUAGE
, langSel
, ARRAYSIZE(langSel
));
247 WCHAR szBuf
[MAX_PATH
], szDispName
[MAX_PATH
], szIndex
[MAX_PATH
], szPath
[MAX_PATH
];
251 wsprintf(szBuf
, L
"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\%s", szLCID
);
253 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
, (LPCTSTR
)szBuf
, 0, KEY_QUERY_VALUE
, &hKey
) == ERROR_SUCCESS
)
255 dwBufLen
= sizeof(szDispName
);
257 if (RegQueryValueExW(hKey
, L
"Layout Display Name", NULL
, NULL
, (LPBYTE
)szDispName
, &dwBufLen
) == ERROR_SUCCESS
)
259 if (szDispName
[0] == '@')
261 for (i
= 0; i
< wcslen(szDispName
); i
++)
263 if ((szDispName
[i
] == ',') && (szDispName
[i
+ 1] == '-'))
265 for (j
= i
+ 2, k
= 0; j
< wcslen(szDispName
)+1; j
++, k
++)
267 szIndex
[k
] = szDispName
[j
];
269 szDispName
[i
- 1] = '\0';
273 szDispName
[i
] = szDispName
[i
+ 1];
276 if (ExpandEnvironmentStringsW(szDispName
, szPath
, ARRAYSIZE(szPath
)))
278 hLib
= LoadLibraryW(szPath
);
281 if (LoadStringW(hLib
, _wtoi(szIndex
), szPath
, ARRAYSIZE(szPath
)) != 0)
283 wcscpy(szName
, szPath
);
293 dwBufLen
= sizeof(szBuf
);
295 if (RegQueryValueExW(hKey
, L
"Layout Text", NULL
, NULL
, (LPBYTE
)szName
, &dwBufLen
) == ERROR_SUCCESS
)
316 iCurSel
= SendMessageW(hwnd
, CB_GETCURSEL
, 0, 0);
317 if (iCurSel
== CB_ERR
)
320 ulLayoutId
= (ULONG
)SendMessageW(hwnd
, CB_GETITEMDATA
, iCurSel
, 0);
321 if (ulLayoutId
== (ULONG
)CB_ERR
)
324 swprintf(szLayoutId
, L
"%08lx", ulLayoutId
);
326 hKl
= LoadKeyboardLayoutW(szLayoutId
, KLF_ACTIVATE
| KLF_REPLACELANG
| KLF_SETFORPROCESS
);
327 SystemParametersInfoW(SPI_SETDEFAULTINPUTLANG
, 0, &hKl
, SPIF_SENDCHANGE
);
333 SelectKeyboardForLanguage(
340 TRACE("LCID: %08lx\n", lcid
);
341 TRACE("LangID: %04lx\n", LANGIDFROMLCID(lcid
));
343 nCount
= SendMessageW(hwnd
, CB_GETCOUNT
, 0, 0);
345 for (i
= 0; i
< nCount
; i
++)
347 LayoutId
= (LCID
)SendMessageW(hwnd
, CB_GETITEMDATA
, i
, 0);
348 TRACE("Layout: %08lx\n", LayoutId
);
350 if (LANGIDFROMLCID(LayoutId
) == LANGIDFROMLCID(lcid
))
352 TRACE("Found 1: %08lx --> %08lx\n", LayoutId
, lcid
);
353 SendMessageW(hwnd
, CB_SETCURSEL
, i
, 0);
358 for (i
= 0; i
< nCount
; i
++)
360 LayoutId
= (LCID
)SendMessageW(hwnd
, CB_GETITEMDATA
, i
, 0);
361 TRACE("Layout: %08lx\n", LayoutId
);
363 if (PRIMARYLANGID(LayoutId
) == PRIMARYLANGID(lcid
))
365 TRACE("Found 2: %08lx --> %08lx\n", LayoutId
, lcid
);
366 SendMessageW(hwnd
, CB_SETCURSEL
, i
, 0);
371 TRACE("No match found!\n");
377 CreateKeyboardLayoutList(
381 WCHAR szLayoutId
[9], szCurrentLayoutId
[9];
382 WCHAR KeyName
[MAX_PATH
];
389 if (!GetKeyboardLayoutNameW(szCurrentLayoutId
))
390 wcscpy(szCurrentLayoutId
, L
"00000409");
392 lError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
393 L
"System\\CurrentControlSet\\Control\\Keyboard Layouts",
395 KEY_ENUMERATE_SUB_KEYS
,
397 if (lError
!= ERROR_SUCCESS
)
402 dwSize
= ARRAYSIZE(szLayoutId
);
404 lError
= RegEnumKeyExW(hKey
,
412 if (lError
!= ERROR_SUCCESS
)
415 GetLayoutName(szLayoutId
, KeyName
);
417 iIndex
= (INT
)SendMessageW(hItemsList
, CB_ADDSTRING
, 0, (LPARAM
)KeyName
);
419 ulLayoutId
= wcstoul(szLayoutId
, NULL
, 16);
420 SendMessageW(hItemsList
, CB_SETITEMDATA
, iIndex
, (LPARAM
)ulLayoutId
);
422 if (wcscmp(szLayoutId
, szCurrentLayoutId
) == 0)
424 SendMessageW(hItemsList
, CB_SETCURSEL
, (WPARAM
)iIndex
, (LPARAM
)0);
436 InitializeDefaultUserLocale(
447 struct {LCTYPE LCType
; PWSTR pValue
;} LocaleData
[] = {
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"},
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"},
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"},
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"},
490 {LOCALE_SCOUNTRY
, L
"sCountry"},
491 {LOCALE_SABBREVLANGNAME
, L
"sLanguage"},
492 {LOCALE_ICOUNTRY
, L
"iCountry"},
495 ret
= RegOpenKeyExW(HKEY_USERS
,
496 L
".DEFAULT\\Control Panel\\International",
498 KEY_READ
| KEY_WRITE
,
500 if (ret
!= ERROR_SUCCESS
)
505 if (pNewLcid
== NULL
)
507 dwSize
= 9 * sizeof(WCHAR
);
508 ret
= RegQueryValueExW(hLocaleKey
,
514 if (ret
!= ERROR_SUCCESS
)
517 lcid
= (LCID
)wcstoul(szBuffer
, &ptr
, 16);
525 swprintf(szBuffer
, L
"%08lx", lcid
);
526 RegSetValueExW(hLocaleKey
,
531 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
535 while (LocaleData
[i
].pValue
!= NULL
)
537 if (GetLocaleInfoW(lcid
,
538 LocaleData
[i
].LCType
| LOCALE_NOUSEROVERRIDE
,
540 ARRAYSIZE(szBuffer
)))
542 RegSetValueExW(hLocaleKey
,
543 LocaleData
[i
].pValue
,
547 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
554 RegCloseKey(hLocaleKey
);
559 CenterWindow(HWND hWnd
)
565 hWndParent
= GetParent(hWnd
);
566 if (hWndParent
== NULL
)
567 hWndParent
= GetDesktopWindow();
569 GetWindowRect(hWndParent
, &rcParent
);
570 GetWindowRect(hWnd
, &rcWindow
);
574 ((rcParent
.right
- rcParent
.left
) - (rcWindow
.right
- rcWindow
.left
)) / 2,
575 ((rcParent
.bottom
- rcParent
.top
) - (rcWindow
.bottom
- rcWindow
.top
)) / 2,
585 LPDRAWITEMSTRUCT lpDrawItem
,
592 if (lpDrawItem
->CtlID
== uCtlID
)
594 /* Position image in centre of dialog */
595 left
= (lpDrawItem
->rcItem
.right
- pState
->ImageInfo
.cxSource
) / 2;
597 hdcMem
= CreateCompatibleDC(lpDrawItem
->hDC
);
600 static BLENDFUNCTION BlendFunc
= {AC_SRC_OVER
, 0, 255, AC_SRC_ALPHA
};
602 SelectObject(hdcMem
, pState
->ImageInfo
.hBitmap
);
603 GdiAlphaBlend(lpDrawItem
->hDC
,
605 lpDrawItem
->rcItem
.top
,
606 pState
->ImageInfo
.cxSource
,
607 pState
->ImageInfo
.cySource
,
610 pState
->ImageInfo
.cxSource
,
611 pState
->ImageInfo
.cySource
,
630 /* Retrieve pointer to the state */
631 pState
= (PSTATE
)GetWindowLongPtrW(hwndDlg
, GWLP_USERDATA
);
636 /* Save pointer to the global state */
637 pState
= (PSTATE
)lParam
;
638 SetWindowLongPtrW(hwndDlg
, GWLP_USERDATA
, (DWORD_PTR
)pState
);
640 /* Center the dialog window */
641 CenterWindow(hwndDlg
);
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
)
648 // Advance to the next page
649 PostMessageW(hwndDlg
, WM_COMMAND
, MAKELONG(IDOK
, BN_CLICKED
), 0L);
654 OnDrawItem((LPDRAWITEMSTRUCT
)lParam
,
660 switch (LOWORD(wParam
))
662 case IDC_LANGUAGELIST
:
663 if (HIWORD(wParam
) == CBN_SELCHANGE
)
668 iCurSel
= SendDlgItemMessageW(hwndDlg
,
673 if (iCurSel
== CB_ERR
)
676 NewLcid
= SendDlgItemMessageW(hwndDlg
,
681 if (NewLcid
== (LCID
)CB_ERR
)
684 TRACE("LCID: 0x%08lx\n", NewLcid
);
685 SelectKeyboardForLanguage(GetDlgItem(hwndDlg
, IDC_LAYOUTLIST
),
691 if (HIWORD(wParam
) == BN_CLICKED
)
696 iCurSel
= SendDlgItemMessageW(hwndDlg
,
701 if (iCurSel
== CB_ERR
)
704 NewLcid
= SendDlgItemMessageW(hwndDlg
,
709 if (NewLcid
== (LCID
)CB_ERR
)
712 /* Set the locale for the current thread */
713 NtSetDefaultLocale(TRUE
, NewLcid
);
715 /* Store the locale settings in the registry */
716 InitializeDefaultUserLocale(&NewLcid
);
718 SetKeyboardLayout(GetDlgItem(hwndDlg
, IDC_LAYOUTLIST
));
720 pState
->NextPage
= STARTPAGE
;
721 EndDialog(hwndDlg
, LOWORD(wParam
));
726 if (HIWORD(wParam
) == BN_CLICKED
)
728 static WCHAR szMsg
[RC_STRING_MAX_SIZE
];
730 LoadStringW(GetModuleHandle(NULL
), IDS_CANCEL_CONFIRM
, szMsg
, ARRAYSIZE(szMsg
));
731 ret
= MessageBoxW(hwndDlg
, szMsg
, L
"ReactOS LiveCD", MB_ICONWARNING
| MB_YESNO
| MB_DEFBUTTON2
);
732 if (ret
== IDOK
|| ret
== IDYES
)
734 pState
->NextPage
= DONE
;
735 pState
->Run
= REBOOT
;
736 EndDialog(hwndDlg
, LOWORD(wParam
));
765 /* Retrieve pointer to the state */
766 pState
= (PSTATE
)GetWindowLongPtrW(hwndDlg
, GWLP_USERDATA
);
771 /* Save pointer to the state */
772 pState
= (PSTATE
)lParam
;
773 SetWindowLongPtrW(hwndDlg
, GWLP_USERDATA
, (DWORD_PTR
)pState
);
775 /* Center the dialog window */
776 CenterWindow(hwndDlg
);
778 if (pState
->Unattend
->bEnabled
)
780 // Click on the 'Run' button
781 PostMessageW(hwndDlg
, WM_COMMAND
, MAKELONG(IDC_RUN
, BN_CLICKED
), 0L);
787 OnDrawItem((LPDRAWITEMSTRUCT
)lParam
,
793 if (HIWORD(wParam
) == BN_CLICKED
)
795 switch (LOWORD(wParam
))
798 pState
->NextPage
= DONE
;
800 EndDialog(hwndDlg
, LOWORD(wParam
));
804 pState
->NextPage
= DONE
;
805 pState
->Run
= INSTALLER
;
806 EndDialog(hwndDlg
, LOWORD(wParam
));
810 pState
->NextPage
= LOCALEPAGE
;
811 EndDialog(hwndDlg
, LOWORD(wParam
));
815 if (HIWORD(wParam
) == BN_CLICKED
)
817 static WCHAR szMsg
[RC_STRING_MAX_SIZE
];
819 LoadStringW(GetModuleHandle(NULL
), IDS_CANCEL_CONFIRM
, szMsg
, ARRAYSIZE(szMsg
));
820 ret
= MessageBoxW(hwndDlg
, szMsg
, L
"ReactOS LiveCD", MB_ICONWARNING
| MB_YESNO
| MB_DEFBUTTON2
);
821 if (ret
== IDOK
|| ret
== IDYES
)
823 pState
->NextPage
= DONE
;
824 pState
->Run
= REBOOT
;
825 EndDialog(hwndDlg
, LOWORD(wParam
));
843 VOID
ParseUnattend(LPCWSTR UnattendInf
, LIVECD_UNATTEND
* pUnattend
)
845 WCHAR Buffer
[MAX_PATH
];
847 pUnattend
->bEnabled
= FALSE
;
849 if (!GetPrivateProfileStringW(L
"Unattend", L
"Signature", L
"", Buffer
, _countof(Buffer
), UnattendInf
))
851 ERR("Unable to parse Signature\n");
855 if (_wcsicmp(Buffer
, L
"$ReactOS$") && _wcsicmp(Buffer
, L
"$Windows NT$"))
857 TRACE("Unknown signature: %S\n", Buffer
);
861 if (!GetPrivateProfileStringW(L
"Unattend", L
"UnattendSetupEnabled", L
"", Buffer
, _countof(Buffer
), UnattendInf
))
863 ERR("Unable to parse UnattendSetupEnabled\n");
867 if (_wcsicmp(Buffer
, L
"yes"))
869 TRACE("Unattended setup is not enabled\n", Buffer
);
873 pUnattend
->bEnabled
= TRUE
;
874 pUnattend
->LocaleID
= 0;
876 if (GetPrivateProfileStringW(L
"Unattend", L
"LocaleID", L
"", Buffer
, _countof(Buffer
), UnattendInf
) && Buffer
[0])
878 pUnattend
->LocaleID
= wcstol(Buffer
, NULL
, 16);
886 LIVECD_UNATTEND Unattend
= {0};
887 WCHAR UnattendInf
[MAX_PATH
];
889 InitLogo(&pState
->ImageInfo
, NULL
);
891 GetWindowsDirectoryW(UnattendInf
, _countof(UnattendInf
));
892 wcscat(UnattendInf
, L
"\\unattend.inf");
893 ParseUnattend(UnattendInf
, &Unattend
);
894 pState
->Unattend
= &Unattend
;
896 while (pState
->NextPage
!= DONE
)
898 switch (pState
->NextPage
)
901 DialogBoxParamW(hInstance
,
902 MAKEINTRESOURCEW(IDD_LOCALEPAGE
),
909 DialogBoxParamW(hInstance
,
910 MAKEINTRESOURCEW(IDD_STARTPAGE
),
921 DeleteObject(pState
->ImageInfo
.hBitmap
);