[TRANSLATION] Update Traditional Chinese translation. (#1142)
[reactos.git] / dll / win32 / syssetup / install.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: System setup
5 * FILE: dll/win32/syssetup/install.c
6 * PROGRAMER: Eric Kohl
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include "precomp.h"
12
13 #define COBJMACROS
14
15 #include <io.h>
16 #include <wincon.h>
17 #include <winnls.h>
18 #include <winsvc.h>
19 #include <userenv.h>
20 #include <shlobj.h>
21 #include <shlwapi.h>
22 #include <shobjidl.h>
23 #include <rpcproxy.h>
24 #include <ndk/cmfuncs.h>
25
26 #define NDEBUG
27 #include <debug.h>
28
29 DWORD WINAPI
30 CMP_WaitNoPendingInstallEvents(DWORD dwTimeout);
31
32 DWORD WINAPI
33 SetupStartService(LPCWSTR lpServiceName, BOOL bWait);
34
35 /* GLOBALS ******************************************************************/
36
37 HINF hSysSetupInf = INVALID_HANDLE_VALUE;
38 ADMIN_INFO AdminInfo;
39
40 /* FUNCTIONS ****************************************************************/
41
42 static VOID
43 FatalError(char *pszFmt,...)
44 {
45 char szBuffer[512];
46 va_list ap;
47
48 va_start(ap, pszFmt);
49 vsprintf(szBuffer, pszFmt, ap);
50 va_end(ap);
51
52 LogItem(NULL, L"Failed");
53
54 strcat(szBuffer, "\nRebooting now!");
55 MessageBoxA(NULL,
56 szBuffer,
57 "ReactOS Setup",
58 MB_OK);
59 }
60
61 static HRESULT
62 CreateShellLink(
63 LPCWSTR pszLinkPath,
64 LPCWSTR pszCmd,
65 LPCWSTR pszArg,
66 LPCWSTR pszDir,
67 LPCWSTR pszIconPath,
68 INT iIconNr,
69 LPCWSTR pszComment)
70 {
71 IShellLinkW *psl;
72 IPersistFile *ppf;
73
74 HRESULT hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, (LPVOID*)&psl);
75
76 if (SUCCEEDED(hr))
77 {
78 hr = IShellLinkW_SetPath(psl, pszCmd);
79
80 if (pszArg)
81 hr = IShellLinkW_SetArguments(psl, pszArg);
82
83 if (pszDir)
84 hr = IShellLinkW_SetWorkingDirectory(psl, pszDir);
85
86 if (pszIconPath)
87 hr = IShellLinkW_SetIconLocation(psl, pszIconPath, iIconNr);
88
89 if (pszComment)
90 hr = IShellLinkW_SetDescription(psl, pszComment);
91
92 hr = IShellLinkW_QueryInterface(psl, &IID_IPersistFile, (LPVOID*)&ppf);
93
94 if (SUCCEEDED(hr))
95 {
96 hr = IPersistFile_Save(ppf, pszLinkPath, TRUE);
97 IPersistFile_Release(ppf);
98 }
99
100 IShellLinkW_Release(psl);
101 }
102
103 return hr;
104 }
105
106
107 static BOOL
108 CreateShortcut(
109 LPCWSTR pszFolder,
110 LPCWSTR pszName,
111 LPCWSTR pszCommand,
112 LPCWSTR pszDescription,
113 INT iIconNr,
114 LPCWSTR pszWorkingDir)
115 {
116 DWORD dwLen;
117 LPWSTR Ptr;
118 LPWSTR lpFilePart;
119 WCHAR szPath[MAX_PATH];
120 WCHAR szWorkingDirBuf[MAX_PATH];
121
122 /* If no working directory is provided, try to compute a default one */
123 if (pszWorkingDir == NULL || pszWorkingDir[0] == L'\0')
124 {
125 if (ExpandEnvironmentStringsW(pszCommand, szPath, ARRAYSIZE(szPath)) == 0)
126 wcscpy(szPath, pszCommand);
127
128 dwLen = GetFullPathNameW(szPath,
129 ARRAYSIZE(szWorkingDirBuf),
130 szWorkingDirBuf,
131 &lpFilePart);
132 if (dwLen != 0 && dwLen <= ARRAYSIZE(szWorkingDirBuf))
133 {
134 /* Since those should only be called with (.exe) files,
135 lpFilePart has not to be NULL */
136 ASSERT(lpFilePart != NULL);
137
138 /* We're only interested in the path. Cut the file name off.
139 Also remove the trailing backslash unless the working directory
140 is only going to be a drive, i.e. C:\ */
141 *(lpFilePart--) = L'\0';
142 if (!(lpFilePart - szWorkingDirBuf == 2 &&
143 szWorkingDirBuf[1] == L':' && szWorkingDirBuf[2] == L'\\'))
144 {
145 *lpFilePart = L'\0';
146 }
147 pszWorkingDir = szWorkingDirBuf;
148 }
149 }
150
151 /* If we failed to compute a working directory, just do not use one */
152 if (pszWorkingDir && pszWorkingDir[0] == L'\0')
153 pszWorkingDir = NULL;
154
155 /* Build the shortcut file name */
156 wcscpy(szPath, pszFolder);
157 Ptr = PathAddBackslash(szPath);
158 wcscpy(Ptr, pszName);
159
160 /* Create the shortcut */
161 return SUCCEEDED(CreateShellLink(szPath,
162 pszCommand,
163 L"",
164 pszWorkingDir,
165 /* Special value to indicate no icon */
166 (iIconNr != -1 ? pszCommand : NULL),
167 iIconNr,
168 pszDescription));
169 }
170
171
172 static BOOL CreateShortcutsFromSection(HINF hinf, LPWSTR pszSection, LPCWSTR pszFolder)
173 {
174 INFCONTEXT Context;
175 DWORD dwFieldCount;
176 INT iIconNr;
177 WCHAR szCommand[MAX_PATH];
178 WCHAR szName[MAX_PATH];
179 WCHAR szDescription[MAX_PATH];
180 WCHAR szDirectory[MAX_PATH];
181
182 if (!SetupFindFirstLine(hinf, pszSection, NULL, &Context))
183 return FALSE;
184
185 do
186 {
187 dwFieldCount = SetupGetFieldCount(&Context);
188 if (dwFieldCount < 3)
189 continue;
190
191 if (!SetupGetStringFieldW(&Context, 1, szCommand, ARRAYSIZE(szCommand), NULL))
192 continue;
193
194 if (!SetupGetStringFieldW(&Context, 2, szName, ARRAYSIZE(szName), NULL))
195 continue;
196
197 if (!SetupGetStringFieldW(&Context, 3, szDescription, ARRAYSIZE(szDescription), NULL))
198 continue;
199
200 if (dwFieldCount < 4 || !SetupGetIntField(&Context, 4, &iIconNr))
201 iIconNr = -1; /* Special value to indicate no icon */
202
203 if (dwFieldCount < 5 || !SetupGetStringFieldW(&Context, 5, szDirectory, ARRAYSIZE(szDirectory), NULL))
204 szDirectory[0] = L'\0';
205
206 wcscat(szName, L".lnk");
207
208 CreateShortcut(pszFolder, szName, szCommand, szDescription, iIconNr, szDirectory);
209
210 } while (SetupFindNextLine(&Context, &Context));
211
212 return TRUE;
213 }
214
215 static BOOL CreateShortcuts(HINF hinf, LPCWSTR szSection)
216 {
217 INFCONTEXT Context;
218 WCHAR szPath[MAX_PATH];
219 WCHAR szFolder[MAX_PATH];
220 WCHAR szFolderSection[MAX_PATH];
221 INT csidl;
222
223 CoInitialize(NULL);
224
225 if (!SetupFindFirstLine(hinf, szSection, NULL, &Context))
226 return FALSE;
227
228 do
229 {
230 if (SetupGetFieldCount(&Context) < 2)
231 continue;
232
233 if (!SetupGetStringFieldW(&Context, 0, szFolderSection, ARRAYSIZE(szFolderSection), NULL))
234 continue;
235
236 if (!SetupGetIntField(&Context, 1, &csidl))
237 continue;
238
239 if (!SetupGetStringFieldW(&Context, 2, szFolder, ARRAYSIZE(szFolder), NULL))
240 continue;
241
242 if (FAILED(SHGetFolderPathAndSubDirW(NULL, csidl|CSIDL_FLAG_CREATE, (HANDLE)-1, SHGFP_TYPE_DEFAULT, szFolder, szPath)))
243 continue;
244
245 CreateShortcutsFromSection(hinf, szFolderSection, szPath);
246
247 } while (SetupFindNextLine(&Context, &Context));
248
249 CoUninitialize();
250
251 return TRUE;
252 }
253
254 static VOID
255 CreateTempDir(
256 IN LPCWSTR VarName)
257 {
258 WCHAR szTempDir[MAX_PATH];
259 WCHAR szBuffer[MAX_PATH];
260 DWORD dwLength;
261 HKEY hKey;
262
263 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
264 L"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
265 0,
266 KEY_QUERY_VALUE,
267 &hKey) != ERROR_SUCCESS)
268 {
269 FatalError("Error: %lu\n", GetLastError());
270 return;
271 }
272
273 /* Get temp dir */
274 dwLength = sizeof(szBuffer);
275 if (RegQueryValueExW(hKey,
276 VarName,
277 NULL,
278 NULL,
279 (LPBYTE)szBuffer,
280 &dwLength) != ERROR_SUCCESS)
281 {
282 FatalError("Error: %lu\n", GetLastError());
283 goto cleanup;
284 }
285
286 /* Expand it */
287 if (!ExpandEnvironmentStringsW(szBuffer, szTempDir, ARRAYSIZE(szTempDir)))
288 {
289 FatalError("Error: %lu\n", GetLastError());
290 goto cleanup;
291 }
292
293 /* Create profiles directory */
294 if (!CreateDirectoryW(szTempDir, NULL))
295 {
296 if (GetLastError() != ERROR_ALREADY_EXISTS)
297 {
298 FatalError("Error: %lu\n", GetLastError());
299 goto cleanup;
300 }
301 }
302
303 cleanup:
304 RegCloseKey(hKey);
305 }
306
307 static BOOL
308 InstallSysSetupInfDevices(VOID)
309 {
310 INFCONTEXT InfContext;
311 WCHAR szLineBuffer[256];
312 DWORD dwLineLength;
313
314 if (!SetupFindFirstLineW(hSysSetupInf,
315 L"DeviceInfsToInstall",
316 NULL,
317 &InfContext))
318 {
319 return FALSE;
320 }
321
322 do
323 {
324 if (!SetupGetStringFieldW(&InfContext,
325 0,
326 szLineBuffer,
327 ARRAYSIZE(szLineBuffer),
328 &dwLineLength))
329 {
330 return FALSE;
331 }
332
333 if (!SetupDiInstallClassW(NULL, szLineBuffer, DI_QUIETINSTALL, NULL))
334 {
335 return FALSE;
336 }
337 }
338 while (SetupFindNextLine(&InfContext, &InfContext));
339
340 return TRUE;
341 }
342
343 static BOOL
344 InstallSysSetupInfComponents(VOID)
345 {
346 INFCONTEXT InfContext;
347 WCHAR szNameBuffer[256];
348 WCHAR szSectionBuffer[256];
349 HINF hComponentInf = INVALID_HANDLE_VALUE;
350
351 if (!SetupFindFirstLineW(hSysSetupInf,
352 L"Infs.Always",
353 NULL,
354 &InfContext))
355 {
356 DPRINT("No Inf.Always section found\n");
357 }
358 else
359 {
360 do
361 {
362 if (!SetupGetStringFieldW(&InfContext,
363 1, // Get the component name
364 szNameBuffer,
365 ARRAYSIZE(szNameBuffer),
366 NULL))
367 {
368 FatalError("Error while trying to get component name \n");
369 return FALSE;
370 }
371
372 if (!SetupGetStringFieldW(&InfContext,
373 2, // Get the component install section
374 szSectionBuffer,
375 ARRAYSIZE(szSectionBuffer),
376 NULL))
377 {
378 FatalError("Error while trying to get component install section \n");
379 return FALSE;
380 }
381
382 DPRINT("Trying to execute install section '%S' from '%S' \n", szSectionBuffer, szNameBuffer);
383
384 hComponentInf = SetupOpenInfFileW(szNameBuffer,
385 NULL,
386 INF_STYLE_WIN4,
387 NULL);
388
389 if (hComponentInf == INVALID_HANDLE_VALUE)
390 {
391 FatalError("SetupOpenInfFileW() failed to open '%S' (Error: %lu)\n", szNameBuffer, GetLastError());
392 return FALSE;
393 }
394
395 if (!SetupInstallFromInfSectionW(NULL,
396 hComponentInf,
397 szSectionBuffer,
398 SPINST_ALL,
399 NULL,
400 NULL,
401 SP_COPY_NEWER,
402 SetupDefaultQueueCallbackW,
403 NULL,
404 NULL,
405 NULL))
406 {
407 FatalError("Error while trying to install : %S (Error: %lu)\n", szNameBuffer, GetLastError());
408 SetupCloseInfFile(hComponentInf);
409 return FALSE;
410 }
411
412 SetupCloseInfFile(hComponentInf);
413 }
414 while (SetupFindNextLine(&InfContext, &InfContext));
415 }
416
417 return TRUE;
418 }
419
420
421
422 BOOL
423 RegisterTypeLibraries(HINF hinf, LPCWSTR szSection)
424 {
425 INFCONTEXT InfContext;
426 BOOL res;
427 WCHAR szName[MAX_PATH];
428 WCHAR szPath[MAX_PATH];
429 INT csidl;
430 LPWSTR p;
431 HMODULE hmod;
432 HRESULT hret;
433
434 /* Begin iterating the entries in the inf section */
435 res = SetupFindFirstLine(hinf, szSection, NULL, &InfContext);
436 if (!res) return FALSE;
437
438 do
439 {
440 /* Get the name of the current type library */
441 if (!SetupGetStringFieldW(&InfContext, 1, szName, ARRAYSIZE(szName), NULL))
442 {
443 FatalError("SetupGetStringFieldW failed\n");
444 continue;
445 }
446
447 if (!SetupGetIntField(&InfContext, 2, &csidl))
448 csidl = CSIDL_SYSTEM;
449
450 hret = SHGetFolderPathW(NULL, csidl, NULL, 0, szPath);
451 if (FAILED(hret))
452 {
453 FatalError("SHGetFolderPathW failed hret=0x%lx\n", hret);
454 continue;
455 }
456
457 p = PathAddBackslash(szPath);
458 wcscpy(p, szName);
459
460 hmod = LoadLibraryW(szName);
461 if (hmod == NULL)
462 {
463 FatalError("LoadLibraryW failed\n");
464 continue;
465 }
466
467 __wine_register_resources(hmod);
468
469 } while (SetupFindNextLine(&InfContext, &InfContext));
470
471 return TRUE;
472 }
473
474 static BOOL
475 EnableUserModePnpManager(VOID)
476 {
477 SC_HANDLE hSCManager = NULL;
478 SC_HANDLE hService = NULL;
479 BOOL bRet = FALSE;
480
481 hSCManager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
482 if (hSCManager == NULL)
483 {
484 DPRINT1("Unable to open the service control manager.\n");
485 DPRINT1("Last Error %d\n", GetLastError());
486 goto cleanup;
487 }
488
489 hService = OpenServiceW(hSCManager,
490 L"PlugPlay",
491 SERVICE_CHANGE_CONFIG | SERVICE_START);
492 if (hService == NULL)
493 {
494 DPRINT1("Unable to open PlugPlay service\n");
495 goto cleanup;
496 }
497
498 bRet = ChangeServiceConfigW(hService,
499 SERVICE_NO_CHANGE,
500 SERVICE_AUTO_START,
501 SERVICE_NO_CHANGE,
502 NULL, NULL, NULL,
503 NULL, NULL, NULL, NULL);
504 if (!bRet)
505 {
506 DPRINT1("Unable to change the service configuration\n");
507 goto cleanup;
508 }
509
510 bRet = StartServiceW(hService, 0, NULL);
511 if (!bRet && (GetLastError() != ERROR_SERVICE_ALREADY_RUNNING))
512 {
513 DPRINT1("Unable to start service\n");
514 goto cleanup;
515 }
516
517 bRet = TRUE;
518
519 cleanup:
520 if (hService != NULL)
521 CloseServiceHandle(hService);
522 if (hSCManager != NULL)
523 CloseServiceHandle(hSCManager);
524 return bRet;
525 }
526
527 static INT_PTR CALLBACK
528 StatusMessageWindowProc(
529 IN HWND hwndDlg,
530 IN UINT uMsg,
531 IN WPARAM wParam,
532 IN LPARAM lParam)
533 {
534 UNREFERENCED_PARAMETER(wParam);
535
536 switch (uMsg)
537 {
538 case WM_INITDIALOG:
539 {
540 WCHAR szMsg[256];
541
542 if (!LoadStringW(hDllInstance, IDS_STATUS_INSTALL_DEV, szMsg, ARRAYSIZE(szMsg)))
543 return FALSE;
544 SetDlgItemTextW(hwndDlg, IDC_STATUSLABEL, szMsg);
545 return TRUE;
546 }
547 }
548 return FALSE;
549 }
550
551 static DWORD WINAPI
552 ShowStatusMessageThread(
553 IN LPVOID lpParameter)
554 {
555 HWND hWnd, hItem;
556 MSG Msg;
557 UNREFERENCED_PARAMETER(lpParameter);
558
559 hWnd = CreateDialogParam(hDllInstance,
560 MAKEINTRESOURCE(IDD_STATUSWINDOW_DLG),
561 GetDesktopWindow(),
562 StatusMessageWindowProc,
563 (LPARAM)NULL);
564 if (!hWnd)
565 return 0;
566
567 ShowWindow(hWnd, SW_SHOW);
568
569 hItem = GetDlgItem(hWnd, IDC_STATUSPROGRESS);
570 if (hItem)
571 {
572 PostMessage(hItem, PBM_SETMARQUEE, TRUE, 40);
573 }
574
575 /* Message loop for the Status window */
576 while (GetMessage(&Msg, NULL, 0, 0))
577 {
578 TranslateMessage(&Msg);
579 DispatchMessage(&Msg);
580 }
581
582 EndDialog(hWnd, 0);
583
584 return 0;
585 }
586
587 static LONG
588 ReadRegSzKey(
589 IN HKEY hKey,
590 IN LPCWSTR pszKey,
591 OUT LPWSTR* pValue)
592 {
593 LONG rc;
594 DWORD dwType;
595 DWORD cbData = 0;
596 LPWSTR pwszValue;
597
598 if (!pValue)
599 return ERROR_INVALID_PARAMETER;
600
601 *pValue = NULL;
602 rc = RegQueryValueExW(hKey, pszKey, NULL, &dwType, NULL, &cbData);
603 if (rc != ERROR_SUCCESS)
604 return rc;
605 if (dwType != REG_SZ)
606 return ERROR_FILE_NOT_FOUND;
607 pwszValue = HeapAlloc(GetProcessHeap(), 0, cbData + sizeof(WCHAR));
608 if (!pwszValue)
609 return ERROR_NOT_ENOUGH_MEMORY;
610 rc = RegQueryValueExW(hKey, pszKey, NULL, NULL, (LPBYTE)pwszValue, &cbData);
611 if (rc != ERROR_SUCCESS)
612 {
613 HeapFree(GetProcessHeap(), 0, pwszValue);
614 return rc;
615 }
616 /* NULL-terminate the string */
617 pwszValue[cbData / sizeof(WCHAR)] = '\0';
618
619 *pValue = pwszValue;
620 return ERROR_SUCCESS;
621 }
622
623 static BOOL
624 IsConsoleBoot(VOID)
625 {
626 HKEY hControlKey = NULL;
627 LPWSTR pwszSystemStartOptions = NULL;
628 LPWSTR pwszCurrentOption, pwszNextOption; /* Pointers into SystemStartOptions */
629 BOOL bConsoleBoot = FALSE;
630 LONG rc;
631
632 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
633 L"SYSTEM\\CurrentControlSet\\Control",
634 0,
635 KEY_QUERY_VALUE,
636 &hControlKey);
637 if (rc != ERROR_SUCCESS)
638 goto cleanup;
639
640 rc = ReadRegSzKey(hControlKey, L"SystemStartOptions", &pwszSystemStartOptions);
641 if (rc != ERROR_SUCCESS)
642 goto cleanup;
643
644 /* Check for CONSOLE switch in SystemStartOptions */
645 pwszCurrentOption = pwszSystemStartOptions;
646 while (pwszCurrentOption)
647 {
648 pwszNextOption = wcschr(pwszCurrentOption, L' ');
649 if (pwszNextOption)
650 *pwszNextOption = L'\0';
651 if (wcsicmp(pwszCurrentOption, L"CONSOLE") == 0)
652 {
653 DPRINT("Found %S. Switching to console boot\n", pwszCurrentOption);
654 bConsoleBoot = TRUE;
655 goto cleanup;
656 }
657 pwszCurrentOption = pwszNextOption ? pwszNextOption + 1 : NULL;
658 }
659
660 cleanup:
661 if (hControlKey != NULL)
662 RegCloseKey(hControlKey);
663 if (pwszSystemStartOptions)
664 HeapFree(GetProcessHeap(), 0, pwszSystemStartOptions);
665 return bConsoleBoot;
666 }
667
668 static BOOL
669 CommonInstall(VOID)
670 {
671 HANDLE hThread = NULL;
672 BOOL bResult = FALSE;
673
674 hSysSetupInf = SetupOpenInfFileW(L"syssetup.inf",
675 NULL,
676 INF_STYLE_WIN4,
677 NULL);
678 if (hSysSetupInf == INVALID_HANDLE_VALUE)
679 {
680 FatalError("SetupOpenInfFileW() failed to open 'syssetup.inf' (Error: %lu)\n", GetLastError());
681 return FALSE;
682 }
683
684 if (!InstallSysSetupInfDevices())
685 {
686 FatalError("InstallSysSetupInfDevices() failed!\n");
687 goto Exit;
688 }
689
690 if(!InstallSysSetupInfComponents())
691 {
692 FatalError("InstallSysSetupInfComponents() failed!\n");
693 goto Exit;
694 }
695
696 if (!IsConsoleBoot())
697 {
698 hThread = CreateThread(NULL,
699 0,
700 ShowStatusMessageThread,
701 NULL,
702 0,
703 NULL);
704 }
705
706 if (!EnableUserModePnpManager())
707 {
708 FatalError("EnableUserModePnpManager() failed!\n");
709 goto Exit;
710 }
711
712 if (CMP_WaitNoPendingInstallEvents(INFINITE) != WAIT_OBJECT_0)
713 {
714 FatalError("CMP_WaitNoPendingInstallEvents() failed!\n");
715 goto Exit;
716 }
717
718 bResult = TRUE;
719
720 Exit:
721
722 if (bResult == FALSE)
723 {
724 SetupCloseInfFile(hSysSetupInf);
725 }
726
727 if (hThread != NULL)
728 {
729 PostThreadMessage(GetThreadId(hThread), WM_QUIT, 0, 0);
730 WaitForSingleObject(hThread, INFINITE);
731 CloseHandle(hThread);
732 }
733
734 return bResult;
735 }
736
737 /* Install a section of a .inf file
738 * Returns TRUE if success, FALSE if failure. Error code can
739 * be retrieved with GetLastError()
740 */
741 static
742 BOOL
743 InstallInfSection(
744 IN HWND hWnd,
745 IN LPCWSTR InfFile,
746 IN LPCWSTR InfSection OPTIONAL,
747 IN LPCWSTR InfService OPTIONAL)
748 {
749 WCHAR Buffer[MAX_PATH];
750 HINF hInf = INVALID_HANDLE_VALUE;
751 UINT BufferSize;
752 PVOID Context = NULL;
753 BOOL ret = FALSE;
754
755 /* Get Windows directory */
756 BufferSize = ARRAYSIZE(Buffer) - 5 - wcslen(InfFile);
757 if (GetWindowsDirectoryW(Buffer, BufferSize) > BufferSize)
758 {
759 /* Function failed */
760 SetLastError(ERROR_GEN_FAILURE);
761 goto cleanup;
762 }
763 /* We have enough space to add some information in the buffer */
764 if (Buffer[wcslen(Buffer) - 1] != '\\')
765 wcscat(Buffer, L"\\");
766 wcscat(Buffer, L"Inf\\");
767 wcscat(Buffer, InfFile);
768
769 /* Install specified section */
770 hInf = SetupOpenInfFileW(Buffer, NULL, INF_STYLE_WIN4, NULL);
771 if (hInf == INVALID_HANDLE_VALUE)
772 goto cleanup;
773
774 Context = SetupInitDefaultQueueCallback(hWnd);
775 if (Context == NULL)
776 goto cleanup;
777
778 ret = TRUE;
779 if (ret && InfSection)
780 {
781 ret = SetupInstallFromInfSectionW(
782 hWnd, hInf,
783 InfSection, SPINST_ALL,
784 NULL, NULL, SP_COPY_NEWER,
785 SetupDefaultQueueCallbackW, Context,
786 NULL, NULL);
787 }
788 if (ret && InfService)
789 {
790 ret = SetupInstallServicesFromInfSectionW(hInf, InfService, 0);
791 }
792
793 cleanup:
794 if (Context)
795 SetupTermDefaultQueueCallback(Context);
796 if (hInf != INVALID_HANDLE_VALUE)
797 SetupCloseInfFile(hInf);
798 return ret;
799 }
800
801 static
802 DWORD
803 InstallLiveCD(VOID)
804 {
805 STARTUPINFOW StartupInfo;
806 PROCESS_INFORMATION ProcessInformation;
807 BOOL bRes;
808
809 /* Hack: Install TCP/IP protocol driver */
810 bRes = InstallInfSection(NULL,
811 L"nettcpip.inf",
812 L"MS_TCPIP.PrimaryInstall",
813 L"MS_TCPIP.PrimaryInstall.Services");
814 if (!bRes && GetLastError() != ERROR_FILE_NOT_FOUND)
815 {
816 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
817 }
818 else
819 {
820 /* Start the TCP/IP protocol driver */
821 SetupStartService(L"Tcpip", FALSE);
822 SetupStartService(L"Dhcp", FALSE);
823 }
824
825 if (!CommonInstall())
826 goto error;
827
828 /* Register components */
829 _SEH2_TRY
830 {
831 if (!SetupInstallFromInfSectionW(NULL,
832 hSysSetupInf, L"RegistrationPhase2",
833 SPINST_ALL,
834 0, NULL, 0, NULL, NULL, NULL, NULL))
835 {
836 DPRINT1("SetupInstallFromInfSectionW failed!\n");
837 }
838
839 RegisterTypeLibraries(hSysSetupInf, L"TypeLibraries");
840 }
841 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
842 {
843 DPRINT1("Catching exception\n");
844 }
845 _SEH2_END;
846
847 SetupCloseInfFile(hSysSetupInf);
848
849 /* Run the shell */
850 ZeroMemory(&StartupInfo, sizeof(StartupInfo));
851 StartupInfo.cb = sizeof(StartupInfo);
852 bRes = CreateProcessW(L"userinit.exe",
853 NULL,
854 NULL,
855 NULL,
856 FALSE,
857 0,
858 NULL,
859 NULL,
860 &StartupInfo,
861 &ProcessInformation);
862 if (!bRes)
863 goto error;
864
865 CloseHandle(ProcessInformation.hThread);
866 CloseHandle(ProcessInformation.hProcess);
867
868 return 0;
869
870 error:
871 MessageBoxW(
872 NULL,
873 L"Failed to load LiveCD! You can shutdown your computer, or press ENTER to reboot.",
874 L"ReactOS LiveCD",
875 MB_OK);
876 return 0;
877 }
878
879
880 static BOOL
881 SetSetupType(DWORD dwSetupType)
882 {
883 DWORD dwError;
884 HKEY hKey;
885
886 dwError = RegOpenKeyExW(
887 HKEY_LOCAL_MACHINE,
888 L"SYSTEM\\Setup",
889 0,
890 KEY_SET_VALUE,
891 &hKey);
892 if (dwError != ERROR_SUCCESS)
893 return FALSE;
894
895 dwError = RegSetValueExW(
896 hKey,
897 L"SetupType",
898 0,
899 REG_DWORD,
900 (LPBYTE)&dwSetupType,
901 sizeof(DWORD));
902 RegCloseKey(hKey);
903 if (dwError != ERROR_SUCCESS)
904 return FALSE;
905
906 return TRUE;
907 }
908
909 static DWORD CALLBACK
910 HotkeyThread(LPVOID Parameter)
911 {
912 ATOM hotkey;
913 MSG msg;
914
915 DPRINT("HotkeyThread start\n");
916
917 hotkey = GlobalAddAtomW(L"Setup Shift+F10 Hotkey");
918
919 if (!RegisterHotKey(NULL, hotkey, MOD_SHIFT, VK_F10))
920 DPRINT1("RegisterHotKey failed with %lu\n", GetLastError());
921
922 while (GetMessage(&msg, NULL, 0, 0))
923 {
924 if (msg.hwnd == NULL && msg.message == WM_HOTKEY && msg.wParam == hotkey)
925 {
926 STARTUPINFOW si = { sizeof(si) };
927 PROCESS_INFORMATION pi;
928
929 if (CreateProcessW(L"cmd.exe",
930 NULL,
931 NULL,
932 NULL,
933 FALSE,
934 CREATE_NEW_CONSOLE,
935 NULL,
936 NULL,
937 &si,
938 &pi))
939 {
940 CloseHandle(pi.hProcess);
941 CloseHandle(pi.hThread);
942 }
943 else
944 {
945 DPRINT1("Failed to launch command prompt: %lu\n", GetLastError());
946 }
947 }
948 }
949
950 UnregisterHotKey(NULL, hotkey);
951 GlobalDeleteAtom(hotkey);
952
953 DPRINT("HotkeyThread terminate\n");
954 return 0;
955 }
956
957
958 static
959 BOOL
960 InitializeProgramFilesDir(VOID)
961 {
962 LONG Error;
963 HKEY hKey;
964 DWORD dwLength;
965 WCHAR szProgramFilesDirPath[MAX_PATH];
966 WCHAR szCommonFilesDirPath[MAX_PATH];
967 WCHAR szBuffer[MAX_PATH];
968
969 /* Load 'Program Files' location */
970 if (!LoadStringW(hDllInstance,
971 IDS_PROGRAMFILES,
972 szBuffer,
973 ARRAYSIZE(szBuffer)))
974 {
975 DPRINT1("Error: %lu\n", GetLastError());
976 return FALSE;
977 }
978
979 if (!LoadStringW(hDllInstance,
980 IDS_COMMONFILES,
981 szCommonFilesDirPath,
982 ARRAYSIZE(szCommonFilesDirPath)))
983 {
984 DPRINT1("Warning: %lu\n", GetLastError());
985 }
986
987 /* Expand it */
988 if (!ExpandEnvironmentStringsW(szBuffer,
989 szProgramFilesDirPath,
990 ARRAYSIZE(szProgramFilesDirPath)))
991 {
992 DPRINT1("Error: %lu\n", GetLastError());
993 return FALSE;
994 }
995
996 wcscpy(szBuffer, szProgramFilesDirPath);
997 wcscat(szBuffer, L"\\");
998 wcscat(szBuffer, szCommonFilesDirPath);
999
1000 if (!ExpandEnvironmentStringsW(szBuffer,
1001 szCommonFilesDirPath,
1002 ARRAYSIZE(szCommonFilesDirPath)))
1003 {
1004 DPRINT1("Warning: %lu\n", GetLastError());
1005 }
1006
1007 /* Store it */
1008 Error = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1009 L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
1010 0,
1011 KEY_SET_VALUE,
1012 &hKey);
1013 if (Error != ERROR_SUCCESS)
1014 {
1015 DPRINT1("Error: %lu\n", Error);
1016 return FALSE;
1017 }
1018
1019 dwLength = (wcslen(szProgramFilesDirPath) + 1) * sizeof(WCHAR);
1020 Error = RegSetValueExW(hKey,
1021 L"ProgramFilesDir",
1022 0,
1023 REG_SZ,
1024 (LPBYTE)szProgramFilesDirPath,
1025 dwLength);
1026 if (Error != ERROR_SUCCESS)
1027 {
1028 DPRINT1("Error: %lu\n", Error);
1029 RegCloseKey(hKey);
1030 return FALSE;
1031 }
1032
1033 dwLength = (wcslen(szCommonFilesDirPath) + 1) * sizeof(WCHAR);
1034 Error = RegSetValueExW(hKey,
1035 L"CommonFilesDir",
1036 0,
1037 REG_SZ,
1038 (LPBYTE)szCommonFilesDirPath,
1039 dwLength);
1040 if (Error != ERROR_SUCCESS)
1041 {
1042 DPRINT1("Warning: %lu\n", Error);
1043 }
1044
1045 RegCloseKey(hKey);
1046
1047 /* Create directory */
1048 // FIXME: Security!
1049 if (!CreateDirectoryW(szProgramFilesDirPath, NULL))
1050 {
1051 if (GetLastError() != ERROR_ALREADY_EXISTS)
1052 {
1053 DPRINT1("Error: %lu\n", GetLastError());
1054 return FALSE;
1055 }
1056 }
1057
1058 /* Create directory */
1059 // FIXME: Security!
1060 if (!CreateDirectoryW(szCommonFilesDirPath, NULL))
1061 {
1062 if (GetLastError() != ERROR_ALREADY_EXISTS)
1063 {
1064 DPRINT1("Warning: %lu\n", GetLastError());
1065 // return FALSE;
1066 }
1067 }
1068
1069 return TRUE;
1070 }
1071
1072
1073 static
1074 VOID
1075 InitializeDefaultUserLocale(VOID)
1076 {
1077 WCHAR szBuffer[80];
1078 PWSTR ptr;
1079 HKEY hLocaleKey;
1080 DWORD ret;
1081 DWORD dwSize;
1082 LCID lcid;
1083 INT i;
1084
1085 struct {LCTYPE LCType; PWSTR pValue;} LocaleData[] = {
1086 /* Number */
1087 {LOCALE_SDECIMAL, L"sDecimal"},
1088 {LOCALE_STHOUSAND, L"sThousand"},
1089 {LOCALE_SNEGATIVESIGN, L"sNegativeSign"},
1090 {LOCALE_SPOSITIVESIGN, L"sPositiveSign"},
1091 {LOCALE_SGROUPING, L"sGrouping"},
1092 {LOCALE_SLIST, L"sList"},
1093 {LOCALE_SNATIVEDIGITS, L"sNativeDigits"},
1094 {LOCALE_INEGNUMBER, L"iNegNumber"},
1095 {LOCALE_IDIGITS, L"iDigits"},
1096 {LOCALE_ILZERO, L"iLZero"},
1097 {LOCALE_IMEASURE, L"iMeasure"},
1098 {LOCALE_IDIGITSUBSTITUTION, L"NumShape"},
1099
1100 /* Currency */
1101 {LOCALE_SCURRENCY, L"sCurrency"},
1102 {LOCALE_SMONDECIMALSEP, L"sMonDecimalSep"},
1103 {LOCALE_SMONTHOUSANDSEP, L"sMonThousandSep"},
1104 {LOCALE_SMONGROUPING, L"sMonGrouping"},
1105 {LOCALE_ICURRENCY, L"iCurrency"},
1106 {LOCALE_INEGCURR, L"iNegCurr"},
1107 {LOCALE_ICURRDIGITS, L"iCurrDigits"},
1108
1109 /* Time */
1110 {LOCALE_STIMEFORMAT, L"sTimeFormat"},
1111 {LOCALE_STIME, L"sTime"},
1112 {LOCALE_S1159, L"s1159"},
1113 {LOCALE_S2359, L"s2359"},
1114 {LOCALE_ITIME, L"iTime"},
1115 {LOCALE_ITIMEMARKPOSN, L"iTimePrefix"},
1116 {LOCALE_ITLZERO, L"iTLZero"},
1117
1118 /* Date */
1119 {LOCALE_SLONGDATE, L"sLongDate"},
1120 {LOCALE_SSHORTDATE, L"sShortDate"},
1121 {LOCALE_SDATE, L"sDate"},
1122 {LOCALE_IFIRSTDAYOFWEEK, L"iFirstDayOfWeek"},
1123 {LOCALE_IFIRSTWEEKOFYEAR, L"iFirstWeekOfYear"},
1124 {LOCALE_IDATE, L"iDate"},
1125 {LOCALE_ICALENDARTYPE, L"iCalendarType"},
1126
1127 /* Misc */
1128 {LOCALE_SCOUNTRY, L"sCountry"},
1129 {LOCALE_SABBREVLANGNAME, L"sLanguage"},
1130 {LOCALE_ICOUNTRY, L"iCountry"},
1131 {0, NULL}};
1132
1133 ret = RegOpenKeyExW(HKEY_USERS,
1134 L".DEFAULT\\Control Panel\\International",
1135 0,
1136 KEY_READ | KEY_WRITE,
1137 &hLocaleKey);
1138 if (ret != ERROR_SUCCESS)
1139 {
1140 return;
1141 }
1142
1143 dwSize = 9 * sizeof(WCHAR);
1144 ret = RegQueryValueExW(hLocaleKey,
1145 L"Locale",
1146 NULL,
1147 NULL,
1148 (PBYTE)szBuffer,
1149 &dwSize);
1150 if (ret != ERROR_SUCCESS)
1151 goto done;
1152
1153 lcid = (LCID)wcstoul(szBuffer, &ptr, 16);
1154 if (lcid == 0)
1155 goto done;
1156
1157 i = 0;
1158 while (LocaleData[i].pValue != NULL)
1159 {
1160 if (GetLocaleInfoW(lcid,
1161 LocaleData[i].LCType | LOCALE_NOUSEROVERRIDE,
1162 szBuffer,
1163 ARRAYSIZE(szBuffer)))
1164 {
1165 RegSetValueExW(hLocaleKey,
1166 LocaleData[i].pValue,
1167 0,
1168 REG_SZ,
1169 (PBYTE)szBuffer,
1170 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1171 }
1172
1173 i++;
1174 }
1175
1176 done:
1177 RegCloseKey(hLocaleKey);
1178 }
1179
1180
1181 static
1182 DWORD
1183 SaveDefaultUserHive(VOID)
1184 {
1185 WCHAR szDefaultUserHive[MAX_PATH];
1186 HKEY hUserKey = NULL;
1187 DWORD cchSize;
1188 DWORD dwError;
1189
1190 DPRINT("SaveDefaultUserHive()\n");
1191
1192 cchSize = ARRAYSIZE(szDefaultUserHive);
1193 GetDefaultUserProfileDirectoryW(szDefaultUserHive, &cchSize);
1194
1195 wcscat(szDefaultUserHive, L"\\ntuser.dat");
1196
1197 dwError = RegOpenKeyExW(HKEY_USERS,
1198 L".DEFAULT",
1199 0,
1200 KEY_READ,
1201 &hUserKey);
1202 if (dwError != ERROR_SUCCESS)
1203 {
1204 DPRINT1("RegOpenKeyExW() failed (Error %lu)\n", dwError);
1205 return dwError;
1206 }
1207
1208 pSetupEnablePrivilege(L"SeBackupPrivilege", TRUE);
1209
1210 /* Save the Default hive */
1211 dwError = RegSaveKeyExW(hUserKey,
1212 szDefaultUserHive,
1213 NULL,
1214 REG_STANDARD_FORMAT);
1215 if (dwError == ERROR_ALREADY_EXISTS)
1216 {
1217 WCHAR szBackupHive[MAX_PATH];
1218
1219 /* Build the backup hive file name by replacing the extension */
1220 wcscpy(szBackupHive, szDefaultUserHive);
1221 wcscpy(&szBackupHive[wcslen(szBackupHive) - 4], L".bak");
1222
1223 /* Back up the existing default user hive by renaming it, replacing any possible existing old backup */
1224 if (!MoveFileExW(szDefaultUserHive,
1225 szBackupHive,
1226 MOVEFILE_REPLACE_EXISTING))
1227 {
1228 dwError = GetLastError();
1229 DPRINT1("Failed to create a default-user hive backup '%S', MoveFileExW failed (Error %lu)\n",
1230 szBackupHive, dwError);
1231 }
1232 else
1233 {
1234 /* The backup has been done, retry saving the Default hive */
1235 dwError = RegSaveKeyExW(hUserKey,
1236 szDefaultUserHive,
1237 NULL,
1238 REG_STANDARD_FORMAT);
1239 }
1240 }
1241 if (dwError != ERROR_SUCCESS)
1242 {
1243 DPRINT1("RegSaveKeyExW() failed (Error %lu)\n", dwError);
1244 }
1245
1246 pSetupEnablePrivilege(L"SeBackupPrivilege", FALSE);
1247
1248 RegCloseKey(hUserKey);
1249
1250 return dwError;
1251 }
1252
1253
1254 static
1255 DWORD
1256 InstallReactOS(VOID)
1257 {
1258 WCHAR szBuffer[MAX_PATH];
1259 HANDLE token;
1260 TOKEN_PRIVILEGES privs;
1261 HKEY hKey;
1262 HINF hShortcutsInf;
1263 HANDLE hHotkeyThread;
1264 BOOL ret;
1265
1266 InitializeSetupActionLog(FALSE);
1267 LogItem(NULL, L"Installing ReactOS");
1268
1269 CreateTempDir(L"TEMP");
1270 CreateTempDir(L"TMP");
1271
1272 if (!InitializeProgramFilesDir())
1273 {
1274 FatalError("InitializeProgramFilesDir() failed");
1275 return 0;
1276 }
1277
1278 if (!InitializeProfiles())
1279 {
1280 FatalError("InitializeProfiles() failed");
1281 return 0;
1282 }
1283
1284 InitializeDefaultUserLocale();
1285
1286 if (GetWindowsDirectoryW(szBuffer, ARRAYSIZE(szBuffer)))
1287 {
1288 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
1289 L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion",
1290 0,
1291 KEY_WRITE,
1292 &hKey) == ERROR_SUCCESS)
1293 {
1294 RegSetValueExW(hKey,
1295 L"PathName",
1296 0,
1297 REG_SZ,
1298 (LPBYTE)szBuffer,
1299 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1300
1301 RegSetValueExW(hKey,
1302 L"SystemRoot",
1303 0,
1304 REG_SZ,
1305 (LPBYTE)szBuffer,
1306 (wcslen(szBuffer) + 1) * sizeof(WCHAR));
1307
1308 RegCloseKey(hKey);
1309 }
1310
1311 PathAddBackslash(szBuffer);
1312 wcscat(szBuffer, L"system");
1313 CreateDirectory(szBuffer, NULL);
1314 }
1315
1316 if (SaveDefaultUserHive() != ERROR_SUCCESS)
1317 {
1318 FatalError("SaveDefaultUserHive() failed");
1319 return 0;
1320 }
1321
1322 if (!CopySystemProfile(0))
1323 {
1324 FatalError("CopySystemProfile() failed");
1325 return 0;
1326 }
1327
1328 hHotkeyThread = CreateThread(NULL, 0, HotkeyThread, NULL, 0, NULL);
1329
1330 /* Hack: Install TCP/IP protocol driver */
1331 ret = InstallInfSection(NULL,
1332 L"nettcpip.inf",
1333 L"MS_TCPIP.PrimaryInstall",
1334 L"MS_TCPIP.PrimaryInstall.Services");
1335 if (!ret && GetLastError() != ERROR_FILE_NOT_FOUND)
1336 {
1337 DPRINT("InstallInfSection() failed with error 0x%lx\n", GetLastError());
1338 }
1339 else
1340 {
1341 /* Start the TCP/IP protocol driver */
1342 SetupStartService(L"Tcpip", FALSE);
1343 SetupStartService(L"Dhcp", FALSE);
1344 }
1345
1346
1347 if (!CommonInstall())
1348 return 0;
1349
1350 InstallWizard();
1351
1352 InstallSecurity();
1353
1354 SetAutoAdminLogon();
1355
1356 hShortcutsInf = SetupOpenInfFileW(L"shortcuts.inf",
1357 NULL,
1358 INF_STYLE_WIN4,
1359 NULL);
1360 if (hShortcutsInf == INVALID_HANDLE_VALUE)
1361 {
1362 FatalError("Failed to open shortcuts.inf");
1363 return 0;
1364 }
1365
1366 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders"))
1367 {
1368 FatalError("CreateShortcuts() failed");
1369 return 0;
1370 }
1371
1372 SetupCloseInfFile(hShortcutsInf);
1373
1374 hShortcutsInf = SetupOpenInfFileW(L"rosapps_shortcuts.inf",
1375 NULL,
1376 INF_STYLE_WIN4,
1377 NULL);
1378 if (hShortcutsInf != INVALID_HANDLE_VALUE)
1379 {
1380 if (!CreateShortcuts(hShortcutsInf, L"ShortcutFolders"))
1381 {
1382 FatalError("CreateShortcuts(rosapps) failed");
1383 return 0;
1384 }
1385 SetupCloseInfFile(hShortcutsInf);
1386 }
1387
1388 SetupCloseInfFile(hSysSetupInf);
1389 SetSetupType(0);
1390
1391 if (hHotkeyThread)
1392 {
1393 PostThreadMessage(GetThreadId(hHotkeyThread), WM_QUIT, 0, 0);
1394 CloseHandle(hHotkeyThread);
1395 }
1396
1397 LogItem(NULL, L"Installing ReactOS done");
1398 TerminateSetupActionLog();
1399
1400 if (AdminInfo.Name != NULL)
1401 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Name);
1402
1403 if (AdminInfo.Domain != NULL)
1404 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Domain);
1405
1406 if (AdminInfo.Password != NULL)
1407 RtlFreeHeap(RtlGetProcessHeap(), 0, AdminInfo.Password);
1408
1409 /* Get shutdown privilege */
1410 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &token))
1411 {
1412 FatalError("OpenProcessToken() failed!");
1413 return 0;
1414 }
1415 if (!LookupPrivilegeValue(NULL,
1416 SE_SHUTDOWN_NAME,
1417 &privs.Privileges[0].Luid))
1418 {
1419 FatalError("LookupPrivilegeValue() failed!");
1420 return 0;
1421 }
1422 privs.PrivilegeCount = 1;
1423 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
1424 if (AdjustTokenPrivileges(token,
1425 FALSE,
1426 &privs,
1427 0,
1428 (PTOKEN_PRIVILEGES)NULL,
1429 NULL) == 0)
1430 {
1431 FatalError("AdjustTokenPrivileges() failed!");
1432 return 0;
1433 }
1434
1435 ExitWindowsEx(EWX_REBOOT, 0);
1436 return 0;
1437 }
1438
1439
1440 /*
1441 * Standard Windows-compatible export, which dispatches
1442 * to either 'InstallReactOS' or 'InstallLiveCD'.
1443 */
1444 INT
1445 WINAPI
1446 InstallWindowsNt(INT argc, WCHAR** argv)
1447 {
1448 INT i;
1449 PWSTR p;
1450
1451 for (i = 0; i < argc; ++i)
1452 {
1453 p = argv[i];
1454 if (*p == L'-')
1455 {
1456 p++;
1457
1458 // NOTE: On Windows, "mini" means "minimal UI", and can be used
1459 // in addition to "newsetup"; these options are not exclusive.
1460 if (_wcsicmp(p, L"newsetup") == 0)
1461 return (INT)InstallReactOS();
1462 else if (_wcsicmp(p, L"mini") == 0)
1463 return (INT)InstallLiveCD();
1464
1465 /* Add support for other switches */
1466 }
1467 }
1468
1469 return 0;
1470 }
1471
1472
1473 /*
1474 * @unimplemented
1475 */
1476 DWORD WINAPI
1477 SetupChangeFontSize(
1478 IN HANDLE hWnd,
1479 IN LPCWSTR lpszFontSize)
1480 {
1481 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1482 return FALSE;
1483 }
1484
1485 /*
1486 * @unimplemented
1487 */
1488 DWORD WINAPI
1489 SetupChangeLocaleEx(HWND hWnd,
1490 LCID Lcid,
1491 LPCWSTR lpSrcRootPath,
1492 char Unknown,
1493 DWORD dwUnused1,
1494 DWORD dwUnused2)
1495 {
1496 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1497 return FALSE;
1498 }
1499
1500 /*
1501 * @implemented
1502 */
1503 DWORD WINAPI
1504 SetupChangeLocale(HWND hWnd, LCID Lcid)
1505 {
1506 return SetupChangeLocaleEx(hWnd, Lcid, NULL, 0, 0, 0);
1507 }
1508
1509
1510 DWORD
1511 WINAPI
1512 SetupStartService(
1513 LPCWSTR lpServiceName,
1514 BOOL bWait)
1515 {
1516 SC_HANDLE hManager = NULL;
1517 SC_HANDLE hService = NULL;
1518 DWORD dwError = ERROR_SUCCESS;
1519
1520 hManager = OpenSCManagerW(NULL,
1521 NULL,
1522 SC_MANAGER_ALL_ACCESS);
1523 if (hManager == NULL)
1524 {
1525 dwError = GetLastError();
1526 goto done;
1527 }
1528
1529 hService = OpenServiceW(hManager,
1530 lpServiceName,
1531 SERVICE_START);
1532 if (hService == NULL)
1533 {
1534 dwError = GetLastError();
1535 goto done;
1536 }
1537
1538 if (!StartService(hService, 0, NULL))
1539 {
1540 dwError = GetLastError();
1541 goto done;
1542 }
1543
1544 done:
1545 if (hService != NULL)
1546 CloseServiceHandle(hService);
1547
1548 if (hManager != NULL)
1549 CloseServiceHandle(hManager);
1550
1551 return dwError;
1552 }