add a note as to why I hackfixed it, so I don't forget
[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 /*
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS system libraries
22 * PURPOSE: System setup
23 * FILE: lib/syssetup/install.c
24 * PROGRAMER: Eric Kohl
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #define WIN32_NO_STATUS
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 <io.h>
37 #include <tchar.h>
38 #include <stdlib.h>
39
40 #include <samlib/samlib.h>
41 #include <syssetup/syssetup.h>
42 #include <userenv.h>
43 #include <setupapi.h>
44
45 #include <shlobj.h>
46 #include <objidl.h>
47 #include <shlwapi.h>
48
49 #include "globals.h"
50 #include "resource.h"
51
52 #include <debug.h>
53
54 DWORD WINAPI
55 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout);
56
57 /* GLOBALS ******************************************************************/
58
59 PSID DomainSid = NULL;
60 PSID AdminSid = NULL;
61
62 HINF hSysSetupInf = INVALID_HANDLE_VALUE;
63
64 /* FUNCTIONS ****************************************************************/
65
66 static VOID
67 DebugPrint(char* fmt,...)
68 {
69 char buffer[512];
70 va_list ap;
71
72 va_start(ap, fmt);
73 vsprintf(buffer, fmt, ap);
74 va_end(ap);
75
76 LogItem(SYSSETUP_SEVERITY_FATAL_ERROR, L"Failed");
77
78 strcat(buffer, "\nRebooting now!");
79 MessageBoxA(NULL,
80 buffer,
81 "ReactOS Setup",
82 MB_OK);
83 }
84
85
86 HRESULT CreateShellLink(LPCTSTR linkPath, LPCTSTR cmd, LPCTSTR arg, LPCTSTR dir, LPCTSTR iconPath, int icon_nr, LPCTSTR comment)
87 {
88 IShellLink* psl;
89 IPersistFile* ppf;
90 #ifndef _UNICODE
91 WCHAR buffer[MAX_PATH];
92 #endif /* _UNICODE */
93
94 HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
95
96 if (SUCCEEDED(hr))
97 {
98 hr = psl->lpVtbl->SetPath(psl, cmd);
99
100 if (arg)
101 {
102 hr = psl->lpVtbl->SetArguments(psl, arg);
103 }
104
105 if (dir)
106 {
107 hr = psl->lpVtbl->SetWorkingDirectory(psl, dir);
108 }
109
110 if (iconPath)
111 {
112 hr = psl->lpVtbl->SetIconLocation(psl, iconPath, icon_nr);
113 }
114
115 if (comment)
116 {
117 hr = psl->lpVtbl->SetDescription(psl, comment);
118 }
119
120 hr = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
121
122 if (SUCCEEDED(hr))
123 {
124 #ifdef _UNICODE
125 hr = ppf->lpVtbl->Save(ppf, linkPath, TRUE);
126 #else /* _UNICODE */
127 MultiByteToWideChar(CP_ACP, 0, linkPath, -1, buffer, MAX_PATH);
128
129 hr = ppf->lpVtbl->Save(ppf, buffer, TRUE);
130 #endif /* _UNICODE */
131
132 ppf->lpVtbl->Release(ppf);
133 }
134
135 psl->lpVtbl->Release(psl);
136 }
137
138 return hr;
139 }
140
141
142 static BOOL
143 CreateShortcut(int csidl, LPCTSTR folder, UINT nIdName, LPCTSTR command, UINT nIdTitle, BOOL bCheckExistence)
144 {
145 TCHAR path[MAX_PATH];
146 TCHAR exeName[MAX_PATH];
147 TCHAR title[256];
148 TCHAR name[256];
149 LPTSTR p = path;
150 TCHAR szWorkingDir[MAX_PATH];
151 LPTSTR lpWorkingDir = NULL;
152 LPTSTR lpFilePart;
153 DWORD dwLen;
154
155 if (ExpandEnvironmentStrings(command,
156 path,
157 sizeof(path) / sizeof(path[0])) == 0)
158 {
159 _tcscpy(path,
160 command);
161 }
162
163 if (bCheckExistence)
164 {
165 if ((_taccess(path, 0 )) == -1)
166 /* Expected error, don't return FALSE */
167 return TRUE;
168 }
169
170 dwLen = GetFullPathName(path,
171 sizeof(szWorkingDir) / sizeof(szWorkingDir[0]),
172 szWorkingDir,
173 &lpFilePart);
174 if (dwLen != 0 && dwLen <= sizeof(szWorkingDir) / sizeof(szWorkingDir[0]))
175 {
176 /* Save the file name */
177 _tcscpy(exeName, lpFilePart);
178
179 if (lpFilePart != NULL)
180 {
181 /* We're only interested in the path. Cut the file name off.
182 Also remove the trailing backslash unless the working directory
183 is only going to be a drive, ie. C:\ */
184 *(lpFilePart--) = _T('\0');
185 if (!(lpFilePart - szWorkingDir == 2 && szWorkingDir[1] == _T(':') &&
186 szWorkingDir[2] == _T('\\')))
187 {
188 *lpFilePart = _T('\0');
189 }
190 }
191
192 lpWorkingDir = szWorkingDir;
193 }
194
195
196 if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
197 return FALSE;
198
199 if (folder)
200 {
201 p = PathAddBackslash(p);
202 _tcscpy(p, folder);
203 }
204
205 p = PathAddBackslash(p);
206
207 if (!LoadString(hDllInstance, nIdName, name, sizeof(name)/sizeof(name[0])))
208 return FALSE;
209 _tcscpy(p, name);
210
211 if (!LoadString(hDllInstance, nIdTitle, title, sizeof(title)/sizeof(title[0])))
212 return FALSE;
213
214 // FIXME: we should pass 'command' straight in here, but shell32 doesn't
215 // expand it, and explorer uses ShellExecuteEx anyway instead of calling
216 // shell32's STDMETHODCALLTYPE Resolve / IShellLinkW_fnResolve
217 return SUCCEEDED(CreateShellLink(path, exeName, _T(""), lpWorkingDir, NULL, 0, title));
218 }
219
220
221 static BOOL
222 CreateShortcutFolder(int csidl, UINT nID, LPTSTR name, int nameLen)
223 {
224 TCHAR path[MAX_PATH];
225 LPTSTR p;
226
227 if (!SHGetSpecialFolderPath(0, path, csidl, TRUE))
228 return FALSE;
229
230 if (!LoadString(hDllInstance, nID, name, nameLen))
231 return FALSE;
232
233 p = PathAddBackslash(path);
234 _tcscpy(p, name);
235
236 return CreateDirectory(path, NULL) || GetLastError()==ERROR_ALREADY_EXISTS;
237 }
238
239
240 static BOOL
241 CreateRandomSid(
242 OUT PSID *Sid)
243 {
244 SID_IDENTIFIER_AUTHORITY SystemAuthority = {SECURITY_NT_AUTHORITY};
245 LARGE_INTEGER SystemTime;
246 PULONG Seed;
247 NTSTATUS Status;
248
249 NtQuerySystemTime(&SystemTime);
250 Seed = &SystemTime.u.LowPart;
251
252 Status = RtlAllocateAndInitializeSid(
253 &SystemAuthority,
254 4,
255 SECURITY_NT_NON_UNIQUE,
256 RtlUniform(Seed),
257 RtlUniform(Seed),
258 RtlUniform(Seed),
259 SECURITY_NULL_RID,
260 SECURITY_NULL_RID,
261 SECURITY_NULL_RID,
262 SECURITY_NULL_RID,
263 Sid);
264 return NT_SUCCESS(Status);
265 }
266
267
268 static VOID
269 AppendRidToSid(
270 OUT PSID *Dst,
271 IN PSID Src,
272 IN ULONG NewRid)
273 {
274 ULONG Rid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
275 UCHAR RidCount;
276 ULONG i;
277
278 RidCount = *RtlSubAuthorityCountSid (Src);
279
280 for (i = 0; i < RidCount; i++)
281 Rid[i] = *RtlSubAuthoritySid (Src, i);
282
283 if (RidCount < 8)
284 {
285 Rid[RidCount] = NewRid;
286 RidCount++;
287 }
288
289 RtlAllocateAndInitializeSid(
290 RtlIdentifierAuthoritySid(Src),
291 RidCount,
292 Rid[0],
293 Rid[1],
294 Rid[2],
295 Rid[3],
296 Rid[4],
297 Rid[5],
298 Rid[6],
299 Rid[7],
300 Dst);
301 }
302
303
304 static VOID
305 CreateTempDir(
306 IN LPCWSTR VarName)
307 {
308 TCHAR szTempDir[MAX_PATH];
309 TCHAR szBuffer[MAX_PATH];
310 DWORD dwLength;
311 HKEY hKey;
312
313 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
314 _T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),
315 0,
316 KEY_QUERY_VALUE,
317 &hKey))
318 {
319 DebugPrint("Error: %lu\n", GetLastError());
320 return;
321 }
322
323 /* Get temp dir */
324 dwLength = MAX_PATH * sizeof(TCHAR);
325 if (RegQueryValueEx(hKey,
326 VarName,
327 NULL,
328 NULL,
329 (LPBYTE)szBuffer,
330 &dwLength))
331 {
332 DebugPrint("Error: %lu\n", GetLastError());
333 RegCloseKey(hKey);
334 return;
335 }
336
337 /* Expand it */
338 if (!ExpandEnvironmentStrings(szBuffer,
339 szTempDir,
340 MAX_PATH))
341 {
342 DebugPrint("Error: %lu\n", GetLastError());
343 RegCloseKey(hKey);
344 return;
345 }
346
347 /* Create profiles directory */
348 if (!CreateDirectory(szTempDir, NULL))
349 {
350 if (GetLastError() != ERROR_ALREADY_EXISTS)
351 {
352 DebugPrint("Error: %lu\n", GetLastError());
353 RegCloseKey(hKey);
354 return;
355 }
356 }
357
358 RegCloseKey(hKey);
359 }
360
361
362 BOOL
363 ProcessSysSetupInf(VOID)
364 {
365 INFCONTEXT InfContext;
366 TCHAR LineBuffer[256];
367 DWORD LineLength;
368
369 if (!SetupFindFirstLine(hSysSetupInf,
370 _T("DeviceInfsToInstall"),
371 NULL,
372 &InfContext))
373 {
374 return FALSE;
375 }
376
377 do
378 {
379 if (!SetupGetStringField(&InfContext,
380 0,
381 LineBuffer,
382 sizeof(LineBuffer)/sizeof(LineBuffer[0]),
383 &LineLength))
384 {
385 return FALSE;
386 }
387
388 if (!SetupDiInstallClass(NULL, LineBuffer, DI_QUIETINSTALL, NULL))
389 {
390 return FALSE;
391 }
392 }
393 while (SetupFindNextLine(&InfContext, &InfContext));
394
395 return TRUE;
396 }
397
398
399 static BOOL
400 EnableUserModePnpManager(VOID)
401 {
402 SC_HANDLE hSCManager = NULL;
403 SC_HANDLE hService = NULL;
404 BOOL ret = FALSE;
405
406 hSCManager = OpenSCManager(NULL, NULL, 0);
407 if (hSCManager == NULL)
408 goto cleanup;
409
410 hService = OpenService(hSCManager, _T("PlugPlay"), SERVICE_CHANGE_CONFIG | SERVICE_START);
411 if (hService == NULL)
412 goto cleanup;
413
414 ret = ChangeServiceConfig(
415 hService,
416 SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
417 NULL, NULL, NULL, NULL, NULL, NULL, NULL);
418 if (!ret)
419 goto cleanup;
420
421 ret = StartService(hService, 0, NULL);
422 if (!ret)
423 goto cleanup;
424
425 ret = TRUE;
426
427 cleanup:
428 if (hSCManager != NULL)
429 CloseServiceHandle(hSCManager);
430 if (hService != NULL)
431 CloseServiceHandle(hService);
432 return ret;
433 }
434
435
436 static BOOL CALLBACK
437 StatusMessageWindowProc(
438 IN HWND hwndDlg,
439 IN UINT uMsg,
440 IN WPARAM wParam,
441 IN LPARAM lParam)
442 {
443 UNREFERENCED_PARAMETER(wParam);
444
445 switch (uMsg)
446 {
447 case WM_INITDIALOG:
448 {
449 TCHAR szMsg[256];
450
451 if (!LoadString(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, sizeof(szMsg)/sizeof(szMsg[0])))
452 return FALSE;
453 SetDlgItemText(hwndDlg, IDC_STATUSLABEL, szMsg);
454 return TRUE;
455 }
456 }
457 return FALSE;
458 }
459
460
461 static DWORD WINAPI
462 ShowStatusMessageThread(
463 IN LPVOID lpParameter)
464 {
465 HWND *phWnd = (HWND *)lpParameter;
466 HWND hWnd;
467 MSG Msg;
468
469 hWnd = CreateDialogParam(
470 hDllInstance,
471 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
472 GetDesktopWindow(),
473 StatusMessageWindowProc,
474 (LPARAM)NULL);
475 if (!hWnd)
476 return 0;
477 *phWnd = hWnd;
478
479 ShowWindow(hWnd, SW_SHOW);
480
481 /* Message loop for the Status window */
482 while (GetMessage(&Msg, NULL, 0, 0))
483 {
484 TranslateMessage(&Msg);
485 DispatchMessage(&Msg);
486 }
487
488 return 0;
489 }
490
491 static BOOL
492 CommonInstall(VOID)
493 {
494 HWND hWnd = NULL;
495
496 hSysSetupInf = SetupOpenInfFileW(
497 L"syssetup.inf",
498 NULL,
499 INF_STYLE_WIN4,
500 NULL);
501 if (hSysSetupInf == INVALID_HANDLE_VALUE)
502 {
503 DebugPrint("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
504 return FALSE;
505 }
506
507 if (!ProcessSysSetupInf())
508 {
509 DebugPrint("ProcessSysSetupInf() failed!\n");
510 SetupCloseInfFile(hSysSetupInf);
511 return FALSE;
512 }
513
514 CreateThread(
515 NULL,
516 0,
517 ShowStatusMessageThread,
518 (LPVOID)&hWnd,
519 0,
520 NULL);
521
522 if (!EnableUserModePnpManager())
523 {
524 DebugPrint("EnableUserModePnpManager() failed!\n");
525 SetupCloseInfFile(hSysSetupInf);
526 EndDialog(hWnd, 0);
527 return FALSE;
528 }
529
530 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
531 {
532 DebugPrint("CMP_WaitNoPendingInstallEvents() failed!\n");
533 SetupCloseInfFile(hSysSetupInf);
534 EndDialog(hWnd, 0);
535 return FALSE;
536 }
537
538 EndDialog(hWnd, 0);
539 return TRUE;
540 }
541
542 DWORD WINAPI
543 InstallLiveCD(IN HINSTANCE hInstance)
544 {
545 STARTUPINFO StartupInfo;
546 PROCESS_INFORMATION ProcessInformation;
547 BOOL res;
548
549 if (!CommonInstall())
550 goto cleanup;
551 SetupCloseInfFile(hSysSetupInf);
552
553 /* Run the shell */
554 StartupInfo.cb = sizeof(StartupInfo);
555 StartupInfo.lpReserved = NULL;
556 StartupInfo.lpDesktop = NULL;
557 StartupInfo.lpTitle = NULL;
558 StartupInfo.dwFlags = 0;
559 StartupInfo.cbReserved2 = 0;
560 StartupInfo.lpReserved2 = 0;
561 res = CreateProcess(
562 _T("userinit.exe"),
563 NULL,
564 NULL,
565 NULL,
566 FALSE,
567 0,
568 NULL,
569 NULL,
570 &StartupInfo,
571 &ProcessInformation);
572 if (!res)
573 goto cleanup;
574
575 /* Wait for process termination */
576 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
577
578 cleanup:
579 MessageBoxA(
580 NULL,
581 "You can shutdown your computer, or press ENTER to reboot",
582 "ReactOS LiveCD",
583 MB_OK);
584 return 0;
585 }
586
587
588 static BOOL
589 CreateShortcuts(VOID)
590 {
591 TCHAR szFolder[256];
592
593 CoInitialize(NULL);
594
595 /* Create desktop shortcuts */
596 CreateShortcut(CSIDL_DESKTOP, NULL, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, FALSE);
597
598 /* Create program startmenu shortcuts */
599 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_EXPLORER, _T("%SystemRoot%\\explorer.exe"), IDS_CMT_EXPLORER, FALSE);
600 CreateShortcut(CSIDL_PROGRAMS, NULL, IDS_SHORT_DOWNLOADER, _T("%SystemRoot%\\system32\\downloader.exe"), IDS_CMT_DOWNLOADER, TRUE);
601
602 /* Create administrative tools startmenu shortcuts */
603 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_SERVICE, _T("%SystemRoot%\\system32\\servman.exe"), IDS_CMT_SERVMAN, FALSE);
604 CreateShortcut(CSIDL_COMMON_ADMINTOOLS, NULL, IDS_SHORT_DEVICE, _T("%SystemRoot%\\system32\\devmgmt.exe"), IDS_CMT_DEVMGMT, FALSE);
605
606 /* Create and fill Accessories subfolder */
607 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_ACCESSORIES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
608 {
609 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CALC, _T("%SystemRoot%\\system32\\calc.exe"), IDS_CMT_CALC, FALSE);
610 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_CMD, _T("%SystemRoot%\\system32\\cmd.exe"), IDS_CMT_CMD, FALSE);
611 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_NOTEPAD, _T("%SystemRoot%\\system32\\notepad.exe"), IDS_CMT_NOTEPAD, FALSE);
612 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_REGEDIT, _T("%SystemRoot%\\regedit.exe"), IDS_CMT_REGEDIT, FALSE);
613 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WORDPAD, _T("%SystemRoot%\\system32\\wordpad.exe"), IDS_CMT_WORDPAD, FALSE);
614 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SNAP, _T("%SystemRoot%\\system32\\screenshot.exe"), IDS_CMT_SCREENSHOT, TRUE);
615 }
616
617 /* Create Games subfolder and fill if the exe is available */
618 if (CreateShortcutFolder(CSIDL_PROGRAMS, IDS_GAMES, szFolder, sizeof(szFolder)/sizeof(szFolder[0])))
619 {
620 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_SOLITAIRE, _T("%SystemRoot%\\system32\\sol.exe"), IDS_CMT_SOLITAIRE, FALSE);
621 CreateShortcut(CSIDL_PROGRAMS, szFolder, IDS_SHORT_WINEMINE, _T("%SystemRoot%\\system32\\winemine.exe"), IDS_CMT_WINEMINE, FALSE);
622 }
623
624 CoUninitialize();
625
626 return TRUE;
627 }
628
629 DWORD WINAPI
630 InstallReactOS(HINSTANCE hInstance)
631 {
632 TCHAR szBuffer[MAX_PATH];
633 DWORD LastError;
634
635 InitializeSetupActionLog(FALSE);
636 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS");
637
638 /* Set user langage to the system language */
639 SetUserDefaultLCID(GetSystemDefaultLCID());
640 SetThreadLocale(GetSystemDefaultLCID());
641
642 if (!InitializeProfiles())
643 {
644 DebugPrint("InitializeProfiles() failed");
645 return 0;
646 }
647
648 if (!CreateShortcuts())
649 {
650 DebugPrint("InitializeProfiles() failed");
651 return 0;
652 }
653
654 /* Initialize the Security Account Manager (SAM) */
655 if (!SamInitializeSAM())
656 {
657 DebugPrint("SamInitializeSAM() failed!");
658 return 0;
659 }
660
661 /* Create the semi-random Domain-SID */
662 if (!CreateRandomSid(&DomainSid))
663 {
664 DebugPrint("Domain-SID creation failed!");
665 return 0;
666 }
667
668 /* Set the Domain SID (aka Computer SID) */
669 if (!SamSetDomainSid(DomainSid))
670 {
671 DebugPrint("SamSetDomainSid() failed!");
672 RtlFreeSid(DomainSid);
673 return 0;
674 }
675
676 /* Append the Admin-RID */
677 AppendRidToSid(&AdminSid, DomainSid, DOMAIN_USER_RID_ADMIN);
678
679 /* Create the Administrator account */
680 if (!SamCreateUser(L"Administrator", L"", AdminSid))
681 {
682 /* Check what the error was.
683 * If the Admin Account already exists, then it means Setup
684 * wasn't allowed to finish properly. Instead of rebooting
685 * and not completing it, let it restart instead
686 */
687 LastError = GetLastError();
688 if (LastError != ERROR_USER_EXISTS)
689 {
690 DebugPrint("SamCreateUser() failed!");
691 RtlFreeSid(AdminSid);
692 RtlFreeSid(DomainSid);
693 return 0;
694 }
695 }
696
697 /* Create the Administrator profile */
698 if (!CreateUserProfileW(AdminSid, L"Administrator"))
699 {
700 DebugPrint("CreateUserProfileW() failed!");
701 RtlFreeSid(AdminSid);
702 RtlFreeSid(DomainSid);
703 return 0;
704 }
705
706 RtlFreeSid(AdminSid);
707 RtlFreeSid(DomainSid);
708
709 CreateTempDir(L"TEMP");
710 CreateTempDir(L"TMP");
711
712 if (GetWindowsDirectory(szBuffer, sizeof(szBuffer) / sizeof(TCHAR)))
713 {
714 PathAddBackslash(szBuffer);
715 _tcscat(szBuffer, _T("system"));
716 CreateDirectory(szBuffer, NULL);
717 }
718
719 if (!CommonInstall())
720 return 0;
721
722 InstallWizard();
723
724 SetupCloseInfFile(hSysSetupInf);
725
726 LogItem(SYSSETUP_SEVERITY_INFORMATION, L"Installing ReactOS done");
727 TerminateSetupActionLog();
728
729 /// THE FOLLOWING DPRINT IS FOR THE SYSTEM REGRESSION TOOL
730 /// DO NOT REMOVE!!!
731 DbgPrint("SYSREG_CHECKPOINT:SYSSETUP_COMPLETE\n");
732
733 return 0;
734 }
735
736
737 /*
738 * @unimplemented
739 */
740 DWORD STDCALL
741 SetupChangeFontSize(
742 IN HANDLE hWnd,
743 IN LPCWSTR lpszFontSize)
744 {
745 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
746 return FALSE;
747 }