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 *****************************************************************/
38 #include <ndk/cmfuncs.h>
44 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout
);
46 /* GLOBALS ******************************************************************/
48 HINF hSysSetupInf
= INVALID_HANDLE_VALUE
;
51 /* FUNCTIONS ****************************************************************/
54 FatalError(char *pszFmt
,...)
60 vsprintf(szBuffer
, pszFmt
, ap
);
63 LogItem(SYSSETUP_SEVERITY_FATAL_ERROR
, L
"Failed");
65 strcat(szBuffer
, "\nRebooting now!");
85 WCHAR wszBuf
[MAX_PATH
];
88 HRESULT hr
= CoCreateInstance(&CLSID_ShellLink
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IShellLink
, (LPVOID
*)&psl
);
92 hr
= psl
->lpVtbl
->SetPath(psl
, pszCmd
);
96 hr
= psl
->lpVtbl
->SetArguments(psl
, pszArg
);
101 hr
= psl
->lpVtbl
->SetWorkingDirectory(psl
, pszDir
);
106 hr
= psl
->lpVtbl
->SetIconLocation(psl
, pszIconPath
, iIconNr
);
111 hr
= psl
->lpVtbl
->SetDescription(psl
, pszComment
);
114 hr
= psl
->lpVtbl
->QueryInterface(psl
, &IID_IPersistFile
, (LPVOID
*)&ppf
);
119 hr
= ppf
->lpVtbl
->Save(ppf
, pszLinkPath
, TRUE
);
121 MultiByteToWideChar(CP_ACP
, 0, pszLinkPath
, -1, wszBuf
, MAX_PATH
);
123 hr
= ppf
->lpVtbl
->Save(ppf
, wszBuf
, TRUE
);
124 #endif /* _UNICODE */
126 ppf
->lpVtbl
->Release(ppf
);
129 psl
->lpVtbl
->Release(psl
);
141 LPCTSTR pszDescription
,
144 TCHAR szPath
[MAX_PATH
];
145 TCHAR szExeName
[MAX_PATH
];
147 TCHAR szWorkingDirBuf
[MAX_PATH
];
148 LPTSTR pszWorkingDir
= NULL
;
152 if (ExpandEnvironmentStrings(pszCommand
,
154 sizeof(szPath
) / sizeof(szPath
[0])) == 0)
156 _tcscpy(szPath
, pszCommand
);
159 if ((_taccess(szPath
, 0 )) == -1)
160 /* Expected error, don't return FALSE */
163 dwLen
= GetFullPathName(szPath
,
164 sizeof(szWorkingDirBuf
) / sizeof(szWorkingDirBuf
[0]),
167 if (dwLen
!= 0 && dwLen
<= sizeof(szWorkingDirBuf
) / sizeof(szWorkingDirBuf
[0]))
169 /* Since those should only be called with (.exe) files,
170 lpFilePart has not to be NULL */
171 ASSERT(lpFilePart
!= NULL
);
173 /* Save the file name */
174 _tcscpy(szExeName
, lpFilePart
);
176 /* We're only interested in the path. Cut the file name off.
177 Also remove the trailing backslash unless the working directory
178 is only going to be a drive, ie. C:\ */
179 *(lpFilePart
--) = _T('\0');
180 if (!(lpFilePart
- szWorkingDirBuf
== 2 && szWorkingDirBuf
[1] == _T(':') &&
181 szWorkingDirBuf
[2] == _T('\\')))
183 *lpFilePart
= _T('\0');
186 pszWorkingDir
= szWorkingDirBuf
;
189 _tcscpy(szPath
, pszFolder
);
191 Ptr
= PathAddBackslash(szPath
);
193 _tcscpy(Ptr
, pszName
);
195 // FIXME: we should pass 'command' straight in here, but shell32 doesn't expand it
196 return SUCCEEDED(CreateShellLink(szPath
, szExeName
, _T(""), pszWorkingDir
, szExeName
, iIconNr
, pszDescription
));
200 static BOOL
CreateShortcutsFromSection(HINF hinf
, LPWSTR pszSection
, LPCWSTR pszFolder
)
203 WCHAR szCommand
[MAX_PATH
];
204 WCHAR szName
[MAX_PATH
];
205 WCHAR szDescription
[MAX_PATH
];
208 if (!SetupFindFirstLine(hinf
, pszSection
, NULL
, &Context
))
213 if (SetupGetFieldCount(&Context
) < 4)
216 if (!SetupGetStringFieldW(&Context
, 1, szCommand
, MAX_PATH
, NULL
))
219 if (!SetupGetStringFieldW(&Context
, 2, szName
, MAX_PATH
, NULL
))
222 if (!SetupGetStringFieldW(&Context
, 3, szDescription
, MAX_PATH
, NULL
))
225 if (!SetupGetIntField(&Context
, 4, &iIconNr
))
228 _tcscat(szName
, L
".lnk");
230 CreateShortcut(pszFolder
, szName
, szCommand
, szDescription
, iIconNr
);
232 }while (SetupFindNextLine(&Context
, &Context
));
237 static BOOL
CreateShortcuts(HINF hinf
, LPCWSTR szSection
)
240 WCHAR szPath
[MAX_PATH
];
241 WCHAR szFolder
[MAX_PATH
];
242 WCHAR szFolderSection
[MAX_PATH
];
248 if (!SetupFindFirstLine(hinf
, szSection
, NULL
, &Context
))
253 if (SetupGetFieldCount(&Context
) < 2)
256 if (!SetupGetStringFieldW(&Context
, 0, szFolderSection
, MAX_PATH
, NULL
))
259 if (!SetupGetIntField(&Context
, 1, &csidl
))
262 if (!SetupGetStringFieldW(&Context
, 2, szFolder
, MAX_PATH
, NULL
))
265 if (!SHGetSpecialFolderPathW(0, szPath
, csidl
, TRUE
))
268 p
= PathAddBackslash(szPath
);
269 _tcscpy(p
, szFolder
);
271 if (!CreateDirectory(szPath
, NULL
))
273 if (GetLastError() != ERROR_ALREADY_EXISTS
)
279 CreateShortcutsFromSection(hinf
, szFolderSection
, szPath
);
281 }while (SetupFindNextLine(&Context
, &Context
));
292 WCHAR szTempDir
[MAX_PATH
];
293 WCHAR szBuffer
[MAX_PATH
];
297 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
298 L
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
301 &hKey
) != ERROR_SUCCESS
)
303 FatalError("Error: %lu\n", GetLastError());
308 dwLength
= MAX_PATH
* sizeof(WCHAR
);
309 if (RegQueryValueExW(hKey
,
314 &dwLength
) != ERROR_SUCCESS
)
316 FatalError("Error: %lu\n", GetLastError());
321 if (!ExpandEnvironmentStringsW(szBuffer
,
325 FatalError("Error: %lu\n", GetLastError());
329 /* Create profiles directory */
330 if (!CreateDirectoryW(szTempDir
, NULL
))
332 if (GetLastError() != ERROR_ALREADY_EXISTS
)
334 FatalError("Error: %lu\n", GetLastError());
344 InstallSysSetupInfDevices(VOID
)
346 INFCONTEXT InfContext
;
347 WCHAR szLineBuffer
[256];
350 if (!SetupFindFirstLineW(hSysSetupInf
,
351 L
"DeviceInfsToInstall",
360 if (!SetupGetStringFieldW(&InfContext
,
363 sizeof(szLineBuffer
)/sizeof(szLineBuffer
[0]),
369 if (!SetupDiInstallClassW(NULL
, szLineBuffer
, DI_QUIETINSTALL
, NULL
))
374 while (SetupFindNextLine(&InfContext
, &InfContext
));
380 InstallSysSetupInfComponents(VOID
)
382 INFCONTEXT InfContext
;
383 WCHAR szNameBuffer
[256];
384 WCHAR szSectionBuffer
[256];
385 HINF hComponentInf
= INVALID_HANDLE_VALUE
;
387 if (!SetupFindFirstLineW(hSysSetupInf
,
392 DPRINT("No Inf.Always section found\n");
398 if (!SetupGetStringFieldW(&InfContext
,
399 1, // Get the component name
401 sizeof(szNameBuffer
)/sizeof(szNameBuffer
[0]),
404 FatalError("Error while trying to get component name \n");
408 if (!SetupGetStringFieldW(&InfContext
,
409 2, // Get the component install section
411 sizeof(szSectionBuffer
)/sizeof(szSectionBuffer
[0]),
414 FatalError("Error while trying to get component install section \n");
418 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer
, szNameBuffer
);
420 hComponentInf
= SetupOpenInfFileW(szNameBuffer
,
425 if (hComponentInf
== INVALID_HANDLE_VALUE
)
427 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer
, GetLastError());
431 if (!SetupInstallFromInfSectionW(NULL
,
438 SetupDefaultQueueCallbackW
,
443 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer
, GetLastError());
444 SetupCloseInfFile(hComponentInf
);
448 SetupCloseInfFile(hComponentInf
);
450 while (SetupFindNextLine(&InfContext
, &InfContext
));
460 RegisterTypeLibraries (HINF hinf
, LPCWSTR szSection
)
462 INFCONTEXT InfContext
;
464 WCHAR szName
[MAX_PATH
];
465 WCHAR szPath
[MAX_PATH
];
471 /* Begin iterating the entries in the inf section */
472 res
= SetupFindFirstLine(hinf
, szSection
, NULL
, &InfContext
);
473 if (!res
) return FALSE
;
477 /* Get the name of the current type library */
478 if (!SetupGetStringFieldW(&InfContext
, 1, szName
, MAX_PATH
, NULL
))
480 FatalError("SetupGetStringFieldW failed\n");
484 if (!SetupGetIntField(&InfContext
, 2, &csidl
))
485 csidl
= CSIDL_SYSTEM
;
487 hret
= SHGetFolderPathW(NULL
, csidl
, NULL
, 0, szPath
);
490 FatalError("SHGetSpecialFolderPathW failed hret=0x%d\n", hret
);
494 p
= PathAddBackslash(szPath
);
497 hmod
= LoadLibraryW(szName
);
500 FatalError("LoadLibraryW failed\n");
504 __wine_register_resources(hmod
);
506 }while (SetupFindNextLine(&InfContext
, &InfContext
));
512 EnableUserModePnpManager(VOID
)
514 SC_HANDLE hSCManager
= NULL
;
515 SC_HANDLE hService
= NULL
;
518 hSCManager
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
519 if (hSCManager
== NULL
)
521 DPRINT1("Unable to open the service control manager.\n");
522 DPRINT1("Last Error %d\n", GetLastError());
526 hService
= OpenServiceW(hSCManager
,
528 SERVICE_CHANGE_CONFIG
| SERVICE_START
);
529 if (hService
== NULL
)
531 DPRINT1("Unable to open PlugPlay service\n");
535 bRet
= ChangeServiceConfigW(hService
,
540 NULL
, NULL
, NULL
, NULL
);
543 DPRINT1("Unable to change the service configuration\n");
547 bRet
= StartServiceW(hService
, 0, NULL
);
548 if (!bRet
&& (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING
))
550 DPRINT1("Unable to start service\n");
557 if (hService
!= NULL
)
558 CloseServiceHandle(hService
);
559 if (hSCManager
!= NULL
)
560 CloseServiceHandle(hSCManager
);
564 static INT_PTR CALLBACK
565 StatusMessageWindowProc(
571 UNREFERENCED_PARAMETER(wParam
);
579 if (!LoadStringW(hDllInstance
, IDS_STATUS_INSTALL_DEV
, szMsg
, sizeof(szMsg
)/sizeof(szMsg
[0])))
581 SetDlgItemTextW(hwndDlg
, IDC_STATUSLABEL
, szMsg
);
589 ShowStatusMessageThread(
590 IN LPVOID lpParameter
)
592 HWND
*phWnd
= (HWND
*)lpParameter
;
596 hWnd
= CreateDialogParam(
598 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG
),
600 StatusMessageWindowProc
,
606 ShowWindow(hWnd
, SW_SHOW
);
608 /* Message loop for the Status window */
609 while (GetMessage(&Msg
, NULL
, 0, 0))
611 TranslateMessage(&Msg
);
612 DispatchMessage(&Msg
);
630 return ERROR_INVALID_PARAMETER
;
633 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
634 if (rc
!= ERROR_SUCCESS
)
636 if (dwType
!= REG_SZ
)
637 return ERROR_FILE_NOT_FOUND
;
638 pwszValue
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
640 return ERROR_NOT_ENOUGH_MEMORY
;
641 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)pwszValue
, &cbData
);
642 if (rc
!= ERROR_SUCCESS
)
644 HeapFree(GetProcessHeap(), 0, pwszValue
);
647 /* NULL-terminate the string */
648 pwszValue
[cbData
/ sizeof(WCHAR
)] = '\0';
651 return ERROR_SUCCESS
;
657 HKEY hControlKey
= NULL
;
658 LPWSTR pwszSystemStartOptions
= NULL
;
659 LPWSTR pwszCurrentOption
, pwszNextOption
; /* Pointers into SystemStartOptions */
660 BOOL bConsoleBoot
= FALSE
;
665 L
"SYSTEM\\CurrentControlSet\\Control",
669 if (rc
!= ERROR_SUCCESS
)
672 rc
= ReadRegSzKey(hControlKey
, L
"SystemStartOptions", &pwszSystemStartOptions
);
673 if (rc
!= ERROR_SUCCESS
)
676 /* Check for CONSOLE switch in SystemStartOptions */
677 pwszCurrentOption
= pwszSystemStartOptions
;
678 while (pwszCurrentOption
)
680 pwszNextOption
= wcschr(pwszCurrentOption
, L
' ');
682 *pwszNextOption
= L
'\0';
683 if (wcsicmp(pwszCurrentOption
, L
"CONSOLE") == 0)
685 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption
);
689 pwszCurrentOption
= pwszNextOption
? pwszNextOption
+ 1 : NULL
;
693 if (hControlKey
!= NULL
)
694 RegCloseKey(hControlKey
);
695 if (pwszSystemStartOptions
)
696 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions
);
705 hSysSetupInf
= SetupOpenInfFileW(
710 if (hSysSetupInf
== INVALID_HANDLE_VALUE
)
712 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
716 if (!InstallSysSetupInfDevices())
718 FatalError("InstallSysSetupInfDevices() failed!\n");
722 if(!InstallSysSetupInfComponents())
724 FatalError("InstallSysSetupInfComponents() failed!\n");
728 if (!IsConsoleBoot())
732 hThread
= CreateThread(
735 ShowStatusMessageThread
,
741 CloseHandle(hThread
);
744 if (!EnableUserModePnpManager())
746 FatalError("EnableUserModePnpManager() failed!\n");
750 if (CMP_WaitNoPendingInstallEvents(INFINITE
) != WAIT_OBJECT_0
)
752 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
762 SetupCloseInfFile(hSysSetupInf
);
767 InstallLiveCD(IN HINSTANCE hInstance
)
769 STARTUPINFOW StartupInfo
;
770 PROCESS_INFORMATION ProcessInformation
;
773 if (!CommonInstall())
776 /* Register components */
779 if (!SetupInstallFromInfSectionW(NULL
,
780 hSysSetupInf
, L
"RegistrationPhase2",
782 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
))
784 DPRINT1("SetupInstallFromInfSectionW failed!\n");
787 RegisterTypeLibraries(hSysSetupInf
, L
"TypeLibraries");
789 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
791 DPRINT1("Catching exception\n");
795 SetupCloseInfFile(hSysSetupInf
);
798 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
799 StartupInfo
.cb
= sizeof(StartupInfo
);
800 bRes
= CreateProcessW(
810 &ProcessInformation
);
814 CloseHandle(ProcessInformation
.hThread
);
815 CloseHandle(ProcessInformation
.hProcess
);
822 L
"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
830 SetSetupType(DWORD dwSetupType
)
835 dwError
= RegOpenKeyExW(
841 if (dwError
!= ERROR_SUCCESS
)
844 dwError
= RegSetValueExW(
849 (LPBYTE
)&dwSetupType
,
852 if (dwError
!= ERROR_SUCCESS
)
859 InstallReactOS(HINSTANCE hInstance
)
861 TCHAR szBuffer
[MAX_PATH
];
863 TOKEN_PRIVILEGES privs
;
867 InitializeSetupActionLog(FALSE
);
868 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS");
870 if (!InitializeProfiles())
872 FatalError("InitializeProfiles() failed");
876 CreateTempDir(L
"TEMP");
877 CreateTempDir(L
"TMP");
879 if (GetWindowsDirectory(szBuffer
, sizeof(szBuffer
) / sizeof(TCHAR
)))
881 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
882 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
885 &hKey
) == ERROR_SUCCESS
)
892 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
899 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
904 PathAddBackslash(szBuffer
);
905 _tcscat(szBuffer
, _T("system"));
906 CreateDirectory(szBuffer
, NULL
);
909 if (!CommonInstall())
918 hShortcutsInf
= SetupOpenInfFileW(L
"shortcuts.inf",
922 if (hShortcutsInf
== INVALID_HANDLE_VALUE
)
924 FatalError("Failed to open shortcuts.inf");
928 if (!CreateShortcuts(hShortcutsInf
, L
"ShortcutFolders"))
930 FatalError("CreateShortcuts() failed");
934 SetupCloseInfFile(hShortcutsInf
);
936 /* ROS HACK, as long as NtUnloadKey is not implemented */
938 NTSTATUS Status
= NtUnloadKey(NULL
);
939 if (Status
== STATUS_NOT_IMPLEMENTED
)
941 /* Create the Administrator profile */
942 PROFILEINFOW ProfileInfo
;
946 ret
= LogonUserW(AdminInfo
.Name
,
949 LOGON32_LOGON_INTERACTIVE
,
950 LOGON32_PROVIDER_DEFAULT
,
954 FatalError("LogonUserW() failed!");
957 ZeroMemory(&ProfileInfo
, sizeof(PROFILEINFOW
));
958 ProfileInfo
.dwSize
= sizeof(PROFILEINFOW
);
959 ProfileInfo
.lpUserName
= L
"Administrator";
960 ProfileInfo
.dwFlags
= PI_NOUI
;
961 LoadUserProfileW(hToken
, &ProfileInfo
);
966 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
969 /* END OF ROS HACK */
971 SetupCloseInfFile(hSysSetupInf
);
974 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS done");
975 TerminateSetupActionLog();
977 if (AdminInfo
.Name
!= NULL
)
978 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Name
);
980 if (AdminInfo
.Domain
!= NULL
)
981 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Domain
);
983 if (AdminInfo
.Password
!= NULL
)
984 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Password
);
986 /* Get shutdown privilege */
987 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &token
))
989 FatalError("OpenProcessToken() failed!");
992 if (!LookupPrivilegeValue(
995 &privs
.Privileges
[0].Luid
))
997 FatalError("LookupPrivilegeValue() failed!");
1000 privs
.PrivilegeCount
= 1;
1001 privs
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
1002 if (AdjustTokenPrivileges(
1007 (PTOKEN_PRIVILEGES
)NULL
,
1010 FatalError("AdjustTokenPrivileges() failed!");
1014 ExitWindowsEx(EWX_REBOOT
, 0);
1023 SetupChangeFontSize(
1025 IN LPCWSTR lpszFontSize
)
1027 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1035 SetupChangeLocaleEx(HWND hWnd
,
1037 LPCWSTR lpSrcRootPath
,
1042 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1050 SetupChangeLocale(HWND hWnd
, LCID Lcid
)
1052 return SetupChangeLocaleEx(hWnd
, Lcid
, NULL
, 0, 0, 0);