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