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
];
247 if (!SetupFindFirstLine(hinf
, szSection
, NULL
, &Context
))
252 if (SetupGetFieldCount(&Context
) < 2)
255 if (!SetupGetStringFieldW(&Context
, 0, szFolderSection
, MAX_PATH
, NULL
))
258 if (!SetupGetIntField(&Context
, 1, &csidl
))
261 if (!SetupGetStringFieldW(&Context
, 2, szFolder
, MAX_PATH
, NULL
))
264 if (FAILED(SHGetFolderPathAndSubDirW(NULL
, csidl
|CSIDL_FLAG_CREATE
, (HANDLE
)-1, SHGFP_TYPE_DEFAULT
, szFolder
, szPath
)))
267 CreateShortcutsFromSection(hinf
, szFolderSection
, szPath
);
269 }while (SetupFindNextLine(&Context
, &Context
));
280 WCHAR szTempDir
[MAX_PATH
];
281 WCHAR szBuffer
[MAX_PATH
];
285 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
286 L
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
289 &hKey
) != ERROR_SUCCESS
)
291 FatalError("Error: %lu\n", GetLastError());
296 dwLength
= MAX_PATH
* sizeof(WCHAR
);
297 if (RegQueryValueExW(hKey
,
302 &dwLength
) != ERROR_SUCCESS
)
304 FatalError("Error: %lu\n", GetLastError());
309 if (!ExpandEnvironmentStringsW(szBuffer
,
313 FatalError("Error: %lu\n", GetLastError());
317 /* Create profiles directory */
318 if (!CreateDirectoryW(szTempDir
, NULL
))
320 if (GetLastError() != ERROR_ALREADY_EXISTS
)
322 FatalError("Error: %lu\n", GetLastError());
332 InstallSysSetupInfDevices(VOID
)
334 INFCONTEXT InfContext
;
335 WCHAR szLineBuffer
[256];
338 if (!SetupFindFirstLineW(hSysSetupInf
,
339 L
"DeviceInfsToInstall",
348 if (!SetupGetStringFieldW(&InfContext
,
351 sizeof(szLineBuffer
)/sizeof(szLineBuffer
[0]),
357 if (!SetupDiInstallClassW(NULL
, szLineBuffer
, DI_QUIETINSTALL
, NULL
))
362 while (SetupFindNextLine(&InfContext
, &InfContext
));
368 InstallSysSetupInfComponents(VOID
)
370 INFCONTEXT InfContext
;
371 WCHAR szNameBuffer
[256];
372 WCHAR szSectionBuffer
[256];
373 HINF hComponentInf
= INVALID_HANDLE_VALUE
;
375 if (!SetupFindFirstLineW(hSysSetupInf
,
380 DPRINT("No Inf.Always section found\n");
386 if (!SetupGetStringFieldW(&InfContext
,
387 1, // Get the component name
389 sizeof(szNameBuffer
)/sizeof(szNameBuffer
[0]),
392 FatalError("Error while trying to get component name \n");
396 if (!SetupGetStringFieldW(&InfContext
,
397 2, // Get the component install section
399 sizeof(szSectionBuffer
)/sizeof(szSectionBuffer
[0]),
402 FatalError("Error while trying to get component install section \n");
406 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer
, szNameBuffer
);
408 hComponentInf
= SetupOpenInfFileW(szNameBuffer
,
413 if (hComponentInf
== INVALID_HANDLE_VALUE
)
415 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer
, GetLastError());
419 if (!SetupInstallFromInfSectionW(NULL
,
426 SetupDefaultQueueCallbackW
,
431 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer
, GetLastError());
432 SetupCloseInfFile(hComponentInf
);
436 SetupCloseInfFile(hComponentInf
);
438 while (SetupFindNextLine(&InfContext
, &InfContext
));
448 RegisterTypeLibraries (HINF hinf
, LPCWSTR szSection
)
450 INFCONTEXT InfContext
;
452 WCHAR szName
[MAX_PATH
];
453 WCHAR szPath
[MAX_PATH
];
459 /* Begin iterating the entries in the inf section */
460 res
= SetupFindFirstLine(hinf
, szSection
, NULL
, &InfContext
);
461 if (!res
) return FALSE
;
465 /* Get the name of the current type library */
466 if (!SetupGetStringFieldW(&InfContext
, 1, szName
, MAX_PATH
, NULL
))
468 FatalError("SetupGetStringFieldW failed\n");
472 if (!SetupGetIntField(&InfContext
, 2, &csidl
))
473 csidl
= CSIDL_SYSTEM
;
475 hret
= SHGetFolderPathW(NULL
, csidl
, NULL
, 0, szPath
);
478 FatalError("SHGetFolderPathW failed hret=0x%d\n", hret
);
482 p
= PathAddBackslash(szPath
);
485 hmod
= LoadLibraryW(szName
);
488 FatalError("LoadLibraryW failed\n");
492 __wine_register_resources(hmod
);
494 }while (SetupFindNextLine(&InfContext
, &InfContext
));
500 EnableUserModePnpManager(VOID
)
502 SC_HANDLE hSCManager
= NULL
;
503 SC_HANDLE hService
= NULL
;
506 hSCManager
= OpenSCManagerW(NULL
, NULL
, SC_MANAGER_ENUMERATE_SERVICE
);
507 if (hSCManager
== NULL
)
509 DPRINT1("Unable to open the service control manager.\n");
510 DPRINT1("Last Error %d\n", GetLastError());
514 hService
= OpenServiceW(hSCManager
,
516 SERVICE_CHANGE_CONFIG
| SERVICE_START
);
517 if (hService
== NULL
)
519 DPRINT1("Unable to open PlugPlay service\n");
523 bRet
= ChangeServiceConfigW(hService
,
528 NULL
, NULL
, NULL
, NULL
);
531 DPRINT1("Unable to change the service configuration\n");
535 bRet
= StartServiceW(hService
, 0, NULL
);
536 if (!bRet
&& (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING
))
538 DPRINT1("Unable to start service\n");
545 if (hService
!= NULL
)
546 CloseServiceHandle(hService
);
547 if (hSCManager
!= NULL
)
548 CloseServiceHandle(hSCManager
);
552 static INT_PTR CALLBACK
553 StatusMessageWindowProc(
559 UNREFERENCED_PARAMETER(wParam
);
567 if (!LoadStringW(hDllInstance
, IDS_STATUS_INSTALL_DEV
, szMsg
, sizeof(szMsg
)/sizeof(szMsg
[0])))
569 SetDlgItemTextW(hwndDlg
, IDC_STATUSLABEL
, szMsg
);
577 ShowStatusMessageThread(
578 IN LPVOID lpParameter
)
580 HWND
*phWnd
= (HWND
*)lpParameter
;
584 hWnd
= CreateDialogParam(
586 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG
),
588 StatusMessageWindowProc
,
594 ShowWindow(hWnd
, SW_SHOW
);
596 /* Message loop for the Status window */
597 while (GetMessage(&Msg
, NULL
, 0, 0))
599 TranslateMessage(&Msg
);
600 DispatchMessage(&Msg
);
618 return ERROR_INVALID_PARAMETER
;
621 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, &dwType
, NULL
, &cbData
);
622 if (rc
!= ERROR_SUCCESS
)
624 if (dwType
!= REG_SZ
)
625 return ERROR_FILE_NOT_FOUND
;
626 pwszValue
= HeapAlloc(GetProcessHeap(), 0, cbData
+ sizeof(WCHAR
));
628 return ERROR_NOT_ENOUGH_MEMORY
;
629 rc
= RegQueryValueExW(hKey
, pszKey
, NULL
, NULL
, (LPBYTE
)pwszValue
, &cbData
);
630 if (rc
!= ERROR_SUCCESS
)
632 HeapFree(GetProcessHeap(), 0, pwszValue
);
635 /* NULL-terminate the string */
636 pwszValue
[cbData
/ sizeof(WCHAR
)] = '\0';
639 return ERROR_SUCCESS
;
645 HKEY hControlKey
= NULL
;
646 LPWSTR pwszSystemStartOptions
= NULL
;
647 LPWSTR pwszCurrentOption
, pwszNextOption
; /* Pointers into SystemStartOptions */
648 BOOL bConsoleBoot
= FALSE
;
653 L
"SYSTEM\\CurrentControlSet\\Control",
657 if (rc
!= ERROR_SUCCESS
)
660 rc
= ReadRegSzKey(hControlKey
, L
"SystemStartOptions", &pwszSystemStartOptions
);
661 if (rc
!= ERROR_SUCCESS
)
664 /* Check for CONSOLE switch in SystemStartOptions */
665 pwszCurrentOption
= pwszSystemStartOptions
;
666 while (pwszCurrentOption
)
668 pwszNextOption
= wcschr(pwszCurrentOption
, L
' ');
670 *pwszNextOption
= L
'\0';
671 if (wcsicmp(pwszCurrentOption
, L
"CONSOLE") == 0)
673 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption
);
677 pwszCurrentOption
= pwszNextOption
? pwszNextOption
+ 1 : NULL
;
681 if (hControlKey
!= NULL
)
682 RegCloseKey(hControlKey
);
683 if (pwszSystemStartOptions
)
684 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions
);
693 hSysSetupInf
= SetupOpenInfFileW(
698 if (hSysSetupInf
== INVALID_HANDLE_VALUE
)
700 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
704 if (!InstallSysSetupInfDevices())
706 FatalError("InstallSysSetupInfDevices() failed!\n");
710 if(!InstallSysSetupInfComponents())
712 FatalError("InstallSysSetupInfComponents() failed!\n");
716 if (!IsConsoleBoot())
720 hThread
= CreateThread(
723 ShowStatusMessageThread
,
729 CloseHandle(hThread
);
732 if (!EnableUserModePnpManager())
734 FatalError("EnableUserModePnpManager() failed!\n");
738 if (CMP_WaitNoPendingInstallEvents(INFINITE
) != WAIT_OBJECT_0
)
740 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
750 SetupCloseInfFile(hSysSetupInf
);
755 InstallLiveCD(IN HINSTANCE hInstance
)
757 STARTUPINFOW StartupInfo
;
758 PROCESS_INFORMATION ProcessInformation
;
761 if (!CommonInstall())
764 /* Register components */
767 if (!SetupInstallFromInfSectionW(NULL
,
768 hSysSetupInf
, L
"RegistrationPhase2",
770 0, NULL
, 0, NULL
, NULL
, NULL
, NULL
))
772 DPRINT1("SetupInstallFromInfSectionW failed!\n");
775 RegisterTypeLibraries(hSysSetupInf
, L
"TypeLibraries");
777 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
779 DPRINT1("Catching exception\n");
783 SetupCloseInfFile(hSysSetupInf
);
786 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
787 StartupInfo
.cb
= sizeof(StartupInfo
);
788 bRes
= CreateProcessW(
798 &ProcessInformation
);
802 CloseHandle(ProcessInformation
.hThread
);
803 CloseHandle(ProcessInformation
.hProcess
);
810 L
"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
818 SetSetupType(DWORD dwSetupType
)
823 dwError
= RegOpenKeyExW(
829 if (dwError
!= ERROR_SUCCESS
)
832 dwError
= RegSetValueExW(
837 (LPBYTE
)&dwSetupType
,
840 if (dwError
!= ERROR_SUCCESS
)
847 InstallReactOS(HINSTANCE hInstance
)
849 TCHAR szBuffer
[MAX_PATH
];
851 TOKEN_PRIVILEGES privs
;
855 InitializeSetupActionLog(FALSE
);
856 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS");
858 if (!InitializeProfiles())
860 FatalError("InitializeProfiles() failed");
864 CreateTempDir(L
"TEMP");
865 CreateTempDir(L
"TMP");
867 if (GetWindowsDirectory(szBuffer
, sizeof(szBuffer
) / sizeof(TCHAR
)))
869 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
870 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
873 &hKey
) == ERROR_SUCCESS
)
880 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
887 (wcslen(szBuffer
) + 1) * sizeof(WCHAR
));
892 PathAddBackslash(szBuffer
);
893 _tcscat(szBuffer
, _T("system"));
894 CreateDirectory(szBuffer
, NULL
);
897 if (!CommonInstall())
906 hShortcutsInf
= SetupOpenInfFileW(L
"shortcuts.inf",
910 if (hShortcutsInf
== INVALID_HANDLE_VALUE
)
912 FatalError("Failed to open shortcuts.inf");
916 if (!CreateShortcuts(hShortcutsInf
, L
"ShortcutFolders"))
918 FatalError("CreateShortcuts() failed");
922 SetupCloseInfFile(hShortcutsInf
);
924 /* ROS HACK, as long as NtUnloadKey is not implemented */
926 NTSTATUS Status
= NtUnloadKey(NULL
);
927 if (Status
== STATUS_NOT_IMPLEMENTED
)
929 /* Create the Administrator profile */
930 PROFILEINFOW ProfileInfo
;
934 ret
= LogonUserW(AdminInfo
.Name
,
937 LOGON32_LOGON_INTERACTIVE
,
938 LOGON32_PROVIDER_DEFAULT
,
942 FatalError("LogonUserW() failed!");
945 ZeroMemory(&ProfileInfo
, sizeof(PROFILEINFOW
));
946 ProfileInfo
.dwSize
= sizeof(PROFILEINFOW
);
947 ProfileInfo
.lpUserName
= L
"Administrator";
948 ProfileInfo
.dwFlags
= PI_NOUI
;
949 LoadUserProfileW(hToken
, &ProfileInfo
);
954 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
957 /* END OF ROS HACK */
959 SetupCloseInfFile(hSysSetupInf
);
962 LogItem(SYSSETUP_SEVERITY_INFORMATION
, L
"Installing ReactOS done");
963 TerminateSetupActionLog();
965 if (AdminInfo
.Name
!= NULL
)
966 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Name
);
968 if (AdminInfo
.Domain
!= NULL
)
969 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Domain
);
971 if (AdminInfo
.Password
!= NULL
)
972 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo
.Password
);
974 /* Get shutdown privilege */
975 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
, &token
))
977 FatalError("OpenProcessToken() failed!");
980 if (!LookupPrivilegeValue(
983 &privs
.Privileges
[0].Luid
))
985 FatalError("LookupPrivilegeValue() failed!");
988 privs
.PrivilegeCount
= 1;
989 privs
.Privileges
[0].Attributes
= SE_PRIVILEGE_ENABLED
;
990 if (AdjustTokenPrivileges(
995 (PTOKEN_PRIVILEGES
)NULL
,
998 FatalError("AdjustTokenPrivileges() failed!");
1002 ExitWindowsEx(EWX_REBOOT
, 0);
1011 SetupChangeFontSize(
1013 IN LPCWSTR lpszFontSize
)
1015 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1023 SetupChangeLocaleEx(HWND hWnd
,
1025 LPCWSTR lpSrcRootPath
,
1030 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
1038 SetupChangeLocale(HWND hWnd
, LCID Lcid
)
1040 return SetupChangeLocaleEx(hWnd
, Lcid
, NULL
, 0, 0, 0);