2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: System setup
4 * FILE: dll/win32/syssetup/wizard.c
5 * PURPOSE: GUI controls
6 * PROGRAMMERS: Eric Kohl
7 * Pierre Schweitzer <heis_spiter@hotmail.com>
8 * Ismael Ferreras Morezuelas <swyterzone+ros@gmail.com>
11 /* INCLUDES *****************************************************************/
23 #define PM_REGISTRATION_NOTIFY (WM_APP + 1)
24 /* Private Message used to communicate progress from the background
25 registration thread to the main thread.
26 wParam = 0 Registration in progress
27 = 1 Registration completed
28 lParam = Pointer to a REGISTRATIONNOTIFY structure */
30 typedef struct _REGISTRATIONNOTIFY
36 } REGISTRATIONNOTIFY
, *PREGISTRATIONNOTIFY
;
38 typedef struct _REGISTRATIONDATA
44 } REGISTRATIONDATA
, *PREGISTRATIONDATA
;
47 /* FUNCTIONS ****************************************************************/
49 extern void WINAPI
Control_RunDLLW(HWND hWnd
, HINSTANCE hInst
, LPCWSTR cmd
, DWORD nCmdShow
);
52 GetRosInstallCD(WCHAR
*pwszPath
, DWORD cchPathMax
);
56 CenterWindow(HWND hWnd
)
62 hWndParent
= GetParent(hWnd
);
63 if (hWndParent
== NULL
)
64 hWndParent
= GetDesktopWindow();
66 GetWindowRect(hWndParent
, &rcParent
);
67 GetWindowRect(hWnd
, &rcWindow
);
71 ((rcParent
.right
- rcParent
.left
) - (rcWindow
.right
- rcWindow
.left
)) / 2,
72 ((rcParent
.bottom
- rcParent
.top
) - (rcWindow
.bottom
- rcWindow
.top
)) / 2,
82 LOGFONTW LogFont
= {0};
86 LogFont
.lfWeight
= FW_HEAVY
;
87 wcscpy(LogFont
.lfFaceName
, L
"MS Shell Dlg");
90 LogFont
.lfHeight
= -MulDiv(12, GetDeviceCaps(hdc
, LOGPIXELSY
), 72);
92 hFont
= CreateFontIndirectW(&LogFont
);
103 LOGFONTW tmpFont
= {0};
107 /* Grabs the Drawing Context */
110 tmpFont
.lfHeight
= -MulDiv(8, GetDeviceCaps(hDc
, LOGPIXELSY
), 72);
111 tmpFont
.lfWeight
= FW_HEAVY
;
112 wcscpy(tmpFont
.lfFaceName
, L
"MS Shell Dlg");
114 hBoldFont
= CreateFontIndirectW(&tmpFont
);
116 ReleaseDC(NULL
, hDc
);
121 static INT_PTR CALLBACK
122 GplDlgProc(HWND hwndDlg
,
127 HRSRC GplTextResource
;
137 GplTextResource
= FindResourceW(hDllInstance
, MAKEINTRESOURCE(IDR_GPL
), L
"RT_TEXT");
138 if (NULL
== GplTextResource
)
142 Size
= SizeofResource(hDllInstance
, GplTextResource
);
147 GplText
= HeapAlloc(GetProcessHeap(), 0, Size
+ 1);
152 GplTextMem
= LoadResource(hDllInstance
, GplTextResource
);
153 if (NULL
== GplTextMem
)
155 HeapFree(GetProcessHeap(), 0, GplText
);
158 GplTextLocked
= LockResource(GplTextMem
);
159 if (NULL
== GplTextLocked
)
161 HeapFree(GetProcessHeap(), 0, GplText
);
164 memcpy(GplText
, GplTextLocked
, Size
);
165 GplText
[Size
] = '\0';
166 SendMessageA(GetDlgItem(hwndDlg
, IDC_GPL_TEXT
), WM_SETTEXT
, 0, (LPARAM
) GplText
);
167 HeapFree(GetProcessHeap(), 0, GplText
);
168 SetFocus(GetDlgItem(hwndDlg
, IDOK
));
172 EndDialog(hwndDlg
, IDCANCEL
);
176 if (HIWORD(wParam
) == BN_CLICKED
&& IDOK
== LOWORD(wParam
))
178 EndDialog(hwndDlg
, IDOK
);
190 static INT_PTR CALLBACK
191 WelcomeDlgProc(HWND hwndDlg
,
196 PSETUPDATA pSetupData
;
198 pSetupData
= (PSETUPDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
207 /* Get pointer to the global setup data */
208 pSetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
209 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pSetupData
);
211 hwndControl
= GetParent(hwndDlg
);
213 /* Center the wizard window */
214 CenterWindow (hwndControl
);
216 /* Hide the system menu */
217 dwStyle
= GetWindowLongPtr(hwndControl
, GWL_STYLE
);
218 SetWindowLongPtr(hwndControl
, GWL_STYLE
, dwStyle
& ~WS_SYSMENU
);
220 /* Hide and disable the 'Cancel' button */
221 hwndControl
= GetDlgItem(GetParent(hwndDlg
), IDCANCEL
);
222 ShowWindow (hwndControl
, SW_HIDE
);
223 EnableWindow (hwndControl
, FALSE
);
226 SendDlgItemMessage(hwndDlg
,
229 (WPARAM
)pSetupData
->hTitleFont
,
237 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
242 LogItem(L
"BEGIN", L
"WelcomePage");
243 /* Enable the Next button */
244 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
);
245 if (pSetupData
->UnattendSetup
)
247 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, IDD_ACKPAGE
);
253 LogItem(L
"END", L
"WelcomePage");
257 pSetupData
->UnattendSetup
= FALSE
;
274 static INT_PTR CALLBACK
275 AckPageDlgProc(HWND hwndDlg
,
282 PWCHAR End
, CurrentProject
;
283 INT ProjectsSize
, ProjectsCount
;
284 PSETUPDATA pSetupData
;
286 pSetupData
= (PSETUPDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
292 pSetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
293 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pSetupData
);
299 Projects
= HeapAlloc(GetProcessHeap(), 0, ProjectsSize
* sizeof(WCHAR
));
300 if (NULL
== Projects
)
304 ProjectsCount
= LoadStringW(hDllInstance
, IDS_ACKPROJECTS
, Projects
, ProjectsSize
);
305 if (0 == ProjectsCount
)
307 HeapFree(GetProcessHeap(), 0, Projects
);
310 if (ProjectsCount
< ProjectsSize
- 1)
314 HeapFree(GetProcessHeap(), 0, Projects
);
318 CurrentProject
= Projects
;
319 while (L
'\0' != *CurrentProject
)
321 End
= wcschr(CurrentProject
, L
'\n');
326 (void)ListBox_AddString(GetDlgItem(hwndDlg
, IDC_PROJECTS
), CurrentProject
);
329 CurrentProject
= End
+ 1;
333 CurrentProject
+= wcslen(CurrentProject
);
336 HeapFree(GetProcessHeap(), 0, Projects
);
341 if (HIWORD(wParam
) == BN_CLICKED
&& IDC_VIEWGPL
== LOWORD(wParam
))
343 DialogBox(hDllInstance
, MAKEINTRESOURCE(IDD_GPL
), NULL
, GplDlgProc
);
344 SetForegroundWindow(GetParent(hwndDlg
));
350 lpnm
= (LPNMHDR
)lParam
;
355 /* Enable the Back and Next buttons */
356 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_NEXT
);
357 if (pSetupData
->UnattendSetup
)
359 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, IDD_LOCALEPAGE
);
365 pSetupData
->UnattendSetup
= FALSE
;
383 WriteOwnerSettings(WCHAR
* OwnerName
,
384 WCHAR
* OwnerOrganization
)
391 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
392 L
"Software\\Microsoft\\Windows NT\\CurrentVersion",
397 if (res
!= ERROR_SUCCESS
)
402 res
= RegSetValueExW(hKey
,
407 (wcslen(OwnerName
) + 1) * sizeof(WCHAR
));
409 if (res
!= ERROR_SUCCESS
)
415 res
= RegSetValueExW(hKey
,
416 L
"RegisteredOrganization",
419 (LPBYTE
)OwnerOrganization
,
420 (wcslen(OwnerOrganization
) + 1) * sizeof(WCHAR
));
423 return (res
== ERROR_SUCCESS
);
426 static INT_PTR CALLBACK
427 OwnerPageDlgProc(HWND hwndDlg
,
433 WCHAR OwnerOrganization
[51];
435 WCHAR ErrorName
[256];
437 PSETUPDATA pSetupData
;
439 pSetupData
= (PSETUPDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
445 pSetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
446 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pSetupData
);
448 /* set a localized ('Owner') placeholder string as default */
449 if (LoadStringW(hDllInstance
, IDS_MACHINE_OWNER_NAME
, OwnerName
, _countof(OwnerName
)))
451 SendDlgItemMessage(hwndDlg
, IDC_OWNERNAME
, WM_SETTEXT
, 0, (LPARAM
)OwnerName
);
454 SendDlgItemMessage(hwndDlg
, IDC_OWNERNAME
, EM_LIMITTEXT
, 50, 0);
455 SendDlgItemMessage(hwndDlg
, IDC_OWNERORGANIZATION
, EM_LIMITTEXT
, 50, 0);
457 /* Set focus to owner name */
458 SetFocus(GetDlgItem(hwndDlg
, IDC_OWNERNAME
));
460 /* Select the default text to quickly overwrite it by typing */
461 SendDlgItemMessage(hwndDlg
, IDC_OWNERNAME
, EM_SETSEL
, 0, -1);
468 lpnm
= (LPNMHDR
)lParam
;
473 /* Enable the Back and Next buttons */
474 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_NEXT
);
475 if (pSetupData
->UnattendSetup
)
477 SendMessage(GetDlgItem(hwndDlg
, IDC_OWNERNAME
), WM_SETTEXT
, 0, (LPARAM
)pSetupData
->OwnerName
);
478 SendMessage(GetDlgItem(hwndDlg
, IDC_OWNERORGANIZATION
), WM_SETTEXT
, 0, (LPARAM
)pSetupData
->OwnerOrganization
);
479 if (WriteOwnerSettings(pSetupData
->OwnerName
, pSetupData
->OwnerOrganization
))
481 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, IDD_COMPUTERPAGE
);
489 if (GetDlgItemTextW(hwndDlg
, IDC_OWNERNAME
, OwnerName
, 50) == 0)
491 if (0 == LoadStringW(hDllInstance
, IDS_REACTOS_SETUP
, Title
, sizeof(Title
) / sizeof(Title
[0])))
493 wcscpy(Title
, L
"ReactOS Setup");
495 if (0 == LoadStringW(hDllInstance
, IDS_WZD_NAME
, ErrorName
, sizeof(ErrorName
) / sizeof(ErrorName
[0])))
497 wcscpy(ErrorName
, L
"Setup cannot continue until you enter your name.");
499 MessageBoxW(hwndDlg
, ErrorName
, Title
, MB_ICONERROR
| MB_OK
);
501 SetFocus(GetDlgItem(hwndDlg
, IDC_OWNERNAME
));
502 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, -1);
507 OwnerOrganization
[0] = 0;
508 GetDlgItemTextW(hwndDlg
, IDC_OWNERORGANIZATION
, OwnerOrganization
, 50);
510 if (!WriteOwnerSettings(OwnerName
, OwnerOrganization
))
512 SetFocus(GetDlgItem(hwndDlg
, IDC_OWNERNAME
));
513 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, -1);
518 pSetupData
->UnattendSetup
= FALSE
;
536 WriteComputerSettings(WCHAR
* ComputerName
, HWND hwndDlg
)
539 WCHAR ErrorComputerName
[256];
541 if (!SetComputerNameW(ComputerName
))
545 if (0 == LoadStringW(hDllInstance
, IDS_REACTOS_SETUP
, Title
, sizeof(Title
) / sizeof(Title
[0])))
547 wcscpy(Title
, L
"ReactOS Setup");
549 if (0 == LoadStringW(hDllInstance
, IDS_WZD_SETCOMPUTERNAME
, ErrorComputerName
,
550 sizeof(ErrorComputerName
) / sizeof(ErrorComputerName
[0])))
552 wcscpy(ErrorComputerName
, L
"Setup failed to set the computer name.");
554 MessageBoxW(hwndDlg
, ErrorComputerName
, Title
, MB_ICONERROR
| MB_OK
);
560 /* Try to also set DNS hostname */
561 SetComputerNameExW(ComputerNamePhysicalDnsHostname
, ComputerName
);
563 /* Set the accounts domain name */
564 SetAccountsDomainSid(NULL
, ComputerName
);
572 WriteDefaultLogonData(LPWSTR Domain
)
574 WCHAR szAdministratorName
[256];
578 if (LoadStringW(hDllInstance
,
579 IDS_ADMINISTRATOR_NAME
,
581 sizeof(szAdministratorName
) / sizeof(WCHAR
)) == 0)
583 wcscpy(szAdministratorName
, L
"Administrator");
586 lError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
587 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon",
591 if (lError
!= ERROR_SUCCESS
)
594 lError
= RegSetValueEx(hKey
,
599 (wcslen(Domain
)+ 1) * sizeof(WCHAR
));
600 if (lError
!= ERROR_SUCCESS
)
602 DPRINT1("RegSetValueEx(\"DefaultDomain\") failed!\n");
605 lError
= RegSetValueEx(hKey
,
609 (LPBYTE
)szAdministratorName
,
610 (wcslen(szAdministratorName
)+ 1) * sizeof(WCHAR
));
611 if (lError
!= ERROR_SUCCESS
)
613 DPRINT1("RegSetValueEx(\"DefaultUserName\") failed!\n");
622 /* lpBuffer will be filled with a 15-char string (plus the null terminator) */
624 GenerateComputerName(LPWSTR lpBuffer
)
626 static const WCHAR Chars
[] = L
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
627 static const unsigned cChars
= sizeof(Chars
) / sizeof(WCHAR
) - 1;
630 wcscpy(lpBuffer
, L
"REACTOS-");
632 srand(GetTickCount());
634 /* fill in 7 characters */
635 for (i
= 8; i
< 15; i
++)
636 lpBuffer
[i
] = Chars
[rand() % cChars
];
638 lpBuffer
[15] = UNICODE_NULL
; /* NULL-terminate */
641 static INT_PTR CALLBACK
642 ComputerPageDlgProc(HWND hwndDlg
,
647 WCHAR ComputerName
[MAX_COMPUTERNAME_LENGTH
+ 1];
648 WCHAR Password1
[128];
649 WCHAR Password2
[128];
652 WCHAR EmptyComputerName
[256], NotMatchPassword
[256], WrongPassword
[256];
654 PSETUPDATA pSetupData
;
656 pSetupData
= (PSETUPDATA
)GetWindowLongPtr(hwndDlg
, DWLP_USER
);
658 if (0 == LoadStringW(hDllInstance
, IDS_REACTOS_SETUP
, Title
, sizeof(Title
) / sizeof(Title
[0])))
660 wcscpy(Title
, L
"ReactOS Setup");
666 pSetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
667 SetWindowLongPtr(hwndDlg
, DWLP_USER
, (LONG_PTR
)pSetupData
);
669 /* Generate a new pseudo-random computer name */
670 GenerateComputerName(ComputerName
);
672 /* Display current computer name */
673 SetDlgItemTextW(hwndDlg
, IDC_COMPUTERNAME
, ComputerName
);
675 /* Set text limits */
676 SendDlgItemMessage(hwndDlg
, IDC_COMPUTERNAME
, EM_LIMITTEXT
, MAX_COMPUTERNAME_LENGTH
, 0);
677 SendDlgItemMessage(hwndDlg
, IDC_ADMINPASSWORD1
, EM_LIMITTEXT
, 127, 0);
678 SendDlgItemMessage(hwndDlg
, IDC_ADMINPASSWORD2
, EM_LIMITTEXT
, 127, 0);
680 /* Set focus to computer name */
681 SetFocus(GetDlgItem(hwndDlg
, IDC_COMPUTERNAME
));
682 if (pSetupData
->UnattendSetup
)
684 SendMessage(GetDlgItem(hwndDlg
, IDC_COMPUTERNAME
), WM_SETTEXT
, 0, (LPARAM
)pSetupData
->ComputerName
);
685 SendMessage(GetDlgItem(hwndDlg
, IDC_ADMINPASSWORD1
), WM_SETTEXT
, 0, (LPARAM
)pSetupData
->AdminPassword
);
686 SendMessage(GetDlgItem(hwndDlg
, IDC_ADMINPASSWORD2
), WM_SETTEXT
, 0, (LPARAM
)pSetupData
->AdminPassword
);
687 WriteComputerSettings(pSetupData
->ComputerName
, NULL
);
688 SetAdministratorPassword(pSetupData
->AdminPassword
);
691 /* Store the administrator account name as the default user name */
692 WriteDefaultLogonData(pSetupData
->ComputerName
);
698 lpnm
= (LPNMHDR
)lParam
;
703 /* Enable the Back and Next buttons */
704 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_NEXT
);
705 if (pSetupData
->UnattendSetup
&& WriteComputerSettings(pSetupData
->ComputerName
, hwndDlg
))
707 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, IDD_DATETIMEPAGE
);
713 if (0 == GetDlgItemTextW(hwndDlg
, IDC_COMPUTERNAME
, ComputerName
, MAX_COMPUTERNAME_LENGTH
+ 1))
715 if (0 == LoadStringW(hDllInstance
, IDS_WZD_COMPUTERNAME
, EmptyComputerName
,
716 sizeof(EmptyComputerName
) / sizeof(EmptyComputerName
[0])))
718 wcscpy(EmptyComputerName
, L
"Setup cannot continue until you enter the name of your computer.");
720 MessageBoxW(hwndDlg
, EmptyComputerName
, Title
, MB_ICONERROR
| MB_OK
);
721 SetFocus(GetDlgItem(hwndDlg
, IDC_COMPUTERNAME
));
722 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, -1);
726 /* No need to check computer name for invalid characters,
727 * SetComputerName() will do it for us */
729 if (!WriteComputerSettings(ComputerName
, hwndDlg
))
731 SetFocus(GetDlgItem(hwndDlg
, IDC_COMPUTERNAME
));
732 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, -1);
737 /* Check if admin passwords have been entered */
738 if ((GetDlgItemText(hwndDlg
, IDC_ADMINPASSWORD1
, Password1
, 128) == 0) ||
739 (GetDlgItemText(hwndDlg
, IDC_ADMINPASSWORD2
, Password2
, 128) == 0))
741 if (0 == LoadStringW(hDllInstance
, IDS_WZD_PASSWORDEMPTY
, EmptyPassword
,
742 sizeof(EmptyPassword
) / sizeof(EmptyPassword
[0])))
744 wcscpy(EmptyPassword
, L
"You must enter a password !");
746 MessageBoxW(hwndDlg
, EmptyPassword
, Title
, MB_ICONERROR
| MB_OK
);
747 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, -1);
751 GetDlgItemTextW(hwndDlg
, IDC_ADMINPASSWORD1
, Password1
, 128);
752 GetDlgItemTextW(hwndDlg
, IDC_ADMINPASSWORD2
, Password2
, 128);
754 /* Check if passwords match */
755 if (wcscmp(Password1
, Password2
))
757 if (0 == LoadStringW(hDllInstance
, IDS_WZD_PASSWORDMATCH
, NotMatchPassword
,
758 sizeof(NotMatchPassword
) / sizeof(NotMatchPassword
[0])))
760 wcscpy(NotMatchPassword
, L
"The passwords you entered do not match. Please enter the desired password again.");
762 MessageBoxW(hwndDlg
, NotMatchPassword
, Title
, MB_ICONERROR
| MB_OK
);
763 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, -1);
767 /* Check password for invalid characters */
768 Password
= (PWCHAR
)Password1
;
771 if (!isprint(*Password
))
773 if (0 == LoadStringW(hDllInstance
, IDS_WZD_PASSWORDCHAR
, WrongPassword
,
774 sizeof(WrongPassword
) / sizeof(WrongPassword
[0])))
776 wcscpy(WrongPassword
, L
"The password you entered contains invalid characters. Please enter a cleaned password.");
778 MessageBoxW(hwndDlg
, WrongPassword
, Title
, MB_ICONERROR
| MB_OK
);
779 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, -1);
785 /* Set admin password */
786 SetAdministratorPassword(Password1
);
790 pSetupData
->UnattendSetup
= FALSE
;
808 SetKeyboardLayoutName(HWND hwnd
)
811 TCHAR szLayoutPath
[256];
812 TCHAR szLocaleName
[32];
816 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
817 _T("SYSTEM\\CurrentControlSet\\Control\\NLS\\Locale"),
823 dwValueSize
= 16 * sizeof(TCHAR
);
824 if (RegQueryValueEx(hKey
,
835 _tcscpy(szLayoutPath
,
836 _T("SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"));
837 _tcscat(szLayoutPath
,
840 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
847 dwValueSize
= 32 * sizeof(TCHAR
);
848 if (RegQueryValueEx(hKey
,
865 RunControlPanelApplet(HWND hwnd
, PCWSTR pwszCPLParameters
)
868 if (pwszCPLParameters
)
870 STARTUPINFOW StartupInfo
;
871 PROCESS_INFORMATION ProcessInformation
;
872 WCHAR CmdLine
[MAX_PATH
] = L
"rundll32.exe shell32.dll,Control_RunDLL ";
874 ZeroMemory(&StartupInfo
, sizeof(StartupInfo
));
875 StartupInfo
.cb
= sizeof(StartupInfo
);
877 ASSERT(_countof(CmdLine
) > wcslen(CmdLine
) + wcslen(pwszCPLParameters
));
878 wcscat(CmdLine
, pwszCPLParameters
);
880 if (!CreateProcessW(NULL
,
889 &ProcessInformation
))
891 MessageBoxW(hwnd
, L
"Error: Failed to launch the Control Panel Applet.", NULL
, MB_ICONERROR
);
895 while((MsgWaitForMultipleObjects(1, &ProcessInformation
.hProcess
, FALSE
, INFINITE
, QS_ALLINPUT
|QS_ALLPOSTMESSAGE
)) != WAIT_OBJECT_0
)
897 while(PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
899 TranslateMessage(&msg
);
900 DispatchMessageW(&msg
);
903 CloseHandle(ProcessInformation
.hThread
);
904 CloseHandle(ProcessInformation
.hProcess
);
909 MessageBoxW(hwnd
, L
"Error: Failed to launch the Control Panel Applet.", NULL
, MB_ICONERROR
);
915 WriteUserLocale(VOID
)
921 lcid
= GetSystemDefaultLCID();
923 if (GetLocaleInfoW(MAKELCID(lcid
, SORT_DEFAULT
), LOCALE_ILANGUAGE
, Locale
, sizeof(Locale
) / sizeof(Locale
[0])) != 0)
925 if (RegCreateKeyExW(HKEY_CURRENT_USER
, L
"Control Panel\\International",
926 0, NULL
, REG_OPTION_NON_VOLATILE
,
927 KEY_WRITE
, NULL
, &hKey
, NULL
) == ERROR_SUCCESS
)
929 RegSetValueExW(hKey
, L
"Locale", 0, REG_SZ
, (LPBYTE
)Locale
, (wcslen(Locale
) + 1) * sizeof(WCHAR
));
935 static INT_PTR CALLBACK
936 LocalePageDlgProc(HWND hwndDlg
,
941 PSETUPDATA SetupData
;
943 /* Retrieve pointer to the global setup data */
944 SetupData
= (PSETUPDATA
)GetWindowLongPtr (hwndDlg
, GWL_USERDATA
);
950 /* Save pointer to the global setup data */
951 SetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
952 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)SetupData
);
955 SetKeyboardLayoutName(GetDlgItem(hwndDlg
, IDC_LAYOUTTEXT
));
960 if (HIWORD(wParam
) == BN_CLICKED
)
962 switch (LOWORD(wParam
))
964 case IDC_CUSTOMLOCALE
:
965 RunControlPanelApplet(hwndDlg
, L
"intl.cpl,,5");
966 /* FIXME: Update input locale name */
969 case IDC_CUSTOMLAYOUT
:
970 RunControlPanelApplet(hwndDlg
, L
"input.dll,@1");
978 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
983 /* Enable the Back and Next buttons */
984 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_NEXT
);
985 if (SetupData
->UnattendSetup
)
987 WCHAR wszPath
[MAX_PATH
];
988 if (GetRosInstallCD(wszPath
, _countof(wszPath
)))
990 WCHAR wszParams
[1024];
991 swprintf(wszParams
, L
"intl.cpl,,/f:\"%sreactos\\unattend.inf\"", wszPath
);
992 RunControlPanelApplet(hwndDlg
, wszParams
);
996 RunControlPanelApplet(hwndDlg
, L
"intl.cpl,,/f:\"unattend.inf\"");
999 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, IDD_OWNERPAGE
);
1008 SetupData
->UnattendSetup
= FALSE
;
1025 static PTIMEZONE_ENTRY
1026 GetLargerTimeZoneEntry(PSETUPDATA SetupData
, DWORD Index
)
1028 PTIMEZONE_ENTRY Entry
;
1030 Entry
= SetupData
->TimeZoneListHead
;
1031 while (Entry
!= NULL
)
1033 if (Entry
->Index
>= Index
)
1036 Entry
= Entry
->Next
;
1044 CreateTimeZoneList(PSETUPDATA SetupData
)
1046 WCHAR szKeyName
[256];
1054 PTIMEZONE_ENTRY Entry
;
1055 PTIMEZONE_ENTRY Current
;
1057 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1058 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
1067 dwNameSize
= 256 * sizeof(WCHAR
);
1068 lError
= RegEnumKeyExW(hZonesKey
,
1076 if (lError
!= ERROR_SUCCESS
&& lError
!= ERROR_MORE_DATA
)
1079 if (RegOpenKeyExW(hZonesKey
,
1086 Entry
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(TIMEZONE_ENTRY
));
1089 RegCloseKey(hZoneKey
);
1093 dwValueSize
= 64 * sizeof(WCHAR
);
1094 if (RegQueryValueExW(hZoneKey
,
1098 (LPBYTE
)&Entry
->Description
,
1101 RegCloseKey(hZoneKey
);
1105 dwValueSize
= 32 * sizeof(WCHAR
);
1106 if (RegQueryValueExW(hZoneKey
,
1110 (LPBYTE
)&Entry
->StandardName
,
1113 RegCloseKey(hZoneKey
);
1117 dwValueSize
= 32 * sizeof(WCHAR
);
1118 if (RegQueryValueExW(hZoneKey
,
1122 (LPBYTE
)&Entry
->DaylightName
,
1125 RegCloseKey(hZoneKey
);
1129 dwValueSize
= sizeof(DWORD
);
1130 if (RegQueryValueExW(hZoneKey
,
1134 (LPBYTE
)&Entry
->Index
,
1137 RegCloseKey(hZoneKey
);
1141 dwValueSize
= sizeof(TZ_INFO
);
1142 if (RegQueryValueExW(hZoneKey
,
1146 (LPBYTE
)&Entry
->TimezoneInfo
,
1149 RegCloseKey(hZoneKey
);
1153 RegCloseKey(hZoneKey
);
1155 if (SetupData
->TimeZoneListHead
== NULL
&&
1156 SetupData
->TimeZoneListTail
== NULL
)
1160 SetupData
->TimeZoneListHead
= Entry
;
1161 SetupData
->TimeZoneListTail
= Entry
;
1165 Current
= GetLargerTimeZoneEntry(SetupData
, Entry
->Index
);
1166 if (Current
!= NULL
)
1168 if (Current
== SetupData
->TimeZoneListHead
)
1170 /* Prepend to head */
1172 Entry
->Next
= SetupData
->TimeZoneListHead
;
1173 SetupData
->TimeZoneListHead
->Prev
= Entry
;
1174 SetupData
->TimeZoneListHead
= Entry
;
1178 /* Insert before current */
1179 Entry
->Prev
= Current
->Prev
;
1180 Entry
->Next
= Current
;
1181 Current
->Prev
->Next
= Entry
;
1182 Current
->Prev
= Entry
;
1187 /* Append to tail */
1188 Entry
->Prev
= SetupData
->TimeZoneListTail
;
1190 SetupData
->TimeZoneListTail
->Next
= Entry
;
1191 SetupData
->TimeZoneListTail
= Entry
;
1198 RegCloseKey(hZonesKey
);
1203 DestroyTimeZoneList(PSETUPDATA SetupData
)
1205 PTIMEZONE_ENTRY Entry
;
1207 while (SetupData
->TimeZoneListHead
!= NULL
)
1209 Entry
= SetupData
->TimeZoneListHead
;
1211 SetupData
->TimeZoneListHead
= Entry
->Next
;
1212 if (SetupData
->TimeZoneListHead
!= NULL
)
1214 SetupData
->TimeZoneListHead
->Prev
= NULL
;
1217 HeapFree(GetProcessHeap(), 0, Entry
);
1220 SetupData
->TimeZoneListTail
= NULL
;
1224 GetTimeZoneListIndex(LPDWORD lpIndex
)
1226 WCHAR szLanguageIdString
[9];
1233 BOOL bFound
= FALSE
;
1234 unsigned long iLanguageID
;
1238 *lpIndex
= 85; /* fallback to GMT time zone */
1240 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1241 L
"SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
1247 dwValueSize
= 9 * sizeof(WCHAR
);
1248 if (RegQueryValueExW(hKey
,
1252 (LPBYTE
)szLanguageIdString
,
1259 iLanguageID
= wcstoul(szLanguageIdString
, NULL
, 16);
1264 iLanguageID
= *lpIndex
;
1267 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1268 L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
1275 if (RegQueryValueExW(hKey
,
1286 Buffer
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwValueSize
);
1293 if (RegQueryValueExW(hKey
,
1300 HeapFree(GetProcessHeap(), 0, Buffer
);
1310 Length
= wcslen(Ptr
);
1311 if (wcstoul(Ptr
, NULL
, 16) == iLanguageID
)
1314 Ptr
= Ptr
+ Length
+ 1;
1320 *lpIndex
= wcstoul(Ptr
, &End
, 10);
1321 HeapFree(GetProcessHeap(), 0, Buffer
);
1325 Length
= wcslen(Ptr
);
1326 Ptr
= Ptr
+ Length
+ 1;
1329 HeapFree(GetProcessHeap(), 0, Buffer
);
1336 ShowTimeZoneList(HWND hwnd
, PSETUPDATA SetupData
, DWORD dwEntryIndex
)
1338 PTIMEZONE_ENTRY Entry
;
1342 GetTimeZoneListIndex(&dwEntryIndex
);
1344 Entry
= SetupData
->TimeZoneListHead
;
1345 while (Entry
!= NULL
)
1347 dwCount
= SendMessage(hwnd
,
1350 (LPARAM
)Entry
->Description
);
1352 if (dwEntryIndex
!= 0 && dwEntryIndex
== Entry
->Index
)
1355 Entry
= Entry
->Next
;
1366 SetLocalTimeZone(HWND hwnd
, PSETUPDATA SetupData
)
1368 TIME_ZONE_INFORMATION TimeZoneInformation
;
1369 PTIMEZONE_ENTRY Entry
;
1373 dwIndex
= SendMessage(hwnd
,
1379 Entry
= SetupData
->TimeZoneListHead
;
1386 Entry
= Entry
->Next
;
1389 wcscpy(TimeZoneInformation
.StandardName
,
1390 Entry
->StandardName
);
1391 wcscpy(TimeZoneInformation
.DaylightName
,
1392 Entry
->DaylightName
);
1394 TimeZoneInformation
.Bias
= Entry
->TimezoneInfo
.Bias
;
1395 TimeZoneInformation
.StandardBias
= Entry
->TimezoneInfo
.StandardBias
;
1396 TimeZoneInformation
.DaylightBias
= Entry
->TimezoneInfo
.DaylightBias
;
1398 memcpy(&TimeZoneInformation
.StandardDate
,
1399 &Entry
->TimezoneInfo
.StandardDate
,
1400 sizeof(SYSTEMTIME
));
1401 memcpy(&TimeZoneInformation
.DaylightDate
,
1402 &Entry
->TimezoneInfo
.DaylightDate
,
1403 sizeof(SYSTEMTIME
));
1405 /* Set time zone information */
1406 SetTimeZoneInformation(&TimeZoneInformation
);
1411 GetLocalSystemTime(HWND hwnd
, PSETUPDATA SetupData
)
1416 if (DateTime_GetSystemtime(GetDlgItem(hwnd
, IDC_DATEPICKER
), &Date
) != GDT_VALID
)
1421 if (DateTime_GetSystemtime(GetDlgItem(hwnd
, IDC_TIMEPICKER
), &Time
) != GDT_VALID
)
1426 SetupData
->SystemTime
.wYear
= Date
.wYear
;
1427 SetupData
->SystemTime
.wMonth
= Date
.wMonth
;
1428 SetupData
->SystemTime
.wDayOfWeek
= Date
.wDayOfWeek
;
1429 SetupData
->SystemTime
.wDay
= Date
.wDay
;
1430 SetupData
->SystemTime
.wHour
= Time
.wHour
;
1431 SetupData
->SystemTime
.wMinute
= Time
.wMinute
;
1432 SetupData
->SystemTime
.wSecond
= Time
.wSecond
;
1433 SetupData
->SystemTime
.wMilliseconds
= Time
.wMilliseconds
;
1440 SetAutoDaylightInfo(HWND hwnd
)
1445 if (SendMessage(hwnd
, BM_GETCHECK
, 0, 0) == BST_UNCHECKED
)
1447 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1448 L
"SYSTEM\\CurrentControlSet\\Control\\TimeZoneInformation",
1454 RegSetValueExW(hKey
,
1455 L
"DisableAutoDaylightTimeSet",
1466 SetSystemLocalTime(HWND hwnd
, PSETUPDATA SetupData
)
1471 * Call SetLocalTime twice to ensure correct results
1473 Ret
= SetLocalTime(&SetupData
->SystemTime
) &&
1474 SetLocalTime(&SetupData
->SystemTime
);
1481 UpdateLocalSystemTime(HWND hwnd
)
1483 SYSTEMTIME LocalTime
;
1485 GetLocalTime(&LocalTime
);
1486 DateTime_SetSystemtime(GetDlgItem(hwnd
, IDC_DATEPICKER
), GDT_VALID
, &LocalTime
);
1487 DateTime_SetSystemtime(GetDlgItem(hwnd
, IDC_TIMEPICKER
), GDT_VALID
, &LocalTime
);
1492 WriteDateTimeSettings(HWND hwndDlg
, PSETUPDATA SetupData
)
1495 WCHAR ErrorLocalTime
[256];
1497 GetLocalSystemTime(hwndDlg
, SetupData
);
1498 SetLocalTimeZone(GetDlgItem(hwndDlg
, IDC_TIMEZONELIST
),
1501 SetAutoDaylightInfo(GetDlgItem(hwndDlg
, IDC_AUTODAYLIGHT
));
1502 if(!SetSystemLocalTime(hwndDlg
, SetupData
))
1504 if (0 == LoadStringW(hDllInstance
, IDS_REACTOS_SETUP
, Title
, sizeof(Title
) / sizeof(Title
[0])))
1506 wcscpy(Title
, L
"ReactOS Setup");
1508 if (0 == LoadStringW(hDllInstance
, IDS_WZD_LOCALTIME
, ErrorLocalTime
,
1509 sizeof(ErrorLocalTime
) / sizeof(ErrorLocalTime
[0])))
1511 wcscpy(ErrorLocalTime
, L
"Setup was unable to set the local time.");
1513 MessageBoxW(hwndDlg
, ErrorLocalTime
, Title
, MB_ICONWARNING
| MB_OK
);
1521 static INT_PTR CALLBACK
1522 DateTimePageDlgProc(HWND hwndDlg
,
1527 PSETUPDATA SetupData
;
1529 /* Retrieve pointer to the global setup data */
1530 SetupData
= (PSETUPDATA
)GetWindowLongPtr (hwndDlg
, GWL_USERDATA
);
1535 /* Save pointer to the global setup data */
1536 SetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1537 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)SetupData
);
1539 CreateTimeZoneList(SetupData
);
1541 if (SetupData
->UnattendSetup
)
1543 ShowTimeZoneList(GetDlgItem(hwndDlg
, IDC_TIMEZONELIST
),
1544 SetupData
, SetupData
->TimeZoneIndex
);
1546 if (!SetupData
->DisableAutoDaylightTimeSet
)
1548 SendDlgItemMessage(hwndDlg
, IDC_AUTODAYLIGHT
, BM_SETCHECK
, (WPARAM
)BST_CHECKED
, 0);
1553 ShowTimeZoneList(GetDlgItem(hwndDlg
, IDC_TIMEZONELIST
),
1556 SendDlgItemMessage(hwndDlg
, IDC_AUTODAYLIGHT
, BM_SETCHECK
, (WPARAM
)BST_CHECKED
, 0);
1561 UpdateLocalSystemTime(hwndDlg
);
1565 switch (((LPNMHDR
)lParam
)->code
)
1568 /* Enable the Back and Next buttons */
1569 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_BACK
| PSWIZB_NEXT
);
1570 if (SetupData
->UnattendSetup
&& WriteDateTimeSettings(hwndDlg
, SetupData
))
1572 SetWindowLongPtr(hwndDlg
, DWL_MSGRESULT
, SetupData
->uFirstNetworkWizardPage
);
1575 SetTimer(hwndDlg
, 1, 1000, NULL
);
1578 case PSN_KILLACTIVE
:
1579 case DTN_DATETIMECHANGE
:
1580 KillTimer(hwndDlg
, 1);
1584 WriteDateTimeSettings(hwndDlg
, SetupData
);
1588 SetupData
->UnattendSetup
= FALSE
;
1597 DestroyTimeZoneList(SetupData
);
1608 static UINT CALLBACK
1609 RegistrationNotificationProc(PVOID Context
,
1614 PREGISTRATIONDATA RegistrationData
;
1615 REGISTRATIONNOTIFY RegistrationNotify
;
1616 PSP_REGISTER_CONTROL_STATUSW StatusInfo
;
1618 WCHAR ErrorMessage
[128];
1620 RegistrationData
= (PREGISTRATIONDATA
) Context
;
1622 if (SPFILENOTIFY_STARTREGISTRATION
== Notification
||
1623 SPFILENOTIFY_ENDREGISTRATION
== Notification
)
1625 StatusInfo
= (PSP_REGISTER_CONTROL_STATUSW
) Param1
;
1626 RegistrationNotify
.CurrentItem
= wcsrchr(StatusInfo
->FileName
, L
'\\');
1627 if (NULL
== RegistrationNotify
.CurrentItem
)
1629 RegistrationNotify
.CurrentItem
= StatusInfo
->FileName
;
1633 RegistrationNotify
.CurrentItem
++;
1636 if (SPFILENOTIFY_STARTREGISTRATION
== Notification
)
1638 DPRINT("Received SPFILENOTIFY_STARTREGISTRATION notification for %S\n",
1639 StatusInfo
->FileName
);
1640 RegistrationNotify
.ErrorMessage
= NULL
;
1641 RegistrationNotify
.Progress
= RegistrationData
->Registered
;
1645 DPRINT("Received SPFILENOTIFY_ENDREGISTRATION notification for %S\n",
1646 StatusInfo
->FileName
);
1647 DPRINT("Win32Error %u FailureCode %u\n", StatusInfo
->Win32Error
,
1648 StatusInfo
->FailureCode
);
1649 if (SPREG_SUCCESS
!= StatusInfo
->FailureCode
)
1651 switch(StatusInfo
->FailureCode
)
1653 case SPREG_LOADLIBRARY
:
1654 MessageID
= IDS_LOADLIBRARY_FAILED
;
1656 case SPREG_GETPROCADDR
:
1657 MessageID
= IDS_GETPROCADDR_FAILED
;
1660 MessageID
= IDS_REGSVR_FAILED
;
1662 case SPREG_DLLINSTALL
:
1663 MessageID
= IDS_DLLINSTALL_FAILED
;
1666 MessageID
= IDS_TIMEOUT
;
1669 MessageID
= IDS_REASON_UNKNOWN
;
1672 if (0 == LoadStringW(hDllInstance
, MessageID
,
1674 sizeof(ErrorMessage
) /
1675 sizeof(ErrorMessage
[0])))
1677 ErrorMessage
[0] = L
'\0';
1679 if (SPREG_TIMEOUT
!= StatusInfo
->FailureCode
)
1681 FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
,
1682 StatusInfo
->Win32Error
, 0,
1683 ErrorMessage
+ wcslen(ErrorMessage
),
1684 sizeof(ErrorMessage
) / sizeof(ErrorMessage
[0]) -
1685 wcslen(ErrorMessage
), NULL
);
1687 RegistrationNotify
.ErrorMessage
= ErrorMessage
;
1691 RegistrationNotify
.ErrorMessage
= NULL
;
1693 if (RegistrationData
->Registered
< RegistrationData
->DllCount
)
1695 RegistrationData
->Registered
++;
1699 RegistrationNotify
.Progress
= RegistrationData
->Registered
;
1700 RegistrationNotify
.ActivityID
= IDS_REGISTERING_COMPONENTS
;
1701 SendMessage(RegistrationData
->hwndDlg
, PM_REGISTRATION_NOTIFY
,
1702 0, (LPARAM
) &RegistrationNotify
);
1708 DPRINT1("Received unexpected notification %u\n", Notification
);
1709 return SetupDefaultQueueCallback(RegistrationData
->DefaultContext
,
1710 Notification
, Param1
, Param2
);
1715 static DWORD CALLBACK
1716 RegistrationProc(LPVOID Parameter
)
1718 PREGISTRATIONDATA RegistrationData
;
1719 REGISTRATIONNOTIFY RegistrationNotify
;
1720 DWORD LastError
= NO_ERROR
;
1721 WCHAR UnknownError
[84];
1723 RegistrationData
= (PREGISTRATIONDATA
) Parameter
;
1724 RegistrationData
->Registered
= 0;
1725 RegistrationData
->DefaultContext
= SetupInitDefaultQueueCallback(RegistrationData
->hwndDlg
);
1729 if (!SetupInstallFromInfSectionW(GetParent(RegistrationData
->hwndDlg
),
1731 L
"RegistrationPhase2",
1733 SPINST_REGISTERCALLBACKAWARE
|
1738 RegistrationNotificationProc
,
1743 LastError
= GetLastError();
1746 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1748 DPRINT("Catching exception\n");
1749 LastError
= RtlNtStatusToDosError(_SEH2_GetExceptionCode());
1753 if (NO_ERROR
== LastError
)
1755 RegistrationNotify
.ErrorMessage
= NULL
;
1759 DPRINT1("SetupInstallFromInfSection failed with error %u\n",
1761 if (0 == FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
|
1762 FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, LastError
, 0,
1763 (LPWSTR
) &RegistrationNotify
.ErrorMessage
, 0,
1766 if (0 == LoadStringW(hDllInstance
, IDS_UNKNOWN_ERROR
,
1768 sizeof(UnknownError
) / sizeof(UnknownError
[0]) -
1771 wcscpy(UnknownError
, L
"Unknown error");
1773 wcscat(UnknownError
, L
" ");
1774 _ultow(LastError
, UnknownError
+ wcslen(UnknownError
), 10);
1775 RegistrationNotify
.ErrorMessage
= UnknownError
;
1779 RegistrationNotify
.Progress
= RegistrationData
->DllCount
;
1780 RegistrationNotify
.ActivityID
= IDS_REGISTERING_COMPONENTS
;
1781 RegistrationNotify
.CurrentItem
= NULL
;
1782 SendMessage(RegistrationData
->hwndDlg
, PM_REGISTRATION_NOTIFY
,
1783 1, (LPARAM
) &RegistrationNotify
);
1784 if (NULL
!= RegistrationNotify
.ErrorMessage
&&
1785 UnknownError
!= RegistrationNotify
.ErrorMessage
)
1787 LocalFree((PVOID
) RegistrationNotify
.ErrorMessage
);
1790 SetupTermDefaultQueueCallback(RegistrationData
->DefaultContext
);
1791 HeapFree(GetProcessHeap(), 0, RegistrationData
);
1793 RegisterTypeLibraries(hSysSetupInf
, L
"TypeLibraries");
1795 // FIXME: Move this call to a separate cleanup page!
1796 RtlCreateBootStatusDataFile();
1803 StartComponentRegistration(HWND hwndDlg
, PULONG MaxProgress
)
1805 HANDLE RegistrationThread
;
1808 WCHAR SectionName
[512];
1809 PREGISTRATIONDATA RegistrationData
;
1812 if (! SetupFindFirstLineW(hSysSetupInf
, L
"RegistrationPhase2",
1813 L
"RegisterDlls", &Context
))
1815 DPRINT1("No RegistrationPhase2 section found\n");
1818 if (! SetupGetStringFieldW(&Context
, 1, SectionName
,
1819 sizeof(SectionName
) / sizeof(SectionName
[0]),
1822 DPRINT1("Unable to retrieve section name\n");
1825 DllCount
= SetupGetLineCountW(hSysSetupInf
, SectionName
);
1826 DPRINT("SectionName %S DllCount %ld\n", SectionName
, DllCount
);
1829 SetLastError(STATUS_NOT_FOUND
);
1833 *MaxProgress
= (ULONG
) DllCount
;
1836 * Create a background thread to do the actual registrations, so the
1837 * main thread can just run its message loop.
1839 RegistrationThread
= NULL
;
1840 RegistrationData
= HeapAlloc(GetProcessHeap(), 0,
1841 sizeof(REGISTRATIONDATA
));
1842 if (RegistrationData
!= NULL
)
1844 RegistrationData
->hwndDlg
= hwndDlg
;
1845 RegistrationData
->DllCount
= DllCount
;
1846 RegistrationThread
= CreateThread(NULL
, 0, RegistrationProc
,
1847 RegistrationData
, 0, NULL
);
1848 if (RegistrationThread
!= NULL
)
1850 CloseHandle(RegistrationThread
);
1854 DPRINT1("CreateThread failed, error %u\n", GetLastError());
1855 HeapFree(GetProcessHeap(), 0, RegistrationData
);
1861 DPRINT1("HeapAlloc() failed, error %u\n", GetLastError());
1869 static INT_PTR CALLBACK
1870 ProcessPageDlgProc(HWND hwndDlg
,
1875 PSETUPDATA SetupData
;
1876 PREGISTRATIONNOTIFY RegistrationNotify
;
1877 static UINT oldActivityID
= -1;
1880 /* Retrieve pointer to the global setup data */
1881 SetupData
= (PSETUPDATA
)GetWindowLongPtr (hwndDlg
, GWL_USERDATA
);
1887 /* Save pointer to the global setup data */
1888 SetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
1889 SetWindowLongPtr(hwndDlg
, GWL_USERDATA
, (DWORD_PTR
)SetupData
);
1895 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
1896 ULONG MaxProgress
= 0;
1901 /* Disable the Back and Next buttons */
1902 PropSheet_SetWizButtons(GetParent(hwndDlg
), 0);
1904 StartComponentRegistration(hwndDlg
, &MaxProgress
);
1906 SendDlgItemMessage(hwndDlg
, IDC_PROCESSPROGRESS
, PBM_SETRANGE
,
1907 0, MAKELPARAM(0, MaxProgress
));
1908 SendDlgItemMessage(hwndDlg
, IDC_PROCESSPROGRESS
, PBM_SETPOS
,
1916 SetupData
->UnattendSetup
= FALSE
;
1925 case PM_REGISTRATION_NOTIFY
:
1928 RegistrationNotify
= (PREGISTRATIONNOTIFY
) lParam
;
1929 // update if necessary only
1930 if (oldActivityID
!= RegistrationNotify
->ActivityID
)
1932 if (0 != LoadStringW(hDllInstance
, RegistrationNotify
->ActivityID
,
1934 sizeof(Activity
) / sizeof(Activity
[0])))
1936 SendDlgItemMessageW(hwndDlg
, IDC_ACTIVITY
, WM_SETTEXT
,
1937 0, (LPARAM
) Activity
);
1939 oldActivityID
= RegistrationNotify
->ActivityID
;
1941 SendDlgItemMessageW(hwndDlg
, IDC_ITEM
, WM_SETTEXT
, 0,
1942 (LPARAM
)(NULL
== RegistrationNotify
->CurrentItem
?
1943 L
"" : RegistrationNotify
->CurrentItem
));
1944 SendDlgItemMessage(hwndDlg
, IDC_PROCESSPROGRESS
, PBM_SETPOS
,
1945 RegistrationNotify
->Progress
, 0);
1946 if (NULL
!= RegistrationNotify
->ErrorMessage
)
1948 if (0 == LoadStringW(hDllInstance
, IDS_REACTOS_SETUP
,
1949 Title
, sizeof(Title
) / sizeof(Title
[0])))
1951 wcscpy(Title
, L
"ReactOS Setup");
1953 MessageBoxW(hwndDlg
, RegistrationNotify
->ErrorMessage
,
1954 Title
, MB_ICONERROR
| MB_OK
);
1960 /* Enable the Back and Next buttons */
1961 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_NEXT
);
1962 PropSheet_PressButton(GetParent(hwndDlg
), PSBTN_NEXT
);
1976 SetInstallationCompleted(VOID
)
1979 DWORD InProgress
= 0;
1982 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE
,
1986 &hKey
) == ERROR_SUCCESS
)
1988 RegSetValueExW( hKey
, L
"SystemSetupInProgress", 0, REG_DWORD
, (LPBYTE
)&InProgress
, sizeof(InProgress
) );
1989 RegCloseKey( hKey
);
1992 if (RegOpenKeyExW( HKEY_LOCAL_MACHINE
,
1993 L
"Software\\Microsoft\\Windows NT\\CurrentVersion",
1996 &hKey
) == ERROR_SUCCESS
)
1998 InstallDate
= (DWORD
)time(NULL
);
1999 RegSetValueExW( hKey
, L
"InstallDate", 0, REG_DWORD
, (LPBYTE
)&InstallDate
, sizeof(InstallDate
) );
2000 RegCloseKey( hKey
);
2004 static INT_PTR CALLBACK
2005 FinishDlgProc(HWND hwndDlg
,
2015 /* Get pointer to the global setup data */
2016 PSETUPDATA SetupData
= (PSETUPDATA
)((LPPROPSHEETPAGE
)lParam
)->lParam
;
2018 if (!SetupData
->UnattendSetup
|| !SetupData
->DisableGeckoInst
)
2020 /* Run the Wine Gecko prompt */
2021 Control_RunDLLW(hwndDlg
, 0, L
"appwiz.cpl install_gecko", SW_SHOW
);
2024 /* Set title font */
2025 SendDlgItemMessage(hwndDlg
,
2028 (WPARAM
)SetupData
->hTitleFont
,
2030 if (SetupData
->UnattendSetup
)
2032 KillTimer(hwndDlg
, 1);
2033 SetInstallationCompleted();
2041 SetInstallationCompleted();
2051 hWndProgress
= GetDlgItem(hwndDlg
, IDC_RESTART_PROGRESS
);
2052 Position
= SendMessage(hWndProgress
, PBM_GETPOS
, 0, 0);
2053 if (Position
== 300)
2055 KillTimer(hwndDlg
, 1);
2056 PropSheet_PressButton(GetParent(hwndDlg
), PSBTN_FINISH
);
2060 SendMessage(hWndProgress
, PBM_SETPOS
, Position
+ 1, 0);
2067 LPNMHDR lpnm
= (LPNMHDR
)lParam
;
2072 /* Enable the correct buttons on for the active page */
2073 PropSheet_SetWizButtons(GetParent(hwndDlg
), PSWIZB_FINISH
);
2075 SendDlgItemMessage(hwndDlg
, IDC_RESTART_PROGRESS
, PBM_SETRANGE
, 0,
2076 MAKELPARAM(0, 300));
2077 SendDlgItemMessage(hwndDlg
, IDC_RESTART_PROGRESS
, PBM_SETPOS
, 0, 0);
2078 SetTimer(hwndDlg
, 1, 50, NULL
);
2082 DestroyWindow(GetParent(hwndDlg
));
2101 PSETUPDATA pSetupData
)
2103 INFCONTEXT InfContext
;
2105 WCHAR szValue
[MAX_PATH
];
2109 if (!SetupFindFirstLineW(pSetupData
->hUnattendedInf
,
2111 L
"UnattendSetupEnabled",
2114 DPRINT1("Error: Cant find UnattendSetupEnabled Key! %d\n", GetLastError());
2118 if (!SetupGetStringFieldW(&InfContext
,
2121 sizeof(szValue
) / sizeof(WCHAR
),
2124 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2128 if (wcscmp(szValue
, L
"yes") != 0)
2130 DPRINT("Unattend setup was disabled by UnattendSetupEnabled key.\n");
2134 pSetupData
->UnattendSetup
= TRUE
;
2136 if (!SetupFindFirstLineW(pSetupData
->hUnattendedInf
,
2141 DPRINT1("Error: SetupFindFirstLine failed %d\n", GetLastError());
2147 if (!SetupGetStringFieldW(&InfContext
,
2150 sizeof(szName
) / sizeof(WCHAR
),
2153 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2157 if (!SetupGetStringFieldW(&InfContext
,
2160 sizeof(szValue
) / sizeof(WCHAR
),
2163 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2166 DPRINT1("Name %S Value %S\n", szName
, szValue
);
2167 if (!wcscmp(szName
, L
"FullName"))
2169 if ((sizeof(pSetupData
->OwnerName
) / sizeof(TCHAR
)) > LineLength
)
2171 wcscpy(pSetupData
->OwnerName
, szValue
);
2174 else if (!wcscmp(szName
, L
"OrgName"))
2176 if ((sizeof(pSetupData
->OwnerOrganization
) / sizeof(WCHAR
)) > LineLength
)
2178 wcscpy(pSetupData
->OwnerOrganization
, szValue
);
2181 else if (!wcscmp(szName
, L
"ComputerName"))
2183 if ((sizeof(pSetupData
->ComputerName
) / sizeof(WCHAR
)) > LineLength
)
2185 wcscpy(pSetupData
->ComputerName
, szValue
);
2188 else if (!wcscmp(szName
, L
"AdminPassword"))
2190 if ((sizeof(pSetupData
->AdminPassword
) / sizeof(WCHAR
)) > LineLength
)
2192 wcscpy(pSetupData
->AdminPassword
, szValue
);
2195 else if (!wcscmp(szName
, L
"TimeZoneIndex"))
2197 pSetupData
->TimeZoneIndex
= _wtoi(szValue
);
2199 else if (!wcscmp(szName
, L
"DisableAutoDaylightTimeSet"))
2201 pSetupData
->DisableAutoDaylightTimeSet
= _wtoi(szValue
);
2203 else if (!wcscmp(szName
, L
"DisableGeckoInst"))
2205 if(!wcscmp(szValue
, L
"yes"))
2206 pSetupData
->DisableGeckoInst
= 1;
2208 pSetupData
->DisableGeckoInst
= 0;
2212 while (SetupFindNextLine(&InfContext
, &InfContext
));
2214 if (SetupFindFirstLineW(pSetupData
->hUnattendedInf
,
2219 DEVMODEW dm
= { { 0 } };
2220 dm
.dmSize
= sizeof(dm
);
2221 if (EnumDisplaySettingsW(NULL
, ENUM_CURRENT_SETTINGS
, &dm
))
2226 if (!SetupGetStringFieldW(&InfContext
,
2229 sizeof(szName
) / sizeof(WCHAR
),
2232 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2236 if (!SetupGetStringFieldW(&InfContext
,
2239 sizeof(szValue
) / sizeof(WCHAR
),
2242 DPRINT1("Error: SetupGetStringField failed with %d\n", GetLastError());
2245 iValue
= _wtoi(szValue
);
2246 DPRINT1("Name %S Value %i\n", szName
, iValue
);
2251 if (!wcscmp(szName
, L
"BitsPerPel"))
2253 dm
.dmFields
|= DM_BITSPERPEL
;
2254 dm
.dmBitsPerPel
= iValue
;
2256 else if (!wcscmp(szName
, L
"XResolution"))
2258 dm
.dmFields
|= DM_PELSWIDTH
;
2259 dm
.dmPelsWidth
= iValue
;
2261 else if (!wcscmp(szName
, L
"YResolution"))
2263 dm
.dmFields
|= DM_PELSHEIGHT
;
2264 dm
.dmPelsHeight
= iValue
;
2266 else if (!wcscmp(szName
, L
"VRefresh"))
2268 dm
.dmFields
|= DM_DISPLAYFREQUENCY
;
2269 dm
.dmDisplayFrequency
= iValue
;
2272 while (SetupFindNextLine(&InfContext
, &InfContext
));
2274 ChangeDisplaySettingsW(&dm
, CDS_UPDATEREGISTRY
);
2278 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2279 L
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\RunOnce",
2282 &hKey
) != ERROR_SUCCESS
)
2284 DPRINT1("Error: failed to open HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\RunOnce\n");
2288 if (SetupFindFirstLineW(pSetupData
->hUnattendedInf
,
2297 if(SetupGetStringFieldW(&InfContext
,
2300 sizeof(szValue
) / sizeof(WCHAR
),
2303 WCHAR szPath
[MAX_PATH
];
2304 swprintf(szName
, L
"%d", i
);
2305 DPRINT("szName %S szValue %S\n", szName
, szValue
);
2307 if (ExpandEnvironmentStringsW(szValue
, szPath
, MAX_PATH
))
2309 DPRINT("value %S\n", szPath
);
2310 if (RegSetValueExW(hKey
,
2314 (const BYTE
*)szPath
,
2315 (wcslen(szPath
) + 1) * sizeof(WCHAR
)) == ERROR_SUCCESS
)
2321 } while(SetupFindNextLine(&InfContext
, &InfContext
));
2328 * GetRosInstallCD should find the path to ros installation medium
2330 * If there are more than one CDDrive in it containing a ReactOS
2331 * installation cd, then it will pick the first one regardless if
2332 * it is really the installation cd
2334 * The best way to implement this is to set the key
2335 * HKLM\Software\Microsoft\Windows NT\CurrentVersion\SourcePath (REG_SZ)
2339 GetRosInstallCD(WCHAR
*pwszPath
, DWORD cchPathMax
)
2341 WCHAR wszDrives
[512];
2345 cchDrives
= GetLogicalDriveStringsW(_countof(wszDrives
) - 1, wszDrives
);
2346 if (cchDrives
== 0 || cchDrives
>= _countof(wszDrives
))
2348 /* buffer too small or failure */
2349 LogItem(NULL
, L
"GetLogicalDriveStringsW failed");
2353 for (pwszDrive
= wszDrives
; pwszDrive
[0]; pwszDrive
+= wcslen(pwszDrive
) + 1)
2355 if (GetDriveTypeW(pwszDrive
) == DRIVE_CDROM
)
2357 WCHAR wszBuf
[MAX_PATH
];
2358 wsprintf(wszBuf
, L
"%sreactos\\system32\\ntoskrnl.exe", pwszDrive
);
2359 LogItem(NULL
, wszBuf
);
2360 if (GetFileAttributesW(wszBuf
) != INVALID_FILE_ATTRIBUTES
)
2362 /* the file exists, so this is the right drive */
2363 wcsncpy(pwszPath
, pwszDrive
, cchPathMax
);
2364 OutputDebugStringW(L
"GetRosInstallCD: ");OutputDebugStringW(pwszPath
);OutputDebugStringW(L
"\n");
2374 ProcessUnattendSetup(
2375 PSETUPDATA pSetupData
)
2377 WCHAR szPath
[MAX_PATH
];
2380 if (!GetRosInstallCD(szPath
, MAX_PATH
))
2382 /* no cd drive found */
2386 dwLength
= wcslen(szPath
);
2387 if (dwLength
+ 21 > MAX_PATH
)
2390 * allocate bigger buffer
2395 wcscat(szPath
, L
"reactos\\unattend.inf");
2397 pSetupData
->hUnattendedInf
= SetupOpenInfFileW(szPath
,
2401 if (pSetupData
->hUnattendedInf
!= INVALID_HANDLE_VALUE
)
2403 ProcessUnattendInf(pSetupData
);
2407 typedef DWORD(WINAPI
*PFNREQUESTWIZARDPAGES
)(PDWORD
, HPROPSHEETPAGE
*, PSETUPDATA
);
2412 PROPSHEETHEADER psh
;
2413 HPROPSHEETPAGE
*phpage
= NULL
;
2414 PROPSHEETPAGE psp
= {0};
2418 PSETUPDATA pSetupData
= NULL
;
2419 HMODULE hNetShell
= NULL
;
2420 PFNREQUESTWIZARDPAGES pfn
= NULL
;
2421 DWORD dwPageCount
= 8, dwNetworkPageCount
= 0;
2423 LogItem(L
"BEGIN_SECTION", L
"InstallWizard");
2425 /* Allocate setup data */
2426 pSetupData
= HeapAlloc(GetProcessHeap(),
2429 if (pSetupData
== NULL
)
2431 LogItem(NULL
, L
"SetupData allocation failed!");
2433 L
"Setup failed to allocate global data!",
2435 MB_ICONERROR
| MB_OK
);
2439 hNetShell
= LoadLibraryW(L
"netshell.dll");
2440 if (hNetShell
!= NULL
)
2442 DPRINT("Netshell.dll loaded!\n");
2444 pfn
= (PFNREQUESTWIZARDPAGES
)GetProcAddress(hNetShell
,
2445 "NetSetupRequestWizardPages");
2448 pfn(&dwNetworkPageCount
, NULL
, NULL
);
2449 dwPageCount
+= dwNetworkPageCount
;
2453 DPRINT("PageCount: %lu\n", dwPageCount
);
2455 phpage
= HeapAlloc(GetProcessHeap(),
2457 dwPageCount
* sizeof(HPROPSHEETPAGE
));
2460 LogItem(NULL
, L
"Page array allocation failed!");
2462 L
"Setup failed to allocate page array!",
2464 MB_ICONERROR
| MB_OK
);
2468 pSetupData
->hUnattendedInf
= INVALID_HANDLE_VALUE
;
2469 ProcessUnattendSetup(pSetupData
);
2471 /* Create the Welcome page */
2472 psp
.dwSize
= sizeof(PROPSHEETPAGE
);
2473 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
2474 psp
.hInstance
= hDllInstance
;
2475 psp
.lParam
= (LPARAM
)pSetupData
;
2476 psp
.pfnDlgProc
= WelcomeDlgProc
;
2477 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_WELCOMEPAGE
);
2478 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2480 /* Create the Acknowledgements page */
2481 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
2482 psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_ACKTITLE
);
2483 psp
.pszHeaderSubTitle
= MAKEINTRESOURCE(IDS_ACKSUBTITLE
);
2484 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_ACKPAGE
);
2485 psp
.pfnDlgProc
= AckPageDlgProc
;
2486 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2488 /* Create the Locale page */
2489 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
2490 psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_LOCALETITLE
);
2491 psp
.pszHeaderSubTitle
= MAKEINTRESOURCE(IDS_LOCALESUBTITLE
);
2492 psp
.pfnDlgProc
= LocalePageDlgProc
;
2493 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_LOCALEPAGE
);
2494 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2497 /* Create the Owner page */
2498 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
2499 psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_OWNERTITLE
);
2500 psp
.pszHeaderSubTitle
= MAKEINTRESOURCE(IDS_OWNERSUBTITLE
);
2501 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_OWNERPAGE
);
2502 psp
.pfnDlgProc
= OwnerPageDlgProc
;
2503 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2505 /* Create the Computer page */
2506 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
2507 psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_COMPUTERTITLE
);
2508 psp
.pszHeaderSubTitle
= MAKEINTRESOURCE(IDS_COMPUTERSUBTITLE
);
2509 psp
.pfnDlgProc
= ComputerPageDlgProc
;
2510 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_COMPUTERPAGE
);
2511 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2514 /* Create the DateTime page */
2515 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
2516 psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_DATETIMETITLE
);
2517 psp
.pszHeaderSubTitle
= MAKEINTRESOURCE(IDS_DATETIMESUBTITLE
);
2518 psp
.pfnDlgProc
= DateTimePageDlgProc
;
2519 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_DATETIMEPAGE
);
2520 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2523 pSetupData
->uFirstNetworkWizardPage
= IDD_PROCESSPAGE
;
2524 pSetupData
->uPostNetworkWizardPage
= IDD_PROCESSPAGE
;
2528 pfn(&dwNetworkPageCount
, &phpage
[nPages
], pSetupData
);
2529 nPages
+= dwNetworkPageCount
;
2532 /* Create the Process page */
2533 psp
.dwFlags
= PSP_DEFAULT
| PSP_USEHEADERTITLE
| PSP_USEHEADERSUBTITLE
;
2534 psp
.pszHeaderTitle
= MAKEINTRESOURCE(IDS_PROCESSTITLE
);
2535 psp
.pszHeaderSubTitle
= MAKEINTRESOURCE(IDS_PROCESSSUBTITLE
);
2536 psp
.pfnDlgProc
= ProcessPageDlgProc
;
2537 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_PROCESSPAGE
);
2538 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2541 /* Create the Finish page */
2542 psp
.dwFlags
= PSP_DEFAULT
| PSP_HIDEHEADER
;
2543 psp
.pfnDlgProc
= FinishDlgProc
;
2544 psp
.pszTemplate
= MAKEINTRESOURCE(IDD_FINISHPAGE
);
2545 phpage
[nPages
++] = CreatePropertySheetPage(&psp
);
2547 /* Create the property sheet */
2548 psh
.dwSize
= sizeof(PROPSHEETHEADER
);
2549 psh
.dwFlags
= PSH_WIZARD97
| PSH_WATERMARK
| PSH_HEADER
| PSH_MODELESS
;
2550 psh
.hInstance
= hDllInstance
;
2551 psh
.hwndParent
= NULL
;
2552 psh
.nPages
= nPages
;
2554 psh
.phpage
= phpage
;
2555 psh
.pszbmWatermark
= MAKEINTRESOURCE(IDB_WATERMARK
);
2556 psh
.pszbmHeader
= MAKEINTRESOURCE(IDB_HEADER
);
2558 /* Create title font */
2559 pSetupData
->hTitleFont
= CreateTitleFont();
2560 pSetupData
->hBoldFont
= CreateBoldFont();
2562 /* Display the wizard */
2563 hWnd
= (HWND
)PropertySheet(&psh
);
2564 ShowWindow(hWnd
, SW_SHOW
);
2566 while (GetMessage(&msg
, NULL
, 0, 0))
2568 if (!IsDialogMessage(hWnd
, &msg
))
2570 TranslateMessage(&msg
);
2571 DispatchMessage(&msg
);
2575 if (pSetupData
->hUnattendedInf
!= INVALID_HANDLE_VALUE
)
2576 SetupCloseInfFile(pSetupData
->hUnattendedInf
);
2580 HeapFree(GetProcessHeap(), 0, phpage
);
2582 if (hNetShell
!= NULL
)
2583 FreeLibrary(hNetShell
);
2585 if (pSetupData
!= NULL
)
2587 DeleteObject(pSetupData
->hBoldFont
);
2588 DeleteObject(pSetupData
->hTitleFont
);
2589 HeapFree(GetProcessHeap(), 0, pSetupData
);
2592 LogItem(L
"END_SECTION", L
"InstallWizard");