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