[SERVICES] Set default status to SERVICE_START_PENDING when starting a service.
[reactos.git] / reactos / dll / win32 / syssetup / install.c
index 29943c3..b3bd427 100644 (file)
  *  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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  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 system libraries
  * PURPOSE:           System setup
- * FILE:              lib/syssetup/install.c
+ * FILE:              dll/win32/syssetup/install.c
  * PROGRAMER:         Eric Kohl
  */
 
@@ -49,6 +49,9 @@
 #include "globals.h"
 #include "resource.h"
 
+#define NDEBUG
+#include <debug.h>
+
 DWORD WINAPI
 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout);
 
@@ -61,628 +64,1041 @@ HINF hSysSetupInf = INVALID_HANDLE_VALUE;
 
 /* FUNCTIONS ****************************************************************/
 
-void
+static VOID
 DebugPrint(char* fmt,...)
 {
-  char buffer[512];
-  va_list ap;
-
-  va_start(ap, fmt);
-  vsprintf(buffer, fmt, ap);
-  va_end(ap);
-
-  strcat(buffer, "\nRebooting now!");
-  MessageBoxA(NULL,
-             buffer,
-             "ReactOS Setup",
-             MB_OK);
+    char buffer[512];
+    va_list ap;
+
+    va_start(ap, fmt);
+    vsprintf(buffer, fmt, ap);
+    va_end(ap);
+
+    LogItem(SYSSETUP_SEVERITY_FATAL_ERROR, L"Failed");
+
+    strcat(buffer, "\nRebooting now!");
+    MessageBoxA(NULL,
+                buffer,
+                "ReactOS Setup",
+                MB_OK);
 }
 
 
 HRESULT CreateShellLink(LPCTSTR linkPath, LPCTSTR cmd, LPCTSTR arg, LPCTSTR dir, LPCTSTR iconPath, int icon_nr, LPCTSTR comment)
 {
-  IShellLink* psl;
-  IPersistFile* ppf;
+    IShellLink* psl;
+    IPersistFile* ppf;
 #ifndef _UNICODE
-  WCHAR buffer[MAX_PATH];
+    WCHAR buffer[MAX_PATH];
 #endif /* _UNICODE */
 
-  HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
+    HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
 
-  if (SUCCEEDED(hr))
+    if (SUCCEEDED(hr))
     {
-      hr = psl->lpVtbl->SetPath(psl, cmd);
+        hr = psl->lpVtbl->SetPath(psl, cmd);
 
-      if (arg)
+        if (arg)
         {
-          hr = psl->lpVtbl->SetArguments(psl, arg);
+            hr = psl->lpVtbl->SetArguments(psl, arg);
         }
 
-      if (dir)
+        if (dir)
         {
-          hr = psl->lpVtbl->SetWorkingDirectory(psl, dir);
+            hr = psl->lpVtbl->SetWorkingDirectory(psl, dir);
         }
 
-      if (iconPath)
+        if (iconPath)
         {
-          hr = psl->lpVtbl->SetIconLocation(psl, iconPath, icon_nr);
+            hr = psl->lpVtbl->SetIconLocation(psl, iconPath, icon_nr);
         }
 
-      if (comment)
+        if (comment)
         {
-          hr = psl->lpVtbl->SetDescription(psl, comment);
+            hr = psl->lpVtbl->SetDescription(psl, comment);
         }
 
-      hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
+        hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
 
-      if (SUCCEEDED(hr))
+        if (SUCCEEDED(hr))
         {
 #ifdef _UNICODE
-          hr = ppf->lpVtbl->Save(ppf, linkPath, TRUE);
+            hr = ppf->lpVtbl->Save(ppf, linkPath, TRUE);
 #else /* _UNICODE */
-          MultiByteToWideChar(CP_ACP, 0, linkPath, -1, buffer, MAX_PATH);
+            MultiByteToWideChar(CP_ACP, 0, linkPath, -1, buffer, MAX_PATH);
 
-          hr = ppf->lpVtbl->Save(ppf, buffer, TRUE);
+            hr = ppf->lpVtbl->Save(ppf, buffer, TRUE);
 #endif /* _UNICODE */
 
-          ppf->lpVtbl->Release(ppf);
+            ppf->lpVtbl->Release(ppf);
         }
 
-      psl->lpVtbl->Release(psl);
+        psl->lpVtbl->Release(psl);
     }
 
-  return hr;
+    return hr;
 }
 
 
 static BOOL
