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