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