Removed an old hack that's not necessary any longer since r31418 (2nd stage localizat...
[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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * PURPOSE: System setup
23 * FILE: lib/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 TCHAR szTempDir[MAX_PATH];
308 TCHAR szBuffer[MAX_PATH];
309 DWORD dwLength;
310 HKEY hKey;
311
312 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
313 _T("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(TCHAR);
324 if (RegQueryValueEx(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 (!ExpandEnvironmentStrings(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 (!CreateDirectory(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 TCHAR LineBuffer[256];
366 DWORD LineLength;
367
368 if (!SetupFindFirstLine(hSysSetupInf,
369 _T("DeviceInfsToInstall"),
370 NULL,
371 &InfContext))
372 {
373 return FALSE;
374 }
375
376 do
377 {
378 if (!SetupGetStringField(&InfContext,
379 0,
380 LineBuffer,
381 sizeof(LineBuffer)/sizeof(LineBuffer[0]),
382 &LineLength))
383 {
384 return FALSE;
385 }
386
387 if (!SetupDiInstallClass(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 TCHAR NameBuffer[256];
401 TCHAR SectionBuffer[256];
402
403 if (!SetupFindFirstLine(hSysSetupInf,
404 _T("Infs.Always"),
405 NULL,
406 &InfContext))
407 {
408 DPRINT("No Inf.Always section found\n");
409 }
410 else
411 {
412 do
413 {
414 if (!SetupGetStringField(&InfContext,
415 1, // Get the component name
416 NameBuffer,
417 sizeof(NameBuffer)/sizeof(NameBuffer[0]),
418 NULL))
419 {
420 DebugPrint("Error while trying to get component name \n");
421 return FALSE;
422 }
423
424 if (!SetupGetStringField(&InfContext,
425 2, // Get the component install section
426 SectionBuffer,
427 sizeof(SectionBuffer)/sizeof(SectionBuffer[0]),
428 NULL))
429 {
430 DebugPrint("Error while trying to get component install section \n");
431 return FALSE;
432 }
433
434 DPRINT("Trying to execute install section '%S' from '%S' \n", SectionBuffer , NameBuffer);
435
436 if (!SetupInstallFromInfSection(NULL,
437 hSysSetupInf,
438 SectionBuffer,
439 SPINST_ALL,
440 NULL,
441 NULL,
442 SP_COPY_NEWER,
443 NULL,
444 NULL,
445 NULL,
446 NULL))
447 {
448 DebugPrint("Error while trying to install : %S (Error: %lu) \n", NameBuffer, GetLastError());
449 return FALSE;
450 }
451 }
452 while (SetupFindNextLine(&InfContext, &InfContext));
453 }
454
455 return TRUE;
456 }
457
458 static BOOL
459 EnableUserModePnpManager(VOID)
460 {
461 SC_HANDLE hSCManager = NULL;
462 SC_HANDLE hService = NULL;
463 BOOL ret = FALSE;
464
465 hSCManager = OpenSCManager(NULL, NULL, 0);
466 if (hSCManager == NULL)
467 goto cleanup;
468
469 hService = OpenService(hSCManager, _T("PlugPlay"), SERVICE_CHANGE_CONFIG | SERVICE_START);
470 if (hService == NULL)
471 goto cleanup;
472
473 ret = ChangeServiceConfig(
474 hService,
475 SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
476 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
477 if (!ret)
478 goto cleanup;
479
480 ret = StartService(hService, 0, NULL);
481 if (!ret)
482 goto cleanup;
483
484 ret = TRUE;
485
486 cleanup:
487 if (hSCManager != NULL)
488 CloseServiceHandle(hSCManager);
489 if (hService != NULL)
490 CloseServiceHandle(hService);
491 return ret;
492 }
493
494
495 static BOOL CALLBACK
496 StatusMessageWindowProc(
497 IN HWND hwndDlg,
498 IN UINT uMsg,
499 IN WPARAM wParam,
500 IN LPARAM lParam)
501 {
502 UNREFERENCED_PARAMETER(wParam);
503
504 switch (uMsg)
505 {
506 case WM_INITDIALOG:
507 {
508 TCHAR szMsg[256];
509
510 if (!LoadString(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
511 return FALSE;
512 SetDlgItemText(hwndDlg, IDC_STATUSLABEL, szMsg);
513 return TRUE;
514 }
515 }
516 return FALSE;
517 }
518
519
520 static DWORD WINAPI
521 ShowStatusMessageThread(
522 IN LPVOID lpParameter)
523 {
524 HWND *phWnd = (HWND *)lpParameter;
525 HWND hWnd;
526 MSG Msg;
527
528 hWnd = CreateDialogParam(
529 hDllInstance,
530 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
531 GetDesktopWindow(),
532 StatusMessageWindowProc,
533 (LPARAM)NULL);
534 if (!hWnd)
535 return 0;
536 *phWnd = hWnd;
537
538 ShowWindow(hWnd, SW_SHOW);
539
540 /* Message loop for the Status window */
541 while (GetMessage(&Msg, NULL, 0, 0))
542 {
543 TranslateMessage(&Msg);
544 DispatchMessage(&Msg);
545 }
546
547 return 0;
548 }
549
550 static LONG
551 ReadRegSzKey(
552 IN HKEY hKey,
553 IN LPCWSTR pszKey,
554 OUT LPWSTR* pValue)
555 {
556 LONG rc;
557 DWORD dwType;
558 DWORD cbData = 0;
559 LPWSTR Value;
560
561 if (!pValue)
562 return ERROR_INVALID_PARAMETER;
563
564 *pValue = NULL;
565 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
566 if (rc != ERROR_SUCCESS)
567 return rc;
568 if (dwType != REG_SZ)
569 return ERROR_FILE_NOT_FOUND;
570 Value = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
571 if (!Value)
572 return ERROR_NOT_ENOUGH_MEMORY;
573 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)Value, &cbData);
574 if (rc != ERROR_SUCCESS)
575 {
576 HeapFree(GetProcessHeap(), 0, Value);
577 return rc;
578 }
579 /* NULL-terminate the string */
580 Value[cbData / sizeof(WCHAR)] = '\0';
581
582 *pValue = Value;
583 return ERROR_SUCCESS;
584 }
585
586 static BOOL
587 IsConsoleBoot(VOID)
588 {
589 HKEY ControlKey = NULL;
590 LPWSTR SystemStartOptions = NULL;
591 LPWSTR CurrentOption, NextOption; /* Pointers into SystemStartOptions */
592 BOOL ConsoleBoot = FALSE;
593 LONG rc;
594
595 rc = RegOpenKeyExW(
596 HKEY_LOCAL_MACHINE,
597 L"SYSTEM\\CurrentControlSet\\Control",
598 0,
599 KEY_QUERY_VALUE,
600 &ControlKey);
601
602 rc = ReadRegSzKey(ControlKey, L"SystemStartOptions", &SystemStartOptions);
603 if (rc != ERROR_SUCCESS)
604 goto cleanup;
605
606 /* Check for CMDCONS in SystemStartOptions */
607 CurrentOption = SystemStartOptions;
608 while (CurrentOption)
609 {
610 NextOption = wcschr(CurrentOption, L' ');
611 if (NextOption)
612 *NextOption = L'\0';
613 if (wcsicmp(CurrentOption, L"CONSOLE") == 0)
614 {
615 DPRINT("Found %S. Switching to console boot\n", CurrentOption);
616 ConsoleBoot = TRUE;
617 goto cleanup;
618 }
619 CurrentOption = NextOption ? NextOption + 1 : NULL;
620 }
621
622 cleanup:
623 if (ControlKey != NULL)
624 RegCloseKey(ControlKey);
625 HeapFree(GetProcessHeap(), 0, SystemStartOptions);
626 return ConsoleBoot;
627 }
628
629 static BOOL
630 CommonInstall(VOID)
631 {
632 HWND hWnd = NULL;
633
634 hSysSetupInf = SetupOpenInfFileW(
635 L"syssetup.inf",
636 NULL,
637 INF_STYLE_WIN4,
638 NULL);
639 if (hSysSetupInf == INVALID_HANDLE_VALUE)
640 {
641 DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
642 return FALSE;
643 }
644
645 if (!InstallSysSetupInfDevices())
646 {
647 DebugPrint("InstallSysSetupInfDevices() failed!\n");
648 SetupCloseInfFile(hSysSetupInf);
649 return FALSE;
650 }
651
652 if(!InstallSysSetupInfComponents())
653 {
654 DebugPrint("InstallSysSetupInfComponents() failed!\n");
655 SetupCloseInfFile(hSysSetupInf);
656 return FALSE;
657 }
658
659 if (!IsConsoleBoot())
660 {
661 CreateThread(
662 NULL,
663 0,
664 ShowStatusMessageThread,
665 (LPVOID)&hWnd,
666 0,
667 NULL);
668 }
669
670 if (!EnableUserModePnpManager())
671 {
672 DebugPrint("EnableUserModePnpManager() failed!\n");
673 SetupCloseInfFile(hSysSetupInf);
674 EndDialog(hWnd, 0);
675 return FALSE;
676 }
677
678 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
679 {
680 DebugPrint("CMP_WaitNoPendingInstallEvents() failed!\n");
681 SetupCloseInfFile(hSysSetupInf);
682 EndDialog(hWnd, 0);
683 return FALSE;
684 }
685
686 EndDialog(hWnd, 0);
687 return TRUE;
688 }
689
690 DWORD WINAPI
691 InstallLiveCD(IN HINSTANCE hInstance)
692 {
693 STARTUPINFO StartupInfo;
694 PROCESS_INFORMATION ProcessInformation;
695 BOOL res;
696
697 if (!CommonInstall())
698 goto cleanup;
699 SetupCloseInfFile(hSysSetupInf);
700
701 /* Run the shell */
702 StartupInfo.cb = sizeof(StartupInfo);
703 StartupInfo.lpReserved = NULL;
704 StartupInfo.lpDesktop = NULL;
705 StartupInfo.lpTitle = NULL;
706 StartupInfo.dwFlags = 0;
707 StartupInfo.cbReserved2 = 0;
708 StartupInfo.lpReserved2 = 0;
709 res = CreateProcess(
710 _T("userinit.exe"),
711 NULL,
712 NULL,
713 NULL,
714 FALSE,
715 0,
716 NULL,
717 NULL,
718 &StartupInfo,
719 &ProcessInformation);
720 if (!res)
721 goto cleanup;
722
723 return 0;
724
725 cleanup:
726 MessageBoxA(
727 NULL,
728 "You can shutdown your computer, or press ENTER to reboot",
729 "ReactOS LiveCD",
730 MB_OK);
731 return 0;
732 }
733
734
735 static BOOL
736 CreateShortcuts(VOID)
737 {
738 TCHAR szFolder[256];
739
740 CoInitialize(NULL);
741
742 /* Create desktop shortcuts */
743 CreateShortcut(CSIDL_DESKTOP, NULL, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, FALSE);
744
745 /* Create program startmenu shortcuts */
746 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_EXPLORER, _T("%SystemRoot%\\explorer.exe"), IDS_CMT_EXPLORER, FALSE);
747 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_DOWNLOADER, _T("%SystemRoot%\\system32\\downloader.exe"), IDS_CMT_DOWNLOADER, TRUE);
748
749 /* Create administrative tools startmenu shortcuts */
750 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_SERVICE, _T("%SystemRoot%\\system32\\servman.exe"), IDS_CMT_SERVMAN, FALSE);
751 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_DEVICE, _T("%SystemRoot%\\system32\\devmgmt.exe"), IDS_CMT_DEVMGMT, FALSE);
752
753 /* Create and fill Accessories subfolder */
754 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
755 {
756 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CALC, _T("%SystemRoot%\\system32\\calc.exe"), IDS_CMT_CALC, FALSE);
757 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, FALSE);
758 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_NOTEPAD, _T("%SystemRoot%\\system32\\notepad.exe"), IDS_CMT_NOTEPAD, FALSE);
759 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_REGEDIT, _T("%SystemRoot%\\regedit.exe"), IDS_CMT_REGEDIT, FALSE);
760 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WORDPAD, _T("%SystemRoot%\\system32\\wordpad.exe"), IDS_CMT_WORDPAD, FALSE);
761 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNAP, _T("%SystemRoot%\\system32\\screenshot.exe"), IDS_CMT_SCREENSHOT, TRUE);
762 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_RDESKTOP, _T("%SystemRoot%\\system32\\mstsc.exe"), IDS_CMT_RDESKTOP, FALSE);
763 }
764
765 /* Creacte System Tools subfolder and fill if the exe is available */
766 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_TOOLS, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
767 {
768 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CHARMAP, _T("%SystemRoot%\\system32\\charmap.exe"), IDS_CMT_CHARMAP, FALSE);
769 }
770
771 /* Creacte Accessibility subfolder and fill if the exe is available */
772 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_ACCESSIBILITY, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
773 {
774 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MAGNIFY, _T("%SystemRoot%\\system32\\magnify.exe"), IDS_CMT_MAGNIFY, TRUE);
775 }
776
777 /* Create Games subfolder and fill if the exe is available */
778 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
779 {
780 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SOLITAIRE, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE, FALSE);
781 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WINEMINE, _T("%SystemRoot%\\system32\\winemine.exe"), IDS_CMT_WINEMINE, FALSE);
782 }
783
784 CoUninitialize();
785
786 return TRUE;
787 }
788
789 static BOOL
790 SetSetupType(DWORD dwSetupType)
791 {
792 DWORD dwError;
793 HKEY hKey;
794
795 dwError = RegOpenKeyExW(
796 HKEY_LOCAL_MACHINE,
797 L"SYSTEM\\Setup",
798 0,
799 KEY_SET_VALUE,
800 &hKey);
801 if (dwError != ERROR_SUCCESS)
802 return FALSE;
803
804 dwError = RegSetValueExW(
805 hKey,
806 L"SetupType",
807 0,
808 REG_DWORD,
809 (LPBYTE)&dwSetupType,
810 sizeof(DWORD));
811 RegCloseKey(hKey);
812 if (dwError != ERROR_SUCCESS)
813 return FALSE;
814
815 return TRUE;
816 }
817
818 DWORD WINAPI
819 InstallReactOS(HINSTANCE hInstance)
820 {
821 TCHAR szBuffer[MAX_PATH];
822 DWORD LastError;
823 HANDLE token;
824 TOKEN_PRIVILEGES privs;
825
826 InitializeSetupActionLog(FALSE);
827 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
828
829 if (!InitializeProfiles())
830 {
831 DebugPrint("InitializeProfiles() failed");
832 return 0;
833 }
834
835 if (!CreateShortcuts())
836 {
837 DebugPrint("InitializeProfiles() failed");
838 return 0;
839 }
840
841 /* Initialize the Security Account Manager (SAM) */
842 if (!SamInitializeSAM())
843 {
844 DebugPrint("SamInitializeSAM() failed!");
845 return 0;
846 }
847
848 /* Create the semi-random Domain-SID */
849 if (!CreateRandomSid(&DomainSid))
850 {
851 DebugPrint("Domain-SID creation failed!");
852 return 0;
853 }
854
855 /* Set the Domain SID (aka Computer SID) */
856 if (!SamSetDomainSid(DomainSid))
857 {
858 DebugPrint("SamSetDomainSid() failed!");
859 RtlFreeSid(DomainSid);
860 return 0;
861 }
862
863 /* Append the Admin-RID */
864 AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
865
866 /* Create the Administrator account */
867 if (!SamCreateUser(L"Administrator", L"", AdminSid))
868 {
869 /* Check what the error was.
870 * If the Admin Account already exists, then it means Setup
871 * wasn't allowed to finish properly. Instead of rebooting
872 * and not completing it, let it restart instead
873 */
874 LastError = GetLastError();
875 if (LastError != ERROR_USER_EXISTS)
876 {
877 DebugPrint("SamCreateUser() failed!");
878 RtlFreeSid(AdminSid);
879 RtlFreeSid(DomainSid);
880 return 0;
881 }
882 }
883
884 RtlFreeSid(AdminSid);
885 RtlFreeSid(DomainSid);
886
887 /* ROS HACK, as long as NtUnloadKey is not implemented */
888 {
889 NTSTATUS Status = NtUnloadKey(NULL);
890 if (Status == STATUS_NOT_IMPLEMENTED)
891 {
892 /* Create the Administrator profile */
893 PROFILEINFOW ProfileInfo;
894 HANDLE hToken;
895 BOOL ret;
896 #define LOGON32_LOGON_NETWORK 3
897 ret = LogonUserW(L"Administrator", L"", L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken);
898 if (!ret)
899 {
900 DebugPrint("LogonUserW() failed!");
901 return 0;
902 }
903 ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
904 ProfileInfo.dwSize = sizeof(PROFILEINFOW);
905 ProfileInfo.lpUserName = L"Administrator";
906 ProfileInfo.dwFlags = PI_NOUI;
907 LoadUserProfileW(hToken, &ProfileInfo);
908 CloseHandle(hToken);
909 }
910 else
911 {
912 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
913 }
914 }
915 /* END OF ROS HACK */
916
917 CreateTempDir(L"TEMP");
918 CreateTempDir(L"TMP");
919
920 if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
921 {
922 PathAddBackslash(szBuffer);
923 _tcscat(szBuffer, _T("system"));
924 CreateDirectory(szBuffer, NULL);
925 }
926
927 if (!CommonInstall())
928 return 0;
929
930 InstallWizard();
931
932 SetupCloseInfFile(hSysSetupInf);
933 SetSetupType(0);
934
935 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS done");
936 TerminateSetupActionLog();
937
938 /* Get shutdown privilege */
939 if (! OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
940 {
941 DebugPrint("OpenProcessToken() failed!");
942 return 0;
943 }
944 if (!LookupPrivilegeValue(
945 NULL,
946 SE_SHUTDOWN_NAME,
947 &privs.Privileges[0].Luid))
948 {
949 DebugPrint("LookupPrivilegeValue() failed!");
950 return 0;
951 }
952 privs.PrivilegeCount = 1;
953 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
954 if (AdjustTokenPrivileges(
955 token,
956 FALSE,
957 &privs,
958 0,
959 (PTOKEN_PRIVILEGES)NULL,
960 NULL) == 0)
961 {
962 DebugPrint("AdjustTokenPrivileges() failed!");
963 return 0;
964 }
965
966 if (SetupData.BootCDRegtestActive)
967 {
968 /// THE FOLLOWING DPRINT IS FOR THE SYSTEM REGRESSION TOOL
969 /// DO NOT REMOVE!!!
970 DbgPrint("SYSREG_CHECKPOINT:SYSSETUP_COMPLETE\n");
971 }
972
973 ExitWindowsEx(EWX_REBOOT, 0);
974 return 0;
975 }
976
977
978 /*
979 * @unimplemented
980 */
981 DWORD STDCALL
982 SetupChangeFontSize(
983 IN HANDLE hWnd,
984 IN LPCWSTR lpszFontSize)
985 {
986 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
987 return FALSE;
988 }