Enable plug and play manager in livecd.
[reactos.git] / reactos / dll / win32 / 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 InstallLiveCD (HINSTANCE hInstance)
373 {
374 LONG rc;
375 HKEY hKey = NULL;
376 DWORD dwType;
377 DWORD requiredSize;
378 LPTSTR Shell = NULL;
379 TCHAR CommandLine[MAX_PATH];
380 STARTUPINFO StartupInfo;
381 PROCESS_INFORMATION ProcessInformation;
382 BOOL res;
383
384 hSysSetupInf = SetupOpenInfFileW(
385 L"syssetup.inf",
386 NULL,
387 INF_STYLE_WIN4,
388 NULL);
389 if (hSysSetupInf == INVALID_HANDLE_VALUE)
390 {
391 DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
392 return 0;
393 }
394
395 if (!ProcessSysSetupInf())
396 {
397 DebugPrint("ProcessSysSetupInf() failed!\n");
398 return 0;
399 }
400
401 SetupCloseInfFile(hSysSetupInf);
402
403 if (!EnableUserModePnpManager())
404 {
405 DebugPrint("EnableUserModePnpManager() failed!\n");
406 return 0;
407 }
408
409 /* Load the default shell */
410 rc = RegOpenKeyEx(
411 HKEY_LOCAL_MACHINE,
412 TEXT("SOFTWARE\\ReactOS\\Windows NT\\CurrentVersion\\Winlogon"), /* FIXME: should be REGSTR_PATH_WINLOGON */
413 0,
414 KEY_QUERY_VALUE,
415 &hKey);
416 if (rc != ERROR_SUCCESS)
417 goto cleanup;
418 rc = RegQueryValueEx(
419 hKey,
420 TEXT("Shell"),
421 NULL,
422 &dwType,
423 NULL,
424 &requiredSize);
425 if (rc != ERROR_SUCCESS)
426 goto cleanup;
427 else if (dwType != REG_SZ && dwType != REG_EXPAND_SZ)
428 goto cleanup;
429 else if (requiredSize > (MAX_PATH - 1) * sizeof(TCHAR))
430 goto cleanup;
431 Shell = HeapAlloc(GetProcessHeap(), 0, requiredSize + sizeof(TCHAR));
432 if (!Shell)
433 goto cleanup;
434 Shell[requiredSize / sizeof(WCHAR)] = '\0';
435 rc = RegQueryValueEx(
436 hKey,
437 TEXT("Shell"),
438 NULL,
439 NULL,
440 (LPBYTE)Shell,
441 &requiredSize);
442 if (rc != ERROR_SUCCESS)
443 goto cleanup;
444 if (dwType == REG_EXPAND_SZ)
445 ExpandEnvironmentStrings(Shell, CommandLine, MAX_PATH);
446 else if (dwType == REG_SZ)
447 _tcscpy(CommandLine, Shell);
448
449 /* Run the shell */
450 StartupInfo.cb = sizeof(StartupInfo);
451 StartupInfo.lpReserved = NULL;
452 StartupInfo.lpDesktop = NULL;
453 StartupInfo.lpTitle = NULL;
454 StartupInfo.dwFlags = 0;
455 StartupInfo.cbReserved2 = 0;
456 StartupInfo.lpReserved2 = 0;
457 res = CreateProcess(
458 CommandLine,
459 NULL,
460 NULL,
461 NULL,
462 FALSE,
463 0,
464 NULL,
465 NULL,
466 &StartupInfo,
467 &ProcessInformation);
468 if (!res)
469 goto cleanup;
470
471 /* Wait for process termination */
472 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
473
474 cleanup:
475 if (hKey != NULL)
476 RegCloseKey(hKey);
477 HeapFree(GetProcessHeap(), 0, Shell);
478 MessageBoxA(
479 NULL,
480 "You can shutdown your computer, or press ENTER to reboot",
481 "ReactOS LiveCD",
482 MB_OK);
483 return 0;
484 }
485
486
487 DWORD STDCALL
488 InstallReactOS (HINSTANCE hInstance)
489 {
490 TCHAR sAccessories[256];
491 TCHAR sGames[256];
492
493
494 # if 0
495 OutputDebugStringA ("InstallReactOS() called\n");
496
497 if (!InitializeSetupActionLog (FALSE))
498 {
499 OutputDebugStringA ("InitializeSetupActionLog() failed\n");
500 }
501
502 LogItem (SYSSETUP_SEVERITY_INFORMATION,
503 L"ReactOS Setup starting");
504
505 LogItem (SYSSETUP_SEVERITY_FATAL_ERROR,
506 L"Buuuuuuaaaah!");
507
508 LogItem (SYSSETUP_SEVERITY_INFORMATION,
509 L"ReactOS Setup finished");
510
511 TerminateSetupActionLog ();
512 #endif
513 #if 0
514 UNICODE_STRING SidString;
515 #endif
516 ULONG LastError;
517
518 if (!InitializeProfiles ())
519 {
520 DebugPrint ("InitializeProfiles() failed\n");
521 return 0;
522 }
523
524 CoInitialize(NULL);
525
526 /* create desktop shortcuts */
527 CreateShortcut(CSIDL_DESKTOP, NULL, _T("Command Prompt.lnk"), _T("cmd.exe"), IDS_CMT_CMD);
528
529 /* create program startmenu shortcuts */
530 CreateShortcut(CSIDL_PROGRAMS, NULL, _T("winefile.lnk"), _T("winefile.exe"), IDS_CMT_WINEFILE);
531 CreateShortcut(CSIDL_PROGRAMS, NULL, _T("ibrowser.lnk"), _T("ibrowser.exe"), IDS_CMT_IBROWSER);
532 CreateShortcut(CSIDL_PROGRAMS, NULL, _T("Get Firefox.lnk"), _T("getfirefox.exe"), IDS_CMT_GETFIREFOX);
533
534 /* create administritive tools startmenu shortcuts */
535 CreateShortcut(CSIDL_ADMINTOOLS, NULL, _T("Services.lnk"), _T("servman.exe"), IDS_CMT_SERVMAN);
536
537 /* create and fill Accessories subfolder */
538 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, sAccessories, 256))
539 {
540 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Calculator.lnk"), _T("calc.exe"), IDS_CMT_CALC);
541 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Command Prompt.lnk"), _T("cmd.exe"), IDS_CMT_CMD);
542 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Notepad.lnk"), _T("notepad.exe"), IDS_CMT_NOTEPAD);
543 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("ReactOS Explorer.lnk"), _T("explorer.exe"), IDS_CMT_EXPLORER);
544 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("Regedit.lnk"), _T("regedit.exe"), IDS_CMT_REGEDIT);
545 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("WordPad.lnk"), _T("wordpad.exe"), IDS_CMT_WORDPAD);
546 CreateShortcut(CSIDL_PROGRAMS, sAccessories, _T("SnapShot.lnk"), _T("screenshot.exe"), IDS_CMT_SCREENSHOT);
547 }
548
549
550 /* create Games subfolder and fill if the exe is available */
551 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, sGames, 256))
552 {
553 CreateShortcut(CSIDL_PROGRAMS, sGames, _T("Solitaire.lnk"), _T("sol.exe"), IDS_CMT_SOLITAIRE);
554 CreateShortcut(CSIDL_PROGRAMS, sGames, _T("WineMine.lnk"), _T("winemine.exe"), IDS_CMT_WINEMINE);
555 }
556
557 CoUninitialize();
558
559 /* Create the semi-random Domain-SID */
560 CreateRandomSid (&DomainSid);
561 if (DomainSid == NULL)
562 {
563 DebugPrint ("Domain-SID creation failed!\n");
564 return 0;
565 }
566
567 #if 0
568 RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
569 DebugPrint ("Domain-SID: %wZ\n", &SidString);
570 RtlFreeUnicodeString (&SidString);
571 #endif
572
573 /* Initialize the Security Account Manager (SAM) */
574 if (!SamInitializeSAM ())
575 {
576 DebugPrint ("SamInitializeSAM() failed!\n");
577 RtlFreeSid (DomainSid);
578 return 0;
579 }
580
581 /* Set the Domain SID (aka Computer SID) */
582 if (!SamSetDomainSid (DomainSid))
583 {
584 DebugPrint ("SamSetDomainSid() failed!\n");
585 RtlFreeSid (DomainSid);
586 return 0;
587 }
588
589 /* Append the Admin-RID */
590 AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
591
592 #if 0
593 RtlConvertSidToUnicodeString (&SidString, DomainSid, TRUE);
594 DebugPrint ("Admin-SID: %wZ\n", &SidString);
595 RtlFreeUnicodeString (&SidString);
596 #endif
597
598 /* Create the Administrator account */
599 if (!SamCreateUser(L"Administrator", L"", AdminSid))
600 {
601 /* Check what the error was.
602 * If the Admin Account already exists, then it means Setup
603 * wasn't allowed to finish properly. Instead of rebooting
604 * and not completing it, let it restart instead
605 */
606 LastError = GetLastError();
607 if (LastError != ERROR_USER_EXISTS)
608 {
609 DebugPrint("SamCreateUser() failed!\n");
610 RtlFreeSid(AdminSid);
611 RtlFreeSid(DomainSid);
612 return 0;
613 }
614 }
615
616 /* Create the Administrator profile */
617 if (!CreateUserProfileW(AdminSid, L"Administrator"))
618 {
619 DebugPrint("CreateUserProfileW() failed!\n");
620 RtlFreeSid(AdminSid);
621 RtlFreeSid(DomainSid);
622 return 0;
623 }
624
625 RtlFreeSid(AdminSid);
626 RtlFreeSid(DomainSid);
627
628 CreateTempDir(L"TEMP");
629 CreateTempDir(L"TMP");
630
631 hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf",
632 NULL,
633 INF_STYLE_WIN4,
634 NULL);
635 if (hSysSetupInf == INVALID_HANDLE_VALUE)
636 {
637 DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
638 return 0;
639 }
640
641 if (!ProcessSysSetupInf())
642 {
643 DebugPrint("ProcessSysSetupInf() failed!\n");
644 return 0;
645 }
646
647 if (!EnableUserModePnpManager())
648 {
649 DebugPrint("EnableUserModePnpManager() failed!\n");
650 return 0;
651 }
652
653 InstallWizard();
654
655 SetupCloseInfFile(hSysSetupInf);
656
657 return 0;
658 }
659
660
661 /*
662 * @unimplemented
663 */
664 DWORD STDCALL
665 SetupChangeFontSize(HANDLE hWnd,
666 LPCWSTR lpszFontSize)
667 {
668 return FALSE;
669 }