-CreateShortcut(int csidl, LPCTSTR folder, LPCTSTR linkName, LPCTSTR command, UINT nIdTitle)
+CreateShortcut(int csidl, LPCTSTR folder, UINT nIdName, LPCTSTR command, UINT nIdTitle, BOOL bCheckExistence)
 {
-  TCHAR path[MAX_PATH];
-  TCHAR title[256];
-  LPTSTR p = path;
+    TCHAR path[MAX_PATH];
+    TCHAR exeName[MAX_PATH];
+    TCHAR title[256];
+    TCHAR name[256];
+    LPTSTR p = path;
+    TCHAR szWorkingDir[MAX_PATH];
+    LPTSTR lpWorkingDir = NULL;
+    LPTSTR lpFilePart;
+    DWORD dwLen;
+
+    if (ExpandEnvironmentStrings(command,
+                                 path,
+                                 sizeof(path) / sizeof(path[0])) == 0)
+    {
+        _tcscpy(path,
+                command);
+    }
 
-  if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
-    return FALSE;
+    if (bCheckExistence)
+    {
+        if ((_taccess(path, 0 )) == -1)
+            /* Expected error, don't return FALSE */
+            return TRUE;
+    }
 
-  if (folder)
+    dwLen = GetFullPathName(path,
+                            sizeof(szWorkingDir) / sizeof(szWorkingDir[0]),
+                            szWorkingDir,
+                            &lpFilePart);
+    if (dwLen != 0 && dwLen <= sizeof(szWorkingDir) / sizeof(szWorkingDir[0]))
     {
-      p = PathAddBackslash(p);
-      _tcscpy(p, folder);
+        /* Save the file name */
+        _tcscpy(exeName, lpFilePart);
+
+        if (lpFilePart != NULL)
+        {
+            /* We're only interested in the path. Cut the file name off.
+               Also remove the trailing backslash unless the working directory
+               is only going to be a drive, ie. C:\ */
+            *(lpFilePart--) = _T('\0');
+            if (!(lpFilePart - szWorkingDir == 2 && szWorkingDir[1] == _T(':') &&
+                  szWorkingDir[2] == _T('\\')))
+            {
+                *lpFilePart = _T('\0');
+            }
+        }
+
+        lpWorkingDir = szWorkingDir;
     }
 
-  p = PathAddBackslash(p);
-  _tcscpy(p, linkName);
 
-  if (!LoadString(hDllInstance, nIdTitle, title, 256))
-    return FALSE;
+    if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
+        return FALSE;
+
+    if (folder)
+    {
+        p = PathAddBackslash(p);
+        _tcscpy(p, folder);
+    }
 
-  return SUCCEEDED(CreateShellLink(path, command, _T(""), NULL, NULL, 0, title));
+    p = PathAddBackslash(p);
+
+    if (!LoadString(hDllInstance, nIdName, name, sizeof(name)/sizeof(name[0])))
+        return FALSE;
+    _tcscpy(p, name);
+
+    if (!LoadString(hDllInstance, nIdTitle, title, sizeof(title)/sizeof(title[0])))
+        return FALSE;
+
+    // FIXME: we should pass 'command' straight in here, but shell32 doesn't expand it
+    return SUCCEEDED(CreateShellLink(path, exeName, _T(""), lpWorkingDir, NULL, 0, title));
 }
 
 
 static BOOL
 CreateShortcutFolder(int csidl, UINT nID, LPTSTR name, int nameLen)
 {
-  TCHAR path[MAX_PATH];
-  LPTSTR p;
+    TCHAR path[MAX_PATH];
+    LPTSTR p;
 
-  if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
-    return FALSE;
+    if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
+        return FALSE;
 
-  if (!LoadString(hDllInstance, nID, name, nameLen))
-    return FALSE;
+    if (!LoadString(hDllInstance, nID, name, nameLen))
+        return FALSE;
 
-  p = PathAddBackslash(path);
-  _tcscpy(p, name);
+    p = PathAddBackslash(path);
+    _tcscpy(p, name);
 
-  return CreateDirectory(path, NULL) || GetLastError()==ERROR_ALREADY_EXISTS;
+    return CreateDirectory(path, NULL) || GetLastError()==ERROR_ALREADY_EXISTS;
 }
 
 
-static VOID
-CreateRandomSid (PSID *Sid)
+static BOOL
+CreateRandomSid(
+    OUT PSID *Sid)
 {
-  SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
-  LARGE_INTEGER SystemTime;
-  PULONG Seed;
-
-  NtQuerySystemTime (&SystemTime);
-  Seed = &SystemTime.u.LowPart;
-
-  RtlAllocateAndInitializeSid (&SystemAuthority,
-                              4,
-                              SECURITY_NT_NON_UNIQUE,
-                              RtlUniform (Seed),
-                              RtlUniform (Seed),
-                              RtlUniform (Seed),
-                              SECURITY_NULL_RID,
-                              SECURITY_NULL_RID,
-                              SECURITY_NULL_RID,
-                              SECURITY_NULL_RID,
-                              Sid);
+    SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
+    LARGE_INTEGER SystemTime;
+    PULONG Seed;
+    NTSTATUS Status;
+
+    NtQuerySystemTime(&SystemTime);
+    Seed = &SystemTime.u.LowPart;
+
+    Status = RtlAllocateAndInitializeSid(
+        &SystemAuthority,
+        4,
+        SECURITY_NT_NON_UNIQUE,
+        RtlUniform(Seed),
+        RtlUniform(Seed),
+        RtlUniform(Seed),
+        SECURITY_NULL_RID,
+        SECURITY_NULL_RID,
+        SECURITY_NULL_RID,
+        SECURITY_NULL_RID,
+        Sid);
+    return NT_SUCCESS(Status);
 }
 
 
 static VOID
-AppendRidToSid (PSID *Dst,
-               PSID Src,
-               ULONG NewRid)
+AppendRidToSid(
+    OUT PSID *Dst,
+    IN PSID Src,
+    IN ULONG NewRid)
 {
-  ULONG Rid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-  UCHAR RidCount;
-  ULONG i;
+    ULONG Rid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+    UCHAR RidCount;
+    ULONG i;
 
-  RidCount = *RtlSubAuthorityCountSid (Src);
+    RidCount = *RtlSubAuthorityCountSid (Src);
 
-  for (i = 0; i < RidCount; i++)
-    Rid[i] = *RtlSubAuthoritySid (Src, i);
+    for (i = 0; i < RidCount; i++)
+        Rid[i] = *RtlSubAuthoritySid (Src, i);
 
-  if (RidCount < 8)
+    if (RidCount < 8)
     {
-      Rid[RidCount] = NewRid;
-      RidCount++;
+        Rid[RidCount] = NewRid;
+        RidCount++;
     }
 
-  RtlAllocateAndInitializeSid (RtlIdentifierAuthoritySid (Src),
-                              RidCount,
-                              Rid[0],
-                              Rid[1],
-                              Rid[2],
-                              Rid[3],
-                              Rid[4],
-                              Rid[5],
-                              Rid[6],
-                              Rid[7],
-                              Dst);
+    RtlAllocateAndInitializeSid(
+        RtlIdentifierAuthoritySid(Src),
+        RidCount,
+        Rid[0],
+        Rid[1],
+        Rid[2],
+        Rid[3],
+        Rid[4],
+        Rid[5],
+        Rid[6],
+        Rid[7],
+        Dst);
 }
 
 
 static VOID
-CreateTempDir(LPCWSTR VarName)
+CreateTempDir(
+    IN LPCWSTR VarName)
 {
-  TCHAR szTempDir[MAX_PATH];
-  TCHAR szBuffer[MAX_PATH];
-  DWORD dwLength;
-  HKEY hKey;
-
-  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                  _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
-                  0,
-                  KEY_ALL_ACCESS,
-                  &hKey))
+    WCHAR szTempDir[MAX_PATH];
+    WCHAR szBuffer[MAX_PATH];
+    DWORD dwLength;
+    HKEY hKey;
+
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                     L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
+                     0,
+                     KEY_QUERY_VALUE,
+                     &hKey))
     {
-      DebugPrint("Error: %lu\n", GetLastError());
-      return;
+        DebugPrint("Error: %lu\n", GetLastError());
+        return;
     }
 
