[SYSSETUP] Use a $winnt$.inf file to retrieve setup information for the 2nd-stage setup.

Following r75518, we use the $winnt$.inf file (created in System32
by the 1st-stage installer) as the setup information file for the
2nd-stage setup for:

- retrieving the installation source media path;
- retrieving the unattended information that was copied from the
  unattend.inf file from the installation source media.

The installation source media path is converted from NT format to
Win32 format for usage with Win32 functions and storage in the registry:
this is done by GetInstallSourceWin32(), which replaces the hackish
GetRosInstallCD() function.

The $winnt$.inf file is also updated, and the registry values "SourcePath"
and "ServicePackSourcePath" are created / updated in:
HKLM\Software\Microsoft\Windows\CurrentVersion\Setup .

svn path=/branches/setup_improvements/; revision=75524
This commit is contained in:
Hermès Bélusca-Maïto 2017-08-10 19:21:08 +00:00
parent 7e248feabf
commit c8d37c1a0d
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 194 additions and 88 deletions

View file

@ -50,9 +50,6 @@ typedef struct _REGISTRATIONDATA
extern void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
BOOL
GetRosInstallCD(WCHAR *pwszPath, DWORD cchPathMax);
static VOID
CenterWindow(HWND hWnd)
@ -983,16 +980,9 @@ LocalePageDlgProc(HWND hwndDlg,
PropSheet_SetWizButtons(GetParent(hwndDlg), PSWIZB_BACK | PSWIZB_NEXT);
if (SetupData->UnattendSetup)
{
WCHAR wszPath[MAX_PATH];
if (GetRosInstallCD(wszPath, _countof(wszPath)))
// if (!*SetupData->SourcePath)
{
WCHAR wszParams[1024];
swprintf(wszParams, L"intl.cpl,,/f:\"%sreactos\\unattend.inf\"", wszPath);
RunControlPanelApplet(hwndDlg, wszParams);
}
else
{
RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"unattend.inf\"");
RunControlPanelApplet(hwndDlg, L"intl.cpl,,/f:\"$winnt$.inf\""); // Should be in System32
}
SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, IDD_OWNERPAGE);
@ -2176,9 +2166,70 @@ FinishDlgProc(HWND hwndDlg,
}
/*
* 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
ProcessUnattendInf(
PSETUPDATA pSetupData)
ProcessUnattendSection(
IN OUT PSETUPDATA pSetupData)
{
INFCONTEXT InfContext;
WCHAR szName[256];
@ -2186,7 +2237,7 @@ ProcessUnattendInf(
DWORD LineLength;
HKEY hKey;
if (!SetupFindFirstLineW(pSetupData->hUnattendedInf,
if (!SetupFindFirstLineW(pSetupData->hSetupInf,
L"Unattend",
L"UnattendSetupEnabled",
&InfContext))
@ -2213,7 +2264,7 @@ ProcessUnattendInf(
pSetupData->UnattendSetup = TRUE;
if (!SetupFindFirstLineW(pSetupData->hUnattendedInf,
if (!SetupFindFirstLineW(pSetupData->hSetupInf,
L"Unattend",
NULL,
&InfContext))
@ -2290,7 +2341,7 @@ ProcessUnattendInf(
} while (SetupFindNextLine(&InfContext, &InfContext));
if (SetupFindFirstLineW(pSetupData->hUnattendedInf,
if (SetupFindFirstLineW(pSetupData->hSetupInf,
L"Display",
NULL,
&InfContext))
@ -2363,7 +2414,7 @@ ProcessUnattendInf(
return;
}
if (SetupFindFirstLineW(pSetupData->hUnattendedInf,
if (SetupFindFirstLineW(pSetupData->hSetupInf,
L"GuiRunOnce",
NULL,
&InfContext))
@ -2401,84 +2452,135 @@ ProcessUnattendInf(
RegCloseKey(hKey);
}
/*
* GetRosInstallCD should find the path to ros installation medium
* BUG 1
* If there are more than one CDDrive in it containing a ReactOS
* installation cd, then it will pick the first one regardless if
* it is really the installation cd
*
* The best way to implement this is to set the key
* HKLM\Software\Microsoft\Windows NT\CurrentVersion\SourcePath (REG_SZ)
*/
BOOL
GetRosInstallCD(WCHAR *pwszPath, DWORD cchPathMax)
{
WCHAR wszDrives[512];
DWORD cchDrives;
WCHAR *pwszDrive;
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[0]; pwszDrive += wcslen(pwszDrive) + 1)
{
if (GetDriveTypeW(pwszDrive) == DRIVE_CDROM)
{
WCHAR wszBuf[MAX_PATH];
wsprintf(wszBuf, L"%sreactos\\system32\\ntoskrnl.exe", pwszDrive);
LogItem(NULL, wszBuf);
if (GetFileAttributesW(wszBuf) != INVALID_FILE_ATTRIBUTES)
{
/* the file exists, so this is the right drive */
wcsncpy(pwszPath, pwszDrive, cchPathMax);
OutputDebugStringW(L"GetRosInstallCD: ");OutputDebugStringW(pwszPath);OutputDebugStringW(L"\n");
return TRUE;
}
}
}
return FALSE;
}
VOID
ProcessUnattendSetup(
PSETUPDATA pSetupData)
ProcessSetupInf(
IN OUT PSETUPDATA pSetupData)
{
WCHAR szPath[MAX_PATH];
DWORD dwLength;
WCHAR szValue[MAX_PATH];
INFCONTEXT InfContext;
DWORD LineLength;
HKEY hKey;
LONG res;
if (!GetRosInstallCD(szPath, MAX_PATH))
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)
{
/* no cd drive found */
DPRINT1("Error: Cannot open the setup information file %S with error %d\n", szPath, GetLastError());
return;
}
dwLength = wcslen(szPath);
if (dwLength + 21 > MAX_PATH)
/* Retrieve the NT source path from which the 1st-stage installer was run */
if (!SetupFindFirstLineW(pSetupData->hSetupInf,
L"data",
L"sourcepath",
&InfContext))
{
/* FIXME
* allocate bigger buffer
*/
DPRINT1("Error: Cannot find UnattendSetupEnabled Key! %d\n", GetLastError());
return;
}
wcscat(szPath, L"reactos\\unattend.inf");
pSetupData->hUnattendedInf = SetupOpenInfFileW(szPath,
NULL,
INF_STYLE_OLDNT,
NULL);
if (pSetupData->hUnattendedInf != INVALID_HANDLE_VALUE)
if (!SetupGetStringFieldW(&InfContext,
1,
szValue,
ARRAYSIZE(szValue),
&LineLength))
{
ProcessUnattendInf(pSetupData);
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);
@ -2542,8 +2644,8 @@ InstallWizard(VOID)
goto done;
}
pSetupData->hUnattendedInf = INVALID_HANDLE_VALUE;
ProcessUnattendSetup(pSetupData);
/* Process the $winnt$.inf setup file */
ProcessSetupInf(pSetupData);
/* Create the Welcome page */
psp.dwSize = sizeof(PROPSHEETPAGE);
@ -2658,8 +2760,8 @@ InstallWizard(VOID)
DeleteObject(pSetupData->hBoldFont);
DeleteObject(pSetupData->hTitleFont);
if (pSetupData->hUnattendedInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(pSetupData->hUnattendedInf);
if (pSetupData->hSetupInf != INVALID_HANDLE_VALUE)
SetupCloseInfFile(pSetupData->hSetupInf);
done:
if (phpage != NULL)

View file

@ -44,15 +44,19 @@ typedef struct _TIMEZONE_ENTRY
ULONG Index;
} TIMEZONE_ENTRY, *PTIMEZONE_ENTRY;
/* Private Setup data shared between syssetup.dll and netshell.dll */
typedef struct _SETUPDATA
{
HFONT hTitleFont;
HFONT hBoldFont;
WCHAR SourcePath[MAX_PATH]; // PCWSTR
WCHAR UnattendFile[MAX_PATH]; // PCWSTR
WCHAR OwnerName[51];
WCHAR OwnerOrganization[51];
WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1]; /* max. 15 characters */
WCHAR AdminPassword[128]; /* max. 127 characters */
WCHAR AdminPassword[128]; /* max. 127 characters */
BOOL UnattendSetup;
BOOL DisableGeckoInst;
@ -63,7 +67,7 @@ typedef struct _SETUPDATA
DWORD DisableAutoDaylightTimeSet;
LCID LocaleID;
HINF hUnattendedInf;
HINF hSetupInf;
UINT uFirstNetworkWizardPage;
UINT uPostNetworkWizardPage;