7e671bbc24b1755e09d279f7975eab7289899bd3
[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
228 static VOID
229 CreateTempDir(
230 IN LPCWSTR VarName)
231 {
232 WCHAR szTempDir[MAX_PATH];
233 WCHAR szBuffer[MAX_PATH];
234 DWORD dwLength;
235 HKEY hKey;
236
237 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
238 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
239 0,
240 KEY_QUERY_VALUE,
241 &hKey) != ERROR_SUCCESS)
242 {
243 FatalError("Error: %lu\n", GetLastError());
244 return;
245 }
246
247 /* Get temp dir */
248 dwLength = MAX_PATH * sizeof(WCHAR);
249 if (RegQueryValueExW(hKey,
250 VarName,
251 NULL,
252 NULL,
253 (LPBYTE)szBuffer,
254 &dwLength) != ERROR_SUCCESS)
255 {
256 FatalError("Error: %lu\n", GetLastError());
257 goto cleanup;
258 }
259
260 /* Expand it */
261 if (!ExpandEnvironmentStringsW(szBuffer,
262 szTempDir,
263 MAX_PATH))
264 {
265 FatalError("Error: %lu\n", GetLastError());
266 goto cleanup;
267 }
268
269 /* Create profiles directory */
270 if (!CreateDirectoryW(szTempDir, NULL))
271 {
272 if (GetLastError() != ERROR_ALREADY_EXISTS)
273 {
274 FatalError("Error: %lu\n", GetLastError());
275 goto cleanup;
276 }
277 }
278
279 cleanup:
280 RegCloseKey(hKey);
281 }
282
283 static BOOL
284 InstallSysSetupInfDevices(VOID)
285 {
286 INFCONTEXT InfContext;
287 WCHAR szLineBuffer[256];
288 DWORD dwLineLength;
289
290 if (!SetupFindFirstLineW(hSysSetupInf,
291 L"DeviceInfsToInstall",
292 NULL,
293 &InfContext))
294 {
295 return FALSE;
296 }
297
298 do
299 {
300 if (!SetupGetStringFieldW(&InfContext,
301 0,
302 szLineBuffer,
303 sizeof(szLineBuffer)/sizeof(szLineBuffer[0]),
304 &dwLineLength))
305 {
306 return FALSE;
307 }
308
309 if (!SetupDiInstallClassW(NULL, szLineBuffer, DI_QUIETINSTALL, NULL))
310 {
311 return FALSE;
312 }
313 }
314 while (SetupFindNextLine(&InfContext, &InfContext));
315
316 return TRUE;
317 }
318
319 static BOOL
320 InstallSysSetupInfComponents(VOID)
321 {
322 INFCONTEXT InfContext;
323 WCHAR szNameBuffer[256];
324 WCHAR szSectionBuffer[256];
325 HINF hComponentInf = INVALID_HANDLE_VALUE;
326
327 if (!SetupFindFirstLineW(hSysSetupInf,
328 L"Infs.Always",
329 NULL,
330 &InfContext))
331 {
332 DPRINT("No Inf.Always section found\n");
333 }
334 else
335 {
336 do
337 {
338 if (!SetupGetStringFieldW(&InfContext,
339 1, // Get the component name
340 szNameBuffer,
341 sizeof(szNameBuffer)/sizeof(szNameBuffer[0]),
342 NULL))
343 {
344 FatalError("Error while trying to get component name \n");
345 return FALSE;
346 }
347
348 if (!SetupGetStringFieldW(&InfContext,
349 2, // Get the component install section
350 szSectionBuffer,
351 sizeof(szSectionBuffer)/sizeof(szSectionBuffer[0]),
352 NULL))
353 {
354 FatalError("Error while trying to get component install section \n");
355 return FALSE;
356 }
357
358 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer, szNameBuffer);
359
360 hComponentInf = SetupOpenInfFileW(szNameBuffer,
361 NULL,
362 INF_STYLE_WIN4,
363 NULL);
364
365 if (hComponentInf == INVALID_HANDLE_VALUE)
366 {
367 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer, GetLastError());
368 return FALSE;
369 }
370
371 if (!SetupInstallFromInfSectionW(NULL,
372 hComponentInf,
373 szSectionBuffer,
374 SPINST_ALL,
375 NULL,
376 NULL,
377 SP_COPY_NEWER,
378 SetupDefaultQueueCallbackW,
379 NULL,
380 NULL,
381 NULL))
382 {
383 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer, GetLastError());
384 SetupCloseInfFile(hComponentInf);
385 return FALSE;
386 }
387
388 SetupCloseInfFile(hComponentInf);
389 }
390 while (SetupFindNextLine(&InfContext, &InfContext));
391 }
392
393 return TRUE;
394 }
395
396 static BOOL
397 EnableUserModePnpManager(VOID)
398 {
399 SC_HANDLE hSCManager = NULL;
400 SC_HANDLE hService = NULL;
401 BOOL bRet = FALSE;
402
403 hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
404 if (hSCManager == NULL)
405 {
406 DPRINT1("Unable to open the service control manager.\n");
407 DPRINT1("Last Error %d\n", GetLastError());
408 goto cleanup;
409 }
410
411 hService = OpenServiceW(hSCManager,
412 L"PlugPlay",
413 SERVICE_CHANGE_CONFIG | SERVICE_START);
414 if (hService == NULL)
415 {
416 DPRINT1("Unable to open PlugPlay service\n");
417 goto cleanup;
418 }
419
420 bRet = ChangeServiceConfigW(hService,
421 SERVICE_NO_CHANGE,
422 SERVICE_AUTO_START,
423 SERVICE_NO_CHANGE,
424 NULL, NULL, NULL,
425 NULL, NULL, NULL, NULL);
426 if (!bRet)
427 {
428 DPRINT1("Unable to change the service configuration\n");
429 goto cleanup;
430 }
431
432 bRet = StartServiceW(hService, 0, NULL);
433 if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
434 {
435 DPRINT1("Unable to start service\n");
436 goto cleanup;
437 }
438
439 bRet = TRUE;
440
441 cleanup:
442 if (hSCManager != NULL)
443 CloseServiceHandle(hSCManager);
444 if (hService != NULL)
445 CloseServiceHandle(hService);
446 return bRet;
447 }
448
449 static INT_PTR CALLBACK
450 StatusMessageWindowProc(
451 IN HWND hwndDlg,
452 IN UINT uMsg,
453 IN WPARAM wParam,
454 IN LPARAM lParam)
455 {
456 UNREFERENCED_PARAMETER(wParam);
457
458 switch (uMsg)
459 {
460 case WM_INITDIALOG:
461 {
462 WCHAR szMsg[256];
463
464 if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
465 return FALSE;
466 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
467 return TRUE;
468 }
469 }
470 return FALSE;
471 }
472
473 static DWORD WINAPI
474 ShowStatusMessageThread(
475 IN LPVOID lpParameter)
476 {
477 HWND *phWnd = (HWND *)lpParameter;
478 HWND hWnd;
479 MSG Msg;
480
481 hWnd = CreateDialogParam(
482 hDllInstance,
483 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
484 GetDesktopWindow(),
485 StatusMessageWindowProc,
486 (LPARAM)NULL);
487 if (!hWnd)
488 return 0;
489 *phWnd = hWnd;
490
491 ShowWindow(hWnd, SW_SHOW);
492
493 /* Message loop for the Status window */
494 while (GetMessage(&Msg, NULL, 0, 0))
495 {
496 TranslateMessage(&Msg);
497 DispatchMessage(&Msg);
498 }
499
500 return 0;
501 }
502
503 static LONG
504 ReadRegSzKey(
505 IN HKEY hKey,
506 IN LPCWSTR pszKey,
507 OUT LPWSTR* pValue)
508 {
509 LONG rc;
510 DWORD dwType;
511 DWORD cbData = 0;
512 LPWSTR pwszValue;
513
514 if (!pValue)
515 return ERROR_INVALID_PARAMETER;
516
517 *pValue = NULL;
518 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
519 if (rc != ERROR_SUCCESS)
520 return rc;
521 if (dwType != REG_SZ)
522 return ERROR_FILE_NOT_FOUND;
523 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
524 if (!pwszValue)
525 return ERROR_NOT_ENOUGH_MEMORY;
526 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData);
527 if (rc != ERROR_SUCCESS)
528 {
529 HeapFree(GetProcessHeap(), 0, pwszValue);
530 return rc;
531 }
532 /* NULL-terminate the string */
533 pwszValue[cbData / sizeof(WCHAR)] = '\0';
534
535 *pValue = pwszValue;
536 return ERROR_SUCCESS;
537 }
538
539 static BOOL
540 IsConsoleBoot(VOID)
541 {
542 HKEY hControlKey = NULL;
543 LPWSTR pwszSystemStartOptions = NULL;
544 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */
545 BOOL bConsoleBoot = FALSE;
546 LONG rc;
547
548 rc = RegOpenKeyExW(
549 HKEY_LOCAL_MACHINE,
550 L"SYSTEM\\CurrentControlSet\\Control",
551 0,
552 KEY_QUERY_VALUE,
553 &hControlKey);
554 if (rc != ERROR_SUCCESS)
555 goto cleanup;
556
557 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions);
558 if (rc != ERROR_SUCCESS)
559 goto cleanup;
560
561 /* Check for CONSOLE switch in SystemStartOptions */
562 pwszCurrentOption = pwszSystemStartOptions;
563 while (pwszCurrentOption)
564 {
565 pwszNextOption = wcschr(pwszCurrentOption, L' ');
566 if (pwszNextOption)
567 *pwszNextOption = L'\0';
568 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0)
569 {
570 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption);
571 bConsoleBoot = TRUE;
572 goto cleanup;
573 }
574 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL;
575 }
576
577 cleanup:
578 if (hControlKey != NULL)
579 RegCloseKey(hControlKey);
580 if (pwszSystemStartOptions)
581 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions);
582 return bConsoleBoot;
583 }
584
585 static BOOL
586 CommonInstall(VOID)
587 {
588 HWND hWnd = NULL;
589
590 hSysSetupInf = SetupOpenInfFileW(
591 L"syssetup.inf",
592 NULL,
593 INF_STYLE_WIN4,
594 NULL);
595 if (hSysSetupInf == INVALID_HANDLE_VALUE)
596 {
597 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
598 return FALSE;
599 }
600
601 if (!InstallSysSetupInfDevices())
602 {
603 FatalError("InstallSysSetupInfDevices() failed!\n");
604 goto error;
605 }
606
607 if(!InstallSysSetupInfComponents())
608 {
609 FatalError("InstallSysSetupInfComponents() failed!\n");
610 goto error;
611 }
612
613 if (!IsConsoleBoot())
614 {
615 HANDLE hThread;
616
617 hThread = CreateThread(
618 NULL,
619 0,
620 ShowStatusMessageThread,
621 (LPVOID)&hWnd,
622 0,
623 NULL);
624
625 if (hThread)
626 CloseHandle(hThread);
627 }
628
629 if (!EnableUserModePnpManager())
630 {
631 FatalError("EnableUserModePnpManager() failed!\n");
632 goto error;
633 }
634
635 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
636 {
637 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
638 goto error;
639 }
640
641 EndDialog(hWnd, 0);
642 return TRUE;
643
644 error:
645 if (hWnd)
646 EndDialog(hWnd, 0);
647 SetupCloseInfFile(hSysSetupInf);
648 return FALSE;
649 }
650
651 DWORD WINAPI
652 InstallLiveCD(IN HINSTANCE hInstance)
653 {
654 STARTUPINFOW StartupInfo;
655 PROCESS_INFORMATION ProcessInformation;
656 BOOL bRes;
657
658 if (!CommonInstall())
659 goto error;
660
661 /* Register components */
662 _SEH2_TRY
663 {
664 if (!SetupInstallFromInfSectionW(NULL,
665 hSysSetupInf, L"RegistrationPhase2",
666 SPINST_ALL,
667 0, NULL, 0, NULL, NULL, NULL, NULL))
668 {
669 DPRINT1("SetupInstallFromInfSectionW failed!\n");
670 }
671 }
672 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
673 {
674 DPRINT1("Catching exception\n");
675 }
676 _SEH2_END;
677
678 SetupCloseInfFile(hSysSetupInf);
679
680 /* Run the shell */
681 StartupInfo.cb = sizeof(STARTUPINFOW);
682 StartupInfo.lpReserved = NULL;
683 StartupInfo.lpDesktop = NULL;
684 StartupInfo.lpTitle = NULL;
685 StartupInfo.dwFlags = 0;
686 StartupInfo.cbReserved2 = 0;
687 StartupInfo.lpReserved2 = 0;
688 bRes = CreateProcessW(
689 L"userinit.exe",
690 NULL,
691 NULL,
692 NULL,
693 FALSE,
694 0,
695 NULL,
696 NULL,
697 &StartupInfo,
698 &ProcessInformation);
699 if (!bRes)
700 goto error;
701
702 CloseHandle(ProcessInformation.hThread);
703 CloseHandle(ProcessInformation.hProcess);
704
705 return 0;
706
707 error:
708 MessageBoxW(
709 NULL,
710 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
711 L"ReactOS LiveCD",
712 MB_OK);
713 return 0;
714 }
715
716
717 static BOOL
718 CreateShortcuts(VOID)
719 {
720 TCHAR szFolder[256];
721
722 CoInitialize(NULL);
723
724 /* Create desktop shortcuts */
725 CreateShortcut(CSIDL_DESKTOP, NULL, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, TRUE, 0);
726
727 /* Create program startmenu shortcuts */
728 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_EXPLORER, _T("%SystemRoot%\\explorer.exe"), IDS_CMT_EXPLORER, TRUE, 1);
729 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_DOWNLOADER, _T("%SystemRoot%\\system32\\rapps.exe"), IDS_CMT_DOWNLOADER, TRUE, 0);
730
731 /* Create administrative tools startmenu shortcuts */
732 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_SERVICE, _T("%SystemRoot%\\system32\\servman.exe"), IDS_CMT_SERVMAN, TRUE, 0);
733 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_DEVICE, _T("%SystemRoot%\\system32\\devmgmt.exe"), IDS_CMT_DEVMGMT, TRUE, 0);
734 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_EVENTVIEW, _T("%SystemRoot%\\system32\\eventvwr.exe"), IDS_CMT_EVENTVIEW, TRUE, 0);
735 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_MSCONFIG, _T("%SystemRoot%\\system32\\msconfig.exe"), IDS_CMT_MSCONFIG, TRUE, 0);
736
737 /* Create and fill Accessories subfolder */
738 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
739 {
740 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CALC, _T("%SystemRoot%\\system32\\calc.exe"), IDS_CMT_CALC, TRUE, 0);
741 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, TRUE, 0);
742 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_NOTEPAD, _T("%SystemRoot%\\system32\\notepad.exe"), IDS_CMT_NOTEPAD, TRUE, 0);
743 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_RDESKTOP, _T("%SystemRoot%\\system32\\mstsc.exe"), IDS_CMT_RDESKTOP, TRUE, 0);
744 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNAP, _T("%SystemRoot%\\system32\\screenshot.exe"), IDS_CMT_SCREENSHOT, TRUE, 0);
745 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WORDPAD, _T("%SystemRoot%\\system32\\wordpad.exe"), IDS_CMT_WORDPAD, TRUE, 0);
746 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_PAINT, _T("%SystemRoot%\\system32\\mspaint.exe"), IDS_CMT_PAINT, TRUE, 0);
747 }
748
749 /* Create System Tools subfolder and fill if the exe is available */
750 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_TOOLS, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
751 {
752 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CHARMAP, _T("%SystemRoot%\\system32\\charmap.exe"), IDS_CMT_CHARMAP, TRUE, 0);
753 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_KBSWITCH, _T("%SystemRoot%\\system32\\kbswitch.exe"), IDS_CMT_KBSWITCH, TRUE, 0);
754 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_REGEDIT, _T("%SystemRoot%\\regedit.exe"), IDS_CMT_REGEDIT, TRUE, 0);
755 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_DXDIAG, _T("%SystemRoot%\\system32\\dxdiag.exe"), IDS_CMT_DXDIAG, TRUE, 0);
756 }
757
758 /* Create Accessibility subfolder and fill if the exe is available */
759 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_ACCESSIBILITY, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
760 {
761 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MAGNIFY, _T("%SystemRoot%\\system32\\magnify.exe"), IDS_CMT_MAGNIFY, TRUE, 0);
762 }
763
764 /* Create Entertainment subfolder and fill if the exe is available */
765 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_SYS_ENTERTAINMENT, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
766 {
767 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_MPLAY32, _T("%SystemRoot%\\system32\\mplay32.exe"), IDS_CMT_MPLAY32, TRUE, 0);
768 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDVOL32, _T("%SystemRoot%\\system32\\sndvol32.exe"), IDS_CMT_SNDVOL32, TRUE, 0);
769 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNDREC32, _T("%SystemRoot%\\system32\\sndrec32.exe"), IDS_CMT_SNDREC32, TRUE, 0);
770 }
771
772 /* Create Games subfolder and fill if the exe is available */
773 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
774 {
775 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SOLITAIRE, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE, TRUE, 0);
776 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WINEMINE, _T("%SystemRoot%\\system32\\winmine.exe"), IDS_CMT_WINEMINE, TRUE, 0);
777 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SPIDER, _T("%SystemRoot%\\system32\\spider.exe"), IDS_CMT_SPIDER, TRUE, 0);
778 }
779
780 CoUninitialize();
781
782 return TRUE;
783 }
784
785 static BOOL
786 SetSetupType(DWORD dwSetupType)
787 {
788 DWORD dwError;
789 HKEY hKey;
790
791 dwError = RegOpenKeyExW(
792 HKEY_LOCAL_MACHINE,
793 L"SYSTEM\\Setup",
794 0,
795 KEY_SET_VALUE,
796 &hKey);
797 if (dwError != ERROR_SUCCESS)
798 return FALSE;
799
800 dwError = RegSetValueExW(
801 hKey,
802 L"SetupType",
803 0,
804 REG_DWORD,
805 (LPBYTE)&dwSetupType,
806 sizeof(DWORD));
807 RegCloseKey(hKey);
808 if (dwError != ERROR_SUCCESS)
809 return FALSE;
810
811 return TRUE;
812 }
813
814 DWORD WINAPI
815 InstallReactOS(HINSTANCE hInstance)
816 {
817 TCHAR szBuffer[MAX_PATH];
818 HANDLE token;
819 TOKEN_PRIVILEGES privs;
820 HKEY hKey;
821
822 InitializeSetupActionLog(FALSE);
823 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
824
825 if (!InitializeProfiles())
826 {
827 FatalError("InitializeProfiles() failed");
828 return 0;
829 }
830
831 CreateTempDir(L"TEMP");
832 CreateTempDir(L"TMP");
833
834 if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
835 {
836 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
837 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
838 0,
839 KEY_WRITE,
840 &hKey) == ERROR_SUCCESS)
841 {
842 RegSetValueExW(hKey,
843 L"PathName",
844 0,
845 REG_SZ,
846 (LPBYTE)szBuffer,
847 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
848
849 RegSetValueExW(hKey,
850 L"SystemRoot",
851 0,
852 REG_SZ,
853 (LPBYTE)szBuffer,
854 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
855
856 RegCloseKey(hKey);
857 }
858
859 PathAddBackslash(szBuffer);
860 _tcscat(szBuffer, _T("system"));
861 CreateDirectory(szBuffer, NULL);
862 }
863
864 if (!CommonInstall())
865 return 0;
866
867 InstallWizard();
868
869 InstallSecurity();
870
871 if (!CreateShortcuts())
872 {
873 FatalError("CreateShortcuts() failed");
874 return 0;
875 }
876
877 /* ROS HACK, as long as NtUnloadKey is not implemented */
878 {
879 NTSTATUS Status = NtUnloadKey(NULL);
880 if (Status == STATUS_NOT_IMPLEMENTED)
881 {
882 /* Create the Administrator profile */
883 PROFILEINFOW ProfileInfo;
884 HANDLE hToken;
885 BOOL ret;
886
887 ret = LogonUserW(L"Administrator", L"", L"", LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &hToken);
888 if (!ret)
889 {
890 FatalError("LogonUserW() failed!");
891 return 0;
892 }
893 ZeroMemory(&ProfileInfo, sizeof(PROFILEINFOW));
894 ProfileInfo.dwSize = sizeof(PROFILEINFOW);
895 ProfileInfo.lpUserName = L"Administrator";
896 ProfileInfo.dwFlags = PI_NOUI;
897 LoadUserProfileW(hToken, &ProfileInfo);
898 CloseHandle(hToken);
899 }
900 else
901 {
902 DPRINT1("ROS HACK not needed anymore. Please remove it\n");
903 }
904 }
905 /* END OF ROS HACK */
906
907 SetupCloseInfFile(hSysSetupInf);
908 SetSetupType(0);
909
910 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS done");
911 TerminateSetupActionLog();
912
913 /* Get shutdown privilege */
914 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
915 {
916 FatalError("OpenProcessToken() failed!");
917 return 0;
918 }
919 if (!LookupPrivilegeValue(
920 NULL,
921 SE_SHUTDOWN_NAME,
922 &privs.Privileges[0].Luid))
923 {
924 FatalError("LookupPrivilegeValue() failed!");
925 return 0;
926 }
927 privs.PrivilegeCount = 1;
928 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
929 if (AdjustTokenPrivileges(
930 token,
931 FALSE,
932 &privs,
933 0,
934 (PTOKEN_PRIVILEGES)NULL,
935 NULL) == 0)
936 {
937 FatalError("AdjustTokenPrivileges() failed!");
938 return 0;
939 }
940
941 ExitWindowsEx(EWX_REBOOT, 0);
942 return 0;
943 }
944
945
946 /*
947 * @unimplemented
948 */
949 DWORD WINAPI
950 SetupChangeFontSize(
951 IN HANDLE hWnd,
952 IN LPCWSTR lpszFontSize)
953 {
954 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
955 return FALSE;
956 }
957
958 /*
959 * @unimplemented
960 */
961 DWORD WINAPI
962 SetupChangeLocaleEx(HWND hWnd,
963 LCID Lcid,
964 LPCWSTR lpSrcRootPath,
965 char Unknown,
966 DWORD dwUnused1,
967 DWORD dwUnused2)
968 {
969 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
970 return FALSE;
971 }
972
973 /*
974 * @implemented
975 */
976 DWORD WINAPI
977 SetupChangeLocale(HWND hWnd, LCID Lcid)
978 {
979 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
980 }