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
;
43 /* FUNCTIONS ****************************************************************/
46 FatalError(char *pszFmt
,...)
52 vsprintf(szBuffer
, pszFmt
, ap
);
55 LogItem(SYSSETUP_SEVERITY_FATAL_ERROR
, L
"Failed");
57 strcat(szBuffer
, "\nRebooting now!");
77 WCHAR wszBuf
[MAX_PATH
];
80 HRESULT hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLink
, (LPVOID
*)&psl
);
84 hr
= psl
->lpVtbl
->SetPath(psl
, pszCmd
);
88 hr
= psl
->lpVtbl
->SetArguments(psl
, pszArg
);
93 hr
= psl
->lpVtbl
->SetWorkingDirectory(psl
, pszDir
);
98 hr
= psl
->lpVtbl
->SetIconLocation(psl
, pszIconPath
, iIconNr
);
103 hr
= psl
->lpVtbl
->SetDescription(psl
, pszComment
);
106 hr
= psl
->lpVtbl
->QueryInterface(psl
, &IID_IPersistFile
, (LPVOID
*)&ppf
);
111 hr
= ppf
->lpVtbl
->Save(ppf
, pszLinkPath
, TRUE
);
113 MultiByteToWideChar(CP_ACP
, 0, pszLinkPath
, -1, wszBuf
, MAX_PATH
);
115 hr
= ppf
->lpVtbl
->Save(ppf
, wszBuf
, TRUE
);
116 #endif /* _UNICODE */
118 ppf
->lpVtbl
->Release(ppf
);
121 psl
->lpVtbl
->Release(psl
);
133 LPCTSTR pszDescription
,
136 TCHAR szPath
[MAX_PATH
];
137 TCHAR szExeName
[MAX_PATH
];
139 TCHAR szWorkingDirBuf
[MAX_PATH
];
140 LPTSTR pszWorkingDir
= NULL
;
144 if (ExpandEnvironmentStrings(pszCommand
,
146 sizeof(szPath
) / sizeof(szPath
[0])) == 0)
148 _tcscpy(szPath
, pszCommand
);
151 if ((_taccess(szPath
, 0 )) == -1)
152 /* Expected error, don't return FALSE */
155 dwLen
= GetFullPathName(szPath
,
156 sizeof(szWorkingDirBuf
) / sizeof(szWorkingDirBuf
[0]),
159 if (dwLen
!= 0 && dwLen
<= sizeof(szWorkingDirBuf
) / sizeof(szWorkingDirBuf
[0]))
161 /* Since those should only be called with (.exe) files,
162 lpFilePart has not to be NULL */
163 ASSERT(lpFilePart
!= NULL
);
165 /* Save the file name */
166 _tcscpy(szExeName
, lpFilePart
);
168 /* We're only interested in the path. Cut the file name off.
169 Also remove the trailing backslash unless the working directory
170 is only going to be a drive, ie. C:\ */
171 *(lpFilePart
--) = _T('\0');
172 if (!(lpFilePart
- szWorkingDirBuf
== 2 && szWorkingDirBuf
[1] == _T(':') &&
173 szWorkingDirBuf
[2] == _T('\\')))
175 *lpFilePart
= _T('\0');
178 pszWorkingDir
= szWorkingDirBuf
;
181 _tcscpy(szPath
, pszFolder
);
183 Ptr
= PathAddBackslash(szPath
);
185 _tcscpy(Ptr
, pszName
);
187 // FIXME: we should pass 'command' straight in here, but shell32 doesn't expand it
188 return SUCCEEDED(CreateShellLink(szPath
, szExeName
, _T(""), pszWorkingDir
, szExeName
, iIconNr
, pszDescription
));
192 static BOOL
CreateShortcutsFromSection(HINF hinf
, LPWSTR pszSection
, LPCWSTR pszFolder
)
195 WCHAR szCommand
[MAX_PATH
];
196 WCHAR szName
[MAX_PATH
];
197 WCHAR szDescription
[MAX_PATH
];
200 if (!SetupFindFirstLine(hinf
, pszSection
, NULL
, &Context
))
205 if (SetupGetFieldCount(&Context
) < 4)
208 if (!SetupGetStringFieldW(&Context
, 1, szCommand
, MAX_PATH
, NULL
))
211 if (!SetupGetStringFieldW(&Context
, 2, szName
, MAX_PATH
, NULL
))
214 if (!SetupGetStringFieldW(&Context
, 3, szDescription
, MAX_PATH
, NULL
))
217 if (!SetupGetIntField(&Context
, 4, &iIconNr
))
220 _tcscat(szName
, L
".lnk");
222 CreateShortcut(pszFolder
, szName
, szCommand
, szDescription
, iIconNr
);
224 }while (SetupFindNextLine(&Context
, &Context
));
229 static BOOL
CreateShortcuts(HINF hinf
, LPCWSTR szSection
)
232 WCHAR szPath
[MAX_PATH
];
233 WCHAR szFolder
[MAX_PATH
];
234 WCHAR szFolderSection
[MAX_PATH
];
240 if (!SetupFindFirstLine(hinf
, szSection
, NULL
, &Context
))
245 if (SetupGetFieldCount(&Context
) < 2)
248 if (!SetupGetStringFieldW(&Context
, 0, szFolderSection
, MAX_PATH
, NULL
))
251 if (!SetupGetIntField(&Context
, 1, &csidl
))
254 if (!SetupGetStringFieldW(&Context
, 2, szFolder
, MAX_PATH
, NULL
))
257 if (!SHGetSpecialFolderPathW(0, szPath
, csidl
, TRUE
))
260 p
= PathAddBackslash(szPath
);
261 _tcscpy(p
, szFolder
);
263 if (!CreateDirectory(szPath
, NULL
))
265 if (GetLastError() != ERROR_ALREADY_EXISTS
)
271 CreateShortcutsFromSection(hinf
, szFolderSection
, szPath
);
273 }while (SetupFindNextLine(&Context
, &Context
));
284 WCHAR szTempDir
[MAX_PATH
];
285 WCHAR szBuffer
[MAX_PATH
];
289 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
290 L
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
293 &hKey
) != ERROR_SUCCESS
)
295 FatalError("Error: %lu\n", GetLastError());
300 dwLength
= MAX_PATH
* sizeof(WCHAR
);
301 if (RegQueryValueExW(hKey
,
306 &dwLength
) != ERROR_SUCCESS
)
308 FatalError("Error: %lu\n", GetLastError());
313 if (!ExpandEnvironmentStringsW(szBuffer
,
317 FatalError("Error: %lu\n", GetLastError());
321 /* Create profiles directory */
322 if (!CreateDirectoryW(szTempDir
, NULL
))
324 if (GetLastError() != ERROR_ALREADY_EXISTS
)
326 FatalError("Error: %lu\n", GetLastError());
336 InstallSysSetupInfDevices(VOID
)
338 INFCONTEXT InfContext
;
339 WCHAR szLineBuffer
[256];
342 if (!SetupFindFirstLineW(hSysSetupInf
,
343 L
"DeviceInfsToInstall",
352 if (!SetupGetStringFieldW(&InfContext
,
355 sizeof(szLineBuffer
)/sizeof(szLineBuffer
[0]),
361 if (!SetupDiInstallClassW(NULL
, szLineBuffer
, DI_QUIETINSTALL
, NULL
))
366 while (SetupFindNextLine(&InfContext
, &InfContext
));
372 InstallSysSetupInfComponents(VOID
)
374 INFCONTEXT InfContext
;
375 WCHAR szNameBuffer
[256];
376 WCHAR szSectionBuffer
[256];
377 HINF hComponentInf
= INVALID_HANDLE_VALUE
;
379 if (!SetupFindFirstLineW(hSysSetupInf
,
384 DPRINT("No Inf.Always section found\n");
390 if (!SetupGetStringFieldW(&InfContext
,
391 1, // Get the component name
393 sizeof(szNameBuffer
)/sizeof(szNameBuffer
[0]),
396 FatalError("Error while trying to get component name \n");
400 if (!SetupGetStringFieldW(&InfContext
,
401 2, // Get the component install section
403 sizeof(szSectionBuffer
)/sizeof(szSectionBuffer
[0]),
406 FatalError("Error while trying to get component install section \n");
410 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer
, szNameBuffer
);
412 hComponentInf
= SetupOpenInfFileW(szNameBuffer
,
417 if (hComponentInf
== INVALID_HANDLE_VALUE
)
419 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer
, GetLastError());
423 if (!SetupInstallFromInfSectionW(NULL
,
430 SetupDefaultQueueCallbackW
,
435 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer
, GetLastError());
436 SetupCloseInfFile(hComponentInf
);
440 SetupCloseInfFile(hComponentInf
);
442 while (SetupFindNextLine(&InfContext
, &InfContext
));
452 RegisterTypeLibraries (HINF hinf
, LPCWSTR szSection
)
454 INFCONTEXT InfContext
;
456 WCHAR szName
[MAX_PATH
];
457 WCHAR szPath
[MAX_PATH
];
463 /* Begin iterating the entries in the inf section */
464 res
= SetupFindFirstLine(hinf
, szSection
, NULL
, &InfContext
);
465 if (!res
) return FALSE
;
469 /* Get the name of the current type library */
470 if (!SetupGetStringFieldW(&InfContext
, 1, szName
, MAX_PATH
, NULL
))
472 FatalError("SetupGetStringFieldW failed\n");
476 if (!SetupGetIntField(&InfContext
, 2, &csidl
))
477 csidl
= CSIDL_SYSTEM
;
479 hret
= SHGetFolderPathW(NULL
, csidl
, NULL
, 0, szPath
);
482 FatalError("SHGetSpecialFolderPathW failed hret=0x%d\n", hret
);
486 p
= PathAddBackslash(szPath
);
489 hmod
= LoadLibraryW(szName
);
492 FatalError("LoadLibraryW failed\n");
496 __wine_register_resources(hmod
);
498 }while (SetupFindNextLine(&InfContext
, &InfContext
));
504 EnableUserModePnpManager(VOID
)
506 SC_HANDLE hSCManager
= NULL
;
507 SC_HANDLE hService
= NULL
;
510 hSCManager
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
511 if (hSCManager
== NULL
)
513 DPRINT1("Unable to open the service control manager.\n");
514 DPRINT1("Last Error %d\n", GetLastError());
518 hService
= OpenServiceW(hSCManager
,
520 SERVICE_CHANGE_CONFIG
| SERVICE_START
);
521 if (hService
== NULL
)
523 DPRINT1("Unable to open PlugPlay service\n");
527 bRet
= ChangeServiceConfigW(hService
,
532 NULL
, NULL
, NULL
, NULL
);
535 DPRINT1("Unable to change the service configuration\n");
539 bRet
= StartServiceW(hService
, 0, NULL
);
540 if (!bRet
&& (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING
))
542 DPRINT1("Unable to start service\n");
549 if (hService
!= NULL
)
550 CloseServiceHandle(hService
);
551 if (hSCManager
!= NULL
)
552 CloseServiceHandle(hSCManager
);
556 static INT_PTR CALLBACK
557 StatusMessageWindowProc(
563 UNREFERENCED_PARAMETER(wParam
);
571 if (!LoadStringW(hDllInstance
, IDS_STATUS_INSTALL_DEV
, szMsg
, sizeof(szMsg
)/sizeof(szMsg
[0])))
573 SetDlgItemTextW(hwndDlg
, IDC_STATUSLABEL
, szMsg
);
581 ShowStatusMessageThread(
582 IN LPVOID lpParameter
)
584 HWND
*phWnd
= (HWND
*)lpParameter
;
588 hWnd
= CreateDialogParam(
590 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG
),
592 StatusMessageWindowProc
,
598 ShowWindow(hWnd
, SW_SHOW
);
600 /* Message loop for the Status window */
601 while (GetMessage(&Msg
, NULL
, 0, 0))
603 TranslateMessage(&Msg
);
604 DispatchMessage(&Msg
);
622 return ERROR_INVALID_PARAMETER
;
625 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
626 if (rc
!= ERROR_SUCCESS
)
628 if (dwType
!= REG_SZ
)
629 return ERROR_FILE_NOT_FOUND
;
630 pwszValue
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
632 return ERROR_NOT_ENOUGH_MEMORY
;
633 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)pwszValue
, &cbData
);
634 if (rc
!= ERROR_SUCCESS
)
636 HeapFree(GetProcessHeap(), 0, pwszValue
);
639 /* NULL-terminate the string */
640 pwszValue
[cbData
/ sizeof(WCHAR
)] = '\0';
643 return ERROR_SUCCESS
;
649 HKEY hControlKey
= NULL
;
650 LPWSTR pwszSystemStartOptions
= NULL
;
651 LPWSTR pwszCurrentOption
, pwszNextOption
; /* Pointers into SystemStartOptions */
652 BOOL bConsoleBoot
= FALSE
;
657 L
"SYSTEM\\CurrentControlSet\\Control",
661 if (rc
!= ERROR_SUCCESS
)
664 rc
= ReadRegSzKey(hControlKey
, L
"SystemStartOptions", &pwszSystemStartOptions
);
665 if (rc
!= ERROR_SUCCESS
)
668 /* Check for CONSOLE switch in SystemStartOptions */
669 pwszCurrentOption
= pwszSystemStartOptions
;
670 while (pwszCurrentOption
)
672 pwszNextOption
= wcschr(pwszCurrentOption
, L
' ');
674 *pwszNextOption
= L
'\0';
675 if (wcsicmp(pwszCurrentOption
, L
"CONSOLE") == 0)
677 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption
);
681 pwszCurrentOption
= pwszNextOption
? pwszNextOption
+ 1 : NULL
;
685 if (hControlKey
!= NULL
)
686 RegCloseKey(hControlKey
);
687 if (pwszSystemStartOptions
)
688 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions
);
697 hSysSetupInf
= SetupOpenInfFileW(
702 if (hSysSetupInf
== INVALID_HANDLE_VALUE
)
704 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
708 if (!InstallSysSetupInfDevices())
710 FatalError("InstallSysSetupInfDevices() failed!\n");
714 if(!InstallSysSetupInfComponents())
716 FatalError("InstallSysSetupInfComponents() failed!\n");
720 if (!IsConsoleBoot())
724 hThread
= CreateThread(
727 ShowStatusMessageThread
,
733 CloseHandle(hThread
);
736 if (!EnableUserModePnpManager())
738 FatalError("EnableUserModePnpManager() failed!\n");
742 if (CMP_WaitNoPendingInstallEvents(INFINITE
) != WAIT_OBJECT_0
)
744 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
754 SetupCloseInfFile(hSysSetupInf
);
759 InstallLiveCD(IN HINSTANCE hInstance
)
761 STARTUPINFOW StartupInfo
;
762 PROCESS_INFORMATION ProcessInformation
;
765 if (!CommonInstall())
768 /* Register components */
771 if (!SetupInstallFromInfSectionW(NULL
,
772 hSysSetupInf
, L
"RegistrationPhase2",
774 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
))
776 DPRINT1("SetupInstallFromInfSectionW failed!\n");
779 RegisterTypeLibraries(hSysSetupInf
, L
"TypeLibraries");
781 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
783 DPRINT1("Catching exception\n");
787 SetupCloseInfFile(hSysSetupInf
);
790 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
791 StartupInfo
.cb
= sizeof(StartupInfo
);
792 bRes
= CreateProcessW(
802 &ProcessInformation
);
806 CloseHandle(ProcessInformation
.hThread
);
807 CloseHandle(ProcessInformation
.hProcess
);
814 L
"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
822 SetSetupType(DWORD dwSetupType
)
827 dwError
= RegOpenKeyExW(
833 if (dwError
!= ERROR_SUCCESS
)
836 dwError
= RegSetValueExW(
841 (LPBYTE
)&dwSetupType
,
844 if (dwError
!= ERROR_SUCCESS
)
851 InstallReactOS(HINSTANCE hInstance
)
853 TCHAR szBuffer
[MAX_PATH
];
855 TOKEN_PRIVILEGES privs
;
859 InitializeSetupActionLog(FALSE
);
860 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS");
862 if (!InitializeProfiles())
864 FatalError("InitializeProfiles() failed");
868 CreateTempDir(L
"TEMP");
869 CreateTempDir(L
"TMP");
871 if (GetWindowsDirectory(szBuffer
, sizeof(szBuffer
) / sizeof(TCHAR
)))
873 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
874 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
877 &hKey
) == ERROR_SUCCESS
)
884 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
891 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
896 PathAddBackslash(szBuffer
);
897 _tcscat(szBuffer
, _T("system"));
898 CreateDirectory(szBuffer
, NULL
);
901 if (!CommonInstall())
908 hShortcutsInf
= SetupOpenInfFileW(L
"shortcuts.inf",
912 if (hShortcutsInf
== INVALID_HANDLE_VALUE
)
914 FatalError("Failed to open shortcuts.inf");
918 if (!CreateShortcuts(hShortcutsInf
, L
"ShortcutFolders"))
920 FatalError("CreateShortcuts() failed");
924 SetupCloseInfFile(hShortcutsInf
);
926 /* ROS HACK, as long as NtUnloadKey is not implemented */
928 NTSTATUS Status
= NtUnloadKey(NULL
);
929 if (Status
== STATUS_NOT_IMPLEMENTED
)
931 /* Create the Administrator profile */
932 PROFILEINFOW ProfileInfo
;
936 ret
= LogonUserW(L
"Administrator", L
"", L
"", LOGON32_LOGON_INTERACTIVE
, LOGON32_PROVIDER_DEFAULT
, &hToken
);
939 FatalError("LogonUserW() failed!");
942 ZeroMemory(&ProfileInfo
, sizeof(PROFILEINFOW
));
943 ProfileInfo
.dwSize
= sizeof(PROFILEINFOW
);
944 ProfileInfo
.lpUserName
= L
"Administrator";
945 ProfileInfo
.dwFlags
= PI_NOUI
;
946 LoadUserProfileW(hToken
, &ProfileInfo
);
951 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
954 /* END OF ROS HACK */
956 SetupCloseInfFile(hSysSetupInf
);
959 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS done");
960 TerminateSetupActionLog();
962 /* Get shutdown privilege */
963 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &token
))
965 FatalError("OpenProcessToken() failed!");
968 if (!LookupPrivilegeValue(
971 &privs
.Privileges
[0].Luid
))
973 FatalError("LookupPrivilegeValue() failed!");
976 privs
.PrivilegeCount
= 1;
977 privs
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
978 if (AdjustTokenPrivileges(
983 (PTOKEN_PRIVILEGES
)NULL
,
986 FatalError("AdjustTokenPrivileges() failed!");
990 ExitWindowsEx(EWX_REBOOT
, 0);
1001 IN LPCWSTR lpszFontSize
)
1003 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1011 SetupChangeLocaleEx(HWND hWnd
,
1013 LPCWSTR lpSrcRootPath
,
1018 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1026 SetupChangeLocale(HWND hWnd
, LCID Lcid
)
1028 return SetupChangeLocaleEx(hWnd
, Lcid
, NULL
, 0, 0, 0);