mirror of
https://github.com/reactos/reactos.git
synced 2024-10-30 19:41:57 +00:00
03422451b3
on TRACE, WARN, FIXME and ERR calls. Plus a few nit picks.
722 lines
21 KiB
C
722 lines
21 KiB
C
/*
|
|
* ReactOS applications
|
|
* Copyright (C) 2001, 2002 ReactOS Team
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Userinit Logon Application
|
|
* FILE: base/system/userinit/userinit.c
|
|
* PROGRAMMERS: Thomas Weidenmueller (w3seek@users.sourceforge.net)
|
|
* Hervé Poussineau (hpoussin@reactos.org)
|
|
*/
|
|
|
|
#include "userinit.h"
|
|
|
|
#define CMP_MAGIC 0x01234567
|
|
|
|
/* GLOBALS ******************************************************************/
|
|
|
|
HINSTANCE hInstance;
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
LONG
|
|
ReadRegSzKey(
|
|
IN HKEY hKey,
|
|
IN LPCWSTR pszKey,
|
|
OUT LPWSTR *pValue)
|
|
{
|
|
LONG rc;
|
|
DWORD dwType;
|
|
DWORD cbData = 0;
|
|
LPWSTR Value;
|
|
|
|
TRACE("(%p, %s, %p)\n", hKey, debugstr_w(pszKey), pValue);
|
|
|
|
rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey), rc);
|
|
return rc;
|
|
}
|
|
if (dwType != REG_SZ)
|
|
{
|
|
WARN("Wrong registry data type (%u vs %u)\n", dwType, REG_SZ);
|
|
return ERROR_FILE_NOT_FOUND;
|
|
}
|
|
Value = (WCHAR*) HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
|
|
if (!Value)
|
|
{
|
|
WARN("No memory\n");
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegQueryValueEx(%s) failed with error %lu\n", debugstr_w(pszKey), rc);
|
|
HeapFree(GetProcessHeap(), 0, Value);
|
|
return rc;
|
|
}
|
|
/* NULL-terminate the string */
|
|
Value[cbData / sizeof(WCHAR)] = L'\0';
|
|
|
|
*pValue = Value;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
static BOOL
|
|
IsConsoleShell(VOID)
|
|
{
|
|
HKEY ControlKey = NULL;
|
|
LPWSTR SystemStartOptions = NULL;
|
|
LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
|
|
LONG rc;
|
|
BOOL ret = FALSE;
|
|
|
|
TRACE("()\n");
|
|
|
|
rc = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
REGSTR_PATH_CURRENT_CONTROL_SET,
|
|
0,
|
|
KEY_QUERY_VALUE,
|
|
&ControlKey);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegOpenKeyEx() failed with error %lu\n", rc);
|
|
goto cleanup;
|
|
}
|
|
|
|
rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("ReadRegSzKey() failed with error %lu\n", rc);
|
|
goto cleanup;
|
|
}
|
|
|
|
/* Check for CONSOLE switch in SystemStartOptions */
|
|
CurrentOption = SystemStartOptions;
|
|
while (CurrentOption)
|
|
{
|
|
NextOption = wcschr(CurrentOption, L' ');
|
|
if (NextOption)
|
|
*NextOption = L'\0';
|
|
if (_wcsicmp(CurrentOption, L"CONSOLE") == 0)
|
|
{
|
|
TRACE("Found 'CONSOLE' boot option\n");
|
|
ret = TRUE;
|
|
goto cleanup;
|
|
}
|
|
CurrentOption = NextOption ? NextOption + 1 : NULL;
|
|
}
|
|
|
|
cleanup:
|
|
if (ControlKey != NULL)
|
|
RegCloseKey(ControlKey);
|
|
HeapFree(GetProcessHeap(), 0, SystemStartOptions);
|
|
TRACE("IsConsoleShell() returning %d\n", ret);
|
|
return ret;
|
|
}
|
|
|
|
static BOOL
|
|
GetShell(
|
|
OUT WCHAR *CommandLine, /* must be at least MAX_PATH long */
|
|
IN HKEY hRootKey)
|
|
{
|
|
HKEY hKey;
|
|
DWORD Type, Size;
|
|
WCHAR Shell[MAX_PATH];
|
|
BOOL ConsoleShell = IsConsoleShell();
|
|
LONG rc;
|
|
|
|
TRACE("(%p, %p)\n", CommandLine, hRootKey);
|
|
|
|
rc = RegOpenKeyExW(hRootKey, L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
|
|
0, KEY_QUERY_VALUE, &hKey);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegOpenKeyEx() failed with error %lu\n", rc);
|
|
return FALSE;
|
|
}
|
|
|
|
Size = sizeof(Shell);
|
|
rc = RegQueryValueExW(hKey,
|
|
ConsoleShell ? L"ConsoleShell" : L"Shell",
|
|
NULL,
|
|
&Type,
|
|
(LPBYTE)Shell,
|
|
&Size);
|
|
RegCloseKey(hKey);
|
|
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegQueryValueEx() failed with error %lu\n", rc);
|
|
return FALSE;
|
|
}
|
|
|
|
if ((Type == REG_SZ) || (Type == REG_EXPAND_SZ))
|
|
{
|
|
TRACE("Found command line %s\n", debugstr_w(Shell));
|
|
wcscpy(CommandLine, Shell);
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
WARN("Wrong type %lu (expected %u or %u)\n", Type, REG_SZ, REG_EXPAND_SZ);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
static BOOL
|
|
StartProcess(
|
|
IN LPCWSTR CommandLine)
|
|
{
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
WCHAR ExpandedCmdLine[MAX_PATH];
|
|
|
|
TRACE("(%s)\n", debugstr_w(CommandLine));
|
|
|
|
ExpandEnvironmentStringsW(CommandLine, ExpandedCmdLine, ARRAYSIZE(ExpandedCmdLine));
|
|
|
|
ZeroMemory(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
si.dwFlags = STARTF_USESHOWWINDOW;
|
|
si.wShowWindow = SW_SHOWNORMAL;
|
|
ZeroMemory(&pi, sizeof(pi));
|
|
|
|
if (!CreateProcessW(NULL,
|
|
ExpandedCmdLine,
|
|
NULL,
|
|
NULL,
|
|
FALSE,
|
|
NORMAL_PRIORITY_CLASS,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&pi))
|
|
{
|
|
WARN("CreateProcessW() failed with error %lu\n", GetLastError());
|
|
return FALSE;
|
|
}
|
|
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL
|
|
StartShell(VOID)
|
|
{
|
|
WCHAR Shell[MAX_PATH];
|
|
WCHAR szMsg[RC_STRING_MAX_SIZE];
|
|
DWORD Type, Size;
|
|
DWORD Value = 0;
|
|
LONG rc;
|
|
HKEY hKey;
|
|
|
|
TRACE("()\n");
|
|
|
|
/* Safe Mode shell run */
|
|
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot\\Option",
|
|
0, KEY_QUERY_VALUE, &hKey);
|
|
if (rc == ERROR_SUCCESS)
|
|
{
|
|
Size = sizeof(Value);
|
|
rc = RegQueryValueExW(hKey, L"UseAlternateShell", NULL,
|
|
&Type, (LPBYTE)&Value, &Size);
|
|
RegCloseKey(hKey);
|
|
|
|
if (rc == ERROR_SUCCESS)
|
|
{
|
|
if (Type == REG_DWORD)
|
|
{
|
|
if (Value)
|
|
{
|
|
/* Safe Mode Alternate Shell required */
|
|
rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
|
L"SYSTEM\\CurrentControlSet\\Control\\SafeBoot",
|
|
0, KEY_READ, &hKey);
|
|
if (rc == ERROR_SUCCESS)
|
|
{
|
|
Size = sizeof(Shell);
|
|
rc = RegQueryValueExW(hKey, L"AlternateShell", NULL,
|
|
&Type, (LPBYTE)Shell, &Size);
|
|
RegCloseKey(hKey);
|
|
|
|
if (rc == ERROR_SUCCESS)
|
|
{
|
|
if ((Type == REG_SZ) || (Type == REG_EXPAND_SZ))
|
|
{
|
|
TRACE("Key located - %s\n", debugstr_w(Shell));
|
|
|
|
/* Try to run alternate shell */
|
|
if (StartProcess(Shell))
|
|
{
|
|
TRACE("Alternate shell started (Safe Mode)\n");
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARN("Wrong type %lu (expected %u or %u)\n",
|
|
Type, REG_SZ, REG_EXPAND_SZ);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARN("Alternate shell in Safe Mode required but not specified.\n");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
WARN("Wrong type %lu (expected %u)\n", Type, REG_DWORD);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Try to run shell in user key */
|
|
if (GetShell(Shell, HKEY_CURRENT_USER) && StartProcess(Shell))
|
|
{
|
|
TRACE("Started shell from HKEY_CURRENT_USER\n");
|
|
return TRUE;
|
|
}
|
|
|
|
/* Try to run shell in local machine key */
|
|
if (GetShell(Shell, HKEY_LOCAL_MACHINE) && StartProcess(Shell))
|
|
{
|
|
TRACE("Started shell from HKEY_LOCAL_MACHINE\n");
|
|
return TRUE;
|
|
}
|
|
|
|
/* Try default shell */
|
|
if (IsConsoleShell())
|
|
{
|
|
*Shell = UNICODE_NULL;
|
|
if (GetSystemDirectoryW(Shell, ARRAYSIZE(Shell) - 8))
|
|
StringCchCatW(Shell, ARRAYSIZE(Shell), L"\\");
|
|
StringCchCatW(Shell, ARRAYSIZE(Shell), L"cmd.exe");
|
|
}
|
|
else
|
|
{
|
|
*Shell = UNICODE_NULL;
|
|
if (GetSystemWindowsDirectoryW(Shell, ARRAYSIZE(Shell) - 13))
|
|
StringCchCatW(Shell, ARRAYSIZE(Shell), L"\\");
|
|
StringCchCatW(Shell, ARRAYSIZE(Shell), L"explorer.exe");
|
|
}
|
|
|
|
if (!StartProcess(Shell))
|
|
{
|
|
WARN("Failed to start default shell '%s'\n", debugstr_w(Shell));
|
|
LoadStringW(GetModuleHandle(NULL), IDS_SHELL_FAIL, szMsg, ARRAYSIZE(szMsg));
|
|
MessageBoxW(NULL, szMsg, NULL, MB_OK);
|
|
return FALSE;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
const WCHAR g_RegColorNames[][32] = {
|
|
L"Scrollbar", /* 00 = COLOR_SCROLLBAR */
|
|
L"Background", /* 01 = COLOR_DESKTOP */
|
|
L"ActiveTitle", /* 02 = COLOR_ACTIVECAPTION */
|
|
L"InactiveTitle", /* 03 = COLOR_INACTIVECAPTION */
|
|
L"Menu", /* 04 = COLOR_MENU */
|
|
L"Window", /* 05 = COLOR_WINDOW */
|
|
L"WindowFrame", /* 06 = COLOR_WINDOWFRAME */
|
|
L"MenuText", /* 07 = COLOR_MENUTEXT */
|
|
L"WindowText", /* 08 = COLOR_WINDOWTEXT */
|
|
L"TitleText", /* 09 = COLOR_CAPTIONTEXT */
|
|
L"ActiveBorder", /* 10 = COLOR_ACTIVEBORDER */
|
|
L"InactiveBorder", /* 11 = COLOR_INACTIVEBORDER */
|
|
L"AppWorkSpace", /* 12 = COLOR_APPWORKSPACE */
|
|
L"Hilight", /* 13 = COLOR_HIGHLIGHT */
|
|
L"HilightText", /* 14 = COLOR_HIGHLIGHTTEXT */
|
|
L"ButtonFace", /* 15 = COLOR_BTNFACE */
|
|
L"ButtonShadow", /* 16 = COLOR_BTNSHADOW */
|
|
L"GrayText", /* 17 = COLOR_GRAYTEXT */
|
|
L"ButtonText", /* 18 = COLOR_BTNTEXT */
|
|
L"InactiveTitleText", /* 19 = COLOR_INACTIVECAPTIONTEXT */
|
|
L"ButtonHilight", /* 20 = COLOR_BTNHIGHLIGHT */
|
|
L"ButtonDkShadow", /* 21 = COLOR_3DDKSHADOW */
|
|
L"ButtonLight", /* 22 = COLOR_3DLIGHT */
|
|
L"InfoText", /* 23 = COLOR_INFOTEXT */
|
|
L"InfoWindow", /* 24 = COLOR_INFOBK */
|
|
L"ButtonAlternateFace", /* 25 = COLOR_ALTERNATEBTNFACE */
|
|
L"HotTrackingColor", /* 26 = COLOR_HOTLIGHT */
|
|
L"GradientActiveTitle", /* 27 = COLOR_GRADIENTACTIVECAPTION */
|
|
L"GradientInactiveTitle", /* 28 = COLOR_GRADIENTINACTIVECAPTION */
|
|
L"MenuHilight", /* 29 = COLOR_MENUHILIGHT */
|
|
L"MenuBar" /* 30 = COLOR_MENUBAR */
|
|
};
|
|
|
|
static COLORREF
|
|
StrToColorref(
|
|
IN LPWSTR lpszCol)
|
|
{
|
|
BYTE rgb[3];
|
|
|
|
TRACE("(%s)\n", debugstr_w(lpszCol));
|
|
|
|
rgb[0] = (BYTE)wcstoul(lpszCol, &lpszCol, 10);
|
|
rgb[1] = (BYTE)wcstoul(lpszCol, &lpszCol, 10);
|
|
rgb[2] = (BYTE)wcstoul(lpszCol, &lpszCol, 10);
|
|
return RGB(rgb[0], rgb[1], rgb[2]);
|
|
}
|
|
|
|
static VOID
|
|
SetUserSysColors(VOID)
|
|
{
|
|
HKEY hKey;
|
|
INT i;
|
|
WCHAR szColor[25];
|
|
DWORD Type, Size;
|
|
COLORREF crColor;
|
|
LONG rc;
|
|
|
|
TRACE("()\n");
|
|
|
|
rc = RegOpenKeyExW(HKEY_CURRENT_USER, REGSTR_PATH_COLORS,
|
|
0, KEY_QUERY_VALUE, &hKey);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegOpenKeyEx() failed with error %lu\n", rc);
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < ARRAYSIZE(g_RegColorNames); i++)
|
|
{
|
|
Size = sizeof(szColor);
|
|
rc = RegQueryValueExW(hKey, g_RegColorNames[i], NULL, &Type,
|
|
(LPBYTE)szColor, &Size);
|
|
if (rc == ERROR_SUCCESS && Type == REG_SZ)
|
|
{
|
|
crColor = StrToColorref(szColor);
|
|
SetSysColors(1, &i, &crColor);
|
|
}
|
|
else
|
|
{
|
|
WARN("RegQueryValueEx(%s) failed with error %lu\n",
|
|
debugstr_w(g_RegColorNames[i]), rc);
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
static VOID
|
|
SetUserWallpaper(VOID)
|
|
{
|
|
HKEY hKey;
|
|
DWORD Type, Size;
|
|
WCHAR szWallpaper[MAX_PATH + 1];
|
|
LONG rc;
|
|
|
|
TRACE("()\n");
|
|
|
|
rc = RegOpenKeyExW(HKEY_CURRENT_USER, REGSTR_PATH_DESKTOP,
|
|
0, KEY_QUERY_VALUE, &hKey);
|
|
if (rc != ERROR_SUCCESS)
|
|
{
|
|
WARN("RegOpenKeyEx() failed with error %lu\n", rc);
|
|
return;
|
|
}
|
|
|
|
Size = sizeof(szWallpaper);
|
|
rc = RegQueryValueExW(hKey,
|
|
L"Wallpaper",
|
|
NULL,
|
|
&Type,
|
|
(LPBYTE)szWallpaper,
|
|
&Size);
|
|
RegCloseKey(hKey);
|
|
|
|
if (rc == ERROR_SUCCESS && Type == REG_SZ)
|
|
{
|
|
ExpandEnvironmentStringsW(szWallpaper, szWallpaper, ARRAYSIZE(szWallpaper));
|
|
TRACE("Using wallpaper %s\n", debugstr_w(szWallpaper));
|
|
|
|
/* Load and change the wallpaper */
|
|
SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, szWallpaper, SPIF_SENDCHANGE);
|
|
}
|
|
else
|
|
{
|
|
/* Remove the wallpaper */
|
|
TRACE("No wallpaper set in registry (error %lu)\n", rc);
|
|
SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, NULL, SPIF_SENDCHANGE);
|
|
}
|
|
}
|
|
|
|
static VOID
|
|
SetUserSettings(VOID)
|
|
{
|
|
TRACE("()\n");
|
|
|
|
UpdatePerUserSystemParameters(1, TRUE);
|
|
SetUserSysColors();
|
|
SetUserWallpaper();
|
|
}
|
|
|
|
typedef DWORD (WINAPI *PCMP_REPORT_LOGON)(DWORD, DWORD);
|
|
|
|
static VOID
|
|
NotifyLogon(VOID)
|
|
{
|
|
HINSTANCE hModule;
|
|
PCMP_REPORT_LOGON CMP_Report_LogOn;
|
|
|
|
TRACE("()\n");
|
|
|
|
hModule = LoadLibraryW(L"setupapi.dll");
|
|
if (!hModule)
|
|
{
|
|
WARN("LoadLibrary() failed with error %lu\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
CMP_Report_LogOn = (PCMP_REPORT_LOGON)GetProcAddress(hModule, "CMP_Report_LogOn");
|
|
if (CMP_Report_LogOn)
|
|
CMP_Report_LogOn(CMP_MAGIC, GetCurrentProcessId());
|
|
else
|
|
WARN("GetProcAddress() failed\n");
|
|
|
|
FreeLibrary(hModule);
|
|
}
|
|
|
|
static BOOL
|
|
StartInstaller(IN LPCTSTR lpInstallerName)
|
|
{
|
|
SYSTEM_INFO SystemInfo;
|
|
SIZE_T cchInstallerNameLen;
|
|
PWSTR ptr;
|
|
DWORD dwAttribs;
|
|
WCHAR Installer[MAX_PATH];
|
|
WCHAR szMsg[RC_STRING_MAX_SIZE];
|
|
|
|
cchInstallerNameLen = wcslen(lpInstallerName);
|
|
if (ARRAYSIZE(Installer) < cchInstallerNameLen)
|
|
{
|
|
/* The buffer is not large enough to contain the installer file name */
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* First, try to find the installer using the default drive, under
|
|
* the directory whose name corresponds to the currently-running
|
|
* CPU architecture.
|
|
*/
|
|
GetSystemInfo(&SystemInfo);
|
|
|
|
*Installer = UNICODE_NULL;
|
|
/* Alternatively one can use SharedUserData->NtSystemRoot */
|
|
GetSystemWindowsDirectoryW(Installer, ARRAYSIZE(Installer) - cchInstallerNameLen - 1);
|
|
ptr = wcschr(Installer, L'\\');
|
|
if (ptr)
|
|
*++ptr = UNICODE_NULL;
|
|
else
|
|
*Installer = UNICODE_NULL;
|
|
|
|
/* Append the corresponding CPU architecture */
|
|
switch (SystemInfo.wProcessorArchitecture)
|
|
{
|
|
case PROCESSOR_ARCHITECTURE_INTEL:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"I386");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_MIPS:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"MIPS");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_ALPHA:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"ALPHA");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_PPC:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"PPC");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_SHX:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"SHX");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_ARM:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"ARM");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_IA64:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"IA64");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_ALPHA64:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"ALPHA64");
|
|
break;
|
|
|
|
case PROCESSOR_ARCHITECTURE_AMD64:
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"AMD64");
|
|
break;
|
|
|
|
// case PROCESSOR_ARCHITECTURE_MSIL: /* .NET CPU-independent code */
|
|
case PROCESSOR_ARCHITECTURE_UNKNOWN:
|
|
default:
|
|
WARN("Unknown processor architecture %lu\n", SystemInfo.wProcessorArchitecture);
|
|
SystemInfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
if (SystemInfo.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_UNKNOWN)
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"\\");
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), lpInstallerName);
|
|
|
|
dwAttribs = GetFileAttributesW(Installer);
|
|
if ((dwAttribs != INVALID_FILE_ATTRIBUTES) &&
|
|
!(dwAttribs & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
/* We have found the installer */
|
|
if (StartProcess(Installer))
|
|
return TRUE;
|
|
}
|
|
|
|
ERR("Failed to start the installer '%s', trying alternative.\n", debugstr_w(Installer));
|
|
|
|
/*
|
|
* We failed. Try to find the installer from either the current
|
|
* ReactOS installation directory, or from our current directory.
|
|
*/
|
|
*Installer = UNICODE_NULL;
|
|
/* Alternatively one can use SharedUserData->NtSystemRoot */
|
|
if (GetSystemWindowsDirectoryW(Installer, ARRAYSIZE(Installer) - cchInstallerNameLen - 1))
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), L"\\");
|
|
StringCchCatW(Installer, ARRAYSIZE(Installer), lpInstallerName);
|
|
|
|
dwAttribs = GetFileAttributesW(Installer);
|
|
if ((dwAttribs != INVALID_FILE_ATTRIBUTES) &&
|
|
!(dwAttribs & FILE_ATTRIBUTE_DIRECTORY))
|
|
{
|
|
/* We have found the installer */
|
|
if (StartProcess(Installer))
|
|
return TRUE;
|
|
}
|
|
|
|
/* We failed. Display an error message and quit. */
|
|
ERR("Failed to start the installer '%s'.\n", debugstr_w(Installer));
|
|
LoadStringW(GetModuleHandle(NULL), IDS_INSTALLER_FAIL, szMsg, ARRAYSIZE(szMsg));
|
|
MessageBoxW(NULL, szMsg, NULL, MB_OK);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Used to get the shutdown privilege */
|
|
static BOOL
|
|
EnablePrivilege(LPCWSTR lpszPrivilegeName, BOOL bEnablePrivilege)
|
|
{
|
|
BOOL Success;
|
|
HANDLE hToken;
|
|
TOKEN_PRIVILEGES tp;
|
|
|
|
Success = OpenProcessToken(GetCurrentProcess(),
|
|
TOKEN_ADJUST_PRIVILEGES,
|
|
&hToken);
|
|
if (!Success) return Success;
|
|
|
|
Success = LookupPrivilegeValueW(NULL,
|
|
lpszPrivilegeName,
|
|
&tp.Privileges[0].Luid);
|
|
if (!Success) goto Quit;
|
|
|
|
tp.PrivilegeCount = 1;
|
|
tp.Privileges[0].Attributes = (bEnablePrivilege ? SE_PRIVILEGE_ENABLED : 0);
|
|
|
|
Success = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
|
|
|
|
Quit:
|
|
CloseHandle(hToken);
|
|
return Success;
|
|
}
|
|
|
|
|
|
int WINAPI
|
|
wWinMain(IN HINSTANCE hInst,
|
|
IN HINSTANCE hPrevInstance,
|
|
IN LPWSTR lpszCmdLine,
|
|
IN int nCmdShow)
|
|
{
|
|
BOOL bIsLiveCD, Success = TRUE;
|
|
STATE State;
|
|
|
|
hInstance = hInst;
|
|
|
|
bIsLiveCD = IsLiveCD();
|
|
|
|
Restart:
|
|
SetUserSettings();
|
|
|
|
if (bIsLiveCD)
|
|
{
|
|
State.NextPage = LOCALEPAGE;
|
|
State.Run = SHELL;
|
|
}
|
|
else
|
|
{
|
|
State.NextPage = DONE;
|
|
State.Run = SHELL;
|
|
}
|
|
|
|
if (State.NextPage != DONE) // && bIsLiveCD
|
|
{
|
|
RunLiveCD(&State);
|
|
}
|
|
|
|
switch (State.Run)
|
|
{
|
|
case SHELL:
|
|
Success = StartShell();
|
|
if (Success)
|
|
NotifyLogon();
|
|
break;
|
|
|
|
case INSTALLER:
|
|
Success = StartInstaller(L"reactos.exe");
|
|
break;
|
|
|
|
case REBOOT:
|
|
{
|
|
EnablePrivilege(SE_SHUTDOWN_NAME, TRUE);
|
|
ExitWindowsEx(EWX_REBOOT, 0);
|
|
EnablePrivilege(SE_SHUTDOWN_NAME, FALSE);
|
|
Success = TRUE;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
Success = FALSE;
|
|
break;
|
|
}
|
|
|
|
/*
|
|
* In LiveCD mode, go back to the main menu if we failed
|
|
* to either start the shell or the installer.
|
|
*/
|
|
if (bIsLiveCD && !Success)
|
|
goto Restart;
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* EOF */
|