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