3 * Copyright (C) 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * PURPOSE: System setup
23 * FILE: lib/syssetup/install.c
24 * PROGRAMER: Eric Kohl
27 /* INCLUDES *****************************************************************/
29 #define WIN32_NO_STATUS
31 #define NTOS_MODE_USER
32 #include <ndk/ntndk.h>
40 #include <samlib/samlib.h>
41 #include <syssetup/syssetup.h>
55 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout
);
57 /* GLOBALS ******************************************************************/
59 PSID DomainSid
= NULL
;
62 HINF hSysSetupInf
= INVALID_HANDLE_VALUE
;
64 /* FUNCTIONS ****************************************************************/
67 DebugPrint(char* fmt
,...)
73 vsprintf(buffer
, fmt
, ap
);
76 LogItem(SYSSETUP_SEVERITY_FATAL_ERROR
, L
"Failed");
78 strcat(buffer
, "\nRebooting now!");
86 HRESULT
CreateShellLink(LPCTSTR linkPath
, LPCTSTR cmd
, LPCTSTR arg
, LPCTSTR dir
, LPCTSTR iconPath
, int icon_nr
, LPCTSTR comment
)
91 WCHAR buffer
[MAX_PATH
];
94 HRESULT hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLink
, (LPVOID
*)&psl
);
98 hr
= psl
->lpVtbl
->SetPath(psl
, cmd
);
102 hr
= psl
->lpVtbl
->SetArguments(psl
, arg
);
107 hr
= psl
->lpVtbl
->SetWorkingDirectory(psl
, dir
);
112 hr
= psl
->lpVtbl
->SetIconLocation(psl
, iconPath
, icon_nr
);
117 hr
= psl
->lpVtbl
->SetDescription(psl
, comment
);
120 hr
= psl
->lpVtbl
->QueryInterface(psl
, &IID_IPersistFile
, (LPVOID
*)&ppf
);
125 hr
= ppf
->lpVtbl
->Save(ppf
, linkPath
, TRUE
);
127 MultiByteToWideChar(CP_ACP
, 0, linkPath
, -1, buffer
, MAX_PATH
);
129 hr
= ppf
->lpVtbl
->Save(ppf
, buffer
, TRUE
);
130 #endif /* _UNICODE */
132 ppf
->lpVtbl
->Release(ppf
);
135 psl
->lpVtbl
->Release(psl
);
143 CreateShortcut(int csidl
, LPCTSTR folder
, UINT nIdName
, LPCTSTR command
, UINT nIdTitle
, BOOL bCheckExistence
)
145 TCHAR path
[MAX_PATH
];
146 TCHAR exeName
[MAX_PATH
];
150 TCHAR szWorkingDir
[MAX_PATH
];
151 LPTSTR lpWorkingDir
= NULL
;
155 if (ExpandEnvironmentStrings(command
,
157 sizeof(path
) / sizeof(path
[0])) == 0)
165 if ((_taccess(path
, 0 )) == -1)
166 /* Expected error, don't return FALSE */
170 dwLen
= GetFullPathName(path
,
171 sizeof(szWorkingDir
) / sizeof(szWorkingDir
[0]),
174 if (dwLen
!= 0 && dwLen
<= sizeof(szWorkingDir
) / sizeof(szWorkingDir
[0]))
176 /* Save the file name */
177 _tcscpy(exeName
, lpFilePart
);
179 if (lpFilePart
!= NULL
)
181 /* We're only interested in the path. Cut the file name off.
182 Also remove the trailing backslash unless the working directory
183 is only going to be a drive, ie. C:\ */
184 *(lpFilePart
--) = _T('\0');
185 if (!(lpFilePart
- szWorkingDir
== 2 && szWorkingDir
[1] == _T(':') &&
186 szWorkingDir
[2] == _T('\\')))
188 *lpFilePart
= _T('\0');
192 lpWorkingDir
= szWorkingDir
;
196 if (!SHGetSpecialFolderPath(0, path
, csidl
, TRUE
))
201 p
= PathAddBackslash(p
);
205 p
= PathAddBackslash(p
);
207 if (!LoadString(hDllInstance
, nIdName
, name
, sizeof(name
)/sizeof(name
[0])))
211 if (!LoadString(hDllInstance
, nIdTitle
, title
, sizeof(title
)/sizeof(title
[0])))
214 // FIXME: we should pass 'command' straight in here, but shell32 doesn't expand it
215 return SUCCEEDED(CreateShellLink(path
, exeName
, _T(""), lpWorkingDir
, NULL
, 0, title
));
220 CreateShortcutFolder(int csidl
, UINT nID
, LPTSTR name
, int nameLen
)
222 TCHAR path
[MAX_PATH
];
225 if (!SHGetSpecialFolderPath(0, path
, csidl
, TRUE
))
228 if (!LoadString(hDllInstance
, nID
, name
, nameLen
))
231 p
= PathAddBackslash(path
);
234 return CreateDirectory(path
, NULL
) || GetLastError()==ERROR_ALREADY_EXISTS
;
242 SID_IDENTIFIER_AUTHORITY SystemAuthority
= {SECURITY_NT_AUTHORITY
};
243 LARGE_INTEGER SystemTime
;
247 NtQuerySystemTime(&SystemTime
);
248 Seed
= &SystemTime
.u
.LowPart
;
250 Status
= RtlAllocateAndInitializeSid(
253 SECURITY_NT_NON_UNIQUE
,
262 return NT_SUCCESS(Status
);
272 ULONG Rid
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
276 RidCount
= *RtlSubAuthorityCountSid (Src
);
278 for (i
= 0; i
< RidCount
; i
++)
279 Rid
[i
] = *RtlSubAuthoritySid (Src
, i
);
283 Rid
[RidCount
] = NewRid
;
287 RtlAllocateAndInitializeSid(
288 RtlIdentifierAuthoritySid(Src
),
306 TCHAR szTempDir
[MAX_PATH
];
307 TCHAR szBuffer
[MAX_PATH
];
311 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
312 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
317 DebugPrint("Error: %lu\n", GetLastError());
322 dwLength
= MAX_PATH
* sizeof(TCHAR
);
323 if (RegQueryValueEx(hKey
,
330 DebugPrint("Error: %lu\n", GetLastError());
336 if (!ExpandEnvironmentStrings(szBuffer
,
340 DebugPrint("Error: %lu\n", GetLastError());
345 /* Create profiles directory */
346 if (!CreateDirectory(szTempDir
, NULL
))
348 if (GetLastError() != ERROR_ALREADY_EXISTS
)
350 DebugPrint("Error: %lu\n", GetLastError());
361 InstallSysSetupInfDevices(VOID
)
363 INFCONTEXT InfContext
;
364 TCHAR LineBuffer
[256];
367 if (!SetupFindFirstLine(hSysSetupInf
,
368 _T("DeviceInfsToInstall"),
377 if (!SetupGetStringField(&InfContext
,
380 sizeof(LineBuffer
)/sizeof(LineBuffer
[0]),
386 if (!SetupDiInstallClass(NULL
, LineBuffer
, DI_QUIETINSTALL
, NULL
))
391 while (SetupFindNextLine(&InfContext
, &InfContext
));
396 InstallSysSetupInfComponents(VOID
)
398 INFCONTEXT InfContext
;
399 TCHAR NameBuffer
[256];
400 TCHAR SectionBuffer
[256];
402 if (!SetupFindFirstLine(hSysSetupInf
,
407 DPRINT("No Inf.Always section found\n");
413 if (!SetupGetStringField(&InfContext
,
414 1, // Get the component name
416 sizeof(NameBuffer
)/sizeof(NameBuffer
[0]),
419 DebugPrint("Error while trying to get component name \n");
423 if (!SetupGetStringField(&InfContext
,
424 2, // Get the component install section
426 sizeof(SectionBuffer
)/sizeof(SectionBuffer
[0]),
429 DebugPrint("Error while trying to get component install section \n");
433 DPRINT("Trying to execute install section '%S' from '%S' \n", SectionBuffer
, NameBuffer
);
435 if (!SetupInstallFromInfSection(NULL
,
447 DebugPrint("Error while trying to install : %S (Error: %lu) \n", NameBuffer
, GetLastError());
451 while (SetupFindNextLine(&InfContext
, &InfContext
));
458 EnableUserModePnpManager(VOID
)
460 SC_HANDLE hSCManager
= NULL
;
461 SC_HANDLE hService
= NULL
;
464 hSCManager
= OpenSCManager(NULL
, NULL
, 0);
465 if (hSCManager
== NULL
)
468 hService
= OpenService(hSCManager
, _T("PlugPlay"), SERVICE_CHANGE_CONFIG
| SERVICE_START
);
469 if (hService
== NULL
)
472 ret
= ChangeServiceConfig(
474 SERVICE_NO_CHANGE
, SERVICE_AUTO_START
, SERVICE_NO_CHANGE
,
475 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
479 ret
= StartService(hService
, 0, NULL
);
486 if (hSCManager
!= NULL
)
487 CloseServiceHandle(hSCManager
);
488 if (hService
!= NULL
)
489 CloseServiceHandle(hService
);
495 StatusMessageWindowProc(
501 UNREFERENCED_PARAMETER(wParam
);
509 if (!LoadString(hDllInstance
, IDS_STATUS_INSTALL_DEV
, szMsg
, sizeof(szMsg
)/sizeof(szMsg
[0])))
511 SetDlgItemText(hwndDlg
, IDC_STATUSLABEL
, szMsg
);
520 ShowStatusMessageThread(
521 IN LPVOID lpParameter
)
523 HWND
*phWnd
= (HWND
*)lpParameter
;
527 hWnd
= CreateDialogParam(
529 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG
),
531 StatusMessageWindowProc
,
537 ShowWindow(hWnd
, SW_SHOW
);
539 /* Message loop for the Status window */
540 while (GetMessage(&Msg
, NULL
, 0, 0))
542 TranslateMessage(&Msg
);
543 DispatchMessage(&Msg
);
554 hSysSetupInf
= SetupOpenInfFileW(
559 if (hSysSetupInf
== INVALID_HANDLE_VALUE
)
561 DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
565 if (!InstallSysSetupInfDevices())
567 DebugPrint("InstallSysSetupInfDevices() failed!\n");
568 SetupCloseInfFile(hSysSetupInf
);
572 if(!InstallSysSetupInfComponents())
574 DebugPrint("InstallSysSetupInfComponents() failed!\n");
575 SetupCloseInfFile(hSysSetupInf
);
582 ShowStatusMessageThread
,
587 if (!EnableUserModePnpManager())
589 DebugPrint("EnableUserModePnpManager() failed!\n");
590 SetupCloseInfFile(hSysSetupInf
);
595 if (CMP_WaitNoPendingInstallEvents(INFINITE
) != WAIT_OBJECT_0
)
597 DebugPrint("CMP_WaitNoPendingInstallEvents() failed!\n");
598 SetupCloseInfFile(hSysSetupInf
);
608 InstallLiveCD(IN HINSTANCE hInstance
)
610 STARTUPINFO StartupInfo
;
611 PROCESS_INFORMATION ProcessInformation
;
614 if (!CommonInstall())
616 SetupCloseInfFile(hSysSetupInf
);
619 StartupInfo
.cb
= sizeof(StartupInfo
);
620 StartupInfo
.lpReserved
= NULL
;
621 StartupInfo
.lpDesktop
= NULL
;
622 StartupInfo
.lpTitle
= NULL
;
623 StartupInfo
.dwFlags
= 0;
624 StartupInfo
.cbReserved2
= 0;
625 StartupInfo
.lpReserved2
= 0;
636 &ProcessInformation
);
645 "You can shutdown your computer, or press ENTER to reboot",
653 CreateShortcuts(VOID
)
659 /* Create desktop shortcuts */
660 CreateShortcut(CSIDL_DESKTOP
, NULL
, IDS_SHORT_CMD
, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD
, FALSE
);
662 /* Create program startmenu shortcuts */
663 CreateShortcut(CSIDL_PROGRAMS
, NULL
, IDS_SHORT_EXPLORER
, _T("%SystemRoot%\\explorer.exe"), IDS_CMT_EXPLORER
, FALSE
);
664 CreateShortcut(CSIDL_PROGRAMS
, NULL
, IDS_SHORT_DOWNLOADER
, _T("%SystemRoot%\\system32\\downloader.exe"), IDS_CMT_DOWNLOADER
, TRUE
);
666 /* Create administrative tools startmenu shortcuts */
667 CreateShortcut(CSIDL_COMMON_ADMINTOOLS
, NULL
, IDS_SHORT_SERVICE
, _T("%SystemRoot%\\system32\\servman.exe"), IDS_CMT_SERVMAN
, FALSE
);
668 CreateShortcut(CSIDL_COMMON_ADMINTOOLS
, NULL
, IDS_SHORT_DEVICE
, _T("%SystemRoot%\\system32\\devmgmt.exe"), IDS_CMT_DEVMGMT
, FALSE
);
670 /* Create and fill Accessories subfolder */
671 if (CreateShortcutFolder(CSIDL_PROGRAMS
, IDS_ACCESSORIES
, szFolder
, sizeof(szFolder
)/sizeof(szFolder
[0])))
673 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_CALC
, _T("%SystemRoot%\\system32\\calc.exe"), IDS_CMT_CALC
, FALSE
);
674 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_CMD
, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD
, FALSE
);
675 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_NOTEPAD
, _T("%SystemRoot%\\system32\\notepad.exe"), IDS_CMT_NOTEPAD
, FALSE
);
676 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_REGEDIT
, _T("%SystemRoot%\\regedit.exe"), IDS_CMT_REGEDIT
, FALSE
);
677 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_WORDPAD
, _T("%SystemRoot%\\system32\\wordpad.exe"), IDS_CMT_WORDPAD
, FALSE
);
678 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_SNAP
, _T("%SystemRoot%\\system32\\screenshot.exe"), IDS_CMT_SCREENSHOT
, TRUE
);
681 /* Creacte System Tools subfolder and fill if the exe is available */
682 if (CreateShortcutFolder(CSIDL_PROGRAMS
, IDS_SYS_TOOLS
, szFolder
, sizeof(szFolder
)/sizeof(szFolder
[0])))
684 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_CHARMAP
, _T("%SystemRoot%\\system32\\charmap.exe"), IDS_CMT_CHARMAP
, FALSE
);
687 /* Creacte Accessibility subfolder and fill if the exe is available */
688 if (CreateShortcutFolder(CSIDL_PROGRAMS
, IDS_SYS_ACCESSIBILITY
, szFolder
, sizeof(szFolder
)/sizeof(szFolder
[0])))
690 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_MAGNIFY
, _T("%SystemRoot%\\system32\\magnify.exe"), IDS_CMT_MAGNIFY
, FALSE
);
693 /* Create Games subfolder and fill if the exe is available */
694 if (CreateShortcutFolder(CSIDL_PROGRAMS
, IDS_GAMES
, szFolder
, sizeof(szFolder
)/sizeof(szFolder
[0])))
696 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_SOLITAIRE
, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE
, FALSE
);
697 CreateShortcut(CSIDL_PROGRAMS
, szFolder
, IDS_SHORT_WINEMINE
, _T("%SystemRoot%\\system32\\winemine.exe"), IDS_CMT_WINEMINE
, FALSE
);
706 SetSetupType(DWORD dwSetupType
)
711 dwError
= RegOpenKeyExW(
717 if (dwError
!= ERROR_SUCCESS
)
720 dwError
= RegSetValueExW(
725 (LPBYTE
)&dwSetupType
,
728 if (dwError
!= ERROR_SUCCESS
)
735 InstallReactOS(HINSTANCE hInstance
)
737 TCHAR szBuffer
[MAX_PATH
];
740 TOKEN_PRIVILEGES privs
;
742 InitializeSetupActionLog(FALSE
);
743 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS");
745 /* Set user langage to the system language */
746 SetUserDefaultLCID(GetSystemDefaultLCID());
747 SetThreadLocale(GetSystemDefaultLCID());
749 if (!InitializeProfiles())
751 DebugPrint("InitializeProfiles() failed");
755 if (!CreateShortcuts())
757 DebugPrint("InitializeProfiles() failed");
761 /* Initialize the Security Account Manager (SAM) */
762 if (!SamInitializeSAM())
764 DebugPrint("SamInitializeSAM() failed!");
768 /* Create the semi-random Domain-SID */
769 if (!CreateRandomSid(&DomainSid
))
771 DebugPrint("Domain-SID creation failed!");
775 /* Set the Domain SID (aka Computer SID) */
776 if (!SamSetDomainSid(DomainSid
))
778 DebugPrint("SamSetDomainSid() failed!");
779 RtlFreeSid(DomainSid
);
783 /* Append the Admin-RID */
784 AppendRidToSid(&AdminSid
, DomainSid
, DOMAIN_USER_RID_ADMIN
);
786 /* Create the Administrator account */
787 if (!SamCreateUser(L
"Administrator", L
"", AdminSid
))
789 /* Check what the error was.
790 * If the Admin Account already exists, then it means Setup
791 * wasn't allowed to finish properly. Instead of rebooting
792 * and not completing it, let it restart instead
794 LastError
= GetLastError();
795 if (LastError
!= ERROR_USER_EXISTS
)
797 DebugPrint("SamCreateUser() failed!");
798 RtlFreeSid(AdminSid
);
799 RtlFreeSid(DomainSid
);
804 RtlFreeSid(AdminSid
);
805 RtlFreeSid(DomainSid
);
807 /* ROS HACK, as long as NtUnloadKey is not implemented */
809 NTSTATUS Status
= NtUnloadKey(NULL
);
810 if (Status
== STATUS_NOT_IMPLEMENTED
)
812 /* Create the Administrator profile */
813 PROFILEINFOW ProfileInfo
;
816 #define LOGON32_LOGON_NETWORK 3
817 ret
= LogonUserW(L
"Administrator", L
"", L
"", LOGON32_LOGON_NETWORK
, LOGON32_PROVIDER_DEFAULT
, &hToken
);
820 DebugPrint("LogonUserW() failed!");
823 ZeroMemory(&ProfileInfo
, sizeof(PROFILEINFOW
));
824 ProfileInfo
.dwSize
= sizeof(PROFILEINFOW
);
825 ProfileInfo
.lpUserName
= L
"Administrator";
826 ProfileInfo
.dwFlags
= PI_NOUI
;
827 LoadUserProfileW(hToken
, &ProfileInfo
);
832 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
835 /* END OF ROS HACK */
837 CreateTempDir(L
"TEMP");
838 CreateTempDir(L
"TMP");
840 if (GetWindowsDirectory(szBuffer
, sizeof(szBuffer
) / sizeof(TCHAR
)))
842 PathAddBackslash(szBuffer
);
843 _tcscat(szBuffer
, _T("system"));
844 CreateDirectory(szBuffer
, NULL
);
847 if (!CommonInstall())
852 SetupCloseInfFile(hSysSetupInf
);
855 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS done");
856 TerminateSetupActionLog();
858 /* Get shutdown privilege */
859 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &token
))
861 DebugPrint("OpenProcessToken() failed!");
864 if (!LookupPrivilegeValue(
867 &privs
.Privileges
[0].Luid
))
869 DebugPrint("LookupPrivilegeValue() failed!");
872 privs
.PrivilegeCount
= 1;
873 privs
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
874 if (AdjustTokenPrivileges(
879 (PTOKEN_PRIVILEGES
)NULL
,
882 DebugPrint("AdjustTokenPrivileges() failed!");
886 if (SetupData
.BootCDRegtestActive
)
888 /// THE FOLLOWING DPRINT IS FOR THE SYSTEM REGRESSION TOOL
890 DbgPrint("SYSREG_CHECKPOINT:SYSSETUP_COMPLETE\n");
893 ExitWindowsEx(EWX_REBOOT
, 0);
904 IN LPCWSTR lpszFontSize
)
906 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);