// SoftEther VPN Source Code - Stable Edition Repository // Cedar Communication Module // // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0. // // Copyright (c) Daiyuu Nobori. // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan. // Copyright (c) SoftEther Corporation. // Copyright (c) all contributors on SoftEther VPN project in GitHub. // // All Rights Reserved. // // http://www.softether.org/ // // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project. // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN // // License: The Apache License, Version 2.0 // https://www.apache.org/licenses/LICENSE-2.0 // // DISCLAIMER // ========== // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH, // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS, // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS. // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE // LAW OR COURT RULE. // // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A // STATEMENT FOR WARNING AND DISCLAIMER. // // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE. // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE. // // // SOURCE CODE CONTRIBUTION // ------------------------ // // Your contribution to SoftEther VPN Project is much appreciated. // Please send patches to us through GitHub. // Read the SoftEther VPN Patch Acceptance Policy in advance: // http://www.softether.org/5-download/src/9.patch // // // DEAR SECURITY EXPERTS // --------------------- // // If you find a bug or a security vulnerability please kindly inform us // about the problem immediately so that we can fix the security problem // to protect a lot of users around the world as soon as possible. // // Our e-mail address for security reports is: // softether-vpn-security [at] softether.org // // Please note that the above e-mail address is not a technical support // inquiry address. If you need technical assistance, please visit // http://www.softether.org/ and ask your question on the users forum. // // Thank you for your cooperation. // // // NO MEMORY OR RESOURCE LEAKS // --------------------------- // // The memory-leaks and resource-leaks verification under the stress // test has been passed before release this source code. // SW.c // Setup Wizard for Win32 #include #ifdef WIN32 #define SM_C #define CM_C #define NM_C #define SW_C #define _WIN32_WINNT 0x0502 #define WINVER 0x0502 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "CMInner.h" #include "SMInner.h" #include "NMInner.h" #include "EMInner.h" #include "SWInner.h" #include "../PenCore/resource.h" //// Old MSI product information // VPN Server static SW_OLD_MSI old_msi_vpnserver[] = { {"{B5B58F8A-D56C-4f3e-B400-235A6E007101}", "{1BDA6B01-2DB3-478c-AA5B-E973A7DC49A4}"}, {"{124DDAE2-B9AF-4541-B3EF-B169D9007101}", "{BCDE5CF2-7413-47d0-92E1-F6F2189D8E60}"}, }; static SW_OLD_MSI old_msi_vpnclient[] = { {"{54864EDD-4FC6-4269-AA17-3E7C13607101}", "{13ED64E0-532D-4ff0-A3A0-5D700C73259E}"}, {"{8A215EB7-C5F2-4193-9D7D-1017F1007101}", "{AD593FE5-759E-46c6-9355-29031A8C7D44}"}, }; static SW_OLD_MSI old_msi_vpnbridge[] = { {"{58CE8E96-1234-499D-CAFE-3E62261DF211}", "{211FA6A7-1234-4985-CAFE-3DD3E3151E7E}"}, }; // List of file names needed to SFX static char *sfx_vpn_server_bridge_files[] = { "vpnsetup.exe", "vpnsetup_x64.exe", "vpnserver.exe", "vpnserver_x64.exe", "vpnbridge.exe", "vpnbridge_x64.exe", "vpnsmgr.exe", "vpnsmgr_x64.exe", "vpncmd.exe", "vpncmd_x64.exe", "hamcore.se2", }; static char *sfx_vpn_client_files[] = { "vpnsetup.exe", "vpnsetup_x64.exe", "vpnclient.exe", "vpnclient_x64.exe", "vpncmgr.exe", "vpncmgr_x64.exe", "vpncmd.exe", "vpncmd_x64.exe", "vpninstall.exe", "vpnweb.cab", "hamcore.se2", }; // Global variables to be used out of necessity static bool g_stop_flag = false; static HANDLE g_wait_process_handle = NULL; // SFX generation main bool SwGenSfxModeMain(char *mode, wchar_t *dst) { LIST *o; bool ret = false; // Validate arguments if (mode == NULL || dst == NULL) { return false; } o = SwNewSfxFileList(); if (SwAddBasicFilesToList(o, mode)) { if (SwCompileSfx(o, dst)) { ret = true; } } SwFreeSfxFileList(o); return ret; } // Compile the SFX files bool SwCompileSfx(LIST *o, wchar_t *dst_filename) { bool ret = false; wchar_t exe_filename[MAX_PATH]; HINSTANCE hKernel32 = LoadLibraryA("kernel32.dll"); HANDLE (WINAPI *_BeginUpdateResourceW)(LPCWSTR, BOOL) = NULL; BOOL (WINAPI *_UpdateResourceA)(HANDLE, LPCSTR, LPCSTR, WORD, LPVOID, DWORD) = NULL; BOOL (WINAPI *_EndUpdateResourceW)(HANDLE, BOOL) = NULL; // Validate arguments if (o == NULL || dst_filename == NULL || hKernel32 == NULL) { return false; } // Get the API related to the resource editing _BeginUpdateResourceW = (HANDLE (__stdcall *)(LPCWSTR,UINT))GetProcAddress(hKernel32, "BeginUpdateResourceW"); _UpdateResourceA = (UINT (__stdcall *)(HANDLE,LPCSTR,LPCSTR,WORD,LPVOID,DWORD))GetProcAddress(hKernel32, "UpdateResourceA"); _EndUpdateResourceW = (UINT (__stdcall *)(HANDLE,UINT))GetProcAddress(hKernel32, "EndUpdateResourceW"); if (_BeginUpdateResourceW != NULL && _UpdateResourceA != NULL && _EndUpdateResourceW != NULL) { // Generate the setup.exe file in the Temp directory ConbinePathW(exe_filename, sizeof(exe_filename), MsGetMyTempDirW(), L"setup.exe"); if (FileCopyW(L"|vpnsetup_nosign.exe", exe_filename)) { // Resource updating start HANDLE h = _BeginUpdateResourceW(exe_filename, false); if (h != NULL) { UINT i; bool ok = true; for (i = 0;i < LIST_NUM(o);i++) { SW_SFX_FILE *f = LIST_DATA(o, i); BUF *b; // Read the original file b = ReadDumpW(f->DiskFileName); if (b != NULL) { // Add resources char inner_name[MAX_PATH]; BUF *b2; StrCpy(inner_name, sizeof(inner_name), f->InnerFileName); StrUpper(inner_name); if (StrCmpi(inner_name, "hamcore.se2") == 0) { // Not to re-compress the hamcore.se2 because they are already compressed // Prepend "raw_" to file name Format(inner_name, sizeof(inner_name), "raw_%s", f->InnerFileName); StrUpper(inner_name); } else { // Compress b2 = CompressBuf(b); FreeBuf(b); b = b2; } if (_UpdateResourceA(h, SW_SFX_RESOURCE_TYPE, inner_name, MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), b->Buf, b->Size) == false) { ok = false; } FreeBuf(b); } if (ok == false) { break; } } if (ok) { // Success to add all resources if (_EndUpdateResourceW(h, false)) { h = NULL; // File Copy if (FileCopyW(exe_filename, dst_filename)) { // All succeed ret = true; } } } if (ret == false) { // Failed to add resource if (h != NULL) { _EndUpdateResourceW(h, true); h = NULL; } } FileDeleteW(exe_filename); } } } FreeLibrary(hKernel32); return ret; } // Create new item in the SFX compression list SW_SFX_FILE *SwNewSfxFile(char *inner_file_name, wchar_t *disk_file_name) { SW_SFX_FILE *f = ZeroMalloc(sizeof(SW_SFX_FILE)); StrCpy(f->InnerFileName, sizeof(f->InnerFileName), inner_file_name); UniStrCpy(f->DiskFileName, sizeof(f->DiskFileName), disk_file_name); return f; } // Add the basically required files for the components to SFX compressed files list bool SwAddBasicFilesToList(LIST *o, char *component_name) { UINT i; // Validate arguments if (o == NULL || component_name == NULL) { return false; } if (StrCmpi(component_name, "vpnserver_vpnbridge") == 0) { // VPN Server & VPN Bridge for (i = 0; i < (sizeof(sfx_vpn_server_bridge_files) / sizeof(char *)); i++) { char *name = sfx_vpn_server_bridge_files[i]; wchar_t name_w[MAX_PATH]; wchar_t src_file_name[MAX_PATH]; StrToUni(name_w, sizeof(name_w), name); ConbinePathW(src_file_name, sizeof(src_file_name), MsGetExeFileDirW(), name_w); Add(o, SwNewSfxFile(name, src_file_name)); } } else if (StrCmpi(component_name, "vpnclient") == 0) { // VPN Client for (i = 0; i < (sizeof(sfx_vpn_client_files) / sizeof(char *)); i++) { char *name = sfx_vpn_client_files[i]; wchar_t name_w[MAX_PATH]; wchar_t src_file_name[MAX_PATH]; StrToUni(name_w, sizeof(name_w), name); ConbinePathW(src_file_name, sizeof(src_file_name), MsGetExeFileDirW(), name_w); Add(o, SwNewSfxFile(name, src_file_name)); } } else { return false; } Add(o, SwNewSfxFile("install_src.dat", L"|install_src.dat")); return true; } // Release the SFX file list void SwFreeSfxFileList(LIST *o) { UINT i; // Validate arguments if (o == NULL) { return; } for (i = 0;i < LIST_NUM(o);i++) { SW_SFX_FILE *f = LIST_DATA(o, i); Free(f); } ReleaseList(o); } // Generate the SFX file list LIST *SwNewSfxFileList() { LIST *o = NewListFast(NULL); return o; } // Extract from the SFX files bool SwSfxExtractFile(HWND hWnd, void *data, UINT size, wchar_t *dst, bool compressed) { IO *io; bool ret = false; // Validate arguments if (data == NULL || size == 0 || dst == NULL) { return false; } io = FileCreateW(dst); if (compressed == false) { // Write uncompressed files as is ret = FileWrite(io, data, size); } else { // Unzip when the files are compressed BUF *src = NewBuf(); BUF *dst; WriteBuf(src, data, size); dst = UncompressBuf(src); FreeBuf(src); ret = FileWrite(io, dst->Buf, dst->Size); FreeBuf(dst); } FileClose(io); if (ret == false) { FileDeleteW(dst); } return ret; } // SFX extraction process bool SwSfxExtractProcess(HWND hWnd, bool *hide_error_msg) { TOKEN_LIST *t; UINT i; bool ret = true; wchar_t exec_filename[MAX_SIZE]; bool is_easy_installer = false; bool dummy_bool = false; if (hide_error_msg == NULL) { hide_error_msg = &dummy_bool; } *hide_error_msg = false; Zero(exec_filename, sizeof(exec_filename)); // Enumerate the DATAFILE resources t = MsEnumResources(NULL, SW_SFX_RESOURCE_TYPE); for (i = 0;i < t->NumTokens;i++) { char *resource_name = t->Token[i]; char filename[MAX_PATH]; wchar_t filename_w[MAX_PATH]; wchar_t tmp_filename[MAX_PATH]; HRSRC hr; bool ok = false; bool is_compressed = true; DoEvents(hWnd); if (g_stop_flag) { // User cancel ret = false; break; } StrCpy(filename, sizeof(filename), resource_name); StrLower(filename); if (EndWith(filename, ".vpn")) { is_easy_installer = true; } if (StartWith(filename, "raw_")) { StrToUni(filename_w, sizeof(filename_w), filename + 4); is_compressed = false; } else { StrToUni(filename_w, sizeof(filename_w), filename); } ConbinePathW(tmp_filename, sizeof(tmp_filename), MsGetMyTempDirW(), filename_w); if (EndWith(filename, "vpnsetup.exe")) { UniStrCpy(exec_filename, sizeof(exec_filename), tmp_filename); } // Find the resources hr = FindResourceA(MsGetCurrentModuleHandle(), resource_name, SW_SFX_RESOURCE_TYPE); if (hr != NULL) { HGLOBAL hg = LoadResource(MsGetCurrentModuleHandle(), hr); if (hg != NULL) { UINT size = SizeofResource(MsGetCurrentModuleHandle(), hr); void *ptr = LockResource(hg); if (size != 0 && ptr != NULL) { if (SwSfxExtractFile(hWnd, ptr, size, tmp_filename, is_compressed)) { ok = true; } } } } DoEvents(hWnd); if (ok == false) { // Failure ret = false; break; } } FreeToken(t); if (ret) { wchar_t exe_name[MAX_PATH]; wchar_t *exe_dir = MsGetExeFileDirW(); GetFileNameFromFilePathW(exe_name, sizeof(exe_name), MsGetExeFileNameW()); } if (ret) { // Start the vpnsetup.exe if (UniIsEmptyStr(exec_filename)) { ret = false; } else { void *handle = NULL; wchar_t params[MAX_SIZE]; wchar_t *current_params = GetCommandLineUniStr(); wchar_t tmp[MAX_SIZE]; char *last_lang; wchar_t copy_of_me[MAX_PATH]; UniStrCpy(params, sizeof(params), current_params); // Copy itself to the Temp directory CombinePathW(copy_of_me, sizeof(copy_of_me), MsGetMyTempDirW(), L"installer.cache"); if (FileCopyW(MsGetExeFileNameW(), copy_of_me) == false) { Zero(copy_of_me, sizeof(copy_of_me)); } // Add a path of this own UniFormat(tmp, sizeof(tmp), L" /CALLERSFXPATH:\"%s\"", copy_of_me); UniStrCat(params, sizeof(params), tmp); // Add information of whether it's a simple installer UniFormat(tmp, sizeof(tmp), L" /ISEASYINSTALLER:%u", is_easy_installer); UniStrCat(params, sizeof(params), tmp); UniTrim(params); // Specify a language by the lang.config last_lang = MsRegReadStrEx2(REG_CURRENT_USER, SW_REG_KEY, "Last User Language", false, true); if (IsEmptyStr(last_lang) == false) { wchar_t lang_filename[MAX_PATH]; BUF *buf; CombinePathW(lang_filename, sizeof(lang_filename), MsGetMyTempDirW(), L"lang.config"); buf = NewBuf(); WriteBufLine(buf, ""); WriteBufLine(buf, last_lang); WriteBufLine(buf, ""); DumpBufW(buf, lang_filename); FreeBuf(buf); } Free(last_lang); if (MsExecuteEx2W(exec_filename, params, &handle, false) == false) { ret = false; } else { g_wait_process_handle = handle; } } } return ret; } // Copy the files of VPN Gate bool SwSfxCopyVgFiles(HWND hWnd, wchar_t *src, wchar_t *dst) { wchar_t *msg; wchar_t srcfilename[MAX_PATH]; wchar_t exefilename[MAX_PATH]; GetFileNameFromFilePathW(srcfilename, sizeof(srcfilename), src); GetFileNameFromFilePathW(exefilename, sizeof(exefilename), MsGetExeFileNameW()); if (FileCopyW(src, dst)) { return true; } msg = L"The file \"%s\" was not found on the directory which the installer \"%s\" is located on.\r\n\r\n" L"To continue the installation, the file \"%s\" is required on the same direcotry.\r\n" L"If you have extracted the installer from a ZIP archive, you have to also extract the file \"%s\" from the ZIP archive together."; MsgBoxEx(hWnd, MB_ICONINFORMATION, msg, srcfilename, exefilename, srcfilename, srcfilename); return false; } // SFX extraction dialog procedure bool CALLBACK SfxModeMainDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { UINT ret; bool hide_msg = false; switch (msg) { case WM_INITDIALOG: SetTimer(hWnd, 1, 500, NULL); break; case WM_TIMER: switch (wParam) { case 1: KillTimer(hWnd, 1); ret = SW_EXIT_CODE_USER_CANCEL; if (SwSfxExtractProcess(hWnd, &hide_msg)) { ret = 0; } else { if (g_stop_flag == false) { if (hide_msg == false) { MsgBoxEx(hWnd, MB_ICONSTOP, L"Fatal Error: Self extracting files to the temporary directory was failed.\r\n\r\n" L"Please try again after reboot Windows."); } } } EndDialog(hWnd, ret); break; } break; case WM_COMMAND: switch (wParam) { case IDOK: case IDCANCEL: g_stop_flag = true; Disable(hWnd, IDCANCEL); break; } break; case WM_CLOSE: break; } return false; } // Main process as SFX mode UINT SwSfxModeMain() { UINT ret; // Select either English or Japanese UINT dialog_id = (MsIsCurrentUserLocaleIdJapanese() ? 10001 : 10002); g_wait_process_handle = NULL; g_stop_flag = false; // Show the screen ret = (UINT)DialogBoxParamA(MsGetCurrentModuleHandle(), MAKEINTRESOURCEA(dialog_id), NULL, (DLGPROC)SfxModeMainDialogProc, 0); if (g_wait_process_handle != NULL) { // If this have started the vpnsetup.exe, wait for termination of the child process ret = MsWaitProcessExit(g_wait_process_handle); } return ret; } // Resource name enumeration procedure bool CALLBACK SwEnumResourceNamesProc(HMODULE hModule, const char *type, char *name, LONG_PTR lParam) { bool *b = (bool *)lParam; // Validate arguments if (type == NULL || name == NULL || lParam == 0) { return false; } *b = true; return true; } // Main process of vpnsetup.exe UINT SWExec() { UINT ret = 0; bool is_datafile_exists = false; // Examine whether DATAFILE resources are stored in setup.exe that is currently running EnumResourceNamesA(NULL, SW_SFX_RESOURCE_TYPE, SwEnumResourceNamesProc, (LONG_PTR)(&is_datafile_exists)); if (is_datafile_exists) { // If DATAFILE resources are stored, extract it as SFX MayaquaMinimalMode(); } InitMayaqua(false, false, 0, NULL); InitCedar(); if (is_datafile_exists == false) { // Start the Setup Wizard ret = SWExecMain(); } else { // SFX mode ret = SwSfxModeMain(); } FreeCedar(); FreeMayaqua(); return ret; } // Dialog procedure (for copy and paste) UINT SwDefaultDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, true, true, false); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: break; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Update the file specification dialog void SwWeb2Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page) { bool ok = true; // Validate arguments if (hWnd == NULL || sw == NULL || wizard_page == NULL || wizard == NULL) { return; } if (IsEmptyUniStr(sw->Web_OutFile) || IsEmptyUniStr(sw->Web_SettingFile)) { ok = false; } SetText(hWnd, E_SETTING, sw->Web_SettingFile); SetText(hWnd, E_OUT, sw->Web_OutFile); SetWizardButton(wizard_page, ok, true, true, false); } // Update the file specification dialog void SwEasy2Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page) { bool ok = true; // Validate arguments if (hWnd == NULL || sw == NULL || wizard_page == NULL || wizard == NULL) { return; } if (IsEmptyUniStr(sw->Easy_OutFile) || IsEmptyUniStr(sw->Easy_SettingFile)) { ok = false; } SetText(hWnd, E_SETTING, sw->Easy_SettingFile); SetText(hWnd, E_OUT, sw->Easy_OutFile); SetWizardButton(wizard_page, ok, true, true, false); } // Generate a SFX file name of the default void SwGenerateDefaultSfxFileName(wchar_t *name, UINT size) { // Validate arguments if (name == NULL) { return; } UniFormat(name, size, L"easy-" GC_SW_SOFTETHER_PREFIX_W L"vpnclient-v%u.%02u-%u-%04u-%02u-%02u-windows.exe", CEDAR_VER / 100, CEDAR_VER % 100, CEDAR_BUILD, BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D); } // Generate a ZIP file name of the default void SwGenerateDefaultZipFileName(wchar_t *name, UINT size) { // Validate arguments if (name == NULL) { return; } UniFormat(name, size, L"web-" GC_SW_SOFTETHER_PREFIX_W L"vpnclient-v%u.%02u-%u-%04u-%02u-%02u-windows.zip", CEDAR_VER / 100, CEDAR_VER % 100, CEDAR_BUILD, BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D); } // Specify a file UINT SwEasy2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; wchar_t *fn; wchar_t tmp[MAX_SIZE]; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: DlgFont(hWnd, S_BOLD1, 10, true); DlgFont(hWnd, S_BOLD2, 10, true); Check(hWnd, B_DELETE_SENSITIVE, sw->Easy_EraseSensitive); Check(hWnd, B_EASYMODE, sw->Easy_EasyMode); break; case WM_WIZ_SHOW: SwEasy2Update(hWnd, sw, wizard, wizard_page); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: // Save the Settings MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EraseSensitive", sw->Easy_EraseSensitive); MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EasyMode", sw->Easy_EasyMode); return D_SW_PERFORM; case WM_WIZ_BACK: return D_SW_EASY1; case WM_COMMAND: switch (wParam) { case B_DELETE_SENSITIVE: sw->Easy_EraseSensitive = IsChecked(hWnd, B_DELETE_SENSITIVE); sw->Easy_EasyMode = IsChecked(hWnd, B_EASYMODE); break; case B_BROWSE_SETTING: fn = OpenDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"), _UU("CM_ACCOUNT_OPEN_TITLE")); if (fn != NULL) { // Parse if (CiTryToParseAccountFile(fn) == false) { // Failure MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_ACCOUNT_PARSE_FAILED")); } else { // Success UniStrCpy(sw->Easy_SettingFile, sizeof(sw->Easy_SettingFile), fn); SwEasy2Update(hWnd, sw, wizard, wizard_page); FocusEx(hWnd, E_SETTING); } Free(fn); } break; case B_BROWSE_OUT: SwGenerateDefaultSfxFileName(tmp, sizeof(tmp)); fn = SaveDlg(hWnd, _UU("SW_EXE_FILTER"), _UU("DLG_SAVE_FILE"), tmp, L".exe"); if (fn != NULL) { UniStrCpy(sw->Easy_OutFile, sizeof(sw->Easy_OutFile), fn); SwEasy2Update(hWnd, sw, wizard, wizard_page); } break; case B_HINT: break; } break; } return 0; } // Specify a file UINT SwWeb2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; wchar_t *fn; wchar_t tmp[MAX_SIZE]; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: DlgFont(hWnd, S_BOLD1, 10, true); DlgFont(hWnd, S_BOLD2, 10, true); Check(hWnd, B_DELETE_SENSITIVE, sw->Web_EraseSensitive); Check(hWnd, B_EASYMODE, sw->Web_EasyMode); break; case WM_WIZ_SHOW: SwWeb2Update(hWnd, sw, wizard, wizard_page); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: // Save the settings MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EraseSensitive", sw->Web_EraseSensitive); MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EasyMode", sw->Web_EasyMode); return D_SW_PERFORM; case WM_WIZ_BACK: return D_SW_WEB1; case WM_COMMAND: switch (wParam) { case B_DELETE_SENSITIVE: sw->Web_EraseSensitive = IsChecked(hWnd, B_DELETE_SENSITIVE); sw->Web_EasyMode = IsChecked(hWnd, B_EASYMODE); break; case B_BROWSE_SETTING: fn = OpenDlg(hWnd, _UU("CM_ACCOUNT_SETTING_FILE"), _UU("CM_ACCOUNT_OPEN_TITLE")); if (fn != NULL) { // Parse if (CiTryToParseAccountFile(fn) == false) { // Failure MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("CM_ACCOUNT_PARSE_FAILED")); } else { // Success UniStrCpy(sw->Web_SettingFile, sizeof(sw->Web_SettingFile), fn); SwWeb2Update(hWnd, sw, wizard, wizard_page); FocusEx(hWnd, E_SETTING); } Free(fn); } break; case B_BROWSE_OUT: SwGenerateDefaultZipFileName(tmp, sizeof(tmp)); fn = SaveDlg(hWnd, _UU("DLG_ZIP_FILER"), _UU("DLG_SAVE_FILE"), tmp, L".zip"); if (fn != NULL) { UniStrCpy(sw->Web_OutFile, sizeof(sw->Web_OutFile), fn); SwWeb2Update(hWnd, sw, wizard, wizard_page); } break; case B_HINT: break; } break; } return 0; } // Start screen of the Web Installer Creation Wizard UINT SwWeb1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: wizard->CloseConfirmMsg = NULL; DlgFont(hWnd, S_TITLE, 11, true); break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, false, true, false); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: return D_SW_WEB2; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Start screen of the Simple installer creation wizard UINT SwEasy1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: wizard->CloseConfirmMsg = NULL; DlgFont(hWnd, S_TITLE, 11, true); break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, false, true, false); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: return D_SW_EASY2; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Get the icon for the language UINT SwGetLangIcon(char *name) { UINT ret = ICO_NULL; // Validate arguments if (name == NULL) { return ICO_NULL; } if (StrCmpi(name, "ja") == 0) { ret = ICO_LANG_JAPANESE; } else if (StrCmpi(name, "en") == 0) { ret = ICO_LANG_ENGLISH; } else if (StrCmpi(name, "cn") == 0) { ret = ICO_LANG_CHINESE; } return ret; } // Initialize the language list void SwLang1Init(HWND hWnd, SW *sw) { LVB *b; UINT i; SW_COMPONENT *default_select = NULL; LIST *o; UINT current_lang = GetCurrentLangId(); UINT select_index = INFINITE; // Validate arguments if (hWnd == NULL || sw == NULL) { return; } o = LoadLangList(); LvReset(hWnd, L_LIST); b = LvInsertStart(); for (i = 0;i < LIST_NUM(o);i++) { LANGLIST *t = LIST_DATA(o, i); wchar_t tmp[MAX_SIZE]; wchar_t tmp2[MAX_SIZE]; UniFormat(tmp, sizeof(tmp), L"(%s)", t->TitleLocal); UniFormat(tmp2, sizeof(tmp2), L" %s", t->TitleEnglish); LvInsertAdd(b, SwGetLangIcon(t->Name), (void *)(t->Id + 1), 2, tmp2, tmp); if (t->Id == current_lang) { select_index = i; } } LvInsertEnd(b, hWnd, L_LIST); if (sw->CurrentComponent == NULL) { LvSelectByParam(hWnd, L_LIST, default_select); } else { LvSelectByParam(hWnd, L_LIST, sw->CurrentComponent); } LvAutoSize(hWnd, L_LIST); FreeLangList(o); if (select_index != INFINITE) { LvSelect(hWnd, L_LIST, select_index); } LvSort(hWnd, L_LIST, 0, false); Focus(hWnd, L_LIST); // Show the current language if (true) { LANGLIST t; wchar_t tmp[MAX_SIZE]; Zero(&t, sizeof(t)); GetCurrentLang(&t); UniFormat(tmp, sizeof(tmp), L"%s (%s)", t.TitleEnglish, t.TitleLocal); SetText(hWnd, E_CURRENT, tmp); if (MsIsVista()) { SetFont(hWnd, E_CURRENT, GetMeiryoFontEx(11)); } else { DlgFont(hWnd, E_CURRENT, 11, false); } } } // Update of control void SwLang1Update(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page) { UINT id; // Validate arguments if (hWnd == NULL || sw == NULL || wizard == NULL || wizard_page == NULL) { return; } id = (UINT)LvGetSelectedParam(hWnd, L_LIST); if (id == 0) { SetWizardButtonEx(wizard_page, false, false, true, false, (MsIsAdmin() == false && sw->IsSystemMode)); } else { SetWizardButtonEx(wizard_page, true, false, true, false, (MsIsAdmin() == false && sw->IsSystemMode)); } } // Language setting screen UINT SwLang1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; NMHDR *n; UINT id; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: LvInitEx2(hWnd, L_LIST, false, true); if (MsIsVista()) { SetFont(hWnd, L_LIST, GetMeiryoFontEx(12)); } else { DlgFont(hWnd, L_LIST, 12, false); } LvInsertColumn(hWnd, L_LIST, 0, L"English Name", 250); LvInsertColumn(hWnd, L_LIST, 1, L"Local Name", 250); SwLang1Update(hWnd, sw, wizard, wizard_page); break; case WM_WIZ_SHOW: SetWizardButtonEx(wizard_page, true, false, true, false, (MsIsAdmin() == false && sw->IsSystemMode)); SwLang1Init(hWnd, sw); SwLang1Update(hWnd, sw, wizard, wizard_page); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: if (SwEnterSingle(sw) == false) { // Multiple-starts prevention MsgBox(hWnd, MB_ICONINFORMATION, _UU("SW_OTHER_INSTANCE_EXISTS")); break; } if (MsIsNt() == false) { // Win9x MsgBox(hWnd, MB_ICONSTOP, L"Windows 9x / Me doesn't support multi-language switcing.\r\n\r\nIf you want to switch to another language, please use Windows NT 4.0, 2000 or greater."); break; } // Get the current selection id = (UINT)LvGetSelectedParam(hWnd, L_LIST); if (id != 0) { id--; if (id == GetCurrentLangId()) { // No change sw->LangNotChanged = true; sw->ExitCode = 0; return D_SW_ERROR; } else { wchar_t add_param[MAX_SIZE]; LIST *o; LANGLIST *new_lang; LANGLIST old_lang; char new_lang_name[MAX_SIZE]; char old_lang_name[MAX_SIZE]; GetCurrentLang(&old_lang); o = LoadLangList(); if (o == NULL) { MsgBox(hWnd, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED")); break; } new_lang = GetLangById(o, id); if (new_lang == NULL) { MsgBox(hWnd, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED")); FreeLangList(o); break; } StrCpy(new_lang_name, sizeof(new_lang_name), new_lang->Name); StrCpy(old_lang_name, sizeof(old_lang_name), old_lang.Name); FreeLangList(o); UniFormat(add_param, sizeof(add_param), L"/LANGID:%u", id); if (sw->DoubleClickBlocker) { break; } sw->DoubleClickBlocker = true; sw->LangId = id; if (sw->IsSystemMode == false) { LABEL_RUN_CHILD_PROCESS: // Start the process immediately in the case of user mode if (SaveLangConfigCurrentDir(new_lang_name) == false) { sw->DoubleClickBlocker = false; MsgBox(hWnd, MB_ICONSTOP, _UU("SW_LANG_SET_FAILED")); break; } UniStrCat(add_param, sizeof(add_param), L" /LANGNOW:yes"); if (SwReExecMyself(sw, add_param, false)) { // Terminate itself if it succeeds to start the child process CloseWizard(wizard_page); break; } else { // Child process startup failure sw->DoubleClickBlocker = false; // Undo the language setting SaveLangConfigCurrentDir(old_lang_name); break; } } // In the case of system mode if (MsIsAdmin() == false) { if (MsIsVista()) { if (sw->IsReExecForUac == false) { // If there is no Admin privileges in Vista or later, attempt to acquire Admin rights by UAC first during the first run UniStrCat(add_param, sizeof(add_param), L" /SETLANGANDREBOOT:true"); if (SwReExecMyself(sw, add_param, true)) { // Terminate itself if it succeeds to start the child process CloseWizard(wizard_page); break; } else { // Do nothing if it fails to start in the UAC sw->DoubleClickBlocker = false; break; } } else { // If no Admin privileges after being started by the UAC, jump to the guidance screen indicating it is not Admin return D_SW_NOT_ADMIN; } } else { // Jump to guide screen indicating that it is not the Admin in the case of XP or earlier return D_SW_NOT_ADMIN; } } else { // Start the process if there is a Admin privileges goto LABEL_RUN_CHILD_PROCESS; } } } break; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { } break; case WM_NOTIFY: n = (NMHDR *)lParam; switch (n->idFrom) { case L_LIST: switch (n->code) { case LVN_ITEMCHANGED: SwLang1Update(hWnd, sw, wizard, wizard_page); break; } break; } break; } return 0; } // Start the uninstallation UINT SwUninst1(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: FormatText(hWnd, S_TITLE, sw->CurrentComponent->Title); FormatText(hWnd, S_WELCOME, sw->CurrentComponent->Title); break; case WM_WIZ_SHOW: DlgFont(hWnd, S_TITLE, 11, true); SetWizardButtonEx(wizard_page, true, false, true, false, sw->IsSystemMode); sw->DoubleClickBlocker = false; break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: if (MsgBoxEx(hWnd, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_UNINSTALL_CONFIRM"), sw->CurrentComponent->Title) == IDNO) { break; } if (SwEnterSingle(sw) == false) { // Multiple-starts prevention MsgBox(hWnd, MB_ICONINFORMATION, _UU("SW_OTHER_INSTANCE_EXISTS")); break; } if (sw->DoubleClickBlocker) { break; } sw->DoubleClickBlocker = true; if (sw->IsSystemMode == false) { // Start uninstallation immediately in the case of user mode return D_SW_PERFORM; } // In the case of system mode if (MsIsAdmin() == false) { if (MsIsVista()) { if (sw->IsReExecForUac == false) { // If there is no Admin privileges in Vista or later, attempt to acquire Admin rights by UAC first during the first run if (SwReExecMyself(sw, NULL, true)) { // Terminate itself if it succeeds to start the child process CloseWizard(wizard_page); break; } else { // If fail to run in UAC, jump to guide screen indicating that it is not Admin return D_SW_NOT_ADMIN; } } else { // If no Admin privileges after being started by the UAC, jump to the guidance screen indicating it is not Admin return D_SW_NOT_ADMIN; } } else { // Jump to guide screen indicating that it is not the Admin in the case of XP or earlier return D_SW_NOT_ADMIN; } } else { // Start the uninstallation if it has Admin privileges return D_SW_PERFORM; } break; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Completion screen UINT SwFinish(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; char tmp[MAX_SIZE]; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: if (sw->EasyMode) { SetIcon(hWnd, S_ICON, ICO_SETUP); } else if (sw->WebMode) { SetIcon(hWnd, S_ICON, ICO_INTERNET); } else { FormatText(hWnd, S_INFO, sw->CurrentComponent->Title); SetIcon(hWnd, S_ICON, sw->CurrentComponent->Icon); } wizard->CloseConfirmMsg = NULL; sw->ExitCode = 0; break; case WM_WIZ_SHOW: if (UniIsEmptyStr(sw->FinishMsg) == false) { SetText(hWnd, S_INFO, sw->FinishMsg); } SetWizardButton(wizard_page, true, false, false, true); if (sw->HideStartCommand || sw->UninstallMode || sw->LanguageMode || sw->EasyMode || sw->WebMode || UniIsEmptyStr(sw->CurrentComponent->StartExeName)) { Hide(hWnd, B_RUN); sw->Run = false; } else { SetText(hWnd, B_RUN, sw->CurrentComponent->StartDescription); Show(hWnd, B_RUN); Format(tmp, sizeof(tmp), "UI_NoCheck_%s_%u", sw->CurrentComponent->Name, sw->IsSystemMode); Check(hWnd, B_RUN, !MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, tmp)); sw->Run = IsChecked(hWnd, B_RUN); } break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: break; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { case B_RUN: if (sw->HideStartCommand || sw->UninstallMode || sw->LanguageMode || sw->EasyMode || sw->WebMode || UniIsEmptyStr(sw->CurrentComponent->StartExeName)) { } else { Format(tmp, sizeof(tmp), "UI_NoCheck_%s_%u", sw->CurrentComponent->Name, sw->IsSystemMode); sw->Run = IsChecked(hWnd, B_RUN); MsRegWriteInt(REG_CURRENT_USER, SW_REG_KEY, tmp, !sw->Run); } break; } break; } return 0; } // Error occuring screen UINT SwError(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: wizard->CloseConfirmMsg = NULL; if (sw->EasyMode) { SetText(hWnd, S_INFO, _UU("SW_EASY_ERROR_MSG")); } else if (sw->WebMode) { SetText(hWnd, S_INFO, _UU("SW_WEB_ERROR_MSG")); } else { FormatText(hWnd, S_INFO, sw->CurrentComponent->Title); } if (sw->MsiRebootRequired) { // MSI requires a reboot wchar_t tmp[MAX_SIZE]; SetIcon(hWnd, S_ICON, ICO_INFORMATION); UniFormat(tmp, sizeof(tmp), _UU("SW_MSI_UNINSTALL_REBOOT_REQUIRED"), sw->CurrentComponent->Title); SetText(hWnd, S_INFO, tmp); } if (sw->LangNotChanged) { // Language has not changed wchar_t tmp[MAX_SIZE]; SetIcon(hWnd, S_ICON, ICO_INFORMATION); UniFormat(tmp, sizeof(tmp), _UU("SW_LANG_NOT_CHANGED"), sw->CurrentComponent->Title); SetText(hWnd, S_INFO, tmp); } break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, false, false, true); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: break; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Execution thread of the setup process void SwPerformThread(THREAD *thread, void *param) { WIZARD_PAGE *wp = (WIZARD_PAGE *)param; SW *sw; SW_COMPONENT *c; bool ret; SW_UI ui; // Validate arguments if (thread == NULL || param == NULL) { return; } sw = (SW *)wp->Wizard->Param; sw->ExitCode = SW_EXIT_CODE_INTERNAL_ERROR; // Components to be installed c = sw->CurrentComponent; if (sw->EasyMode) { // Create a simple installer ret = SwEasyMain(sw, wp); } else if (sw->WebMode) { // Create a Web installer ret = SwWebMain(sw, wp); } else if (sw->UninstallMode == false) { // Installation ret = SwInstallMain(sw, wp, c); } else { // Uninstallation ret = SwUninstallMain(sw, wp, c); } // Notify the results to the window Zero(&ui, sizeof(ui)); ui.Type = (ret ? SW_UI_TYPE_FINISH : SW_UI_TYPE_ERROR); SwInteractUi(wp, &ui); } // Create a file copy task SW_TASK_COPY *SwNewCopyTask(wchar_t *srcfilename, wchar_t *dstfilename, wchar_t *srcdir, wchar_t *dstdir, bool overwrite, bool setup_file) { SW_TASK_COPY *ct; // Validate arguments if (srcfilename == NULL || srcdir == NULL || dstdir == NULL) { return NULL; } ct = ZeroMalloc(sizeof(SW_TASK_COPY)); UniStrCpy(ct->SrcFileName, sizeof(ct->SrcFileName), srcfilename); if (UniIsEmptyStr(dstfilename)) { UniStrCpy(ct->DstFileName, sizeof(ct->DstFileName), srcfilename); } else { UniStrCpy(ct->DstFileName, sizeof(ct->DstFileName), dstfilename); } UniStrCpy(ct->SrcDir, sizeof(ct->SrcDir), srcdir); UniStrCpy(ct->DstDir, sizeof(ct->DstDir), dstdir); ct->Overwrite = overwrite; ct->SetupFile = setup_file; return ct; } // Release the file copy task void SwFreeCopyTask(SW_TASK_COPY *ct) { // Validate arguments if (ct == NULL) { return; } Free(ct); } // Create a link creation task SW_TASK_LINK *SwNewLinkTask(wchar_t *target_dir, wchar_t *target_exe, wchar_t *target_arg, wchar_t *icon_exe, UINT icon_index, wchar_t *dest_dir, wchar_t *dest_name, wchar_t *dest_desc, bool no_delete_dir) { SW_TASK_LINK *lt; // Validate arguments if (target_dir == NULL || target_exe == NULL || dest_dir == NULL || dest_name == NULL) { return NULL; } lt = ZeroMalloc(sizeof(SW_TASK_LINK)); UniStrCpy(lt->TargetDir, sizeof(lt->TargetDir), target_dir); UniStrCpy(lt->TargetExe, sizeof(lt->TargetExe), target_exe); UniStrCpy(lt->TargetArg, sizeof(lt->TargetArg), target_arg); if (UniIsEmptyStr(icon_exe) == false) { UniStrCpy(lt->IconExe, sizeof(lt->IconExe), icon_exe); } else { UniStrCpy(lt->IconExe, sizeof(lt->IconExe), target_exe); } lt->IconIndex = icon_index; UniStrCpy(lt->DestDir, sizeof(lt->DestDir), dest_dir); UniStrCpy(lt->DestName, sizeof(lt->DestName), dest_name); UniStrCpy(lt->DestDescription, sizeof(lt->DestDescription), dest_desc); lt->NoDeleteDir = no_delete_dir; return lt; } // Release the link creation task void SwFreeLinkTask(SW_TASK_LINK *lt) { // Validate arguments if (lt == NULL) { return; } Free(lt); } // Create a Setup task SW_TASK *SwNewTask() { SW_TASK *t = ZeroMalloc(sizeof(SW_TASK)); t->CopyTasks = NewListFast(NULL); t->SetSecurityPaths = NewListFast(NULL); t->LinkTasks = NewListFast(NULL); return t; } // Release the Setup Tasks void SwFreeTask(SW_TASK *t) { UINT i; // Validate arguments if (t == NULL) { return; } for (i = 0;i < LIST_NUM(t->CopyTasks);i++) { SW_TASK_COPY *ct = LIST_DATA(t->CopyTasks, i); SwFreeCopyTask(ct); } ReleaseList(t->CopyTasks); FreeStrList(t->SetSecurityPaths); for (i = 0;i < LIST_NUM(t->LinkTasks);i++) { SW_TASK_LINK *lt = LIST_DATA(t->LinkTasks, i); SwFreeLinkTask(lt); } ReleaseList(t->LinkTasks); Free(t); } // Delete the shortcut file void SwDeleteShortcuts(SW_LOGFILE *logfile) { UINT i; LIST *o; // Validate arguments if (logfile == NULL) { return; } o = NewListFast(NULL); for (i = 0;i < LIST_NUM(logfile->LogList);i++) { SW_LOG *g = LIST_DATA(logfile->LogList, LIST_NUM(logfile->LogList) - i - 1); switch (g->Type) { case SW_LOG_TYPE_LNK: FileDeleteW(g->Path); Add(o, g); break; case SW_LOG_TYPE_LNK_DIR: SleepThread(100); DeleteDirW(g->Path); Add(o, g); break; } } for (i = 0;i < LIST_NUM(o);i++) { SW_LOG *g = LIST_DATA(o, i); Delete(logfile->LogList, g); Free(g); } ReleaseList(o); } // Uninstall main bool SwUninstallMain(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c) { bool x64 = MsIs64BitWindows(); bool ok; wchar_t tmp[MAX_SIZE]; UINT i; // Validate arguments if (sw == NULL || wp == NULL || c == NULL) { return false; } SwPerformPrint(wp, _UU("SW_PERFORM_MSG_INIT_UNINST")); // Stop the Service ok = true; if (c->InstallService) { char svc_title_name[MAX_SIZE]; wchar_t *svc_title; Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName); svc_title = _UU(svc_title_name); if (UniIsEmptyStr(svc_title) == false) { if (sw->IsSystemMode && MsIsNt()) { // WinNT and system mode if (MsIsServiceRunning(c->SvcName)) { wchar_t svc_exe[MAX_SIZE]; UINT64 giveup_tick; UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC"), svc_title); SwPerformPrint(wp, tmp); LABEL_RETRY_3: if (MsStopService(c->SvcName) == false) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC_ERROR"), svc_title, c->SvcName); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; } else { if (MsIsServiceRunning(c->SvcName)) { goto LABEL_RETRY_3; } } } // Wait 5 seconds if stop the service SleepThread(5000); // Wait until the EXE file for the service become ready to write ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName); giveup_tick = Tick64() + (UINT64)10000; while (IsFileWriteLockedW(svc_exe)) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe); SwPerformPrint(wp, tmp); SleepThread(100); if (Tick64() >= giveup_tick) { break; } } } } else { // Win9x or user mode wchar_t svc_exe[MAX_SIZE]; UINT64 giveup_tick; // Stop the Service MsStopUserModeSvc(c->SvcName); SleepThread(3000); // Wait until the EXE file for the service become ready to write ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName); giveup_tick = Tick64() + (UINT64)10000; while (IsFileWriteLockedW(svc_exe)) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe); SwPerformPrint(wp, tmp); SleepThread(100); if (Tick64() >= giveup_tick) { break; } } } } } if (ok == false) { goto LABEL_CLEANUP; } // Examine preliminary whether the files to be deleted can be written successfully ok = true; SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_PREPARE")); for (i = 0;i < LIST_NUM(sw->LogFile->LogList);i++) { SW_LOG *g = LIST_DATA(sw->LogFile->LogList, i); if (g->Type == SW_LOG_TYPE_FILE) { wchar_t fullpath[MAX_SIZE]; IO *io; bool write_ok; bool new_file; LABEL_RETRY_1: write_ok = new_file = false; UniStrCpy(fullpath, sizeof(fullpath), g->Path); // If the process with the same name is running, kill it if (MsKillProcessByExeName(fullpath) != 0) { // Wait for 1 second if kill the process SleepThread(1000); } // Writing check io = FileOpenExW(fullpath, true, true); if (io == NULL) { io = FileCreateW(fullpath); new_file = true; } if (io != NULL) { // Writing OK write_ok = true; FileCloseEx(io, true); if (new_file) { FileDeleteW(fullpath); } } if (write_ok == false) { // Show an error message if it fails UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_DELETE_ERROR"), fullpath, c->Title); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; break; } else { // Retry goto LABEL_RETRY_1; } } } } if (ok == false) { goto LABEL_CLEANUP; } // Delete the service if (c->InstallService) { char svc_title_name[MAX_SIZE]; char svc_description_name[MAX_SIZE]; wchar_t *svc_title; Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName); Format(svc_description_name, sizeof(svc_description_name), "SVC_%s_DESCRIPT", c->SvcName); svc_title = _UU(svc_title_name); if (UniIsEmptyStr(svc_title) == false) { if (sw->IsSystemMode == false || MsIsNt() == false) { // Win9x or user mode if (MsIsNt() == false) { // Remove the Run key from the registry for Win9x MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1, c->SvcName); MsRegDeleteValue(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2, c->SvcName); } } else { // System mode UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_UNINSTALL_SVC"), svc_title); SwPerformPrint(wp, tmp); LABEL_RETRY_4: if (MsIsServiceInstalled(c->SvcName)) { // Stop the service if it is running by any chance MsStopService(c->SvcName); } if (MsIsServiceInstalled(c->SvcName)) { // Uninstall the service if (MsUninstallService(c->SvcName) == false) { // Show an error message if it fails UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_UNINSTALL_FAILED"), svc_title, c->SvcName); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; } else { // Retry goto LABEL_RETRY_4; } } } } } } // Delete the shortcut SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_LINKS")); SwDeleteShortcuts(sw->LogFile); // Delete the registry, files, and directories for (i = 0;i < LIST_NUM(sw->LogFile->LogList);i++) { SW_LOG *g = LIST_DATA(sw->LogFile->LogList, LIST_NUM(sw->LogFile->LogList) - i - 1); char tmpa[MAX_SIZE]; UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_DELETE"), g->Path); switch (g->Type) { case SW_LOG_TYPE_FILE: // File SwPerformPrint(wp, tmp); FileDeleteW(g->Path); break; case SW_LOG_TYPE_DIR: // Directory SwPerformPrint(wp, tmp); SleepThread(100); DeleteDirW(g->Path); break; case SW_LOG_TYPE_REGISTRY: // Registry SwPerformPrint(wp, tmp); UniToStr(tmpa, sizeof(tmpa), g->Path); MsRegDeleteKeyEx2(REG_LOCAL_MACHINE, tmpa, false, true); break; } } // Remove the installed build number from the registry if (true) { char keyname[MAX_SIZE]; Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name); MsRegDeleteValueEx2(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER, keyname, "InstalledBuild", false, true); } // Remove the EULA agreement record MsRegDeleteValueEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name, false, true); SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_SETUP_INFO")); if (c->Id == SW_CMP_VPN_CLIENT) { // Remove the UI Helper MsRegDeleteValueEx2(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", SW_VPN_CLIENT_UIHELPER_REGVALUE, false, true); } // Remove the installation directory from the registry if (true) { // Remove the installed directory from the registry char keyname[MAX_SIZE]; Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name); MsRegDeleteKeyEx2(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER, keyname, false, true); } // Delete the setuplog.dat if (true) { wchar_t setuplog[MAX_PATH]; ConbinePathW(setuplog, sizeof(setuplog), MsGetExeDirNameW(), L"setuplog.dat"); FileDeleteW(setuplog); } // Delete the existing Virtual Network Adapters // Currently disabled because of 32bit/64bit problems #if 0 if (c->Id == SW_CMP_VPN_CLIENT) { if (MsIsNt()) { if (!(MsIs64BitWindows() && Is32())) { UINT i; TOKEN_LIST *t; SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_NIC")); // Enumeration t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD); if (t != NULL) { if (t->NumTokens >= 1) { if (SwPerformMsgBox(wp, MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_PERFORM_MSG_DELETE_NIC")) == IDYES) { for (i = 0;i < t->NumTokens;i++) { char *name = t->Token[i]; MsUninstallVLan(name); } } } FreeToken(t); } } } } #endif SwPerformPrint(wp, _UU("SW_PERFORM_MSG_UPDATING")); // Notify the update to the system MsUpdateSystem(); // Completion message SwPerformPrint(wp, _UU("SW_PERFORM_MSG_FINISHED")); if (ok == false) { goto LABEL_CLEANUP; } LABEL_CLEANUP: return ok; } // Create a Task List void SwDefineTasks(SW *sw, SW_TASK *t, SW_COMPONENT *c) { wchar_t tmp[MAX_SIZE]; bool x64 = MsIs64BitWindows(); wchar_t src_setup_exe_fullpath[MAX_PATH]; wchar_t src_setup_exe_dir[MAX_PATH]; wchar_t src_setup_exe_filename[MAX_PATH]; wchar_t dir_desktop[MAX_PATH]; wchar_t dir_startmenu[MAX_PATH]; wchar_t dir_program[MAX_PATH]; wchar_t dir_app_program[MAX_PATH]; wchar_t dir_config_program[MAX_PATH]; wchar_t dir_admin_tools[MAX_PATH]; wchar_t dir_config_language[MAX_PATH]; wchar_t dir_startup[MAX_PATH]; wchar_t tmp1[MAX_SIZE], tmp2[MAX_SIZE]; SW_TASK_COPY *setup_exe; SW_TASK_COPY *setup_exe_x64; // Validate arguments if (sw == NULL || t == NULL || c == NULL) { return; } //// Organize directory name for creating shortcut // Desktop UniStrCpy(dir_desktop, sizeof(dir_desktop), (sw->IsSystemMode ? MsGetCommonDesktopDirW() : MsGetPersonalDesktopDirW())); // Start menu UniStrCpy(dir_startmenu, sizeof(dir_startmenu), (sw->IsSystemMode ? MsGetCommonStartMenuDirW() : MsGetPersonalStartMenuDirW())); // Program UniStrCpy(dir_program, sizeof(dir_program), (sw->IsSystemMode ? MsGetCommonProgramsDirW() : MsGetPersonalProgramsDirW())); // Program directory for this application ConbinePathW(dir_app_program, sizeof(dir_app_program), dir_program, c->LongName); if (sw->IsSystemMode == false) { // User mode UniStrCat(dir_app_program, sizeof(dir_app_program), _UU("SW_TAG_USERNAME")); } // Configuration tool directory ConbinePathW(dir_config_program, sizeof(dir_config_program), dir_app_program, _UU("SW_DIRNAME_CONFIG_TOOLS")); // Language configuration directory ConbinePathW(dir_config_language, sizeof(dir_config_language), dir_app_program, _UU("SW_DIRNAME_LANGUAGE_TOOLS")); // Directory for System administrator tool ConbinePathW(dir_admin_tools, sizeof(dir_admin_tools), dir_app_program, _UU("SW_DIRNAME_ADMIN_TOOLS")); // Startup UniStrCpy(dir_startup, sizeof(dir_startup), (sw->IsSystemMode ? MsGetCommonStartupDirW() : MsGetPersonalStartupDirW())); // Get the path information related to vpnsetup.exe UniStrCpy(src_setup_exe_fullpath, sizeof(src_setup_exe_fullpath), MsGetExeFileNameW()); GetDirNameFromFilePathW(src_setup_exe_dir, sizeof(src_setup_exe_dir), src_setup_exe_fullpath); GetFileNameFromFilePathW(src_setup_exe_filename, sizeof(src_setup_exe_filename), src_setup_exe_fullpath); // Add the Setup program (themselves) to the copy list Add(t->CopyTasks, (setup_exe = SwNewCopyTask(src_setup_exe_filename, L"vpnsetup.exe", src_setup_exe_dir, sw->InstallDir, true, true))); // Add vpnsetup_x64.exe to the copy list Add(t->CopyTasks, (setup_exe_x64 = SwNewCopyTask(L"vpnsetup_x64.exe", L"vpnsetup_x64.exe", src_setup_exe_dir, sw->InstallDir, true, true))); // Generate the file processing list for each component if (c->Id == SW_CMP_VPN_SERVER) { // VPN Server SW_TASK_COPY *ct; SW_TASK_COPY *vpnserver, *vpncmd, *vpnsmgr; CombinePathW(tmp, sizeof(tmp), sw->InstallDir, L"backup.vpn_server.config"); Add(t->SetSecurityPaths, CopyUniStr(tmp)); if (x64 == false) { vpnserver = SwNewCopyTask(L"vpnserver.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnsmgr = SwNewCopyTask(L"vpnsmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } else { vpnserver = SwNewCopyTask(L"vpnserver_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnsmgr = SwNewCopyTask(L"vpnsmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } Add(t->CopyTasks, vpnserver); Add(t->CopyTasks, vpncmd); Add(t->CopyTasks, vpnsmgr); Add(t->CopyTasks, (ct = SwNewCopyTask(L"|empty.config", L"vpn_server.config", sw->InstallSrc, sw->InstallDir, false, false))); Add(t->CopyTasks, SwNewCopyTask(L"|backup_dir_readme.txt", L"readme.txt", sw->InstallSrc, tmp, false, false)); CombinePathW(tmp, sizeof(tmp), ct->DstDir, ct->DstFileName); Add(t->SetSecurityPaths, CopyUniStr(tmp)); //// Definition of the shortcuts // Desktop and Start menu Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_desktop, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_startmenu, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true)); // Programs\PacketiX VPN Server Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNSMGR_FULL"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNCMD"), _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnserver->DstFileName, L"/traffic", L"vpnsetup.exe", 2, dir_admin_tools, _UU("SW_LINK_NAME_TRAFFIC"), _UU("SW_LINK_NAME_TRAFFIC_COMMENT"), false)); // Programs\PacketiX VPN Server\Configuration tool Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnserver->DstFileName, L"/tcp", L"vpnsetup.exe", 3, dir_config_program, _UU("SW_LINK_NAME_TCP"), _UU("SW_LINK_NAME_TCP_COMMENT"), false)); if (MsIsWin2000OrGreater()) { Add(t->LinkTasks, SwNewLinkTask(MsGetSystem32DirW(), L"services.msc", NULL, L"filemgmt.dll", 0, dir_config_program, _UU("SW_LINK_NAME_SERVICES"), _UU("SW_LINK_NAME_SERVICES_COMMENT"), false)); if (sw->IsSystemMode) { // Debugging information collecting tool Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, L"/debug", L"vpnsetup.exe", 4, dir_admin_tools, _UU("SW_LINK_NAME_DEBUG"), _UU("SW_LINK_NAME_DEBUG_COMMENT"), false)); } } if (sw->IsSystemMode == false) { // Register to the start-up in the case of user mode Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnserver->DstFileName, L"/usermode", NULL, 0, dir_startup, _UU("SW_LINK_NAME_VPNSERVER_SVC"), _UU("SW_LINK_NAME_VPNSERVER_SVC_COMMENT"), true)); } } else if (c->Id == SW_CMP_VPN_BRIDGE) { // VPN Bridge SW_TASK_COPY *ct; SW_TASK_COPY *vpnbridge, *vpncmd, *vpnsmgr; CombinePathW(tmp, sizeof(tmp), sw->InstallDir, L"backup.vpn_bridge.config"); Add(t->SetSecurityPaths, CopyUniStr(tmp)); if (x64 == false) { vpnbridge = SwNewCopyTask(L"vpnbridge.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnsmgr = SwNewCopyTask(L"vpnsmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } else { vpnbridge = SwNewCopyTask(L"vpnbridge_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnsmgr = SwNewCopyTask(L"vpnsmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } Add(t->CopyTasks, vpnbridge); Add(t->CopyTasks, vpncmd); Add(t->CopyTasks, vpnsmgr); Add(t->CopyTasks, (ct = SwNewCopyTask(L"|empty.config", L"vpn_bridge.config", sw->InstallSrc, sw->InstallDir, false, false))); Add(t->CopyTasks, SwNewCopyTask(L"|backup_dir_readme.txt", L"readme.txt", sw->InstallSrc, tmp, false, false)); CombinePathW(tmp, sizeof(tmp), ct->DstDir, ct->DstFileName); Add(t->SetSecurityPaths, CopyUniStr(tmp)); //// Definition of the shortcuts // Desktop and Start menu Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_desktop, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_startmenu, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT" : "SW_LINK_NAME_VPNSMGR_SHORT_UM"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true)); // Programs\PacketiX VPN Bridge Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNSMGR_FULL"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNCMD"), _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnbridge->DstFileName, L"/traffic", L"vpnsetup.exe", 2, dir_admin_tools, _UU("SW_LINK_NAME_TRAFFIC"), _UU("SW_LINK_NAME_TRAFFIC_COMMENT"), false)); // Programs\PacketiX VPN Bridge\Configuration tool Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnbridge->DstFileName, L"/tcp", L"vpnsetup.exe", 3, dir_config_program, _UU("SW_LINK_NAME_TCP"), _UU("SW_LINK_NAME_TCP_COMMENT"), false)); if (MsIsWin2000OrGreater()) { Add(t->LinkTasks, SwNewLinkTask(MsGetSystem32DirW(), L"services.msc", NULL, L"filemgmt.dll", 0, dir_config_program, _UU("SW_LINK_NAME_SERVICES"), _UU("SW_LINK_NAME_SERVICES_COMMENT"), false)); if (sw->IsSystemMode) { // Debugging information collecting tool Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, L"/debug", L"vpnsetup.exe", 4, dir_admin_tools, _UU("SW_LINK_NAME_DEBUG"), _UU("SW_LINK_NAME_DEBUG_COMMENT"), false)); } } if (sw->IsSystemMode == false) { // Register to the start-up in the case of user mode Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnbridge->DstFileName, L"/usermode", NULL, 0, dir_startup, _UU("SW_LINK_NAME_VPNBRIDGE_SVC"), _UU("SW_LINK_NAME_VPNBRIDGE_SVC_COMMENT"), true)); } } else if (c->Id == SW_CMP_VPN_CLIENT) { // VPN Client SW_TASK_COPY *ct; SW_TASK_COPY *vpnclient, *vpncmd, *vpncmgr; SW_TASK_COPY *vpnclient_gomi, *vpncmd_gomi, *vpncmgr_gomi; SW_TASK_COPY *sfx_cache = NULL; SW_TASK_COPY *vpnweb; SW_TASK_COPY *vpninstall; wchar_t *src_config_filename; CombinePathW(tmp, sizeof(tmp), sw->InstallDir, L"backup.vpn_client.config"); Add(t->SetSecurityPaths, CopyUniStr(tmp)); if (x64 == false) { vpnclient = SwNewCopyTask(L"vpnclient.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmgr = SwNewCopyTask(L"vpncmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnclient_gomi = SwNewCopyTask(L"vpnclient_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd_gomi = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmgr_gomi = SwNewCopyTask(L"vpncmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } else { vpnclient = SwNewCopyTask(L"vpnclient_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmgr = SwNewCopyTask(L"vpncmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnclient_gomi = SwNewCopyTask(L"vpnclient.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmd_gomi = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmgr_gomi = SwNewCopyTask(L"vpncmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } if (vpncmgr != NULL) { CombinePathW(sw->vpncmgr_path, sizeof(sw->vpncmgr_path), vpncmgr->DstDir, vpncmgr->DstFileName); } if (UniIsEmptyStr(sw->CallerSfxPath) == false) { if (IsFileExistsW(sw->CallerSfxPath)) { // Cache the calling SFX file body to the installation directory wchar_t srcname[MAX_PATH]; wchar_t srcdir[MAX_PATH]; GetFileNameFromFilePathW(srcname, sizeof(srcname), sw->CallerSfxPath); GetDirNameFromFilePathW(srcdir, sizeof(srcdir), sw->CallerSfxPath); sfx_cache = SwNewCopyTask(srcname, SW_SFX_CACHE_FILENAME, srcdir, sw->InstallDir, true, false); } } vpnweb = SwNewCopyTask(L"vpnweb.cab", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpninstall = SwNewCopyTask(L"vpninstall.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); Add(t->CopyTasks, vpnclient); Add(t->CopyTasks, vpncmd); Add(t->CopyTasks, vpncmgr); Add(t->CopyTasks, vpnclient_gomi); Add(t->CopyTasks, vpncmd_gomi); Add(t->CopyTasks, vpncmgr_gomi); Add(t->CopyTasks, vpnweb); Add(t->CopyTasks, vpninstall); if (sfx_cache != NULL) { Add(t->CopyTasks, sfx_cache); } src_config_filename = L"|empty.config"; Add(t->CopyTasks, (ct = SwNewCopyTask(src_config_filename, L"vpn_client.config", sw->InstallSrc, sw->InstallDir, false, false))); Add(t->CopyTasks, SwNewCopyTask(L"|backup_dir_readme.txt", L"readme.txt", sw->InstallSrc, tmp, false, false)); CombinePathW(tmp, sizeof(tmp), ct->DstDir, ct->DstFileName); Add(t->SetSecurityPaths, CopyUniStr(tmp)); //// Definition of the shortcuts // Desktop and Start menu Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, NULL, NULL, 0, dir_desktop, _UU("SW_LINK_NAME_VPNCMGR_SHORT"), _UU("SW_LINK_NAME_VPNCMGR_COMMENT"), true)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, NULL, NULL, 0, dir_startmenu, _UU("SW_LINK_NAME_VPNCMGR_SHORT"), _UU("SW_LINK_NAME_VPNCMGR_COMMENT"), true)); // Programs\PacketiX VPN Client Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNCMGR_FULL"), _UU("SW_LINK_NAME_VPNCMGR_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_app_program, _UU("SW_LINK_NAME_VPNCMGR2_FULL"), _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNCMD"), _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnclient->DstFileName, L"/traffic", L"vpnsetup.exe", 2, dir_admin_tools, _UU("SW_LINK_NAME_TRAFFIC"), _UU("SW_LINK_NAME_TRAFFIC_COMMENT"), false)); // Programs\PacketiX VPN Client\Configuration Tools Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnclient->DstFileName, L"/tcp", L"vpnsetup.exe", 3, dir_config_program, _UU("SW_LINK_NAME_TCP"), _UU("SW_LINK_NAME_TCP_COMMENT"), false)); if (MsIsWin2000OrGreater()) { Add(t->LinkTasks, SwNewLinkTask(MsGetSystem32DirW(), L"services.msc", NULL, L"filemgmt.dll", 0, dir_config_program, _UU("SW_LINK_NAME_SERVICES"), _UU("SW_LINK_NAME_SERVICES_COMMENT"), false)); if (sw->IsSystemMode) { // Debugging information collecting tool Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, L"/debug", L"vpnsetup.exe", 4, dir_admin_tools, _UU("SW_LINK_NAME_DEBUG"), _UU("SW_LINK_NAME_DEBUG_COMMENT"), false)); } } // Programs\PacketiX VPN Client\System administrators tool if (MsIsNt()) { Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, L"vpnsetup.exe", L"/easy:true", L"vpnsetup.exe", 12, dir_admin_tools, _UU("SW_LINK_NAME_EASYINSTALLER"), _UU("SW_LINK_NAME_EASYINSTALLER_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, L"vpnsetup.exe", L"/web:true", L"vpnsetup.exe", 1, dir_admin_tools, _UU("SW_LINK_NAME_WEBINSTALLER"), _UU("SW_LINK_NAME_WEBINSTALLER_COMMENT"), false)); } // Startup Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/startup", NULL, 0, dir_startup, _UU("SW_LINK_NAME_VPNCMGRTRAY_FULL"), _UU("SW_LINK_NAME_VPNCMGRTRAY_COMMENT"), true)); } else if (c->Id == SW_CMP_VPN_SMGR) { // VPN Server Manager (Tools Only) SW_TASK_COPY *vpncmd, *vpnsmgr; if (x64 == false) { vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnsmgr = SwNewCopyTask(L"vpnsmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } else { vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpnsmgr = SwNewCopyTask(L"vpnsmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } Add(t->CopyTasks, vpncmd); Add(t->CopyTasks, vpnsmgr); //// Definition of the shortcuts // Desktop and Start menu Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_desktop, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY" : "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY_UM"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_startmenu, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY" : "SW_LINK_NAME_VPNSMGR_SHORT_TOOLSONLY_UM"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), true)); // Programs\PacketiX VPN Server Manager (Tools Only) Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpnsmgr->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNSMGR_FULL"), _UU("SW_LINK_NAME_VPNSMGR_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNCMD"), _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false)); } else if (c->Id == SW_CMP_VPN_CMGR) { // VPN Client Manager (Tools Only) SW_TASK_COPY *vpncmd, *vpncmgr; if (x64 == false) { vpncmd = SwNewCopyTask(L"vpncmd.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmgr = SwNewCopyTask(L"vpncmgr.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } else { vpncmd = SwNewCopyTask(L"vpncmd_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); vpncmgr = SwNewCopyTask(L"vpncmgr_x64.exe", NULL, sw->InstallSrc, sw->InstallDir, true, false); } Add(t->CopyTasks, vpncmd); Add(t->CopyTasks, vpncmgr); //// Definition of the shortcuts // Desktop and Start menu Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_desktop, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNCMGRTOOLS_SHORT" : "SW_LINK_NAME_VPNCMGRTOOLS_SHORT_UM"), _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), true)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_startmenu, _UU(sw->IsSystemMode ? "SW_LINK_NAME_VPNCMGRTOOLS_SHORT" : "SW_LINK_NAME_VPNCMGRTOOLS_SHORT_UM"), _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), true)); // Programs\PacketiX VPN Client Manager (Tools Only) Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmgr->DstFileName, L"/remote", L"vpnsetup.exe", 1, dir_app_program, _UU("SW_LINK_NAME_VPNCMGR2_FULL"), _UU("SW_LINK_NAME_VPNCMGR2_COMMENT"), false)); Add(t->LinkTasks, SwNewLinkTask(sw->InstallDir, vpncmd->DstFileName, NULL, NULL, 0, dir_app_program, _UU("SW_LINK_NAME_VPNCMD"), _UU("SW_LINK_NAME_VPNCMD_COMMENT"), false)); } // Uninstallation UniFormat(tmp1, sizeof(tmp1), _UU("SW_LINK_NAME_UNINSTALL"), c->Title); UniFormat(tmp2, sizeof(tmp2), _UU("SW_LINK_NAME_UNINSTALL_COMMENT"), c->Title); Add(t->LinkTasks, SwNewLinkTask(setup_exe->DstDir, setup_exe->DstFileName, NULL, NULL, 0, dir_config_program, tmp1, tmp2, false)); // Language settings (except for Win9x) if (MsIsNt()) { UniFormat(tmp1, sizeof(tmp1), _UU("SW_LINK_NAME_LANGUAGE"), c->Title); UniFormat(tmp2, sizeof(tmp2), _UU("SW_LINK_NAME_LANGUAGE_COMMENT"), c->Title); Add(t->LinkTasks, SwNewLinkTask(setup_exe->DstDir, setup_exe->DstFileName, L"/language:yes", L"vpnsetup.exe", 10, dir_config_language, tmp1, tmp2, false)); } // Hamcore! Add(t->CopyTasks, SwNewCopyTask(L"hamcore.se2", NULL, sw->InstallSrc, sw->InstallDir, true, true)); } // Build the Web installer bool SwWebMain(SW *sw, WIZARD_PAGE *wp) { bool ret = false; wchar_t tmp[MAX_SIZE]; // Validate arguments if (sw == NULL || wp == NULL) { return false; } SwPerformPrint(wp, _UU("SW_PERFORM_MSG_WEB_INIT")); if (true) { wchar_t installer_src_exe[MAX_PATH]; wchar_t src_cab[MAX_PATH]; wchar_t vpninstall_exe[MAX_PATH]; char inf_path[MAX_PATH]; char htm_path[MAX_PATH]; LANGLIST current_lang; BUF *inf_buf = NULL; BUF *htm_buf = NULL; BUF *setting_buf = NULL; char *inf_data = NULL; UINT inf_data_size; char *htm_data = NULL; UINT htm_data_size; char ver_major[64]; char ver_minor[64]; char ver_build[64]; char *normal_mode = (sw->Web_EasyMode ? "false" : "true"); char package_name[MAX_SIZE]; ZIP_PACKER *z = NULL; ToStr(ver_major, CEDAR_VER / 100); ToStr(ver_minor, CEDAR_VER % 100); ToStr(ver_build, CEDAR_BUILD); Format(package_name, sizeof(package_name), GC_SW_SOFTETHER_PREFIX "vpnclient-v%u.%02u-%u-%04u-%02u-%02u-windows.exe", CEDAR_VER / 100, CEDAR_VER % 100, CEDAR_BUILD, BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D); GetCurrentLang(¤t_lang); // Installer cache file CombinePathW(installer_src_exe, sizeof(installer_src_exe), MsGetExeDirNameW(), SW_SFX_CACHE_FILENAME); // Cab file CombinePathW(src_cab, sizeof(src_cab), MsGetExeDirNameW(), L"vpnweb.cab"); // Vpninstall file CombinePathW(vpninstall_exe, sizeof(vpninstall_exe), MsGetExeDirNameW(), L"vpninstall.exe"); // Confirm existence of the file if (IsFileExistsW(installer_src_exe) == false) { UniFormat(tmp, sizeof(tmp), _UU("SW_FILE_NOT_FOUNT"), installer_src_exe); SwPerformMsgBox(wp, MB_ICONSTOP, tmp); goto LABEL_CLEANUP; } if (IsFileExistsW(src_cab) == false) { UniFormat(tmp, sizeof(tmp), _UU("SW_FILE_NOT_FOUNT"), src_cab); SwPerformMsgBox(wp, MB_ICONSTOP, tmp); goto LABEL_CLEANUP; } if (IsFileExistsW(vpninstall_exe) == false) { UniFormat(tmp, sizeof(tmp), _UU("SW_FILE_NOT_FOUNT"), vpninstall_exe); SwPerformMsgBox(wp, MB_ICONSTOP, tmp); goto LABEL_CLEANUP; } // Read the configuration file setting_buf = ReadDumpW(sw->Web_SettingFile); if (setting_buf != NULL) { if (sw->Web_EraseSensitive) { // Remove the secret information CiEraseSensitiveInAccount(setting_buf); } } // Verify the signature of the installer cache file if (MsCheckFileDigitalSignatureW(NULL, installer_src_exe, NULL) == false) { // Installer cache file is not signed if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_INSTALLER_CACHE_IS_NOT_SIGNED")) == IDNO) { // Cancel goto LABEL_CLEANUP; } } // Read the .inf file Format(inf_path, sizeof(inf_path), "|vpninstall_%s.inf", current_lang.Name); inf_buf = ReadDump(inf_path); if (inf_buf == NULL) { goto LABEL_CLEANUP; } inf_data_size = (inf_buf->Size + 1024) * 2; inf_data = ZeroMalloc(inf_data_size); Copy(inf_data, inf_buf->Buf, inf_buf->Size); ReplaceStrEx(inf_data, inf_data_size, inf_data, "$VER_BUILD$", ver_build, false); ReplaceStrEx(inf_data, inf_data_size, inf_data, "$PACKAGE_FILENAME$", package_name, false); ReplaceStrEx(inf_data, inf_data_size, inf_data, "$NORMAL_MODE$", normal_mode, false); // Read the .htm file Format(htm_path, sizeof(htm_path), "|vpnweb_sample_%s.htm", current_lang.Name); htm_buf = ReadDump(htm_path); if (htm_buf == NULL) { goto LABEL_CLEANUP; } htm_data_size = (htm_buf->Size + 1024) * 2; htm_data = ZeroMalloc(htm_data_size); Copy(htm_data, htm_buf->Buf, htm_buf->Size); ReplaceStrEx(htm_data, htm_data_size, htm_data, "$VER_MAJOR$", ver_major, false); ReplaceStrEx(htm_data, htm_data_size, htm_data, "$VER_MINOR$", ver_minor, false); ReplaceStrEx(htm_data, htm_data_size, htm_data, "$VER_BUILD$", ver_build, false); // Creating a ZIP z = NewZipPacker(); if (ZipAddRealFileW(z, "vpnweb.cab", 0, 0, src_cab) == false || ZipAddRealFileW(z, "vpninstall.exe", 0, 0, vpninstall_exe) == false || ZipAddRealFileW(z, package_name, 0, 0, installer_src_exe) == false) { goto LABEL_CLEANUP; } ZipAddFileSimple(z, "vpninstall.inf", 0, 0, inf_data, StrLen(inf_data)); ZipAddFileSimple(z, "index.html", 0, 0, htm_data, StrLen(htm_data)); ZipAddFileSimple(z, "auto_setting.vpn", 0, 0, setting_buf->Buf, setting_buf->Size); // Export if (ZipWriteW(z, sw->Web_OutFile)) { ret = true; UniFormat(sw->FinishMsg, sizeof(sw->FinishMsg), _UU("SW_WEB_FINISHED"), sw->Web_OutFile); } LABEL_CLEANUP: FreeZipPacker(z); FreeBuf(setting_buf); FreeBuf(inf_buf); FreeBuf(htm_buf); Free(inf_data); Free(htm_data); } return ret; } // Build a simple installer bool SwEasyMain(SW *sw, WIZARD_PAGE *wp) { LIST *o; BUF *b; bool ret = false; wchar_t account_tmp[MAX_PATH]; // Validate arguments if (sw == NULL || wp == NULL) { return false; } SwPerformPrint(wp, _UU("SW_PERFORM_MSG_EASY_INIT")); o = SwNewSfxFileList(); SwAddBasicFilesToList(o, "vpnclient"); // Load a connection setting file b = ReadDumpW(sw->Easy_SettingFile); if (b != NULL) { if (sw->Easy_EraseSensitive) { // Remove secret information CiEraseSensitiveInAccount(b); } // Save to a temporary folder CombinePathW(account_tmp, sizeof(account_tmp), MsGetMyTempDirW(), L"vpn_setting.vpn"); if (DumpBufW(b, account_tmp)) { // Add a connection settings to file list of SFX Add(o, SwNewSfxFile(SW_AUTO_CONNECT_ACCOUNT_FILE_NAME, account_tmp)); if (sw->Easy_EasyMode) { // Set the connection manager to simple mode Add(o, SwNewSfxFile(SW_FLAG_EASY_MODE, account_tmp)); } if (SwCompileSfx(o, sw->Easy_OutFile)) { ret = true; } FileDeleteW(account_tmp); } FreeBuf(b); } SwFreeSfxFileList(o); if (ret) { // Completion message UniFormat(sw->FinishMsg, sizeof(sw->FinishMsg), _UU("SW_EASY_FINISHED_MSG"), sw->Easy_OutFile); } return ret; } // Installation main bool SwInstallMain(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c) { SW_TASK *t; bool ret = false; UINT i; wchar_t tmp[MAX_SIZE * 2]; bool ok; bool x64 = MsIs64BitWindows(); // Validate arguments if (sw == NULL || wp == NULL || c == NULL) { return false; } ok = true; t = NULL; // Create a Setup task SwPerformPrint(wp, _UU("SW_PERFORM_MSG_INIT_TASKS")); t = SwNewTask(); // Create a list of files to be installed SwDefineTasks(sw, t, c); if (sw->LanguageMode) { goto LABEL_CREATE_SHORTCUT; } if (sw->OnlyAutoSettingMode) { goto LABEL_IMPORT_SETTING; } // Install the SeLow if (SuIsSupportedOs(true)) { // Only in the system mode if (c->InstallService && sw->IsSystemMode) { // Not to install in the case of the VPN Client bool install_su = false; if (c->Id != SW_CMP_VPN_CLIENT) { install_su = true; } if (install_su) { bool ret; SwPerformPrint(wp, _UU("SW_PERFORM_MSG_INSTALL_SELOW")); ret = SuInstallDriver(false); if (ret == false) { if (MsIs64BitWindows() && MsIsWindows10()) { void *proc_handle = NULL; wchar_t exe[MAX_PATH]; CombinePathW(exe, sizeof(exe), MsGetExeDirNameW(), L"vpnsetup_x64.exe"); if (MsExecuteEx2W(exe, L"/SUINSTMODE:yes", &proc_handle, true)) { if (proc_handle != NULL) { MsWaitProcessExit(proc_handle); } } } } } } } // Uninstall the old MSI ok = true; if (sw->IsSystemMode && c->OldMsiList != NULL) { bool reboot_required = false; if (SwUninstallOldMsiInstalled(wp->Wizard->hWndWizard, wp, c, &reboot_required) == false) { // MSI uninstall Failed ok = false; } else if (reboot_required) { // Require to restart ok = false; sw->MsiRebootRequired = true; } } if (ok == false) { goto LABEL_CLEANUP; } // Stop the Service ok = true; if (c->InstallService) { char svc_title_name[MAX_SIZE]; wchar_t *svc_title; Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName); svc_title = _UU(svc_title_name); if (UniIsEmptyStr(svc_title) == false) { if (sw->IsSystemMode && MsIsNt()) { // WinNT and system mode if (MsIsServiceRunning(c->SvcName)) { wchar_t svc_exe[MAX_SIZE]; UINT64 giveup_tick; UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC"), svc_title); SwPerformPrint(wp, tmp); LABEL_RETRY_3: if (MsStopService(c->SvcName) == false) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_STOP_SVC_ERROR"), svc_title, c->SvcName); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; } else { if (MsIsServiceRunning(c->SvcName)) { goto LABEL_RETRY_3; } } } // Wait for 5 seconds if stopped the service SleepThread(5000); // Wait until the EXE file for the service become ready to write ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName); giveup_tick = Tick64() + (UINT64)10000; while (IsFileWriteLockedW(svc_exe)) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe); SwPerformPrint(wp, tmp); SleepThread(100); if (Tick64() >= giveup_tick) { break; } } } } else { // In the case of Win9x or user mode wchar_t svc_exe[MAX_SIZE]; UINT64 giveup_tick; // Stop the Service MsStopUserModeSvc(c->SvcName); SleepThread(3000); // Wait until the EXE file for the service become ready to write ConbinePathW(svc_exe, sizeof(svc_exe), sw->InstallDir, c->SvcFileName); giveup_tick = Tick64() + (UINT64)10000; while (IsFileWriteLockedW(svc_exe)) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WAIT_FOR_FILE_UNLOCK"), svc_exe); SwPerformPrint(wp, tmp); SleepThread(100); if (Tick64() >= giveup_tick) { break; } } } } } if (ok == false) { goto LABEL_CLEANUP; } // Examine preliminary whether files to be copied are writable successfully ok = true; SwPerformPrint(wp, _UU("SW_PERFORM_MSG_COPY_PREPARE")); for (i = 0;i < LIST_NUM(t->CopyTasks);i++) { SW_TASK_COPY *ct = LIST_DATA(t->CopyTasks, i); wchar_t fullpath[MAX_SIZE]; IO *io; bool write_ok; bool new_file; bool new_dir; UINT64 giveup_tick = Tick64() + 30000ULL; LABEL_RETRY_1: new_dir = write_ok = new_file = false; CombinePathW(fullpath, sizeof(fullpath), ct->DstDir, ct->DstFileName); if (ct->Overwrite == false) { // Do not check if overwrite is Off continue; } // If the process with the same name is running, kill it if (MsKillProcessByExeName(fullpath) != 0) { // Wait for 1 second if killed the process SleepThread(1000); } new_dir = MakeDirExW(ct->DstDir); // Write check io = FileOpenExW(fullpath, true, true); if (io == NULL) { io = FileCreateW(fullpath); new_file = true; } if (io != NULL) { // Writing OK write_ok = true; FileCloseEx(io, true); if (new_file) { FileDeleteW(fullpath); } } if (new_dir) { DeleteDirW(ct->DstDir); } if (write_ok == false) { UINT64 now = Tick64(); if (now <= giveup_tick) { // Do the auto-retry in 30 seconds SleepThread(1000); goto LABEL_RETRY_1; } // Show an error message if it fails UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WRITE_ERROR"), fullpath, c->Title); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; break; } else { // Retry goto LABEL_RETRY_1; } } } if (ok == false) { goto LABEL_CLEANUP; } // File Copy ok = true; for (i = 0;i < LIST_NUM(t->CopyTasks);i++) { SW_TASK_COPY *ct = LIST_DATA(t->CopyTasks, i); wchar_t fullpath_src[MAX_SIZE]; wchar_t fullpath_dst[MAX_SIZE]; bool skip; LABEL_RETRY_2: if (UniStartWith(ct->SrcFileName, L"|") == false) { CombinePathW(fullpath_src, sizeof(fullpath_src), ct->SrcDir, ct->SrcFileName); } else { UniStrCpy(fullpath_src, sizeof(fullpath_src), ct->SrcFileName); } CombinePathW(fullpath_dst, sizeof(fullpath_dst), ct->DstDir, ct->DstFileName); UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_COPY_FILE"), fullpath_dst); SwPerformPrint(wp, tmp); skip = false; if (ct->Overwrite == false) { if (IsFileExistsW(fullpath_dst)) { // Do nothing because the destination file already exists skip = true; } } if (skip == false) { // Create a directory if (MakeDirExW(ct->DstDir)) { SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_DIR, ct->DstDir); } // Copy if (FileCopyW(fullpath_src, fullpath_dst) == false && ct->Overwrite) { // Show an error message if it fails UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_COPY_ERROR"), fullpath_dst); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; break; } else { // Retry goto LABEL_RETRY_2; } } else { if (ct->Overwrite && ct->SetupFile == false) { SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_FILE, fullpath_dst); } } } } if (ok == false) { goto LABEL_CLEANUP; } if (sw->IsSystemMode && MsIsNt()) { // ACL settings only in the system mode for (i = 0;i < LIST_NUM(t->SetSecurityPaths);i++) { // Security Settings wchar_t *path = LIST_DATA(t->SetSecurityPaths, i); UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SET_SECURITY"), path); SwPerformPrint(wp, tmp); MsSetFileSecureAcl(path); } } // Set the language of the destination if (true) { LANGLIST current_lang; wchar_t langfilename[MAX_PATH]; Zero(¤t_lang, sizeof(current_lang)); GetCurrentLang(¤t_lang); ConbinePathW(langfilename, sizeof(langfilename), sw->InstallDir, L"lang.config"); SaveLangConfig(langfilename, current_lang.Name); } // Firewall registration if (true) { char dira[MAX_PATH]; UniToStr(dira, sizeof(dira), sw->InstallDir); RegistWindowsFirewallAllEx(dira); } if (c->Id == SW_CMP_VPN_SERVER || c->Id == SW_CMP_VPN_BRIDGE) { // Disable the off-loading MsDisableNetworkOffloadingEtc(); } // Install the service ok = true; if (c->InstallService) { char svc_title_name[MAX_SIZE]; char svc_description_name[MAX_SIZE]; wchar_t *svc_title; Format(svc_title_name, sizeof(svc_title_name), "SVC_%s_TITLE", c->SvcName); Format(svc_description_name, sizeof(svc_description_name), "SVC_%s_DESCRIPT", c->SvcName); svc_title = _UU(svc_title_name); if (UniIsEmptyStr(svc_title) == false) { if (sw->IsSystemMode == false || MsIsNt() == false) { // Just simply start in user mode or Win9x mode wchar_t fullpath[MAX_SIZE]; LABEL_RETRY_USERMODE_EXEC: CombinePathW(fullpath, sizeof(fullpath), sw->InstallDir, c->SvcFileName); if (MsExecuteW(fullpath, (MsIsNt() ? L"/usermode" : L"/win9x_service")) == false) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_USERMODE_EXEC_FAILED"), fullpath); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; } else { // Retry goto LABEL_RETRY_USERMODE_EXEC; } } else { if (MsIsNt() == false) { // Register into the registry as a background service in the case of Win9x wchar_t fullpath2[MAX_SIZE]; UniFormat(fullpath2, sizeof(fullpath2), L"\"%s\" /win9x_service", fullpath); MsRegWriteStrW(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_1, c->SvcName, fullpath2); MsRegWriteStrW(REG_LOCAL_MACHINE, WIN9X_SVC_REGKEY_2, c->SvcName, fullpath2); } } } else { // System mode UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_INSTALL_SVC"), svc_title); SwPerformPrint(wp, tmp); LABEL_RETRY_4: if (MsIsServiceInstalled(c->SvcName)) { // Stop the service if it is running by any chance MsStopService(c->SvcName); } if (MsIsServiceInstalled(c->SvcName)) { // Uninstall the old service if (MsUninstallService(c->SvcName) == false) { // Show an error message if it fails UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_UNINSTALL_FAILED"), svc_title, c->SvcName); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; } else { // Retry goto LABEL_RETRY_4; } } } if (ok) { wchar_t fullpath[MAX_SIZE]; wchar_t fullpath2[MAX_SIZE]; CombinePathW(fullpath2, sizeof(fullpath), sw->InstallDir, c->SvcFileName); UniFormat(fullpath, sizeof(fullpath), L"\"%s\" /service", fullpath2); // Install a new service if (MsInstallServiceW(c->SvcName, svc_title, _UU(svc_description_name), fullpath) == false) { // Show the error message if it fails UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_SVC_INSTALL_FAILED"), svc_title, c->SvcName); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; } else { // Retry goto LABEL_RETRY_4; } } else { wchar_t wtmp[256]; StrToUni(wtmp, sizeof(wtmp), c->SvcName); SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_SVC, wtmp); } } if (ok) { UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_START_SVC"), svc_title); SwPerformPrint(wp, tmp); MsRegWriteIntEx2(REG_LOCAL_MACHINE, "Software\\" GC_REG_COMPANY_NAME "\\Update Service Config", c->SvcName, 0, false, true); LABEL_RETRY_5: // Start the service if (MsStartService(c->SvcName) == false) { // Show the error message if it fails UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_START_SVC_ERROR"), svc_title, c->SvcName); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, tmp) != IDRETRY) { // Cancel ok = false; } else { // Retry if (MsIsServiceRunning(c->SvcName) == false) { goto LABEL_RETRY_5; } } } } } if (c->Id == SW_CMP_VPN_CLIENT) { // In the VPN Client service, wait until the service port can be connected SwWaitForVpnClientPortReady(SW_VPNCLIENT_SERVICE_WAIT_READY_TIMEOUT); } } } if (ok == false) { goto LABEL_CLEANUP; } LABEL_CREATE_SHORTCUT: // Create a shortcut SwInstallShortcuts(sw, wp, c, t); if (sw->LanguageMode) { // Update the Description of the service if in the language setting mode if (c->InstallService) { char svc_description_name[MAX_SIZE]; wchar_t *svc_description; Format(svc_description_name, sizeof(svc_description_name), "SVC_%s_DESCRIPT", c->SvcName); svc_description = _UU(svc_description_name); if (UniIsEmptyStr(svc_description) == false) { if (sw->IsSystemMode && MsIsNt()) { MsSetServiceDescription(c->SvcName, svc_description); } } } goto LABEL_REGISTER_UNINSTALL; } if (c->Id == SW_CMP_VPN_CLIENT) { // Register the UI Helper in the Run in the case of the VPN Client wchar_t fullpath[MAX_PATH]; wchar_t fullcmd[MAX_SIZE]; ConbinePathW(fullpath, sizeof(fullpath), sw->InstallDir, c->SvcFileName); UniFormat(fullcmd, sizeof(fullcmd), L"\"%s\" /uihelp", fullpath); MsRegWriteStrEx2W(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", SW_VPN_CLIENT_UIHELPER_REGVALUE, fullcmd, false, true); // Start the UI Helper MsExecuteW(fullpath, L"/uihelp"); SleepThread(3000); } if (true) { // Run the vpncmd and exit immediately wchar_t fullpath[MAX_PATH]; ConbinePathW(fullpath, sizeof(fullpath), sw->InstallDir, (MsIsX64() ? L"vpncmd_x64.exe" : L"vpncmd.exe")); RunW(fullpath, L"/?", true, false); } if (c->Id == SW_CMP_VPN_CLIENT) { wchar_t dst_vpnclient_exe[MAX_PATH]; wchar_t vpnclient_arg[MAX_SIZE]; ConbinePathW(dst_vpnclient_exe, sizeof(dst_vpnclient_exe), sw->InstallDir, c->SvcFileName); UniFormat(vpnclient_arg, sizeof(vpnclient_arg), L"\"%s\" \"%%1\"", dst_vpnclient_exe); // Register the association to .vpn file in the case of VPN Client MsRegWriteStrEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_EXT_REGKEY, NULL, SW_VPN_CLIENT_EXT_REGVALUE, false, true); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_EXT_REGKEY); MsRegNewKeyEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_EXT_REGKEY_SUB1, false, true); MsRegNewKeyEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_EXT_REGKEY_SUB2, false, true); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_EXT_REGKEY_SUB1); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_EXT_REGKEY_SUB2); MsRegWriteStrEx2(REG_LOCAL_MACHINE, SW_VPN_CLIENT_VPNFILE_REGKEY, NULL, SW_VPN_CLIENT_VPNFILE_REGVALUE, false, true); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_REGKEY); MsRegWriteStrEx2W(REG_LOCAL_MACHINE, SW_VPN_CLIENT_VPNFILE_ICON_REGKEY, NULL, dst_vpnclient_exe, false, true); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_ICON_REGKEY); MsRegWriteStrEx2W(REG_LOCAL_MACHINE, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY, NULL, vpnclient_arg, false, true); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY_SUB2); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY_SUB1); SwAddLogA(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, SW_VPN_CLIENT_VPNFILE_SHELLOPEN_CMD_REGKEY); } if (c->Id == SW_CMP_VPN_CLIENT) { // Disable the MMCSS MsSetMMCSSNetworkThrottlingEnable(false); } LABEL_IMPORT_SETTING: if (c->Id == SW_CMP_VPN_CLIENT) { if (UniIsEmptyStr(sw->auto_setting_path) == false) { if (UniIsEmptyStr(sw->vpncmgr_path) == false) { if (sw->DisableAutoImport == false) { wchar_t tmp_setting_path[MAX_PATH]; wchar_t arg[MAX_PATH]; void *handle; bool easy_mode = IsFileExists(SW_FLAG_EASY_MODE_2); // Run the vpncmgr, and start a connection by importing the connection configuration file // Store a connection setting file to stable temporally directory SwPerformPrint(wp, _UU("SW_PERFORM_MSG_IMPORTING_ACCOUNT")); ConbinePathW(tmp_setting_path, sizeof(tmp_setting_path), MsGetTempDirW(), L"vpn_auto_connect.vpn"); FileCopyW(sw->auto_setting_path, tmp_setting_path); // Start the vpncmgr UniFormat(arg, sizeof(arg), L"/%S \"%s\"", (easy_mode ? "easy" : "normal"), tmp_setting_path); handle = MsRunAsUserExW(sw->vpncmgr_path, arg, false); if (handle != NULL) { sw->HideStartCommand = true; CloseHandle(handle); } } } } } if (sw->OnlyAutoSettingMode) { goto LABEL_FINISHED; } LABEL_REGISTER_UNINSTALL: // Register the uninstall information if (sw->IsSystemMode) { char uninstall_keyname[MAX_SIZE]; wchar_t uninstall_keyname_w[MAX_SIZE]; char uninstall_version[MAX_SIZE]; wchar_t dst_setup_exe[MAX_PATH]; wchar_t setup_icon[MAX_SIZE]; wchar_t uninstaller_exe[MAX_PATH]; SYSTEMTIME st; char install_date[MAX_PATH]; SwPerformPrint(wp, _UU("SW_PERFORM_MSG_REGISTER_UNINSTALL")); Zero(&st, sizeof(st)); LocalTime(&st); Format(install_date, sizeof(install_date), "%04u/%02u/%02u", st.wYear, st.wMonth, st.wDay); CombinePathW(dst_setup_exe, sizeof(dst_setup_exe), sw->InstallDir, L"vpnsetup.exe"); Format(uninstall_keyname, sizeof(uninstall_keyname), "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\softether_" GC_SW_SOFTETHER_PREFIX "%s", c->Name); StrToUni(uninstall_keyname_w, sizeof(uninstall_keyname_w), uninstall_keyname); GetCedarVersion(uninstall_version, sizeof(uninstall_version)); // Display name MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "DisplayName", c->LongName, false, true); // Version MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "DisplayVersion", uninstall_version, false, true); // Icon UniFormat(setup_icon, sizeof(setup_icon), L"\"%s\",%u", dst_setup_exe, c->IconExeIndex); MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "DisplayIcon", setup_icon, false, true); // Information MsRegWriteIntEx2(REG_LOCAL_MACHINE, uninstall_keyname, "NoModify", 1, false, true); MsRegWriteIntEx2(REG_LOCAL_MACHINE, uninstall_keyname, "NoRepair", 1, false, true); // Link MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "HelpLink", _SS("SW_UNINSTALLINFO_URL"), false, true); MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "URLInfoAbout", _SS("SW_UNINSTALLINFO_URL"), false, true); MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "URLUpdateInfo", _SS("SW_UNINSTALLINFO_URL"), false, true); // Publisher MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "Publisher", _UU("SW_UNINSTALLINFO_PUBLISHER"), false, true); // Date of installation MsRegWriteStrEx2(REG_LOCAL_MACHINE, uninstall_keyname, "InstallDate", install_date, false, true); // Uninstaller UniFormat(uninstaller_exe, sizeof(uninstaller_exe), L"\"%s\"", dst_setup_exe); MsRegWriteStrEx2W(REG_LOCAL_MACHINE, uninstall_keyname, "UninstallString", uninstaller_exe, false, true); if (sw->LanguageMode == false) { SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_REGISTRY, uninstall_keyname_w); } } // Write the log if (true) { wchar_t log_filename[MAX_SIZE]; L_RETRY_LOG: SwPerformPrint(wp, _UU("SW_PERFORM_MSG_WRITE_LOG")); CombinePathW(log_filename, sizeof(log_filename), sw->InstallDir, L"setuplog.dat"); if (sw->LanguageMode == false) { SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_FILE, log_filename); } sw->LogFile->IsSystemMode = sw->IsSystemMode; sw->LogFile->Component = sw->CurrentComponent; sw->LogFile->Build = CEDAR_BUILD; if (SwSaveLogFile(sw, log_filename, sw->LogFile) == false) { // Show the error message if it fails UINT msgret; UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_WRITE_LOG_ERROR"), log_filename); msgret = SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_YESNO, tmp); if (msgret == IDYES) { // Retry goto L_RETRY_LOG; } } } if (true) { // Record the installed build number and directory in the registry char keyname[MAX_SIZE]; LANGLIST current_lang; LANGLIST current_os_lang; GetCurrentLang(¤t_lang); GetCurrentLang(¤t_os_lang); Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name); MsRegWriteStrEx2W(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER, keyname, "InstalledDir", sw->InstallDir, false, true); MsRegWriteIntEx2(sw->IsSystemMode ? REG_LOCAL_MACHINE : REG_CURRENT_USER, keyname, "InstalledBuild", CEDAR_BUILD, false, true); // Set the language to registry MsRegWriteStrEx2(REG_CURRENT_USER, SW_REG_KEY, "Last User Language", current_lang.Name, false, true); MsRegWriteStrEx2(REG_CURRENT_USER, SW_REG_KEY, "Last Operating System Language", current_os_lang.Name, false, true); // Save the EULA agreement record if (sw->EulaAgreed && sw->CurrentEulaHash != 0) { MsRegWriteIntEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name, sw->CurrentEulaHash, false, true); } } SwPerformPrint(wp, _UU("SW_PERFORM_MSG_UPDATING")); // Notify the update to the system MsUpdateSystem(); if (sw->LanguageMode) { // Show a message that the language configuration is complete wchar_t msg[MAX_SIZE]; UniFormat(msg, sizeof(msg), _UU("SW_LANG_OK"), c->Title, c->Title); if (c->InstallService) { UniStrCat(msg, sizeof(msg), _UU("SW_LANG_OK_SERVICE")); } if (c->Id == SW_CMP_VPN_CLIENT) { UniStrCat(msg, sizeof(msg), _UU("SW_LANG_OK_VPNCMGR")); } UniStrCpy(sw->FinishMsg, sizeof(sw->FinishMsg), msg); } LABEL_FINISHED: // Completion message SwPerformPrint(wp, _UU("SW_PERFORM_MSG_FINISHED")); ret = true; LABEL_CLEANUP: // Release the task if (t != NULL) { SwFreeTask(t); } return ret; } // Wait for that the listening port of the VPN Client service becomes available bool SwWaitForVpnClientPortReady(UINT timeout) { UINT64 start, giveup; bool ret = false; if (timeout == 0) { timeout = SW_VPNCLIENT_SERVICE_WAIT_READY_TIMEOUT; } start = Tick64(); giveup = start + (UINT64)timeout; while (Tick64() < giveup) { if (CheckTCPPortEx("localhost", CLIENT_CONFIG_PORT, 1000)) { ret = true; break; } SleepThread(1000); } return ret; } // Create a Shortcut file (Delete the old one) void SwInstallShortcuts(SW *sw, WIZARD_PAGE *wp, SW_COMPONENT *c, SW_TASK *t) { UINT i; wchar_t tmp[MAX_SIZE]; wchar_t setuplog[MAX_PATH]; LIST *o; SW_LOGFILE *oldlog; // Validate arguments if (sw == NULL || wp == NULL || c == NULL || t == NULL) { return; } // If there is an old setup log, read it CombinePathW(setuplog, sizeof(setuplog), sw->InstallDir, L"setuplog.dat"); oldlog = SwLoadLogFile(sw, setuplog); if (oldlog != NULL) { SwPerformPrint(wp, _UU("SW_PERFORM_MSG_DELETE_OLD_LINKS")); SwDeleteShortcuts(oldlog); SwFreeLogFile(oldlog); } // Remove only the shortcut setup log from the current log o = NewListFast(NULL); for (i = 0;i < LIST_NUM(sw->LogFile->LogList);i++) { SW_LOG *g = LIST_DATA(sw->LogFile->LogList, i); if (g->Type == SW_LOG_TYPE_LNK || g->Type == SW_LOG_TYPE_LNK_DIR) { Add(o, g); } } for (i = 0;i < LIST_NUM(o);i++) { SW_LOG *g = LIST_DATA(o, i); Delete(sw->LogFile->LogList, g); Free(g); } ReleaseList(o); for (i = 0;i < LIST_NUM(t->LinkTasks);i++) { SW_TASK_LINK *lt = LIST_DATA(t->LinkTasks, i); wchar_t lnk_fullpath[MAX_SIZE]; wchar_t lnk_dirname[MAX_SIZE]; wchar_t target_fullpath[MAX_SIZE]; wchar_t target_dirname[MAX_SIZE]; wchar_t icon_fullpath[MAX_SIZE]; L_RETRY_LINK: SwPerformPrint(wp, _UU("SW_PERFORM_MSG_CREATE_LINKS")); // Generate the full path of the LNK file CombinePathW(lnk_fullpath, sizeof(lnk_fullpath), lt->DestDir, lt->DestName); UniStrCat(lnk_fullpath, sizeof(lnk_fullpath), L".lnk"); // Get the directory name to be saved the LNK file GetDirNameFromFilePathW(lnk_dirname, sizeof(lnk_dirname), lnk_fullpath); // Generate the full path to the link destination CombinePathW(target_fullpath, sizeof(target_fullpath), lt->TargetDir, lt->TargetExe); // Create the full path of the icon CombinePathW(icon_fullpath, sizeof(icon_fullpath), lt->TargetDir, lt->IconExe); // Get the directory name of the full path to the link destination GetDirNameFromFilePathW(target_dirname, sizeof(target_dirname), target_fullpath); // Create a directory MakeDirExW(lnk_dirname); if (lt->NoDeleteDir == false) { SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_LNK_DIR, lnk_dirname); } // Create the LNK file if (CreateLink(lnk_fullpath, target_fullpath, target_dirname, lt->TargetArg, lt->DestDescription, icon_fullpath, lt->IconIndex) == false) { // Show the error message if it fails UINT msgret; UniFormat(tmp, sizeof(tmp), _UU("SW_PERFORM_MSG_CRAETE_LINK_ERROR"), lnk_fullpath); msgret = SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_YESNO, tmp); if (msgret == IDYES) { // Retry goto L_RETRY_LINK; } } else { SwAddLog(sw, sw->LogFile, SW_LOG_TYPE_LNK, lnk_fullpath); } } } // Search component SW_COMPONENT *SwFindComponent(SW *sw, char *name) { UINT i; // Validate arguments if (sw == NULL || IsEmptyStr(name)) { return NULL; } for (i = 0;i < LIST_NUM(sw->ComponentList);i++) { SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i); if (StrCmpi(c->Name, name) == 0) { return c; } } return NULL; } // Release the log file void SwFreeLogFile(SW_LOGFILE *logfile) { UINT i; // Validate arguments if (logfile == NULL) { return; } for (i = 0;i < LIST_NUM(logfile->LogList);i++) { SW_LOG *g = LIST_DATA(logfile->LogList, i); Free(g); } ReleaseList(logfile->LogList); Free(logfile); } // Create a new log file SW_LOGFILE *SwNewLogFile() { SW_LOGFILE *logfile = ZeroMalloc(sizeof(SW_LOGFILE)); logfile->LogList = NewListFast(NULL); return logfile; } // Read the log file SW_LOGFILE *SwLoadLogFile(SW *sw, wchar_t *filename) { FOLDER *r = NULL; FOLDER *items = NULL; FOLDER *info = NULL; UINT i; TOKEN_LIST *t = NULL; bool is_system_mode = false; char component_name[MAX_SIZE] = { 0 }; UINT build; SW_COMPONENT *c = NULL; SW_LOGFILE *ret = NULL; // Validate arguments if (sw == NULL || filename == NULL) { return NULL; } r = CfgReadW(filename); if (r == NULL) { goto LABEL_CLEANUP; } items = CfgGetFolder(r, "Items"); info = CfgGetFolder(r, "Info"); if (items == NULL || info == NULL) { goto LABEL_CLEANUP; } t = CfgEnumFolderToTokenList(items); if (t == NULL) { goto LABEL_CLEANUP; } // Mode and components is_system_mode = CfgGetBool(info, "IsSystemMode"); CfgGetStr(info, "ComponentName", component_name, sizeof(component_name)); build = CfgGetInt(info, "Build"); if (build == 0) { goto LABEL_CLEANUP; } c = SwFindComponent(sw, component_name); if (c == NULL) { goto LABEL_CLEANUP; } ret = ZeroMalloc(sizeof(SW_LOGFILE)); ret->IsSystemMode = is_system_mode; ret->Component = c; ret->Build = build; ret->LogList = NewListFast(NULL); // Item List for (i = 0;i < t->NumTokens;i++) { char *name = t->Token[i]; FOLDER *f = CfgGetFolder(items, name); if (f != NULL) { UINT type = CfgGetInt(f, "Type"); wchar_t value[MAX_SIZE]; if (CfgGetUniStr(f, "Path", value, sizeof(value))) { if (IsEmptyUniStr(value) == false && type != 0) { SW_LOG *g = ZeroMalloc(sizeof(SW_LOG)); g->Type = type; UniStrCpy(g->Path, sizeof(g->Path), value); Add(ret->LogList, g); } } } } LABEL_CLEANUP: if (r != NULL) { CfgDeleteFolder(r); } if (t != NULL) { FreeToken(t); } return ret; } // Save the log file bool SwSaveLogFile(SW *sw, wchar_t *dst_name, SW_LOGFILE *logfile) { FOLDER *r; FOLDER *items; FOLDER *info; UINT i; bool ret; // Validate arguments if (sw == NULL || dst_name == NULL || logfile == NULL) { return false; } r = CfgCreateRoot(); items = CfgCreateFolder(r, "Items"); info = CfgCreateFolder(r, "Info"); CfgAddBool(info, "IsSystemMode", logfile->IsSystemMode); CfgAddStr(info, "ComponentName", logfile->Component->Name); CfgAddInt(info, "Build", logfile->Build); for (i = 0;i < LIST_NUM(logfile->LogList);i++) { FOLDER *f; SW_LOG *g = LIST_DATA(logfile->LogList, i); char name[MAX_PATH]; Format(name, sizeof(name), "Item%04u", i); f = CfgCreateFolder(items, name); CfgAddInt(f, "Type", g->Type); CfgAddUniStr(f, "Path", g->Path); } ret = CfgSaveExW3(NULL, r, dst_name, NULL, true); CfgDeleteFolder(r); return ret; } // Display the string to the status screen void SwPerformPrint(WIZARD_PAGE *wp, wchar_t *str) { SW_UI ui; // Validate arguments if (wp == NULL || str == NULL) { return; } Zero(&ui, sizeof(ui)); ui.Type = SW_UI_TYPE_PRINT; ui.Message = str; SwInteractUi(wp, &ui); } // Show a message box on the screen UINT SwPerformMsgBox(WIZARD_PAGE *wp, UINT flags, wchar_t *msg) { SW_UI ui; // Validate arguments if (wp == NULL || msg == NULL) { return 0; } Zero(&ui, sizeof(ui)); ui.Type = SW_UI_TYPE_MSGBOX; ui.Message = msg; ui.Param = flags; return SwInteractUi(wp, &ui); } // Call the UI interaction UINT SwInteractUi(WIZARD_PAGE *wp, SW_UI *ui) { // Validate arguments if (wp == NULL || ui == NULL) { return 0; } SendMsg(wp->hWndPage, 0, WM_SW_INTERACT_UI, 0xCAFE, (LPARAM)ui); SleepThread(50); return ui->RetCode; } // UI interaction is called void SwInteractUiCalled(HWND hWnd, SW *sw, WIZARD_PAGE *wp, SW_UI *ui) { // Validate arguments if (hWnd == NULL || sw == NULL || wp == NULL || ui == NULL) { return; } switch (ui->Type) { case SW_UI_TYPE_PRINT: // Display the message SetText(hWnd, S_STATUS, ui->Message); break; case SW_UI_TYPE_MSGBOX: // Show a message box ui->RetCode = MsgBox(hWnd, ui->Param, ui->Message); break; case SW_UI_TYPE_FINISH: // Complete PostMessageA(hWnd, WM_SW_EXIT, 0xCAFE, 1); break; case SW_UI_TYPE_ERROR: // Error PostMessageA(hWnd, WM_SW_EXIT, 0xCAFE, 0); break; } } // Initialize the setup process screen void SwPerformInit(HWND hWnd, SW *sw, WIZARD_PAGE *wp) { // Validate arguments if (hWnd == NULL || sw == NULL || wp == NULL) { return; } DlgFont(hWnd, S_INFO, 10, true); if (sw->EasyMode) { SetIcon(hWnd, S_ICON, ICO_SETUP); SetText(hWnd, S_INFO, _UU("SW_PERFORM_MSG_EASY_INFO")); } else if (sw->WebMode) { SetIcon(hWnd, S_ICON, ICO_SETUP); SetText(hWnd, S_INFO, _UU("SW_PERFORM_MSG_WEB_INFO")); } else { SetIcon(hWnd, S_ICON, sw->CurrentComponent->Icon); FormatText(hWnd, S_INFO, sw->CurrentComponent->Title); } SetTextA(hWnd, S_STATUS, ""); if (MsIsWinXPOrWinVista()) { // Display the progress bar for Windows XP or later SendMsg(hWnd, IDC_PROGRESS1, PBM_SETMARQUEE, TRUE, 100); SetStyle(hWnd, IDC_PROGRESS1, PBS_MARQUEE); } else { // Hide the progress bar in the case of Windows 2000 or earlier Hide(hWnd, IDC_PROGRESS1); } } // Do the set-up process UINT SwPerform(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: SwPerformInit(hWnd, sw, wizard_page); break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, false, false, false, false); SetTimer(hWnd, 1, 100, NULL); break; case WM_TIMER: KillTimer(hWnd, 1); // Main thread execution if (sw->PerformThread == NULL) { sw->PerformThread = NewThread(SwPerformThread, wizard_page); } break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: break; case WM_WIZ_BACK: break; case WM_SW_INTERACT_UI: // UI interaction is called if (wParam == 0xCAFE) { SwInteractUiCalled(hWnd, sw, wizard_page, (SW_UI *)lParam); } break; case WM_COMMAND: switch (wParam) { } break; case WM_SW_EXIT: // Close this screen since the process completed if (wParam == 0xCAFE) { JumpWizard(wizard_page, (lParam == 0 ? D_SW_ERROR : D_SW_FINISH)); if (sw->PerformThread != NULL) { WaitThread(sw->PerformThread, INFINITE); ReleaseThread(sw->PerformThread); sw->PerformThread = NULL; } } break; } return 0; } // Final confirmation screen UINT SwReady(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: FormatText(hWnd, S_INFO, sw->CurrentComponent->Title); break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, true, true, false); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: return D_SW_PERFORM; case WM_WIZ_BACK: return D_SW_DIR; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Uninstall all the old MSI products bool SwUninstallOldMsiInstalled(HWND hWnd, WIZARD_PAGE *wp, SW_COMPONENT *c, bool *reboot_required) { UINT i; bool dummy_bool = false; // Validate arguments if (c == NULL || wp == NULL) { return true; } if (reboot_required == NULL) { reboot_required = &dummy_bool; } *reboot_required = false; if (c->OldMsiList == NULL) { return true; } for (i = 0;i < c->NumOldMsi;i++) { SW_OLD_MSI *m = &c->OldMsiList[i]; wchar_t tmp[MAX_SIZE]; if (MsGetMsiInstalledDir(m->ComponentCode, tmp, sizeof(tmp))) { bool rr = false; wchar_t msg[MAX_SIZE]; LABEL_RETRY: UniFormat(msg, sizeof(msg), _UU("SW_PERFORM_MSG_UNINSTALL_MSI"), c->Title); SwPerformPrint(wp, msg); if (MsMsiUninstall(m->ProductCode, hWnd, &rr) == false) { UniFormat(msg, sizeof(msg), _UU("SW_MSI_UNINSTALL_FAILED"), c->Title, m->ProductCode); if (SwPerformMsgBox(wp, MB_ICONEXCLAMATION | MB_RETRYCANCEL, msg) == IDRETRY) { goto LABEL_RETRY; } return false; } else { if (rr) { *reboot_required = true; return true; } } } } return true; } // Get the directory where the old MSI products are installed wchar_t *SwGetOldMsiInstalledDir(SW_COMPONENT *c) { UINT i; // Validate arguments if (c == NULL) { return NULL; } if (c->OldMsiList == NULL) { return NULL; } for (i = 0;i < c->NumOldMsi;i++) { SW_OLD_MSI *m = &c->OldMsiList[i]; wchar_t tmp[MAX_SIZE]; if (MsGetMsiInstalledDir(m->ComponentCode, tmp, sizeof(tmp))) { return UniCopyStr(tmp); } } return NULL; } // Initialize the default installation directory void SwInitDefaultInstallDir(SW *sw) { char keyname[MAX_SIZE]; wchar_t *reg_dir_system; wchar_t *reg_dir_user; wchar_t *msi_dir_system = NULL; // Validate arguments if (sw == NULL) { return; } msi_dir_system = SwGetOldMsiInstalledDir(sw->CurrentComponent); Format(keyname, sizeof(keyname), "%s\\%s", SW_REG_KEY, sw->CurrentComponent->Name); if (UniIsEmptyStr(msi_dir_system) == false) { MsRegWriteStrEx2W(REG_LOCAL_MACHINE, keyname, "InstalledDir", msi_dir_system, false, true); } reg_dir_system = MsRegReadStrEx2W(REG_LOCAL_MACHINE, keyname, "InstalledDir", false, true); reg_dir_user = MsRegReadStrEx2W(REG_CURRENT_USER, keyname, "InstalledDir", false, true); // Generate a directory name in the case of system mode CombinePathW(sw->DefaultInstallDir_System, sizeof(sw->DefaultInstallDir_System), MsGetProgramFilesDirX64W(), sw->CurrentComponent->DefaultDirName); // Generate a directory name in the case of user mode CombinePathW(sw->DefaultInstallDir_User, sizeof(sw->DefaultInstallDir_User), MsGetPersonalAppDataDirW(), sw->CurrentComponent->DefaultDirName); if (UniIsEmptyStr(reg_dir_system) == false) { UniStrCpy(sw->DefaultInstallDir_System, sizeof(sw->DefaultInstallDir_System), reg_dir_system); } if (UniIsEmptyStr(reg_dir_user) == false) { UniStrCpy(sw->DefaultInstallDir_User, sizeof(sw->DefaultInstallDir_User), reg_dir_user); } if (MsIsNt() == false) { // Set to system mode for Win9x sw->IsSystemMode = true; } if (MsIsAdmin() == false) { sw->IsAvailableSystemMode = false; sw->IsAvailableUserMode = true; } else if (MsIsNt() == false) { sw->IsAvailableSystemMode = true; sw->IsAvailableUserMode = false; } else { sw->IsAvailableSystemMode = true; sw->IsAvailableUserMode = !sw->CurrentComponent->SystemModeOnly; } sw->ShowWarningForUserMode = sw->CurrentComponent->InstallService; Free(reg_dir_system); Free(reg_dir_user); Free(msi_dir_system); } // Update the installation directory setting screen void SwDirUpdate(HWND hWnd, SW *sw, WIZARD_PAGE *wizard_page) { bool user_mode_selected; bool show_custom; bool change_dir; // Validate arguments if (hWnd == NULL || sw == NULL || wizard_page == NULL) { return; } change_dir = IsChecked(hWnd, R_CUSTOM); SetShow(hWnd, S_DEST, change_dir); SetShow(hWnd, E_DIR, change_dir); SetShow(hWnd, B_BROWSE, change_dir); show_custom = IsChecked(hWnd, R_SHOWCUSTOM); SetShow(hWnd, R_FOR_SYSTEM, show_custom); SetShow(hWnd, R_FOR_USER, show_custom); user_mode_selected = IsChecked(hWnd, R_FOR_USER); SetText(hWnd, R_DEFAULT, user_mode_selected ? sw->DefaultInstallDir_User : sw->DefaultInstallDir_System); if (user_mode_selected == false) { Hide(hWnd, S_WARNING); Hide(hWnd, S_WARNING2); } else { SetShow(hWnd, S_WARNING, sw->ShowWarningForUserMode); SetShow(hWnd, S_WARNING2, sw->ShowWarningForUserMode); } SetEnable(hWnd, R_SHOWCUSTOM, !user_mode_selected); DlgFont(hWnd, R_DEFAULT, 0, !change_dir); } // Check the directory name planned to be created newly bool SwCheckNewDirName(wchar_t *name) { char tmp[MAX_SIZE]; UCHAR rand[16]; wchar_t testname[MAX_SIZE]; IO *io; bool new_dir; // Validate arguments if (name == NULL) { return false; } // Create a directory new_dir = MakeDirExW(name); // Writes the appropriate files Rand(rand, sizeof(rand)); BinToStr(tmp, sizeof(tmp), rand, sizeof(rand)); UniFormat(testname, sizeof(testname), L"%s\\%S.dat", name, tmp); io = FileCreateW(testname); if (io == NULL) { return false; } FileClose(io); FileDeleteW(testname); if (new_dir) { DeleteDirW(name); } return true; } // Set the installation directory UINT SwDir(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; wchar_t tmp[MAX_SIZE]; wchar_t setuplog[MAX_SIZE]; wchar_t *s; SW_LOGFILE *logfile; bool is_system_mode; bool skip_ver_check = false; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: SetIcon(hWnd, S_ICON, sw->CurrentComponent->Icon); SwInitDefaultInstallDir(sw); FormatText(hWnd, S_INFO, sw->CurrentComponent->Title); FormatText(hWnd, R_FOR_USER, MsGetUserNameW()); FormatText(hWnd, S_WARNING, MsGetUserNameW(), sw->CurrentComponent->Title); Check(hWnd, R_FOR_SYSTEM, sw->IsSystemMode); Check(hWnd, R_FOR_USER, !sw->IsSystemMode); if (sw->IsSystemMode == false) { Check(hWnd, R_SHOWCUSTOM, true); } SetText(hWnd, E_DIR, sw->IsSystemMode ? sw->DefaultInstallDir_System : sw->DefaultInstallDir_User); Check(hWnd, R_DEFAULT, true); SetEnable(hWnd, R_FOR_SYSTEM, sw->IsAvailableSystemMode); SetEnable(hWnd, R_FOR_USER, sw->IsAvailableUserMode); SwDirUpdate(hWnd, sw, wizard_page); break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, false, true, false); SwDirUpdate(hWnd, sw, wizard_page); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: if (IsChecked(hWnd, R_CUSTOM)) { GetTxt(hWnd, E_DIR, tmp, sizeof(tmp)); } else { if (IsChecked(hWnd, R_FOR_SYSTEM)) { UniStrCpy(tmp, sizeof(tmp), sw->DefaultInstallDir_System); } else { UniStrCpy(tmp, sizeof(tmp), sw->DefaultInstallDir_User); } } is_system_mode = IsChecked(hWnd, R_FOR_SYSTEM); if (is_system_mode == false) { if (sw->CurrentComponent->InstallService) { if (MsIsServiceInstalled(sw->CurrentComponent->SvcName)) { // If the type of installation is user mode and the same software // is running in system mode already, warn about it if (MsgBoxEx(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_SYSTEM_MODE_ALREADY_INSTALLED"), sw->CurrentComponent->Title) == IDNO) { break; } } } } UniTrim(tmp); Win32NukuEnW(tmp, sizeof(tmp), tmp); // Check Length if (UniStrLen(tmp) > 110) { MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_MORE_THAN_110")); FocusEx(hWnd, E_DIR); break; } // Check whether it's a full path if (UniStartWith(tmp, L"\\\\") == false && (tmp[1] != L':' || tmp[2] != L'\\')) { MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_IS_NOT_FULLPATH"), tmp); FocusEx(hWnd, E_DIR); break; } NormalizePathW(tmp, sizeof(tmp), tmp); // Check the type of the drive if (IsChecked(hWnd, R_FOR_SYSTEM)) { // System mode service is installed only on the hard disk bool ok = true; if (UniStartWith(tmp, L"\\\\")) { ok = false; } else { char tmpa[MAX_SIZE]; UINT ret; UniToStr(tmpa, sizeof(tmpa), tmp); tmpa[3] = 0; ret = GetDriveTypeA(tmpa); if (ret != DRIVE_FIXED && ret != DRIVE_RAMDISK) { ok = false; } } if (ok == false) { MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_IS_NOT_HDD"), tmp, sw->CurrentComponent->Title); FocusEx(hWnd, E_DIR); break; } } // Write check if (SwCheckNewDirName(tmp) == false) { MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_WRITE_ERROR"), tmp); FocusEx(hWnd, E_DIR); break; } // Analyze if there is a setuplog.dat on destination CombinePathW(setuplog, sizeof(setuplog), tmp, L"setuplog.dat"); logfile = SwLoadLogFile(sw, setuplog); if (logfile == NULL && IsFileExistsW(setuplog)) { MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_DST_IS_BROKEN"), setuplog); FocusEx(hWnd, E_DIR); break; } if (logfile != NULL && (logfile->Build > CEDAR_BUILD) && UniIsEmptyStr(sw->auto_setting_path) == false && sw->CurrentComponent->Id == SW_CMP_VPN_CLIENT && logfile->Component->Id == SW_CMP_VPN_CLIENT) { // In the case of the VPN Client, show a message if a newer version is installed and // the automatic connection setting by simple installer should be applied if (MsgBox(hWnd, MB_ICONINFORMATION | MB_OKCANCEL, _UU("SW_DIR_DST_IS_NEWER_2")) == IDCANCEL) { // Cancel FocusEx(hWnd, E_DIR); break; } skip_ver_check = true; } if (logfile != NULL) { wchar_t *errmsg = NULL; if (logfile->Component != sw->CurrentComponent) { errmsg = _UU("SW_DIR_DST_IS_OTHER_PRODUCT"); } else if ((skip_ver_check == false) && (logfile->Build > CEDAR_BUILD)) { errmsg = _UU("SW_DIR_DST_IS_NEWER"); } else if (logfile->IsSystemMode && is_system_mode == false) { errmsg = _UU("SW_DIR_DST_IS_SYSTEM_MODE"); } else if (logfile->IsSystemMode == false && is_system_mode) { errmsg = _UU("SW_DIR_DST_IS_USER_MODE"); } SwFreeLogFile(logfile); if (errmsg != NULL) { MsgBox(hWnd, MB_ICONEXCLAMATION, errmsg); FocusEx(hWnd, E_DIR); break; } } // Check whether installation destination and installation source are not same if (UniStrCmpi(tmp, sw->InstallSrc) == 0) { MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_DIR_DST_IS_SAME_TO_SRC"), tmp); FocusEx(hWnd, E_DIR); break; } UniStrCpy(sw->InstallDir, sizeof(sw->InstallDir), tmp); sw->IsSystemMode = IsChecked(hWnd, R_FOR_SYSTEM); sw->OnlyAutoSettingMode = skip_ver_check; return D_SW_READY; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { case R_DEFAULT: case R_CUSTOM: case R_SHOWCUSTOM: case R_FOR_SYSTEM: case R_FOR_USER: SwDirUpdate(hWnd, sw, wizard_page); break; } switch (wParam) { case R_FOR_SYSTEM: SetText(hWnd, E_DIR, sw->DefaultInstallDir_System); break; case R_FOR_USER: SetText(hWnd, E_DIR, sw->DefaultInstallDir_User); break; case B_BROWSE: GetTxt(hWnd, E_DIR, tmp, sizeof(tmp)); s = FolderDlgW(hWnd, _UU("SW_DIR_SELECT"), tmp); if (s != NULL) { if (UniEndWith(s, sw->CurrentComponent->DefaultDirName)) { UniStrCpy(tmp, sizeof(tmp), s); } else { CombinePathW(tmp, sizeof(tmp), s, sw->CurrentComponent->DefaultDirName); } SetText(hWnd, E_DIR, tmp); FocusEx(hWnd, E_DIR); Free(s); } break; } break; } return 0; } // Warning screen UINT SwWarning(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; BUF *b; UCHAR c = 0; wchar_t *str; char warning_filename[MAX_PATH]; LANGLIST t; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: break; case WM_WIZ_SHOW: DlgFont(hWnd, B_AGREE, 0, true); GetCurrentLang(&t); SetFont(hWnd, E_TEXT, GetFont((t.Id == SE_LANG_JAPANESE && MsIsWindows7()) ? "Meiryo UI" : NULL, 10, false , false, false, false)); Format(warning_filename, sizeof(warning_filename), "|warning_%s.txt", t.Name); b = ReadDump(warning_filename); SeekBuf(b, b->Size, 0); c = 0; WriteBuf(b, &c, 1); str = CopyUtfToUni(b->Buf); UniIsEmptyStr(str); SetText(hWnd, E_TEXT, str); FreeBuf(b); Free(str); UnselectEdit(hWnd, E_TEXT); Focus(hWnd, E_TEXT); SetWizardButton(wizard_page, true, true, true, false); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: if (SwEnterSingle(sw) == false) { // Multiple-starts prevention MsgBox(hWnd, MB_ICONINFORMATION, _UU("SW_OTHER_INSTANCE_EXISTS")); break; } return D_SW_DIR; case WM_WIZ_BACK: return D_SW_EULA; case WM_COMMAND: break; } return 0; } // Update the license agreement screen void SwEulaUpdate(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page) { // Validate arguments if (hWnd == NULL || sw == NULL || wizard == NULL || wizard_page == NULL) { return; } sw->EulaAgreed = IsChecked(hWnd, B_AGREE); if (sw->EulaAgreed == false) { // Delete the agreement record in the case of non-agreement for the EULA MsRegDeleteValueEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name, false, true); } SetWizardButton(wizard_page, sw->EulaAgreed, true, true, false); } // License Agreement UINT SwEula(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; BUF *b; UCHAR c = 0; wchar_t *str; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: break; case WM_WIZ_SHOW: SetFont(hWnd, E_TEXT, GetFont((MsIsWindows7() ? "Segoe UI" : "Verdana"), 10, false, false, false, false)); //DlgFont(hWnd, B_AGREE, 10, true); b = ReadDump("|eula.txt"); SeekBuf(b, b->Size, 0); c = 0; WriteBuf(b, &c, 1); str = CopyUtfToUni(b->Buf); UniIsEmptyStr(str); SetText(hWnd, E_TEXT, str); sw->CurrentEulaHash = HashToUINT(b->Buf, b->Size); FreeBuf(b); Free(str); if (sw->CurrentComponent != NULL && sw->CurrentEulaHash != 0 && sw->CurrentEulaHash == MsRegReadIntEx2(REG_CURRENT_USER, SW_REG_KEY_EULA, sw->CurrentComponent->Name, false, true)) { // Check the consent check box in advance if the user accepts the same EULA during the last installation sw->EulaAgreed = true; } Check(hWnd, B_AGREE, sw->EulaAgreed); UnselectEdit(hWnd, E_TEXT); Focus(hWnd, E_TEXT); SwEulaUpdate(hWnd, sw, wizard, wizard_page); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: SwEulaUpdate(hWnd, sw, wizard, wizard_page); if (sw->EulaAgreed) { return D_SW_WARNING; } break; case WM_WIZ_BACK: sw->EulaAgreed = false; return D_SW_COMPONENTS; case WM_COMMAND: switch (wParam) { case B_AGREE: SwEulaUpdate(hWnd, sw, wizard, wizard_page); break; } break; } return 0; } // Initialize a component list void SwComponentsInit(HWND hWnd, SW *sw) { LVB *b; UINT i; SW_COMPONENT *default_select = NULL; // Validate arguments if (hWnd == NULL || sw == NULL) { return; } LvReset(hWnd, L_LIST); b = LvInsertStart(); for (i = 0;i < LIST_NUM(sw->ComponentList);i++) { SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i); if (c->Detected) { wchar_t tmp[MAX_SIZE]; UniFormat(tmp, sizeof(tmp), L" %s", c->Title); LvInsertAdd(b, c->Icon, c, 1, tmp); if (c->SystemModeOnly == false || MsIsAdmin()) { if (default_select == NULL) { default_select = c; } } } } LvInsertEnd(b, hWnd, L_LIST); if (sw->CurrentComponent == NULL) { LvSelectByParam(hWnd, L_LIST, default_select); } else { LvSelectByParam(hWnd, L_LIST, sw->CurrentComponent); } Focus(hWnd, L_LIST); } // Update the Component Selection screen void SwComponentsUpdate(HWND hWnd, SW *sw, WIZARD *wizard, WIZARD_PAGE *wizard_page) { SW_COMPONENT *c; // Validate arguments if (hWnd == NULL || sw == NULL || wizard == NULL || wizard_page == NULL) { return; } c = (SW_COMPONENT *)LvGetSelectedParam(hWnd, L_LIST); if (c == NULL) { Hide(hWnd, S_TITLE); Hide(hWnd, S_DESCRIPTION); Hide(hWnd, S_ICON); SetWizardButton(wizard_page, false, true, true, false); } else { wchar_t tmp[MAX_SIZE]; if (c->SystemModeOnly && MsIsAdmin() == false) { // Components to be installed only in system mode is set to unselectable SetText(hWnd, S_TITLE, _UU("SW_COMPONENTS_REQUIRE_ADMIN")); UniFormat(tmp, sizeof(tmp), _UU("SW_COMPONENTS_REQUIRE_ADMIN_TEXT"), c->Title); SetText(hWnd, S_DESCRIPTION, tmp); SetIcon(hWnd, S_ICON, ICO_WARNING); SetWizardButton(wizard_page, false, true, true, false); } else { // Show the description of the component UniFormat(tmp, sizeof(tmp), _UU("SW_COMPONENTS_ABOUT_TAG"), c->Title); SetText(hWnd, S_TITLE, tmp); SetText(hWnd, S_DESCRIPTION, c->Description); SetIcon(hWnd, S_ICON, c->Icon); SetWizardButton(wizard_page, true, true, true, false); } Show(hWnd, S_TITLE); Show(hWnd, S_DESCRIPTION); Show(hWnd, S_ICON); } } // Component selection screen UINT SwComponents(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; NMHDR *n; SW_COMPONENT *c; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: LvInitEx2(hWnd, L_LIST, false, true); if (MsIsVista()) { SetFont(hWnd, L_LIST, GetMeiryoFontEx(12)); SetFont(hWnd, S_TITLE, GetMeiryoFontEx(11)); } else { DlgFont(hWnd, L_LIST, 12, false); DlgFont(hWnd, S_TITLE, 11, false); } LvInsertColumn(hWnd, L_LIST, 0, L"Component", 515); break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, true, true, false); SwComponentsInit(hWnd, sw); SwComponentsUpdate(hWnd, sw, wizard, wizard_page); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: c = (SW_COMPONENT *)LvGetSelectedParam(hWnd, L_LIST); if (c != NULL) { if (SwCheckOs(sw, c) == false) { // OS Check Failed MsgBoxEx(hWnd, MB_ICONEXCLAMATION, _UU("SW_OS_FAILED"), c->Title); break; } sw->CurrentComponent = c; if (sw->CurrentComponent->SystemModeOnly == false || MsIsAdmin()) { if (sw->CurrentComponent->Id == SW_CMP_VPN_SERVER && MsIsServiceInstalled(GC_SVC_NAME_VPNBRIDGE)) { // The user is trying to install the VPN Server but, VPN Bridge already exists if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_NOTICE_VPNBRIDGE_IS_INSTALLED")) == IDNO) { break; } } else if (sw->CurrentComponent->Id == SW_CMP_VPN_BRIDGE && MsIsServiceInstalled(GC_SVC_NAME_VPNSERVER)) { // The user is trying to install the VPN Bridge, but a VPN Server already exists if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_YESNO | MB_DEFBUTTON2, _UU("SW_NOTICE_VPNSERVER_IS_INSTALLED")) == IDNO) { break; } } // Continue return D_SW_EULA; } } break; case WM_WIZ_BACK: if (MsIsAdmin()) { return D_SW_WELCOME; } else { return D_SW_MODE; } break; case WM_COMMAND: switch (wParam) { } break; case WM_NOTIFY: n = (NMHDR *)lParam; switch (n->idFrom) { case L_LIST: switch (n->code) { case LVN_ITEMCHANGED: SwComponentsUpdate(hWnd, sw, wizard, wizard_page); break; } break; } break; } return 0; } // Screen that is displayed when the user don't have administrative privileges UINT SwNotAdminDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: break; case WM_WIZ_SHOW: FormatText(hWnd, S_INFO, MsGetUserNameW()); SetShow(hWnd, S_INFO2, (sw->UninstallMode ? false : true)); SetWizardButton(wizard_page, true, ((sw->UninstallMode && sw->IsReExecForUac) ? false : true), true, true); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: break; case WM_WIZ_BACK: if (sw->UninstallMode == false) { return D_SW_MODE; } else { return D_SW_UNINST1; } break; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Choose the setup mode UINT SwModeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: break; case WM_WIZ_SHOW: SetWizardButton(wizard_page, true, true, true, false); FormatText(hWnd, S_USER, MsGetUserNameW()); // Choose the initial state Check(hWnd, R_SYSTEM, sw->IsSystemMode); Check(hWnd, R_USER, !sw->IsSystemMode); Focus(hWnd, (sw->IsSystemMode ? R_SYSTEM : R_USER)); sw->DoubleClickBlocker = false; SetUacIcon(hWnd, S_UAC); break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: // Mode sw->IsSystemMode = IsChecked(hWnd, R_SYSTEM); if (sw->DoubleClickBlocker) { break; } sw->DoubleClickBlocker = true; if (sw->IsSystemMode) { if (MsIsVista() && MsIsAdmin() == false && sw->IsReExecForUac == false) { // If UAC is available and this isn't invoked via UAC, // give the user a chance to get administrator privileges on UAC start again if (SwReExecMyself(sw, NULL, true)) { // Terminate itself if it succeeds to start the child process CloseWizard(wizard_page); } else { // Jump to screen prompts to re-start as a administrator if it fails to start the child process return D_SW_NOT_ADMIN; } } else { if (MsIsAdmin()) { // Jump to the component list screen if the user has administrator privileges return D_SW_COMPONENTS; } else { // Jump to screen prompts to re-start as a administrator if the user doesn't have administrator privileges return D_SW_NOT_ADMIN; } } } else { // Jump to the component list screen return D_SW_COMPONENTS; } break; case WM_WIZ_BACK: return D_SW_WELCOME; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Welcome screen UINT SwWelcomeDlg(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, WIZARD *wizard, WIZARD_PAGE *wizard_page, void *param) { SW *sw = (SW *)param; // Validate arguments if (hWnd == NULL || sw == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: break; case WM_WIZ_SHOW: DlgFont(hWnd, S_WELCOME, 10, false); DlgFont(hWnd, S_TITLE, 11, true); SetWizardButtonEx(wizard_page, true, false, true, false, true); sw->DoubleClickBlocker = false; break; case WM_WIZ_HIDE: break; case WM_CLOSE: break; case WM_WIZ_NEXT: if (IsFileExistsW(L"@install_src.dat") == false) { // Vpnsetup.exe is launched from other than the installation source MsgBoxEx(hWnd, MB_ICONSTOP, _UU("SW_NOT_INSTALL_SRC")); break; } if (MsIsKB3033929RequiredAndMissing()) { // KB3033929 is missing if (MsgBoxEx(hWnd, MB_ICONINFORMATION | MB_OKCANCEL, _UU("SW_KB3033929_REQUIRED")) == IDCANCEL) { break; } } if (sw->DoubleClickBlocker) { break; } sw->DoubleClickBlocker = true; if (MsIsAdmin() == false) { if (MsIsVista()) { if (sw->IsReExecForUac == false) { // If there is no Admin privileges in Vista or later, attempt to acquire Admin rights by UAC first during the first run if (SwReExecMyself(sw, NULL, true)) { // Terminate itself if it succeeds to start the child process CloseWizard(wizard_page); break; } else { // Jump to mode selection screen if it fails to start the // child process (including user presses the cancel of UAC) return D_SW_MODE; } } else { // Jump to mode selection screen when the user don't have Admin rights after being activated by UAC return D_SW_MODE; } } else { // Jump to the mode selection screen in the case of older than Vista return D_SW_MODE; } } else { // Skip to the component list screen if the user has Admin privileges return D_SW_COMPONENTS; } break; case WM_WIZ_BACK: break; case WM_COMMAND: switch (wParam) { } break; } return 0; } // Restart itself bool SwReExecMyself(SW *sw, wchar_t *additional_params, bool as_admin) { wchar_t *current_params; wchar_t new_param[MAX_SIZE]; void *handle; bool ret = false; // Validate arguments if (sw == NULL) { return false; } if (sw->ReExecProcessHandle != NULL) { return false; } current_params = GetCommandLineUniStr(); if (IsEmptyUniStr(additional_params)) { additional_params = L""; } UniFormat(new_param, sizeof(new_param), L"%s %s %s", current_params, (as_admin ? L"/UAC:true" : L""), additional_params); UniTrim(new_param); handle = NULL; ret = MsExecuteEx2W(MsGetExeFileNameW(), new_param, &handle, as_admin); Free(current_params); if (ret == false) { return false; } sw->ReExecProcessHandle = handle; return true; } // Show the UI void SwUiMain(SW *sw) { WIZARD *w; wchar_t verstr[MAX_SIZE]; char ver[MAX_SIZE]; // Validate arguments if (sw == NULL) { return; } // Define the wizard UI GetCedarVersion(ver, sizeof(ver)); UniFormat(verstr, sizeof(verstr), _UU("SW_TITLE"), ver); // DO NOT REMOVE THIS INDICATION !!! UniStrCat(verstr, sizeof(verstr), L" - Customized Version"); w = NewWizard(ICO_SETUP, BMP_SELOGO49x49, verstr, sw); w->CloseConfirmMsg = _UU("SW_EXIT_CONFIRM"); AddWizardPage(w, NewWizardPage(D_SW_WELCOME, SwWelcomeDlg, _UU("SW_WELCOME_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_MODE, SwModeDlg, _UU("SW_MODE_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_NOT_ADMIN, SwNotAdminDlg, _UU("SW_NOT_ADMIN_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_COMPONENTS, SwComponents, _UU("SW_COMPONENTS_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_EULA, SwEula, _UU("SW_EULA_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_WARNING, SwWarning, _UU("SW_WARNING_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_DIR, SwDir, _UU("SW_DIR_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_READY, SwReady, _UU("SW_READY_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_PERFORM, SwPerform, _UU("SW_PERFORM_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_ERROR, SwError, _UU("SW_ERROR_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_FINISH, SwFinish, _UU("SW_FINISH_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_UNINST1, SwUninst1, _UU("SW_UNINST1_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_LANG1, SwLang1, _UU("SW_LANG1_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_EASY1, SwEasy1, _UU("SW_EASY1_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_EASY2, SwEasy2, _UU("SW_EASY2_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_WEB1, SwWeb1, _UU("SW_WEB1_TITLE"))); AddWizardPage(w, NewWizardPage(D_SW_WEB2, SwWeb2, _UU("SW_WEB2_TITLE"))); if (MsIsVista()) { w->IsAreoStyle = true; } if (sw->UninstallMode) { // Uninstall mode UINT start_page = D_SW_UNINST1; if (sw->IsReExecForUac) { // In the case of this have been executed for UAC if (MsIsAdmin()) { // Uninstall start_page = D_SW_PERFORM; } else { // Error screen start_page = D_SW_NOT_ADMIN; } } ShowWizard(NULL, w, start_page); } else if (sw->WebMode) { // Web installer creation mode UINT start_page = D_SW_WEB1; ShowWizard(NULL, w, start_page); } else if (sw->EasyMode) { // Simple installer creation mode UINT start_page = D_SW_EASY1; ShowWizard(NULL, w, start_page); } else if (sw->LanguageMode) { // Language setting mode UINT start_page = D_SW_LANG1; w->CloseConfirmMsg = NULL; if (sw->IsReExecForUac) { // In the case of this have been executed for UAC if (MsIsAdmin()) { // Do the language setting start_page = D_SW_PERFORM; } else { // Error screen start_page = D_SW_NOT_ADMIN; } } else { if (sw->LangNow) { // If not via UAC but Lang Now is set start_page = D_SW_PERFORM; } } if (sw->SetLangAndReboot && sw->LangNow == false) { // Restart myself immediately by changing the lang.config LIST *o = LoadLangList(); if (o == NULL) { MsgBox(NULL, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED")); } else { LANGLIST *new_lang = GetLangById(o, sw->LangId); LANGLIST old_lang; Zero(&old_lang, sizeof(old_lang)); GetCurrentLang(&old_lang); if (new_lang == NULL) { MsgBox(NULL, MB_ICONSTOP, _UU("SW_LANG_LIST_LOAD_FAILED")); } else { if (SaveLangConfigCurrentDir(new_lang->Name) == false) { MsgBox(NULL, MB_ICONSTOP, _UU("SW_LANG_SET_FAILED")); } else { if (SwReExecMyself(sw, L"/LANGNOW:true ", false) == false) { SaveLangConfigCurrentDir(old_lang.Name); MsgBox(NULL, MB_ICONSTOP, _UU("SW_CHILD_PROCESS_ERROR")); sw->ExitCode = SW_EXIT_CODE_INTERNAL_ERROR; } } } FreeLangList(o); } } else { // Show the wizard ShowWizard(NULL, w, start_page); } } else { // Installation mode UINT start_page = D_SW_WELCOME; if (sw->IsReExecForUac) { // In the case of this have been executed for UAC if (MsIsAdmin()) { // Jump to component list if the user have system administrator privileges start_page = D_SW_COMPONENTS; } else { // Jump to the setup mode selection screen when fail // to get admin privileges even executed by enabling UAC start_page = D_SW_MODE; } } ShowWizard(NULL, w, start_page); if (sw->Run) { // Auto run the app wchar_t tmp[MAX_PATH]; HANDLE h; UNI_TOKEN_LIST *t; t = UniParseToken(sw->CurrentComponent->StartExeName, L" "); if (t != NULL) { wchar_t exe[MAX_PATH]; wchar_t arg[MAX_PATH]; Zero(exe, sizeof(exe)); Zero(arg, sizeof(arg)); if (t->NumTokens >= 1) { UniStrCpy(exe, sizeof(exe), t->Token[0]); } if (t->NumTokens >= 2) { UniStrCpy(arg, sizeof(arg), t->Token[1]); } if (UniIsEmptyStr(exe) == false) { CombinePathW(tmp, sizeof(tmp), sw->InstallDir, exe); h = MsRunAsUserExW(tmp, arg, false); if (h != NULL) { CloseHandle(h); } } UniFreeToken(t); } } } FreeWizard(w); } // Release the component void SwFreeComponent(SW_COMPONENT *c) { // Validate arguments if (c == NULL) { return; } FreeStrList(c->NeedFiles); Free(c->Name); Free(c->SvcName); Free(c->LongName); Free(c->Title); Free(c->Description); Free(c->DefaultDirName); Free(c->SvcFileName); Free(c->StartExeName); Free(c->StartDescription); Free(c); } // Create a component SW_COMPONENT *SwNewComponent(char *name, char *svc_name, UINT id, UINT icon, UINT icon_index, wchar_t *svc_filename, wchar_t *long_name, bool system_mode_only, UINT num_files, char *files[], wchar_t *start_exe_name, wchar_t *start_description, SW_OLD_MSI *old_msis, UINT num_old_msis) { SW_COMPONENT *c; UINT i; char tmp[MAX_SIZE]; // Validate arguments if (name == NULL || files == NULL || long_name == NULL) { return NULL; } if (svc_name == NULL) { svc_name = name; } c = ZeroMalloc(sizeof(SW_COMPONENT)); c->Id = id; c->NeedFiles = NewListFast(NULL); for (i = 0;i < num_files;i++) { Add(c->NeedFiles, CopyStr(files[i])); } c->SystemModeOnly = system_mode_only; c->Name = CopyStr(name); c->SvcName = CopyStr(svc_name); c->DefaultDirName = CopyUniStr(long_name); c->LongName = CopyUniStr(long_name); Format(tmp, sizeof(tmp), "SW_COMPONENT_%s_TITLE", name); c->Title = CopyUniStr(_UU(tmp)); Format(tmp, sizeof(tmp), "SW_COMPONENT_%s_DESCRIPTION", name); c->Description = CopyUniStr(_UU(tmp)); c->Icon = icon; c->IconExeIndex = icon_index; if (UniIsEmptyStr(svc_filename) == false) { c->InstallService = true; c->SvcFileName = UniCopyStr(svc_filename); } if (UniIsEmptyStr(start_exe_name) == false && UniIsEmptyStr(start_description) == false) { c->StartExeName = UniCopyStr(start_exe_name); c->StartDescription = UniCopyStr(start_description); } c->OldMsiList = old_msis; c->NumOldMsi = num_old_msis; return c; } // Examine the OS requirements bool SwCheckOs(SW *sw, SW_COMPONENT *c) { // Validate arguments if (sw == NULL || c == NULL) { return false; } if (c->Id == SW_CMP_VPN_CLIENT) { OS_INFO *info = GetOsInfo(); if (OS_IS_WINDOWS_NT(info->OsType)) { if (MsIsWin2000OrGreater() == false) { // It doesn't work with WinNT 4.0 return false; } } else { if (GET_KETA(info->OsType, 100) <= 1) { // It doesn't work with Win95 return false; } else if (info->OsType == OSTYPE_WINDOWS_98) { if (EndWith(info->OsVersion, "A") == false) { // It doesn't work in Win98 First Edition return false; } } } } return true; } // Define the component void SwDefineComponents(SW *sw) { SW_COMPONENT *c; char *vpn_server_files[] = { "vpnserver.exe", "vpnserver_x64.exe", "vpnsmgr.exe", "vpnsmgr_x64.exe", "vpncmd.exe", "vpncmd_x64.exe", "hamcore.se2", }; char *vpn_client_files[] = { "vpnclient.exe", "vpnclient_x64.exe", "vpncmgr.exe", "vpncmgr_x64.exe", "vpncmd.exe", "vpncmd_x64.exe", "hamcore.se2", "vpninstall.exe", "vpnweb.cab", }; char *vpn_bridge_files[] = { "vpnbridge.exe", "vpnbridge_x64.exe", "vpnsmgr.exe", "vpnsmgr_x64.exe", "vpncmd.exe", "vpncmd_x64.exe", "hamcore.se2", }; char *vpn_smgr_files[] = { "vpnsmgr.exe", "vpnsmgr_x64.exe", "vpncmd.exe", "vpncmd_x64.exe", "hamcore.se2", }; char *vpn_cmgr_files[] = { "vpncmgr.exe", "vpncmgr_x64.exe", "vpncmd.exe", "vpncmd_x64.exe", "hamcore.se2", }; // Validate arguments if (sw == NULL) { return; } // VPN Server c = SwNewComponent(SW_NAME_VPNSERVER, GC_SVC_NAME_VPNSERVER, SW_CMP_VPN_SERVER, ICO_VPNSERVER, 5, (MsIsX64() ? L"vpnserver_x64.exe" : L"vpnserver.exe"), SW_LONG_VPNSERVER, false, sizeof(vpn_server_files) / sizeof(char *), vpn_server_files, (MsIsX64() ? L"vpnsmgr_x64.exe" : L"vpnsmgr.exe"), _UU("SW_RUN_TEXT_VPNSMGR"), old_msi_vpnserver, sizeof(old_msi_vpnserver) / sizeof(SW_OLD_MSI)); Add(sw->ComponentList, c); // VPN Client c = SwNewComponent(SW_NAME_VPNCLIENT, GC_SVC_NAME_VPNCLIENT, SW_CMP_VPN_CLIENT, ICO_VPN, 6, (MsIsX64() ? L"vpnclient_x64.exe" : L"vpnclient.exe"), SW_LONG_VPNCLIENT, true, sizeof(vpn_client_files) / sizeof(char *), vpn_client_files, (MsIsX64() ? L"vpncmgr_x64.exe" : L"vpncmgr.exe"), _UU("SW_RUN_TEXT_VPNCMGR"), old_msi_vpnclient, sizeof(old_msi_vpnclient) / sizeof(SW_OLD_MSI)); #ifdef GC_ENABLE_VPNGATE #endif // GC_ENABLE_VPNGATE Add(sw->ComponentList, c); // VPN Bridge c = SwNewComponent(SW_NAME_VPNBRIDGE, GC_SVC_NAME_VPNBRIDGE, SW_CMP_VPN_BRIDGE, ICO_CASCADE, 7, (MsIsX64() ? L"vpnbridge_x64.exe" : L"vpnbridge.exe"), SW_LONG_VPNBRIDGE, false, sizeof(vpn_bridge_files) / sizeof(char *), vpn_bridge_files, (MsIsX64() ? L"vpnsmgr_x64.exe" : L"vpnsmgr.exe"), _UU("SW_RUN_TEXT_VPNSMGR"), old_msi_vpnbridge, sizeof(old_msi_vpnbridge) / sizeof(SW_OLD_MSI)); Add(sw->ComponentList, c); // VPN Server Manager (Tools Only) c = SwNewComponent(SW_NAME_VPNSMGR, NULL, SW_CMP_VPN_SMGR, ICO_USER_ADMIN, 8, NULL, SW_LONG_VPNSMGR, false, sizeof(vpn_smgr_files) / sizeof(char *), vpn_smgr_files, (MsIsX64() ? L"vpnsmgr_x64.exe" : L"vpnsmgr.exe"), _UU("SW_RUN_TEXT_VPNSMGR"), NULL, 0); Add(sw->ComponentList, c); // VPN Client Manager (Tools Only) c = SwNewComponent(SW_NAME_VPNCMGR, NULL, SW_CMP_VPN_CMGR, ICO_INTERNET, 9, NULL, SW_LONG_VPNCMGR, false, sizeof(vpn_cmgr_files) / sizeof(char *), vpn_cmgr_files, (MsIsX64() ? L"vpncmgr_x64.exe /remote" : L"vpncmgr.exe /remote"), _UU("SW_RUN_TEXT_VPNCMGR"), NULL, 0); Add(sw->ComponentList, c); } // Detect the available components void SwDetectComponents(SW *sw) { UINT i; // Validate arguments if (sw == NULL) { return; } for (i = 0;i < LIST_NUM(sw->ComponentList);i++) { SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i); c->Detected = SwIsComponentDetected(sw, c); } // Determine whether the automatic connection configuration file exists in the same directory if (true) { wchar_t tmp[MAX_PATH]; ConbinePathW(tmp, sizeof(tmp), MsGetExeDirNameW(), SW_AUTO_CONNECT_ACCOUNT_FILE_NAME_W); if (IsFileExistsW(tmp)) { // Exist UniStrCpy(sw->auto_setting_path, sizeof(sw->auto_setting_path), tmp); } } } // Determine whether detection of the component is successful bool SwIsComponentDetected(SW *sw, SW_COMPONENT *c) { UINT i; bool ret = true; // Validate arguments if (sw == NULL || c == NULL) { return false; } for (i = 0;i < LIST_NUM(c->NeedFiles);i++) { char *name = LIST_DATA(c->NeedFiles, i); wchar_t name_w[MAX_SIZE]; wchar_t fullpath[MAX_SIZE]; StrToUni(name_w, sizeof(name_w), name); CombinePathW(fullpath, sizeof(fullpath), sw->InstallSrc, name_w); if (IsFileExistsW(fullpath) == false) { ret = false; break; } } if (c->InstallService == false) { if (sw->IsEasyInstaller || sw->IsWebInstaller) { // Prevent installing only management tool // for Web installer or a simple installer ret = false; } } return ret; } // Add a new log void SwAddLog(SW *sw, SW_LOGFILE *logfile, UINT type, wchar_t *path) { SW_LOG *g; // Validate arguments if (sw == NULL || path == NULL || logfile == NULL) { return; } g = ZeroMalloc(sizeof(SW_LOG)); g->Type = type; UniStrCpy(g->Path, sizeof(g->Path), path); Add(logfile->LogList, g); } void SwAddLogA(SW *sw, SW_LOGFILE *logfile, UINT type, char *path) { wchar_t *w; // Validate arguments if (sw == NULL || path == NULL || logfile == NULL) { return; } w = CopyStrToUni(path); SwAddLog(sw, logfile, type, w); Free(w); } // Create a SW SW *NewSw() { SW *sw = ZeroMalloc(sizeof(SW)); sw->IsSystemMode = true; sw->ComponentList = NewListFast(NULL); sw->ExitCode = SW_EXIT_CODE_USER_CANCEL; UniStrCpy(sw->InstallSrc, sizeof(sw->InstallSrc), MsGetExeDirNameW()); SwDefineComponents(sw); return sw; } // Release the SW UINT FreeSw(SW *sw) { UINT i; UINT ret; // Validate arguments if (sw == NULL) { return SW_EXIT_CODE_INTERNAL_ERROR; } SwLeaveSingle(sw); for (i = 0;i < LIST_NUM(sw->ComponentList);i++) { SW_COMPONENT *c = LIST_DATA(sw->ComponentList, i); SwFreeComponent(c); } ReleaseList(sw->ComponentList); SwFreeLogFile(sw->LogFile); if (sw->ReExecProcessHandle != NULL) { // If you have started the child process, wait for the termination of child process sw->ExitCode = MsWaitProcessExit(sw->ReExecProcessHandle); } ret = sw->ExitCode; Free(sw); return ret; } // Exit the multi-starts prevention mode void SwLeaveSingle(SW *sw) { // Validate arguments if (sw == NULL) { return; } if (sw->Single != NULL) { FreeSingleInstance(sw->Single); sw->Single = NULL; } } // Enter multiple-starts prevention mode bool SwEnterSingle(SW *sw) { // Validate arguments if (sw == NULL) { return false; } if (sw->Single != NULL) { return true; } sw->Single = NewSingleInstance(SW_SINGLE_INSTANCE_NAME); if (sw->Single == NULL) { return false; } return true; } // Parse the command line void SwParseCommandLine(SW *sw) { CONSOLE *c; wchar_t *cmdline; LIST *o; PARAM args[] = { {"UAC", NULL, NULL, NULL, NULL, }, {"LANGUAGE", NULL, NULL, NULL, NULL, }, {"LANGID", NULL, NULL, NULL, NULL, }, {"LANGNOW", NULL, NULL, NULL, NULL, }, {"SETLANGANDREBOOT", NULL, NULL, NULL, NULL, }, {"EASY", NULL, NULL, NULL, NULL, }, {"WEB", NULL, NULL, NULL, NULL, }, {"SFXMODE", NULL, NULL, NULL, NULL, }, {"SFXOUT", NULL, NULL, NULL, NULL, }, {"HIDESTARTCOMMAND", NULL, NULL, NULL, NULL, }, {"CALLERSFXPATH", NULL, NULL, NULL, NULL, }, {"ISEASYINSTALLER", NULL, NULL, NULL, NULL, }, {"DISABLEAUTOIMPORT", NULL, NULL, NULL, NULL, }, {"ISWEBINSTALLER", NULL, NULL, NULL, NULL, }, {"SUINSTMODE", NULL, NULL, NULL, NULL, }, }; // Validate arguments if (sw == NULL) { return; } c = NewLocalConsole(NULL, NULL); if (c == NULL) { return; } cmdline = GetCommandLineUniStr(); if (UniIsEmptyStr(cmdline) == false) { o = ParseCommandList(c, "setup", cmdline, args, sizeof(args) / sizeof(args[0])); if (o != NULL) { sw->IsReExecForUac = GetParamYes(o, "UAC"); sw->LanguageMode = GetParamYes(o, "LANGUAGE"); sw->LangId = GetParamInt(o, "LANGID"); sw->LangNow = GetParamYes(o, "LANGNOW"); sw->SetLangAndReboot = GetParamYes(o, "SETLANGANDREBOOT"); sw->HideStartCommand = GetParamYes(o, "HIDESTARTCOMMAND"); sw->SuInstMode = GetParamYes(o, "SUINSTMODE"); // Special mode if (sw->LanguageMode == false) { sw->EasyMode = GetParamYes(o, "EASY"); if (sw->EasyMode == false) { sw->WebMode = GetParamYes(o, "WEB"); } } StrCpy(sw->SfxMode, sizeof(sw->SfxMode), GetParamStr(o, "SFXMODE")); UniStrCpy(sw->SfxOut, sizeof(sw->SfxOut), GetParamUniStr(o, "SFXOUT")); UniStrCpy(sw->CallerSfxPath, sizeof(sw->CallerSfxPath), GetParamUniStr(o, "CALLERSFXPATH")); sw->IsEasyInstaller = GetParamYes(o, "ISEASYINSTALLER"); sw->IsWebInstaller = GetParamYes(o, "ISWEBINSTALLER"); sw->DisableAutoImport = GetParamYes(o, "DISABLEAUTOIMPORT"); FreeParamValueList(o); } } Free(cmdline); c->Free(c); } // Start the Setup Wizard UINT SWExecMain() { SW *sw; UINT ret; SW_LOGFILE *logfile = NULL; wchar_t verstr[MAX_SIZE]; char ver[MAX_SIZE]; // Define the wizard UI GetCedarVersion(ver, sizeof(ver)); UniFormat(verstr, sizeof(verstr), _UU("SW_TITLE"), ver); InitWinUi(verstr, _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE")); // Create a SW sw = NewSw(); // Read the setting sw->Easy_EraseSensitive = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EraseSensitive"); sw->Easy_EasyMode = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Easy_EasyMode"); sw->Web_EraseSensitive = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EraseSensitive"); sw->Web_EasyMode = MsRegReadInt(REG_CURRENT_USER, SW_REG_KEY, "Web_EasyMode"); // Parse the command line SwParseCommandLine(sw); // Test! //sw->WebMode = true; // Detect the installable components SwDetectComponents(sw); if (IsEmptyStr(sw->SfxMode) == false && UniIsEmptyStr(sw->SfxOut) == false) { // SFX generation mode if (SwGenSfxModeMain(sw->SfxMode, sw->SfxOut)) { // Success sw->ExitCode = 0; } } else if (sw->SuInstMode) { // SuInst mode sw->ExitCode = 0; if (SuInstallDriver(false) == false) { sw->ExitCode = SW_EXIT_CODE_INTERNAL_ERROR; } } else { // Normal mode // Load setuplog.dat if (IsFileExistsW(L"@" L"setuplog.dat") && (logfile = SwLoadLogFile(sw, L"@" L"setuplog.dat")) == NULL) { // Setuplog.dat is broken MsgBox(NULL, MB_ICONSTOP, _UU("SW_SETUPLOG_CORRUPTED")); } else { sw->LogFile = logfile; if (sw->LogFile == NULL) { // Setuplog.dat does not exist sw->LogFile = SwNewLogFile(); } else { // When setuplog.dat exists, it is in either of language-setting-change-mode, simple-installer-creation-mode, uninstall-mode sw->CurrentComponent = sw->LogFile->Component; sw->IsSystemMode = sw->LogFile->IsSystemMode; UniStrCpy(sw->InstallDir, sizeof(sw->InstallDir), MsGetExeDirNameW()); if (sw->LanguageMode == false && sw->EasyMode == false && sw->WebMode == false) { // Uninstall mode sw->UninstallMode = true; } } // UI main SwUiMain(sw); } } // Release the SW ret = FreeSw(sw); FreeWinUi(); return ret; } #endif // WIN32