make more robust by calling GetSystemDirectory
[reactos.git] / reactos / lib / syssetup / install.c
index 048373e..e3a8199 100644 (file)
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: install.c,v 1.13 2004/06/24 09:17:33 gvg Exp $
+/* $Id$
  *
  * COPYRIGHT:         See COPYING in the top level directory
  * PROJECT:           ReactOS system libraries
  * PURPOSE:           System setup
  * FILE:              lib/syssetup/install.c
- * PROGRAMER:         Eric Kohl (ekohl@rz-online.de)
+ * PROGRAMER:         Eric Kohl
  */
 
 /* INCLUDES *****************************************************************/
 
-#include <ntos.h>
+#define WIN32_NO_STATUS
 #include <windows.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
+
 #include <commctrl.h>
 #include <stdio.h>
+#include <io.h>
+#include <tchar.h>
+#include <stdlib.h>
 
-#include <samlib.h>
-#include <syssetup.h>
+#include <samlib/samlib.h>
+#include <syssetup/syssetup.h>
 #include <userenv.h>
+#include <setupapi.h>
+
+#include <shlobj.h>
+#include <objidl.h>
+#include <shlwapi.h>
 
 #include "globals.h"
 #include "resource.h"
 
-// #define NO_GUI
 #define VMWINST
 
 
@@ -48,6 +58,7 @@
 PSID DomainSid = NULL;
 PSID AdminSid = NULL;
 
+HINF hSysSetupInf = INVALID_HANDLE_VALUE;
 
 /* FUNCTIONS ****************************************************************/
 
@@ -61,15 +72,11 @@ DebugPrint(char* fmt,...)
   vsprintf(buffer, fmt, ap);
   va_end(ap);
 
-#ifdef NO_GUI
-  OutputDebugStringA(buffer);
-#else
-  strcat (buffer, "\nRebooting now!");
-  MessageBoxA (NULL,
-              buffer,
-              "ReactOS Setup",
-              MB_OK);
-#endif
+  strcat(buffer, "\nRebooting now!");
+  MessageBoxA(NULL,
+             buffer,
+             "ReactOS Setup",
+             MB_OK);
 }
 
 
