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