-  /* Get temp dir */
-  dwLength = MAX_PATH * sizeof(TCHAR);
-  if (RegQueryValueEx(hKey,
-                     VarName,
-                     NULL,
-                     NULL,
-                     (LPBYTE)szBuffer,
-                     &dwLength))
+    /* Get temp dir */
+    dwLength = MAX_PATH * sizeof(WCHAR);
+    if (RegQueryValueExW(hKey,
+                        VarName,
+                        NULL,
+                        NULL,
+                        (LPBYTE)szBuffer,
+                        &dwLength))
     {
-      DebugPrint("Error: %lu\n", GetLastError());
-      RegCloseKey(hKey);
-      return;
+        DebugPrint("Error: %lu\n", GetLastError());
+        RegCloseKey(hKey);
+        return;
     }
 
-  /* Expand it */
-  if (!ExpandEnvironmentStrings(szBuffer,
-                               szTempDir,
-                               MAX_PATH))
+    /* Expand it */
+    if (!ExpandEnvironmentStringsW(szBuffer,
+                                  szTempDir,
+                                  MAX_PATH))
     {
-      DebugPrint("Error: %lu\n", GetLastError());
-      RegCloseKey(hKey);
-      return;
+        DebugPrint("Error: %lu\n", GetLastError());
+        RegCloseKey(hKey);
+        return;
     }
 
-  /* Create profiles directory */
-  if (!CreateDirectory(szTempDir, NULL))
+    /* Create profiles directory */
+    if (!CreateDirectoryW(szTempDir, NULL))
     {
-      if (GetLastError() != ERROR_ALREADY_EXISTS)
-       {
-         DebugPrint("Error: %lu\n", GetLastError());
-         RegCloseKey(hKey);
-         return;
-       }
+        if (GetLastError() != ERROR_ALREADY_EXISTS)
+        {
+            DebugPrint("Error: %lu\n", GetLastError());
+            RegCloseKey(hKey);
+            return;
+        }
     }
 
-  RegCloseKey(hKey);
+    RegCloseKey(hKey);
 }
 
 
 BOOL
