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 along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * PURPOSE: System setup
23 * FILE: dll/win32/syssetup/install.c
24 * PROGRAMER: Eric Kohl
27 /* INCLUDES *****************************************************************/
37 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout
);
39 /* GLOBALS ******************************************************************/
41 HINF hSysSetupInf
= INVALID_HANDLE_VALUE
;
44 /* FUNCTIONS ****************************************************************/
47 FatalError(char *pszFmt
,...)
53 vsprintf(szBuffer
, pszFmt
, ap
);
56 LogItem(SYSSETUP_SEVERITY_FATAL_ERROR
, L
"Failed");
58 strcat(szBuffer
, "\nRebooting now!");
78 WCHAR wszBuf
[MAX_PATH
];
81 HRESULT hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLink
, (LPVOID
*)&psl
);
85 hr
= psl
->lpVtbl
->SetPath(psl
, pszCmd
);
89 hr
= psl
->lpVtbl
->SetArguments(psl
, pszArg
);
94 hr
= psl
->lpVtbl
->SetWorkingDirectory(psl
, pszDir
);
99 hr
= psl
->lpVtbl
->SetIconLocation(psl
, pszIconPath
, iIconNr
);
104 hr
= psl
->lpVtbl
->SetDescription(psl
, pszComment
);
107 hr
= psl
->lpVtbl
->QueryInterface(psl
, &IID_IPersistFile
, (LPVOID
*)&ppf
);
112 hr
= ppf
->lpVtbl
->Save(ppf
, pszLinkPath
, TRUE
);
114 MultiByteToWideChar(CP_ACP
, 0, pszLinkPath
, -1, wszBuf
, MAX_PATH
);
116 hr
= ppf
->lpVtbl
->Save(ppf
, wszBuf
, TRUE
);
117 #endif /* _UNICODE */
119 ppf
->lpVtbl
->Release(ppf
);
122 psl
->lpVtbl
->Release(psl
);
134 LPCTSTR pszDescription
,
137 TCHAR szPath
[MAX_PATH
];
138 TCHAR szExeName
[MAX_PATH
];
140 TCHAR szWorkingDirBuf
[MAX_PATH
];
141 LPTSTR pszWorkingDir
= NULL
;
145 if (ExpandEnvironmentStrings(pszCommand
,
147 sizeof(szPath
) / sizeof(szPath
[0])) == 0)
149 _tcscpy(szPath
, pszCommand
);
152 if ((_taccess(szPath
, 0 )) == -1)
153 /* Expected error, don't return FALSE */
156 dwLen
= GetFullPathName(szPath
,
157 sizeof(szWorkingDirBuf
) / sizeof(szWorkingDirBuf
[0]),
160 if (dwLen
!= 0 && dwLen
<= sizeof(szWorkingDirBuf
) / sizeof(szWorkingDirBuf
[0]))
162 /* Since those should only be called with (.exe) files,
163 lpFilePart has not to be NULL */
164 ASSERT(lpFilePart
!= NULL
);
166 /* Save the file name */
167 _tcscpy(szExeName
, lpFilePart
);
169 /* We're only interested in the path. Cut the file name off.
170 Also remove the trailing backslash unless the working directory
171 is only going to be a drive, ie. C:\ */
172 *(lpFilePart
--) = _T('\0');
173 if (!(lpFilePart
- szWorkingDirBuf
== 2 && szWorkingDirBuf
[1] == _T(':') &&
174 szWorkingDirBuf
[2] == _T('\\')))
176 *lpFilePart
= _T('\0');
179 pszWorkingDir
= szWorkingDirBuf
;
182 _tcscpy(szPath
, pszFolder
);
184 Ptr
= PathAddBackslash(szPath
);
186 _tcscpy(Ptr
, pszName
);
188 // FIXME: we should pass 'command' straight in here, but shell32 doesn't expand it
189 return SUCCEEDED(CreateShellLink(szPath
, szExeName
, _T(""), pszWorkingDir
, szExeName
, iIconNr
, pszDescription
));
193 static BOOL
CreateShortcutsFromSection(HINF hinf
, LPWSTR pszSection
, LPCWSTR pszFolder
)
196 WCHAR szCommand
[MAX_PATH
];
197 WCHAR szName
[MAX_PATH
];
198 WCHAR szDescription
[MAX_PATH
];
201 if (!SetupFindFirstLine(hinf
, pszSection
, NULL
, &Context
))
206 if (SetupGetFieldCount(&Context
) < 4)
209 if (!SetupGetStringFieldW(&Context
, 1, szCommand
, MAX_PATH
, NULL
))
212 if (!SetupGetStringFieldW(&Context
, 2, szName
, MAX_PATH
, NULL
))
215 if (!SetupGetStringFieldW(&Context
, 3, szDescription
, MAX_PATH
, NULL
))
218 if (!SetupGetIntField(&Context
, 4, &iIconNr
))
221 _tcscat(szName
, L
".lnk");
223 CreateShortcut(pszFolder
, szName
, szCommand
, szDescription
, iIconNr
);
225 }while (SetupFindNextLine(&Context
, &Context
));
230 static BOOL
CreateShortcuts(HINF hinf
, LPCWSTR szSection
)
233 WCHAR szPath
[MAX_PATH
];
234 WCHAR szFolder
[MAX_PATH
];
235 WCHAR szFolderSection
[MAX_PATH
];
241 if (!SetupFindFirstLine(hinf
, szSection
, NULL
, &Context
))
246 if (SetupGetFieldCount(&Context
) < 2)
249 if (!SetupGetStringFieldW(&Context
, 0, szFolderSection
, MAX_PATH
, NULL
))
252 if (!SetupGetIntField(&Context
, 1, &csidl
))
255 if (!SetupGetStringFieldW(&Context
, 2, szFolder
, MAX_PATH
, NULL
))
258 if (!SHGetSpecialFolderPathW(0, szPath
, csidl
, TRUE
))
261 p
= PathAddBackslash(szPath
);
262 _tcscpy(p
, szFolder
);
264 if (!CreateDirectory(szPath
, NULL
))
266 if (GetLastError() != ERROR_ALREADY_EXISTS
)
272 CreateShortcutsFromSection(hinf
, szFolderSection
, szPath
);
274 }while (SetupFindNextLine(&Context
, &Context
));
285 WCHAR szTempDir
[MAX_PATH
];
286 WCHAR szBuffer
[MAX_PATH
];
290 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
291 L
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
294 &hKey
) != ERROR_SUCCESS
)
296 FatalError("Error: %lu\n", GetLastError());
301 dwLength
= MAX_PATH
* sizeof(WCHAR
);
302 if (RegQueryValueExW(hKey
,
307 &dwLength
) != ERROR_SUCCESS
)
309 FatalError("Error: %lu\n", GetLastError());
314 if (!ExpandEnvironmentStringsW(szBuffer
,
318 FatalError("Error: %lu\n", GetLastError());
322 /* Create profiles directory */
323 if (!CreateDirectoryW(szTempDir
, NULL
))
325 if (GetLastError() != ERROR_ALREADY_EXISTS
)
327 FatalError("Error: %lu\n", GetLastError());
337 InstallSysSetupInfDevices(VOID
)
339 INFCONTEXT InfContext
;
340 WCHAR szLineBuffer
[256];
343 if (!SetupFindFirstLineW(hSysSetupInf
,
344 L
"DeviceInfsToInstall",
353 if (!SetupGetStringFieldW(&InfContext
,
356 sizeof(szLineBuffer
)/sizeof(szLineBuffer
[0]),
362 if (!SetupDiInstallClassW(NULL
, szLineBuffer
, DI_QUIETINSTALL
, NULL
))
367 while (SetupFindNextLine(&InfContext
, &InfContext
));
373 InstallSysSetupInfComponents(VOID
)
375 INFCONTEXT InfContext
;
376 WCHAR szNameBuffer
[256];
377 WCHAR szSectionBuffer
[256];
378 HINF hComponentInf
= INVALID_HANDLE_VALUE
;
380 if (!SetupFindFirstLineW(hSysSetupInf
,
385 DPRINT("No Inf.Always section found\n");
391 if (!SetupGetStringFieldW(&InfContext
,
392 1, // Get the component name
394 sizeof(szNameBuffer
)/sizeof(szNameBuffer
[0]),
397 FatalError("Error while trying to get component name \n");
401 if (!SetupGetStringFieldW(&InfContext
,
402 2, // Get the component install section
404 sizeof(szSectionBuffer
)/sizeof(szSectionBuffer
[0]),
407 FatalError("Error while trying to get component install section \n");
411 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer
, szNameBuffer
);
413 hComponentInf
= SetupOpenInfFileW(szNameBuffer
,
418 if (hComponentInf
== INVALID_HANDLE_VALUE
)
420 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer
, GetLastError());
424 if (!SetupInstallFromInfSectionW(NULL
,
431 SetupDefaultQueueCallbackW
,
436 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer
, GetLastError());
437 SetupCloseInfFile(hComponentInf
);
441 SetupCloseInfFile(hComponentInf
);
443 while (SetupFindNextLine(&InfContext
, &InfContext
));
453 RegisterTypeLibraries (HINF hinf
, LPCWSTR szSection
)
455 INFCONTEXT InfContext
;
457 WCHAR szName
[MAX_PATH
];
458 WCHAR szPath
[MAX_PATH
];
464 /* Begin iterating the entries in the inf section */
465 res
= SetupFindFirstLine(hinf
, szSection
, NULL
, &InfContext
);
466 if (!res
) return FALSE
;
470 /* Get the name of the current type library */
471 if (!SetupGetStringFieldW(&InfContext
, 1, szName
, MAX_PATH
, NULL
))
473 FatalError("SetupGetStringFieldW failed\n");
477 if (!SetupGetIntField(&InfContext
, 2, &csidl
))
478 csidl
= CSIDL_SYSTEM
;
480 hret
= SHGetFolderPathW(NULL
, csidl
, NULL
, 0, szPath
);
483 FatalError("SHGetSpecialFolderPathW failed hret=0x%d\n", hret
);
487 p
= PathAddBackslash(szPath
);
490 hmod
= LoadLibraryW(szName
);
493 FatalError("LoadLibraryW failed\n");
497 __wine_register_resources(hmod
);
499 }while (SetupFindNextLine(&InfContext
, &InfContext
));
505 EnableUserModePnpManager(VOID
)
507 SC_HANDLE hSCManager
= NULL
;
508 SC_HANDLE hService
= NULL
;
511 hSCManager
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
512 if (hSCManager
== NULL
)
514 DPRINT1("Unable to open the service control manager.\n");
515 DPRINT1("Last Error %d\n", GetLastError());
519 hService
= OpenServiceW(hSCManager
,
521 SERVICE_CHANGE_CONFIG
| SERVICE_START
);
522 if (hService
== NULL
)
524 DPRINT1("Unable to open PlugPlay service\n");
528 bRet
= ChangeServiceConfigW(hService
,
533 NULL
, NULL
, NULL
, NULL
);
536 DPRINT1("Unable to change the service configuration\n");
540 bRet
= StartServiceW(hService
, 0, NULL
);
541 if (!bRet
&& (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING
))
543 DPRINT1("Unable to start service\n");
550 if (hService
!= NULL
)
551 CloseServiceHandle(hService
);
552 if (hSCManager
!= NULL
)
553 CloseServiceHandle(hSCManager
);
557 static INT_PTR CALLBACK
558 StatusMessageWindowProc(
564 UNREFERENCED_PARAMETER(wParam
);
572 if (!LoadStringW(hDllInstance
, IDS_STATUS_INSTALL_DEV
, szMsg
, sizeof(szMsg
)/sizeof(szMsg
[0])))
574 SetDlgItemTextW(hwndDlg
, IDC_STATUSLABEL
, szMsg
);
582 ShowStatusMessageThread(
583 IN LPVOID lpParameter
)
585 HWND
*phWnd
= (HWND
*)lpParameter
;
589 hWnd
= CreateDialogParam(
591 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG
),
593 StatusMessageWindowProc
,
599 ShowWindow(hWnd
, SW_SHOW
);
601 /* Message loop for the Status window */
602 while (GetMessage(&Msg
, NULL
, 0, 0))
604 TranslateMessage(&Msg
);
605 DispatchMessage(&Msg
);
623 return ERROR_INVALID_PARAMETER
;
626 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
627 if (rc
!= ERROR_SUCCESS
)
629 if (dwType
!= REG_SZ
)
630 return ERROR_FILE_NOT_FOUND
;
631 pwszValue
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
633 return ERROR_NOT_ENOUGH_MEMORY
;
634 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)pwszValue
, &cbData
);
635 if (rc
!= ERROR_SUCCESS
)
637 HeapFree(GetProcessHeap(), 0, pwszValue
);
640 /* NULL-terminate the string */
641 pwszValue
[cbData
/ sizeof(WCHAR
)] = '\0';
644 return ERROR_SUCCESS
;
650 HKEY hControlKey
= NULL
;
651 LPWSTR pwszSystemStartOptions
= NULL
;
652 LPWSTR pwszCurrentOption
, pwszNextOption
; /* Pointers into SystemStartOptions */
653 BOOL bConsoleBoot
= FALSE
;
658 L
"SYSTEM\\CurrentControlSet\\Control",
662 if (rc
!= ERROR_SUCCESS
)
665 rc
= ReadRegSzKey(hControlKey
, L
"SystemStartOptions", &pwszSystemStartOptions
);
666 if (rc
!= ERROR_SUCCESS
)
669 /* Check for CONSOLE switch in SystemStartOptions */
670 pwszCurrentOption
= pwszSystemStartOptions
;
671 while (pwszCurrentOption
)
673 pwszNextOption
= wcschr(pwszCurrentOption
, L
' ');
675 *pwszNextOption
= L
'\0';
676 if (wcsicmp(pwszCurrentOption
, L
"CONSOLE") == 0)
678 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption
);
682 pwszCurrentOption
= pwszNextOption
? pwszNextOption
+ 1 : NULL
;
686 if (hControlKey
!= NULL
)
687 RegCloseKey(hControlKey
);
688 if (pwszSystemStartOptions
)
689 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions
);
698 hSysSetupInf
= SetupOpenInfFileW(
703 if (hSysSetupInf
== INVALID_HANDLE_VALUE
)
705 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
709 if (!InstallSysSetupInfDevices())
711 FatalError("InstallSysSetupInfDevices() failed!\n");
715 if(!InstallSysSetupInfComponents())
717 FatalError("InstallSysSetupInfComponents() failed!\n");
721 if (!IsConsoleBoot())
725 hThread
= CreateThread(
728 ShowStatusMessageThread
,
734 CloseHandle(hThread
);
737 if (!EnableUserModePnpManager())
739 FatalError("EnableUserModePnpManager() failed!\n");
743 if (CMP_WaitNoPendingInstallEvents(INFINITE
) != WAIT_OBJECT_0
)
745 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
755 SetupCloseInfFile(hSysSetupInf
);
760 InstallLiveCD(IN HINSTANCE hInstance
)
762 STARTUPINFOW StartupInfo
;
763 PROCESS_INFORMATION ProcessInformation
;
766 if (!CommonInstall())
769 /* Register components */
772 if (!SetupInstallFromInfSectionW(NULL
,
773 hSysSetupInf
, L
"RegistrationPhase2",
775 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
))
777 DPRINT1("SetupInstallFromInfSectionW failed!\n");
780 RegisterTypeLibraries(hSysSetupInf
, L
"TypeLibraries");
782 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
784 DPRINT1("Catching exception\n");
788 SetupCloseInfFile(hSysSetupInf
);
791 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
792 StartupInfo
.cb
= sizeof(StartupInfo
);
793 bRes
= CreateProcessW(
803 &ProcessInformation
);
807 CloseHandle(ProcessInformation
.hThread
);
808 CloseHandle(ProcessInformation
.hProcess
);
815 L
"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
823 SetSetupType(DWORD dwSetupType
)
828 dwError
= RegOpenKeyExW(
834 if (dwError
!= ERROR_SUCCESS
)
837 dwError
= RegSetValueExW(
842 (LPBYTE
)&dwSetupType
,
845 if (dwError
!= ERROR_SUCCESS
)
852 InstallReactOS(HINSTANCE hInstance
)
854 TCHAR szBuffer
[MAX_PATH
];
856 TOKEN_PRIVILEGES privs
;
860 InitializeSetupActionLog(FALSE
);
861 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS");
863 if (!InitializeProfiles())
865 FatalError("InitializeProfiles() failed");
869 CreateTempDir(L
"TEMP");
870 CreateTempDir(L
"TMP");
872 if (GetWindowsDirectory(szBuffer
, sizeof(szBuffer
) / sizeof(TCHAR
)))
874 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
875 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
878 &hKey
) == ERROR_SUCCESS
)
885 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
892 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
897 PathAddBackslash(szBuffer
);
898 _tcscat(szBuffer
, _T("system"));
899 CreateDirectory(szBuffer
, NULL
);
902 if (!CommonInstall())
911 hShortcutsInf
= SetupOpenInfFileW(L
"shortcuts.inf",
915 if (hShortcutsInf
== INVALID_HANDLE_VALUE
)
917 FatalError("Failed to open shortcuts.inf");
921 if (!CreateShortcuts(hShortcutsInf
, L
"ShortcutFolders"))
923 FatalError("CreateShortcuts() failed");
927 SetupCloseInfFile(hShortcutsInf
);
929 /* ROS HACK, as long as NtUnloadKey is not implemented */
931 NTSTATUS Status
= NtUnloadKey(NULL
);
932 if (Status
== STATUS_NOT_IMPLEMENTED
)
934 /* Create the Administrator profile */
935 PROFILEINFOW ProfileInfo
;
939 ret
= LogonUserW(AdminInfo
.Name
,
942 LOGON32_LOGON_INTERACTIVE
,
943 LOGON32_PROVIDER_DEFAULT
,
947 FatalError("LogonUserW() failed!");
950 ZeroMemory(&ProfileInfo
, sizeof(PROFILEINFOW
));
951 ProfileInfo
.dwSize
= sizeof(PROFILEINFOW
);
952 ProfileInfo
.lpUserName
= L
"Administrator";
953 ProfileInfo
.dwFlags
= PI_NOUI
;
954 LoadUserProfileW(hToken
, &ProfileInfo
);
959 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
962 /* END OF ROS HACK */
964 SetupCloseInfFile(hSysSetupInf
);
967 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS done");
968 TerminateSetupActionLog();
970 if (AdminInfo
.Name
!= NULL
)
971 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Name
);
973 if (AdminInfo
.Domain
!= NULL
)
974 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Domain
);
976 if (AdminInfo
.Password
!= NULL
)
977 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Password
);
979 /* Get shutdown privilege */
980 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &token
))
982 FatalError("OpenProcessToken() failed!");
985 if (!LookupPrivilegeValue(
988 &privs
.Privileges
[0].Luid
))
990 FatalError("LookupPrivilegeValue() failed!");
993 privs
.PrivilegeCount
= 1;
994 privs
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
995 if (AdjustTokenPrivileges(
1000 (PTOKEN_PRIVILEGES
)NULL
,
1003 FatalError("AdjustTokenPrivileges() failed!");
1007 ExitWindowsEx(EWX_REBOOT
, 0);
1016 SetupChangeFontSize(
1018 IN LPCWSTR lpszFontSize
)
1020 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1028 SetupChangeLocaleEx(HWND hWnd
,
1030 LPCWSTR lpSrcRootPath
,
1035 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1043 SetupChangeLocale(HWND hWnd
, LCID Lcid
)
1045 return SetupChangeLocaleEx(hWnd
, Lcid
, NULL
, 0, 0, 0);