* Sync up to trunk HEAD (r62975).
[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 LPWSTR p;
245
246 CoInitialize(NULL);
247
248 if (!SetupFindFirstLine(hinf, szSection, NULL, &Context))
249 return FALSE;
250
251 do
252 {
253 if (SetupGetFieldCount(&Context) < 2)
254 continue;
255
256 if (!SetupGetStringFieldW(&Context, 0, szFolderSection, MAX_PATH, NULL))
257 continue;
258
259 if (!SetupGetIntField(&Context, 1, &csidl))
260 continue;
261
262 if (!SetupGetStringFieldW(&Context, 2, szFolder, MAX_PATH, NULL))
263 continue;
264
265 if (!SHGetSpecialFolderPathW(0, szPath, csidl, TRUE))
266 continue;
267
268 p = PathAddBackslash(szPath);
269 _tcscpy(p, szFolder);
270
271 if (!CreateDirectory(szPath, NULL))
272 {
273 if (GetLastError() != ERROR_ALREADY_EXISTS)
274 {
275 continue;
276 }
277 }
278
279 CreateShortcutsFromSection(hinf, szFolderSection, szPath);
280
281 }while (SetupFindNextLine(&Context, &Context));
282
283 CoUninitialize();
284
285 return TRUE;
286 }
287
288 static VOID
289 CreateTempDir(
290 IN LPCWSTR VarName)
291 {
292 WCHAR szTempDir[MAX_PATH];
293 WCHAR szBuffer[MAX_PATH];
294 DWORD dwLength;
295 HKEY hKey;
296
297 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
298 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
299 0,
300 KEY_QUERY_VALUE,
301 &hKey) != ERROR_SUCCESS)
302 {
303 FatalError("Error: %lu\n", GetLastError());
304 return;
305 }
306
307 /* Get temp dir */
308 dwLength = MAX_PATH * sizeof(WCHAR);
309 if (RegQueryValueExW(hKey,
310 VarName,
311 NULL,
312 NULL,
313 (LPBYTE)szBuffer,
314 &dwLength) != ERROR_SUCCESS)
315 {
316 FatalError("Error: %lu\n", GetLastError());
317 goto cleanup;
318 }
319
320 /* Expand it */
321 if (!ExpandEnvironmentStringsW(szBuffer,
322 szTempDir,
323 MAX_PATH))
324 {
325 FatalError("Error: %lu\n", GetLastError());
326 goto cleanup;
327 }
328
329 /* Create profiles directory */
330 if (!CreateDirectoryW(szTempDir, NULL))
331 {
332 if (GetLastError() != ERROR_ALREADY_EXISTS)
333 {
334 FatalError("Error: %lu\n", GetLastError());
335 goto cleanup;
336 }
337 }
338
339 cleanup:
340 RegCloseKey(hKey);
341 }
342
343 static BOOL
344 InstallSysSetupInfDevices(VOID)
345 {
346 INFCONTEXT InfContext;
347 WCHAR szLineBuffer[256];
348 DWORD dwLineLength;
349
350 if (!SetupFindFirstLineW(hSysSetupInf,
351 L"DeviceInfsToInstall",
352 NULL,
353 &InfContext))
354 {
355 return FALSE;
356 }
357
358 do
359 {
360 if (!SetupGetStringFieldW(&InfContext,
361 0,
362 szLineBuffer,
363 sizeof(szLineBuffer)/sizeof(szLineBuffer[0]),
364 &dwLineLength))
365 {
366 return FALSE;
367 }
368
369 if (!SetupDiInstallClassW(NULL, szLineBuffer, DI_QUIETINSTALL, NULL))
370 {
371 return FALSE;
372 }
373 }
374 while (SetupFindNextLine(&InfContext, &InfContext));
375
376 return TRUE;
377 }
378
379 static BOOL
380 InstallSysSetupInfComponents(VOID)
381 {
382 INFCONTEXT InfContext;
383 WCHAR szNameBuffer[256];
384 WCHAR szSectionBuffer[256];
385 HINF hComponentInf = INVALID_HANDLE_VALUE;
386
387 if (!SetupFindFirstLineW(hSysSetupInf,
388 L"Infs.Always",
389 NULL,
390 &InfContext))
391 {
392 DPRINT("No Inf.Always section found\n");
393 }
394 else
395 {
396 do
397 {
398 if (!SetupGetStringFieldW(&InfContext,
399 1, // Get the component name
400 szNameBuffer,
401 sizeof(szNameBuffer)/sizeof(szNameBuffer[0]),
402 NULL))
403 {
404 FatalError("Error while trying to get component name \n");
405 return FALSE;
406 }
407
408 if (!SetupGetStringFieldW(&InfContext,
409 2, // Get the component install section
410 szSectionBuffer,
411 sizeof(szSectionBuffer)/sizeof(szSectionBuffer[0]),
412 NULL))
413 {
414 FatalError("Error while trying to get component install section \n");
415 return FALSE;
416 }
417
418 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer, szNameBuffer);
419
420 hComponentInf = SetupOpenInfFileW(szNameBuffer,
421 NULL,
422 INF_STYLE_WIN4,
423 NULL);
424
425 if (hComponentInf == INVALID_HANDLE_VALUE)
426 {
427 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer, GetLastError());
428 return FALSE;
429 }
430
431 if (!SetupInstallFromInfSectionW(NULL,
432 hComponentInf,
433 szSectionBuffer,
434 SPINST_ALL,
435 NULL,
436 NULL,
437 SP_COPY_NEWER,
438 SetupDefaultQueueCallbackW,
439 NULL,
440 NULL,
441 NULL))
442 {
443 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer, GetLastError());
444 SetupCloseInfFile(hComponentInf);
445 return FALSE;
446 }
447
448 SetupCloseInfFile(hComponentInf);
449 }
450 while (SetupFindNextLine(&InfContext, &InfContext));
451 }
452
453 return TRUE;
454 }
455
456
457
458
459 BOOL
460 RegisterTypeLibraries (HINF hinf, LPCWSTR szSection)
461 {
462 INFCONTEXT InfContext;
463 BOOL res;
464 WCHAR szName[MAX_PATH];
465 WCHAR szPath[MAX_PATH];
466 INT csidl;
467 LPWSTR p;
468 HMODULE hmod;
469 HRESULT hret;
470
471 /* Begin iterating the entries in the inf section */
472 res = SetupFindFirstLine(hinf, szSection, NULL, &InfContext);
473 if (!res) return FALSE;
474
475 do
476 {
477 /* Get the name of the current type library */
478 if (!SetupGetStringFieldW(&InfContext, 1, szName, MAX_PATH, NULL))
479 {
480 FatalError("SetupGetStringFieldW failed\n");
481 continue;
482 }
483
484 if (!SetupGetIntField(&InfContext, 2, &csidl))
485 csidl = CSIDL_SYSTEM;
486
487 hret = SHGetFolderPathW(NULL, csidl, NULL, 0, szPath);
488 if (FAILED(hret))
489 {
490 FatalError("SHGetSpecialFolderPathW failed hret=0x%d\n", hret);
491 continue;
492 }
493
494 p = PathAddBackslash(szPath);
495 _tcscpy(p, szName);
496
497 hmod = LoadLibraryW(szName);
498 if (hmod == NULL)
499 {
500 FatalError("LoadLibraryW failed\n");
501 continue;
502 }
503
504 __wine_register_resources(hmod);
505
506 }while (SetupFindNextLine(&InfContext, &InfContext));
507
508 return TRUE;
509 }
510
511 static BOOL
512 EnableUserModePnpManager(VOID)
513 {
514 SC_HANDLE hSCManager = NULL;
515 SC_HANDLE hService = NULL;
516 BOOL bRet = FALSE;
517
518 hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
519 if (hSCManager == NULL)
520 {
521 DPRINT1("Unable to open the service control manager.\n");
522 DPRINT1("Last Error %d\n", GetLastError());
523 goto cleanup;
524 }
525
526 hService = OpenServiceW(hSCManager,
527 L"PlugPlay",
528 SERVICE_CHANGE_CONFIG | SERVICE_START);
529 if (hService == NULL)
530 {
531 DPRINT1("Unable to open PlugPlay service\n");
532 goto cleanup;
533 }
534
535 bRet = ChangeServiceConfigW(hService,
536 SERVICE_NO_CHANGE,
537 SERVICE_AUTO_START,
538 SERVICE_NO_CHANGE,
539 NULL, NULL, NULL,
540 NULL, NULL, NULL, NULL);
541 if (!bRet)
542 {
543 DPRINT1("Unable to change the service configuration\n");
544 goto cleanup;
545 }
546
547 bRet = StartServiceW(hService, 0, NULL);
548 if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
549 {
550 DPRINT1("Unable to start service\n");
551 goto cleanup;
552 }
553
554 bRet = TRUE;
555
556 cleanup:
557 if (hService != NULL)
558 CloseServiceHandle(hService);
559 if (hSCManager != NULL)
560 CloseServiceHandle(hSCManager);
561 return bRet;
562 }
563
564 static INT_PTR CALLBACK
565 StatusMessageWindowProc(
566 IN HWND hwndDlg,
567 IN UINT uMsg,
568 IN WPARAM wParam,
569 IN LPARAM lParam)
570 {
571 UNREFERENCED_PARAMETER(wParam);
572
573 switch (uMsg)
574 {
575 case WM_INITDIALOG:
576 {
577 WCHAR szMsg[256];
578
579 if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
580 return FALSE;
581 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
582 return TRUE;
583 }
584 }
585 return FALSE;
586 }
587
588 static DWORD WINAPI
589 ShowStatusMessageThread(
590 IN LPVOID lpParameter)
591 {
592 HWND *phWnd = (HWND *)lpParameter;
593 HWND hWnd;
594 MSG Msg;
595
596 hWnd = CreateDialogParam(
597 hDllInstance,
598 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
599 GetDesktopWindow(),
600 StatusMessageWindowProc,
601 (LPARAM)NULL);
602 if (!hWnd)
603 return 0;
604 *phWnd = hWnd;
605
606 ShowWindow(hWnd, SW_SHOW);
607
608 /* Message loop for the Status window */
609 while (GetMessage(&Msg, NULL, 0, 0))
610 {
611 TranslateMessage(&Msg);
612 DispatchMessage(&Msg);
613 }
614
615 return 0;
616 }
617
618 static LONG
619 ReadRegSzKey(
620 IN HKEY hKey,
621 IN LPCWSTR pszKey,
622 OUT LPWSTR* pValue)
623 {
624 LONG rc;
625 DWORD dwType;
626 DWORD cbData = 0;
627 LPWSTR pwszValue;
628
629 if (!pValue)
630 return ERROR_INVALID_PARAMETER;
631
632 *pValue = NULL;
633 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
634 if (rc != ERROR_SUCCESS)
635 return rc;
636 if (dwType != REG_SZ)
637 return ERROR_FILE_NOT_FOUND;
638 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
639 if (!pwszValue)
640 return ERROR_NOT_ENOUGH_MEMORY;
641 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData);
642 if (rc != ERROR_SUCCESS)
643 {
644 HeapFree(GetProcessHeap(), 0, pwszValue);
645 return rc;
646 }
647 /* NULL-terminate the string */
648 pwszValue[cbData / sizeof(WCHAR)] = '\0';
649
650 *pValue = pwszValue;
651 return ERROR_SUCCESS;
652 }
653
654 static BOOL
655 IsConsoleBoot(VOID)
656 {
657 HKEY hControlKey = NULL;
658 LPWSTR pwszSystemStartOptions = NULL;
659 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */
660 BOOL bConsoleBoot = FALSE;
661 LONG rc;
662
663 rc = RegOpenKeyExW(
664 HKEY_LOCAL_MACHINE,
665 L"SYSTEM\\CurrentControlSet\\Control",
666 0,
667 KEY_QUERY_VALUE,
668 &hControlKey);
669 if (rc != ERROR_SUCCESS)
670 goto cleanup;
671
672 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions);
673 if (rc != ERROR_SUCCESS)
674 goto cleanup;
675
676 /* Check for CONSOLE switch in SystemStartOptions */
677 pwszCurrentOption = pwszSystemStartOptions;
678 while (pwszCurrentOption)
679 {
680 pwszNextOption = wcschr(pwszCurrentOption, L' ');
681 if (pwszNextOption)
682 *pwszNextOption = L'\0';
683 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0)
684 {
685 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption);
686 bConsoleBoot = TRUE;
687 goto cleanup;
688 }
689 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL;
690 }
691
692 cleanup:
693 if (hControlKey != NULL)
694 RegCloseKey(hControlKey);
695 if (pwszSystemStartOptions)
696 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions);
697 return bConsoleBoot;
698 }
699
700 static BOOL
701 CommonInstall(VOID)
702 {
703 HWND hWnd = NULL;
704
705 hSysSetupInf = SetupOpenInfFileW(
706 L"syssetup.inf",
707 NULL,
708 INF_STYLE_WIN4,
709 NULL);
710 if (hSysSetupInf == INVALID_HANDLE_VALUE)
711 {
712 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
713 return FALSE;
714 }
715
716 if (!InstallSysSetupInfDevices())
717 {
718 FatalError("InstallSysSetupInfDevices() failed!\n");
719 goto error;
720 }
721
722 if(!InstallSysSetupInfComponents())
723 {
724 FatalError("InstallSysSetupInfComponents() failed!\n");
725 goto error;
726 }
727
728 if (!IsConsoleBoot())
729 {
730 HANDLE hThread;
731
732 hThread = CreateThread(
733 NULL,
734 0,
735 ShowStatusMessageThread,
736 (LPVOID)&hWnd,
737 0,
738 NULL);
739
740 if (hThread)
741 CloseHandle(hThread);
742 }
743
744 if (!EnableUserModePnpManager())
745 {
746 FatalError("EnableUserModePnpManager() failed!\n");
747 goto error;
748 }
749
750 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
751 {
752 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
753 goto error;
754 }
755
756 EndDialog(hWnd, 0);
757 return TRUE;
758
759 error:
760 if (hWnd)
761 EndDialog(hWnd, 0);
762 SetupCloseInfFile(hSysSetupInf);
763 return FALSE;
764 }
765
766 DWORD WINAPI
767 InstallLiveCD(IN HINSTANCE hInstance)
768 {
769 STARTUPINFOW StartupInfo;
770 PROCESS_INFORMATION ProcessInformation;
771 BOOL bRes;
772
773 if (!CommonInstall())
774 goto error;
775
776 /* Register components */
777 _SEH2_TRY
778 {
779 if (!SetupInstallFromInfSectionW(NULL,
780 hSysSetupInf, L"RegistrationPhase2",
781 SPINST_ALL,
782 0, NULL, 0, NULL, NULL, NULL, NULL))
783 {
784 DPRINT1("SetupInstallFromInfSectionW failed!\n");
785 }
786
787 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries");
788 }
789 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
790 {
791 DPRINT1("Catching exception\n");
792 }
793 _SEH2_END;
794
795 SetupCloseInfFile(hSysSetupInf);
796
797 /* Run the shell */
798 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
799 StartupInfo.cb = sizeof(StartupInfo);
800 bRes = CreateProcessW(
801 L"userinit.exe",
802 NULL,
803 NULL,
804 NULL,
805 FALSE,
806 0,
807 NULL,
808 NULL,
809 &StartupInfo,
810 &ProcessInformation);
811 if (!bRes)
812 goto error;
813
814 CloseHandle(ProcessInformation.hThread);
815 CloseHandle(ProcessInformation.hProcess);
816
817 return 0;
818
819 error:
820 MessageBoxW(
821 NULL,
822 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
823 L"ReactOS LiveCD",
824 MB_OK);
825 return 0;
826 }
827
828
829 static BOOL
830 SetSetupType(DWORD dwSetupType)
831 {
832 DWORD dwError;
833 HKEY hKey;
834
835 dwError = RegOpenKeyExW(
836 HKEY_LOCAL_MACHINE,
837 L"SYSTEM\\Setup",
838 0,
839 KEY_SET_VALUE,
840 &hKey);
841 if (dwError != ERROR_SUCCESS)
842 return FALSE;
843
844 dwError = RegSetValueExW(
845 hKey,
846 L"SetupType",
847 0,
848 REG_DWORD,
849 (LPBYTE)&dwSetupType,
850 sizeof(DWORD));
851 RegCloseKey(hKey);
852 if (dwError != ERROR_SUCCESS)
853 return FALSE;
854
855 return TRUE;
856 }
857
858 DWORD WINAPI
859 InstallReactOS(HINSTANCE hInstance)
860 {
861 TCHAR szBuffer[MAX_PATH];
862 HANDLE token;
863 TOKEN_PRIVILEGES privs;
864 HKEY hKey;
865 HINF hShortcutsInf;
866
867 InitializeSetupActionLog(FALSE);
868 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
869
870 if (!InitializeProfiles())
871 {
872 FatalError("InitializeProfiles() failed");
873 return 0;
874 }
875
876 CreateTempDir(L"TEMP");
877 CreateTempDir(L"TMP");
878
879 if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
880 {
881 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
882 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
883 0,
884 KEY_WRITE,
885 &hKey) == ERROR_SUCCESS)
886 {
887 RegSetValueExW(hKey,
888 L"PathName",
889 0,
890 REG_SZ,
891 (LPBYTE)szBuffer,
892 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
893
894 RegSetValueExW(hKey,
895 L"SystemRoot",
896 0,
897 REG_SZ,
898 (LPBYTE)szBuffer,
899 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
900
901 RegCloseKey(hKey);
902 }
903
904 PathAddBackslash(szBuffer);
905 _tcscat(szBuffer, _T("system"));
906 CreateDirectory(szBuffer, NULL);
907 }
908
909 if (!CommonInstall())
910 return 0;
911
912 InstallWizard();
913
914 InstallSecurity();
915
916 SetAutoAdminLogon();
917
918 hShortcutsInf = SetupOpenInfFileW(L"shortcuts.inf",
919 NULL,
920 INF_STYLE_WIN4,
921 NULL);
922 if (hShortcutsInf == INVALID_HANDLE_VALUE)
923 {
924 FatalError("Failed to open shortcuts.inf");
925 return 0;
926 }
927
928 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders"))
929 {
930 FatalError("CreateShortcuts() failed");
931 return 0;
932 }
933
934 SetupCloseInfFile(hShortcutsInf);
935
936 /* ROS HACK, as long as NtUnloadKey is not implemented */
937 {
938 NTSTATUS Status = NtUnloadKey(NULL);
939 if (Status == STATUS_NOT_IMPLEMENTED)
940 {
941 /* Create the Administrator profile */
942 PROFILEINFOW ProfileInfo;
943 HANDLE hToken;
944 BOOL ret;
945
946 ret = LogonUserW(AdminInfo.Name,
947 AdminInfo.Domain,
948 AdminInfo.Password,
949 LOGON32_LOGON_INTERACTIVE,
950 LOGON32_PROVIDER_DEFAULT,
951 &hToken);
952 if (!ret)
953 {
954 FatalError("LogonUserW() failed!");
955 return 0;
956 }
957 ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
958 ProfileInfo.dwSize = sizeof(PROFILEINFOW);
959 ProfileInfo.lpUserName = L"Administrator";
960 ProfileInfo.dwFlags = PI_NOUI;
961 LoadUserProfileW(hToken, &ProfileInfo);
962 CloseHandle(hToken);
963 }
964 else
965 {
966 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
967 }
968 }
969 /* END OF ROS HACK */
970
971 SetupCloseInfFile(hSysSetupInf);
972 SetSetupType(0);
973
974 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS done");
975 TerminateSetupActionLog();
976
977 if (AdminInfo.Name != NULL)
978 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Name);
979
980 if (AdminInfo.Domain != NULL)
981 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Domain);
982
983 if (AdminInfo.Password != NULL)
984 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Password);
985
986 /* Get shutdown privilege */
987 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
988 {
989 FatalError("OpenProcessToken() failed!");
990 return 0;
991 }
992 if (!LookupPrivilegeValue(
993 NULL,
994 SE_SHUTDOWN_NAME,
995 &privs.Privileges[0].Luid))
996 {
997 FatalError("LookupPrivilegeValue() failed!");
998 return 0;
999 }
1000 privs.PrivilegeCount = 1;
1001 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1002 if (AdjustTokenPrivileges(
1003 token,
1004 FALSE,
1005 &privs,
1006 0,
1007 (PTOKEN_PRIVILEGES)NULL,
1008 NULL) == 0)
1009 {
1010 FatalError("AdjustTokenPrivileges() failed!");
1011 return 0;
1012 }
1013
1014 ExitWindowsEx(EWX_REBOOT, 0);
1015 return 0;
1016 }
1017
1018
1019 /*
1020 * @unimplemented
1021 */
1022 DWORD WINAPI
1023 SetupChangeFontSize(
1024 IN HANDLE hWnd,
1025 IN LPCWSTR lpszFontSize)
1026 {
1027 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1028 return FALSE;
1029 }
1030
1031 /*
1032 * @unimplemented
1033 */
1034 DWORD WINAPI
1035 SetupChangeLocaleEx(HWND hWnd,
1036 LCID Lcid,
1037 LPCWSTR lpSrcRootPath,
1038 char Unknown,
1039 DWORD dwUnused1,
1040 DWORD dwUnused2)
1041 {
1042 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1043 return FALSE;
1044 }
1045
1046 /*
1047 * @implemented
1048 */
1049 DWORD WINAPI
1050 SetupChangeLocale(HWND hWnd, LCID Lcid)
1051 {
1052 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
1053 }