-ProcessSysSetupInf(VOID)
+InstallSysSetupInfDevices(VOID)
 {
-  INFCONTEXT InfContext;
-  TCHAR LineBuffer[256];
-  DWORD LineLength;
-
-  if (!SetupFindFirstLine(hSysSetupInf,
-                         _T("DeviceInfsToInstall"),
-                         NULL,
-                         &InfContext))
-  {
-    return FALSE;
-  }
-
-  do
-  {
-    if (!SetupGetStringField(&InfContext,
-                            0,
-                            LineBuffer,
-                            256,
-                            &LineLength))
+    INFCONTEXT InfContext;
+    WCHAR LineBuffer[256];
+    DWORD LineLength;
+
+    if (!SetupFindFirstLineW(hSysSetupInf,
+                            L"DeviceInfsToInstall",
+                            NULL,
+                            &InfContext))
     {
-      return FALSE;
+        return FALSE;
     }
 
-    if (!SetupDiInstallClass(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
+    do
     {
-      return FALSE;
+        if (!SetupGetStringFieldW(&InfContext,
+                                 0,
+                                 LineBuffer,
+                                 sizeof(LineBuffer)/sizeof(LineBuffer[0]),
+                                 &LineLength))
+        {
+            return FALSE;
+        }
+
+        if (!SetupDiInstallClassW(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
+        {
+            return FALSE;
+        }
     }
-  }
-  while (SetupFindNextLine(&InfContext, &InfContext));
+    while (SetupFindNextLine(&InfContext, &InfContext));
 
-  return TRUE;
+    return TRUE;
 }
+BOOL
+InstallSysSetupInfComponents(VOID)
+{
+    INFCONTEXT InfContext;
+    WCHAR NameBuffer[256];
+    WCHAR SectionBuffer[256];
+    HINF hComponentInf = INVALID_HANDLE_VALUE;
+
+    if (!SetupFindFirstLineW(hSysSetupInf,
+                            L"Infs.Always",
+                            NULL,
+                            &InfContext))
+    {
+        DPRINT("No Inf.Always section found\n");
+    }
+    else
+    {
+        do
+        {
+            if (!SetupGetStringFieldW(&InfContext,
+                                     1, // Get the component name
+                                     NameBuffer,
+                                     sizeof(NameBuffer)/sizeof(NameBuffer[0]),
+                                     NULL))
+            {
+                DebugPrint("Error while trying to get component name \n");
+                return FALSE;
+            }
+
+            if (!SetupGetStringFieldW(&InfContext,
+                                     2, // Get the component install section
+                                     SectionBuffer,
+                                     sizeof(SectionBuffer)/sizeof(SectionBuffer[0]),
+                                     NULL))
+            {
+                DebugPrint("Error while trying to get component install section \n");
+                return FALSE;
+            }
+
+            DPRINT("Trying to execute install section '%S' from '%S' \n", SectionBuffer , NameBuffer);
+
+            hComponentInf = SetupOpenInfFileW(NameBuffer,
+                                              NULL,
+                                              INF_STYLE_WIN4,
+                                              NULL);
+
+            if (hComponentInf == INVALID_HANDLE_VALUE)
+            {
+                DebugPrint("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", NameBuffer ,GetLastError());
+                return FALSE;
+            }
+
+            if (!SetupInstallFromInfSectionW(NULL,
+                                            hComponentInf,
+                                            SectionBuffer,
+                                            SPINST_ALL,
+                                            NULL,
+                                            NULL,
+                                            SP_COPY_NEWER,
+                                            SetupDefaultQueueCallbackW,
+                                            NULL,
+                                            NULL,
+                                            NULL))
+           {
+                DebugPrint("Error while trying to install : %S (Error: %lu)\n", NameBuffer, GetLastError());
+                SetupCloseInfFile(hComponentInf);
+                return FALSE;
+           }
+
+           SetupCloseInfFile(hComponentInf);
+        }
+        while (SetupFindNextLine(&InfContext, &InfContext));
+    }
 
+    return TRUE;
+}
 
 static BOOL
 EnableUserModePnpManager(VOID)
 {
-  SC_HANDLE hSCManager = NULL;
-  SC_HANDLE hService = NULL;
-  BOOL ret = FALSE;
+    SERVICE_STATUS_PROCESS ServiceStatus;
+    SC_HANDLE hSCManager = NULL;
+    SC_HANDLE hService = NULL;
+    DWORD dwStartTickCount;
+    DWORD dwOldCheckPoint;
+    DWORD BytesNeeded = 0;
+    DWORD dwWaitTime;
+    DWORD dwMaxWait;
+    BOOL ret = FALSE;
+
+    hSCManager = OpenSCManager(NULL, NULL, 0);
+    if (hSCManager == NULL)
+        goto cleanup;
+
+    hService = OpenServiceW(hSCManager,
+                            L"PlugPlay",
+                            SERVICE_CHANGE_CONFIG | SERVICE_START | SERVICE_QUERY_STATUS);
+    if (hService == NULL)
+        goto cleanup;
+
+    ret = ChangeServiceConfigW(hService,
+                               SERVICE_NO_CHANGE,
+                               SERVICE_AUTO_START,
+                               SERVICE_NO_CHANGE,
+                               NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL);
+    if (!ret)
+        goto cleanup;
+
+    ret = StartServiceW(hService, 0, NULL);
+    if (!ret)
+    {
+        /* If the service is already running, just return TRUE */
+        ret = GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
+        goto cleanup;
+    }
 
-  hSCManager = OpenSCManager(NULL, NULL, 0);
-  if (hSCManager == NULL)
-    goto cleanup;
+    ret = QueryServiceStatusEx(hService,
+                               SC_STATUS_PROCESS_INFO,
+                               (LPBYTE)&ServiceStatus,
+                               sizeof(SERVICE_STATUS_PROCESS),
+                               &BytesNeeded);
+    if (!ret)
+        goto cleanup;
 
-  hService = OpenService(hSCManager, _T("PlugPlay"), SERVICE_CHANGE_CONFIG | SERVICE_START);
-  if (hService == NULL)
-    goto cleanup;
+    /* We don't want to wait for more than 30 seconds */
+    dwMaxWait = 30000;
+    dwStartTickCount = GetTickCount();
 
-  ret = ChangeServiceConfig(
-    hService,
-    SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
-    NULL, NULL, NULL, NULL, NULL, NULL, NULL);
-  if (!ret)
-    goto cleanup;
+    /* Loop until it's running */
+    while (ServiceStatus.dwCurrentState != SERVICE_RUNNING)
+    {
+        dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+        dwWaitTime = ServiceStatus.dwWaitHint / 10;
+
+        /* Get the latest status info */
+        if (!QueryServiceStatusEx(hService,
+                                  SC_STATUS_PROCESS_INFO,
+                                  (LPBYTE)&ServiceStatus,
+                                  sizeof(SERVICE_STATUS_PROCESS),
+                                  &BytesNeeded))
+        {
+            /* Something went wrong... */
+            break;
+        }
 
-  ret = StartService(hService, 0, NULL);
-  if (!ret)
-    goto cleanup;
+        /* Is the service making progress? */
+        if (ServiceStatus.dwCheckPoint > dwOldCheckPoint)
+        {
+            /* It is, get the latest tickcount to reset the max wait time */
+            dwStartTickCount = GetTickCount();
+            dwOldCheckPoint = ServiceStatus.dwCheckPoint;
+        }
+        else
+        {
+            /* It's not, make sure we haven't exceeded our wait time */
+            if (GetTickCount() >= dwStartTickCount + dwMaxWait)
+            {
+                /* We have, give up */
+                break;
+            }
+        }
 
-  ret = TRUE;
+        /* Adjust the wait hint times */
+        if (dwWaitTime < 200)
+            dwWaitTime = 200;
+        else if (dwWaitTime > 10000)
+            dwWaitTime = 10000;
+
+        /* Wait before trying again */
+        Sleep(dwWaitTime);
+    }
+
+    ret = ServiceStatus.dwCurrentState == SERVICE_RUNNING;
 
 cleanup:
-  if (hSCManager != NULL)
-    CloseServiceHandle(hSCManager);
-  if (hService != NULL)
-    CloseServiceHandle(hService);
-  return ret;
+    if (hSCManager != NULL)
+        CloseServiceHandle(hSCManager);
+    if (hService != NULL)
+        CloseServiceHandle(hService);
+    return ret;
 }
 
 
-DWORD STDCALL
-InstallLiveCD (HINSTANCE hInstance)
+static BOOL CALLBACK
+StatusMessageWindowProc(
+    IN HWND hwndDlg,
+    IN UINT uMsg,
+    IN WPARAM wParam,
+    IN LPARAM lParam)
 {
-  LONG rc;
-  HKEY hKey = NULL;
-  DWORD dwType;
-  DWORD requiredSize;
-  LPTSTR Shell = NULL;
-  TCHAR CommandLine[MAX_PATH];
-  STARTUPINFO StartupInfo;
-  PROCESS_INFORMATION ProcessInformation;
-  BOOL res;
-
-  hSysSetupInf = SetupOpenInfFileW(
-    L"syssetup.inf",
-    NULL,
-    INF_STYLE_WIN4,
-    NULL);
-  if (hSysSetupInf == INVALID_HANDLE_VALUE)
-  {
-    DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
-    return 0;
-  }
+    UNREFERENCED_PARAMETER(wParam);
+
+    switch (uMsg)
+    {
+        case WM_INITDIALOG:
+        {
+            WCHAR szMsg[256];
+
+            if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
+                return FALSE;
+            SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+
+static DWORD WINAPI
+ShowStatusMessageThread(
+    IN LPVOID lpParameter)
+{
+    HWND *phWnd = (HWND *)lpParameter;
+    HWND hWnd;
+    MSG Msg;
+
+    hWnd = CreateDialogParam(
+        hDllInstance,
+        MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
+        GetDesktopWindow(),
+        StatusMessageWindowProc,
+        (LPARAM)NULL);
+    if (!hWnd)
+        return 0;
+    *phWnd = hWnd;
+
+    ShowWindow(hWnd, SW_SHOW);
+
+    /* Message loop for the Status window */
+    while (GetMessage(&Msg, NULL, 0, 0))
+    {
+        TranslateMessage(&Msg);
+        DispatchMessage(&Msg);
+    }
 
-  if (!ProcessSysSetupInf())
-  {
-    DebugPrint("ProcessSysSetupInf() failed!\n");
     return 0;
-  }
+}
+
+static LONG
+ReadRegSzKey(
+    IN HKEY hKey,
+    IN LPCWSTR pszKey,
+    OUT LPWSTR* pValue)
+{
+    LONG rc;
+    DWORD dwType;
+    DWORD cbData = 0;
+    LPWSTR Value;
+
+    if (!pValue)
+        return ERROR_INVALID_PARAMETER;
+
+    *pValue = NULL;
+    rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
+    if (rc != ERROR_SUCCESS)
+        return rc;
+    if (dwType != REG_SZ)
+        return ERROR_FILE_NOT_FOUND;
+    Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
+    if (!Value)
+        return ERROR_NOT_ENOUGH_MEMORY;
+    rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
+    if (rc != ERROR_SUCCESS)
+    {
+        HeapFree(GetProcessHeap(), 0, Value);
+        return rc;
+    }
+    /* NULL-terminate the string */
+    Value[cbData / sizeof(WCHAR)] = '\0';
+
+    *pValue = Value;
+    return ERROR_SUCCESS;
+}
 
-  SetupCloseInfFile(hSysSetupInf);
+static BOOL
+IsConsoleBoot(VOID)
+{
+    HKEY ControlKey = NULL;
+    LPWSTR SystemStartOptions = NULL;
+    LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
+    BOOL ConsoleBoot = FALSE;
+    LONG rc;
+
+    rc = RegOpenKeyExW(
+        HKEY_LOCAL_MACHINE,
+        L"SYSTEM\\CurrentControlSet\\Control",
+        0,
+        KEY_QUERY_VALUE,
+        &ControlKey);
+
+    rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
+    if (rc != ERROR_SUCCESS)
+        goto cleanup;
+
+    /* Check for CMDCONS in SystemStartOptions */
+    CurrentOption = SystemStartOptions;
+    while (CurrentOption)
+    {
+        NextOption = wcschr(CurrentOption, L' ');
+        if (NextOption)
+            *NextOption = L'\0';
+        if (wcsicmp(CurrentOption, L"CONSOLE") == 0)
+        {
+            DPRINT("Found %S. Switching to console boot\n", CurrentOption);
+            ConsoleBoot = TRUE;
+            goto cleanup;
+        }
+        CurrentOption = NextOption ? NextOption + 1 : NULL;
+    }
+
+cleanup:
+    if (ControlKey != NULL)
+        RegCloseKey(ControlKey);
+    HeapFree(GetProcessHeap(), 0, SystemStartOptions);
+    return ConsoleBoot;
+}
+
+static BOOL
+CommonInstall(VOID)
+{
+    HWND hWnd = NULL;
+
+    hSysSetupInf = SetupOpenInfFileW(
+        L"syssetup.inf",
+        NULL,
+        INF_STYLE_WIN4,
+        NULL);
+    if (hSysSetupInf == INVALID_HANDLE_VALUE)
+    {
+        DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
+        return FALSE;
+    }
+
+    if (!InstallSysSetupInfDevices())
+    {
+        DebugPrint("InstallSysSetupInfDevices() failed!\n");
+        SetupCloseInfFile(hSysSetupInf);
+        return FALSE;
+    }
+
+    if(!InstallSysSetupInfComponents())
+    {
+        DebugPrint("InstallSysSetupInfComponents() failed!\n");
+        SetupCloseInfFile(hSysSetupInf);
+        return FALSE;
+    }
+
+    if (!IsConsoleBoot())
+    {
+        CreateThread(
+            NULL,
+            0,
+            ShowStatusMessageThread,
+            (LPVOID)&hWnd,
+            0,
+            NULL);
+    }
+
+    if (!EnableUserModePnpManager())
+    {
+       DebugPrint("EnableUserModePnpManager() failed!\n");
+       SetupCloseInfFile(hSysSetupInf);
+       EndDialog(hWnd, 0);
+       return FALSE;
+    }
+
+    if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
+    {
+      DebugPrint("CMP_WaitNoPendingInstallEvents() failed!\n");
+      SetupCloseInfFile(hSysSetupInf);
+      EndDialog(hWnd, 0);
+      return FALSE;
+    }
+
+    EndDialog(hWnd, 0);
+    return TRUE;
+}
+
+DWORD WINAPI
+InstallLiveCD(IN HINSTANCE hInstance)
+{
+    STARTUPINFOW StartupInfo;
+    PROCESS_INFORMATION ProcessInformation;
+    BOOL res;
+
+    if (!CommonInstall())
+        goto cleanup;
+    SetupCloseInfFile(hSysSetupInf);
+
+    /* Run the shell */
+    StartupInfo.cb = sizeof(STARTUPINFOW);
+    StartupInfo.lpReserved = NULL;
+    StartupInfo.lpDesktop = NULL;
+    StartupInfo.lpTitle = NULL;
+    StartupInfo.dwFlags = 0;
+    StartupInfo.cbReserved2 = 0;
+    StartupInfo.lpReserved2 = 0;
+    res = CreateProcessW(
+        L"userinit.exe",
+        NULL,
+        NULL,
+        NULL,
+        FALSE,
+        0,
+        NULL,
+        NULL,
+        &StartupInfo,
+        &ProcessInformation);
+    if (!res)
+        goto cleanup;
 
-  if (!EnableUserModePnpManager())
-  {
-    DebugPrint("EnableUserModePnpManager() failed!\n");
     return 0;
-  }
-
-  /* Load the default shell */
-  rc = RegOpenKeyEx(
-    HKEY_LOCAL_MACHINE,
-    TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon"), /* FIXME: should be REGSTR_PATH_WINLOGON */
-    0,
-    KEY_QUERY_VALUE,
-    &hKey);
-  if (rc != ERROR_SUCCESS)
-    goto cleanup;
-  rc = RegQueryValueEx(
-    hKey,
-    TEXT("Shell"),
-    NULL,
-    &dwType,
-    NULL,
-    &requiredSize);
-  if (rc != ERROR_SUCCESS)
-    goto cleanup;
-  else if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
-    goto cleanup;
-  else if (requiredSize > (MAX_PATH - 1) * sizeof(TCHAR))
-    goto cleanup;
-  Shell = HeapAlloc(GetProcessHeap(), 0, requiredSize + sizeof(TCHAR));
-  if (!Shell)
-    goto cleanup;
-  Shell[requiredSize / sizeof(WCHAR)] = '\0';
-  rc = RegQueryValueEx(
-    hKey,
-    TEXT("Shell"),
-    NULL,
-    NULL,
-    (LPBYTE)Shell,
-    &requiredSize);
-  if (rc != ERROR_SUCCESS)
-    goto cleanup;
-  if (dwType == REG_EXPAND_SZ)
-    ExpandEnvironmentStrings(Shell, CommandLine, MAX_PATH);
-  else if (dwType == REG_SZ)
-    _tcscpy(CommandLine, Shell);
-
-  /* Run the shell */
-  StartupInfo.cb = sizeof(StartupInfo);
-  StartupInfo.lpReserved = NULL;
-  StartupInfo.lpDesktop = NULL;
-  StartupInfo.lpTitle = NULL;
-  StartupInfo.dwFlags = 0;
-  StartupInfo.cbReserved2 = 0;
-  StartupInfo.lpReserved2 = 0;
-  res = CreateProcess(
-    CommandLine,
-    NULL,
-    NULL,
-    NULL,
-    FALSE,
-    0,
-    NULL,
-    NULL,
-    &StartupInfo,
-    &ProcessInformation);
-  if (!res)
-    goto cleanup;
-
-  /* Wait for process termination */
-  WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
 
 cleanup:
-  if (hKey != NULL)
-    RegCloseKey(hKey);
-  HeapFree(GetProcessHeap(), 0, Shell);
-  MessageBoxA(
-    NULL,
-    "You can shutdown your computer, or press ENTER to reboot",
-    "ReactOS LiveCD",
-    MB_OK);
-  return 0;
+    MessageBoxW(
+        NULL,
+        L"You can shutdown your computer, or press ENTER to reboot",
+        L"ReactOS LiveCD",
+        MB_OK);
+    return 0;
 }
 
 
-DWORD STDCALL
-InstallReactOS (HINSTANCE hInstance)
+static BOOL
+CreateShortcuts(VOID)
 {
-  TCHAR sAccessories[256];
-  TCHAR sGames[256];
-  TCHAR szBuffer[MAX_PATH];  
+    TCHAR szFolder[256];
+
+    CoInitialize(NULL);
 
-# if 0
-  OutputDebugStringA ("InstallReactOS() called\n");
+    /* Create desktop shortcuts */
+    CreateShortcut(CSIDL_DESKTOP, NULL, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, TRUE);
 
-  if (!InitializeSetupActionLog (FALSE))
+    /* Create program startmenu shortcuts */
+    CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_EXPLORER, _T("%SystemRoot%\\explorer.exe"), IDS_CMT_EXPLORER, TRUE);
+    CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_DOWNLOADER, _T("%SystemRoot%\\system32\\rapps.exe"), IDS_CMT_DOWNLOADER, TRUE);
+
+    /* Create administrative tools startmenu shortcuts */
+    CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_SERVICE, _T("%SystemRoot%\\system32\\servman.exe"), IDS_CMT_SERVMAN, TRUE);
+    CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_DEVICE, _T("%SystemRoot%\\system32\\devmgmt.exe"), IDS_CMT_DEVMGMT, TRUE);
+    CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_EVENTVIEW, _T("%SystemRoot%\\system32\\eventvwr.exe"), IDS_CMT_EVENTVIEW, TRUE);
+    CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_MSCONFIG, _T("%SystemRoot%\\system32\\msconfig.exe"), IDS_CMT_MSCONFIG, TRUE);
+
+    /* Create and fill Accessories subfolder */
+    if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
     {
-      OutputDebugStringA ("InitializeSetupActionLog() failed\n");
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CALC, _T("%SystemRoot%\\system32\\calc.exe"), IDS_CMT_CALC, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_NOTEPAD, _T("%SystemRoot%\\system32\\notepad.exe"), IDS_CMT_NOTEPAD, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_RDESKTOP, _T("%SystemRoot%\\system32\\mstsc.exe"), IDS_CMT_RDESKTOP, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNAP, _T("%SystemRoot%\\system32\\screenshot.exe"), IDS_CMT_SCREENSHOT, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WORDPAD, _T("%SystemRoot%\\system32\\wordpad.exe"), IDS_CMT_WORDPAD, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_PAINT, _T("%SystemRoot%\\system32\\paint.exe"), IDS_CMT_PAINT, TRUE);
     }
 
-  LogItem (SYSSETUP_SEVERITY_INFORMATION,
-          L"ReactOS Setup starting");
-
-  LogItem (SYSSETUP_SEVERITY_FATAL_ERROR,
-          L"Buuuuuuaaaah!");
+    /* Create System Tools subfolder and fill if the exe is available */
+    if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_TOOLS, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
+    {
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CHARMAP, _T("%SystemRoot%\\system32\\charmap.exe"), IDS_CMT_CHARMAP, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_KBSWITCH, _T("%SystemRoot%\\system32\\kbswitch.exe"), IDS_CMT_KBSWITCH, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_REGEDIT, _T("%SystemRoot%\\regedit.exe"), IDS_CMT_REGEDIT, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_DXDIAG, _T("%SystemRoot%\\system32\\dxdiag.exe"), IDS_CMT_DXDIAG, TRUE);
+    }
 
