mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 17:10:22 +00:00
[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:
parent
7e248feabf
commit
c8d37c1a0d
2 changed files with 194 additions and 88 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue