summaryrefslogtreecommitdiffstats
path: root/bin/win32/BINDInstall/BINDInstallDlg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'bin/win32/BINDInstall/BINDInstallDlg.cpp')
-rw-r--r--bin/win32/BINDInstall/BINDInstallDlg.cpp1601
1 files changed, 1601 insertions, 0 deletions
diff --git a/bin/win32/BINDInstall/BINDInstallDlg.cpp b/bin/win32/BINDInstall/BINDInstallDlg.cpp
new file mode 100644
index 0000000..a123c4a
--- /dev/null
+++ b/bin/win32/BINDInstall/BINDInstallDlg.cpp
@@ -0,0 +1,1601 @@
+/*
+ * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
+ *
+ * SPDX-License-Identifier: MPL-2.0
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, you can obtain one at https://mozilla.org/MPL/2.0/.
+ *
+ * See the COPYRIGHT file distributed with this work for additional
+ * information regarding copyright ownership.
+ */
+
+/*
+ * Copyright (c) 1999-2000 by Nortel Networks Corporation
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Define this to make a standalone installer that will copy msvcrt.dll
+ * and/or msvcrtd.dll during the install
+ */
+// #define BINARIES_INSTALL
+
+/*
+ * msvcrt.dll is the release c-runtime library for MSVC. msvcrtd.dll
+ * is the debug c-runtime library for MSVC. If you have debug
+ * binaries you want to have DEBUG_BINARIES defined. If you have
+ * release binaries you want to have RELEASE_BINARIES defined.
+ * If you have both, then define them both.
+ * Of course, you need msvcrt[d].dll present to install it!
+ */
+#ifdef BINARIES_INSTALL
+// # define DEBUG_BINARIES
+// # define RELEASE_BINARIES
+#endif
+
+#include "stdafx.h"
+#include "BINDInstall.h"
+#include "BINDInstallDlg.h"
+#include "DirBrowse.h"
+#include <winsvc.h>
+#include <shlobj.h>
+#include <shlwapi.h>
+#include <named/ntservice.h>
+#include <isc/bind_registry.h>
+#include <isc/ntgroups.h>
+#include <direct.h>
+#include "AccountInfo.h"
+#include "versioninfo.h"
+
+#include <fstream>
+#include <iostream>
+#include <string>
+#include <vector>
+
+#include <config.h>
+
+#undef open
+
+#define MAX_GROUPS 100
+#define MAX_PRIVS 50
+
+#define LOCAL_SERVICE "NT AUTHORITY\\LocalService"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+
+typedef struct _xexception
+{
+ _xexception(UINT string, ...);
+
+ CString resString;
+} Exception;
+
+_xexception::_xexception(UINT string, ...)
+{
+ CString format;
+ va_list va;
+
+ format.LoadString(string);
+
+ va_start(va, string);
+ resString.FormatV(format, va);
+ va_end(va);
+}
+
+typedef struct _filedata {
+ enum FileDestinations {TargetDir, BinDir, EtcDir, WinSystem};
+ enum FileImportance {Trivial, Normal, Critical};
+
+ char filename[128];
+ int destination;
+ int importance;
+ BOOL checkVer;
+ BOOL withTools;
+} FileData;
+
+#if no_longer_used
+
+const FileData installFiles[] =
+{
+#ifdef BINARIES_INSTALL
+# ifdef DEBUG_BINARIES
+ {"msvcrtd.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+# endif
+# ifdef RELEASE_BINARIES
+ {"msvcrt.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+# endif
+#endif
+#if _MSC_VER < 1400
+#if _MSC_VER >= 1310
+ {"mfc71.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+ {"msvcr71.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+#elif _MSC_VER > 1200 && _MSC_VER < 1310
+ {"mfc70.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+ {"msvcr70.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
+#endif
+#endif
+ {"bindevt.dll", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"libbind9.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libisc.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libisccfg.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libisccc.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libdns.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libirs.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libeay32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"libuv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#ifdef HAVE_LIBXML2
+ {"libxml2.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+#ifdef USE_GSSAPI
+#ifndef _WIN64
+ {"gssapi32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"krb5_32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#else
+ {"gssapi64.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"krb5_64.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+#endif
+#ifdef HAVE_GEOIP
+ {"libgeoip.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+#ifdef WITH_IDN
+ {"idnkit.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+ {"iconv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
+#endif
+ {"named.exe", FileData::BinDir, FileData::Critical, FALSE, FALSE},
+ {"nsupdate.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"BINDInstall.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"rndc.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dig.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"host.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"mdig.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"nslookup.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"delv.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"arpaname.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
+ {"nsec3hash.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"rndc-confgen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"ddns-confgen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"tsig-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-signzone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-dsfromkey.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-importkey.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-keyfromlabel.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-revoke.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-settime.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-verify.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-checkconf.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-checkzone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-compilezone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-journalprint.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"named-rrchecker.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+#ifdef USE_PKCS11
+ {"pkcs11-destroy.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"pkcs11-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"pkcs11-list.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"pkcs11-tokens.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+#endif
+#ifdef USE_PYTHON
+ {"dnssec-checkds.py", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+ {"dnssec-coverage.py", FileData::BinDir, FileData::Normal, FALSE, FALSE},
+#endif
+ {"readme1st.txt", FileData::BinDir, FileData::Trivial, FALSE, TRUE},
+ {NULL, -1, -1}
+};
+
+#else
+
+typedef std::vector<FileData> FileDatas;
+FileDatas installFiles;
+BOOL forwin64 = FALSE;
+BOOL runvcredist = FALSE;
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallDlg dialog
+
+CBINDInstallDlg::CBINDInstallDlg(CWnd* pParent /*=NULL*/)
+ : CDialog(CBINDInstallDlg::IDD, pParent) {
+ char winsys[MAX_PATH];
+
+ //{{AFX_DATA_INIT(CBINDInstallDlg)
+ /* cppcheck-suppress useInitializationList */
+ m_targetDir = _T("");
+ m_version = _T("");
+ m_toolsOnly = FALSE;
+ m_autoStart = FALSE;
+ m_keepFiles = FALSE;
+ m_current = _T("");
+ m_startOnInstall = FALSE;
+ m_accountName = _T("");
+ m_accountPassword = _T("");
+ //}}AFX_DATA_INIT
+ // Note that LoadIcon does not require a subsequent
+ // DestroyIcon in Win32
+ m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
+
+ GetSystemDirectory(winsys, MAX_PATH);
+ m_winSysDir = winsys;
+
+ m_defaultDir = "notyetknown";
+
+ m_installed = FALSE;
+ m_accountExists = FALSE;
+ m_accountUsed = FALSE;
+ m_serviceExists = TRUE;
+ GetCurrentServiceAccountName();
+ m_currentAccount = m_accountName;
+ if (m_accountName == "") {
+ m_accountName = "named";
+ }
+}
+
+void CBINDInstallDlg::DoDataExchange(CDataExchange* pDX) {
+ CDialog::DoDataExchange(pDX);
+ //{{AFX_DATA_MAP(CBINDInstallDlg)
+ DDX_Text(pDX, IDC_TARGETDIR, m_targetDir);
+ DDX_Text(pDX, IDC_VERSION, m_version);
+ DDX_Text(pDX, IDC_ACCOUNT_NAME, m_accountName);
+ DDX_Text(pDX, IDC_ACCOUNT_PASSWORD, m_accountPassword);
+ DDX_Text(pDX, IDC_ACCOUNT_PASSWORD_CONFIRM, m_accountPasswordConfirm);
+ DDX_Check(pDX, IDC_TOOLS_ONLY, m_toolsOnly);
+ DDX_Check(pDX, IDC_AUTO_START, m_autoStart);
+ DDX_Check(pDX, IDC_KEEP_FILES, m_keepFiles);
+ DDX_Text(pDX, IDC_CURRENT, m_current);
+ DDX_Check(pDX, IDC_START, m_startOnInstall);
+ //}}AFX_DATA_MAP
+}
+
+BEGIN_MESSAGE_MAP(CBINDInstallDlg, CDialog)
+ //{{AFX_MSG_MAP(CBINDInstallDlg)
+ ON_WM_PAINT()
+ ON_WM_QUERYDRAGICON()
+ ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
+ ON_BN_CLICKED(IDC_INSTALL, OnInstall)
+ ON_BN_CLICKED(IDC_EXIT, OnExit)
+ ON_BN_CLICKED(IDC_UNINSTALL, OnUninstall)
+ //}}AFX_MSG_MAP
+END_MESSAGE_MAP()
+
+/////////////////////////////////////////////////////////////////////////////
+// CBINDInstallDlg message handlers
+
+BOOL CBINDInstallDlg::OnInitDialog() {
+ CDialog::OnInitDialog();
+
+ // Set the icon for this dialog. The framework does this automatically
+ // when the application's main window is not a dialog
+ SetIcon(m_hIcon, TRUE); // Set big icon
+ SetIcon(m_hIcon, FALSE); // Set small icon
+
+ char filename[MAX_PATH];
+ char dirname[MAX_PATH];
+ char *fptr = &filename[0];
+ GetModuleFileName(NULL, filename, MAX_PATH);
+ char *dptr = strrchr(filename,'\\');
+ size_t index = dptr - fptr;
+ strncpy(dirname, filename, index);
+ dirname[index] = '\0';
+ CString Dirname(dirname);
+ m_currentDir = Dirname;
+
+ ReadInstallFlags();
+ char progfiles[MAX_PATH];
+ int id_program_files;
+ if (forwin64)
+ id_program_files = CSIDL_PROGRAM_FILES;
+ else
+ id_program_files = CSIDL_PROGRAM_FILESX86;
+ SHGetFolderPath(NULL, CSIDL_FLAG_CREATE|id_program_files,
+ NULL, SHGFP_TYPE_CURRENT, progfiles);
+
+ m_defaultDir = progfiles;
+ m_defaultDir += "\\ISC BIND 9";
+
+ CVersionInfo bindInst(filename);
+ if(bindInst.IsValid())
+ m_version.Format(IDS_VERSION, bindInst.GetFileVersionString());
+ else
+ m_version.LoadString(IDS_NO_VERSION);
+
+ DWORD dwBufLen = MAX_PATH;
+ char buf[MAX_PATH];
+ HKEY hKey;
+
+ m_startOnInstall = CheckBINDService();
+
+ /* See if we are installed already */
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
+ == ERROR_SUCCESS) {
+ m_installed = TRUE;
+ memset(buf, 0, MAX_PATH);
+ // Get the install directory
+ if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL, (LPBYTE)buf,
+ &dwBufLen) == ERROR_SUCCESS)
+ if (strcmp(buf, ""))
+ m_defaultDir = buf;
+
+ RegCloseKey(hKey);
+ }
+ m_targetDir = m_defaultDir;
+
+ // Set checkbox defaults
+ m_autoStart = TRUE;
+ m_keepFiles = TRUE;
+
+ UpdateData(FALSE);
+
+ return (TRUE); /* return(TRUE) unless you set the focus to a control */
+}
+
+/*
+ * If you add a minimize button to your dialog, you will need the code below
+ * to draw the icon. For MFC applications using the document/view model,
+ * this is automatically done for you by the framework.
+ */
+
+void CBINDInstallDlg::OnPaint() {
+ if (IsIconic()) {
+ CPaintDC dc(this); // device context for painting
+
+ SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
+
+ // Center icon in client rectangle
+ int cxIcon = GetSystemMetrics(SM_CXICON);
+ int cyIcon = GetSystemMetrics(SM_CYICON);
+ CRect rect;
+ GetClientRect(&rect);
+ int x = (rect.Width() - cxIcon + 1) / 2;
+ int y = (rect.Height() - cyIcon + 1) / 2;
+
+ // Draw the icon
+ dc.DrawIcon(x, y, m_hIcon);
+ }
+ else {
+ CDialog::OnPaint();
+ }
+}
+
+// The system calls this to obtain the cursor to display while the user drags
+// the minimized window.
+HCURSOR CBINDInstallDlg::OnQueryDragIcon() {
+ return((HCURSOR)m_hIcon);
+}
+
+void CBINDInstallDlg::OnBrowse() {
+
+ CDirBrowse browse;
+
+ if (browse.DoModal() == IDOK) {
+ //m_targetDir = browse.m_selectedDir;
+ UpdateData(FALSE);
+ }
+}
+
+/*
+ * User pressed the exit button
+ */
+void CBINDInstallDlg::OnExit() {
+ EndDialog(0);
+}
+
+/*
+ * User pressed the uninstall button. Make it go.
+ */
+void CBINDInstallDlg::OnUninstall() {
+ UpdateData();
+
+ if (MsgBox(IDS_UNINSTALL, MB_YESNO) == IDYES) {
+ if (CheckBINDService())
+ StopBINDService();
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL,
+ SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ return;
+ }
+
+ SC_HANDLE hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hService && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST){
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ return;
+ }
+
+ SERVICE_STATUS ss;
+ QueryServiceStatus(hService, &ss);
+ if (ss.dwCurrentState == SERVICE_RUNNING) {
+ BOOL rc = ControlService(hService,
+ SERVICE_CONTROL_STOP, &ss);
+ if (rc == FALSE || ss.dwCurrentState != SERVICE_STOPPED) {
+ MsgBox(IDS_ERR_STOP_SERVICE, GetErrMessage());
+ return;
+ }
+
+ }
+ CloseServiceHandle(hService);
+ CloseServiceHandle(hSCManager);
+
+ // Directories
+ m_etcDir = m_targetDir + "\\etc";
+ m_binDir = m_targetDir + "\\bin";
+
+ UninstallTags();
+ UnregisterMessages(TRUE);
+ UnregisterService(TRUE);
+ ReadInstallFileList();
+ DeleteFiles(TRUE);
+ if (m_keepFiles == FALSE)
+ RemoveDirs(TRUE);
+ else
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("Not Removed");
+
+
+ // Delete registry keys for named
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SESSION_SUBKEY);
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY);
+ RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY);
+
+ ProgramGroup(FALSE);
+
+ SetCurrent(IDS_UNINSTALL_DONE);
+ MsgBox(IDS_UNINSTALL_DONE);
+ }
+}
+
+/*
+ * User pressed the install button. Make it go.
+ */
+void CBINDInstallDlg::OnInstall() {
+ BOOL success = FALSE;
+ int oldlen;
+ int n;
+
+ if (CheckBINDService())
+ StopBINDService();
+
+ InstallTags();
+
+ UpdateData();
+
+ if (!m_toolsOnly && m_accountName != LOCAL_SERVICE) {
+ /*
+ * Check that the Passwords entered match.
+ */
+ if (m_accountPassword != m_accountPasswordConfirm) {
+ MsgBox(IDS_ERR_PASSWORD);
+ return;
+ }
+
+ /*
+ * Check that there is not leading / trailing whitespace.
+ * This is for compatibility with the standard password dialog.
+ * Passwords really should be treated as opaque blobs.
+ */
+ oldlen = m_accountPassword.GetLength();
+ m_accountPassword.TrimLeft();
+ m_accountPassword.TrimRight();
+ if (m_accountPassword.GetLength() != oldlen) {
+ MsgBox(IDS_ERR_WHITESPACE);
+ return;
+ }
+
+ /*
+ * Check the entered account name.
+ */
+ if (ValidateServiceAccount() == FALSE)
+ return;
+
+ /*
+ * For Registration we need to know if account was changed.
+ */
+ if (m_accountName != m_currentAccount)
+ m_accountUsed = FALSE;
+
+ if (m_accountUsed == FALSE && m_serviceExists == FALSE)
+ {
+ /*
+ * Check that the Password is not null.
+ */
+ if (m_accountPassword.GetLength() == 0) {
+ MsgBox(IDS_ERR_NULLPASSWORD);
+ return;
+ }
+ }
+ } else if (m_accountName == LOCAL_SERVICE) {
+ /* The LocalService always exists. */
+ m_accountExists = TRUE;
+ if (m_accountName != m_currentAccount)
+ m_accountUsed = FALSE;
+ }
+
+ /* Directories */
+ m_etcDir = m_targetDir + "\\etc";
+ m_binDir = m_targetDir + "\\bin";
+
+ if (m_defaultDir != m_targetDir) {
+ if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
+ {
+ int install = MsgBox(IDS_DIREXIST,
+ MB_YESNO | MB_ICONQUESTION, m_targetDir);
+ if (install == IDNO)
+ return;
+ }
+ else {
+ int createDir = MsgBox(IDS_CREATEDIR,
+ MB_YESNO | MB_ICONQUESTION, m_targetDir);
+ if (createDir == IDNO)
+ return;
+ }
+ }
+
+ if (!m_toolsOnly) {
+ if (m_accountExists == FALSE) {
+ success = CreateServiceAccount(m_accountName.GetBuffer(30),
+ m_accountPassword.GetBuffer(30));
+ if (success == FALSE) {
+ MsgBox(IDS_CREATEACCOUNT_FAILED);
+ return;
+ }
+ m_accountExists = TRUE;
+ }
+ }
+
+ ProgramGroup(FALSE);
+
+ /*
+ * Install Visual Studio libraries. As per:
+ * http://blogs.msdn.com/astebner/archive/2006/08/23/715755.aspx
+ *
+ * Vcredist_x86.exe /q:a /c:"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log"
+ */
+ /*system(".\\Vcredist_x86.exe /q:a /c:\"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log\"");*/
+
+ /*
+ * Enclose full path to Vcredist_x86.exe in quotes as
+ * m_currentDir may contain spaces.
+ */
+ if (runvcredist) {
+ char Vcredist_x86[MAX_PATH];
+ if (forwin64)
+ n = snprintf(Vcredist_x86, sizeof(Vcredist_x86),
+ "\"%s\\Vcredist_x64.exe\"",
+ (LPCTSTR) m_currentDir);
+ else
+ n = snprintf(Vcredist_x86, sizeof(Vcredist_x86),
+ "\"%s\\Vcredist_x86.exe\"",
+ (LPCTSTR) m_currentDir);
+ if (n >= 0 && (size_t)n < sizeof(Vcredist_x86))
+ system(Vcredist_x86);
+ }
+ try {
+ CreateDirs();
+ ReadInstallFileList();
+ CopyFiles();
+ if (!m_toolsOnly)
+ RegisterService();
+ RegisterMessages();
+
+ HKEY hKey;
+
+ /* Create a new key for named */
+ SetCurrent(IDS_CREATE_KEY);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY,
+ &hKey) == ERROR_SUCCESS) {
+ // Get the install directory
+ RegSetValueEx(hKey, "InstallDir", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)m_targetDir,
+ m_targetDir.GetLength());
+ RegCloseKey(hKey);
+ }
+
+
+ SetCurrent(IDS_ADD_REMOVE);
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY,
+ &hKey) == ERROR_SUCCESS) {
+ CString buf(BIND_DISPLAY_NAME);
+
+ RegSetValueEx(hKey, "DisplayName", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)buf, buf.GetLength());
+
+ buf.Format("%s\\BINDInstall.exe", m_binDir);
+
+ CStringA installLocA(buf);
+ const char *str = (const char *) installLocA;
+ char pathBuffer[2 * MAX_PATH];
+ strncpy(pathBuffer, str, sizeof(pathBuffer) - 1);
+ pathBuffer[sizeof(pathBuffer) - 1] = 0;
+ PathQuoteSpaces(pathBuffer);
+
+ RegSetValueEx(hKey, "UninstallString", 0, REG_SZ,
+ (LPBYTE)(LPCTSTR)pathBuffer, strlen(pathBuffer));
+ RegCloseKey(hKey);
+ }
+
+ ProgramGroup(FALSE);
+
+ if (m_startOnInstall)
+ StartBINDService();
+ }
+ catch(Exception e) {
+ MessageBox(e.resString);
+ SetCurrent(IDS_CLEANUP);
+ FailedInstall();
+ MsgBox(IDS_FAIL);
+ return;
+ }
+ catch(DWORD dw) {
+ CString msg;
+ msg.Format("A fatal error occurred\n(%s)", GetErrMessage(dw));
+ MessageBox(msg);
+ SetCurrent(IDS_CLEANUP);
+ FailedInstall();
+ MsgBox(IDS_FAIL);
+ return;
+ }
+
+ SetCurrent(IDS_INSTALL_DONE);
+ MsgBox(IDS_SUCCESS);
+}
+
+/*
+ * Methods to do the work
+ */
+void CBINDInstallDlg::CreateDirs() {
+ /* s'OK if the directories already exist */
+ SetCurrent(IDS_CREATE_DIR, m_targetDir);
+ if (!CreateDirectory(m_targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_targetDir, GetErrMessage()));
+
+ SetCurrent(IDS_CREATE_DIR, m_etcDir);
+ if (!CreateDirectory(m_etcDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_etcDir, GetErrMessage()));
+
+ SetCurrent(IDS_CREATE_DIR, m_binDir);
+ if (!CreateDirectory(m_binDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_DIR, m_binDir, GetErrMessage()));
+
+ SetItemStatus(IDC_CREATE_DIR);
+}
+
+void CBINDInstallDlg::RemoveDirs(BOOL uninstall) {
+ if (!m_keepFiles) {
+ SetCurrent(IDS_REMOVE_DIR, m_binDir);
+ // Check for existence then remove if present
+ if (GetFileAttributes(m_binDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_binDir);
+
+ SetCurrent(IDS_REMOVE_DIR, m_etcDir);
+ if (GetFileAttributes(m_etcDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_etcDir);
+
+ SetCurrent(IDS_REMOVE_DIR, m_targetDir);
+ if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
+ RemoveDirectory(m_targetDir);
+ }
+
+ if (uninstall)
+ SetItemStatus(IDC_CREATE_DIR, TRUE);
+}
+
+// InstallFlags: runvcredist and forwin64 options
+void CBINDInstallDlg::ReadInstallFlags() {
+ std::ifstream ff(m_currentDir + "\\InstallFlags");
+ if (!ff) {
+ throw(Exception(IDS_FILE_BAD, "InstallFlags", "can't open"));
+ }
+ while (!ff.eof()) {
+ std::string line;
+ getline(ff, line);
+ if (line.compare("runvcredist") == 0)
+ runvcredist = TRUE;
+ else if (line.compare("forwin64") == 0)
+ forwin64 = TRUE;
+ }
+}
+
+// InstallFiles: {filename-divt}*
+// destination: TBEW
+// importance: TNC
+// checkVer and withTools: TF (boolean)
+void CBINDInstallDlg::ReadInstallFileList() {
+ std::ifstream fl(m_currentDir + "\\InstallFiles");
+ if (!fl) {
+ throw(Exception(IDS_FILE_BAD, "InstallFiles", "can't open"));
+ }
+ while (!fl.eof()) {
+ std::string line;
+ getline(fl, line);
+ if (line.empty())
+ continue;
+ if (line[0] == '#')
+ continue;
+ // zip -l adds spurious \r: remove trailing space chars
+ size_t finish = line.find_last_not_of(" \t\r\n\t\v");
+ if ((finish != std::string::npos) &&
+ (finish + 1 != line.size())) {
+ line.erase(finish + 1);
+ }
+ size_t flags = line.find_last_of('-');
+ if ((flags == std::string::npos) ||
+ (flags + 5 != line.size()))
+ goto bad;
+ std::string file = line.substr(0, flags);
+ if (file.empty() || (file.size() > 127))
+ goto bad;
+ FileData entry;
+ memmove(entry.filename, file.c_str(), file.size() + 1);
+ switch (line[flags + 1]) {
+ case 'T':
+ entry.destination = FileData::TargetDir;
+ break;
+ case 'B':
+ entry.destination = FileData::BinDir;
+ break;
+ case 'E':
+ entry.destination = FileData::EtcDir;
+ break;
+ case 'W':
+ entry.destination = FileData::WinSystem;
+ break;
+ default:
+ goto bad;
+ }
+ switch (line[flags + 2]) {
+ case 'T':
+ entry.importance = FileData::Trivial;
+ break;
+ case 'N':
+ entry.importance = FileData::Normal;
+ break;
+ case 'C':
+ entry.importance = FileData::Critical;
+ break;
+ default:
+ goto bad;
+ }
+ switch (line[flags + 3]) {
+ case 'T':
+ entry.checkVer = TRUE;
+ break;
+ case 'F':
+ entry.checkVer = FALSE;
+ break;
+ default:
+ goto bad;
+ }
+ switch (line[flags + 4]) {
+ case 'T':
+ entry.withTools = TRUE;
+ break;
+ case 'F':
+ entry.withTools = FALSE;
+ break;
+ default:
+ goto bad;
+ }
+ installFiles.push_back(entry);
+ }
+ return;
+
+bad:
+ throw(Exception(IDS_FILE_BAD, "InstallFiles", "syntax error"));
+}
+
+void CBINDInstallDlg::CopyFiles() {
+ CString destFile;
+
+ for (FileDatas::iterator fd = installFiles.begin();
+ fd != installFiles.end(); ++fd) {
+ if (m_toolsOnly && !fd->withTools)
+ continue;
+ SetCurrent(IDS_COPY_FILE, fd->filename);
+
+ destFile = DestDir(fd->destination) + "\\" + fd->filename;
+ CString filespec = m_currentDir + "\\" + fd->filename;
+ CVersionInfo bindFile(destFile);
+
+ CVersionInfo origFile(filespec);
+ if (!origFile.IsValid() && fd->checkVer) {
+ if (MsgBox(IDS_FILE_BAD, MB_YESNO,
+ fd->filename) == IDNO)
+ throw(Exception(IDS_ERR_COPY_FILE,
+ fd->filename,
+ GetErrMessage()));
+ }
+
+ try {
+/*
+ * Ignore Version checking. We need to make sure that all files get
+ * copied regardless of whether or not they are earlier or later
+ * versions since we cannot guarantee that we have either backward or
+ * forward compatibility between versions.
+ */
+ bindFile.CopyFileNoVersion(origFile);
+ }
+ catch(...) {
+ if (fd->importance != FileData::Trivial) {
+ if (fd->importance == FileData::Critical ||
+ MsgBox(IDS_ERR_NONCRIT_FILE, MB_YESNO,
+ fd->filename,
+ GetErrMessage()) == IDNO)
+ {
+ SetItemStatus(IDC_COPY_FILE, FALSE);
+ throw(Exception(IDS_ERR_COPY_FILE,
+ fd->filename,
+ GetErrMessage()));
+ }
+ }
+ }
+ }
+
+ SetItemStatus(IDC_COPY_FILE);
+}
+
+void CBINDInstallDlg::DeleteFiles(BOOL uninstall) {
+ CString destFile;
+
+ for (FileDatas::iterator fd = installFiles.begin();
+ fd != installFiles.end(); ++fd) {
+ if (fd->checkVer)
+ continue;
+
+ destFile = DestDir(fd->destination) + "\\" + fd->filename;
+
+ if (uninstall)
+ SetCurrent(IDS_DELETE_FILE, fd->filename);
+
+ DeleteFile(destFile);
+ }
+
+ if (!m_keepFiles) {
+ WIN32_FIND_DATA findData;
+ CString file = m_etcDir + "\\*.*";
+ BOOL rc;
+ HANDLE hFile;
+
+ hFile = FindFirstFile(file, &findData);
+ rc = hFile != INVALID_HANDLE_VALUE;
+
+ while (rc == TRUE) {
+ if (strcmp(findData.cFileName, ".") &&
+ strcmp(findData.cFileName, "..")) {
+ file = m_etcDir + "\\" + findData.cFileName;
+ SetCurrent(IDS_DELETE_FILE, file);
+ DeleteFile(file);
+ }
+ rc = FindNextFile(hFile, &findData);
+ }
+ FindClose(hFile);
+ }
+
+ if (uninstall)
+ SetItemStatus(IDC_COPY_FILE, TRUE);
+}
+
+/*
+ * Get the service account name out of the registry, if any
+ */
+void
+CBINDInstallDlg::GetCurrentServiceAccountName() {
+ HKEY hKey;
+ BOOL keyFound = FALSE;
+ char accountName[MAX_PATH];
+ DWORD nameLen = MAX_PATH;
+ CString Tmp;
+ m_accountUsed = FALSE;
+
+ memset(accountName, 0, nameLen);
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SERVICE_SUBKEY, 0, KEY_READ,
+ &hKey) == ERROR_SUCCESS) {
+ keyFound = TRUE;
+ }
+ else {
+ m_serviceExists = FALSE;
+ }
+
+ if (keyFound == TRUE) {
+ /* Get the named service account, if one was specified */
+ if (RegQueryValueEx(hKey, "ObjectName", NULL, NULL,
+ (LPBYTE)accountName, &nameLen) != ERROR_SUCCESS)
+ keyFound = FALSE;
+ }
+
+ RegCloseKey(hKey);
+ if (keyFound == FALSE)
+ m_accountName = "";
+ else if (!strcmp(accountName, LOCAL_SERVICE)) {
+ m_accountName = LOCAL_SERVICE;
+ m_accountUsed = TRUE;
+ } else {
+ /*
+ * LocalSystem is not a regular account and is equivalent
+ * to no account but with lots of privileges
+ */
+ Tmp = accountName;
+ if (Tmp == ".\\LocalSystem")
+ m_accountName = "";
+ /* Found account strip any ".\" from it */
+ if (Tmp.Left(2) == ".\\") {
+ m_accountName = Tmp.Mid(2);
+ m_accountUsed = TRUE;
+ }
+ }
+}
+
+BOOL
+CBINDInstallDlg::ValidateServiceAccount() {
+ wchar_t *PrivList[MAX_PRIVS];
+ unsigned int PrivCount = 0;
+ char *Groups[MAX_GROUPS];
+ unsigned int totalGroups = 0;
+ int status;
+ char *name;
+
+ name = m_accountName.GetBuffer(30);
+
+ status = GetAccountPrivileges(name, PrivList, &PrivCount,
+ Groups, &totalGroups, MAX_GROUPS);
+ if (status == RTN_NOACCOUNT) {
+ m_accountExists = FALSE;
+ /* We need to do this in case an account was previously used */
+ m_accountUsed = FALSE;
+ return (TRUE);
+ }
+ if (status != RTN_OK) {
+ MsgBox(IDS_ERR_BADACCOUNT);
+ return (FALSE);
+ }
+
+ m_accountExists = TRUE;
+ if (PrivCount > 1) {
+ if (MsgBox(IDS_ERR_TOOPRIVED, MB_YESNO) == IDYES)
+ return (FALSE);
+ else
+ return (TRUE);
+ }
+
+ /* See if we have the correct privilege */
+ if (wcscmp(PrivList[0], SE_SERVICE_LOGON_PRIV) != 0) {
+ MsgBox(IDS_ERR_WRONGPRIV, PrivList[0]);
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+void
+CBINDInstallDlg::RegisterService() {
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+ CString StartName;
+
+ if (m_accountName == LOCAL_SERVICE)
+ StartName = LOCAL_SERVICE;
+ else
+ StartName = ".\\" + m_accountName;
+ /*
+ * We need to change the service rather than create it
+ * if the service already exists. Do nothing if we are already
+ * using that account
+ */
+ if (m_serviceExists == TRUE) {
+ if (m_accountUsed == FALSE) {
+ UpdateService(StartName);
+ SetItemStatus(IDC_REG_SERVICE);
+ return;
+ } else {
+ SetItemStatus(IDC_REG_SERVICE);
+ return;
+ }
+ }
+
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager)
+ throw(Exception(IDS_ERR_OPEN_SCM, GetErrMessage()));
+
+ DWORD dwStart = SERVICE_DEMAND_START;
+ if (m_autoStart)
+ dwStart = SERVICE_AUTO_START;
+
+ DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+
+ CString namedLoc;
+ namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
+
+ CStringA namedLocA(namedLoc);
+ const char *str = (const char *) namedLocA;
+ char pathBuffer[2 * MAX_PATH];
+ strncpy(pathBuffer, str, sizeof(pathBuffer) - 1);
+ pathBuffer[sizeof(pathBuffer) - 1] = 0;
+ PathQuoteSpaces(pathBuffer);
+
+ SetCurrent(IDS_CREATE_SERVICE);
+ hService = CreateService(hSCManager, BIND_SERVICE_NAME,
+ BIND_DISPLAY_NAME, SERVICE_ALL_ACCESS, dwServiceType, dwStart,
+ SERVICE_ERROR_NORMAL, pathBuffer, NULL, NULL, NULL, StartName,
+ m_accountPassword);
+
+ if (!hService && GetLastError() != ERROR_SERVICE_EXISTS)
+ throw(Exception(IDS_ERR_CREATE_SERVICE, GetErrMessage()));
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ SetItemStatus(IDC_REG_SERVICE);
+}
+
+void
+CBINDInstallDlg::UpdateService(CString StartName) {
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+
+ if(m_toolsOnly)
+ return;
+
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ return;
+ }
+
+ DWORD dwStart = SERVICE_DEMAND_START;
+ if (m_autoStart)
+ dwStart = SERVICE_AUTO_START;
+
+ DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+
+ CString namedLoc;
+ namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
+
+ CStringA namedLocA(namedLoc);
+ const char *str = (const char *) namedLocA;
+ char pathBuffer[2 * MAX_PATH];
+ strncpy(pathBuffer, str, sizeof(pathBuffer) - 1);
+ pathBuffer[sizeof(pathBuffer) - 1] = 0;
+ PathQuoteSpaces(pathBuffer);
+
+ SetCurrent(IDS_OPEN_SERVICE);
+ hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_CHANGE_CONFIG);
+ if (!hService)
+ {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+ return;
+ } else {
+ if (ChangeServiceConfig(hService, dwServiceType, dwStart,
+ SERVICE_ERROR_NORMAL, pathBuffer, NULL, NULL, NULL,
+ StartName, m_accountPassword, BIND_DISPLAY_NAME)
+ != TRUE) {
+ MsgBox(IDS_ERR_UPDATE_SERVICE, GetErrMessage());
+ }
+ }
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ SetItemStatus(IDC_REG_SERVICE);
+}
+
+void CBINDInstallDlg::UnregisterService(BOOL uninstall) {
+ BOOL rc = FALSE;
+ SC_HANDLE hSCManager;
+ SC_HANDLE hService;
+
+ while(1) {
+ SetCurrent(IDS_OPEN_SCM);
+ hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager && uninstall == TRUE) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ break;
+ }
+
+ SetCurrent(IDS_OPEN_SERVICE);
+ hService = OpenService(hSCManager, BIND_SERVICE_NAME,
+ STANDARD_RIGHTS_REQUIRED);
+ if (!hService && uninstall == TRUE)
+ {
+ if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ break;
+ }
+ }
+ else {
+ SetCurrent(IDS_REMOVE_SERVICE);
+ if (!DeleteService(hService) && uninstall == TRUE) {
+ DWORD err = GetLastError();
+ if (err != ERROR_SERVICE_MARKED_FOR_DELETE &&
+ err != ERROR_SERVICE_DOES_NOT_EXIST) {
+ MsgBox(IDS_ERR_REMOVE_SERVICE,
+ GetErrMessage());
+ break;
+ }
+ }
+ }
+
+ rc = TRUE;
+ break;
+ }
+
+ if (hService)
+ CloseServiceHandle(hService);
+
+ if (hSCManager)
+ CloseServiceHandle(hSCManager);
+
+ if (uninstall)
+ SetItemStatus(IDC_REG_SERVICE, rc);
+}
+
+void CBINDInstallDlg::RegisterMessages() {
+ HKEY hKey;
+ DWORD dwData;
+ char pszMsgDLL[MAX_PATH];
+ int n;
+
+ n = snprintf(pszMsgDLL, sizeof(pszMsgDLL), "%s\\%s",
+ (LPCTSTR)m_binDir, "bindevt.dll");
+ if (n < 0 || (size_t)n >= sizeof(pszMsgDLL))
+ throw(Exception(IDS_ERR_CREATE_KEY,
+ "<m_binDir>\\bindevt.dll too long"));
+
+ SetCurrent(IDS_REGISTER_MESSAGES);
+ /* Create a new key for named */
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_MESSAGE_SUBKEY, &hKey)
+ != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_CREATE_KEY, GetErrMessage()));
+
+ /* Add the Event-ID message-file name to the subkey. */
+ if (RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ,
+ (LPBYTE)pszMsgDLL, (DWORD)(strlen(pszMsgDLL) + 1)) != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
+
+ /* Set the supported types flags and addit to the subkey. */
+ dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
+ if (RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD,
+ (LPBYTE)&dwData, sizeof(DWORD)) != ERROR_SUCCESS)
+ throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
+
+ RegCloseKey(hKey);
+
+ SetItemStatus(IDC_REG_MESSAGE);
+}
+
+void CBINDInstallDlg::UnregisterMessages(BOOL uninstall) {
+ BOOL rc = FALSE;
+ HKEY hKey = NULL;
+
+ while(1) {
+ SetCurrent(IDS_UNREGISTER_MESSAGES);
+ /* Open key for Application Event Log */
+ if (RegOpenKey(HKEY_LOCAL_MACHINE, EVENTLOG_APP_SUBKEY, &hKey)
+ != ERROR_SUCCESS)
+ break;
+
+ /* Remove named from the list of messages sources */
+ if (RegDeleteKey(hKey, BIND_MESSAGE_NAME) != ERROR_SUCCESS)
+ break;
+
+ rc = TRUE;
+ break;
+ }
+
+ if (hKey)
+ RegCloseKey(hKey);
+
+ if (uninstall)
+ SetItemStatus(IDC_REG_MESSAGE, rc);
+}
+
+/*
+ * Install failed - clean up quietly
+ */
+void CBINDInstallDlg::FailedInstall() {
+ UnregisterMessages(FALSE);
+ UnregisterService(FALSE);
+ DeleteFiles(FALSE);
+ RemoveDirs(FALSE);
+}
+
+/*
+ * Set the checklist tags for install
+ */
+void CBINDInstallDlg::InstallTags() {
+ CString tag;
+
+ tag.LoadString(IDS_INSTALL_FILE);
+ GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
+
+ tag.LoadString(IDS_INSTALL_DIR);
+ GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
+ GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
+
+ tag.LoadString(IDS_INSTALL_SERVICE);
+ GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
+
+ tag.LoadString(IDS_INSTALL_MESSAGE);
+ GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
+}
+
+/*
+ * Set the checklist tags for uninstall
+ */
+void CBINDInstallDlg::UninstallTags() {
+ CString tag;
+
+ tag.LoadString(IDS_UNINSTALL_FILES);
+ GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_DIR);
+ GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_SERVICE);
+ GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
+
+ tag.LoadString(IDS_UNINSTALL_MESSAGE);
+ GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
+ GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
+}
+
+void CBINDInstallDlg::SetItemStatus(UINT nID, BOOL bSuccess) {
+ GetDlgItem(nID)->SetWindowText(bSuccess == TRUE ? "Done" : "Failed");
+}
+
+
+/*
+ * Set the text in the current operation field - use a string table string
+ */
+void CBINDInstallDlg::SetCurrent(int id, ...) {
+ CString format;
+ va_list va;
+ char buf[128];
+
+ format.LoadString(id);
+ memset(buf, 0, 128);
+
+ va_start(va, id);
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+ buf[sizeof(buf) - 1] = 0;
+ va_end(va);
+
+ m_current.Format("%s", buf);
+ UpdateData(FALSE);
+}
+
+/*
+ * Stop the BIND service
+ */
+void CBINDInstallDlg::StopBINDService() {
+ SERVICE_STATUS svcStatus;
+
+ SetCurrent(IDS_STOP_SERVICE);
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ }
+
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hBINDSvc) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ }
+
+ BOOL rc = ControlService(hBINDSvc, SERVICE_CONTROL_STOP, &svcStatus);
+ if (!rc) {
+ MsgBox(IDS_ERR_STOP_SERVICE, GetErrMessage());
+ }
+}
+
+/*
+ * Start the BIND service
+ */
+void CBINDInstallDlg::StartBINDService() {
+ SetCurrent(IDS_START_SERVICE);
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (!hSCManager) {
+ MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
+ }
+
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (!hBINDSvc) {
+ MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
+ }
+ BOOL rc = StartService(hBINDSvc, 0, NULL);
+ if (!rc) {
+ MsgBox(IDS_ERR_START_SERVICE, GetErrMessage());
+ }
+}
+
+/*
+ * Check to see if the BIND service is running or not
+ */
+BOOL
+CBINDInstallDlg::CheckBINDService() {
+ SERVICE_STATUS svcStatus;
+
+ SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+ if (hSCManager) {
+ SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
+ SERVICE_ALL_ACCESS);
+ if (hBINDSvc) {
+ BOOL rc = ControlService(hBINDSvc,
+ SERVICE_CONTROL_INTERROGATE,
+ &svcStatus);
+ if (!rc) {
+ /* cppcheck-suppress unreadVariable */
+ DWORD err = GetLastError();
+ }
+
+ return (rc &&
+ svcStatus.dwCurrentState == SERVICE_RUNNING);
+ }
+ }
+ return (FALSE);
+}
+
+/*
+ * Display message boxes with variable args, using string table strings
+ * for the format specifiers
+ */
+int CBINDInstallDlg::MsgBox(int id, ...) {
+ CString format;
+ va_list va;
+ char buf[BUFSIZ];
+
+ format.LoadString(id);
+ memset(buf, 0, BUFSIZ);
+
+ va_start(va, id);
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+ buf[sizeof(buf) - 1] = 0;
+ va_end(va);
+
+ return (MessageBox(buf));
+}
+
+int CBINDInstallDlg::MsgBox(int id, UINT type, ...) {
+ CString format;
+ va_list va;
+ char buf[BUFSIZ];
+
+ format.LoadString(id);
+ memset(buf, 0, BUFSIZ);
+
+ va_start(va, type);
+ (void)vsnprintf(buf, sizeof(buf), format, va);
+ buf[sizeof(buf) - 1] = 0;
+ va_end(va);
+
+ return(MessageBox(buf, NULL, type));
+}
+
+/*
+ * Call GetLastError(), retrieve the message associated with the error
+ */
+CString CBINDInstallDlg::GetErrMessage(DWORD err) {
+ LPVOID msgBuf;
+ static char buf[BUFSIZ];
+
+ DWORD len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, err == -1 ? GetLastError() : err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msgBuf, 0, NULL );
+
+
+ strcpy(buf, (LPTSTR)msgBuf);
+ LocalFree(msgBuf);
+ /* Strip off the period and the \n */
+ buf[len - 3] = 0;
+ return(buf);
+}
+
+void CBINDInstallDlg::ProgramGroupCreate(TCHAR *commonPath) {
+ HRESULT hres;
+ IShellLink *psl = NULL;
+ ITEMIDLIST *itemList = NULL;
+ TCHAR fileloc[MAX_PATH];
+ TCHAR linkpath[MAX_PATH];
+ TCHAR path[MAX_PATH];
+ int n;
+
+ n = snprintf(path, sizeof(path), "%s\\ISC", commonPath);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ return;
+ CreateDirectory(path, NULL);
+
+ n = snprintf(path, sizeof(path), "%s\\ISC\\BIND", commonPath);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ return;
+ CreateDirectory(path, NULL);
+
+ hres = CoInitialize(NULL);
+ if (!SUCCEEDED(hres))
+ return;
+
+ // Get a pointer to the IShellLink interface.
+ hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+ IID_IShellLink, (LPVOID *)&psl);
+ if (!SUCCEEDED(hres)) {
+ goto cleanup;
+ }
+
+ IPersistFile* ppf;
+ n = snprintf(linkpath, sizeof(linkpath), "%s\\BINDCtrl.lnk", path);
+ if (n < 0 || (size_t)n >= sizeof(path)) {
+ goto cleanup;
+ }
+
+ n = snprintf(fileloc, sizeof(fileloc), "%s\\BINDCtrl.exe",
+ (LPCTSTR) m_binDir);
+ if (n < 0 || (size_t)n >= sizeof(path)) {
+ goto cleanup;
+ }
+
+ psl->SetPath(fileloc);
+ psl->SetDescription("BIND Control Panel");
+
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ WCHAR wsz[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
+ hres = ppf->Save(wsz, TRUE);
+ ppf->Release();
+ }
+
+ if (GetFileAttributes("readme.txt") == -1) {
+ goto cleanup;
+ }
+
+ n = snprintf(fileloc, sizeof(fileloc), "%s\\Readme.txt",
+ (LPCTSTR) m_targetDir);
+ if (n < 0 || (size_t)n >= sizeof(fileloc)) {
+ goto cleanup;
+ }
+
+ n = snprintf(linkpath, sizeof(linkpath), "%s\\Readme.lnk", path);
+ if (n < 0 || (size_t)n >= sizeof(linkpath)) {
+ goto cleanup;
+ }
+
+ psl->SetPath(fileloc);
+ psl->SetDescription("BIND Readme");
+
+ hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
+ if (SUCCEEDED(hres)) {
+ WCHAR wsz[MAX_PATH];
+
+ MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
+ hres = ppf->Save(wsz, TRUE);
+ ppf->Release();
+ }
+
+ cleanup:
+ if (psl)
+ psl->Release();
+ CoUninitialize();
+}
+
+void CBINDInstallDlg::ProgramGroupRemove(TCHAR *commonPath) {
+ HANDLE hFind;
+ TCHAR filename[MAX_PATH];
+ TCHAR path[MAX_PATH];
+ WIN32_FIND_DATA fd;
+ int n;
+
+ n = snprintf(path, sizeof(path), "%s\\ISC\\BIND", commonPath);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ goto remove_isc;
+
+ n = snprintf(filename, sizeof(filename), "%s\\*.*", path);
+ if (n < 0 || (size_t)n >= sizeof(path))
+ goto remove_isc_bind;
+
+ hFind = FindFirstFile(filename, &fd);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ do {
+ if (strcmp(fd.cFileName, ".") == 0 ||
+ strcmp(fd.cFileName, "..") == 0)
+ continue;
+ n = snprintf(filename, sizeof(filename), "%s\\%s",
+ path, fd.cFileName);
+ if (n >= 0 && (size_t)n < sizeof(filename)) {
+ DeleteFile(filename);
+ }
+ } while (FindNextFile(hFind, &fd));
+ FindClose(hFind);
+ }
+
+ remove_isc_bind:
+ RemoveDirectory(path);
+
+ remove_isc:
+ n = snprintf(path, sizeof(path), "%s\\ISC", commonPath);
+ if (n >= 0 && (size_t)n < sizeof(path))
+ RemoveDirectory(path);
+}
+
+void CBINDInstallDlg::ProgramGroup(BOOL create) {
+ HRESULT hr;
+ ITEMIDLIST *itemList = NULL;
+ LPMALLOC pMalloc = NULL;
+ TCHAR commonPath[MAX_PATH];
+
+ hr = SHGetMalloc(&pMalloc);
+ if (hr != NOERROR) {
+ MessageBox("Could not get a handle to Shell memory object");
+ return;
+ }
+
+ hr = SHGetSpecialFolderLocation(m_hWnd, CSIDL_COMMON_PROGRAMS,
+ &itemList);
+ if (hr != NOERROR) {
+ MessageBox("Could not get a handle to the Common Programs "
+ "folder");
+ if (itemList) {
+ pMalloc->Free(itemList);
+ }
+ return;
+ }
+
+ if (SHGetPathFromIDList(itemList, commonPath)) {
+ if (create) {
+ ProgramGroupCreate(commonPath);
+ } else {
+ ProgramGroupRemove(commonPath);
+ }
+ } else {
+ MessageBox("SHGetPathFromIDList failed");
+ }
+ pMalloc->Free(itemList);
+}
+
+CString CBINDInstallDlg::DestDir(int destination) {
+ switch(destination) {
+ case FileData::TargetDir:
+ return m_targetDir;
+ case FileData::BinDir:
+ return m_binDir;
+ case FileData::EtcDir:
+ return m_etcDir;
+ case FileData::WinSystem:
+ return m_winSysDir;
+ }
+ return("");
+}