[SERVICES] Set default status to SERVICE_START_PENDING when starting a service.
[reactos.git] / reactos / dll / win32 / syssetup / install.c
index 60ef569..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,7 @@
 #include "globals.h"
 #include "resource.h"
 
+#define NDEBUG
 #include <debug.h>
 
 DWORD WINAPI
@@ -303,13 +304,13 @@ static VOID
 CreateTempDir(
     IN LPCWSTR VarName)
 {
-    TCHAR szTempDir[MAX_PATH];
-    TCHAR szBuffer[MAX_PATH];
+    WCHAR szTempDir[MAX_PATH];
+    WCHAR szBuffer[MAX_PATH];
     DWORD dwLength;
     HKEY hKey;
 
-    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                     _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
+    if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+                     L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
                      0,
                      KEY_QUERY_VALUE,
                      &hKey))
@@ -319,8 +320,8 @@ CreateTempDir(
     }
 
     /* Get temp dir */
-    dwLength = MAX_PATH * sizeof(TCHAR);
-    if (RegQueryValueEx(hKey,
+    dwLength = MAX_PATH * sizeof(WCHAR);
+    if (RegQueryValueExW(hKey,
                         VarName,
                         NULL,
                         NULL,
@@ -333,7 +334,7 @@ CreateTempDir(
     }
 
     /* Expand it */
-    if (!ExpandEnvironmentStrings(szBuffer,
+    if (!ExpandEnvironmentStringsW(szBuffer,
                                   szTempDir,
                                   MAX_PATH))
     {
@@ -343,7 +344,7 @@ CreateTempDir(
     }
 
     /* Create profiles directory */
-    if (!CreateDirectory(szTempDir, NULL))
+    if (!CreateDirectoryW(szTempDir, NULL))
     {
         if (GetLastError() != ERROR_ALREADY_EXISTS)
         {
@@ -358,14 +359,14 @@ CreateTempDir(
 
 
 BOOL
-ProcessSysSetupInf(VOID)
+InstallSysSetupInfDevices(VOID)
 {
     INFCONTEXT InfContext;
-    TCHAR LineBuffer[256];
+    WCHAR LineBuffer[256];
     DWORD LineLength;
 
-    if (!SetupFindFirstLine(hSysSetupInf,
-                            _T("DeviceInfsToInstall"),
+    if (!SetupFindFirstLineW(hSysSetupInf,
+                            L"DeviceInfsToInstall",
                             NULL,
                             &InfContext))
     {
@@ -374,7 +375,7 @@ ProcessSysSetupInf(VOID)
 
     do
     {
-        if (!SetupGetStringField(&InfContext,
+        if (!SetupGetStringFieldW(&InfContext,
                                  0,
                                  LineBuffer,
                                  sizeof(LineBuffer)/sizeof(LineBuffer[0]),
@@ -383,7 +384,7 @@ ProcessSysSetupInf(VOID)
             return FALSE;
         }
 
-        if (!SetupDiInstallClass(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
+        if (!SetupDiInstallClassW(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
         {
             return FALSE;
         }
@@ -392,35 +393,180 @@ ProcessSysSetupInf(VOID)
 
     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)
 {
+    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 = OpenService(hSCManager, _T("PlugPlay"), SERVICE_CHANGE_CONFIG | SERVICE_START);
+    hService = OpenServiceW(hSCManager,
+                            L"PlugPlay",
+                            SERVICE_CHANGE_CONFIG | SERVICE_START | SERVICE_QUERY_STATUS);
     if (hService == NULL)
         goto cleanup;
 
-    ret = ChangeServiceConfig(
-        hService,
-        SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
-        NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+    ret = ChangeServiceConfigW(hService,
+                               SERVICE_NO_CHANGE,
+                               SERVICE_AUTO_START,
+                               SERVICE_NO_CHANGE,
+                               NULL, NULL, NULL,
+                               NULL, NULL, NULL, NULL);
     if (!ret)
         goto cleanup;
 
-    ret = StartService(hService, 0, NULL);
+    ret = StartServiceW(hService, 0, NULL);
+    if (!ret)
+    {
+        /* If the service is already running, just return TRUE */
+        ret = GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
+        goto cleanup;
+    }
+
+    ret = QueryServiceStatusEx(hService,
+                               SC_STATUS_PROCESS_INFO,
+                               (LPBYTE)&ServiceStatus,
+                               sizeof(SERVICE_STATUS_PROCESS),
+                               &BytesNeeded);
     if (!ret)
         goto cleanup;
 
-    ret = TRUE;
+    /* We don't want to wait for more than 30 seconds */
+    dwMaxWait = 30000;
+    dwStartTickCount = GetTickCount();
+
+    /* 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;
+        }
+
+        /* 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;
+            }
+        }
+
+        /* 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)
@@ -444,11 +590,11 @@ StatusMessageWindowProc(
     {
         case WM_INITDIALOG:
         {
-            TCHAR szMsg[256];
+            WCHAR szMsg[256];
 
-            if (!LoadString(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
+            if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
                 return FALSE;
-            SetDlgItemText(hwndDlg, IDC_STATUSLABEL, szMsg);
+            SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
             return TRUE;
         }
     }
@@ -486,6 +632,85 @@ ShowStatusMessageThread(
     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;
+}
+
+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)
 {
@@ -502,20 +727,30 @@ CommonInstall(VOID)
         return FALSE;
     }
 
-    if (!ProcessSysSetupInf())
+    if (!InstallSysSetupInfDevices())
     {
-        DebugPrint("ProcessSysSetupInf() failed!\n");
+        DebugPrint("InstallSysSetupInfDevices() failed!\n");
         SetupCloseInfFile(hSysSetupInf);
         return FALSE;
     }
 
-    CreateThread(
-        NULL,
-        0,
-        ShowStatusMessageThread,
-        (LPVOID)&hWnd,
-        0,
-        NULL);
+    if(!InstallSysSetupInfComponents())
+    {
+        DebugPrint("InstallSysSetupInfComponents() failed!\n");
+        SetupCloseInfFile(hSysSetupInf);
+        return FALSE;
+    }
+
+    if (!IsConsoleBoot())
+    {
+        CreateThread(
+            NULL,
+            0,
+            ShowStatusMessageThread,
+            (LPVOID)&hWnd,
+            0,
+            NULL);
+    }
 
     if (!EnableUserModePnpManager())
     {
@@ -540,7 +775,7 @@ CommonInstall(VOID)
 DWORD WINAPI
 InstallLiveCD(IN HINSTANCE hInstance)
 {
-    STARTUPINFO StartupInfo;
+    STARTUPINFOW StartupInfo;
     PROCESS_INFORMATION ProcessInformation;
     BOOL res;
 
@@ -549,15 +784,15 @@ InstallLiveCD(IN HINSTANCE hInstance)
     SetupCloseInfFile(hSysSetupInf);
 
     /* Run the shell */
-    StartupInfo.cb = sizeof(StartupInfo);
+    StartupInfo.cb = sizeof(STARTUPINFOW);
     StartupInfo.lpReserved = NULL;
     StartupInfo.lpDesktop = NULL;
     StartupInfo.lpTitle = NULL;
     StartupInfo.dwFlags = 0;
     StartupInfo.cbReserved2 = 0;
     StartupInfo.lpReserved2 = 0;
-    res = CreateProcess(
-        _T("userinit.exe"),
+    res = CreateProcessW(
+        L"userinit.exe",
         NULL,
         NULL,
         NULL,
@@ -573,10 +808,10 @@ InstallLiveCD(IN HINSTANCE hInstance)
     return 0;
 
 cleanup:
-    MessageBoxA(
+    MessageBoxW(
         NULL,
-        "You can shutdown your computer, or press ENTER to reboot",
-        "ReactOS LiveCD",
+        L"You can shutdown your computer, or press ENTER to reboot",
+        L"ReactOS LiveCD",
         MB_OK);
     return 0;
 }
@@ -590,38 +825,59 @@ CreateShortcuts(VOID)
     CoInitialize(NULL);
 
     /* Create desktop shortcuts */
-    CreateShortcut(CSIDL_DESKTOP, NULL, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, FALSE);
+    CreateShortcut(CSIDL_DESKTOP, NULL, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, TRUE);
 
     /* Create program startmenu shortcuts */
-    CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_EXPLORER, _T("%SystemRoot%\\explorer.exe"), IDS_CMT_EXPLORER, FALSE);
-    CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_DOWNLOADER, _T("%SystemRoot%\\system32\\downloader.exe"), IDS_CMT_DOWNLOADER, TRUE);
+    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, FALSE);
-    CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_DEVICE, _T("%SystemRoot%\\system32\\devmgmt.exe"), IDS_CMT_DEVMGMT, FALSE);
+    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])))
     {
-        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CALC, _T("%SystemRoot%\\system32\\calc.exe"), IDS_CMT_CALC, FALSE);
-        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, FALSE);
-        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_NOTEPAD, _T("%SystemRoot%\\system32\\notepad.exe"), IDS_CMT_NOTEPAD, FALSE);
-        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_REGEDIT, _T("%SystemRoot%\\regedit.exe"), IDS_CMT_REGEDIT, FALSE);
-        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WORDPAD, _T("%SystemRoot%\\system32\\wordpad.exe"), IDS_CMT_WORDPAD, FALSE);
+        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);
     }
 
-    /* Creacte System Tools subfolder and fill if the exe is available */
+    /* 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, FALSE);
+        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);
+    }
+
+    /* 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);
+    }
+
+    /* 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);
     }
 
     /* Create Games subfolder and fill if the exe is available */
     if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
     {
-        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SOLITAIRE, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE, FALSE);
-        CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WINEMINE, _T("%SystemRoot%\\system32\\winemine.exe"), IDS_CMT_WINEMINE, FALSE);
+        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);
     }
 
     CoUninitialize();
@@ -669,10 +925,6 @@ InstallReactOS(HINSTANCE hInstance)
     InitializeSetupActionLog(FALSE);
     LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
 
-    /* Set user langage to the system language */
-    SetUserDefaultLCID(GetSystemDefaultLCID());
-    SetThreadLocale(GetSystemDefaultLCID());
-
     if (!InitializeProfiles())
     {
         DebugPrint("InitializeProfiles() failed");
@@ -710,6 +962,21 @@ InstallReactOS(HINSTANCE hInstance)
     /* Append the Admin-RID */
     AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
 
+    CreateTempDir(L"TEMP");
+    CreateTempDir(L"TMP");
+
+    if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
+    {
+        PathAddBackslash(szBuffer);
+        _tcscat(szBuffer, _T("system"));
+        CreateDirectory(szBuffer, NULL);
+    }
+
+    if (!CommonInstall())
+        return 0;
+
+    InstallWizard();
+
     /* Create the Administrator account */
     if (!SamCreateUser(L"Administrator", L"", AdminSid))
     {
@@ -761,21 +1028,6 @@ InstallReactOS(HINSTANCE hInstance)
     }
     /* END OF ROS HACK */
 
-    CreateTempDir(L"TEMP");
-    CreateTempDir(L"TMP");
-
-    if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
-    {
-        PathAddBackslash(szBuffer);
-        _tcscat(szBuffer, _T("system"));
-        CreateDirectory(szBuffer, NULL);
-    }
-
-    if (!CommonInstall())
-        return 0;
-
-    InstallWizard();
-
     SetupCloseInfFile(hSysSetupInf);
     SetSetupType(0);
 
@@ -810,10 +1062,6 @@ InstallReactOS(HINSTANCE hInstance)
         return 0;
     }
 
-    /// THE FOLLOWING DPRINT IS FOR THE SYSTEM REGRESSION TOOL
-    /// DO NOT REMOVE!!!
-    DbgPrint("SYSREG_CHECKPOINT:SYSSETUP_COMPLETE\n");
-
     ExitWindowsEx(EWX_REBOOT, 0);
     return 0;
 }
@@ -822,7 +1070,7 @@ InstallReactOS(HINSTANCE hInstance)
 /*
  * @unimplemented
  */
-DWORD STDCALL
+DWORD WINAPI
 SetupChangeFontSize(
     IN HANDLE hWnd,
     IN LPCWSTR lpszFontSize)
@@ -830,3 +1078,27 @@ SetupChangeFontSize(
     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
     return FALSE;
 }
+
+/*
+ * @unimplemented
+ */
+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 SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
+}