[SYSSETUP]
[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 #define NDEBUG
32 #include <debug.h>
33
34 DWORD WINAPI
35 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout);
36
37 /* GLOBALS ******************************************************************/
38
39 PSID DomainSid = NULL;
40 PSID AdminSid = NULL;
41
42 HINF hSysSetupInf = INVALID_HANDLE_VALUE;
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 int csidl,
132 LPCTSTR pszFolder,
133 UINT nIdName,
134 LPCTSTR pszCommand,
135 UINT nIdTitle,
136 BOOL bCheckExistence,
137 INT iIconNr)
138 {
139 TCHAR szPath[MAX_PATH];
140 TCHAR szExeName[MAX_PATH];
141 TCHAR szTitle[256];
142 TCHAR szName[256];
143 LPTSTR Ptr = szPath;
144 TCHAR szWorkingDirBuf[MAX_PATH];
145 LPTSTR pszWorkingDir = NULL;
146 LPTSTR lpFilePart;
147 DWORD dwLen;
148
149 if (ExpandEnvironmentStrings(pszCommand,
150 szPath,
151 sizeof(szPath) / sizeof(szPath[0])) == 0)
152 {
153 _tcscpy(szPath, pszCommand);
154 }
155
156 if (bCheckExistence)
157 {
158 if ((_taccess(szPath, 0 )) == -1)
159 /* Expected error, don't return FALSE */
160 return TRUE;
161 }
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
190 if (!SHGetSpecialFolderPath(0, szPath, csidl, TRUE))
191 return FALSE;
192
193 if (pszFolder)
194 {
195 Ptr = PathAddBackslash(Ptr);
196 _tcscpy(Ptr, pszFolder);
197 }
198
199 Ptr = PathAddBackslash(Ptr);
200
201 if (!LoadString(hDllInstance, nIdName, szName, sizeof(szName)/sizeof(szName[0])))
202 return FALSE;
203 _tcscpy(Ptr, szName);
204
205 if (!LoadString(hDllInstance, nIdTitle, szTitle, sizeof(szTitle)/sizeof(szTitle[0])))
206 return FALSE;
207
208 // FIXME: we should pass 'command' straight in here, but shell32 doesn't expand it
209 return SUCCEEDED(CreateShellLink(szPath, szExeName, _T(""), pszWorkingDir, szExeName, iIconNr, szTitle));
210 }
211
212 static BOOL
213 CreateShortcutFolder(int csidl, UINT nID, LPTSTR pszName, int cchNameLen)
214 {
215 TCHAR szPath[MAX_PATH];
216 LPTSTR p;
217
218 if (!SHGetSpecialFolderPath(0, szPath, csidl, TRUE))
219 return FALSE;
220
221 if (!LoadString(hDllInstance, nID, pszName, cchNameLen))
222 return FALSE;
223
224 p = PathAddBackslash(szPath);
225 _tcscpy(p, pszName);
226
227 return CreateDirectory(szPath, NULL) || GetLastError()==ERROR_ALREADY_EXISTS;
228 }
229
230 static BOOL
231 CreateRandomSid(
232 OUT PSID *Sid)
233 {
234 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
235 LARGE_INTEGER SystemTime;
236 PULONG Seed;
237 NTSTATUS Status;
238
239 NtQuerySystemTime(&SystemTime);
240 Seed = &SystemTime.u.LowPart;
241
242 Status = RtlAllocateAndInitializeSid(
243 &SystemAuthority,
244 4,
245 SECURITY_NT_NON_UNIQUE,
246 RtlUniform(Seed),
247 RtlUniform(Seed),
248 RtlUniform(Seed),
249 SECURITY_NULL_RID,
250 SECURITY_NULL_RID,
251 SECURITY_NULL_RID,
252 SECURITY_NULL_RID,
253 Sid);
254 return NT_SUCCESS(Status);
255 }
256
257 static VOID
258 AppendRidToSid(
259 OUT PSID *Dst,
260 IN PSID Src,
261 IN ULONG NewRid)
262 {
263 ULONG Rid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
264 UCHAR RidCount;
265 ULONG i;
266
267 RidCount = *RtlSubAuthorityCountSid (Src);
268
269 for (i = 0; i < RidCount; i++)
270 Rid[i] = *RtlSubAuthoritySid (Src, i);
271
272 if (RidCount < 8)
273 {
274 Rid[RidCount] = NewRid;
275 RidCount++;
276 }
277
278 RtlAllocateAndInitializeSid(
279 RtlIdentifierAuthoritySid(Src),
280 RidCount,
281 Rid[0],
282 Rid[1],
283 Rid[2],
284 Rid[3],
285 Rid[4],
286 Rid[5],
287 Rid[6],
288 Rid[7],
289 Dst);
290 }
291
292 static VOID
293 CreateTempDir(
294 IN LPCWSTR VarName)
295 {
296 WCHAR szTempDir[MAX_PATH];
297 WCHAR szBuffer[MAX_PATH];
298 DWORD dwLength;
299 HKEY hKey;
300
301 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
302 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
303 0,
304 KEY_QUERY_VALUE,
305 &hKey) != ERROR_SUCCESS)
306 {
307 FatalError("Error: %lu\n", GetLastError());
308 return;
309 }
310
311 /* Get temp dir */
312 dwLength = MAX_PATH * sizeof(WCHAR);
313 if (RegQueryValueExW(hKey,
314 VarName,
315 NULL,
316 NULL,
317 (LPBYTE)szBuffer,
318 &dwLength) != ERROR_SUCCESS)
319 {
320 FatalError("Error: %lu\n", GetLastError());
321 goto cleanup;
322 }
323
324 /* Expand it */
325 if (!ExpandEnvironmentStringsW(szBuffer,
326 szTempDir,
327 MAX_PATH))
328 {
329 FatalError("Error: %lu\n", GetLastError());
330 goto cleanup;
331 }
332
333 /* Create profiles directory */
334 if (!CreateDirectoryW(szTempDir, NULL))
335 {
336 if (GetLastError() != ERROR_ALREADY_EXISTS)
337 {
338 FatalError("Error: %lu\n", GetLastError());
339 goto cleanup;
340 }
341 }
342
343 cleanup:
344 RegCloseKey(hKey);
345 }
346
347 static BOOL
348 InstallSysSetupInfDevices(VOID)
349 {
350 INFCONTEXT InfContext;
351 WCHAR szLineBuffer[256];
352 DWORD dwLineLength;
353
354 if (!SetupFindFirstLineW(hSysSetupInf,
355 L"DeviceInfsToInstall",
356 NULL,
357 &InfContext))
358 {
359 return FALSE;
360 }
361
362 do
363 {
364 if (!SetupGetStringFieldW(&InfContext,
365 0,
366 szLineBuffer,
367 sizeof(szLineBuffer)/sizeof(szLineBuffer[0]),
368 &dwLineLength))
369 {
370 return FALSE;
371 }
372
373 if (!SetupDiInstallClassW(NULL, szLineBuffer, DI_QUIETINSTALL, NULL))
374 {
375 return FALSE;
376 }
377 }
378 while (SetupFindNextLine(&InfContext, &InfContext));
379
380 return TRUE;
381 }
382
383 static BOOL
384 InstallSysSetupInfComponents(VOID)
385 {
386 INFCONTEXT InfContext;
387 WCHAR szNameBuffer[256];
388 WCHAR szSectionBuffer[256];
389 HINF hComponentInf = INVALID_HANDLE_VALUE;
390
391 if (!SetupFindFirstLineW(hSysSetupInf,
392 L"Infs.Always",
393 NULL,
394 &InfContext))
395 {
396 DPRINT("No Inf.Always section found\n");
397 }
398 else
399 {
400 do
401 {
402 if (!SetupGetStringFieldW(&InfContext,
403 1, // Get the component name
404 szNameBuffer,
405 sizeof(szNameBuffer)/sizeof(szNameBuffer[0]),
406 NULL))
407 {
408 FatalError("Error while trying to get component name \n");
409 return FALSE;
410 }
411
412 if (!SetupGetStringFieldW(&InfContext,
413 2, // Get the component install section
414 szSectionBuffer,
415 sizeof(szSectionBuffer)/sizeof(szSectionBuffer[0]),
416 NULL))
417 {
418 FatalError("Error while trying to get component install section \n");
419 return FALSE;
420 }
421
422 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer, szNameBuffer);
423
424 hComponentInf = SetupOpenInfFileW(szNameBuffer,
425 NULL,
426 INF_STYLE_WIN4,
427 NULL);
428
429 if (hComponentInf == INVALID_HANDLE_VALUE)
430 {
431 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer, GetLastError());
432 return FALSE;
433 }
434
435 if (!SetupInstallFromInfSectionW(NULL,
436 hComponentInf,
437 szSectionBuffer,
438 SPINST_ALL,
439 NULL,
440 NULL,
441 SP_COPY_NEWER,
442 SetupDefaultQueueCallbackW,
443 NULL,
444 NULL,
445 NULL))
446 {
447 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer, GetLastError());
448 SetupCloseInfFile(hComponentInf);
449 return FALSE;
450 }
451
452 SetupCloseInfFile(hComponentInf);
453 }
454 while (SetupFindNextLine(&InfContext, &InfContext));
455 }
456
457 return TRUE;
458 }
459
460 static BOOL
461 EnableUserModePnpManager(VOID)
462 {
463 SC_HANDLE hSCManager = NULL;
464 SC_HANDLE hService = NULL;
465 BOOL bRet = FALSE;
466
467 hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
468 if (hSCManager == NULL)
469 {
470 DPRINT1("Unable to open the service control manager.\n");
471 DPRINT1("Last Error %d\n", GetLastError());
472 goto cleanup;
473 }
474
475 hService = OpenServiceW(hSCManager,
476 L"PlugPlay",
477 SERVICE_CHANGE_CONFIG | SERVICE_START);
478 if (hService == NULL)
479 {
480 DPRINT1("Unable to open PlugPlay service\n");
481 goto cleanup;
482 }
483
484 bRet = ChangeServiceConfigW(hService,
485 SERVICE_NO_CHANGE,
486 SERVICE_AUTO_START,
487 SERVICE_NO_CHANGE,
488 NULL, NULL, NULL,
489 NULL, NULL, NULL, NULL);
490 if (!bRet)
491 {
492 DPRINT1("Unable to change the service configuration\n");
493 goto cleanup;
494 }
495
496 bRet = StartServiceW(hService, 0, NULL);
497 if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
498 {
499 DPRINT1("Unable to start service\n");
500 goto cleanup;
501 }
502
503 bRet = TRUE;
504
505 cleanup:
506 if (hSCManager != NULL)
507 CloseServiceHandle(hSCManager);
508 if (hService != NULL)
509 CloseServiceHandle(hService);
510 return bRet;
511 }
512
513 static INT_PTR CALLBACK
514 StatusMessageWindowProc(
515 IN HWND hwndDlg,
516 IN UINT uMsg,
517 IN WPARAM wParam,
518 IN LPARAM lParam)
519 {
520 UNREFERENCED_PARAMETER(wParam);
521
522 switch (uMsg)
523 {
524 case WM_INITDIALOG:
525 {
526 WCHAR szMsg[256];
527
528 if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
529 return FALSE;
530 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
531 return TRUE;
532 }
533 }
534 return FALSE;
535 }
536
537 static DWORD WINAPI
538 ShowStatusMessageThread(
539 IN LPVOID lpParameter)
540 {
541 HWND *phWnd = (HWND *)lpParameter;
542 HWND hWnd;
543 MSG Msg;
544
545 hWnd = CreateDialogParam(
546 hDllInstance,
547 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
548 GetDesktopWindow(),
549 StatusMessageWindowProc,
550 (LPARAM)NULL);
551 if (!hWnd)
552 return 0;
553 *phWnd = hWnd;
554
555 ShowWindow(hWnd, SW_SHOW);
556
557 /* Message loop for the Status window */
558 while (GetMessage(&Msg, NULL, 0, 0))
559 {
560 TranslateMessage(&Msg);
561 DispatchMessage(&Msg);
562 }
563
564 return 0;
565 }
566
567 static LONG
568 ReadRegSzKey(
569 IN HKEY hKey,
570 IN LPCWSTR pszKey,
571 OUT LPWSTR* pValue)
572 {
573 LONG rc;
574 DWORD dwType;
575 DWORD cbData = 0;
576 LPWSTR pwszValue;
577
578 if (!pValue)
579 return ERROR_INVALID_PARAMETER;
580
581 *pValue = NULL;
582 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
583 if (rc != ERROR_SUCCESS)
584 return rc;
585 if (dwType != REG_SZ)
586 return ERROR_FILE_NOT_FOUND;
587 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
588 if (!pwszValue)
589 return ERROR_NOT_ENOUGH_MEMORY;
590 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData);
591 if (rc != ERROR_SUCCESS)
592 {
593 HeapFree(GetProcessHeap(), 0, pwszValue);
594 return rc;
595 }
596 /* NULL-terminate the string */
597 pwszValue[cbData / sizeof(WCHAR)] = '\0';
598
599 *pValue = pwszValue;
600 return ERROR_SUCCESS;
601 }
602
603 static BOOL
604 IsConsoleBoot(VOID)
605 {
606 HKEY hControlKey = NULL;
607 LPWSTR pwszSystemStartOptions = NULL;
608 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */
609 BOOL bConsoleBoot = FALSE;
610 LONG rc;
611
612 rc = RegOpenKeyExW(
613 HKEY_LOCAL_MACHINE,
614 L"SYSTEM\\CurrentControlSet\\Control",
615 0,
616 KEY_QUERY_VALUE,
617 &hControlKey);
618 if (rc != ERROR_SUCCESS)
619 goto cleanup;
620
621 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions);
622 if (rc != ERROR_SUCCESS)
623 goto cleanup;
624
625 /* Check for CMDCONS in SystemStartOptions */
626 pwszCurrentOption = pwszSystemStartOptions;
627 while (pwszCurrentOption)
628 {
629 pwszNextOption = wcschr(pwszCurrentOption, L' ');
630 if (pwszNextOption)
631 *pwszNextOption = L'\0';
632 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0)
633 {
634 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption);
635 bConsoleBoot = TRUE;
636 goto cleanup;
637 }
638 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL;
639 }
640
641 cleanup:
642 if (hControlKey != NULL)
643 RegCloseKey(hControlKey);
644 if (pwszSystemStartOptions)
645 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions);
646 return bConsoleBoot;
647 }
648
649 static BOOL
650 CommonInstall(VOID)
651 {
652 HWND hWnd = NULL;
653
654 hSysSetupInf = SetupOpenInfFileW(
655 L"syssetup.inf",
656 NULL,
657 INF_STYLE_WIN4,
658 NULL);
659 if (hSysSetupInf == INVALID_HANDLE_VALUE)
660 {
661 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
662 return FALSE;
663 }
664
665 if (!InstallSysSetupInfDevices())
666 {
667 FatalError("InstallSysSetupInfDevices() failed!\n");
668 goto error;
669 }
670
671 if(!InstallSysSetupInfComponents())
672 {
673 FatalError("InstallSysSetupInfComponents() failed!\n");
674 goto error;
675 }
676
677 if (!IsConsoleBoot())
678 {
679 HANDLE hThread;
680
681 hThread = CreateThread(
682 NULL,
683 0,
684 ShowStatusMessageThread,
685 (LPVOID)&hWnd,
686 0,
687 NULL);
688
689 if (hThread)
690 CloseHandle(hThread);
691 }
692
693 if (!EnableUserModePnpManager())
694 {
695 FatalError("EnableUserModePnpManager() failed!\n");
696 goto error;
697 }
698
699 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
700 {
701 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
702 goto error;
703 }
704
705 EndDialog(hWnd, 0);
706 return TRUE;
707
708 error:
709 if (hWnd)
710 EndDialog(hWnd, 0);
711 SetupCloseInfFile(hSysSetupInf);
712 return FALSE;
713 }
714
715 DWORD WINAPI
716 InstallLiveCD(IN HINSTANCE hInstance)
717 {
718 STARTUPINFOW StartupInfo;
719 PROCESS_INFORMATION ProcessInformation;
720 BOOL bRes;
721
722 if (!CommonInstall())
723 goto error;
724
725 /* Register components */
726 _SEH2_TRY
727 {
728 if (!SetupInstallFromInfSectionW(NULL,
729 hSysSetupInf, L"RegistrationPhase2",
730 SPINST_ALL,
731 0, NULL, 0, NULL, NULL, NULL, NULL))
732 {
733 DPRINT1("SetupInstallFromInfSectionW failed!\n");
734 }
735 }
736 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
737 {
738 DPRINT1("Catching exception\n");
739 }
740 _SEH2_END;
741
742 SetupCloseInfFile(hSysSetupInf);
743
744 /* Run the shell */
745 StartupInfo.cb = sizeof(STARTUPINFOW);
746 StartupInfo.lpReserved = NULL;
747 StartupInfo.lpDesktop = NULL;
748 StartupInfo.lpTitle = NULL;
749 StartupInfo.dwFlags = 0;
750 StartupInfo.cbReserved2 = 0;
751 StartupInfo.lpReserved2 = 0;
752 bRes = CreateProcessW(
753 L"userinit.exe",
754 NULL,
755 NULL,
756 NULL,
757 FALSE,
758 0,
759 NULL,
760 NULL,
761 &StartupInfo,
762 &ProcessInformation);
763 if (!bRes)
764 goto error;
765
766 CloseHandle(ProcessInformation.hThread);
767 CloseHandle(ProcessInformation.hProcess);
768
769 return 0;
770
771 error:
772 MessageBoxW(
773 NULL,
774 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
775 L"ReactOS LiveCD",
776 MB_OK);
777 return 0;
778 }
779
780
781 static BOOL
782 CreateShortcuts(VOID)
783 {
784 TCHAR szFolder[256];
785
786 CoInitialize(NULL);
787
788 /* Create desktop shortcuts */
789 CreateShortcut(CSIDL_DESKTOP, NULL, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, TRUE, 0);
790
791 /* Create program startmenu shortcuts */
792 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_EXPLORER, _T("%SystemRoot%\\explorer.exe"), IDS_CMT_EXPLORER, TRUE, 1);
793 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_DOWNLOADER, _T("%SystemRoot%\\system32\\rapps.exe"), IDS_CMT_DOWNLOADER, TRUE, 0);
794
795 /* Create administrative tools startmenu shortcuts */
796 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_SERVICE, _T("%SystemRoot%\\system32\\servman.exe"), IDS_CMT_SERVMAN, TRUE, 0);
797 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_DEVICE, _T("%SystemRoot%\\system32\\devmgmt.exe"), IDS_CMT_DEVMGMT, TRUE, 0);
798 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_EVENTVIEW, _T("%SystemRoot%\\system32\\eventvwr.exe"), IDS_CMT_EVENTVIEW, TRUE, 0);
799 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_MSCONFIG, _T("%SystemRoot%\\system32\\msconfig.exe"), IDS_CMT_MSCONFIG, TRUE, 0);
800
801 /* Create and fill Accessories subfolder */
802 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
803 {
804 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CALC, _T("%SystemRoot%\\system32\\calc.exe"), IDS_CMT_CALC, TRUE, 0);
805 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, TRUE, 0);
806 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_NOTEPAD, _T("%SystemRoot%\\system32\\notepad.exe"), IDS_CMT_NOTEPAD, TRUE, 0);
807 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_RDESKTOP, _T("%SystemRoot%\\system32\\mstsc.exe"), IDS_CMT_RDESKTOP, TRUE, 0);
808 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNAP, _T("%SystemRoot%\\system32\\screenshot.exe"), IDS_CMT_SCREENSHOT, TRUE, 0);
809 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WORDPAD, _T("%SystemRoot%\\system32\\wordpad.exe"), IDS_CMT_WORDPAD, TRUE, 0);
810 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_PAINT, _T("%SystemRoot%\\system32\\mspaint.exe"), IDS_CMT_PAINT, TRUE, 0);
811 }
812
813 /* Create System Tools subfolder and fill if the exe is available */
814 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_TOOLS, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
815 {
816 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CHARMAP, _T("%SystemRoot%\\system32\\charmap.exe"), IDS_CMT_CHARMAP, TRUE, 0);
817 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_KBSWITCH, _T("%SystemRoot%\\system32\\kbswitch.exe"), IDS_CMT_KBSWITCH, TRUE, 0);
818 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_REGEDIT, _T("%SystemRoot%\\regedit.exe"), IDS_CMT_REGEDIT, TRUE, 0);
819 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_DXDIAG, _T("%SystemRoot%\\system32\\dxdiag.exe"), IDS_CMT_DXDIAG, TRUE, 0);
820 }
821
822 /* Create Accessibility subfolder and fill if the exe is available */
823 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_ACCESSIBILITY, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
824 {
825 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MAGNIFY, _T("%SystemRoot%\\system32\\magnify.exe"), IDS_CMT_MAGNIFY, TRUE, 0);
826 }
827
828 /* Create Entertainment subfolder and fill if the exe is available */
829 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_ENTERTAINMENT, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
830 {
831 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MPLAY32, _T("%SystemRoot%\\system32\\mplay32.exe"), IDS_CMT_MPLAY32, TRUE, 0);
832 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDVOL32, _T("%SystemRoot%\\system32\\sndvol32.exe"), IDS_CMT_SNDVOL32, TRUE, 0);
833 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDREC32, _T("%SystemRoot%\\system32\\sndrec32.exe"), IDS_CMT_SNDREC32, TRUE, 0);
834 }
835
836 /* Create Games subfolder and fill if the exe is available */
837 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
838 {
839 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SOLITAIRE, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE, TRUE, 0);
840 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WINEMINE, _T("%SystemRoot%\\system32\\winmine.exe"), IDS_CMT_WINEMINE, TRUE, 0);
841 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SPIDER, _T("%SystemRoot%\\system32\\spider.exe"), IDS_CMT_SPIDER, TRUE, 0);
842 }
843
844 CoUninitialize();
845
846 return TRUE;
847 }
848
849 static BOOL
850 SetSetupType(DWORD dwSetupType)
851 {
852 DWORD dwError;
853 HKEY hKey;
854
855 dwError = RegOpenKeyExW(
856 HKEY_LOCAL_MACHINE,
857 L"SYSTEM\\Setup",
858 0,
859 KEY_SET_VALUE,
860 &hKey);
861 if (dwError != ERROR_SUCCESS)
862 return FALSE;
863
864 dwError = RegSetValueExW(
865 hKey,
866 L"SetupType",
867 0,
868 REG_DWORD,
869 (LPBYTE)&dwSetupType,
870 sizeof(DWORD));
871 RegCloseKey(hKey);
872 if (dwError != ERROR_SUCCESS)
873 return FALSE;
874
875 return TRUE;
876 }
877
878 DWORD WINAPI
879 InstallReactOS(HINSTANCE hInstance)
880 {
881 TCHAR szBuffer[MAX_PATH];
882 DWORD LastError;
883 HANDLE token;
884 TOKEN_PRIVILEGES privs;
885 HKEY hKey;
886
887 InitializeSetupActionLog(FALSE);
888 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
889
890 if (!InitializeProfiles())
891 {
892 FatalError("InitializeProfiles() failed");
893 return 0;
894 }
895
896 /* Initialize the Security Account Manager (SAM) */
897 if (!SamInitializeSAM())
898 {
899 FatalError("SamInitializeSAM() failed!");
900 return 0;
901 }
902
903 /* Create the semi-random Domain-SID */
904 if (!CreateRandomSid(&DomainSid))
905 {
906 FatalError("Domain-SID creation failed!");
907 return 0;
908 }
909
910 /* Set the Domain SID (aka Computer SID) */
911 if (!SamSetDomainSid(DomainSid))
912 {
913 FatalError("SamSetDomainSid() failed!");
914 RtlFreeSid(DomainSid);
915 return 0;
916 }
917
918 /* Append the Admin-RID */
919 AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
920
921 CreateTempDir(L"TEMP");
922 CreateTempDir(L"TMP");
923
924 if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
925 {
926 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
927 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
928 0,
929 KEY_WRITE,
930 &hKey) == ERROR_SUCCESS)
931 {
932 RegSetValueExW(hKey,
933 L"PathName",
934 0,
935 REG_SZ,
936 (LPBYTE)szBuffer,
937 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
938
939 RegSetValueExW(hKey,
940 L"SystemRoot",
941 0,
942 REG_SZ,
943 (LPBYTE)szBuffer,
944 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
945
946 RegCloseKey(hKey);
947 }
948
949 PathAddBackslash(szBuffer);
950 _tcscat(szBuffer, _T("system"));
951 CreateDirectory(szBuffer, NULL);
952 }
953
954 if (!CommonInstall())
955 return 0;
956
957 InstallWizard();
958
959 /* Create the Administrator account */
960 if (!SamCreateUser(L"Administrator", L"", AdminSid))
961 {
962 /* Check what the error was.
963 * If the Admin Account already exists, then it means Setup
964 * wasn't allowed to finish properly. Instead of rebooting
965 * and not completing it, let it restart instead
966 */
967 LastError = GetLastError();
968 if (LastError != ERROR_USER_EXISTS)
969 {
970 FatalError("SamCreateUser() failed!");
971 RtlFreeSid(AdminSid);
972 RtlFreeSid(DomainSid);
973 return 0;
974 }
975 }
976
977 RtlFreeSid(AdminSid);
978 RtlFreeSid(DomainSid);
979
980 if (!CreateShortcuts())
981 {
982 FatalError("CreateShortcuts() failed");
983 return 0;
984 }
985
986 /* ROS HACK, as long as NtUnloadKey is not implemented */
987 {
988 NTSTATUS Status = NtUnloadKey(NULL);
989 if (Status == STATUS_NOT_IMPLEMENTED)
990 {
991 /* Create the Administrator profile */
992 PROFILEINFOW ProfileInfo;
993 HANDLE hToken;
994 BOOL ret;
995
996 ret = LogonUserW(L"Administrator", L"", L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken);
997 if (!ret)
998 {
999 FatalError("LogonUserW() failed!");
1000 return 0;
1001 }
1002 ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
1003 ProfileInfo.dwSize = sizeof(PROFILEINFOW);
1004 ProfileInfo.lpUserName = L"Administrator";
1005 ProfileInfo.dwFlags = PI_NOUI;
1006 LoadUserProfileW(hToken, &ProfileInfo);
1007 CloseHandle(hToken);
1008 }
1009 else
1010 {
1011 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
1012 }
1013 }
1014 /* END OF ROS HACK */
1015
1016 SetupCloseInfFile(hSysSetupInf);
1017 SetSetupType(0);
1018
1019 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS done");
1020 TerminateSetupActionLog();
1021
1022 /* Get shutdown privilege */
1023 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
1024 {
1025 FatalError("OpenProcessToken() failed!");
1026 return 0;
1027 }
1028 if (!LookupPrivilegeValue(
1029 NULL,
1030 SE_SHUTDOWN_NAME,
1031 &privs.Privileges[0].Luid))
1032 {
1033 FatalError("LookupPrivilegeValue() failed!");
1034 return 0;
1035 }
1036 privs.PrivilegeCount = 1;
1037 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1038 if (AdjustTokenPrivileges(
1039 token,
1040 FALSE,
1041 &privs,
1042 0,
1043 (PTOKEN_PRIVILEGES)NULL,
1044 NULL) == 0)
1045 {
1046 FatalError("AdjustTokenPrivileges() failed!");
1047 return 0;
1048 }
1049
1050 ExitWindowsEx(EWX_REBOOT, 0);
1051 return 0;
1052 }
1053
1054
1055 /*
1056 * @unimplemented
1057 */
1058 DWORD WINAPI
1059 SetupChangeFontSize(
1060 IN HANDLE hWnd,
1061 IN LPCWSTR lpszFontSize)
1062 {
1063 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1064 return FALSE;
1065 }
1066
1067 /*
1068 * @unimplemented
1069 */
1070 DWORD WINAPI
1071 SetupChangeLocaleEx(HWND hWnd,
1072 LCID Lcid,
1073 LPCWSTR lpSrcRootPath,
1074 char Unknown,
1075 DWORD dwUnused1,
1076 DWORD dwUnused2)
1077 {
1078 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1079 return FALSE;
1080 }
1081
1082 /*
1083 * @implemented
1084 */
1085 DWORD WINAPI
1086 SetupChangeLocale(HWND hWnd, LCID Lcid)
1087 {
1088 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
1089 }