move the apps into the same position they are found in windows.
[reactos.git] / reactos / lib / syssetup / install.c
index 9e035d4..38d29c8 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.6 2004/01/16 21:33:23 ekohl 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>
 #include <windows.h>
+#define NTOS_MODE_USER
+#include <ndk/ntndk.h>
+
+#include <commctrl.h>
 #include <stdio.h>
+#include <tchar.h>
+#include <stdlib.h>
 
-#include <syssetup.h>
+#include <samlib/samlib.h>
+#include <syssetup/syssetup.h>
+#include <userenv.h>
+#include <setupapi.h>
 
-#if 0
-VOID Wizard (VOID);
-#endif
+#include <shlobj.h>
+#include <objidl.h>
+#include <shlwapi.h>
+
+#include "globals.h"
+#include "resource.h"
 
-/* userenv.dll */
-BOOL WINAPI InitializeProfiles (VOID);
-BOOL WINAPI CreateUserProfileW (PSID Sid, LPCWSTR lpUserName);
+#define VMWINST
 
 
 /* GLOBALS ******************************************************************/
@@ -47,6 +56,7 @@ BOOL WINAPI CreateUserProfileW (PSID Sid, LPCWSTR lpUserName);
 PSID DomainSid = NULL;
 PSID AdminSid = NULL;
 
+HINF hSysSetupInf = INVALID_HANDLE_VALUE;
 
 /* FUNCTIONS ****************************************************************/
 
@@ -60,7 +70,136 @@ DebugPrint(char* fmt,...)
   vsprintf(buffer, fmt, ap);
   va_end(ap);
 
-  OutputDebugStringA(buffer);
+  strcat(buffer, "\nRebooting now!");
+  MessageBoxA(NULL,
+             buffer,
+             "ReactOS Setup",
+             MB_OK);
+}
+
+
+#ifdef VMWINST
+static BOOL
+RunVMWInstall(VOID)
+{
+  PROCESS_INFORMATION ProcInfo;
+  STARTUPINFO si;
+  WCHAR InstallName[] = L"vmwinst.exe";
+
+  ZeroMemory(&si, sizeof(STARTUPINFO));
+  si.cb = sizeof(STARTUPINFO);
+
+  if(CreateProcess(NULL, InstallName, NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS,
+                   NULL, NULL, &si, &ProcInfo))
+  {
+    WaitForSingleObject(ProcInfo.hProcess, INFINITE);
+    CloseHandle(ProcInfo.hThread);
+    CloseHandle(ProcInfo.hProcess);
+    return TRUE;
+  }
+  return FALSE;
+}
+#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;
 }
 
 
@@ -87,6 +226,7 @@ CreateRandomSid (PSID *Sid)
                               Sid);
 }
 
+
 static VOID
 AppendRidToSid (PSID *Dst,
                PSID Src,
@@ -120,43 +260,134 @@ AppendRidToSid (PSID *Dst,
                               Dst);
 }
 
-static BOOL
-SaveDomainSid (PSID Sid)
+INT_PTR CALLBACK
+RestartDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-  DWORD dwDisposition;
+   switch(msg)
+   {
+      case WM_INITDIALOG:
+         SendDlgItemMessage(hWnd, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0,
+            MAKELPARAM(0, 300));
+         SetTimer(hWnd, 1, 50, NULL);
+         return TRUE;
+
+      case WM_TIMER:
+         {
+            INT Position;
+            HWND hWndProgress;
+
+            hWndProgress = GetDlgItem(hWnd, IDC_RESTART_PROGRESS);
+            Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0);
+            if (Position == 300)
+               EndDialog(hWnd, 0);
+            else
+               SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0);
+         }
+         return TRUE;
+
+      case WM_COMMAND:
+         switch (wParam)
+         {
+            case IDOK:
+            case IDCANCEL:
+               EndDialog(hWnd, 0);
+               return TRUE;
+         }
+         break;
+   }
+
+   return FALSE;
+}
+
+static VOID
+CreateTempDir(LPCWSTR VarName)
+{
+  TCHAR szTempDir[MAX_PATH];
+  TCHAR szBuffer[MAX_PATH];
+  DWORD dwLength;
   HKEY hKey;
 
-  if (RegCreateKeyExW (HKEY_LOCAL_MACHINE,
-                      L"SAM\\Accounts",
-                      0,
-                      NULL,
-                      REG_OPTION_NON_VOLATILE,
-                      KEY_ALL_ACCESS,
-                      NULL,
-                      &hKey,
-                      &dwDisposition))
+  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                  _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
+                  0,
+                  KEY_ALL_ACCESS,
+                  &hKey))
     {
-#if 0
-      DebugPrint ("Failed to create Accounts key! (Error %lu)\n", GetLastError());
-#endif
-      return FALSE;
+      DebugPrint("Error: %lu\n", GetLastError());
+      return;
     }
 
