[MMIXER] Fix additional data size initialization for different audio formats (#6753)
[reactos.git] / dll / win32 / syssetup / install.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: System setup
5 * FILE: dll/win32/syssetup/install.c
6 * PROGRAMER: Eric Kohl
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "precomp.h"
12
13 #define COBJMACROS
14
15 #include <io.h>
16 #include <wincon.h>
17 #include <winnls.h>
18 #include <winsvc.h>
19 #include <userenv.h>
20 #include <shlobj.h>
21 #include <shlwapi.h>
22 #include <shobjidl.h>
23 #include <rpcproxy.h>
24 #include <ndk/cmfuncs.h>
25
26 #define NDEBUG
27 #include <debug.h>
28
29 DWORD WINAPI
30 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout);
31
32 DWORD WINAPI
33 SetupStartService(LPCWSTR lpServiceName, BOOL bWait);
34
35 /* GLOBALS ******************************************************************/
36
37 HINF hSysSetupInf = INVALID_HANDLE_VALUE;
38 ADMIN_INFO AdminInfo;
39
40 /* FUNCTIONS ****************************************************************/
41
42 static VOID
43 FatalError(char *pszFmt,...)
44 {
45 char szBuffer[512];
46 va_list ap;
47
48 va_start(ap, pszFmt);
49 vsprintf(szBuffer, pszFmt, ap);
50 va_end(ap);
51
52 LogItem(NULL, L"Failed");
53
54 strcat(szBuffer, "\nRebooting now!");
55 MessageBoxA(NULL,
56 szBuffer,
57 "ReactOS Setup",
58 MB_OK);
59 }
60
61 static HRESULT
62 CreateShellLink(
63 LPCWSTR pszLinkPath,
64 LPCWSTR pszCmd,
65 LPCWSTR pszArg,
66 LPCWSTR pszDir,
67 LPCWSTR pszIconPath,
68 INT iIconNr,
69 LPCWSTR pszComment)
70 {
71 IShellLinkW *psl;
72 IPersistFile *ppf;
73
74 HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
75
76 if (SUCCEEDED(hr))
77 {
78 hr = IShellLinkW_SetPath(psl, pszCmd);
79
80 if (pszArg)
81 hr = IShellLinkW_SetArguments(psl, pszArg);
82
83 if (pszDir)
84 hr = IShellLinkW_SetWorkingDirectory(psl, pszDir);
85
86 if (pszIconPath)
87 hr = IShellLinkW_SetIconLocation(psl, pszIconPath, iIconNr);
88
89 if (pszComment)
90 hr = IShellLinkW_SetDescription(psl, pszComment);
91
92 hr = IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
93
94 if (SUCCEEDED(hr))
95 {
96 hr = IPersistFile_Save(ppf, pszLinkPath, TRUE);
97 IPersistFile_Release(ppf);
98 }
99
100 IShellLinkW_Release(psl);
101 }
102
103 return hr;
104 }
105
106
107 static BOOL
108 CreateShortcut(
109 LPCWSTR pszFolder,
110 LPCWSTR pszName,
111 LPCWSTR pszCommand,
112 LPCWSTR pszDescription,
113 INT iIconNr,
114 LPCWSTR pszWorkingDir)
115 {
116 DWORD dwLen;
117 LPWSTR Ptr;
118 LPWSTR lpFilePart;
119 WCHAR szPath[MAX_PATH];
120 WCHAR szWorkingDirBuf[MAX_PATH];
121
122 /* If no working directory is provided, try to compute a default one */
123 if (pszWorkingDir == NULL || pszWorkingDir[0] == L'\0')
124 {
125 if (ExpandEnvironmentStringsW(pszCommand, szPath, ARRAYSIZE(szPath)) == 0)
126 wcscpy(szPath, pszCommand);
127
128 dwLen = GetFullPathNameW(szPath,
129 ARRAYSIZE(szWorkingDirBuf),
130 szWorkingDirBuf,
131 &lpFilePart);
132 if (dwLen != 0 && dwLen <= ARRAYSIZE(szWorkingDirBuf))
133 {
134 /* Since those should only be called with (.exe) files,
135 lpFilePart has not to be NULL */
136 ASSERT(lpFilePart != NULL);
137
138 /* We're only interested in the path. Cut the file name off.
139 Also remove the trailing backslash unless the working directory
140 is only going to be a drive, i.e. C:\ */
141 *(lpFilePart--) = L'\0';
142 if (!(lpFilePart - szWorkingDirBuf == 2 &&
143 szWorkingDirBuf[1] == L':' && szWorkingDirBuf[2] == L'\\'))
144 {
145 *lpFilePart = L'\0';
146 }
147 pszWorkingDir = szWorkingDirBuf;
148 }
149 }
150
151 /* If we failed to compute a working directory, just do not use one */
152 if (pszWorkingDir && pszWorkingDir[0] == L'\0')
153 pszWorkingDir = NULL;
154
155 /* Build the shortcut file name */
156 wcscpy(szPath, pszFolder);
157 Ptr = PathAddBackslash(szPath);
158 wcscpy(Ptr, pszName);
159
160 /* Create the shortcut */
161 return SUCCEEDED(CreateShellLink(szPath,
162 pszCommand,
163 L"",
164 pszWorkingDir,
165 /* Special value to indicate no icon */
166 (iIconNr != -1 ? pszCommand : NULL),
167 iIconNr,
168 pszDescription));
169 }
170
171
172 static BOOL CreateShortcutsFromSection(HINF hinf, LPWSTR pszSection, LPCWSTR pszFolder)
173 {
174 INFCONTEXT Context;
175 DWORD dwFieldCount;
176 INT iIconNr;
177 WCHAR szCommand[MAX_PATH];
178 WCHAR szName[MAX_PATH];
179 WCHAR szDescription[MAX_PATH];
180 WCHAR szDirectory[MAX_PATH];
181
182 if (!SetupFindFirstLine(hinf, pszSection, NULL, &Context))
183 return FALSE;
184
185 do
186 {
187 dwFieldCount = SetupGetFieldCount(&Context);
188 if (dwFieldCount < 3)
189 continue;
190
191 if (!SetupGetStringFieldW(&Context, 1, szCommand, ARRAYSIZE(szCommand), NULL))
192 continue;
193
194 if (!SetupGetStringFieldW(&Context, 2, szName, ARRAYSIZE(szName), NULL))
195 continue;
196
197 if (!SetupGetStringFieldW(&Context, 3, szDescription, ARRAYSIZE(szDescription), NULL))
198 continue;
199
200 if (dwFieldCount < 4 || !SetupGetIntField(&Context, 4, &iIconNr))
201 iIconNr = -1; /* Special value to indicate no icon */
202
203 if (dwFieldCount < 5 || !SetupGetStringFieldW(&Context, 5, szDirectory, ARRAYSIZE(szDirectory), NULL))
204 szDirectory[0] = L'\0';
205
206 wcscat(szName, L".lnk");
207
208 CreateShortcut(pszFolder, szName, szCommand, szDescription, iIconNr, szDirectory);
209
210 } while (SetupFindNextLine(&Context, &Context));
211
212 return TRUE;
213 }
214
215 static BOOL CreateShortcuts(HINF hinf, LPCWSTR szSection)
216 {
217 INFCONTEXT Context;
218 WCHAR szPath[MAX_PATH];
219 WCHAR szFolder[MAX_PATH];
220 WCHAR szFolderSection[MAX_PATH];
221 INT csidl;
222
223 CoInitialize(NULL);
224
225 if (!SetupFindFirstLine(hinf, szSection, NULL, &Context))
226 return FALSE;
227
228 do
229 {
230 if (SetupGetFieldCount(&Context) < 2)
231 continue;
232
233 if (!SetupGetStringFieldW(&Context, 0, szFolderSection, ARRAYSIZE(szFolderSection), NULL))
234 continue;
235
236 if (!SetupGetIntField(&Context, 1, &csidl))
237 continue;
238
239 if (!SetupGetStringFieldW(&Context, 2, szFolder, ARRAYSIZE(szFolder), NULL))
240 continue;
241
242 if (FAILED(SHGetFolderPathAndSubDirW(NULL, csidl|CSIDL_FLAG_CREATE, (HANDLE)-1, SHGFP_TYPE_DEFAULT, szFolder, szPath)))
243 continue;
244
245 CreateShortcutsFromSection(hinf, szFolderSection, szPath);
246
247 } while (SetupFindNextLine(&Context, &Context));
248
249 CoUninitialize();
250
251 return TRUE;
252 }
253
254 static VOID
255 CreateTempDir(
256 IN LPCWSTR VarName)
257 {
258 WCHAR szTempDir[MAX_PATH];
259 WCHAR szBuffer[MAX_PATH];
260 DWORD dwLength;
261 HKEY hKey;
262
263 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
264 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
265 0,
266 KEY_QUERY_VALUE,
267 &hKey) != ERROR_SUCCESS)
268 {
269 FatalError("Error: %lu\n", GetLastError());
270 return;
271 }
272
273 /* Get temp dir */
274 dwLength = sizeof(szBuffer);
275 if (RegQueryValueExW(hKey,
276 VarName,
277 NULL,
278 NULL,
279 (LPBYTE)szBuffer,
280 &dwLength) != ERROR_SUCCESS)
281 {
282 FatalError("Error: %lu\n", GetLastError());
283 goto cleanup;
284 }
285
286 /* Expand it */
287 if (!ExpandEnvironmentStringsW(szBuffer, szTempDir, ARRAYSIZE(szTempDir)))
288 {
289 FatalError("Error: %lu\n", GetLastError());
290 goto cleanup;
291 }
292
293 /* Create profiles directory */
294 if (!CreateDirectoryW(szTempDir, NULL))
295 {
296 if (GetLastError() != ERROR_ALREADY_EXISTS)
297 {
298 FatalError("Error: %lu\n", GetLastError());
299 goto cleanup;
300 }
301 }
302
303 cleanup:
304 RegCloseKey(hKey);
305 }
306
307 static BOOL
308 InstallSysSetupInfDevices(VOID)
309 {
310 INFCONTEXT InfContext;
311 WCHAR szLineBuffer[256];
312 DWORD dwLineLength;
313
314 if (!SetupFindFirstLineW(hSysSetupInf,
315 L"DeviceInfsToInstall",
316 NULL,
317 &InfContext))
318 {
319 return FALSE;
320 }
321
322 do
323 {
324 if (!SetupGetStringFieldW(&InfContext,
325 0,
326 szLineBuffer,
327 ARRAYSIZE(szLineBuffer),
328 &dwLineLength))
329 {
330 return FALSE;
331 }
332
333 if (!SetupDiInstallClassW(NULL, szLineBuffer, DI_QUIETINSTALL, NULL))
334 {
335 return FALSE;
336 }
337 }
338 while (SetupFindNextLine(&InfContext, &InfContext));
339
340 return TRUE;
341 }
342
343 static BOOL
344 InstallSysSetupInfComponents(VOID)
345 {
346 INFCONTEXT InfContext;
347 WCHAR szNameBuffer[256];
348 WCHAR szSectionBuffer[256];
349 HINF hComponentInf = INVALID_HANDLE_VALUE;
350
351 if (!SetupFindFirstLineW(hSysSetupInf,
352 L"Infs.Always",
353 NULL,
354 &InfContext))
355 {
356 DPRINT("No Inf.Always section found\n");
357 }
358 else
359 {
360 do
361 {
362 if (!SetupGetStringFieldW(&InfContext,
363 1, // Get the component name
364 szNameBuffer,
365 ARRAYSIZE(szNameBuffer),
366 NULL))
367 {
368 FatalError("Error while trying to get component name \n");
369 return FALSE;
370 }
371
372 if (!SetupGetStringFieldW(&InfContext,
373 2, // Get the component install section
374 szSectionBuffer,
375 ARRAYSIZE(szSectionBuffer),
376 NULL))
377 {
378 FatalError("Error while trying to get component install section \n");
379 return FALSE;
380 }
381
382 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer, szNameBuffer);
383
384 hComponentInf = SetupOpenInfFileW(szNameBuffer,
385 NULL,
386 INF_STYLE_WIN4,
387 NULL);
388
389 if (hComponentInf == INVALID_HANDLE_VALUE)
390 {
391 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer, GetLastError());
392 return FALSE;
393 }
394
395 if (!SetupInstallFromInfSectionW(NULL,
396 hComponentInf,
397 szSectionBuffer,
398 SPINST_ALL,
399 NULL,
400 NULL,
401 SP_COPY_NEWER,
402 SetupDefaultQueueCallbackW,
403 NULL,
404 NULL,
405 NULL))
406 {
407 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer, GetLastError());
408 SetupCloseInfFile(hComponentInf);
409 return FALSE;
410 }
411
412 SetupCloseInfFile(hComponentInf);
413 }
414 while (SetupFindNextLine(&InfContext, &InfContext));
415 }
416
417 return TRUE;
418 }
419
420
421
422 BOOL
423 RegisterTypeLibraries(HINF hinf, LPCWSTR szSection)
424 {
425 INFCONTEXT InfContext;
426 BOOL res;
427 WCHAR szName[MAX_PATH];
428 WCHAR szPath[MAX_PATH];
429 INT csidl;
430 LPWSTR p;
431 HMODULE hmod;
432 HRESULT hret;
433
434 /* Begin iterating the entries in the inf section */
435 res = SetupFindFirstLine(hinf, szSection, NULL, &InfContext);
436 if (!res) return FALSE;
437
438 do
439 {
440 /* Get the name of the current type library */
441 if (!SetupGetStringFieldW(&InfContext, 1, szName, ARRAYSIZE(szName), NULL))
442 {
443 FatalError("SetupGetStringFieldW failed\n");
444 continue;
445 }
446
447 if (!SetupGetIntField(&InfContext, 2, &csidl))
448 csidl = CSIDL_SYSTEM;
449
450 hret = SHGetFolderPathW(NULL, csidl, NULL, 0, szPath);
451 if (FAILED(hret))
452 {
453 FatalError("SHGetFolderPathW failed hret=0x%lx\n", hret);
454 continue;
455 }
456
457 p = PathAddBackslash(szPath);
458 wcscpy(p, szName);
459
460 hmod = LoadLibraryW(szName);
461 if (hmod == NULL)
462 {
463 FatalError("LoadLibraryW failed\n");
464 continue;
465 }
466
467 __wine_register_resources(hmod);
468
469 } while (SetupFindNextLine(&InfContext, &InfContext));
470
471 return TRUE;
472 }
473
474 static BOOL
475 EnableUserModePnpManager(VOID)
476 {
477 SC_HANDLE hSCManager = NULL;
478 SC_HANDLE hService = NULL;
479 BOOL bRet = FALSE;
480
481 hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
482 if (hSCManager == NULL)
483 {
484 DPRINT1("Unable to open the service control manager.\n");
485 DPRINT1("Last Error %d\n", GetLastError());
486 goto cleanup;
487 }
488
489 hService = OpenServiceW(hSCManager,
490 L"PlugPlay",
491 SERVICE_CHANGE_CONFIG | SERVICE_START);
492 if (hService == NULL)
493 {
494 DPRINT1("Unable to open PlugPlay service\n");
495 goto cleanup;
496 }
497
498 bRet = ChangeServiceConfigW(hService,
499 SERVICE_NO_CHANGE,
500 SERVICE_AUTO_START,
501 SERVICE_NO_CHANGE,
502 NULL, NULL, NULL,
503 NULL, NULL, NULL, NULL);
504 if (!bRet)
505 {
506 DPRINT1("Unable to change the service configuration\n");
507 goto cleanup;
508 }
509
510 bRet = StartServiceW(hService, 0, NULL);
511 if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
512 {
513 DPRINT1("Unable to start service\n");
514 goto cleanup;
515 }
516
517 bRet = TRUE;
518
519 cleanup:
520 if (hService != NULL)
521 CloseServiceHandle(hService);
522 if (hSCManager != NULL)
523 CloseServiceHandle(hSCManager);
524 return bRet;
525 }
526
527 static INT_PTR CALLBACK
528 StatusMessageWindowProc(
529 IN HWND hwndDlg,
530 IN UINT uMsg,
531 IN WPARAM wParam,
532 IN LPARAM lParam)
533 {
534 UNREFERENCED_PARAMETER(wParam);
535
536 switch (uMsg)
537 {
538 case WM_INITDIALOG:
539 {
540 WCHAR szMsg[256];
541
542 if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, ARRAYSIZE(szMsg)))
543 return FALSE;
544 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
545 return TRUE;
546 }
547 }
548 return FALSE;
549 }
550
551 static DWORD WINAPI
552 ShowStatusMessageThread(
553 IN LPVOID lpParameter)
554 {
555 HWND hWnd, hItem;
556 MSG Msg;
557 UNREFERENCED_PARAMETER(lpParameter);
558
559 hWnd = CreateDialogParam(hDllInstance,
560 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
561 GetDesktopWindow(),
562 StatusMessageWindowProc,
563 (LPARAM)NULL);
564 if (!hWnd)
565 return 0;
566
567 ShowWindow(hWnd, SW_SHOW);
568
569 hItem = GetDlgItem(hWnd, IDC_STATUSPROGRESS);
570 if (hItem)
571 {
572 PostMessage(hItem, PBM_SETMARQUEE, TRUE, 40);
573 }
574
575 /* Message loop for the Status window */
576 while (GetMessage(&Msg, NULL, 0, 0))
577 {
578 TranslateMessage(&Msg);
579 DispatchMessage(&Msg);
580 }
581
582 EndDialog(hWnd, 0);
583
584 return 0;
585 }
586
587 static LONG
588 ReadRegSzKey(
589 IN HKEY hKey,
590 IN LPCWSTR pszKey,
591 OUT LPWSTR* pValue)
592 {
593 LONG rc;
594 DWORD dwType;
595 DWORD cbData = 0;
596 LPWSTR pwszValue;
597
598 if (!pValue)
599 return ERROR_INVALID_PARAMETER;
600
601 *pValue = NULL;
602 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
603 if (rc != ERROR_SUCCESS)
604 return rc;
605 if (dwType != REG_SZ)
606 return ERROR_FILE_NOT_FOUND;
607 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
608 if (!pwszValue)
609 return ERROR_NOT_ENOUGH_MEMORY;
610 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData);
611 if (rc != ERROR_SUCCESS)
612 {
613 HeapFree(GetProcessHeap(), 0, pwszValue);
614 return rc;
615 }
616 /* NULL-terminate the string */
617 pwszValue[cbData / sizeof(WCHAR)] = '\0';
618
619 *pValue = pwszValue;
620 return ERROR_SUCCESS;
621 }
622
623 static BOOL
624 IsConsoleBoot(VOID)
625 {
626 HKEY hControlKey = NULL;
627 LPWSTR pwszSystemStartOptions = NULL;
628 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */
629 BOOL bConsoleBoot = FALSE;
630 LONG rc;
631
632 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
633 L"SYSTEM\\CurrentControlSet\\Control",
634 0,
635 KEY_QUERY_VALUE,
636 &hControlKey);
637 if (rc != ERROR_SUCCESS)
638 goto cleanup;
639
640 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions);
641 if (rc != ERROR_SUCCESS)
642 goto cleanup;
643
644 /* Check for CONSOLE switch in SystemStartOptions */
645 pwszCurrentOption = pwszSystemStartOptions;
646 while (pwszCurrentOption)
647 {
648 pwszNextOption = wcschr(pwszCurrentOption, L' ');
649 if (pwszNextOption)
650 *pwszNextOption = L'\0';
651 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0)
652 {
653 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption);
654 bConsoleBoot = TRUE;
655 goto cleanup;
656 }
657 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL;
658 }
659
660 cleanup:
661 if (hControlKey != NULL)
662 RegCloseKey(hControlKey);
663 if (pwszSystemStartOptions)
664 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions);
665 return bConsoleBoot;
666 }
667
668 static BOOL
669 CommonInstall(VOID)
670 {
671 HANDLE hThread = NULL;
672 BOOL bResult = FALSE;
673
674 hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf",
675 NULL,
676 INF_STYLE_WIN4,
677 NULL);
678 if (hSysSetupInf == INVALID_HANDLE_VALUE)
679 {
680 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
681 return FALSE;
682 }
683
684 if (!InstallSysSetupInfDevices())
685 {
686 FatalError("InstallSysSetupInfDevices() failed!\n");
687 goto Exit;
688 }
689
690 if(!InstallSysSetupInfComponents())
691 {
692 FatalError("InstallSysSetupInfComponents() failed!\n");
693 goto Exit;
694 }
695
696 if (!IsConsoleBoot())
697 {
698 hThread = CreateThread(NULL,
699 0,
700 ShowStatusMessageThread,
701 NULL,
702 0,
703 NULL);
704 }
705
706 if (!EnableUserModePnpManager())
707 {
708 FatalError("EnableUserModePnpManager() failed!\n");
709 goto Exit;
710 }
711
712 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
713 {
714 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
715 goto Exit;
716 }
717
718 bResult = TRUE;
719
720 Exit:
721
722 if (bResult == FALSE)
723 {
724 SetupCloseInfFile(hSysSetupInf);
725 }
726
727 if (hThread != NULL)
728 {
729 PostThreadMessage(GetThreadId(hThread), WM_QUIT, 0, 0);
730 WaitForSingleObject(hThread, INFINITE);
731 CloseHandle(hThread);
732 }
733
734 return bResult;
735 }
736
737 static
738 DWORD
739 InstallLiveCD(VOID)
740 {
741 STARTUPINFOW StartupInfo;
742 PROCESS_INFORMATION ProcessInformation;
743 BOOL bRes;
744
745 if (!CommonInstall())
746 goto error;
747
748 /* Install the TCP/IP protocol driver */
749 bRes = InstallNetworkComponent(L"MS_TCPIP");
750 if (!bRes && GetLastError() != ERROR_FILE_NOT_FOUND)
751 {
752 DPRINT("InstallNetworkComponent() failed with error 0x%lx\n", GetLastError());
753 }
754 else
755 {
756 /* Start the TCP/IP protocol driver */
757 SetupStartService(L"Tcpip", FALSE);
758 SetupStartService(L"Dhcp", FALSE);
759 }
760
761 /* Register components */
762 _SEH2_TRY
763 {
764 if (!SetupInstallFromInfSectionW(NULL,
765 hSysSetupInf, L"RegistrationPhase2",
766 SPINST_ALL,
767 0, NULL, 0, NULL, NULL, NULL, NULL))
768 {
769 DPRINT1("SetupInstallFromInfSectionW failed!\n");
770 }
771
772 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries");
773 }
774 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
775 {
776 DPRINT1("Catching exception\n");
777 }
778 _SEH2_END;
779
780 SetupCloseInfFile(hSysSetupInf);
781
782 /* Run the shell */
783 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
784 StartupInfo.cb = sizeof(StartupInfo);
785 bRes = CreateProcessW(L"userinit.exe",
786 NULL,
787 NULL,
788 NULL,
789 FALSE,
790 0,
791 NULL,
792 NULL,
793 &StartupInfo,
794 &ProcessInformation);
795 if (!bRes)
796 goto error;
797
798 CloseHandle(ProcessInformation.hThread);
799 CloseHandle(ProcessInformation.hProcess);
800
801 return 0;
802
803 error:
804 MessageBoxW(
805 NULL,
806 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
807 L"ReactOS LiveCD",
808 MB_OK);
809 return 0;
810 }
811
812
813 static BOOL
814 SetSetupType(DWORD dwSetupType)
815 {
816 DWORD dwError;
817 HKEY hKey;
818
819 dwError = RegOpenKeyExW(
820 HKEY_LOCAL_MACHINE,
821 L"SYSTEM\\Setup",
822 0,
823 KEY_SET_VALUE,
824 &hKey);
825 if (dwError != ERROR_SUCCESS)
826 return FALSE;
827
828 dwError = RegSetValueExW(
829 hKey,
830 L"SetupType",
831 0,
832 REG_DWORD,
833 (LPBYTE)&dwSetupType,
834 sizeof(DWORD));
835 RegCloseKey(hKey);
836 if (dwError != ERROR_SUCCESS)
837 return FALSE;
838
839 return TRUE;
840 }
841
842 static DWORD CALLBACK
843 HotkeyThread(LPVOID Parameter)
844 {
845 ATOM hotkey;
846 MSG msg;
847
848 DPRINT("HotkeyThread start\n");
849
850 hotkey = GlobalAddAtomW(L"Setup Shift+F10 Hotkey");
851
852 if (!RegisterHotKey(NULL, hotkey, MOD_SHIFT, VK_F10))
853 DPRINT1("RegisterHotKey failed with %lu\n", GetLastError());
854
855 while (GetMessage(&msg, NULL, 0, 0))
856 {
857 if (msg.hwnd == NULL && msg.message == WM_HOTKEY && msg.wParam == hotkey)
858 {
859 STARTUPINFOW si = { sizeof(si) };
860 PROCESS_INFORMATION pi;
861
862 if (CreateProcessW(L"cmd.exe",
863 NULL,
864 NULL,
865 NULL,
866 FALSE,
867 CREATE_NEW_CONSOLE,
868 NULL,
869 NULL,
870 &si,
871 &pi))
872 {
873 CloseHandle(pi.hProcess);
874 CloseHandle(pi.hThread);
875 }
876 else
877 {
878 DPRINT1("Failed to launch command prompt: %lu\n", GetLastError());
879 }
880 }
881 }
882
883 UnregisterHotKey(NULL, hotkey);
884 GlobalDeleteAtom(hotkey);
885
886 DPRINT("HotkeyThread terminate\n");
887 return 0;
888 }
889
890
891 static
892 BOOL
893 InitializeProgramFilesDir(VOID)
894 {
895 LONG Error;
896 HKEY hKey;
897 DWORD dwLength;
898 WCHAR szProgramFilesDirPath[MAX_PATH];
899 WCHAR szCommonFilesDirPath[MAX_PATH];
900 WCHAR szBuffer[MAX_PATH];
901
902 /* Load 'Program Files' location */
903 if (!LoadStringW(hDllInstance,
904 IDS_PROGRAMFILES,
905 szBuffer,
906 ARRAYSIZE(szBuffer)))
907 {
908 DPRINT1("Error: %lu\n", GetLastError());
909 return FALSE;
910 }
911
912 if (!LoadStringW(hDllInstance,
913 IDS_COMMONFILES,
914 szCommonFilesDirPath,
915 ARRAYSIZE(szCommonFilesDirPath)))
916 {
917 DPRINT1("Warning: %lu\n", GetLastError());
918 }
919
920 /* Expand it */
921 if (!ExpandEnvironmentStringsW(szBuffer,
922 szProgramFilesDirPath,
923 ARRAYSIZE(szProgramFilesDirPath)))
924 {
925 DPRINT1("Error: %lu\n", GetLastError());
926 return FALSE;
927 }
928
929 wcscpy(szBuffer, szProgramFilesDirPath);
930 wcscat(szBuffer, L"\\");
931 wcscat(szBuffer, szCommonFilesDirPath);
932
933 if (!ExpandEnvironmentStringsW(szBuffer,
934 szCommonFilesDirPath,
935 ARRAYSIZE(szCommonFilesDirPath)))
936 {
937 DPRINT1("Warning: %lu\n", GetLastError());
938 }
939
940 /* Store it */
941 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
942 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
943 0,
944 KEY_SET_VALUE,
945 &hKey);
946 if (Error != ERROR_SUCCESS)
947 {
948 DPRINT1("Error: %lu\n", Error);
949 return FALSE;
950 }
951
952 dwLength = (wcslen(szProgramFilesDirPath) + 1) * sizeof(WCHAR);
953 Error = RegSetValueExW(hKey,
954 L"ProgramFilesDir",
955 0,
956 REG_SZ,
957 (LPBYTE)szProgramFilesDirPath,
958 dwLength);
959 if (Error != ERROR_SUCCESS)
960 {
961 DPRINT1("Error: %lu\n", Error);
962 RegCloseKey(hKey);
963 return FALSE;
964 }
965
966 dwLength = (wcslen(szCommonFilesDirPath) + 1) * sizeof(WCHAR);
967 Error = RegSetValueExW(hKey,
968 L"CommonFilesDir",
969 0,
970 REG_SZ,
971 (LPBYTE)szCommonFilesDirPath,
972 dwLength);
973 if (Error != ERROR_SUCCESS)
974 {
975 DPRINT1("Warning: %lu\n", Error);
976 }
977
978 RegCloseKey(hKey);
979
980 /* Create directory */
981 // FIXME: Security!
982 if (!CreateDirectoryW(szProgramFilesDirPath, NULL))
983 {
984 if (GetLastError() != ERROR_ALREADY_EXISTS)
985 {
986 DPRINT1("Error: %lu\n", GetLastError());
987 return FALSE;
988 }
989 }
990
991 /* Create directory */
992 // FIXME: Security!
993 if (!CreateDirectoryW(szCommonFilesDirPath, NULL))
994 {
995 if (GetLastError() != ERROR_ALREADY_EXISTS)
996 {
997 DPRINT1("Warning: %lu\n", GetLastError());
998 // return FALSE;
999 }
1000 }
1001
1002 return TRUE;
1003 }
1004
1005
1006 static
1007 VOID
1008 InitializeDefaultUserLocale(VOID)
1009 {
1010 WCHAR szBuffer[80];
1011 PWSTR ptr;
1012 HKEY hLocaleKey;
1013 DWORD ret;
1014 DWORD dwSize;
1015 LCID lcid;
1016 INT i;
1017
1018 struct {LCTYPE LCType; PWSTR pValue;} LocaleData[] = {
1019 /* Number */
1020 {LOCALE_SDECIMAL, L"sDecimal"},
1021 {LOCALE_STHOUSAND, L"sThousand"},
1022 {LOCALE_SNEGATIVESIGN, L"sNegativeSign"},
1023 {LOCALE_SPOSITIVESIGN, L"sPositiveSign"},
1024 {LOCALE_SGROUPING, L"sGrouping"},
1025 {LOCALE_SLIST, L"sList"},
1026 {LOCALE_SNATIVEDIGITS, L"sNativeDigits"},
1027 {LOCALE_INEGNUMBER, L"iNegNumber"},
1028 {LOCALE_IDIGITS, L"iDigits"},
1029 {LOCALE_ILZERO, L"iLZero"},
1030 {LOCALE_IMEASURE, L"iMeasure"},
1031 {LOCALE_IDIGITSUBSTITUTION, L"NumShape"},
1032
1033 /* Currency */
1034 {LOCALE_SCURRENCY, L"sCurrency"},
1035 {LOCALE_SMONDECIMALSEP, L"sMonDecimalSep"},
1036 {LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep"},
1037 {LOCALE_SMONGROUPING, L"sMonGrouping"},
1038 {LOCALE_ICURRENCY, L"iCurrency"},
1039 {LOCALE_INEGCURR, L"iNegCurr"},
1040 {LOCALE_ICURRDIGITS, L"iCurrDigits"},
1041
1042 /* Time */
1043 {LOCALE_STIMEFORMAT, L"sTimeFormat"},
1044 {LOCALE_STIME, L"sTime"},
1045 {LOCALE_S1159, L"s1159"},
1046 {LOCALE_S2359, L"s2359"},
1047 {LOCALE_ITIME, L"iTime"},
1048 {LOCALE_ITIMEMARKPOSN, L"iTimePrefix"},
1049 {LOCALE_ITLZERO, L"iTLZero"},
1050
1051 /* Date */
1052 {LOCALE_SLONGDATE, L"sLongDate"},
1053 {LOCALE_SSHORTDATE, L"sShortDate"},
1054 {LOCALE_SDATE, L"sDate"},
1055 {LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek"},
1056 {LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear"},
1057 {LOCALE_IDATE, L"iDate"},
1058 {LOCALE_ICALENDARTYPE, L"iCalendarType"},
1059
1060 /* Misc */
1061 {LOCALE_SCOUNTRY, L"sCountry"},
1062 {LOCALE_SABBREVLANGNAME, L"sLanguage"},
1063 {LOCALE_ICOUNTRY, L"iCountry"},
1064 {0, NULL}};
1065
1066 ret = RegOpenKeyExW(HKEY_USERS,
1067 L".DEFAULT\\Control Panel\\International",
1068 0,
1069 KEY_READ | KEY_WRITE,
1070 &hLocaleKey);
1071 if (ret != ERROR_SUCCESS)
1072 {
1073 return;
1074 }
1075
1076 dwSize = 9 * sizeof(WCHAR);
1077 ret = RegQueryValueExW(hLocaleKey,
1078 L"Locale",
1079 NULL,
1080 NULL,
1081 (PBYTE)szBuffer,
1082 &dwSize);
1083 if (ret != ERROR_SUCCESS)
1084 goto done;
1085
1086 lcid = (LCID)wcstoul(szBuffer, &ptr, 16);
1087 if (lcid == 0)
1088 goto done;
1089
1090 i = 0;
1091 while (LocaleData[i].pValue != NULL)
1092 {
1093 if (GetLocaleInfoW(lcid,
1094 LocaleData[i].LCType | LOCALE_NOUSEROVERRIDE,
1095 szBuffer,
1096 ARRAYSIZE(szBuffer)))
1097 {
1098 RegSetValueExW(hLocaleKey,
1099 LocaleData[i].pValue,
1100 0,
1101 REG_SZ,
1102 (PBYTE)szBuffer,
1103 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1104 }
1105
1106 i++;
1107 }
1108
1109 done:
1110 RegCloseKey(hLocaleKey);
1111 }
1112
1113
1114 static
1115 DWORD
1116 SaveDefaultUserHive(VOID)
1117 {
1118 WCHAR szDefaultUserHive[MAX_PATH];
1119 HKEY hUserKey = NULL;
1120 DWORD cchSize;
1121 DWORD dwError;
1122
1123 DPRINT("SaveDefaultUserHive()\n");
1124
1125 cchSize = ARRAYSIZE(szDefaultUserHive);
1126 GetDefaultUserProfileDirectoryW(szDefaultUserHive, &cchSize);
1127
1128 wcscat(szDefaultUserHive, L"\\ntuser.dat");
1129
1130 dwError = RegOpenKeyExW(HKEY_USERS,
1131 L".DEFAULT",
1132 0,
1133 KEY_READ,
1134 &hUserKey);
1135 if (dwError != ERROR_SUCCESS)
1136 {
1137 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
1138 return dwError;
1139 }
1140
1141 pSetupEnablePrivilege(L"SeBackupPrivilege", TRUE);
1142
1143 /* Save the Default hive */
1144 dwError = RegSaveKeyExW(hUserKey,
1145 szDefaultUserHive,
1146 NULL,
1147 REG_STANDARD_FORMAT);
1148 if (dwError == ERROR_ALREADY_EXISTS)
1149 {
1150 WCHAR szBackupHive[MAX_PATH];
1151
1152 /* Build the backup hive file name by replacing the extension */
1153 wcscpy(szBackupHive, szDefaultUserHive);
1154 wcscpy(&szBackupHive[wcslen(szBackupHive) - 4], L".bak");
1155
1156 /* Back up the existing default user hive by renaming it, replacing any possible existing old backup */
1157 if (!MoveFileExW(szDefaultUserHive,
1158 szBackupHive,
1159 MOVEFILE_REPLACE_EXISTING))
1160 {
1161 dwError = GetLastError();
1162 DPRINT1("Failed to create a default-user hive backup '%S', MoveFileExW failed (Error %lu)\n",
1163 szBackupHive, dwError);
1164 }
1165 else
1166 {
1167 /* The backup has been done, retry saving the Default hive */
1168 dwError = RegSaveKeyExW(hUserKey,
1169 szDefaultUserHive,
1170 NULL,
1171 REG_STANDARD_FORMAT);
1172 }
1173 }
1174 if (dwError != ERROR_SUCCESS)
1175 {
1176 DPRINT1("RegSaveKeyExW() failed (Error %lu)\n", dwError);
1177 }
1178
1179 pSetupEnablePrivilege(L"SeBackupPrivilege", FALSE);
1180
1181 RegCloseKey(hUserKey);
1182
1183 return dwError;
1184 }
1185
1186
1187 static
1188 DWORD
1189 InstallReactOS(VOID)
1190 {
1191 WCHAR szBuffer[MAX_PATH];
1192 HANDLE token;
1193 TOKEN_PRIVILEGES privs;
1194 HKEY hKey;
1195 HINF hShortcutsInf;
1196 HANDLE hHotkeyThread;
1197 BOOL ret;
1198
1199 InitializeSetupActionLog(FALSE);
1200 LogItem(NULL, L"Installing ReactOS");
1201
1202 CreateTempDir(L"TEMP");
1203 CreateTempDir(L"TMP");
1204
1205 if (!InitializeProgramFilesDir())
1206 {
1207 FatalError("InitializeProgramFilesDir() failed");
1208 return 0;
1209 }
1210
1211 if (!InitializeProfiles())
1212 {
1213 FatalError("InitializeProfiles() failed");
1214 return 0;
1215 }
1216
1217 InitializeDefaultUserLocale();
1218
1219 if (GetWindowsDirectoryW(szBuffer, ARRAYSIZE(szBuffer)))
1220 {
1221 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1222 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
1223 0,
1224 KEY_WRITE,
1225 &hKey) == ERROR_SUCCESS)
1226 {
1227 RegSetValueExW(hKey,
1228 L"PathName",
1229 0,
1230 REG_SZ,
1231 (LPBYTE)szBuffer,
1232 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1233
1234 RegSetValueExW(hKey,
1235 L"SystemRoot",
1236 0,
1237 REG_SZ,
1238 (LPBYTE)szBuffer,
1239 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1240
1241 RegCloseKey(hKey);
1242 }
1243
1244 PathAddBackslash(szBuffer);
1245 wcscat(szBuffer, L"system");
1246 CreateDirectory(szBuffer, NULL);
1247 }
1248
1249 if (SaveDefaultUserHive() != ERROR_SUCCESS)
1250 {
1251 FatalError("SaveDefaultUserHive() failed");
1252 return 0;
1253 }
1254
1255 if (!CopySystemProfile(0))
1256 {
1257 FatalError("CopySystemProfile() failed");
1258 return 0;
1259 }
1260
1261 hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL);
1262
1263 if (!CommonInstall())
1264 return 0;
1265
1266 /* Install the TCP/IP protocol driver */
1267 ret = InstallNetworkComponent(L"MS_TCPIP");
1268 if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND)
1269 {
1270 DPRINT("InstallNetworkComponent() failed with error 0x%lx\n", GetLastError());
1271 }
1272 else
1273 {
1274 /* Start the TCP/IP protocol driver */
1275 SetupStartService(L"Tcpip", FALSE);
1276 SetupStartService(L"Dhcp", FALSE);
1277 }
1278
1279 InstallWizard();
1280
1281 InstallSecurity();
1282
1283 SetAutoAdminLogon();
1284
1285 hShortcutsInf = SetupOpenInfFileW(L"shortcuts.inf",
1286 NULL,
1287 INF_STYLE_WIN4,
1288 NULL);
1289 if (hShortcutsInf == INVALID_HANDLE_VALUE)
1290 {
1291 FatalError("Failed to open shortcuts.inf");
1292 return 0;
1293 }
1294
1295 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders"))
1296 {
1297 FatalError("CreateShortcuts() failed");
1298 return 0;
1299 }
1300
1301 SetupCloseInfFile(hShortcutsInf);
1302
1303 hShortcutsInf = SetupOpenInfFileW(L"rosapps_shortcuts.inf",
1304 NULL,
1305 INF_STYLE_WIN4,
1306 NULL);
1307 if (hShortcutsInf != INVALID_HANDLE_VALUE)
1308 {
1309 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders"))
1310 {
1311 FatalError("CreateShortcuts(rosapps) failed");
1312 return 0;
1313 }
1314 SetupCloseInfFile(hShortcutsInf);
1315 }
1316
1317 SetupCloseInfFile(hSysSetupInf);
1318 SetSetupType(0);
1319
1320 if (hHotkeyThread)
1321 {
1322 PostThreadMessage(GetThreadId(hHotkeyThread), WM_QUIT, 0, 0);
1323 CloseHandle(hHotkeyThread);
1324 }
1325
1326 LogItem(NULL, L"Installing ReactOS done");
1327 TerminateSetupActionLog();
1328
1329 if (AdminInfo.Name != NULL)
1330 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Name);
1331
1332 if (AdminInfo.Domain != NULL)
1333 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Domain);
1334
1335 if (AdminInfo.Password != NULL)
1336 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Password);
1337
1338 /* Get shutdown privilege */
1339 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
1340 {
1341 FatalError("OpenProcessToken() failed!");
1342 return 0;
1343 }
1344 if (!LookupPrivilegeValue(NULL,
1345 SE_SHUTDOWN_NAME,
1346 &privs.Privileges[0].Luid))
1347 {
1348 FatalError("LookupPrivilegeValue() failed!");
1349 return 0;
1350 }
1351 privs.PrivilegeCount = 1;
1352 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1353 if (AdjustTokenPrivileges(token,
1354 FALSE,
1355 &privs,
1356 0,
1357 (PTOKEN_PRIVILEGES)NULL,
1358 NULL) == 0)
1359 {
1360 FatalError("AdjustTokenPrivileges() failed!");
1361 return 0;
1362 }
1363
1364 ExitWindowsEx(EWX_REBOOT, 0);
1365 return 0;
1366 }
1367
1368
1369 /*
1370 * Standard Windows-compatible export, which dispatches
1371 * to either 'InstallReactOS' or 'InstallLiveCD'.
1372 */
1373 INT
1374 WINAPI
1375 InstallWindowsNt(INT argc, WCHAR** argv)
1376 {
1377 INT i;
1378 PWSTR p;
1379
1380 for (i = 0; i < argc; ++i)
1381 {
1382 p = argv[i];
1383 if (*p == L'-')
1384 {
1385 p++;
1386
1387 // NOTE: On Windows, "mini" means "minimal UI", and can be used
1388 // in addition to "newsetup"; these options are not exclusive.
1389 if (_wcsicmp(p, L"newsetup") == 0)
1390 return (INT)InstallReactOS();
1391 else if (_wcsicmp(p, L"mini") == 0)
1392 return (INT)InstallLiveCD();
1393
1394 /* Add support for other switches */
1395 }
1396 }
1397
1398 return 0;
1399 }
1400
1401
1402 /*
1403 * @unimplemented
1404 */
1405 DWORD WINAPI
1406 SetupChangeFontSize(
1407 IN HANDLE hWnd,
1408 IN LPCWSTR lpszFontSize)
1409 {
1410 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1411 return FALSE;
1412 }
1413
1414 /*
1415 * @unimplemented
1416 */
1417 DWORD WINAPI
1418 SetupChangeLocaleEx(HWND hWnd,
1419 LCID Lcid,
1420 LPCWSTR lpSrcRootPath,
1421 char Unknown,
1422 DWORD dwUnused1,
1423 DWORD dwUnused2)
1424 {
1425 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1426 return FALSE;
1427 }
1428
1429 /*
1430 * @implemented
1431 */
1432 DWORD WINAPI
1433 SetupChangeLocale(HWND hWnd, LCID Lcid)
1434 {
1435 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
1436 }
1437
1438
1439 DWORD
1440 WINAPI
1441 SetupStartService(
1442 LPCWSTR lpServiceName,
1443 BOOL bWait)
1444 {
1445 SC_HANDLE hManager = NULL;
1446 SC_HANDLE hService = NULL;
1447 DWORD dwError = ERROR_SUCCESS;
1448
1449 hManager = OpenSCManagerW(NULL,
1450 NULL,
1451 SC_MANAGER_ALL_ACCESS);
1452 if (hManager == NULL)
1453 {
1454 dwError = GetLastError();
1455 goto done;
1456 }
1457
1458 hService = OpenServiceW(hManager,
1459 lpServiceName,
1460 SERVICE_START);
1461 if (hService == NULL)
1462 {
1463 dwError = GetLastError();
1464 goto done;
1465 }
1466
1467 if (!StartService(hService, 0, NULL))
1468 {
1469 dwError = GetLastError();
1470 goto done;
1471 }
1472
1473 done:
1474 if (hService != NULL)
1475 CloseServiceHandle(hService);
1476
1477 if (hManager != NULL)
1478 CloseServiceHandle(hManager);
1479
1480 return dwError;
1481 }