[SYSSETUP]
[reactos.git] / dll / win32 / syssetup / install.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2003 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /*
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
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "precomp.h"
30
31 #include <tchar.h>
32 #include <wincon.h>
33 #include <winsvc.h>
34 #include <userenv.h>
35 #include <shlobj.h>
36 #include <shlwapi.h>
37 #include <rpcproxy.h>
38 #include <ndk/cmfuncs.h>
39
40 #define NDEBUG
41 #include <debug.h>
42
43 DWORD WINAPI
44 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout);
45
46 /* GLOBALS ******************************************************************/
47
48 HINF hSysSetupInf = INVALID_HANDLE_VALUE;
49 ADMIN_INFO AdminInfo;
50
51 /* FUNCTIONS ****************************************************************/
52
53 static VOID
54 FatalError(char *pszFmt,...)
55 {
56 char szBuffer[512];
57 va_list ap;
58
59 va_start(ap, pszFmt);
60 vsprintf(szBuffer, pszFmt, ap);
61 va_end(ap);
62
63 LogItem(SYSSETUP_SEVERITY_FATAL_ERROR, L"Failed");
64
65 strcat(szBuffer, "\nRebooting now!");
66 MessageBoxA(NULL,
67 szBuffer,
68 "ReactOS Setup",
69 MB_OK);
70 }
71
72 static HRESULT
73 CreateShellLink(
74 LPCTSTR pszLinkPath,
75 LPCTSTR pszCmd,
76 LPCTSTR pszArg,
77 LPCTSTR pszDir,
78 LPCTSTR pszIconPath,
79 int iIconNr,
80 LPCTSTR pszComment)
81 {
82 IShellLink *psl;
83 IPersistFile *ppf;
84 #ifndef _UNICODE
85 WCHAR wszBuf[MAX_PATH];
86 #endif /* _UNICODE */
87
88 HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
89
90 if (SUCCEEDED(hr))
91 {
92 hr = psl->lpVtbl->SetPath(psl, pszCmd);
93
94 if (pszArg)
95 {
96 hr = psl->lpVtbl->SetArguments(psl, pszArg);
97 }
98
99 if (pszDir)
100 {
101 hr = psl->lpVtbl->SetWorkingDirectory(psl, pszDir);
102 }
103
104 if (pszIconPath)
105 {
106 hr = psl->lpVtbl->SetIconLocation(psl, pszIconPath, iIconNr);
107 }
108
109 if (pszComment)
110 {
111 hr = psl->lpVtbl->SetDescription(psl, pszComment);
112 }
113
114 hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
115
116 if (SUCCEEDED(hr))
117 {
118 #ifdef _UNICODE
119 hr = ppf->lpVtbl->Save(ppf, pszLinkPath, TRUE);
120 #else /* _UNICODE */
121 MultiByteToWideChar(CP_ACP, 0, pszLinkPath, -1, wszBuf, MAX_PATH);
122
123 hr = ppf->lpVtbl->Save(ppf, wszBuf, TRUE);
124 #endif /* _UNICODE */
125
126 ppf->lpVtbl->Release(ppf);
127 }
128
129 psl->lpVtbl->Release(psl);
130 }
131
132 return hr;
133 }
134
135
136 static BOOL
137 CreateShortcut(
138 LPCTSTR pszFolder,
139 LPCTSTR pszName,
140 LPCTSTR pszCommand,
141 LPCTSTR pszDescription,
142 INT iIconNr)
143 {
144 TCHAR szPath[MAX_PATH];
145 TCHAR szExeName[MAX_PATH];
146 LPTSTR Ptr;
147 TCHAR szWorkingDirBuf[MAX_PATH];
148 LPTSTR pszWorkingDir = NULL;
149 LPTSTR lpFilePart;
150 DWORD dwLen;
151
152 if (ExpandEnvironmentStrings(pszCommand,
153 szPath,
154 sizeof(szPath) / sizeof(szPath[0])) == 0)
155 {
156 _tcscpy(szPath, pszCommand);
157 }
158
159 if ((_taccess(szPath, 0 )) == -1)
160 /* Expected error, don't return FALSE */
161 return TRUE;
162
163 dwLen = GetFullPathName(szPath,
164 sizeof(szWorkingDirBuf) / sizeof(szWorkingDirBuf[0]),
165 szWorkingDirBuf,
166 &lpFilePart);
167 if (dwLen != 0 && dwLen <= sizeof(szWorkingDirBuf) / sizeof(szWorkingDirBuf[0]))
168 {
169 /* Since those should only be called with (.exe) files,
170 lpFilePart has not to be NULL */
171 ASSERT(lpFilePart != NULL);
172
173 /* Save the file name */
174 _tcscpy(szExeName, lpFilePart);
175
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('\\')))
182 {
183 *lpFilePart = _T('\0');
184 }
185
186 pszWorkingDir = szWorkingDirBuf;
187 }
188
189 _tcscpy(szPath, pszFolder);
190
191 Ptr = PathAddBackslash(szPath);
192
193 _tcscpy(Ptr, pszName);
194
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));
197 }
198
199
200 static BOOL CreateShortcutsFromSection(HINF hinf, LPWSTR pszSection, LPCWSTR pszFolder)
201 {
202 INFCONTEXT Context;
203 WCHAR szCommand[MAX_PATH];
204 WCHAR szName[MAX_PATH];
205 WCHAR szDescription[MAX_PATH];
206 INT iIconNr;
207
208 if (!SetupFindFirstLine(hinf, pszSection, NULL, &Context))
209 return FALSE;
210
211 do
212 {
213 if (SetupGetFieldCount(&Context) < 4)
214 continue;
215
216 if (!SetupGetStringFieldW(&Context, 1, szCommand, MAX_PATH, NULL))
217 continue;
218
219 if (!SetupGetStringFieldW(&Context, 2, szName, MAX_PATH, NULL))
220 continue;
221
222 if (!SetupGetStringFieldW(&Context, 3, szDescription, MAX_PATH, NULL))
223 continue;
224
225 if (!SetupGetIntField(&Context, 4, &iIconNr))
226 continue;
227
228 _tcscat(szName, L".lnk");
229
230 CreateShortcut(pszFolder, szName, szCommand, szDescription, iIconNr);
231
232 }while (SetupFindNextLine(&Context, &Context));
233
234 return TRUE;
235 }
236
237 static BOOL CreateShortcuts(HINF hinf, LPCWSTR szSection)
238 {
239 INFCONTEXT Context;
240 WCHAR szPath[MAX_PATH];
241 WCHAR szFolder[MAX_PATH];
242 WCHAR szFolderSection[MAX_PATH];
243 INT csidl;
244
245 CoInitialize(NULL);
246
247 if (!SetupFindFirstLine(hinf, szSection, NULL, &Context))
248 return FALSE;
249
250 do
251 {
252 if (SetupGetFieldCount(&Context) < 2)
253 continue;
254
255 if (!SetupGetStringFieldW(&Context, 0, szFolderSection, MAX_PATH, NULL))
256 continue;
257
258 if (!SetupGetIntField(&Context, 1, &csidl))
259 continue;
260
261 if (!SetupGetStringFieldW(&Context, 2, szFolder, MAX_PATH, NULL))
262 continue;
263
264 if (FAILED(SHGetFolderPathAndSubDirW(NULL, csidl|CSIDL_FLAG_CREATE, (HANDLE)-1, SHGFP_TYPE_DEFAULT, szFolder, szPath)))
265 continue;
266
267 CreateShortcutsFromSection(hinf, szFolderSection, szPath);
268
269 }while (SetupFindNextLine(&Context, &Context));
270
271 CoUninitialize();
272
273 return TRUE;
274 }
275
276 static VOID
277 CreateTempDir(
278 IN LPCWSTR VarName)
279 {
280 WCHAR szTempDir[MAX_PATH];
281 WCHAR szBuffer[MAX_PATH];
282 DWORD dwLength;
283 HKEY hKey;
284
285 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
286 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
287 0,
288 KEY_QUERY_VALUE,
289 &hKey) != ERROR_SUCCESS)
290 {
291 FatalError("Error: %lu\n", GetLastError());
292 return;
293 }
294
295 /* Get temp dir */
296 dwLength = MAX_PATH * sizeof(WCHAR);
297 if (RegQueryValueExW(hKey,
298 VarName,
299 NULL,
300 NULL,
301 (LPBYTE)szBuffer,
302 &dwLength) != ERROR_SUCCESS)
303 {
304 FatalError("Error: %lu\n", GetLastError());
305 goto cleanup;
306 }
307
308 /* Expand it */
309 if (!ExpandEnvironmentStringsW(szBuffer,
310 szTempDir,
311 MAX_PATH))
312 {
313 FatalError("Error: %lu\n", GetLastError());
314 goto cleanup;
315 }
316
317 /* Create profiles directory */
318 if (!CreateDirectoryW(szTempDir, NULL))
319 {
320 if (GetLastError() != ERROR_ALREADY_EXISTS)
321 {
322 FatalError("Error: %lu\n", GetLastError());
323 goto cleanup;
324 }
325 }
326
327 cleanup:
328 RegCloseKey(hKey);
329 }
330
331 static BOOL
332 InstallSysSetupInfDevices(VOID)
333 {
334 INFCONTEXT InfContext;
335 WCHAR szLineBuffer[256];
336 DWORD dwLineLength;
337
338 if (!SetupFindFirstLineW(hSysSetupInf,
339 L"DeviceInfsToInstall",
340 NULL,
341 &InfContext))
342 {
343 return FALSE;
344 }
345
346 do
347 {
348 if (!SetupGetStringFieldW(&InfContext,
349 0,
350 szLineBuffer,
351 sizeof(szLineBuffer)/sizeof(szLineBuffer[0]),
352 &dwLineLength))
353 {
354 return FALSE;
355 }
356
357 if (!SetupDiInstallClassW(NULL, szLineBuffer, DI_QUIETINSTALL, NULL))
358 {
359 return FALSE;
360 }
361 }
362 while (SetupFindNextLine(&InfContext, &InfContext));
363
364 return TRUE;
365 }
366
367 static BOOL
368 InstallSysSetupInfComponents(VOID)
369 {
370 INFCONTEXT InfContext;
371 WCHAR szNameBuffer[256];
372 WCHAR szSectionBuffer[256];
373 HINF hComponentInf = INVALID_HANDLE_VALUE;
374
375 if (!SetupFindFirstLineW(hSysSetupInf,
376 L"Infs.Always",
377 NULL,
378 &InfContext))
379 {
380 DPRINT("No Inf.Always section found\n");
381 }
382 else
383 {
384 do
385 {
386 if (!SetupGetStringFieldW(&InfContext,
387 1, // Get the component name
388 szNameBuffer,
389 sizeof(szNameBuffer)/sizeof(szNameBuffer[0]),
390 NULL))
391 {
392 FatalError("Error while trying to get component name \n");
393 return FALSE;
394 }
395
396 if (!SetupGetStringFieldW(&InfContext,
397 2, // Get the component install section
398 szSectionBuffer,
399 sizeof(szSectionBuffer)/sizeof(szSectionBuffer[0]),
400 NULL))
401 {
402 FatalError("Error while trying to get component install section \n");
403 return FALSE;
404 }
405
406 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer, szNameBuffer);
407
408 hComponentInf = SetupOpenInfFileW(szNameBuffer,
409 NULL,
410 INF_STYLE_WIN4,
411 NULL);
412
413 if (hComponentInf == INVALID_HANDLE_VALUE)
414 {
415 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer, GetLastError());
416 return FALSE;
417 }
418
419 if (!SetupInstallFromInfSectionW(NULL,
420 hComponentInf,
421 szSectionBuffer,
422 SPINST_ALL,
423 NULL,
424 NULL,
425 SP_COPY_NEWER,
426 SetupDefaultQueueCallbackW,
427 NULL,
428 NULL,
429 NULL))
430 {
431 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer, GetLastError());
432 SetupCloseInfFile(hComponentInf);
433 return FALSE;
434 }
435
436 SetupCloseInfFile(hComponentInf);
437 }
438 while (SetupFindNextLine(&InfContext, &InfContext));
439 }
440
441 return TRUE;
442 }
443
444
445
446
447 BOOL
448 RegisterTypeLibraries (HINF hinf, LPCWSTR szSection)
449 {
450 INFCONTEXT InfContext;
451 BOOL res;
452 WCHAR szName[MAX_PATH];
453 WCHAR szPath[MAX_PATH];
454 INT csidl;
455 LPWSTR p;
456 HMODULE hmod;
457 HRESULT hret;
458
459 /* Begin iterating the entries in the inf section */
460 res = SetupFindFirstLine(hinf, szSection, NULL, &InfContext);
461 if (!res) return FALSE;
462
463 do
464 {
465 /* Get the name of the current type library */
466 if (!SetupGetStringFieldW(&InfContext, 1, szName, MAX_PATH, NULL))
467 {
468 FatalError("SetupGetStringFieldW failed\n");
469 continue;
470 }
471
472 if (!SetupGetIntField(&InfContext, 2, &csidl))
473 csidl = CSIDL_SYSTEM;
474
475 hret = SHGetFolderPathW(NULL, csidl, NULL, 0, szPath);
476 if (FAILED(hret))
477 {
478 FatalError("SHGetFolderPathW failed hret=0x%d\n", hret);
479 continue;
480 }
481
482 p = PathAddBackslash(szPath);
483 _tcscpy(p, szName);
484
485 hmod = LoadLibraryW(szName);
486 if (hmod == NULL)
487 {
488 FatalError("LoadLibraryW failed\n");
489 continue;
490 }
491
492 __wine_register_resources(hmod);
493
494 }while (SetupFindNextLine(&InfContext, &InfContext));
495
496 return TRUE;
497 }
498
499 static BOOL
500 EnableUserModePnpManager(VOID)
501 {
502 SC_HANDLE hSCManager = NULL;
503 SC_HANDLE hService = NULL;
504 BOOL bRet = FALSE;
505
506 hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
507 if (hSCManager == NULL)
508 {
509 DPRINT1("Unable to open the service control manager.\n");
510 DPRINT1("Last Error %d\n", GetLastError());
511 goto cleanup;
512 }
513
514 hService = OpenServiceW(hSCManager,
515 L"PlugPlay",
516 SERVICE_CHANGE_CONFIG | SERVICE_START);
517 if (hService == NULL)
518 {
519 DPRINT1("Unable to open PlugPlay service\n");
520 goto cleanup;
521 }
522
523 bRet = ChangeServiceConfigW(hService,
524 SERVICE_NO_CHANGE,
525 SERVICE_AUTO_START,
526 SERVICE_NO_CHANGE,
527 NULL, NULL, NULL,
528 NULL, NULL, NULL, NULL);
529 if (!bRet)
530 {
531 DPRINT1("Unable to change the service configuration\n");
532 goto cleanup;
533 }
534
535 bRet = StartServiceW(hService, 0, NULL);
536 if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
537 {
538 DPRINT1("Unable to start service\n");
539 goto cleanup;
540 }
541
542 bRet = TRUE;
543
544 cleanup:
545 if (hService != NULL)
546 CloseServiceHandle(hService);
547 if (hSCManager != NULL)
548 CloseServiceHandle(hSCManager);
549 return bRet;
550 }
551
552 static INT_PTR CALLBACK
553 StatusMessageWindowProc(
554 IN HWND hwndDlg,
555 IN UINT uMsg,
556 IN WPARAM wParam,
557 IN LPARAM lParam)
558 {
559 UNREFERENCED_PARAMETER(wParam);
560
561 switch (uMsg)
562 {
563 case WM_INITDIALOG:
564 {
565 WCHAR szMsg[256];
566
567 if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
568 return FALSE;
569 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
570 return TRUE;
571 }
572 }
573 return FALSE;
574 }
575
576 static DWORD WINAPI
577 ShowStatusMessageThread(
578 IN LPVOID lpParameter)
579 {
580 HWND *phWnd = (HWND *)lpParameter;
581 HWND hWnd;
582 MSG Msg;
583
584 hWnd = CreateDialogParam(
585 hDllInstance,
586 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
587 GetDesktopWindow(),
588 StatusMessageWindowProc,
589 (LPARAM)NULL);
590 if (!hWnd)
591 return 0;
592 *phWnd = hWnd;
593
594 ShowWindow(hWnd, SW_SHOW);
595
596 /* Message loop for the Status window */
597 while (GetMessage(&Msg, NULL, 0, 0))
598 {
599 TranslateMessage(&Msg);
600 DispatchMessage(&Msg);
601 }
602
603 return 0;
604 }
605
606 static LONG
607 ReadRegSzKey(
608 IN HKEY hKey,
609 IN LPCWSTR pszKey,
610 OUT LPWSTR* pValue)
611 {
612 LONG rc;
613 DWORD dwType;
614 DWORD cbData = 0;
615 LPWSTR pwszValue;
616
617 if (!pValue)
618 return ERROR_INVALID_PARAMETER;
619
620 *pValue = NULL;
621 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
622 if (rc != ERROR_SUCCESS)
623 return rc;
624 if (dwType != REG_SZ)
625 return ERROR_FILE_NOT_FOUND;
626 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
627 if (!pwszValue)
628 return ERROR_NOT_ENOUGH_MEMORY;
629 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData);
630 if (rc != ERROR_SUCCESS)
631 {
632 HeapFree(GetProcessHeap(), 0, pwszValue);
633 return rc;
634 }
635 /* NULL-terminate the string */
636 pwszValue[cbData / sizeof(WCHAR)] = '\0';
637
638 *pValue = pwszValue;
639 return ERROR_SUCCESS;
640 }
641
642 static BOOL
643 IsConsoleBoot(VOID)
644 {
645 HKEY hControlKey = NULL;
646 LPWSTR pwszSystemStartOptions = NULL;
647 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */
648 BOOL bConsoleBoot = FALSE;
649 LONG rc;
650
651 rc = RegOpenKeyExW(
652 HKEY_LOCAL_MACHINE,
653 L"SYSTEM\\CurrentControlSet\\Control",
654 0,
655 KEY_QUERY_VALUE,
656 &hControlKey);
657 if (rc != ERROR_SUCCESS)
658 goto cleanup;
659
660 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions);
661 if (rc != ERROR_SUCCESS)
662 goto cleanup;
663
664 /* Check for CONSOLE switch in SystemStartOptions */
665 pwszCurrentOption = pwszSystemStartOptions;
666 while (pwszCurrentOption)
667 {
668 pwszNextOption = wcschr(pwszCurrentOption, L' ');
669 if (pwszNextOption)
670 *pwszNextOption = L'\0';
671 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0)
672 {
673 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption);
674 bConsoleBoot = TRUE;
675 goto cleanup;
676 }
677 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL;
678 }
679
680 cleanup:
681 if (hControlKey != NULL)
682 RegCloseKey(hControlKey);
683 if (pwszSystemStartOptions)
684 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions);
685 return bConsoleBoot;
686 }
687
688 static BOOL
689 CommonInstall(VOID)
690 {
691 HWND hWnd = NULL;
692
693 hSysSetupInf = SetupOpenInfFileW(
694 L"syssetup.inf",
695 NULL,
696 INF_STYLE_WIN4,
697 NULL);
698 if (hSysSetupInf == INVALID_HANDLE_VALUE)
699 {
700 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
701 return FALSE;
702 }
703
704 if (!InstallSysSetupInfDevices())
705 {
706 FatalError("InstallSysSetupInfDevices() failed!\n");
707 goto error;
708 }
709
710 if(!InstallSysSetupInfComponents())
711 {
712 FatalError("InstallSysSetupInfComponents() failed!\n");
713 goto error;
714 }
715
716 if (!IsConsoleBoot())
717 {
718 HANDLE hThread;
719
720 hThread = CreateThread(
721 NULL,
722 0,
723 ShowStatusMessageThread,
724 (LPVOID)&hWnd,
725 0,
726 NULL);
727
728 if (hThread)
729 CloseHandle(hThread);
730 }
731
732 if (!EnableUserModePnpManager())
733 {
734 FatalError("EnableUserModePnpManager() failed!\n");
735 goto error;
736 }
737
738 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
739 {
740 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
741 goto error;
742 }
743
744 EndDialog(hWnd, 0);
745 return TRUE;
746
747 error:
748 if (hWnd)
749 EndDialog(hWnd, 0);
750 SetupCloseInfFile(hSysSetupInf);
751 return FALSE;
752 }
753
754 DWORD WINAPI
755 InstallLiveCD(IN HINSTANCE hInstance)
756 {
757 STARTUPINFOW StartupInfo;
758 PROCESS_INFORMATION ProcessInformation;
759 BOOL bRes;
760
761 if (!CommonInstall())
762 goto error;
763
764 /* Register components */
765 _SEH2_TRY
766 {
767 if (!SetupInstallFromInfSectionW(NULL,
768 hSysSetupInf, L"RegistrationPhase2",
769 SPINST_ALL,
770 0, NULL, 0, NULL, NULL, NULL, NULL))
771 {
772 DPRINT1("SetupInstallFromInfSectionW failed!\n");
773 }
774
775 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries");
776 }
777 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
778 {
779 DPRINT1("Catching exception\n");
780 }
781 _SEH2_END;
782
783 SetupCloseInfFile(hSysSetupInf);
784
785 /* Run the shell */
786 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
787 StartupInfo.cb = sizeof(StartupInfo);
788 bRes = CreateProcessW(
789 L"userinit.exe",
790 NULL,
791 NULL,
792 NULL,
793 FALSE,
794 0,
795 NULL,
796 NULL,
797 &StartupInfo,
798 &ProcessInformation);
799 if (!bRes)
800 goto error;
801
802 CloseHandle(ProcessInformation.hThread);
803 CloseHandle(ProcessInformation.hProcess);
804
805 return 0;
806
807 error:
808 MessageBoxW(
809 NULL,
810 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
811 L"ReactOS LiveCD",
812 MB_OK);
813 return 0;
814 }
815
816
817 static BOOL
818 SetSetupType(DWORD dwSetupType)
819 {
820 DWORD dwError;
821 HKEY hKey;
822
823 dwError = RegOpenKeyExW(
824 HKEY_LOCAL_MACHINE,
825 L"SYSTEM\\Setup",
826 0,
827 KEY_SET_VALUE,
828 &hKey);
829 if (dwError != ERROR_SUCCESS)
830 return FALSE;
831
832 dwError = RegSetValueExW(
833 hKey,
834 L"SetupType",
835 0,
836 REG_DWORD,
837 (LPBYTE)&dwSetupType,
838 sizeof(DWORD));
839 RegCloseKey(hKey);
840 if (dwError != ERROR_SUCCESS)
841 return FALSE;
842
843 return TRUE;
844 }
845
846 DWORD WINAPI
847 InstallReactOS(HINSTANCE hInstance)
848 {
849 TCHAR szBuffer[MAX_PATH];
850 HANDLE token;
851 TOKEN_PRIVILEGES privs;
852 HKEY hKey;
853 HINF hShortcutsInf;
854
855 InitializeSetupActionLog(FALSE);
856 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
857
858 if (!InitializeProfiles())
859 {
860 FatalError("InitializeProfiles() failed");
861 return 0;
862 }
863
864 CreateTempDir(L"TEMP");
865 CreateTempDir(L"TMP");
866
867 if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
868 {
869 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
870 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
871 0,
872 KEY_WRITE,
873 &hKey) == ERROR_SUCCESS)
874 {
875 RegSetValueExW(hKey,
876 L"PathName",
877 0,
878 REG_SZ,
879 (LPBYTE)szBuffer,
880 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
881
882 RegSetValueExW(hKey,
883 L"SystemRoot",
884 0,
885 REG_SZ,
886 (LPBYTE)szBuffer,
887 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
888
889 RegCloseKey(hKey);
890 }
891
892 PathAddBackslash(szBuffer);
893 _tcscat(szBuffer, _T("system"));
894 CreateDirectory(szBuffer, NULL);
895 }
896
897 if (!CommonInstall())
898 return 0;
899
900 InstallWizard();
901
902 InstallSecurity();
903
904 SetAutoAdminLogon();
905
906 hShortcutsInf = SetupOpenInfFileW(L"shortcuts.inf",
907 NULL,
908 INF_STYLE_WIN4,
909 NULL);
910 if (hShortcutsInf == INVALID_HANDLE_VALUE)
911 {
912 FatalError("Failed to open shortcuts.inf");
913 return 0;
914 }
915
916 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders"))
917 {
918 FatalError("CreateShortcuts() failed");
919 return 0;
920 }
921
922 SetupCloseInfFile(hShortcutsInf);
923
924 /* ROS HACK, as long as NtUnloadKey is not implemented */
925 {
926 NTSTATUS Status = NtUnloadKey(NULL);
927 if (Status == STATUS_NOT_IMPLEMENTED)
928 {
929 /* Create the Administrator profile */
930 PROFILEINFOW ProfileInfo;
931 HANDLE hToken;
932 BOOL ret;
933
934 ret = LogonUserW(AdminInfo.Name,
935 AdminInfo.Domain,
936 AdminInfo.Password,
937 LOGON32_LOGON_INTERACTIVE,
938 LOGON32_PROVIDER_DEFAULT,
939 &hToken);
940 if (!ret)
941 {
942 FatalError("LogonUserW() failed!");
943 return 0;
944 }
945 ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
946 ProfileInfo.dwSize = sizeof(PROFILEINFOW);
947 ProfileInfo.lpUserName = L"Administrator";
948 ProfileInfo.dwFlags = PI_NOUI;
949 LoadUserProfileW(hToken, &ProfileInfo);
950 CloseHandle(hToken);
951 }
952 else
953 {
954 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
955 }
956 }
957 /* END OF ROS HACK */
958
959 SetupCloseInfFile(hSysSetupInf);
960 SetSetupType(0);
961
962 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS done");
963 TerminateSetupActionLog();
964
965 if (AdminInfo.Name != NULL)
966 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Name);
967
968 if (AdminInfo.Domain != NULL)
969 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Domain);
970
971 if (AdminInfo.Password != NULL)
972 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Password);
973
974 /* Get shutdown privilege */
975 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
976 {
977 FatalError("OpenProcessToken() failed!");
978 return 0;
979 }
980 if (!LookupPrivilegeValue(
981 NULL,
982 SE_SHUTDOWN_NAME,
983 &privs.Privileges[0].Luid))
984 {
985 FatalError("LookupPrivilegeValue() failed!");
986 return 0;
987 }
988 privs.PrivilegeCount = 1;
989 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
990 if (AdjustTokenPrivileges(
991 token,
992 FALSE,
993 &privs,
994 0,
995 (PTOKEN_PRIVILEGES)NULL,
996 NULL) == 0)
997 {
998 FatalError("AdjustTokenPrivileges() failed!");
999 return 0;
1000 }
1001
1002 ExitWindowsEx(EWX_REBOOT, 0);
1003 return 0;
1004 }
1005
1006
1007 /*
1008 * @unimplemented
1009 */
1010 DWORD WINAPI
1011 SetupChangeFontSize(
1012 IN HANDLE hWnd,
1013 IN LPCWSTR lpszFontSize)
1014 {
1015 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1016 return FALSE;
1017 }
1018
1019 /*
1020 * @unimplemented
1021 */
1022 DWORD WINAPI
1023 SetupChangeLocaleEx(HWND hWnd,
1024 LCID Lcid,
1025 LPCWSTR lpSrcRootPath,
1026 char Unknown,
1027 DWORD dwUnused1,
1028 DWORD dwUnused2)
1029 {
1030 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1031 return FALSE;
1032 }
1033
1034 /*
1035 * @implemented
1036 */
1037 DWORD WINAPI
1038 SetupChangeLocale(HWND hWnd, LCID Lcid)
1039 {
1040 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
1041 }