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)
|
if (!IniCache)
|
||||||
return;
|
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");
|
IniSection = IniAddSection(IniCache, L"SetupParams");
|
||||||
if (IniSection)
|
if (IniSection)
|
||||||
{
|
{
|
||||||
@@ -243,6 +244,7 @@ InstallSetupInfFile(
|
|||||||
// L"\"%s\"", L"WinNt5.2");
|
// L"\"%s\"", L"WinNt5.2");
|
||||||
// IniAddKey(IniSection, L"Version", PathBuffer);
|
// IniAddKey(IniSection, L"Version", PathBuffer);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
IniSection = IniAddSection(IniCache, L"Data");
|
IniSection = IniAddSection(IniCache, L"Data");
|
||||||
if (IniSection)
|
if (IniSection)
|
||||||
|
|||||||
@@ -59,6 +59,15 @@ LocaleID = 409
|
|||||||
; 3 - ReactOS Nano Server (Reserved)
|
; 3 - ReactOS Nano Server (Reserved)
|
||||||
InstallationType = 0
|
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.
|
; Enable this section to automatically launch programs after 3rd boot.
|
||||||
;[GuiRunOnce]
|
;[GuiRunOnce]
|
||||||
;%SystemRoot%\system32\cmd.exe
|
;%SystemRoot%\system32\cmd.exe
|
||||||
|
|||||||
@@ -73,6 +73,10 @@ HRESULT
|
|||||||
InstallOptionalComponents(
|
InstallOptionalComponents(
|
||||||
_In_ PITEMSDATA pItemsData);
|
_In_ PITEMSDATA pItemsData);
|
||||||
|
|
||||||
|
HRESULT
|
||||||
|
RunCommandAndWait(
|
||||||
|
_In_ PWCHAR Command);
|
||||||
|
|
||||||
/* install */
|
/* install */
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
@@ -109,6 +113,10 @@ VOID
|
|||||||
SetAutoAdminLogon(VOID);
|
SetAutoAdminLogon(VOID);
|
||||||
|
|
||||||
/* wizard.c */
|
/* wizard.c */
|
||||||
VOID InstallWizard (VOID);
|
VOID
|
||||||
|
InstallWizard(VOID);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
GetSetupInfPath(PWSTR szPath, UINT cchMax);
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
* PURPOSE: System setup
|
* PURPOSE: System setup
|
||||||
* FILE: dll/win32/syssetup/install.c
|
* FILE: dll/win32/syssetup/install.c
|
||||||
* PROGRAMER: Eric Kohl
|
* PROGRAMER: Eric Kohl
|
||||||
|
* Whindmar Saksit <[email protected]>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* INCLUDES *****************************************************************/
|
/* INCLUDES *****************************************************************/
|
||||||
@@ -985,6 +986,26 @@ cleanup:
|
|||||||
return bConsoleBoot;
|
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
|
extern VOID
|
||||||
EnableVisualTheme(
|
EnableVisualTheme(
|
||||||
_In_opt_ HWND hwndParent,
|
_In_opt_ HWND hwndParent,
|
||||||
@@ -1010,8 +1031,7 @@ PreprocessUnattend(
|
|||||||
{
|
{
|
||||||
/* See also wizard.c!ProcessSetupInf()
|
/* See also wizard.c!ProcessSetupInf()
|
||||||
* Retrieve the path of the setup INF */
|
* Retrieve the path of the setup INF */
|
||||||
GetSystemDirectoryW(szPath, _countof(szPath));
|
GetSetupInfPath(szPath, _countof(szPath));
|
||||||
wcscat(szPath, L"\\$winnt$.inf");
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1038,6 +1058,9 @@ PreprocessUnattend(
|
|||||||
|
|
||||||
/* Enable the chosen theme, or use the classic theme */
|
/* Enable the chosen theme, or use the classic theme */
|
||||||
EnableVisualTheme(NULL, bDefaultThemesOff ? NULL : szValue);
|
EnableVisualTheme(NULL, bDefaultThemesOff ? NULL : szValue);
|
||||||
|
|
||||||
|
if (IsInstall)
|
||||||
|
ProcessDetachedProgram(szPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL
|
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);
|
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
|
static VOID
|
||||||
CenterWindow(HWND hWnd)
|
CenterWindow(HWND hWnd)
|
||||||
{
|
{
|
||||||
@@ -2740,31 +2747,38 @@ ProcessPageDlgProc(HWND hwndDlg,
|
|||||||
|
|
||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
SetInstallationCompleted(VOID)
|
SetInstallationCompleted(IN BOOL Unattended)
|
||||||
{
|
{
|
||||||
HKEY hKey = 0;
|
HKEY hKey = 0;
|
||||||
DWORD InProgress = 0;
|
DWORD InProgress = 0;
|
||||||
DWORD InstallDate;
|
DWORD InstallDate;
|
||||||
|
|
||||||
if (RegOpenKeyExW( HKEY_LOCAL_MACHINE,
|
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows NT\\CurrentVersion",
|
||||||
L"SYSTEM\\Setup",
|
0, KEY_WRITE, &hKey) == ERROR_SUCCESS)
|
||||||
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);
|
InstallDate = (DWORD)time(NULL);
|
||||||
RegSetValueExW( hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate) );
|
RegSetValueExW(hKey, L"InstallDate", 0, REG_DWORD, (LPBYTE)&InstallDate, sizeof(InstallDate));
|
||||||
RegCloseKey( hKey );
|
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)
|
if (SetupData->UnattendSetup)
|
||||||
{
|
{
|
||||||
KillTimer(hwndDlg, 1);
|
KillTimer(hwndDlg, 1);
|
||||||
SetInstallationCompleted();
|
SetInstallationCompleted(TRUE);
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2802,7 +2816,7 @@ FinishDlgProc(HWND hwndDlg,
|
|||||||
|
|
||||||
case WM_DESTROY:
|
case WM_DESTROY:
|
||||||
{
|
{
|
||||||
SetInstallationCompleted();
|
SetInstallationCompleted(FALSE);
|
||||||
PostQuitMessage(0);
|
PostQuitMessage(0);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -3335,8 +3349,7 @@ ProcessSetupInf(
|
|||||||
pSetupData->hSetupInf = INVALID_HANDLE_VALUE;
|
pSetupData->hSetupInf = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
/* Retrieve the path of the setup INF */
|
/* Retrieve the path of the setup INF */
|
||||||
GetSystemDirectoryW(szPath, _countof(szPath));
|
GetSetupInfPath(szPath, _countof(szPath));
|
||||||
wcscat(szPath, L"\\$winnt$.inf");
|
|
||||||
|
|
||||||
/* Open the setup INF */
|
/* Open the setup INF */
|
||||||
pSetupData->hSetupInf = SetupOpenInfFileW(szPath,
|
pSetupData->hSetupInf = SetupOpenInfFileW(szPath,
|
||||||
|
|||||||
Reference in New Issue
Block a user