A bit more eye candy for the start menu.
[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 #define WIN32_NO_STATUS
31 #include <windows.h>
32 #define NTOS_MODE_USER
33 #include <ndk/ntndk.h>
34
35 #include <commctrl.h>
36 #include <stdio.h>
37 #include <io.h>
38 #include <tchar.h>
39 #include <stdlib.h>
40
41 #include <samlib/samlib.h>
42 #include <syssetup/syssetup.h>
43 #include <userenv.h>
44 #include <setupapi.h>
45
46 #include <shlobj.h>
47 #include <objidl.h>
48 #include <shlwapi.h>
49
50 #include "globals.h"
51 #include "resource.h"
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 HRESULT CreateShellLink(LPCTSTR linkPath, LPCTSTR cmd, LPCTSTR arg, LPCTSTR dir, LPCTSTR iconPath, int icon_nr, LPCTSTR comment)
82 {
83 IShellLink* psl;
84 IPersistFile* ppf;
85 #ifndef _UNICODE
86 WCHAR buffer[MAX_PATH];
87 #endif /* _UNICODE */
88
89 HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
90
91 if (SUCCEEDED(hr))
92 {
93 hr = psl->lpVtbl->SetPath(psl, cmd);
94
95 if (arg)
96 {
97 hr = psl->lpVtbl->SetArguments(psl, arg);
98 }
99
100 if (dir)
101 {
102 hr = psl->lpVtbl->SetWorkingDirectory(psl, dir);
103 }
104
105 if (iconPath)
106 {
107 hr = psl->lpVtbl->SetIconLocation(psl, iconPath, icon_nr);
108 }
109
110 if (comment)
111 {
112 hr = psl->lpVtbl->SetDescription(psl, comment);
113 }
114
115 hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
116
117 if (SUCCEEDED(hr))
118 {
119 #ifdef _UNICODE
120 hr = ppf->lpVtbl->Save(ppf, linkPath, TRUE);
121 #else /* _UNICODE */
122 MultiByteToWideChar(CP_ACP, 0, linkPath, -1, buffer, MAX_PATH);
123
124 hr = ppf->lpVtbl->Save(ppf, buffer, TRUE);
125 #endif /* _UNICODE */
126
127 ppf->lpVtbl->Release(ppf);
128 }
129
130 psl->lpVtbl->Release(psl);
131 }
132
133 return hr;
134 }
135
136
137 static BOOL
138 CreateShortcut(int csidl, LPCTSTR folder, LPCTSTR linkName, LPCTSTR command, UINT nIdTitle)
139 {
140 TCHAR path[MAX_PATH];
141 TCHAR title[256];
142 LPTSTR p = path;
143
144 if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
145 return FALSE;
146
147 if (folder)
148 {
149 p = PathAddBackslash(p);
150 _tcscpy(p, folder);
151 }
152
153 p = PathAddBackslash(p);
154 _tcscpy(p, linkName);
155
156 if (!LoadString(hDllInstance, nIdTitle, title, 256))
157 return FALSE;
158
159 return SUCCEEDED(CreateShellLink(path, command, _T(""), NULL, NULL, 0, title));
160 }
161
162
163 static BOOL
164 CreateShortcutFolder(int csidl, UINT nID, LPTSTR name, int nameLen)
165 {
166 TCHAR path[MAX_PATH];
167 LPTSTR p;
168
169 if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
170 return FALSE;
171
172 if (!LoadString(hDllInstance, nID, name, nameLen))
173 return FALSE;
174
175 p = PathAddBackslash(path);
176 _tcscpy(p, name);
177
178 return CreateDirectory(path, NULL) || GetLastError()==ERROR_ALREADY_EXISTS;
179 }
180
181
182 static VOID
183 CreateRandomSid (PSID *Sid)
184 {
185 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
186 LARGE_INTEGER SystemTime;
187 PULONG Seed;
188
189 NtQuerySystemTime (&SystemTime);
190 Seed = &SystemTime.u.LowPart;
191
192 RtlAllocateAndInitializeSid (&SystemAuthority,
193 4,
194 SECURITY_NT_NON_UNIQUE_RID,
195 RtlUniform (Seed),
196 RtlUniform (Seed),
197 RtlUniform (Seed),
198 SECURITY_NULL_RID,
199 SECURITY_NULL_RID,
200 SECURITY_NULL_RID,
201 SECURITY_NULL_RID,
202 Sid);
203 }
204
205
206 static VOID
207 AppendRidToSid (PSID *Dst,
208 PSID Src,
209 ULONG NewRid)
210 {
211 ULONG Rid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
212 UCHAR RidCount;
213 ULONG i;
214
215 RidCount = *RtlSubAuthorityCountSid (Src);
216
217 for (i = 0; i < RidCount; i++)
218 Rid[i] = *RtlSubAuthoritySid (Src, i);
219
220 if (RidCount < 8)
221 {
222 Rid[RidCount] = NewRid;
223 RidCount++;
224 }
225
226 RtlAllocateAndInitializeSid (RtlIdentifierAuthoritySid (Src),
227 RidCount,
228 Rid[0],
229 Rid[1],
230 Rid[2],
231 Rid[3],
232 Rid[4],
233 Rid[5],
234 Rid[6],
235 Rid[7],
236 Dst);
237 }
238
239
240 static VOID
241 CreateTempDir(LPCWSTR VarName)
242 {
243 TCHAR szTempDir[MAX_PATH];
244 TCHAR szBuffer[MAX_PATH];
245 DWORD dwLength;
246 HKEY hKey;
247
248 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
249 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
250 0,
251 KEY_ALL_ACCESS,
252 &hKey))
253 {
254 DebugPrint("Error: %lu\n", GetLastError());
255 return;
256 }
257
258 /* Get temp dir */
259 dwLength = MAX_PATH * sizeof(TCHAR);
260 if (RegQueryValueEx(hKey,
261 VarName,
262 NULL,
263 NULL,
264 (LPBYTE)szBuffer,
265 &dwLength))
266 {
267 DebugPrint("Error: %lu\n", GetLastError());
268 RegCloseKey(hKey);
269 return;
270 }
271
272 /* Expand it */
273 if (!ExpandEnvironmentStrings(szBuffer,
274 szTempDir,
275 MAX_PATH))
276 {
277 DebugPrint("Error: %lu\n", GetLastError());
278 RegCloseKey(hKey);
279 return;
280 }
281
282 /* Create profiles directory */
283 if (!CreateDirectory(szTempDir, NULL))
284 {
285 if (GetLastError() != ERROR_ALREADY_EXISTS)
286 {
287 DebugPrint("Error: %lu\n", GetLastError());
288 RegCloseKey(hKey);
289 return;
290 }
291 }
292
293 RegCloseKey(hKey);
294 }
295
296
297 BOOL
298 ProcessSysSetupInf(VOID)
299 {
300 INFCONTEXT InfContext;
301 TCHAR LineBuffer[256];
302 DWORD LineLength;
303
304 if (!SetupFindFirstLine(hSysSetupInf,
305 _T("DeviceInfsToInstall"),
306 NULL,
307 &InfContext))
308 {
309 return FALSE;
310 }
311
312 do
313 {
314 if (!SetupGetStringField(&InfContext,
315 0,
316 LineBuffer,
317 256,
318 &LineLength))
319 {
320 return FALSE;
321 }
322
323 if (!SetupDiInstallClass(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
324 {
325 return FALSE;
326 }
327 }
328 while (SetupFindNextLine(&InfContext, &InfContext));
329
330 return TRUE;
331 }
332
333
334 static BOOL
335 EnableUserModePnpManager(VOID)
336 {
337 SC_HANDLE hSCManager = NULL;
338 SC_HANDLE hService = NULL;
339 BOOL ret = FALSE;
340
341 hSCManager = OpenSCManager(NULL, NULL, 0);
342 if (hSCManager == NULL)
343 goto cleanup;
344
345 hService = OpenService(hSCManager, _T("PlugPlay"), SERVICE_CHANGE_CONFIG | SERVICE_START);
346 if (hService == NULL)
347 goto cleanup;
348
349 ret = ChangeServiceConfig(
350 hService,
351 SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
352 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
353 if (!ret)
354 goto cleanup;
355
356 ret = StartService(hService, 0, NULL);
357 if (!ret)
358 goto cleanup;
359
360 ret = TRUE;
361
362 cleanup:
363 if (hSCManager != NULL)
364 CloseServiceHandle(hSCManager);
365 if (hService != NULL)
366 CloseServiceHandle(hService);
367 return ret;
368 }
369
370
371 DWORD STDCALL
372 InstallReactOS (HINSTANCE hInstance)
373 {
374 TCHAR sAccessories[256];
375 TCHAR sGames[256];
376 TCHAR Sys[MAX_PATH];
377 TCHAR GamePath[MAX_PATH];
378
379
380 # if 0
381 OutputDebugStringA ("InstallReactOS() called\n");
382
383 if (!InitializeSetupActionLog (FALSE))
384 {
385 OutputDebugStringA ("InitializeSetupActionLog() failed\n");
386 }
387
388 LogItem (SYSSETUP_SEVERITY_INFORMATION,
389 L"ReactOS Setup starting");
390
391 LogItem (SYSSETUP_SEVERITY_FATAL_ERROR,
392 L"Buuuuuuaaaah!");
393
394 LogItem (SYSSETUP_SEVERITY_INFORMATION,
395 L"ReactOS Setup finished");
396
397 TerminateSetupActionLog ();
398 #endif
399 #if 0
400 UNICODE_STRING SidString;
401 #endif
402 ULONG LastError;
403
404 if (!InitializeProfiles ())
405 {
406 DebugPrint ("InitializeProfiles() failed\n");
407 return 0;
408 }
409
410 CoInitialize(NULL);
411
412 /* create desktop shortcuts */
413 CreateShortcut(CSIDL_DESKTOP, NULL, _T("Command Prompt.lnk"), _T("cmd.exe"), IDS_CMT_CMD);
414
415 /* create program startmenu shortcuts */
416 CreateShortcut(CSIDL_PROGRAMS, NULL, _T("winefile.lnk"), _T("winefile.exe"), IDS_CMT_WINEFILE);
417 CreateShortcut(CSIDL_PROGRAMS, NULL, _T("ibrowser.lnk"), _T("ibrowser.exe"), IDS_CMT_IBROWSER);
418
419 /* create and fill Accessories subfolder */
420 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, sAccessories, 256)) {
421 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Calculator.lnk"), _T("calc.exe"), IDS_CMT_CALC);
422 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Command Prompt.lnk"), _T("cmd.exe"), IDS_CMT_CMD);
423 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Notepad.lnk"), _T("notepad.exe"), IDS_CMT_NOTEPAD);
424 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("ReactOS Explorer.lnk"), _T("explorer.exe"), IDS_CMT_EXPLORER);
425 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Regedit.lnk"), _T("regedit.exe"), IDS_CMT_REGEDIT);
426 }
427
428
429 /* create Games subfolder and fill if the exe is available */
430 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, sGames, 256)) {
431 if(GetSystemDirectory(Sys, MAX_PATH)) {
432 /* copy system dir */
433 _tcscpy(GamePath, Sys);
434 /* concatonate full file path and check for existance */
435 if((_taccess(_tcscat(GamePath, _T("\\sol.exe")), 0 )) != -1)
436 CreateShortcut(CSIDL_PROGRAMS, sGames, _T("Solitaire.lnk"), _T("sol.exe"), IDS_CMT_SOLITAIRE);
437
438 _tcscpy(GamePath, Sys);
439 if((_taccess(_tcscat(GamePath, _T("\\winemine.exe")), 0 )) != -1)
440 CreateShortcut(CSIDL_PROGRAMS, sGames, _T("WineMine.lnk"), _T("winemine.exe"), IDS_CMT_WINEMINE);
441 }
442 }
443
444 CoUninitialize();
445
446 /* Create the semi-random Domain-SID */
447 CreateRandomSid (&DomainSid);
448 if (DomainSid == NULL)
449 {
450 DebugPrint ("Domain-SID creation failed!\n");
451 return 0;
452 }
453
454 #if 0
455 RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
456 DebugPrint ("Domain-SID: %wZ\n", &SidString);
457 RtlFreeUnicodeString (&SidString);
458 #endif
459
460 /* Initialize the Security Account Manager (SAM) */
461 if (!SamInitializeSAM ())
462 {
463 DebugPrint ("SamInitializeSAM() failed!\n");
464 RtlFreeSid (DomainSid);
465 return 0;
466 }
467
468 /* Set the Domain SID (aka Computer SID) */
469 if (!SamSetDomainSid (DomainSid))
470 {
471 DebugPrint ("SamSetDomainSid() failed!\n");
472 RtlFreeSid (DomainSid);
473 return 0;
474 }
475
476 /* Append the Admin-RID */
477 AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
478
479 #if 0
480 RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
481 DebugPrint ("Admin-SID: %wZ\n", &SidString);
482 RtlFreeUnicodeString (&SidString);
483 #endif
484
485 /* Create the Administrator account */
486 if (!SamCreateUser(L"Administrator", L"", AdminSid))
487 {
488 /* Check what the error was.
489 * If the Admin Account already exists, then it means Setup
490 * wasn't allowed to finish properly. Instead of rebooting
491 * and not completing it, let it restart instead
492 */
493 LastError = GetLastError();
494 if (LastError != ERROR_USER_EXISTS)
495 {
496 DebugPrint("SamCreateUser() failed!\n");
497 RtlFreeSid(AdminSid);
498 RtlFreeSid(DomainSid);
499 return 0;
500 }
501 }
502
503 /* Create the Administrator profile */
504 if (!CreateUserProfileW(AdminSid, L"Administrator"))
505 {
506 DebugPrint("CreateUserProfileW() failed!\n");
507 RtlFreeSid(AdminSid);
508 RtlFreeSid(DomainSid);
509 return 0;
510 }
511
512 RtlFreeSid(AdminSid);
513 RtlFreeSid(DomainSid);
514
515 CreateTempDir(L"TEMP");
516 CreateTempDir(L"TMP");
517
518 hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf",
519 NULL,
520 INF_STYLE_WIN4,
521 NULL);
522 if (hSysSetupInf == INVALID_HANDLE_VALUE)
523 {
524 DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
525 return 0;
526 }
527
528 if (!ProcessSysSetupInf())
529 {
530 DebugPrint("ProcessSysSetupInf() failed!\n");
531 return 0;
532 }
533
534 if (!EnableUserModePnpManager())
535 {
536 DebugPrint("EnableUserModePnpManager() failed!\n");
537 return 0;
538 }
539
540 InstallWizard();
541
542 SetupCloseInfFile(hSysSetupInf);
543
544 return 0;
545 }
546
547
548 /*
549 * @unimplemented
550 */
551 DWORD STDCALL
552 SetupChangeFontSize(HANDLE hWnd,
553 LPCWSTR lpszFontSize)
554 {
555 return FALSE;
556 }