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