migrate substitution keywords to SVN
[reactos.git] / reactos / lib / syssetup / install.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS system libraries
23 * PURPOSE: System setup
24 * FILE: lib/syssetup/install.c
25 * PROGRAMER: Eric Kohl
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ntos.h>
31 #include <windows.h>
32 #include <commctrl.h>
33 #include <stdio.h>
34 #include <tchar.h>
35 #include <stdlib.h>
36
37 #include <samlib.h>
38 #include <syssetup.h>
39 #include <userenv.h>
40 #include <setupapi.h>
41
42 #include <shlobj.h>
43 #include <objidl.h>
44 #include <shlwapi.h>
45
46 #include "globals.h"
47 #include "resource.h"
48
49 #define VMWINST
50
51
52 /* GLOBALS ******************************************************************/
53
54 PSID DomainSid = NULL;
55 PSID AdminSid = NULL;
56
57 HINF hSysSetupInf = INVALID_HANDLE_VALUE;
58
59 /* FUNCTIONS ****************************************************************/
60
61 void
62 DebugPrint(char* fmt,...)
63 {
64 char buffer[512];
65 va_list ap;
66
67 va_start(ap, fmt);
68 vsprintf(buffer, fmt, ap);
69 va_end(ap);
70
71 strcat(buffer, "\nRebooting now!");
72 MessageBoxA(NULL,
73 buffer,
74 "ReactOS Setup",
75 MB_OK);
76 }
77
78
79 #ifdef VMWINST
80 static BOOL
81 RunVMWInstall(VOID)
82 {
83 PROCESS_INFORMATION ProcInfo;
84 STARTUPINFO si;
85
86 ZeroMemory(&si, sizeof(STARTUPINFO));
87 si.cb = sizeof(STARTUPINFO);
88
89 if(CreateProcess(NULL, _T("vmwinst.exe"), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS,
90 NULL, NULL, &si, &ProcInfo))
91 {
92 WaitForSingleObject(ProcInfo.hProcess, INFINITE);
93 CloseHandle(ProcInfo.hThread);
94 CloseHandle(ProcInfo.hProcess);
95 return TRUE;
96 }
97 return FALSE;
98 }
99 #endif
100
101
102 HRESULT CreateShellLink(LPCSTR linkPath, LPCSTR cmd, LPCSTR arg, LPCSTR dir, LPCSTR iconPath, int icon_nr, LPCSTR comment)
103 {
104 IShellLinkA* psl;
105 IPersistFile* ppf;
106 WCHAR buffer[MAX_PATH];
107
108 HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
109
110 if (SUCCEEDED(hr))
111 {
112 hr = psl->lpVtbl->SetPath(psl, cmd);
113
114 if (arg)
115 {
116 hr = psl->lpVtbl->SetArguments(psl, arg);
117 }
118
119 if (dir)
120 {
121 hr = psl->lpVtbl->SetWorkingDirectory(psl, dir);
122 }
123
124 if (iconPath)
125 {
126 hr = psl->lpVtbl->SetIconLocation(psl, iconPath, icon_nr);
127 }
128
129 if (comment)
130 {
131 hr = psl->lpVtbl->SetDescription(psl, comment);
132 }
133
134 hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
135
136 if (SUCCEEDED(hr))
137 {
138 MultiByteToWideChar(CP_ACP, 0, linkPath, -1, buffer, MAX_PATH);
139
140 hr = ppf->lpVtbl->Save(ppf, buffer, TRUE);
141
142 ppf->lpVtbl->Release(ppf);
143 }
144
145 psl->lpVtbl->Release(psl);
146 }
147
148 return hr;
149 }
150
151
152 static VOID
153 CreateCmdLink(VOID)
154 {
155 char path[MAX_PATH];
156 LPSTR p;
157
158 CoInitialize(NULL);
159
160 SHGetSpecialFolderPathA(0, path, CSIDL_DESKTOP, TRUE);
161 p = PathAddBackslashA(path);
162
163 strcpy(p, "Command Prompt.lnk");
164 CreateShellLink(path, "cmd.exe", "", NULL, NULL, 0, "Open command prompt");
165
166 CoUninitialize();
167 }
168
169
170 static VOID
171 CreateRandomSid (PSID *Sid)
172 {
173 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
174 LARGE_INTEGER SystemTime;
175 PULONG Seed;
176
177 NtQuerySystemTime (&SystemTime);
178 Seed = &SystemTime.u.LowPart;
179
180 RtlAllocateAndInitializeSid (&SystemAuthority,
181 4,
182 SECURITY_NT_NON_UNIQUE_RID,
183 RtlUniform (Seed),
184 RtlUniform (Seed),
185 RtlUniform (Seed),
186 SECURITY_NULL_RID,
187 SECURITY_NULL_RID,
188 SECURITY_NULL_RID,
189 SECURITY_NULL_RID,
190 Sid);
191 }
192
193
194 static VOID
195 AppendRidToSid (PSID *Dst,
196 PSID Src,
197 ULONG NewRid)
198 {
199 ULONG Rid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
200 UCHAR RidCount;
201 ULONG i;
202
203 RidCount = *RtlSubAuthorityCountSid (Src);
204
205 for (i = 0; i < RidCount; i++)
206 Rid[i] = *RtlSubAuthoritySid (Src, i);
207
208 if (RidCount < 8)
209 {
210 Rid[RidCount] = NewRid;
211 RidCount++;
212 }
213
214 RtlAllocateAndInitializeSid (RtlIdentifierAuthoritySid (Src),
215 RidCount,
216 Rid[0],
217 Rid[1],
218 Rid[2],
219 Rid[3],
220 Rid[4],
221 Rid[5],
222 Rid[6],
223 Rid[7],
224 Dst);
225 }
226
227 INT_PTR CALLBACK
228 RestartDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
229 {
230 switch(msg)
231 {
232 case WM_INITDIALOG:
233 SendDlgItemMessage(hWnd, IDC_RESTART_PROGRESS, PBM_SETRANGE, 0,
234 MAKELPARAM(0, 300));
235 SetTimer(hWnd, 0, 50, NULL);
236 return TRUE;
237
238 case WM_TIMER:
239 {
240 INT Position;
241 HWND hWndProgress;
242
243 hWndProgress = GetDlgItem(hWnd, IDC_RESTART_PROGRESS);
244 Position = SendMessage(hWndProgress, PBM_GETPOS, 0, 0);
245 if (Position == 300)
246 EndDialog(hWnd, 0);
247 else
248 SendMessage(hWndProgress, PBM_SETPOS, Position + 1, 0);
249 }
250 return TRUE;
251
252 case WM_COMMAND:
253 switch (wParam)
254 {
255 case IDOK:
256 case IDCANCEL:
257 EndDialog(hWnd, 0);
258 return TRUE;
259 }
260 break;
261 }
262
263 return FALSE;
264 }
265
266 static VOID
267 CreateTempDir(LPCWSTR VarName)
268 {
269 TCHAR szTempDir[MAX_PATH];
270 TCHAR szBuffer[MAX_PATH];
271 DWORD dwLength;
272 HKEY hKey;
273
274 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
275 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
276 0,
277 KEY_ALL_ACCESS,
278 &hKey))
279 {
280 DebugPrint("Error: %lu\n", GetLastError());
281 return;
282 }
283
284 /* Get temp dir */
285 dwLength = MAX_PATH * sizeof(TCHAR);
286 if (RegQueryValueEx(hKey,
287 VarName,
288 NULL,
289 NULL,
290 (LPBYTE)szBuffer,
291 &dwLength))
292 {
293 DebugPrint("Error: %lu\n", GetLastError());
294 RegCloseKey(hKey);
295 return;
296 }
297
298 /* Expand it */
299 if (!ExpandEnvironmentStrings(szBuffer,
300 szTempDir,
301 MAX_PATH))
302 {
303 DebugPrint("Error: %lu\n", GetLastError());
304 RegCloseKey(hKey);
305 return;
306 }
307
308 /* Create profiles directory */
309 if (!CreateDirectory(szTempDir, NULL))
310 {
311 if (GetLastError() != ERROR_ALREADY_EXISTS)
312 {
313 DebugPrint("Error: %lu\n", GetLastError());
314 RegCloseKey(hKey);
315 return;
316 }
317 }
318
319 RegCloseKey(hKey);
320 }
321
322
323 BOOL
324 ProcessSysSetupInf(VOID)
325 {
326 INFCONTEXT InfContext;
327 TCHAR LineBuffer[256];
328 DWORD LineLength;
329
330 if (!SetupFindFirstLine(hSysSetupInf,
331 _T("DeviceInfsToInstall"),
332 NULL,
333 &InfContext))
334 {
335 return FALSE;
336 }
337
338 do
339 {
340 if (!SetupGetStringField(&InfContext,
341 0,
342 LineBuffer,
343 256,
344 &LineLength))
345 {
346 return FALSE;
347 }
348
349 if (!SetupDiInstallClass(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
350 {
351 return FALSE;
352 }
353 }
354 while (SetupFindNextLine(&InfContext, &InfContext));
355
356 return TRUE;
357 }
358
359
360 DWORD STDCALL
361 InstallReactOS (HINSTANCE hInstance)
362 {
363 # if 0
364 OutputDebugStringA ("InstallReactOS() called\n");
365
366 if (!InitializeSetupActionLog (FALSE))
367 {
368 OutputDebugStringA ("InitializeSetupActionLog() failed\n");
369 }
370
371 LogItem (SYSSETUP_SEVERITY_INFORMATION,
372 L"ReactOS Setup starting");
373
374 LogItem (SYSSETUP_SEVERITY_FATAL_ERROR,
375 L"Buuuuuuaaaah!");
376
377 LogItem (SYSSETUP_SEVERITY_INFORMATION,
378 L"ReactOS Setup finished");
379
380 TerminateSetupActionLog ();
381 #endif
382 #if 0
383 UNICODE_STRING SidString;
384 #endif
385 ULONG LastError;
386
387 if (!InitializeProfiles ())
388 {
389 DebugPrint ("InitializeProfiles() failed\n");
390 return 0;
391 }
392
393 CreateCmdLink();
394
395 /* Create the semi-random Domain-SID */
396 CreateRandomSid (&DomainSid);
397 if (DomainSid == NULL)
398 {
399 DebugPrint ("Domain-SID creation failed!\n");
400 return 0;
401 }
402
403 #if 0
404 RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
405 DebugPrint ("Domain-SID: %wZ\n", &SidString);
406 RtlFreeUnicodeString (&SidString);
407 #endif
408
409 /* Initialize the Security Account Manager (SAM) */
410 if (!SamInitializeSAM ())
411 {
412 DebugPrint ("SamInitializeSAM() failed!\n");
413 RtlFreeSid (DomainSid);
414 return 0;
415 }
416
417 /* Set the Domain SID (aka Computer SID) */
418 if (!SamSetDomainSid (DomainSid))
419 {
420 DebugPrint ("SamSetDomainSid() failed!\n");
421 RtlFreeSid (DomainSid);
422 return 0;
423 }
424
425 /* Append the Admin-RID */
426 AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
427
428 #if 0
429 RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
430 DebugPrint ("Admin-SID: %wZ\n", &SidString);
431 RtlFreeUnicodeString (&SidString);
432 #endif
433
434 /* Create the Administrator account */
435 if (!SamCreateUser(L"Administrator", L"", AdminSid))
436 {
437 /* Check what the error was.
438 * If the Admin Account already exists, then it means Setup
439 * wasn't allowed to finish properly. Instead of rebooting
440 * and not completing it, let it restart instead
441 */
442 LastError = GetLastError();
443 if (LastError != ERROR_USER_EXISTS)
444 {
445 DebugPrint("SamCreateUser() failed!\n");
446 RtlFreeSid(AdminSid);
447 RtlFreeSid(DomainSid);
448 return 0;
449 }
450 }
451
452 /* Create the Administrator profile */
453 if (!CreateUserProfileW(AdminSid, L"Administrator"))
454 {
455 DebugPrint("CreateUserProfileW() failed!\n");
456 RtlFreeSid(AdminSid);
457 RtlFreeSid(DomainSid);
458 return 0;
459 }
460
461 RtlFreeSid(AdminSid);
462 RtlFreeSid(DomainSid);
463
464 CreateTempDir(L"TEMP");
465 CreateTempDir(L"TMP");
466
467 hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf",
468 NULL,
469 INF_STYLE_WIN4,
470 NULL);
471 if (hSysSetupInf == INVALID_HANDLE_VALUE)
472 {
473 DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
474 return 0;
475 }
476
477 if (!ProcessSysSetupInf())
478 {
479 DebugPrint("ProcessSysSetupInf() failed!\n");
480 return 0;
481 }
482
483 InstallWizard();
484
485 SetupCloseInfFile(hSysSetupInf);
486
487 #ifdef VMWINST
488 RunVMWInstall();
489 #endif
490
491 DialogBox(hDllInstance,
492 MAKEINTRESOURCE(IDD_RESTART),
493 NULL,
494 RestartDlgProc);
495
496 return 0;
497 }
498
499
500 /*
501 * @unimplemented
502 */
503 DWORD STDCALL
504 SetupChangeFontSize(HANDLE hWnd,
505 LPCWSTR lpszFontSize)
506 {
507 return FALSE;
508 }