-  LogItem (SYSSETUP_SEVERITY_INFORMATION,
-          L"ReactOS Setup finished");
+    /* Create Accessibility subfolder and fill if the exe is available */
+    if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_ACCESSIBILITY, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
+    {
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MAGNIFY, _T("%SystemRoot%\\system32\\magnify.exe"), IDS_CMT_MAGNIFY, TRUE);
+    }
 
-  TerminateSetupActionLog ();
-#endif
-#if 0
-  UNICODE_STRING SidString;
-#endif
-  ULONG LastError;
+    /* Create Entertainment subfolder and fill if the exe is available */
+    if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_ENTERTAINMENT, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
+    {
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MPLAY32, _T("%SystemRoot%\\system32\\mplay32.exe"), IDS_CMT_MPLAY32, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDVOL32, _T("%SystemRoot%\\system32\\sndvol32.exe"), IDS_CMT_SNDVOL32, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDREC32, _T("%SystemRoot%\\system32\\sndrec32.exe"), IDS_CMT_SNDREC32, TRUE);
+    }
 
-  if (!InitializeProfiles ())
+    /* Create Games subfolder and fill if the exe is available */
+    if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
     {
-      DebugPrint ("InitializeProfiles() failed\n");
-      return 0;
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SOLITAIRE, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WINEMINE, _T("%SystemRoot%\\system32\\winemine.exe"), IDS_CMT_WINEMINE, TRUE);
+        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SPIDER, _T("%SystemRoot%\\system32\\spider.exe"), IDS_CMT_SPIDER, TRUE);
     }
 
