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