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