-  CoInitialize(NULL);
+    CoUninitialize();
 
-  /* create desktop shortcuts */
-  CreateShortcut(CSIDL_DESKTOP, NULL, _T("Command Prompt.lnk"), _T("cmd.exe"), IDS_CMT_CMD);
+    return TRUE;
+}
 
-  /* create program startmenu shortcuts */  
-  CreateShortcut(CSIDL_PROGRAMS, NULL, _T("winefile.lnk"), _T("winefile.exe"), IDS_CMT_WINEFILE);
-  CreateShortcut(CSIDL_PROGRAMS, NULL, _T("ibrowser.lnk"), _T("ibrowser.exe"), IDS_CMT_IBROWSER);
-  CreateShortcut(CSIDL_PROGRAMS, NULL, _T("Get Firefox.lnk"), _T("getfirefox.exe"), IDS_CMT_GETFIREFOX);
-  CreateShortcut(CSIDL_PROGRAMS, NULL, _T("Download !.lnk"), _T("downloader.exe"), IDS_CMT_DOWNLOADER);
+static BOOL
+SetSetupType(DWORD dwSetupType)
+{
+    DWORD dwError;
+    HKEY hKey;
+
+    dwError = RegOpenKeyExW(
+        HKEY_LOCAL_MACHINE,
+        L"SYSTEM\\Setup",
+        0,
+        KEY_SET_VALUE,
+        &hKey);
+    if (dwError != ERROR_SUCCESS)
+        return FALSE;
+
+    dwError = RegSetValueExW(
+        hKey,
+        L"SetupType",
+        0,
+        REG_DWORD,
+        (LPBYTE)&dwSetupType,
+        sizeof(DWORD));
+    RegCloseKey(hKey);
+    if (dwError != ERROR_SUCCESS)
+        return FALSE;
 
-  /* create administritive tools startmenu shortcuts */
-  CreateShortcut(CSIDL_ADMINTOOLS, NULL, _T("Services.lnk"), _T("servman.exe"), IDS_CMT_SERVMAN);
+    return TRUE;
+}
 