@@ -79,12 +86,13 @@ RunVMWInstall(VOID)
 {
   PROCESS_INFORMATION ProcInfo;
   STARTUPINFO si;
-  
+  WCHAR InstallName[] = L"vmwinst.exe";
+
   ZeroMemory(&si, sizeof(STARTUPINFO));
   si.cb = sizeof(STARTUPINFO);
-  
-  if(CreateProcessA(NULL, "vmwinst.exe", NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, 
-                    NULL, NULL, &si, &ProcInfo))
+
+  if(CreateProcess(NULL, InstallName, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS,
+                   NULL, NULL, &si, &ProcInfo))
   {
     WaitForSingleObject(ProcInfo.hProcess, INFINITE);
     CloseHandle(ProcInfo.hThread);
@@ -96,6 +104,107 @@ RunVMWInstall(VOID)
 #endif
 
 
+HRESULT CreateShellLink(LPCTSTR linkPath, LPCTSTR cmd, LPCTSTR arg, LPCTSTR dir, LPCTSTR iconPath, int icon_nr, LPCTSTR comment)
+{
+  IShellLink* psl;
+  IPersistFile* ppf;
+#ifndef _UNICODE
+  WCHAR buffer[MAX_PATH];
+#endif /* _UNICODE */
+
+  HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
+
+  if (SUCCEEDED(hr))
+    {
+      hr = psl->lpVtbl->SetPath(psl, cmd);
+
+      if (arg)
+        {
+          hr = psl->lpVtbl->SetArguments(psl, arg);
+        }
+
+      if (dir)
+        {
+          hr = psl->lpVtbl->SetWorkingDirectory(psl, dir);
+        }
+
+      if (iconPath)
+        {
+          hr = psl->lpVtbl->SetIconLocation(psl, iconPath, icon_nr);
+        }
+
+      if (comment)
+        {
+          hr = psl->lpVtbl->SetDescription(psl, comment);
+        }
+
+      hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
+
+      if (SUCCEEDED(hr))
+        {
+#ifdef _UNICODE
+          hr = ppf->lpVtbl->Save(ppf, linkPath, TRUE);
+#else /* _UNICODE */
+          MultiByteToWideChar(CP_ACP, 0, linkPath, -1, buffer, MAX_PATH);
+
+          hr = ppf->lpVtbl->Save(ppf, buffer, TRUE);
+#endif /* _UNICODE */
+
+          ppf->lpVtbl->Release(ppf);
+        }
+
+      psl->lpVtbl->Release(psl);
+    }
+
+  return hr;
+}
+
+
+static BOOL
+CreateShortcut(int csidl, LPCTSTR folder, LPCTSTR linkName, LPCTSTR command, UINT nIdTitle)
+{
+  TCHAR path[MAX_PATH];
+  TCHAR title[256];
+  LPTSTR p = path;
+
+  if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
+    return FALSE;
+
+  if (folder)
+    {
+      p = PathAddBackslash(p);
+      _tcscpy(p, folder);
+    }
+
+  p = PathAddBackslash(p);
+  _tcscpy(p, linkName);
+
+  if (!LoadString(hDllInstance, nIdTitle, title, 256))
+    return FALSE;
+
+  return SUCCEEDED(CreateShellLink(path, command, _T(""), NULL, NULL, 0, title));
+}
+
+
+static BOOL
+CreateShortcutFolder(int csidl, UINT nID, LPTSTR name, int nameLen)
+{
+  TCHAR path[MAX_PATH];
+  LPTSTR p;
+
+  if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
+    return FALSE;
+
+  if (!LoadString(hDllInstance, nID, name, nameLen))
+    return FALSE;
+
+  p = PathAddBackslash(path);
+  _tcscpy(p, name);
+
+  return CreateDirectory(path, NULL) || GetLastError()==ERROR_ALREADY_EXISTS;
+}
+
+
 static VOID
 CreateRandomSid (PSID *Sid)
 {
@@ -160,8 +269,8 @@ RestartDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
       case WM_INITDIALOG:
          SendDlgItemMessage(hWnd, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0,
-            MAKELPARAM(0, 300)); 
-         SetTimer(hWnd, 0, 50, NULL);
+            MAKELPARAM(0, 300));
+         SetTimer(hWnd, 1, 50, NULL);
          return TRUE;
 
       case WM_TIMER:
@@ -195,62 +304,105 @@ RestartDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 static VOID
 CreateTempDir(LPCWSTR VarName)
 {
-  WCHAR szTempDir[MAX_PATH];
-  WCHAR szBuffer[MAX_PATH];
+  TCHAR szTempDir[MAX_PATH];
+  TCHAR szBuffer[MAX_PATH];
   DWORD dwLength;
   HKEY hKey;
 
-  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                    L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
-                    0,
-                    KEY_ALL_ACCESS,
-                    &hKey))
+  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                  _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
+                  0,
+                  KEY_ALL_ACCESS,
+                  &hKey))
     {
       DebugPrint("Error: %lu\n", GetLastError());
       return;
     }
 
   /* Get temp dir */
-  dwLength = MAX_PATH * sizeof(WCHAR);
-  if (RegQueryValueEx(hKey,
-                       VarName,
-                       NULL,
-                       NULL,
-                       (LPBYTE)szBuffer,
-                       &dwLength))
+  dwLength = MAX_PATH * sizeof(TCHAR);
+  if (RegQueryValueEx(hKey,
+                     VarName,
+                     NULL,
+                     NULL,
+                     (LPBYTE)szBuffer,
+                     &dwLength))
     {
       DebugPrint("Error: %lu\n", GetLastError());
-      RegCloseKey (hKey);
+      RegCloseKey(hKey);
       return;
     }
 
   /* Expand it */
-  if (!ExpandEnvironmentStrings(szBuffer,
-                                 szTempDir,
-                                 MAX_PATH))
+  if (!ExpandEnvironmentStrings(szBuffer,
+                               szTempDir,
+                               MAX_PATH))
     {
       DebugPrint("Error: %lu\n", GetLastError());
-      RegCloseKey (hKey);
+      RegCloseKey(hKey);
       return;
     }
 
   /* Create profiles directory */
-  if (!CreateDirectory(szTempDir, NULL))
+  if (!CreateDirectory(szTempDir, NULL))
     {
-      if (GetLastError () != ERROR_ALREADY_EXISTS)
+      if (GetLastError() != ERROR_ALREADY_EXISTS)
        {
          DebugPrint("Error: %lu\n", GetLastError());
-         RegCloseKey (hKey);
+         RegCloseKey(hKey);
          return;
        }
     }
 
-  RegCloseKey (hKey);
+  RegCloseKey(hKey);
 }
 
