mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-08-26 19:33:31 +00:00
[SYSSETUP][BOOTDATA] Unattended execute GuiUnattended:DetachedProgram , SetupParams:UserExecute (#9276)
This PR implements two of the three hooks that allows you to run custom applications during 2nd-stage setup (the 3rd hook is `...\$OEM$\Cmdlines.txt`, but that requires file copy operations, etc.) - `DetachedProgram` is documented[^1] for NT4...2003; it is started before installation and `UserExecute` after. - `UserExecute` is a great place to install VM Guest Additions, one reboot less and you have shared folders/clipboard on the first normal boot. [^1]: https://web.archive.org/web/20090902145959/http://technet.microsoft.com/en-us/library/cc757642(WS.10).aspx
This commit is contained in:
@@ -235,6 +235,7 @@ InstallSetupInfFile(
|
||||
if (!IniCache)
|
||||
return;
|
||||
|
||||
#if 0 /* If you need to put something in this section, do it after the merge with Unattend.inf */
|
||||
IniSection = IniAddSection(IniCache, L"SetupParams");
|
||||
if (IniSection)
|
||||
{
|
||||
@@ -243,6 +244,7 @@ InstallSetupInfFile(
|
||||
// L"\"%s\"", L"WinNt5.2");
|
||||
// IniAddKey(IniSection, L"Version", PathBuffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
IniSection = IniAddSection(IniCache, L"Data");
|
||||
if (IniSection)
|
||||
|
||||
@@ -59,6 +59,15 @@ LocaleID = 409
|
||||
; 3 - ReactOS Nano Server (Reserved)
|
||||
InstallationType = 0
|
||||
|
||||
;[GuiUnattended]
|
||||
; Run a program early in 2nd-stage setup.
|
||||
;DetachedProgram=%SystemRoot%\system32\cmd.exe
|
||||
;Arguments="/C echo.Early 2nd-stage setup...&choice>nul /N /T:Y,5"
|
||||
|
||||
;[SetupParams]
|
||||
; Run a program at the end of 2nd-stage setup.
|
||||
;UserExecute="cmd.exe /C echo.End of 2nd-stage setup...&choice>nul /N /T:Y,5"
|
||||
|
||||
; Enable this section to automatically launch programs after 3rd boot.
|
||||
;[GuiRunOnce]
|
||||
;%SystemRoot%\system32\cmd.exe
|
||||
|
||||
@@ -73,6 +73,10 @@ HRESULT
|
||||
InstallOptionalComponents(
|
||||
_In_ PITEMSDATA pItemsData);
|
||||
|
||||
HRESULT
|
||||
RunCommandAndWait(
|
||||
_In_ PWCHAR Command);
|
||||
|
||||
/* install */
|
||||
|
||||
BOOL
|
||||
@@ -109,6 +113,10 @@ VOID
|
||||
SetAutoAdminLogon(VOID);
|
||||
|
||||
/* wizard.c */
|
||||
VOID InstallWizard (VOID);
|
||||
VOID
|
||||
InstallWizard(VOID);
|
||||
|
||||
VOID
|
||||
GetSetupInfPath(PWSTR szPath, UINT cchMax);
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
* PURPOSE: System setup
|
||||
* FILE: dll/win32/syssetup/install.c
|
||||
* PROGRAMER: Eric Kohl
|
||||
* Whindmar Saksit <[email protected]>
|
||||
*/
|
||||
|
||||
/* INCLUDES *****************************************************************/
|
||||
@@ -985,6 +986,26 @@ cleanup:
|
||||
return bConsoleBoot;
|
||||
}
|
||||
|
||||
static VOID
|
||||
ProcessDetachedProgram(
|
||||
_In_ PCWSTR pszInf)
|
||||
{
|
||||
WCHAR szInfApp[MAX_PATH], szInfArg[MAX_PATH * 3];
|
||||
WCHAR szCmd[_countof(szInfApp) + _countof(szInfArg)];
|
||||
UINT cch;
|
||||
|
||||
if (!GetPrivateProfileStringW(L"GuiUnattended", L"DetachedProgram", L"", szInfApp, _countof(szInfApp), pszInf) || !*szInfApp)
|
||||
return;
|
||||
cch = ExpandEnvironmentStrings(szInfApp, szCmd, _countof(szCmd) - 1);
|
||||
if (GetPrivateProfileStringW(L"GuiUnattended", L"Arguments", L"", szInfArg, _countof(szInfArg), pszInf) && cch)
|
||||
{
|
||||
szCmd[cch - 1] = L' ';
|
||||
szCmd[cch] = UNICODE_NULL;
|
||||
ExpandEnvironmentStrings(szInfArg, szCmd + cch, _countof(szCmd) - cch);
|
||||
}
|
||||
RunCommandAndWait(szCmd);
|
||||
}
|
||||
|
||||
extern VOID
|
||||
EnableVisualTheme(
|
||||
_In_opt_ HWND hwndParent,
|
||||
@@ -1010,8 +1031,7 @@ PreprocessUnattend(
|
||||
{
|
||||
/* See also wizard.c!ProcessSetupInf()
|
||||
* Retrieve the path of the setup INF */
|
||||
GetSystemDirectoryW(szPath, _countof(szPath));
|
||||
wcscat(szPath, L"\\$winnt$.inf");
|
||||
GetSetupInfPath(szPath, _countof(szPath));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1038,6 +1058,9 @@ PreprocessUnattend(
|
||||
|
||||
/* Enable the chosen theme, or use the classic theme */
|
||||
EnableVisualTheme(NULL, bDefaultThemesOff ? NULL : szValue);
|
||||
|
||||
if (IsInstall)
|
||||
ProcessDetachedProgram(szPath);
|
||||
}
|
||||
|
||||
static BOOL
|
||||
|
||||
+35
-22
@@ -53,6 +53,13 @@ typedef struct _TIMEZONE_ENTRY
|
||||
|
||||
extern void WINAPI Control_RunDLLW(HWND hWnd, HINSTANCE hInst, LPCWSTR cmd, DWORD nCmdShow);
|
||||
|
||||
VOID
|
||||
GetSetupInfPath(PWSTR szPath, UINT cchMax)
|
||||
{
|
||||
GetSystemDirectoryW(szPath, cchMax);
|
||||
wcscat(szPath, L"\\$winnt$.inf");
|
||||
}
|
||||
|
||||
static VOID
|
||||
CenterWindow(HWND hWnd)
|
||||
{
|
||||
@@ -2740,31 +2747,38 @@ ProcessPageDlgProc(HWND hwndDlg,
|
||||
|
||||
|
||||
static VOID
|
||||
SetInstallationCompleted(VOID)
|
||||
SetInstallationCompleted(IN BOOL Unattended)
|
||||
{
|
||||
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)
|
||||
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 );
|
||||
RegSetValueExW(hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate));
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
if (Unattended)
|
||||
{
|
||||
WCHAR szInf[MAX_PATH];
|
||||
WCHAR szInfCmd[MAX_PATH * 4], szCmd[_countof(szInfCmd)];
|
||||
|
||||
GetSetupInfPath(szInf, _countof(szInf));
|
||||
if (GetPrivateProfileStringW(L"SetupParams", L"UserExecute", L"", szInfCmd, _countof(szInfCmd), szInf) && *szInfCmd)
|
||||
{
|
||||
*szCmd = UNICODE_NULL;
|
||||
ExpandEnvironmentStringsW(szInfCmd, szCmd, _countof(szInfCmd));
|
||||
RunCommandAndWait(szCmd);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2790,7 +2804,7 @@ FinishDlgProc(HWND hwndDlg,
|
||||
if (SetupData->UnattendSetup)
|
||||
{
|
||||
KillTimer(hwndDlg, 1);
|
||||
SetInstallationCompleted();
|
||||
SetInstallationCompleted(TRUE);
|
||||
PostQuitMessage(0);
|
||||
}
|
||||
|
||||
@@ -2802,7 +2816,7 @@ FinishDlgProc(HWND hwndDlg,
|
||||
|
||||
case WM_DESTROY:
|
||||
{
|
||||
SetInstallationCompleted();
|
||||
SetInstallationCompleted(FALSE);
|
||||
PostQuitMessage(0);
|
||||
return TRUE;
|
||||
}
|
||||
@@ -3335,8 +3349,7 @@ ProcessSetupInf(
|
||||
pSetupData->hSetupInf = INVALID_HANDLE_VALUE;
|
||||
|
||||
/* Retrieve the path of the setup INF */
|
||||
GetSystemDirectoryW(szPath, _countof(szPath));
|
||||
wcscat(szPath, L"\\$winnt$.inf");
|
||||
GetSetupInfPath(szPath, _countof(szPath));
|
||||
|
||||
/* Open the setup INF */
|
||||
pSetupData->hSetupInf = SetupOpenInfFileW(szPath,
|
||||
|
||||
Reference in New Issue
Block a user