-  /* create and fill Accessories subfolder */
-  if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, sAccessories, 256)) 
-  {
-       CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Calculator.lnk"), _T("calc.exe"), IDS_CMT_CALC);
-       CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Command Prompt.lnk"), _T("cmd.exe"), IDS_CMT_CMD);
-    CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Notepad.lnk"), _T("notepad.exe"), IDS_CMT_NOTEPAD);
-    CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("ReactOS Explorer.lnk"), _T("explorer.exe"), IDS_CMT_EXPLORER);
-    CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Regedit.lnk"), _T("regedit.exe"), IDS_CMT_REGEDIT);
-    CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("WordPad.lnk"), _T("wordpad.exe"), IDS_CMT_WORDPAD);
-    CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("SnapShot.lnk"), _T("screenshot.exe"), IDS_CMT_SCREENSHOT);
-  }
+DWORD WINAPI
+InstallReactOS(HINSTANCE hInstance)
+{
+    TCHAR szBuffer[MAX_PATH];
+    DWORD LastError;
+    HANDLE token;
+    TOKEN_PRIVILEGES privs;
 
+    InitializeSetupActionLog(FALSE);
+    LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
 
-  /* create Games subfolder and fill if the exe is available */
-  if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, sGames, 256)) 
-  {
-    CreateShortcut(CSIDL_PROGRAMS, sGames, _T("Solitaire.lnk"), _T("sol.exe"), IDS_CMT_SOLITAIRE);
-    CreateShortcut(CSIDL_PROGRAMS, sGames, _T("WineMine.lnk"), _T("winemine.exe"), IDS_CMT_WINEMINE);
-  }
+    if (!InitializeProfiles())
+    {
+        DebugPrint("InitializeProfiles() failed");
+        return 0;
+    }
 
-  CoUninitialize();
+    if (!CreateShortcuts())
+    {
+        DebugPrint("InitializeProfiles() failed");
+        return 0;
+    }
 
-  /* Create the semi-random Domain-SID */
-  CreateRandomSid (&DomainSid);
-  if (DomainSid == NULL)
+    /* Initialize the Security Account Manager (SAM) */
+    if (!SamInitializeSAM())
     {
-      DebugPrint ("Domain-SID creation failed!\n");
-      return 0;
+        DebugPrint("SamInitializeSAM() failed!");
+        return 0;
     }
 
-#if 0
-  RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
-  DebugPrint ("Domain-SID: %wZ\n", &SidString);
-  RtlFreeUnicodeString (&SidString);
-#endif
+    /* Create the semi-random Domain-SID */
+    if (!CreateRandomSid(&DomainSid))
+    {
+        DebugPrint("Domain-SID creation failed!");
+        return 0;
+    }
 
-  /* Initialize the Security Account Manager (SAM) */
-  if (!SamInitializeSAM ())
+    /* Set the Domain SID (aka Computer SID) */
+    if (!SamSetDomainSid(DomainSid))
     {
-      DebugPrint ("SamInitializeSAM() failed!\n");
-      RtlFreeSid (DomainSid);
-      return 0;
+        DebugPrint("SamSetDomainSid() failed!");
+        RtlFreeSid(DomainSid);
+        return 0;
     }
 
-  /* Set the Domain SID (aka Computer SID) */
-  if (!SamSetDomainSid (DomainSid))
+    /* Append the Admin-RID */
+    AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
+
+    CreateTempDir(L"TEMP");
+    CreateTempDir(L"TMP");
+
+    if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
     {
-      DebugPrint ("SamSetDomainSid() failed!\n");
-      RtlFreeSid (DomainSid);
-      return 0;
+        PathAddBackslash(szBuffer);
+        _tcscat(szBuffer, _T("system"));
+        CreateDirectory(szBuffer, NULL);
     }
 