+
+BOOL
+ProcessSysSetupInf(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))
+    {
+      return FALSE;
+    }
+
+    if (!SetupDiInstallClass(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
+    {
+      return FALSE;
+    }
+  }
+  while (SetupFindNextLine(&InfContext, &InfContext));
+
+  return TRUE;
+}
+
+
 DWORD STDCALL
 InstallReactOS (HINSTANCE hInstance)
 {
+  TCHAR sAccessories[256];
+  TCHAR sGames[256];
+  TCHAR Sys[_MAX_PATH];
+    
+
 # if 0
   OutputDebugStringA ("InstallReactOS() called\n");
 
@@ -273,6 +425,7 @@ InstallReactOS (HINSTANCE hInstance)
 #if 0
   UNICODE_STRING SidString;
 #endif
+  ULONG LastError;
 
   if (!InitializeProfiles ())
     {
@@ -280,6 +433,37 @@ InstallReactOS (HINSTANCE hInstance)
       return 0;
     }
 
+  CoInitialize(NULL);
+
+  /* create desktop shortcuts */
+  CreateShortcut(CSIDL_DESKTOP, NULL, _T("Command Prompt.lnk"), _T("cmd.exe"), IDS_CMT_CMD);
+
+  /* create program startmenu shortcuts */  
+  CreateShortcut(CSIDL_PROGRAMS, NULL, _T("winefile.lnk"), _T("winefile.exe"), IDS_CMT_WINEFILE);
+
+  /* create and fill Accessories subfolder */
+  if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, sAccessories, 256)) {
+       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("explorer.lnk"), _T("explorer.exe"), IDS_CMT_EXPLORER);
+    CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("regedit.lnk"), _T("regedit.exe"), IDS_CMT_REGEDIT);
+  }
+
+  if(!GetSystemDirectory(Sys, _MAX_PATH))
+    Sys[0] = L'\0';
+
+  /* create Games subfolder and fill if the exe is available */
+  if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, sGames, 256)) {
+       if (Sys[0] != L'\0') {
+         if((_taccess(_tcscat(Sys, _T("\\sol.exe")), 0 )) != -1)
+        CreateShortcut(CSIDL_PROGRAMS, sGames, _T("Solitaire.lnk"), _T("sol.exe"), IDS_CMT_SOLITAIRE);
+         
+      /* winemine etc .... */
+       }
+  }
+
+  CoUninitialize();
+
   /* Create the semi-random Domain-SID */
   CreateRandomSid (&DomainSid);
   if (DomainSid == NULL)
@@ -311,7 +495,7 @@ InstallReactOS (HINSTANCE hInstance)
     }
 
   /* Append the Admin-RID */
-  AppendRidToSid (&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
+  AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
 
 #if 0
   RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
@@ -320,50 +504,77 @@ InstallReactOS (HINSTANCE hInstance)
 #endif
 
   /* Create the Administrator account */
-  if (!SamCreateUser (L"Administrator", L"", AdminSid))
+  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)
     {
-      DebugPrint ("SamCreateUser() failed!\n");
-      RtlFreeSid (AdminSid);
-      RtlFreeSid (DomainSid);
+      DebugPrint("SamCreateUser() failed!\n");
+      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;
-    }
+  if (!CreateUserProfileW(AdminSid, L"Administrator"))
+  {
+    DebugPrint("CreateUserProfileW() failed!\n");
+    RtlFreeSid(AdminSid);
+    RtlFreeSid(DomainSid);
+    return 0;
+  }
 
-  RtlFreeSid (AdminSid);
-  RtlFreeSid (DomainSid);
+  RtlFreeSid(AdminSid);
+  RtlFreeSid(DomainSid);
 
   CreateTempDir(L"TEMP");
   CreateTempDir(L"TMP");
 
-#if 1
-  InstallWizard ();
-#endif
+  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;
+  }
+
+  InstallWizard();
+
+  SetupCloseInfFile(hSysSetupInf);
 
 #ifdef VMWINST
-  RunVMWInstall ();
+  RunVMWInstall();
 #endif
 
-  DialogBox (hDllInstance,
-            MAKEINTRESOURCE(IDD_RESTART),
-            NULL,
-            RestartDlgProc);
+  DialogBox(hDllInstance,
+           MAKEINTRESOURCE(IDD_RESTART),
+           NULL,
+           RestartDlgProc);
 
   return 0;
 }
 
+
 /*
  * @unimplemented
  */
-DWORD STDCALL SetupChangeFontSize(HANDLE HWindow,
-                                  LPCWSTR lpszFontSize)
+DWORD STDCALL
+SetupChangeFontSize(HANDLE hWnd,
+                    LPCWSTR lpszFontSize)
 {
-  return(FALSE);
+  return FALSE;
 }