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