reactos/dll/win32/syssetup/wizard.c
Stanislav Motylkov 17cb1e1a04
[SYSSETUP] Add placeholders for IDC_LOCALETEXT and IDC_LAYOUTTEXT
The window initialization handler code should update these properly,
but for now just put empty strings there until it's implemented.

This makes reviewing dialog layout easier in visual resource editors
like Resource Hacker and others, so the translation maintenance takes
much less time.

We already use this technique in some other modules like sysdm and zipfldr.

Spotted by Can Taşan. Fix suggested by Thomas Faber.

Additionally:
- Fix position of some elements to avoid overlapping
- Fix some headers according to the latest coding style
2021-10-24 00:12:18 +03:00

2939 lines
90 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: System setup
* FILE: dll/win32/syssetup/wizard.c
* PURPOSE: GUI controls
* PROGRAMMERS: Eric Kohl
* Pierre Schweitzer <heis_spiter@hotmail.com>
* Ismael Ferreras Morezuelas <swyterzone+ros@gmail.com>
* Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
/* INCLUDES *****************************************************************/
#include "precomp.h"
#include <stdlib.h>
#include <time.h>
#include <winnls.h>
#include <windowsx.h>
#include <wincon.h>
#include <shlobj.h>
#include <tzlib.h>
#include <strsafe.h>
#define NDEBUG
#include <debug.h>
#define PM_REGISTRATION_NOTIFY (WM_APP + 1)
/* Private Message used to communicate progress from the background
registration thread to the main thread.
wParam = 0 Registration in progress
= 1 Registration completed
lParam = Pointer to a REGISTRATIONNOTIFY structure */
typedef struct _REGISTRATIONNOTIFY
{
ULONG Progress;
UINT ActivityID;
LPCWSTR CurrentItem;
LPCWSTR ErrorMessage;
} REGISTRATIONNOTIFY, *PREGISTRATIONNOTIFY;
typedef struct _REGISTRATIONDATA
{
HWND hwndDlg;
ULONG DllCount;
ULONG Registered;
PVOID DefaultContext;
} REGISTRATIONDATA, *PREGISTRATIONDATA;
typedef struct _TIMEZONE_ENTRY
{
struct _TIMEZONE_ENTRY *Prev;
struct _TIMEZONE_ENTRY *Next;
WCHAR Description[128]; /* 'Display' */
WCHAR StandardName[32]; /* 'Std' */
WCHAR DaylightName[32]; /* 'Dlt' */
REG_TZI_FORMAT TimezoneInfo; /* 'TZI' */
ULONG Index;
} TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
/* FUNCTIONS ****************************************************************/
extern void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
static VOID
CenterWindow(HWND hWnd)
{
HWND hWndParent;
RECT rcParent;
RECT rcWindow;
hWndParent = GetParent(hWnd);
if (hWndParent == NULL)
hWndParent = GetDesktopWindow();
GetWindowRect(hWndParent, &rcParent);
GetWindowRect(hWnd, &rcWindow);
SetWindowPos(hWnd,
HWND_TOP,
((rcParent.right - rcParent.left) - (rcWindow.right - rcWindow.left)) / 2,
((rcParent.bottom - rcParent.top) - (rcWindow.bottom - rcWindow.top)) / 2,
0,
0,
SWP_NOSIZE);
}
static HFONT
CreateTitleFont(VOID)
{
LOGFONTW LogFont = {0};
HDC hdc;
HFONT hFont;
LogFont.lfWeight = FW_BOLD;
wcscpy(LogFont.lfFaceName, L"MS Shell Dlg");
hdc = GetDC(NULL);
LogFont.lfHeight = -MulDiv(12, GetDeviceCaps(hdc, LOGPIXELSY), 72);
hFont = CreateFontIndirectW(&LogFont);
ReleaseDC(NULL, hdc);
return hFont;
}
static HFONT
CreateBoldFont(VOID)
{
LOGFONTW tmpFont = {0};
HFONT hBoldFont;
HDC hDc;
/* Grabs the Drawing Context */
hDc = GetDC(NULL);
tmpFont.lfHeight = -MulDiv(8, GetDeviceCaps(hDc, LOGPIXELSY), 72);
tmpFont.lfWeight = FW_BOLD;
wcscpy(tmpFont.lfFaceName, L"MS Shell Dlg");
hBoldFont = CreateFontIndirectW(&tmpFont);
ReleaseDC(NULL, hDc);
return hBoldFont;
}
static INT_PTR CALLBACK
GplDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
HRSRC GplTextResource;
HGLOBAL GplTextMem;
PVOID GplTextLocked;
PCHAR GplText;
DWORD Size;
switch (uMsg)
{
case WM_INITDIALOG:
GplTextResource = FindResourceW(hDllInstance, MAKEINTRESOURCE(IDR_GPL), L"RT_TEXT");
if (NULL == GplTextResource)
{
break;
}
Size = SizeofResource(hDllInstance, GplTextResource);
if (0 == Size)
{
break;
}
GplText = HeapAlloc(GetProcessHeap(), 0, Size + 1);
if (NULL == GplText)
{
break;
}
GplTextMem = LoadResource(hDllInstance, GplTextResource);
if (NULL == GplTextMem)
{
HeapFree(GetProcessHeap(), 0, GplText);
break;
}
GplTextLocked = LockResource(GplTextMem);
if (NULL == GplTextLocked)
{
HeapFree(GetProcessHeap(), 0, GplText);
break;
}
memcpy(GplText, GplTextLocked, Size);
GplText[Size] = '\0';
SendMessageA(GetDlgItem(hwndDlg, IDC_GPL_TEXT), WM_SETTEXT, 0, (LPARAM) GplText);
HeapFree(GetProcessHeap(), 0, GplText);
SetFocus(GetDlgItem(hwndDlg, IDOK));
return FALSE;
case WM_CLOSE:
EndDialog(hwndDlg, IDCANCEL);
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED && IDOK == LOWORD(wParam))
{
EndDialog(hwndDlg, IDOK);
}
break;
default:
break;
}
return FALSE;
}
static INT_PTR CALLBACK
WelcomeDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PSETUPDATA pSetupData;
pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
{
HWND hwndControl;
DWORD dwStyle;
/* Get pointer to the global setup data */
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData);
hwndControl = GetParent(hwndDlg);
/* Center the wizard window */
CenterWindow (hwndControl);
/* Hide the system menu */
dwStyle = GetWindowLongPtr(hwndControl, GWL_STYLE);
SetWindowLongPtr(hwndControl, GWL_STYLE, dwStyle & ~WS_SYSMENU);
/* Hide and disable the 'Cancel' button */
hwndControl = GetDlgItem(GetParent(hwndDlg), IDCANCEL);
ShowWindow (hwndControl, SW_HIDE);
EnableWindow (hwndControl, FALSE);
/* Set title font */
SendDlgItemMessage(hwndDlg,
IDC_WELCOMETITLE,
WM_SETFONT,
(WPARAM)pSetupData->hTitleFont,
(LPARAM)TRUE);
}
break;
case WM_NOTIFY:
{
LPNMHDR lpnm = (LPNMHDR)lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE:
LogItem(L"BEGIN", L"WelcomePage");
/* Enable the Next button */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
if (pSetupData->UnattendSetup)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_ACKPAGE);
return TRUE;
}
break;
case PSN_WIZNEXT:
LogItem(L"END", L"WelcomePage");
break;
case PSN_WIZBACK:
pSetupData->UnattendSetup = FALSE;
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
static INT_PTR CALLBACK
AckPageDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
LPNMHDR lpnm;
PWCHAR Projects;
PWCHAR End, CurrentProject;
INT ProjectsSize, ProjectsCount;
PSETUPDATA pSetupData;
pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
{
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData);
Projects = NULL;
ProjectsSize = 256;
while (TRUE)
{
Projects = HeapAlloc(GetProcessHeap(), 0, ProjectsSize * sizeof(WCHAR));
if (NULL == Projects)
{
return FALSE;
}
ProjectsCount = LoadStringW(hDllInstance, IDS_ACKPROJECTS, Projects, ProjectsSize);
if (0 == ProjectsCount)
{
HeapFree(GetProcessHeap(), 0, Projects);
return FALSE;
}
if (ProjectsCount < ProjectsSize - 1)
{
break;
}
HeapFree(GetProcessHeap(), 0, Projects);
ProjectsSize *= 2;
}
CurrentProject = Projects;
while (*CurrentProject != L'\0')
{
End = wcschr(CurrentProject, L'\n');
if (NULL != End)
{
*End = L'\0';
}
(void)ListBox_AddString(GetDlgItem(hwndDlg, IDC_PROJECTS), CurrentProject);
if (NULL != End)
{
CurrentProject = End + 1;
}
else
{
CurrentProject += wcslen(CurrentProject);
}
}
HeapFree(GetProcessHeap(), 0, Projects);
}
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED && IDC_VIEWGPL == LOWORD(wParam))
{
DialogBox(hDllInstance, MAKEINTRESOURCE(IDD_GPL), NULL, GplDlgProc);
SetForegroundWindow(GetParent(hwndDlg));
}
break;
case WM_NOTIFY:
{
lpnm = (LPNMHDR)lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE:
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (pSetupData->UnattendSetup)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_PRODUCT);
return TRUE;
}
break;
case PSN_WIZBACK:
pSetupData->UnattendSetup = FALSE;
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
static const WCHAR s_szProductOptions[] = L"SYSTEM\\CurrentControlSet\\Control\\ProductOptions";
static const WCHAR s_szRosVersion[] = L"SYSTEM\\CurrentControlSet\\Control\\ReactOS\\Settings\\Version";
static const WCHAR s_szControlWindows[] = L"SYSTEM\\CurrentControlSet\\Control\\Windows";
static const WCHAR s_szWinlogon[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon";
typedef struct _PRODUCT_OPTION_DATA
{
LPCWSTR ProductSuite;
LPCWSTR ProductType;
DWORD ReportAsWorkstation;
DWORD CSDVersion;
DWORD LogonType;
} PRODUCT_OPTION_DATA;
static const PRODUCT_OPTION_DATA s_ProductOptionData[] =
{
{ L"Terminal Server\0", L"ServerNT", 0, 0x200, 0 },
{ L"\0", L"WinNT", 1, 0x300, 1 }
};
static BOOL
DoWriteProductOption(PRODUCT_OPTION nOption)
{
HKEY hKey;
LONG error;
LPCWSTR pszData;
DWORD dwValue, cbData;
const PRODUCT_OPTION_DATA *pData = &s_ProductOptionData[nOption];
ASSERT(0 <= nOption && nOption < _countof(s_ProductOptionData));
/* open ProductOptions key */
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szProductOptions, 0, KEY_WRITE, &hKey);
if (error)
{
DPRINT1("RegOpenKeyExW failed\n");
goto Error;
}
/* write ProductSuite */
pszData = pData->ProductSuite;
cbData = (lstrlenW(pszData) + 2) * sizeof(WCHAR);
error = RegSetValueExW(hKey, L"ProductSuite", 0, REG_MULTI_SZ, (const BYTE *)pszData, cbData);
if (error)
{
DPRINT1("RegSetValueExW failed\n");
goto Error;
}
/* write ProductType */
pszData = pData->ProductType;
cbData = (lstrlenW(pszData) + 1) * sizeof(WCHAR);
error = RegSetValueExW(hKey, L"ProductType", 0, REG_SZ, (const BYTE *)pszData, cbData);
if (error)
{
DPRINT1("RegSetValueExW failed\n");
goto Error;
}
RegCloseKey(hKey);
/* open ReactOS version key */
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szRosVersion, 0, KEY_WRITE, &hKey);
if (error)
{
DPRINT1("RegOpenKeyExW failed\n");
goto Error;
}
/* write ReportAsWorkstation */
dwValue = pData->ReportAsWorkstation;
cbData = sizeof(dwValue);
error = RegSetValueExW(hKey, L"ReportAsWorkstation", 0, REG_DWORD, (const BYTE *)&dwValue, cbData);
if (error)
{
DPRINT1("RegSetValueExW failed\n");
goto Error;
}
RegCloseKey(hKey);
/* open Control Windows key */
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szControlWindows, 0, KEY_WRITE, &hKey);
if (error)
{
DPRINT1("RegOpenKeyExW failed\n");
goto Error;
}
/* write Control Windows CSDVersion */
dwValue = pData->CSDVersion;
cbData = sizeof(dwValue);
error = RegSetValueExW(hKey, L"CSDVersion", 0, REG_DWORD, (const BYTE *)&dwValue, cbData);
if (error)
{
DPRINT1("RegSetValueExW failed\n");
goto Error;
}
RegCloseKey(hKey);
/* open Winlogon key */
error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, s_szWinlogon, 0, KEY_WRITE, &hKey);
if (error)
{
DPRINT1("RegOpenKeyExW failed\n");
goto Error;
}
/* write LogonType */
dwValue = pData->LogonType;
cbData = sizeof(dwValue);
error = RegSetValueExW(hKey, L"LogonType", 0, REG_DWORD, (const BYTE *)&dwValue, cbData);
if (error)
{
DPRINT1("RegSetValueExW failed\n");
goto Error;
}
Error:
if (hKey)
RegCloseKey(hKey);
return error == ERROR_SUCCESS;
}
static void
OnChooseOption(HWND hwndDlg, PRODUCT_OPTION nOption)
{
WCHAR szText[256];
ASSERT(0 <= nOption && nOption < _countof(s_ProductOptionData));
switch (nOption)
{
case PRODUCT_OPTION_SERVER:
LoadStringW(hDllInstance, IDS_PRODUCTSERVERINFO, szText, _countof(szText));
break;
case PRODUCT_OPTION_WORKSTATION:
LoadStringW(hDllInstance, IDS_PRODUCTWORKSTATIONINFO, szText, _countof(szText));
break;
default:
return;
}
SetDlgItemTextW(hwndDlg, IDC_PRODUCT_DESCRIPTION, szText);
}
static INT_PTR CALLBACK
ProductPageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
LPNMHDR lpnm;
PSETUPDATA pSetupData;
INT iItem;
WCHAR szText[64], szDefault[64];
HICON hIcon;
pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
{
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData);
LoadStringW(hDllInstance, IDS_DEFAULT, szDefault, _countof(szDefault));
LoadStringW(hDllInstance, IDS_PRODUCTSERVERNAME, szText, _countof(szText));
if (PRODUCT_OPTION_DEFAULT == PRODUCT_OPTION_SERVER)
{
StringCchCatW(szText, _countof(szText), L" ");
StringCchCatW(szText, _countof(szText), szDefault);
}
SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_ADDSTRING, 0, (LPARAM)szText);
LoadStringW(hDllInstance, IDS_PRODUCTWORKSTATIONNAME, szText, _countof(szText));
if (PRODUCT_OPTION_DEFAULT == PRODUCT_OPTION_WORKSTATION)
{
StringCchCatW(szText, _countof(szText), L" ");
StringCchCatW(szText, _countof(szText), szDefault);
}
SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_ADDSTRING, 0, (LPARAM)szText);
SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_SETCURSEL, PRODUCT_OPTION_DEFAULT, 0);
OnChooseOption(hwndDlg, PRODUCT_OPTION_DEFAULT);
hIcon = LoadIcon(NULL, IDI_WINLOGO);
SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_ICON, STM_SETICON, (WPARAM)hIcon, 0);
return TRUE;
}
case WM_COMMAND:
if (HIWORD(wParam) == CBN_SELCHANGE && IDC_PRODUCT_OPTIONS == LOWORD(wParam))
{
iItem = SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_GETCURSEL, 0, 0);
OnChooseOption(hwndDlg, (PRODUCT_OPTION)iItem);
}
break;
case WM_NOTIFY:
{
lpnm = (LPNMHDR)lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE:
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (pSetupData->UnattendSetup)
{
OnChooseOption(hwndDlg, pSetupData->ProductOption);
DoWriteProductOption(pSetupData->ProductOption);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_LOCALEPAGE);
return TRUE;
}
break;
case PSN_WIZNEXT:
iItem = SendDlgItemMessageW(hwndDlg, IDC_PRODUCT_OPTIONS, CB_GETCURSEL, 0, 0);
pSetupData->ProductOption = (PRODUCT_OPTION)iItem;
DoWriteProductOption(pSetupData->ProductOption);
break;
case PSN_WIZBACK:
pSetupData->UnattendSetup = FALSE;
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
static
BOOL
WriteOwnerSettings(WCHAR * OwnerName,
WCHAR * OwnerOrganization)
{
HKEY hKey;
LONG res;
res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows NT\\CurrentVersion",
0,
KEY_ALL_ACCESS,
&hKey);
if (res != ERROR_SUCCESS)
{
return FALSE;
}
res = RegSetValueExW(hKey,
L"RegisteredOwner",
0,
REG_SZ,
(LPBYTE)OwnerName,
(wcslen(OwnerName) + 1) * sizeof(WCHAR));
if (res != ERROR_SUCCESS)
{
RegCloseKey(hKey);
return FALSE;
}
res = RegSetValueExW(hKey,
L"RegisteredOrganization",
0,
REG_SZ,
(LPBYTE)OwnerOrganization,
(wcslen(OwnerOrganization) + 1) * sizeof(WCHAR));
RegCloseKey(hKey);
return (res == ERROR_SUCCESS);
}
static INT_PTR CALLBACK
OwnerPageDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
WCHAR OwnerName[51];
WCHAR OwnerOrganization[51];
WCHAR Title[64];
WCHAR ErrorName[256];
LPNMHDR lpnm;
PSETUPDATA pSetupData;
pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
switch (uMsg)
{
case WM_INITDIALOG:
{
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData);
/* set a localized ('Owner') placeholder string as default */
if (LoadStringW(hDllInstance, IDS_MACHINE_OWNER_NAME, OwnerName, _countof(OwnerName)))
{
SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, WM_SETTEXT, 0, (LPARAM)OwnerName);
}
SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, EM_LIMITTEXT, 50, 0);
SendDlgItemMessage(hwndDlg, IDC_OWNERORGANIZATION, EM_LIMITTEXT, 50, 0);
/* Set focus to owner name */
SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME));
/* Select the default text to quickly overwrite it by typing */
SendDlgItemMessage(hwndDlg, IDC_OWNERNAME, EM_SETSEL, 0, -1);
}
break;
case WM_NOTIFY:
{
lpnm = (LPNMHDR)lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE:
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (pSetupData->UnattendSetup)
{
SendMessage(GetDlgItem(hwndDlg, IDC_OWNERNAME), WM_SETTEXT, 0, (LPARAM)pSetupData->OwnerName);
SendMessage(GetDlgItem(hwndDlg, IDC_OWNERORGANIZATION), WM_SETTEXT, 0, (LPARAM)pSetupData->OwnerOrganization);
if (WriteOwnerSettings(pSetupData->OwnerName, pSetupData->OwnerOrganization))
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_COMPUTERPAGE);
return TRUE;
}
}
break;
case PSN_WIZNEXT:
OwnerName[0] = 0;
if (GetDlgItemTextW(hwndDlg, IDC_OWNERNAME, OwnerName, 50) == 0)
{
if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
{
wcscpy(Title, L"ReactOS Setup");
}
if (0 == LoadStringW(hDllInstance, IDS_WZD_NAME, ErrorName, ARRAYSIZE(ErrorName)))
{
wcscpy(ErrorName, L"Setup cannot continue until you enter your name.");
}
MessageBoxW(hwndDlg, ErrorName, Title, MB_ICONERROR | MB_OK);
SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME));
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
return TRUE;
}
OwnerOrganization[0] = 0;
GetDlgItemTextW(hwndDlg, IDC_OWNERORGANIZATION, OwnerOrganization, 50);
if (!WriteOwnerSettings(OwnerName, OwnerOrganization))
{
SetFocus(GetDlgItem(hwndDlg, IDC_OWNERNAME));
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
return TRUE;
}
case PSN_WIZBACK:
pSetupData->UnattendSetup = FALSE;
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
static
BOOL
WriteComputerSettings(WCHAR * ComputerName, HWND hwndDlg)
{
WCHAR Title[64];
WCHAR ErrorComputerName[256];
LONG lError;
HKEY hKey = NULL;
if (!SetComputerNameW(ComputerName))
{
if (hwndDlg != NULL)
{
if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
{
wcscpy(Title, L"ReactOS Setup");
}
if (0 == LoadStringW(hDllInstance, IDS_WZD_SETCOMPUTERNAME, ErrorComputerName,
ARRAYSIZE(ErrorComputerName)))
{
wcscpy(ErrorComputerName, L"Setup failed to set the computer name.");
}
MessageBoxW(hwndDlg, ErrorComputerName, Title, MB_ICONERROR | MB_OK);
}
return FALSE;
}
/* Set the physical DNS domain */
SetComputerNameExW(ComputerNamePhysicalDnsDomain, L"");
/* Set the physical DNS hostname */
SetComputerNameExW(ComputerNamePhysicalDnsHostname, ComputerName);
/* Set the accounts domain name */
SetAccountsDomainSid(NULL, ComputerName);
/* Now we need to set the Hostname */
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
0,
KEY_SET_VALUE,
&hKey);
if (lError != ERROR_SUCCESS)
{
DPRINT1("RegOpenKeyExW for Tcpip\\Parameters failed (%08lX)\n", lError);
return TRUE;
}
lError = RegSetValueEx(hKey,
L"Hostname",
0,
REG_SZ,
(LPBYTE)ComputerName,
(wcslen(ComputerName) + 1) * sizeof(WCHAR));
if (lError != ERROR_SUCCESS)
{
DPRINT1("RegSetValueEx(\"Hostname\") failed (%08lX)\n", lError);
}
RegCloseKey(hKey);
return TRUE;
}
static
BOOL
WriteDefaultLogonData(LPWSTR Domain)
{
WCHAR szAdministratorName[256];
HKEY hKey = NULL;
LONG lError;
if (LoadStringW(hDllInstance,
IDS_ADMINISTRATOR_NAME,
szAdministratorName,
ARRAYSIZE(szAdministratorName)) == 0)
{
wcscpy(szAdministratorName, L"Administrator");
}
lError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
0,
KEY_SET_VALUE,
&hKey);
if (lError != ERROR_SUCCESS)
return FALSE;
lError = RegSetValueEx(hKey,
L"DefaultDomainName",
0,
REG_SZ,
(LPBYTE)Domain,
(wcslen(Domain)+ 1) * sizeof(WCHAR));
if (lError != ERROR_SUCCESS)
{
DPRINT1("RegSetValueEx(\"DefaultDomainName\") failed!\n");
}
lError = RegSetValueEx(hKey,
L"DefaultUserName",
0,
REG_SZ,
(LPBYTE)szAdministratorName,
(wcslen(szAdministratorName)+ 1) * sizeof(WCHAR));
if (lError != ERROR_SUCCESS)
{
DPRINT1("RegSetValueEx(\"DefaultUserName\") failed!\n");
}
RegCloseKey(hKey);
return TRUE;
}
/* lpBuffer will be filled with a 15-char string (plus the null terminator) */
static void
GenerateComputerName(LPWSTR lpBuffer)
{
static const WCHAR Chars[] = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const unsigned cChars = sizeof(Chars) / sizeof(WCHAR) - 1;
unsigned i;
wcscpy(lpBuffer, L"REACTOS-");
srand(GetTickCount());
/* fill in 7 characters */
for (i = 8; i < 15; i++)
lpBuffer[i] = Chars[rand() % cChars];
lpBuffer[15] = UNICODE_NULL; /* NULL-terminate */
}
static INT_PTR CALLBACK
ComputerPageDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
WCHAR Password1[128];
WCHAR Password2[128];
PWCHAR Password;
WCHAR Title[64];
WCHAR EmptyComputerName[256], NotMatchPassword[256], WrongPassword[256];
LPNMHDR lpnm;
PSETUPDATA pSetupData;
pSetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, DWLP_USER);
if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
{
wcscpy(Title, L"ReactOS Setup");
}
switch (uMsg)
{
case WM_INITDIALOG:
pSetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pSetupData);
/* Generate a new pseudo-random computer name */
GenerateComputerName(ComputerName);
/* Display current computer name */
SetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName);
/* Set text limits */
SendDlgItemMessage(hwndDlg, IDC_COMPUTERNAME, EM_LIMITTEXT, MAX_COMPUTERNAME_LENGTH, 0);
SendDlgItemMessage(hwndDlg, IDC_ADMINPASSWORD1, EM_LIMITTEXT, 127, 0);
SendDlgItemMessage(hwndDlg, IDC_ADMINPASSWORD2, EM_LIMITTEXT, 127, 0);
/* Set focus to computer name */
SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME));
if (pSetupData->UnattendSetup)
{
SendMessage(GetDlgItem(hwndDlg, IDC_COMPUTERNAME), WM_SETTEXT, 0, (LPARAM)pSetupData->ComputerName);
SendMessage(GetDlgItem(hwndDlg, IDC_ADMINPASSWORD1), WM_SETTEXT, 0, (LPARAM)pSetupData->AdminPassword);
SendMessage(GetDlgItem(hwndDlg, IDC_ADMINPASSWORD2), WM_SETTEXT, 0, (LPARAM)pSetupData->AdminPassword);
WriteComputerSettings(pSetupData->ComputerName, NULL);
SetAdministratorPassword(pSetupData->AdminPassword);
}
/* Store the administrator account name as the default user name */
WriteDefaultLogonData(pSetupData->ComputerName);
break;
case WM_NOTIFY:
{
lpnm = (LPNMHDR)lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE:
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (pSetupData->UnattendSetup && WriteComputerSettings(pSetupData->ComputerName, hwndDlg))
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_THEMEPAGE);
return TRUE;
}
break;
case PSN_WIZNEXT:
if (0 == GetDlgItemTextW(hwndDlg, IDC_COMPUTERNAME, ComputerName, MAX_COMPUTERNAME_LENGTH + 1))
{
if (0 == LoadStringW(hDllInstance, IDS_WZD_COMPUTERNAME, EmptyComputerName,
ARRAYSIZE(EmptyComputerName)))
{
wcscpy(EmptyComputerName, L"Setup cannot continue until you enter the name of your computer.");
}
MessageBoxW(hwndDlg, EmptyComputerName, Title, MB_ICONERROR | MB_OK);
SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME));
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
return TRUE;
}
/* No need to check computer name for invalid characters,
* SetComputerName() will do it for us */
if (!WriteComputerSettings(ComputerName, hwndDlg))
{
SetFocus(GetDlgItem(hwndDlg, IDC_COMPUTERNAME));
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
return TRUE;
}
#ifdef PASSWORDS_MANDATORY
/* Check if admin passwords have been entered */
if ((GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD1, Password1, 128) == 0) ||
(GetDlgItemText(hwndDlg, IDC_ADMINPASSWORD2, Password2, 128) == 0))
{
if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDEMPTY, EmptyPassword,
ARRAYSIZE(EmptyPassword)))
{
wcscpy(EmptyPassword, L"You must enter a password !");
}
MessageBoxW(hwndDlg, EmptyPassword, Title, MB_ICONERROR | MB_OK);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
return TRUE;
}
#else
GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD1, Password1, 128);
GetDlgItemTextW(hwndDlg, IDC_ADMINPASSWORD2, Password2, 128);
#endif
/* Check if passwords match */
if (wcscmp(Password1, Password2))
{
if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDMATCH, NotMatchPassword,
ARRAYSIZE(NotMatchPassword)))
{
wcscpy(NotMatchPassword, L"The passwords you entered do not match. Please enter the desired password again.");
}
MessageBoxW(hwndDlg, NotMatchPassword, Title, MB_ICONERROR | MB_OK);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
return TRUE;
}
/* Check password for invalid characters */
Password = (PWCHAR)Password1;
while (*Password)
{
if (!isprint(*Password))
{
if (0 == LoadStringW(hDllInstance, IDS_WZD_PASSWORDCHAR, WrongPassword,
ARRAYSIZE(WrongPassword)))
{
wcscpy(WrongPassword, L"The password you entered contains invalid characters. Please enter a cleaned password.");
}
MessageBoxW(hwndDlg, WrongPassword, Title, MB_ICONERROR | MB_OK);
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
return TRUE;
}
Password++;
}
/* Set admin password */
SetAdministratorPassword(Password1);
break;
case PSN_WIZBACK:
pSetupData->UnattendSetup = FALSE;
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
static VOID
SetUserLocaleName(HWND hwnd)
{
/* FIXME: Set actual locale name */
SetWindowTextW(hwnd, L"");
}
static VOID
SetKeyboardLayoutName(HWND hwnd)
{
#if 0
TCHAR szLayoutPath[256];
TCHAR szLocaleName[32];
DWORD dwLocaleSize;
HKEY hKey;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
_T("SYSTEM\\CurrentControlSet\\Control\\NLS\\Locale"),
0,
KEY_ALL_ACCESS,
&hKey))
return;
dwValueSize = 16 * sizeof(TCHAR);
if (RegQueryValueEx(hKey,
NULL,
NULL,
NULL,
szLocaleName,
&dwLocaleSize))
{
RegCloseKey(hKey);
return;
}
_tcscpy(szLayoutPath,
_T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"));
_tcscat(szLayoutPath,
szLocaleName);
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
szLayoutPath,
0,
KEY_ALL_ACCESS,
&hKey))
return;
dwValueSize = 32 * sizeof(TCHAR);
if (RegQueryValueEx(hKey,
_T("Layout Text"),
NULL,
NULL,
szLocaleName,
&dwLocaleSize))
{
RegCloseKey(hKey);
return;
}
RegCloseKey(hKey);
#else
/* FIXME: Set actual layout name */
SetWindowTextW(hwnd, L"");
#endif
}
static BOOL
RunControlPanelApplet(HWND hwnd, PCWSTR pwszCPLParameters)
{
MSG msg;
STARTUPINFOW StartupInfo;
PROCESS_INFORMATION ProcessInformation;
WCHAR CmdLine[MAX_PATH] = L"rundll32.exe shell32.dll,Control_RunDLL ";
if (!pwszCPLParameters)
{
MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR);
return FALSE;
}
ZeroMemory(&StartupInfo, sizeof(StartupInfo));
StartupInfo.cb = sizeof(StartupInfo);
ZeroMemory(&ProcessInformation, sizeof(ProcessInformation));
ASSERT(_countof(CmdLine) > wcslen(CmdLine) + wcslen(pwszCPLParameters));
wcscat(CmdLine, pwszCPLParameters);
if (!CreateProcessW(NULL,
CmdLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&StartupInfo,
&ProcessInformation))
{
MessageBoxW(hwnd, L"Error: Failed to launch the Control Panel Applet.", NULL, MB_ICONERROR);
return FALSE;
}
while ((MsgWaitForMultipleObjects(1, &ProcessInformation.hProcess, FALSE, INFINITE, QS_ALLINPUT|QS_ALLPOSTMESSAGE )) != WAIT_OBJECT_0)
{
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
CloseHandle(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
return TRUE;
}
static VOID
WriteUserLocale(VOID)
{
HKEY hKey;
LCID lcid;
WCHAR Locale[12];
lcid = GetSystemDefaultLCID();
if (GetLocaleInfoW(MAKELCID(lcid, SORT_DEFAULT), LOCALE_ILANGUAGE, Locale, ARRAYSIZE(Locale)) != 0)
{
if (RegCreateKeyExW(HKEY_CURRENT_USER, L"Control Panel\\International",
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS)
{
RegSetValueExW(hKey, L"Locale", 0, REG_SZ, (LPBYTE)Locale, (wcslen(Locale) + 1) * sizeof(WCHAR));
RegCloseKey(hKey);
}
}
}
static INT_PTR CALLBACK
LocalePageDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PSETUPDATA SetupData;
/* Retrieve pointer to the global setup data */
SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch (uMsg)
{
case WM_INITDIALOG:
{
/* Save pointer to the global setup data */
SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData);
WriteUserLocale();
SetUserLocaleName(GetDlgItem(hwndDlg, IDC_LOCALETEXT));
SetKeyboardLayoutName(GetDlgItem(hwndDlg, IDC_LAYOUTTEXT));
}
break;
case WM_COMMAND:
if (HIWORD(wParam) == BN_CLICKED)
{
switch (LOWORD(wParam))
{
case IDC_CUSTOMLOCALE:
RunControlPanelApplet(hwndDlg, L"intl.cpl,,5");
/* FIXME: Update input locale name */
break;
case IDC_CUSTOMLAYOUT:
RunControlPanelApplet(hwndDlg, L"input.dll,@1");
break;
}
}
break;
case WM_NOTIFY:
{
LPNMHDR lpnm = (LPNMHDR)lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE:
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (SetupData->UnattendSetup)
{
// if (!*SetupData->SourcePath)
{
RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"$winnt$.inf\""); // Should be in System32
}
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_OWNERPAGE);
return TRUE;
}
break;
case PSN_WIZNEXT:
break;
case PSN_WIZBACK:
SetupData->UnattendSetup = FALSE;
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
static PTIMEZONE_ENTRY
GetLargerTimeZoneEntry(PSETUPDATA SetupData, DWORD Index)
{
PTIMEZONE_ENTRY Entry;
Entry = SetupData->TimeZoneListHead;
while (Entry != NULL)
{
if (Entry->Index >= Index)
return Entry;
Entry = Entry->Next;
}
return NULL;
}
static LONG
RetrieveTimeZone(
IN HKEY hZoneKey,
IN PVOID Context)
{
LONG lError;
PSETUPDATA SetupData = (PSETUPDATA)Context;
PTIMEZONE_ENTRY Entry;
PTIMEZONE_ENTRY Current;
ULONG DescriptionSize;
ULONG StandardNameSize;
ULONG DaylightNameSize;
Entry = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(TIMEZONE_ENTRY));
if (Entry == NULL)
{
return ERROR_NOT_ENOUGH_MEMORY;
}
DescriptionSize = sizeof(Entry->Description);
StandardNameSize = sizeof(Entry->StandardName);
DaylightNameSize = sizeof(Entry->DaylightName);
lError = QueryTimeZoneData(hZoneKey,
&Entry->Index,
&Entry->TimezoneInfo,
Entry->Description,
&DescriptionSize,
Entry->StandardName,
&StandardNameSize,
Entry->DaylightName,
&DaylightNameSize);
if (lError != ERROR_SUCCESS)
{
HeapFree(GetProcessHeap(), 0, Entry);
return lError;
}
if (SetupData->TimeZoneListHead == NULL &&
SetupData->TimeZoneListTail == NULL)
{
Entry->Prev = NULL;
Entry->Next = NULL;
SetupData->TimeZoneListHead = Entry;
SetupData->TimeZoneListTail = Entry;
}
else
{
Current = GetLargerTimeZoneEntry(SetupData, Entry->Index);
if (Current != NULL)
{
if (Current == SetupData->TimeZoneListHead)
{
/* Prepend to head */
Entry->Prev = NULL;
Entry->Next = SetupData->TimeZoneListHead;
SetupData->TimeZoneListHead->Prev = Entry;
SetupData->TimeZoneListHead = Entry;
}
else
{
/* Insert before current */
Entry->Prev = Current->Prev;
Entry->Next = Current;
Current->Prev->Next = Entry;
Current->Prev = Entry;
}
}
else
{
/* Append to tail */
Entry->Prev = SetupData->TimeZoneListTail;
Entry->Next = NULL;
SetupData->TimeZoneListTail->Next = Entry;
SetupData->TimeZoneListTail = Entry;
}
}
return ERROR_SUCCESS;
}
static VOID
CreateTimeZoneList(PSETUPDATA SetupData)
{
EnumerateTimeZoneList(RetrieveTimeZone, SetupData);
}
static VOID
DestroyTimeZoneList(PSETUPDATA SetupData)
{
PTIMEZONE_ENTRY Entry;
while (SetupData->TimeZoneListHead != NULL)
{
Entry = SetupData->TimeZoneListHead;
SetupData->TimeZoneListHead = Entry->Next;
if (SetupData->TimeZoneListHead != NULL)
{
SetupData->TimeZoneListHead->Prev = NULL;
}
HeapFree(GetProcessHeap(), 0, Entry);
}
SetupData->TimeZoneListTail = NULL;
}
static VOID
ShowTimeZoneList(HWND hwnd, PSETUPDATA SetupData, DWORD dwEntryIndex)
{
PTIMEZONE_ENTRY Entry;
DWORD dwIndex = 0;
DWORD dwCount;
GetTimeZoneListIndex(&dwEntryIndex);
Entry = SetupData->TimeZoneListHead;
while (Entry != NULL)
{
dwCount = SendMessage(hwnd,
CB_ADDSTRING,
0,
(LPARAM)Entry->Description);
if (dwEntryIndex != 0 && dwEntryIndex == Entry->Index)
dwIndex = dwCount;
Entry = Entry->Next;
}
SendMessage(hwnd,
CB_SETCURSEL,
(WPARAM)dwIndex,
0);
}
static VOID
SetLocalTimeZone(HWND hwnd, PSETUPDATA SetupData)
{
TIME_ZONE_INFORMATION TimeZoneInformation;
PTIMEZONE_ENTRY Entry;
DWORD dwIndex;
DWORD i;
dwIndex = SendMessage(hwnd,
CB_GETCURSEL,
0,
0);
i = 0;
Entry = SetupData->TimeZoneListHead;
while (i < dwIndex)
{
if (Entry == NULL)
return;
i++;
Entry = Entry->Next;
}
wcscpy(TimeZoneInformation.StandardName,
Entry->StandardName);
wcscpy(TimeZoneInformation.DaylightName,
Entry->DaylightName);
TimeZoneInformation.Bias = Entry->TimezoneInfo.Bias;
TimeZoneInformation.StandardBias = Entry->TimezoneInfo.StandardBias;
TimeZoneInformation.DaylightBias = Entry->TimezoneInfo.DaylightBias;
memcpy(&TimeZoneInformation.StandardDate,
&Entry->TimezoneInfo.StandardDate,
sizeof(SYSTEMTIME));
memcpy(&TimeZoneInformation.DaylightDate,
&Entry->TimezoneInfo.DaylightDate,
sizeof(SYSTEMTIME));
/* Set time zone information */
SetTimeZoneInformation(&TimeZoneInformation);
}
static BOOL
GetLocalSystemTime(HWND hwnd, PSETUPDATA SetupData)
{
SYSTEMTIME Date;
SYSTEMTIME Time;
if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_DATEPICKER), &Date) != GDT_VALID)
{
return FALSE;
}
if (DateTime_GetSystemtime(GetDlgItem(hwnd, IDC_TIMEPICKER), &Time) != GDT_VALID)
{
return FALSE;
}
SetupData->SystemTime.wYear = Date.wYear;
SetupData->SystemTime.wMonth = Date.wMonth;
SetupData->SystemTime.wDayOfWeek = Date.wDayOfWeek;
SetupData->SystemTime.wDay = Date.wDay;
SetupData->SystemTime.wHour = Time.wHour;
SetupData->SystemTime.wMinute = Time.wMinute;
SetupData->SystemTime.wSecond = Time.wSecond;
SetupData->SystemTime.wMilliseconds = Time.wMilliseconds;
return TRUE;
}
static BOOL
SetSystemLocalTime(HWND hwnd, PSETUPDATA SetupData)
{
BOOL Ret = FALSE;
/*
* Call SetLocalTime twice to ensure correct results
*/
Ret = SetLocalTime(&SetupData->SystemTime) &&
SetLocalTime(&SetupData->SystemTime);
return Ret;
}
static VOID
UpdateLocalSystemTime(HWND hwnd, SYSTEMTIME LocalTime)
{
DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_DATEPICKER), GDT_VALID, &LocalTime);
DateTime_SetSystemtime(GetDlgItem(hwnd, IDC_TIMEPICKER), GDT_VALID, &LocalTime);
}
static BOOL
WriteDateTimeSettings(HWND hwndDlg, PSETUPDATA SetupData)
{
WCHAR Title[64];
WCHAR ErrorLocalTime[256];
GetLocalSystemTime(hwndDlg, SetupData);
SetLocalTimeZone(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
SetupData);
SetAutoDaylight(SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT,
BM_GETCHECK, 0, 0) != BST_UNCHECKED);
if (!SetSystemLocalTime(hwndDlg, SetupData))
{
if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP, Title, ARRAYSIZE(Title)))
{
wcscpy(Title, L"ReactOS Setup");
}
if (0 == LoadStringW(hDllInstance, IDS_WZD_LOCALTIME, ErrorLocalTime,
ARRAYSIZE(ErrorLocalTime)))
{
wcscpy(ErrorLocalTime, L"Setup was unable to set the local time.");
}
MessageBoxW(hwndDlg, ErrorLocalTime, Title, MB_ICONWARNING | MB_OK);
return FALSE;
}
return TRUE;
}
static INT_PTR CALLBACK
DateTimePageDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PSETUPDATA SetupData;
/* Retrieve pointer to the global setup data */
SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch (uMsg)
{
case WM_INITDIALOG:
{
/* Save pointer to the global setup data */
SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData);
CreateTimeZoneList(SetupData);
if (SetupData->UnattendSetup)
{
ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
SetupData, SetupData->TimeZoneIndex);
if (!SetupData->DisableAutoDaylightTimeSet)
{
SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
}
}
else
{
ShowTimeZoneList(GetDlgItem(hwndDlg, IDC_TIMEZONELIST),
SetupData, -1);
SendDlgItemMessage(hwndDlg, IDC_AUTODAYLIGHT, BM_SETCHECK, (WPARAM)BST_CHECKED, 0);
}
break;
}
case WM_TIMER:
{
SYSTEMTIME LocalTime;
GetLocalTime(&LocalTime);
UpdateLocalSystemTime(hwndDlg, LocalTime);
// Reset timeout.
SetTimer(hwndDlg, 1, 1000 - LocalTime.wMilliseconds, NULL);
break;
}
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
case PSN_SETACTIVE:
{
SYSTEMTIME LocalTime;
GetLocalTime(&LocalTime);
UpdateLocalSystemTime(hwndDlg, LocalTime);
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (SetupData->UnattendSetup && WriteDateTimeSettings(hwndDlg, SetupData))
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, SetupData->uFirstNetworkWizardPage);
return TRUE;
}
SetTimer(hwndDlg, 1, 1000 - LocalTime.wMilliseconds, NULL);
break;
}
case PSN_KILLACTIVE:
case DTN_DATETIMECHANGE:
// NB: Not re-set until changing page (PSN_SETACTIVE).
KillTimer(hwndDlg, 1);
break;
case PSN_WIZNEXT:
WriteDateTimeSettings(hwndDlg, SetupData);
break;
case PSN_WIZBACK:
SetupData->UnattendSetup = FALSE;
break;
default:
break;
}
break;
case WM_DESTROY:
DestroyTimeZoneList(SetupData);
break;
default:
break;
}
return FALSE;
}
static struct ThemeInfo
{
LPCWSTR PreviewBitmap;
UINT DisplayName;
LPCWSTR ThemeFile;
} Themes[] = {
{ MAKEINTRESOURCE(IDB_CLASSIC), IDS_CLASSIC, NULL },
{ MAKEINTRESOURCE(IDB_LAUTUS), IDS_LAUTUS, L"themes\\lautus\\lautus.msstyles" },
{ MAKEINTRESOURCE(IDB_LUNAR), IDS_LUNAR, L"themes\\lunar\\lunar.msstyles" },
{ MAKEINTRESOURCE(IDB_MIZU), IDS_MIZU, L"themes\\mizu\\mizu.msstyles"},
};
static INT_PTR CALLBACK
ThemePageDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PSETUPDATA SetupData;
LPNMLISTVIEW pnmv;
/* Retrieve pointer to the global setup data */
SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch (uMsg)
{
case WM_INITDIALOG:
{
HWND hListView;
HIMAGELIST himl;
DWORD n;
LVITEM lvi = {0};
/* Save pointer to the global setup data */
SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData);
hListView = GetDlgItem(hwndDlg, IDC_THEMEPICKER);
/* Common */
himl = ImageList_Create(180, 163, ILC_COLOR32 | ILC_MASK, ARRAYSIZE(Themes), 1);
lvi.mask = LVIF_TEXT | LVIF_IMAGE |LVIF_STATE;
for (n = 0; n < ARRAYSIZE(Themes); ++n)
{
WCHAR DisplayName[100] = {0};
/* Load the bitmap */
HANDLE image = LoadImageW(hDllInstance, Themes[n].PreviewBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION);
ImageList_AddMasked(himl, image, RGB(255,0,255));
/* Load the string */
LoadStringW(hDllInstance, Themes[n].DisplayName, DisplayName, ARRAYSIZE(DisplayName));
DisplayName[ARRAYSIZE(DisplayName)-1] = UNICODE_NULL;
/* Add the listview item */
lvi.iItem = n;
lvi.iImage = n;
lvi.pszText = DisplayName;
ListView_InsertItem(hListView, &lvi);
}
/* Register the imagelist */
ListView_SetImageList(hListView, himl, LVSIL_NORMAL);
/* Transparant background */
ListView_SetBkColor(hListView, CLR_NONE);
ListView_SetTextBkColor(hListView, CLR_NONE);
/* Reduce the size between the items */
ListView_SetIconSpacing(hListView, 190, 173);
break;
}
case WM_NOTIFY:
switch (((LPNMHDR)lParam)->code)
{
//case LVN_ITEMCHANGING:
case LVN_ITEMCHANGED:
pnmv = (LPNMLISTVIEW)lParam;
if ((pnmv->uChanged & LVIF_STATE) && (pnmv->uNewState & LVIS_SELECTED))
{
int iTheme = pnmv->iItem;
DPRINT1("Selected theme: %u\n", Themes[iTheme].DisplayName);
if (Themes[iTheme].ThemeFile)
{
WCHAR wszParams[1024];
WCHAR wszTheme[MAX_PATH];
WCHAR* format = L"desk.cpl desk,@Appearance /Action:ActivateMSTheme /file:\"%s\"";
SHGetFolderPathAndSubDirW(0, CSIDL_RESOURCES, NULL, SHGFP_TYPE_DEFAULT, Themes[iTheme].ThemeFile, wszTheme);
swprintf(wszParams, format, wszTheme);
RunControlPanelApplet(hwndDlg, wszParams);
}
else
{
RunControlPanelApplet(hwndDlg, L"desk.cpl desk,@Appearance /Action:ActivateMSTheme");
}
}
break;
case PSN_SETACTIVE:
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (SetupData->UnattendSetup)
{
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, SetupData->uFirstNetworkWizardPage);
return TRUE;
}
break;
case PSN_WIZNEXT:
break;
case PSN_WIZBACK:
SetupData->UnattendSetup = FALSE;
break;
default:
break;
}
break;
default:
break;
}
return FALSE;
}
static UINT CALLBACK
RegistrationNotificationProc(PVOID Context,
UINT Notification,
UINT_PTR Param1,
UINT_PTR Param2)
{
PREGISTRATIONDATA RegistrationData;
REGISTRATIONNOTIFY RegistrationNotify;
PSP_REGISTER_CONTROL_STATUSW StatusInfo;
UINT MessageID;
WCHAR ErrorMessage[128];
RegistrationData = (PREGISTRATIONDATA) Context;
if (SPFILENOTIFY_STARTREGISTRATION == Notification ||
SPFILENOTIFY_ENDREGISTRATION == Notification)
{
StatusInfo = (PSP_REGISTER_CONTROL_STATUSW) Param1;
RegistrationNotify.CurrentItem = wcsrchr(StatusInfo->FileName, L'\\');
if (NULL == RegistrationNotify.CurrentItem)
{
RegistrationNotify.CurrentItem = StatusInfo->FileName;
}
else
{
RegistrationNotify.CurrentItem++;
}
if (SPFILENOTIFY_STARTREGISTRATION == Notification)
{
DPRINT("Received SPFILENOTIFY_STARTREGISTRATION notification for %S\n",
StatusInfo->FileName);
RegistrationNotify.ErrorMessage = NULL;
RegistrationNotify.Progress = RegistrationData->Registered;
}
else
{
DPRINT("Received SPFILENOTIFY_ENDREGISTRATION notification for %S\n",
StatusInfo->FileName);
DPRINT("Win32Error %u FailureCode %u\n", StatusInfo->Win32Error,
StatusInfo->FailureCode);
if (SPREG_SUCCESS != StatusInfo->FailureCode)
{
switch(StatusInfo->FailureCode)
{
case SPREG_LOADLIBRARY:
MessageID = IDS_LOADLIBRARY_FAILED;
break;
case SPREG_GETPROCADDR:
MessageID = IDS_GETPROCADDR_FAILED;
break;
case SPREG_REGSVR:
MessageID = IDS_REGSVR_FAILED;
break;
case SPREG_DLLINSTALL:
MessageID = IDS_DLLINSTALL_FAILED;
break;
case SPREG_TIMEOUT:
MessageID = IDS_TIMEOUT;
break;
default:
MessageID = IDS_REASON_UNKNOWN;
break;
}
if (0 == LoadStringW(hDllInstance, MessageID,
ErrorMessage,
ARRAYSIZE(ErrorMessage)))
{
ErrorMessage[0] = L'\0';
}
if (SPREG_TIMEOUT != StatusInfo->FailureCode)
{
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL,
StatusInfo->Win32Error, 0,
ErrorMessage + wcslen(ErrorMessage),
ARRAYSIZE(ErrorMessage) - wcslen(ErrorMessage),
NULL);
}
RegistrationNotify.ErrorMessage = ErrorMessage;
}
else
{
RegistrationNotify.ErrorMessage = NULL;
}
if (RegistrationData->Registered < RegistrationData->DllCount)
{
RegistrationData->Registered++;
}
}
RegistrationNotify.Progress = RegistrationData->Registered;
RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS;
SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY,
0, (LPARAM) &RegistrationNotify);
return FILEOP_DOIT;
}
else
{
DPRINT1("Received unexpected notification %u\n", Notification);
return SetupDefaultQueueCallback(RegistrationData->DefaultContext,
Notification, Param1, Param2);
}
}
static DWORD CALLBACK
RegistrationProc(LPVOID Parameter)
{
PREGISTRATIONDATA RegistrationData;
REGISTRATIONNOTIFY RegistrationNotify;
DWORD LastError = NO_ERROR;
WCHAR UnknownError[84];
RegistrationData = (PREGISTRATIONDATA) Parameter;
RegistrationData->Registered = 0;
RegistrationData->DefaultContext = SetupInitDefaultQueueCallback(RegistrationData->hwndDlg);
_SEH2_TRY
{
if (!SetupInstallFromInfSectionW(GetParent(RegistrationData->hwndDlg),
hSysSetupInf,
L"RegistrationPhase2",
SPINST_REGISTRY |
SPINST_REGISTERCALLBACKAWARE |
SPINST_REGSVR,
0,
NULL,
0,
RegistrationNotificationProc,
RegistrationData,
NULL,
NULL))
{
LastError = GetLastError();
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
DPRINT("Catching exception\n");
LastError = RtlNtStatusToDosError(_SEH2_GetExceptionCode());
}
_SEH2_END;
if (NO_ERROR == LastError)
{
RegistrationNotify.ErrorMessage = NULL;
}
else
{
DPRINT1("SetupInstallFromInfSection failed with error %u\n",
LastError);
if (0 == FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM, NULL, LastError, 0,
(LPWSTR) &RegistrationNotify.ErrorMessage, 0,
NULL))
{
if (0 == LoadStringW(hDllInstance, IDS_UNKNOWN_ERROR,
UnknownError,
ARRAYSIZE(UnknownError) - 20))
{
wcscpy(UnknownError, L"Unknown error");
}
wcscat(UnknownError, L" ");
_ultow(LastError, UnknownError + wcslen(UnknownError), 10);
RegistrationNotify.ErrorMessage = UnknownError;
}
}
RegistrationNotify.Progress = RegistrationData->DllCount;
RegistrationNotify.ActivityID = IDS_REGISTERING_COMPONENTS;
RegistrationNotify.CurrentItem = NULL;
SendMessage(RegistrationData->hwndDlg, PM_REGISTRATION_NOTIFY,
1, (LPARAM) &RegistrationNotify);
if (NULL != RegistrationNotify.ErrorMessage &&
UnknownError != RegistrationNotify.ErrorMessage)
{
LocalFree((PVOID) RegistrationNotify.ErrorMessage);
}
SetupTermDefaultQueueCallback(RegistrationData->DefaultContext);
HeapFree(GetProcessHeap(), 0, RegistrationData);
RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries");
// FIXME: Move this call to a separate cleanup page!
RtlCreateBootStatusDataFile();
return 0;
}
static BOOL
StartComponentRegistration(HWND hwndDlg, PULONG MaxProgress)
{
HANDLE RegistrationThread;
LONG DllCount;
INFCONTEXT Context;
WCHAR SectionName[512];
PREGISTRATIONDATA RegistrationData;
DllCount = -1;
if (!SetupFindFirstLineW(hSysSetupInf, L"RegistrationPhase2",
L"RegisterDlls", &Context))
{
DPRINT1("No RegistrationPhase2 section found\n");
return FALSE;
}
if (!SetupGetStringFieldW(&Context, 1, SectionName,
ARRAYSIZE(SectionName),
NULL))
{
DPRINT1("Unable to retrieve section name\n");
return FALSE;
}
DllCount = SetupGetLineCountW(hSysSetupInf, SectionName);
DPRINT("SectionName %S DllCount %ld\n", SectionName, DllCount);
if (DllCount < 0)
{
SetLastError(STATUS_NOT_FOUND);
return FALSE;
}
*MaxProgress = (ULONG) DllCount;
/*
* Create a background thread to do the actual registrations, so the
* main thread can just run its message loop.
*/
RegistrationThread = NULL;
RegistrationData = HeapAlloc(GetProcessHeap(), 0,
sizeof(REGISTRATIONDATA));
if (RegistrationData != NULL)
{
RegistrationData->hwndDlg = hwndDlg;
RegistrationData->DllCount = DllCount;
RegistrationThread = CreateThread(NULL, 0, RegistrationProc,
RegistrationData, 0, NULL);
if (RegistrationThread != NULL)
{
CloseHandle(RegistrationThread);
}
else
{
DPRINT1("CreateThread failed, error %u\n", GetLastError());
HeapFree(GetProcessHeap(), 0, RegistrationData);
return FALSE;
}
}
else
{
DPRINT1("HeapAlloc() failed, error %u\n", GetLastError());
return FALSE;
}
return TRUE;
}
static INT_PTR CALLBACK
ProcessPageDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
PSETUPDATA SetupData;
PREGISTRATIONNOTIFY RegistrationNotify;
static UINT oldActivityID = -1;
WCHAR Title[64];
/* Retrieve pointer to the global setup data */
SetupData = (PSETUPDATA)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
switch (uMsg)
{
case WM_INITDIALOG:
{
/* Save pointer to the global setup data */
SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (DWORD_PTR)SetupData);
}
break;
case WM_NOTIFY:
{
LPNMHDR lpnm = (LPNMHDR)lParam;
ULONG MaxProgress = 0;
switch (lpnm->code)
{
case PSN_SETACTIVE:
/* Disable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), 0);
StartComponentRegistration(hwndDlg, &MaxProgress);
SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETRANGE,
0, MAKELPARAM(0, MaxProgress));
SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS,
0, 0);
break;
case PSN_WIZNEXT:
break;
case PSN_WIZBACK:
SetupData->UnattendSetup = FALSE;
break;
default:
break;
}
}
break;
case PM_REGISTRATION_NOTIFY:
{
WCHAR Activity[64];
RegistrationNotify = (PREGISTRATIONNOTIFY) lParam;
// update if necessary only
if (oldActivityID != RegistrationNotify->ActivityID)
{
if (0 != LoadStringW(hDllInstance, RegistrationNotify->ActivityID,
Activity,
ARRAYSIZE(Activity)))
{
SendDlgItemMessageW(hwndDlg, IDC_ACTIVITY, WM_SETTEXT,
0, (LPARAM) Activity);
}
oldActivityID = RegistrationNotify->ActivityID;
}
SendDlgItemMessageW(hwndDlg, IDC_ITEM, WM_SETTEXT, 0,
(LPARAM)(NULL == RegistrationNotify->CurrentItem ?
L"" : RegistrationNotify->CurrentItem));
SendDlgItemMessage(hwndDlg, IDC_PROCESSPROGRESS, PBM_SETPOS,
RegistrationNotify->Progress, 0);
if (NULL != RegistrationNotify->ErrorMessage)
{
if (0 == LoadStringW(hDllInstance, IDS_REACTOS_SETUP,
Title, ARRAYSIZE(Title)))
{
wcscpy(Title, L"ReactOS Setup");
}
MessageBoxW(hwndDlg, RegistrationNotify->ErrorMessage,
Title, MB_ICONERROR | MB_OK);
}
if (wParam)
{
/* Enable the Back and Next buttons */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_NEXT);
PropSheet_PressButton(GetParent(hwndDlg), PSBTN_NEXT);
}
}
return TRUE;
default:
break;
}
return FALSE;
}
static VOID
SetInstallationCompleted(VOID)
{
HKEY hKey = 0;
DWORD InProgress = 0;
DWORD InstallDate;
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE,
L"SYSTEM\\Setup",
0,
KEY_WRITE,
&hKey ) == ERROR_SUCCESS)
{
RegSetValueExW( hKey, L"SystemSetupInProgress", 0, REG_DWORD, (LPBYTE)&InProgress, sizeof(InProgress) );
RegCloseKey( hKey );
}
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows NT\\CurrentVersion",
0,
KEY_WRITE,
&hKey ) == ERROR_SUCCESS)
{
InstallDate = (DWORD)time(NULL);
RegSetValueExW( hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate) );
RegCloseKey( hKey );
}
}
static INT_PTR CALLBACK
FinishDlgProc(HWND hwndDlg,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
/* Get pointer to the global setup data */
PSETUPDATA SetupData = (PSETUPDATA)((LPPROPSHEETPAGE)lParam)->lParam;
if (!SetupData->UnattendSetup || !SetupData->DisableGeckoInst)
{
/* Run the Wine Gecko prompt */
Control_RunDLLW(hwndDlg, 0, L"appwiz.cpl install_gecko", SW_SHOW);
}
/* Set title font */
SendDlgItemMessage(hwndDlg,
IDC_FINISHTITLE,
WM_SETFONT,
(WPARAM)SetupData->hTitleFont,
(LPARAM)TRUE);
if (SetupData->UnattendSetup)
{
KillTimer(hwndDlg, 1);
SetInstallationCompleted();
PostQuitMessage(0);
}
}
break;
case WM_DESTROY:
{
SetInstallationCompleted();
PostQuitMessage(0);
return TRUE;
}
case WM_TIMER:
{
INT Position;
HWND hWndProgress;
hWndProgress = GetDlgItem(hwndDlg, IDC_RESTART_PROGRESS);
Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0);
if (Position == 300)
{
KillTimer(hwndDlg, 1);
PropSheet_PressButton(GetParent(hwndDlg), PSBTN_FINISH);
}
else
{
SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0);
}
}
return TRUE;
case WM_NOTIFY:
{
LPNMHDR lpnm = (LPNMHDR)lParam;
switch (lpnm->code)
{
case PSN_SETACTIVE:
/* Enable the correct buttons on for the active page */
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_FINISH);
SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0,
MAKELPARAM(0, 300));
SendDlgItemMessage(hwndDlg, IDC_RESTART_PROGRESS, PBM_SETPOS, 0, 0);
SetTimer(hwndDlg, 1, 50, NULL);
break;
case PSN_WIZFINISH:
DestroyWindow(GetParent(hwndDlg));
break;
default:
break;
}
}
break;
default:
break;
}
return FALSE;
}
/*
* GetInstallSourceWin32 retrieves the path to the ReactOS installation medium
* in Win32 format, for later use by syssetup and storage in the registry.
*/
static BOOL
GetInstallSourceWin32(
OUT PWSTR pwszPath,
IN DWORD cchPathMax,
IN PCWSTR pwszNTPath)
{
WCHAR wszDrives[512];
WCHAR wszNTPath[512]; // MAX_PATH ?
DWORD cchDrives;
PWCHAR pwszDrive;
*pwszPath = UNICODE_NULL;
cchDrives = GetLogicalDriveStringsW(_countof(wszDrives) - 1, wszDrives);
if (cchDrives == 0 || cchDrives >= _countof(wszDrives))
{
/* Buffer too small or failure */
LogItem(NULL, L"GetLogicalDriveStringsW failed");
return FALSE;
}
for (pwszDrive = wszDrives; *pwszDrive; pwszDrive += wcslen(pwszDrive) + 1)
{
WCHAR wszBuf[MAX_PATH];
/* Retrieve the NT path corresponding to the current Win32 DOS path */
pwszDrive[2] = UNICODE_NULL; // Temporarily remove the backslash
QueryDosDeviceW(pwszDrive, wszNTPath, _countof(wszNTPath));
pwszDrive[2] = L'\\'; // Restore the backslash
wcscat(wszNTPath, L"\\"); // Concat a backslash
/* Logging */
wsprintf(wszBuf, L"Testing '%s' --> '%s' %s a CD",
pwszDrive, wszNTPath,
(GetDriveTypeW(pwszDrive) == DRIVE_CDROM) ? L"is" : L"is not");
LogItem(NULL, wszBuf);
/* Check whether the NT path corresponds to the NT installation source path */
if (!_wcsicmp(wszNTPath, pwszNTPath))
{
/* Found it! */
wcscpy(pwszPath, pwszDrive); // cchPathMax
/* Logging */
wsprintf(wszBuf, L"GetInstallSourceWin32: %s", pwszPath);
LogItem(NULL, wszBuf);
wcscat(wszBuf, L"\n");
OutputDebugStringW(wszBuf);
return TRUE;
}
}
return FALSE;
}
VOID
ProcessUnattendSection(
IN OUT PSETUPDATA pSetupData)
{
INFCONTEXT InfContext;
WCHAR szName[256];
WCHAR szValue[MAX_PATH];
DWORD LineLength;
HKEY hKey;
if (!SetupFindFirstLineW(pSetupData->hSetupInf,
L"Unattend",
L"UnattendSetupEnabled",
&InfContext))
{
DPRINT1("Error: Cannot find UnattendSetupEnabled Key! %d\n", GetLastError());
return;
}
if (!SetupGetStringFieldW(&InfContext,
1,
szValue,
ARRAYSIZE(szValue),
&LineLength))
{
DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
return;
}
if (_wcsicmp(szValue, L"yes") != 0)
{
DPRINT("Unattend setup was disabled by UnattendSetupEnabled key.\n");
return;
}
pSetupData->UnattendSetup = TRUE;
if (!SetupFindFirstLineW(pSetupData->hSetupInf,
L"Unattend",
NULL,
&InfContext))
{
DPRINT1("Error: SetupFindFirstLine failed %d\n", GetLastError());
return;
}
do
{
if (!SetupGetStringFieldW(&InfContext,
0,
szName,
ARRAYSIZE(szName),
&LineLength))
{
DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
return;
}
if (!SetupGetStringFieldW(&InfContext,
1,
szValue,
ARRAYSIZE(szValue),
&LineLength))
{
DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
return;
}
DPRINT1("Name %S Value %S\n", szName, szValue);
if (!_wcsicmp(szName, L"FullName"))
{
if (ARRAYSIZE(pSetupData->OwnerName) > LineLength)
{
wcscpy(pSetupData->OwnerName, szValue);
}
}
else if (!_wcsicmp(szName, L"OrgName"))
{
if (ARRAYSIZE(pSetupData->OwnerOrganization) > LineLength)
{
wcscpy(pSetupData->OwnerOrganization, szValue);
}
}
else if (!_wcsicmp(szName, L"ComputerName"))
{
if (ARRAYSIZE(pSetupData->ComputerName) > LineLength)
{
wcscpy(pSetupData->ComputerName, szValue);
}
}
else if (!_wcsicmp(szName, L"AdminPassword"))
{
if (ARRAYSIZE(pSetupData->AdminPassword) > LineLength)
{
wcscpy(pSetupData->AdminPassword, szValue);
}
}
else if (!_wcsicmp(szName, L"TimeZoneIndex"))
{
pSetupData->TimeZoneIndex = _wtoi(szValue);
}
else if (!_wcsicmp(szName, L"DisableAutoDaylightTimeSet"))
{
pSetupData->DisableAutoDaylightTimeSet = _wtoi(szValue);
}
else if (!_wcsicmp(szName, L"DisableGeckoInst"))
{
if (!_wcsicmp(szValue, L"yes"))
pSetupData->DisableGeckoInst = TRUE;
else
pSetupData->DisableGeckoInst = FALSE;
}
else if (!_wcsicmp(szName, L"ProductOption"))
{
pSetupData->ProductOption = (PRODUCT_OPTION)_wtoi(szValue);
}
} while (SetupFindNextLine(&InfContext, &InfContext));
if (SetupFindFirstLineW(pSetupData->hSetupInf,
L"Display",
NULL,
&InfContext))
{
DEVMODEW dm = { { 0 } };
dm.dmSize = sizeof(dm);
if (EnumDisplaySettingsW(NULL, ENUM_CURRENT_SETTINGS, &dm))
{
do
{
int iValue;
if (!SetupGetStringFieldW(&InfContext,
0,
szName,
ARRAYSIZE(szName),
&LineLength))
{
DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
return;
}
if (!SetupGetStringFieldW(&InfContext,
1,
szValue,
ARRAYSIZE(szValue),
&LineLength))
{
DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
return;
}
iValue = _wtoi(szValue);
DPRINT1("Name %S Value %i\n", szName, iValue);
if (!iValue)
continue;
if (!_wcsicmp(szName, L"BitsPerPel"))
{
dm.dmFields |= DM_BITSPERPEL;
dm.dmBitsPerPel = iValue;
}
else if (!_wcsicmp(szName, L"XResolution"))
{
dm.dmFields |= DM_PELSWIDTH;
dm.dmPelsWidth = iValue;
}
else if (!_wcsicmp(szName, L"YResolution"))
{
dm.dmFields |= DM_PELSHEIGHT;
dm.dmPelsHeight = iValue;
}
else if (!_wcsicmp(szName, L"VRefresh"))
{
dm.dmFields |= DM_DISPLAYFREQUENCY;
dm.dmDisplayFrequency = iValue;
}
} while (SetupFindNextLine(&InfContext, &InfContext));
ChangeDisplaySettingsW(&dm, CDS_UPDATEREGISTRY);
}
}
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
0,
KEY_SET_VALUE,
&hKey) != ERROR_SUCCESS)
{
DPRINT1("Error: failed to open HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\n");
return;
}
if (SetupFindFirstLineW(pSetupData->hSetupInf,
L"GuiRunOnce",
NULL,
&InfContext))
{
int i = 0;
do
{
if (SetupGetStringFieldW(&InfContext,
0,
szValue,
ARRAYSIZE(szValue),
NULL))
{
WCHAR szPath[MAX_PATH];
swprintf(szName, L"%d", i);
DPRINT("szName %S szValue %S\n", szName, szValue);
if (ExpandEnvironmentStringsW(szValue, szPath, MAX_PATH))
{
DPRINT("value %S\n", szPath);
if (RegSetValueExW(hKey,
szName,
0,
REG_SZ,
(const BYTE*)szPath,
(wcslen(szPath) + 1) * sizeof(WCHAR)) == ERROR_SUCCESS)
{
i++;
}
}
}
} while (SetupFindNextLine(&InfContext, &InfContext));
}
RegCloseKey(hKey);
}
VOID
ProcessSetupInf(
IN OUT PSETUPDATA pSetupData)
{
WCHAR szPath[MAX_PATH];
WCHAR szValue[MAX_PATH];
INFCONTEXT InfContext;
DWORD LineLength;
HKEY hKey;
LONG res;
pSetupData->hSetupInf = INVALID_HANDLE_VALUE;
/* Retrieve the path of the setup INF */
GetSystemDirectoryW(szPath, _countof(szPath));
wcscat(szPath, L"\\$winnt$.inf");
/* Open the setup INF */
pSetupData->hSetupInf = SetupOpenInfFileW(szPath,
NULL,
INF_STYLE_OLDNT,
NULL);
if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE)
{
DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError());
return;
}
/* Retrieve the NT source path from which the 1st-stage installer was run */
if (!SetupFindFirstLineW(pSetupData->hSetupInf,
L"data",
L"sourcepath",
&InfContext))
{
DPRINT1("Error: Cannot find sourcepath Key! %d\n", GetLastError());
return;
}
if (!SetupGetStringFieldW(&InfContext,
1,
szValue,
ARRAYSIZE(szValue),
&LineLength))
{
DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
return;
}
*pSetupData->SourcePath = UNICODE_NULL;
/* Close the setup INF as we are going to modify it manually */
if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(pSetupData->hSetupInf);
/* Find the installation source path in Win32 format */
if (!GetInstallSourceWin32(pSetupData->SourcePath,
_countof(pSetupData->SourcePath),
szValue))
{
*pSetupData->SourcePath = UNICODE_NULL;
}
/* Save the path in Win32 format in the setup INF */
swprintf(szValue, L"\"%s\"", pSetupData->SourcePath);
WritePrivateProfileStringW(L"data", L"dospath", szValue, szPath);
/*
* Save it also in the registry, in the following keys:
* - HKLM\Software\Microsoft\Windows\CurrentVersion\Setup ,
* values "SourcePath" and "ServicePackSourcePath" (REG_SZ);
* - HKLM\Software\Microsoft\Windows NT\CurrentVersion ,
* value "SourcePath" (REG_SZ); set to the full path (e.g. D:\I386).
*/
#if 0
res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows NT\\CurrentVersion",
0,
KEY_ALL_ACCESS,
&hKey);
if (res != ERROR_SUCCESS)
{
return FALSE;
}
#endif
res = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Setup",
0, NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS, // KEY_WRITE
NULL,
&hKey,
NULL);
if (res == ERROR_SUCCESS)
{
res = RegSetValueExW(hKey,
L"SourcePath",
0,
REG_SZ,
(LPBYTE)pSetupData->SourcePath,
(wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR));
res = RegSetValueExW(hKey,
L"ServicePackSourcePath",
0,
REG_SZ,
(LPBYTE)pSetupData->SourcePath,
(wcslen(pSetupData->SourcePath) + 1) * sizeof(WCHAR));
RegCloseKey(hKey);
}
/* Now, re-open the setup INF (this must succeed) */
pSetupData->hSetupInf = SetupOpenInfFileW(szPath,
NULL,
INF_STYLE_OLDNT,
NULL);
if (pSetupData->hSetupInf == INVALID_HANDLE_VALUE)
{
DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError());
return;
}
/* Process the unattended section of the setup file */
ProcessUnattendSection(pSetupData);
}
typedef DWORD(WINAPI *PFNREQUESTWIZARDPAGES)(PDWORD, HPROPSHEETPAGE *, PSETUPDATA);
VOID
InstallWizard(VOID)
{
PROPSHEETHEADER psh = {0};
HPROPSHEETPAGE *phpage = NULL;
PROPSHEETPAGE psp = {0};
UINT nPages = 0;
HWND hWnd;
MSG msg;
PSETUPDATA pSetupData = NULL;
HMODULE hNetShell = NULL;
PFNREQUESTWIZARDPAGES pfn = NULL;
DWORD dwPageCount = 10, dwNetworkPageCount = 0;
LogItem(L"BEGIN_SECTION", L"InstallWizard");
/* Allocate setup data */
pSetupData = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(SETUPDATA));
if (pSetupData == NULL)
{
LogItem(NULL, L"SetupData allocation failed!");
MessageBoxW(NULL,
L"Setup failed to allocate global data!",
L"ReactOS Setup",
MB_ICONERROR | MB_OK);
goto done;
}
pSetupData->ProductOption = PRODUCT_OPTION_DEFAULT;
hNetShell = LoadLibraryW(L"netshell.dll");
if (hNetShell != NULL)
{
DPRINT("Netshell.dll loaded!\n");
pfn = (PFNREQUESTWIZARDPAGES)GetProcAddress(hNetShell,
"NetSetupRequestWizardPages");
if (pfn != NULL)
{
pfn(&dwNetworkPageCount, NULL, NULL);
dwPageCount += dwNetworkPageCount;
}
}
DPRINT("PageCount: %lu\n", dwPageCount);
phpage = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwPageCount * sizeof(HPROPSHEETPAGE));
if (phpage == NULL)
{
LogItem(NULL, L"Page array allocation failed!");
MessageBoxW(NULL,
L"Setup failed to allocate page array!",
L"ReactOS Setup",
MB_ICONERROR | MB_OK);
goto done;
}
/* Process the $winnt$.inf setup file */
ProcessSetupInf(pSetupData);
/* Create the Welcome page */
psp.dwSize = sizeof(PROPSHEETPAGE);
psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
psp.hInstance = hDllInstance;
psp.lParam = (LPARAM)pSetupData;
psp.pfnDlgProc = WelcomeDlgProc;
psp.pszTemplate = MAKEINTRESOURCE(IDD_WELCOMEPAGE);
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the Acknowledgements page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_ACKTITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_ACKSUBTITLE);
psp.pszTemplate = MAKEINTRESOURCE(IDD_ACKPAGE);
psp.pfnDlgProc = AckPageDlgProc;
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the Product page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PRODUCTTITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PRODUCTSUBTITLE);
psp.pszTemplate = MAKEINTRESOURCE(IDD_PRODUCT);
psp.pfnDlgProc = ProductPageDlgProc;
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the Locale page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_LOCALETITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_LOCALESUBTITLE);
psp.pfnDlgProc = LocalePageDlgProc;
psp.pszTemplate = MAKEINTRESOURCE(IDD_LOCALEPAGE);
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the Owner page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_OWNERTITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_OWNERSUBTITLE);
psp.pszTemplate = MAKEINTRESOURCE(IDD_OWNERPAGE);
psp.pfnDlgProc = OwnerPageDlgProc;
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the Computer page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_COMPUTERTITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_COMPUTERSUBTITLE);
psp.pfnDlgProc = ComputerPageDlgProc;
psp.pszTemplate = MAKEINTRESOURCE(IDD_COMPUTERPAGE);
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the DateTime page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_DATETIMETITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_DATETIMESUBTITLE);
psp.pfnDlgProc = DateTimePageDlgProc;
psp.pszTemplate = MAKEINTRESOURCE(IDD_DATETIMEPAGE);
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the theme selection page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONTITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_THEMESELECTIONSUBTITLE);
psp.pfnDlgProc = ThemePageDlgProc;
psp.pszTemplate = MAKEINTRESOURCE(IDD_THEMEPAGE);
phpage[nPages++] = CreatePropertySheetPage(&psp);
pSetupData->uFirstNetworkWizardPage = IDD_PROCESSPAGE;
pSetupData->uPostNetworkWizardPage = IDD_PROCESSPAGE;
if (pfn)
{
pfn(&dwNetworkPageCount, &phpage[nPages], pSetupData);
nPages += dwNetworkPageCount;
}
/* Create the Process page */
psp.dwFlags = PSP_DEFAULT | PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE;
psp.pszHeaderTitle = MAKEINTRESOURCE(IDS_PROCESSTITLE);
psp.pszHeaderSubTitle = MAKEINTRESOURCE(IDS_PROCESSSUBTITLE);
psp.pfnDlgProc = ProcessPageDlgProc;
psp.pszTemplate = MAKEINTRESOURCE(IDD_PROCESSPAGE);
phpage[nPages++] = CreatePropertySheetPage(&psp);
/* Create the Finish page */
psp.dwFlags = PSP_DEFAULT | PSP_HIDEHEADER;
psp.pfnDlgProc = FinishDlgProc;
psp.pszTemplate = MAKEINTRESOURCE(IDD_FINISHPAGE);
phpage[nPages++] = CreatePropertySheetPage(&psp);
ASSERT(nPages == dwPageCount);
/* Create the property sheet */
psh.dwSize = sizeof(PROPSHEETHEADER);
psh.dwFlags = PSH_WIZARD97 | PSH_WATERMARK | PSH_HEADER | PSH_MODELESS;
psh.hInstance = hDllInstance;
psh.hwndParent = NULL;
psh.nPages = nPages;
psh.nStartPage = 0;
psh.phpage = phpage;
psh.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK);
psh.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER);
/* Create title font */
pSetupData->hTitleFont = CreateTitleFont();
pSetupData->hBoldFont = CreateBoldFont();
/* Display the wizard */
hWnd = (HWND)PropertySheet(&psh);
ShowWindow(hWnd, SW_SHOW);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!IsDialogMessage(hWnd, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
DeleteObject(pSetupData->hBoldFont);
DeleteObject(pSetupData->hTitleFont);
if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(pSetupData->hSetupInf);
done:
if (phpage != NULL)
HeapFree(GetProcessHeap(), 0, phpage);
if (hNetShell != NULL)
FreeLibrary(hNetShell);
if (pSetupData != NULL)
HeapFree(GetProcessHeap(), 0, pSetupData);
LogItem(L"END_SECTION", L"InstallWizard");
}
/* EOF */