-  /* Append the Admin-RID */
-  AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
+    if (!CommonInstall())
+        return 0;
 
-#if 0
-  RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
-  DebugPrint ("Admin-SID: %wZ\n", &SidString);
-  RtlFreeUnicodeString (&SidString);
-#endif
+    InstallWizard();
 
-  /* Create the Administrator account */
-  if (!SamCreateUser(L"Administrator", L"", AdminSid))
-  {
-    /* Check what the error was.
-     * If the Admin Account already exists, then it means Setup
-     * wasn't allowed to finish properly. Instead of rebooting
-     * and not completing it, let it restart instead
-     */
-    LastError = GetLastError();
-    if (LastError != ERROR_USER_EXISTS)
+    /* Create the Administrator account */
+    if (!SamCreateUser(L"Administrator", L"", AdminSid))
     {
-      DebugPrint("SamCreateUser() failed!\n");
-      RtlFreeSid(AdminSid);
-      RtlFreeSid(DomainSid);
-      return 0;
+        /* Check what the error was.
+         * If the Admin Account already exists, then it means Setup
+         * wasn't allowed to finish properly. Instead of rebooting
+         * and not completing it, let it restart instead
+         */
+        LastError = GetLastError();
+        if (LastError != ERROR_USER_EXISTS)
+        {
+            DebugPrint("SamCreateUser() failed!");
+            RtlFreeSid(AdminSid);
+            RtlFreeSid(DomainSid);
+            return 0;
+        }
     }
-  }
 
-  /* Create the Administrator profile */
-  if (!CreateUserProfileW(AdminSid, L"Administrator"))
-  {
-    DebugPrint("CreateUserProfileW() failed!\n");
     RtlFreeSid(AdminSid);
     RtlFreeSid(DomainSid);
-    return 0;
-  }
-
-  RtlFreeSid(AdminSid);
-  RtlFreeSid(DomainSid);
-
-  CreateTempDir(L"TEMP");
-  CreateTempDir(L"TMP");
-
-  if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
-  {
-    PathAddBackslash(szBuffer);
-    _tcscat(szBuffer, _T("system"));
-    CreateDirectory(szBuffer, NULL);
-  }
-
-  hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf",
-                                  NULL,
-                                  INF_STYLE_WIN4,
-                                  NULL);
-  if (hSysSetupInf == INVALID_HANDLE_VALUE)
-  {
-    DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
-    return 0;
-  }
 
-  if (!ProcessSysSetupInf())
-  {
-    DebugPrint("ProcessSysSetupInf() failed!\n");
-    return 0;
-  }
+    /* ROS HACK, as long as NtUnloadKey is not implemented */
+    {
+        NTSTATUS Status = NtUnloadKey(NULL);
+        if (Status == STATUS_NOT_IMPLEMENTED)
+        {
+            /* Create the Administrator profile */
+            PROFILEINFOW ProfileInfo;
+            HANDLE hToken;
+            BOOL ret;
+#define LOGON32_LOGON_NETWORK 3
+            ret = LogonUserW(L"Administrator", L"", L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken);
+            if (!ret)
+            {
+                DebugPrint("LogonUserW() failed!");
+                return 0;
+            }
+            ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
+            ProfileInfo.dwSize = sizeof(PROFILEINFOW);
+            ProfileInfo.lpUserName = L"Administrator";
+            ProfileInfo.dwFlags = PI_NOUI;
+            LoadUserProfileW(hToken, &ProfileInfo);
+            CloseHandle(hToken);
+        }
+        else
+        {
+            DPRINT1("ROS HACK not needed anymore. Please remove it\n");
+        }
+    }
+    /* END OF ROS HACK */
 
-  if (!EnableUserModePnpManager())
-  {
-    DebugPrint("EnableUserModePnpManager() failed!\n");
-    return 0;
-  }
+    SetupCloseInfFile(hSysSetupInf);
+    SetSetupType(0);
 
-  if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
-  {
-    DebugPrint("CMP_WaitNoPendingInstallEvents() failed!\n");
-    return 0;
-  }
+    LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS done");
+    TerminateSetupActionLog();
 
-  InstallWizard();
+    /* Get shutdown privilege */
+    if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
+    {
+        DebugPrint("OpenProcessToken() failed!");
+        return 0;
+    }
+    if (!LookupPrivilegeValue(
+        NULL,
+        SE_SHUTDOWN_NAME,
+        &privs.Privileges[0].Luid))
+    {
+        DebugPrint("LookupPrivilegeValue() failed!");
+        return 0;
+    }
+    privs.PrivilegeCount = 1;
+    privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+    if (AdjustTokenPrivileges(
+        token,
+        FALSE,
+        &privs,
+        0,
+        (PTOKEN_PRIVILEGES)NULL,
+        NULL) == 0)
+    {
+        DebugPrint("AdjustTokenPrivileges() failed!");
+        return 0;
+    }
 
-  SetupCloseInfFile(hSysSetupInf);
+    ExitWindowsEx(EWX_REBOOT, 0);
+    return 0;
+}
 
-  /// THE FOLLOWING DPRINT IS FOR THE SYSTEM REGRESSION TOOL
-  /// DO NOT REMOVE!!!
-  DbgPrint("SYSREG_CHECKPOINT:SYSSETUP_COMPLETE\n");
 
-  return 0;
+/*
+ * @unimplemented
+ */
+DWORD WINAPI
+SetupChangeFontSize(
+    IN HANDLE hWnd,
+    IN LPCWSTR lpszFontSize)
+{
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
 }
 
-
 /*
  * @unimplemented
  */
-DWORD STDCALL
-SetupChangeFontSize(HANDLE hWnd,
-                    LPCWSTR lpszFontSize)
+DWORD WINAPI
+SetupChangeLocaleEx(HWND hWnd,
+                    LCID Lcid,
+                    LPCWSTR lpSrcRootPath,
+                    char Unknown,
+                    DWORD dwUnused1,
+                    DWORD dwUnused2)
+{
+    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
+    return FALSE;
+}
+
+/*
+ * @implemented
+ */
+DWORD WINAPI
+SetupChangeLocale(HWND hWnd, LCID Lcid)
 {
-  return FALSE;
+    return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
 }