-  if (RegSetValueExW (hKey,
-                     L"DomainSID",
-                     0,
-                     REG_BINARY,
-                     (LPBYTE)Sid,
-                     RtlLengthSid (Sid)))
+  /* Get temp dir */
+  dwLength = MAX_PATH * sizeof(TCHAR);
+  if (RegQueryValueEx(hKey,
+                     VarName,
+                     NULL,
+                     NULL,
+                     (LPBYTE)szBuffer,
+                     &dwLength))
+    {
+      DebugPrint("Error: %lu\n", GetLastError());
+      RegCloseKey(hKey);
+      return;
+    }
+
+  /* Expand it */
+  if (!ExpandEnvironmentStrings(szBuffer,
+                               szTempDir,
+                               MAX_PATH))
+    {
+      DebugPrint("Error: %lu\n", GetLastError());
+      RegCloseKey(hKey);
+      return;
+    }
+
+  /* Create profiles directory */
+  if (!CreateDirectory(szTempDir, NULL))
+    {
+      if (GetLastError() != ERROR_ALREADY_EXISTS)
+       {
+         DebugPrint("Error: %lu\n", GetLastError());
+         RegCloseKey(hKey);
+         return;
+       }
+    }
+
+  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))
     {
-#if 0
-      DebugPrint ("Failed to set DomainSID value! (Error %lu)\n", GetLastError());
-#endif
-      RegCloseKey (hKey);
       return FALSE;
     }
 
-  RegCloseKey (hKey);
+    if (!SetupDiInstallClass(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
+    {
+      return FALSE;
+    }
+  }
+  while (SetupFindNextLine(&InfContext, &InfContext));
 
   return TRUE;
 }
@@ -165,6 +396,8 @@ SaveDomainSid (PSID Sid)
 DWORD STDCALL
 InstallReactOS (HINSTANCE hInstance)
 {
+  TCHAR sAccessories[256];
+
 # if 0
   OutputDebugStringA ("InstallReactOS() called\n");
 
@@ -187,30 +420,38 @@ InstallReactOS (HINSTANCE hInstance)
 #if 0
   UNICODE_STRING SidString;
 #endif
+  ULONG LastError;
 
   if (!InitializeProfiles ())
     {
-#if 0
-      OutputDebugStringA ("InitializeProfiles() failed\n");
-#endif
-      MessageBoxA (NULL,
-                  "Profile initialization failed!\nRebooting now!",
-                  "ReactOS Setup",
-                  MB_OK);
+      DebugPrint ("InitializeProfiles() failed\n");
       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("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("explorer.lnk"), _T("explorer.exe"), IDS_CMT_EXPLORER);
+    CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("regedit.lnk"), _T("regedit.exe"), IDS_CMT_REGEDIT);
+  }
+
+  CoUninitialize();
+
+  /* Create the semi-random Domain-SID */
   CreateRandomSid (&DomainSid);
   if (DomainSid == NULL)
     {
-#if 0
-      OutputDebugStringA ("Failed to create the Domain-SID!\n");
-#endif
-      MessageBoxA (NULL,
-                  "Failed to create the Domain SID!\nRebooting now!",
-                  "ReactOS Setup",
-                  MB_OK);
-
+      DebugPrint ("Domain-SID creation failed!\n");
       return 0;
     }
 
@@ -220,66 +461,103 @@ InstallReactOS (HINSTANCE hInstance)
   RtlFreeUnicodeString (&SidString);
 #endif
 
-  if (!SaveDomainSid (DomainSid))
+  /* Initialize the Security Account Manager (SAM) */
+  if (!SamInitializeSAM ())
     {
-#if 0
-      OutputDebugStringA ("Failed to create the Domain-SID!\n");
-#endif
-      MessageBoxA (NULL,
-                  "Failed to save the Domain SID!\nRebooting now!",
-                  "ReactOS Setup",
-                  MB_OK);
+      DebugPrint ("SamInitializeSAM() failed!\n");
+      RtlFreeSid (DomainSid);
+      return 0;
+    }
 
+  /* Set the Domain SID (aka Computer SID) */
+  if (!SamSetDomainSid (DomainSid))
+    {
+      DebugPrint ("SamSetDomainSid() failed!\n");
       RtlFreeSid (DomainSid);
       return 0;
     }
 
-  AppendRidToSid (&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
+  /* Append the Admin-RID */
+  AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
 
 #if 0
-  RtlConvertSidToUnicodeString (&SidString, AdminSid, TRUE);
-  DebugPrint ("Admin SID: %wZ\n", &SidString);
+  RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
+  DebugPrint ("Admin-SID: %wZ\n", &SidString);
   RtlFreeUnicodeString (&SidString);
 #endif
 
-  if (!CreateUserProfileW (AdminSid, L"Administrator"))
+  /* 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)
     {
-#if 0
-      DebugPrint ("Failed to create the admin user profile!\n");
-#endif
-      MessageBoxA (NULL,
-                  "Failed to create the admin user profile!\nRebooting now!",
-                  "ReactOS Setup",
-                  MB_OK);
-
-      RtlFreeSid (AdminSid);
-      RtlFreeSid (DomainSid);
+      DebugPrint("SamCreateUser() failed!\n");
+      RtlFreeSid(AdminSid);
+      RtlFreeSid(DomainSid);
       return 0;
     }
-
-  RtlFreeSid (AdminSid);
-  RtlFreeSid (DomainSid);
-
-#if 0
-  OutputDebugStringA ("System setup successful\n");
+  }
+
+  /* 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");
+
+  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();
 #endif
-  MessageBoxA (NULL,
-              "Profile initialization successful!\nRebooting now!",
-              "ReactOS Setup",
-              MB_OK);
 
-#if 0
-  Wizard ();
-#endif
+  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;
 }