1 /*
2 * Portions Copyright (C) 2004-2010, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 2001, 2003 Internet Software Consortium.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /* Id: BINDInstallDlg.cpp,v 1.48 2010/01/07 23:48:54 tbox Exp */
19
20 /*
21 * Copyright (c) 1999-2000 by Nortel Networks Corporation
22 *
23 * Permission to use, copy, modify, and distribute this software for any
24 * purpose with or without fee is hereby granted, provided that the above
25 * copyright notice and this permission notice appear in all copies.
26 *
27 * THE SOFTWARE IS PROVIDED "AS IS" AND NORTEL NETWORKS DISCLAIMS
28 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
29 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NORTEL NETWORKS
30 * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
31 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
32 * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
33 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
34 * SOFTWARE.
35 */
36
37 /*
38 * Define this to make a standalone installer that will copy msvcrt.dll
39 * and/or msvcrtd.dll during the install
40 */
41 // #define BINARIES_INSTALL
42
43 /*
44 * msvcrt.dll is the release c-runtime library for MSVC. msvcrtd.dll
45 * is the debug c-runtime library for MSVC. If you have debug
46 * binaries you want to have DEBUG_BINARIES defined. If you have
47 * release binaries you want to have RELEASE_BINARIES defined.
48 * If you have both, then define them both.
49 * Of course, you need msvcrt[d].dll present to install it!
50 */
51 #ifdef BINARIES_INSTALL
52 // # define DEBUG_BINARIES
53 // # define RELEASE_BINARIES
54 #endif
55
56 #include "stdafx.h"
57 #include "BINDInstall.h"
58 #include "BINDInstallDlg.h"
59 #include "DirBrowse.h"
60 #include <winsvc.h>
61 #include <shlobj.h>
62 #include <named/ntservice.h>
63 #include <isc/bind_registry.h>
64 #include <isc/ntgroups.h>
65 #include <direct.h>
66 #include "AccountInfo.h"
67 #include "versioninfo.h"
68
69 #include <config.h>
70
71 #define MAX_GROUPS 100
72 #define MAX_PRIVS 50
73
74 #define LOCAL_SERVICE "NT AUTHORITY\\LocalService"
75
76 #ifdef _DEBUG
77 #define new DEBUG_NEW
78 #undef THIS_FILE
79 static char THIS_FILE[] = __FILE__;
80 #endif
81
82 typedef struct _xexception
83 {
84 _xexception(UINT string, ...);
85
86 CString resString;
87 } Exception;
88
_xexception(UINT string,...)89 _xexception::_xexception(UINT string, ...)
90 {
91 CString format;
92 va_list va;
93
94 format.LoadString(string);
95
96 va_start(va, string);
97 resString.FormatV(format, va);
98 va_end(va);
99 }
100
101 typedef struct _filedata {
102 enum FileDestinations {TargetDir, BinDir, EtcDir, WinSystem};
103 enum FileImportance {Trivial, Normal, Critical};
104
105 char *filename;
106 int destination;
107 int importance;
108 BOOL checkVer;
109 BOOL withTools;
110 } FileData;
111
112 const FileData installFiles[] =
113 {
114 #ifdef BINARIES_INSTALL
115 # ifdef DEBUG_BINARIES
116 {"msvcrtd.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
117 # endif
118 # ifdef RELEASE_BINARIES
119 {"msvcrt.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
120 # endif
121 #endif
122 #if _MSC_VER < 1400
123 #if _MSC_VER >= 1310
124 {"mfc71.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
125 {"msvcr71.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
126 #elif _MSC_VER > 1200 && _MSC_VER < 1310
127 {"mfc70.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
128 {"msvcr70.dll", FileData::WinSystem, FileData::Critical, TRUE, TRUE},
129 #endif
130 #endif
131 {"bindevt.dll", FileData::BinDir, FileData::Normal, FALSE, TRUE},
132 {"libbind9.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
133 {"libisc.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
134 {"libisccfg.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
135 {"libisccc.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
136 {"libdns.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
137 {"liblwres.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
138 {"libirs.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
139 #ifdef OPENSSL
140 {"libeay32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
141 #endif
142 #ifdef HAVE_LIBXML2
143 {"libxml2.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
144 #endif
145 #ifdef USE_GSSAPI
146 #ifndef _WIN64
147 {"gssapi32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
148 {"krb5_32.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
149 #else
150 {"gssapi64.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
151 {"krb5_64.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
152 #endif
153 #endif
154 #ifdef HAVE_GEOIP
155 {"libgeoip.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
156 #endif
157 #ifdef WITH_IDN
158 {"idnkit.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
159 {"iconv.dll", FileData::BinDir, FileData::Critical, FALSE, TRUE},
160 #endif
161 {"named.exe", FileData::BinDir, FileData::Critical, FALSE, FALSE},
162 {"nsupdate.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
163 {"BINDInstall.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
164 {"rndc.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
165 {"dig.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
166 {"host.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
167 {"nslookup.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
168 {"delv.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
169 {"arpaname.exe", FileData::BinDir, FileData::Normal, FALSE, TRUE},
170 {"nsec3hash.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
171 {"genrandom.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
172 {"rndc-confgen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
173 {"ddns-confgen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
174 {"tsig-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
175 {"dnssec-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
176 {"dnssec-signzone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
177 {"dnssec-dsfromkey.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
178 {"dnssec-importkey.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
179 {"dnssec-keyfromlabel.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
180 {"dnssec-revoke.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
181 {"dnssec-settime.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
182 {"dnssec-verify.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
183 {"named-checkconf.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
184 {"named-checkzone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
185 {"named-compilezone.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
186 {"named-journalprint.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
187 {"named-rrchecker.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
188 {"isc-hmax-fixup.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
189 #ifdef USE_PKCS11
190 {"pkcs11-destroy.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
191 {"pkcs11-keygen.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
192 {"pkcs11-list.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
193 {"pkcs11-tokens.exe", FileData::BinDir, FileData::Normal, FALSE, FALSE},
194 #endif
195 #ifdef USE_PYTHON
196 {"dnssec-checkds.py", FileData::BinDir, FileData::Normal, FALSE, FALSE},
197 {"dnssec-coverage.py", FileData::BinDir, FileData::Normal, FALSE, FALSE},
198 #endif
199 {"readme1st.txt", FileData::BinDir, FileData::Trivial, FALSE, TRUE},
200 {NULL, -1, -1}
201 };
202
203 /////////////////////////////////////////////////////////////////////////////
204 // CBINDInstallDlg dialog
205
CBINDInstallDlg(CWnd * pParent)206 CBINDInstallDlg::CBINDInstallDlg(CWnd* pParent /*=NULL*/)
207 : CDialog(CBINDInstallDlg::IDD, pParent) {
208 char winsys[MAX_PATH];
209 char progfiles[MAX_PATH];
210
211 //{{AFX_DATA_INIT(CBINDInstallDlg)
212 m_targetDir = _T("");
213 m_version = _T("");
214 m_toolsOnly = FALSE;
215 m_autoStart = FALSE;
216 m_keepFiles = FALSE;
217 m_current = _T("");
218 m_startOnInstall = FALSE;
219 m_accountName = _T("");
220 m_accountPassword = _T("");
221 m_accountName = _T("");
222 //}}AFX_DATA_INIT
223 // Note that LoadIcon does not require a subsequent
224 // DestroyIcon in Win32
225 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
226
227 GetSystemDirectory(winsys, MAX_PATH);
228 m_winSysDir = winsys;
229
230 #ifndef _WIN64
231 SHGetFolderPath(NULL, CSIDL_FLAG_CREATE|CSIDL_PROGRAM_FILESX86,
232 NULL, SHGFP_TYPE_CURRENT, progfiles);
233 #else
234 SHGetFolderPath(NULL, CSIDL_FLAG_CREATE|CSIDL_PROGRAM_FILES,
235 NULL, SHGFP_TYPE_CURRENT, progfiles);
236 #endif
237
238 m_defaultDir = progfiles;
239 m_defaultDir += "\\ISC BIND 9";
240 m_installed = FALSE;
241 m_accountExists = FALSE;
242 m_accountUsed = FALSE;
243 m_serviceExists = TRUE;
244 GetCurrentServiceAccountName();
245 m_currentAccount = m_accountName;
246 if (m_accountName == "") {
247 m_accountName = "named";
248 }
249 }
250
DoDataExchange(CDataExchange * pDX)251 void CBINDInstallDlg::DoDataExchange(CDataExchange* pDX) {
252 CDialog::DoDataExchange(pDX);
253 //{{AFX_DATA_MAP(CBINDInstallDlg)
254 DDX_Text(pDX, IDC_TARGETDIR, m_targetDir);
255 DDX_Text(pDX, IDC_VERSION, m_version);
256 DDX_Text(pDX, IDC_ACCOUNT_NAME, m_accountName);
257 DDX_Text(pDX, IDC_ACCOUNT_PASSWORD, m_accountPassword);
258 DDX_Text(pDX, IDC_ACCOUNT_PASSWORD_CONFIRM, m_accountPasswordConfirm);
259 DDX_Check(pDX, IDC_TOOLS_ONLY, m_toolsOnly);
260 DDX_Check(pDX, IDC_AUTO_START, m_autoStart);
261 DDX_Check(pDX, IDC_KEEP_FILES, m_keepFiles);
262 DDX_Text(pDX, IDC_CURRENT, m_current);
263 DDX_Check(pDX, IDC_START, m_startOnInstall);
264 //}}AFX_DATA_MAP
265 }
266
BEGIN_MESSAGE_MAP(CBINDInstallDlg,CDialog)267 BEGIN_MESSAGE_MAP(CBINDInstallDlg, CDialog)
268 //{{AFX_MSG_MAP(CBINDInstallDlg)
269 ON_WM_PAINT()
270 ON_WM_QUERYDRAGICON()
271 ON_BN_CLICKED(IDC_BROWSE, OnBrowse)
272 ON_BN_CLICKED(IDC_INSTALL, OnInstall)
273 ON_BN_CLICKED(IDC_EXIT, OnExit)
274 ON_BN_CLICKED(IDC_UNINSTALL, OnUninstall)
275 //}}AFX_MSG_MAP
276 END_MESSAGE_MAP()
277
278 /////////////////////////////////////////////////////////////////////////////
279 // CBINDInstallDlg message handlers
280
281 BOOL CBINDInstallDlg::OnInitDialog() {
282 CDialog::OnInitDialog();
283
284 // Set the icon for this dialog. The framework does this automatically
285 // when the application's main window is not a dialog
286 SetIcon(m_hIcon, TRUE); // Set big icon
287 SetIcon(m_hIcon, FALSE); // Set small icon
288
289 char filename[MAX_PATH];
290 char dirname[MAX_PATH];
291 char *fptr = &filename[0];
292 GetModuleFileName(NULL, filename, MAX_PATH);
293 char *dptr = strrchr(filename,'\\');
294 size_t index = dptr - fptr;
295 strncpy(dirname, filename, index);
296 dirname[index] = '\0';
297 CString Dirname(dirname);
298 m_currentDir = Dirname;
299
300 CVersionInfo bindInst(filename);
301 if(bindInst.IsValid())
302 m_version.Format(IDS_VERSION, bindInst.GetFileVersionString());
303 else
304 m_version.LoadString(IDS_NO_VERSION);
305
306 DWORD dwBufLen = MAX_PATH;
307 char buf[MAX_PATH];
308 HKEY hKey;
309
310 m_startOnInstall = CheckBINDService();
311
312 /* See if we are installed already */
313 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SUBKEY, 0, KEY_READ, &hKey)
314 == ERROR_SUCCESS) {
315 m_installed = TRUE;
316 memset(buf, 0, MAX_PATH);
317 // Get the install directory
318 if (RegQueryValueEx(hKey, "InstallDir", NULL, NULL, (LPBYTE)buf,
319 &dwBufLen) == ERROR_SUCCESS)
320 if (strcmp(buf, ""))
321 m_defaultDir = buf;
322
323 RegCloseKey(hKey);
324 }
325 m_targetDir = m_defaultDir;
326
327 // Set checkbox defaults
328 m_autoStart = TRUE;
329 m_keepFiles = TRUE;
330
331 UpdateData(FALSE);
332
333 return (TRUE); /* return(TRUE) unless you set the focus to a control */
334 }
335
336 /*
337 * If you add a minimize button to your dialog, you will need the code below
338 * to draw the icon. For MFC applications using the document/view model,
339 * this is automatically done for you by the framework.
340 */
341
OnPaint()342 void CBINDInstallDlg::OnPaint() {
343 if (IsIconic()) {
344 CPaintDC dc(this); // device context for painting
345
346 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
347
348 // Center icon in client rectangle
349 int cxIcon = GetSystemMetrics(SM_CXICON);
350 int cyIcon = GetSystemMetrics(SM_CYICON);
351 CRect rect;
352 GetClientRect(&rect);
353 int x = (rect.Width() - cxIcon + 1) / 2;
354 int y = (rect.Height() - cyIcon + 1) / 2;
355
356 // Draw the icon
357 dc.DrawIcon(x, y, m_hIcon);
358 }
359 else {
360 CDialog::OnPaint();
361 }
362 }
363
364 // The system calls this to obtain the cursor to display while the user drags
365 // the minimized window.
OnQueryDragIcon()366 HCURSOR CBINDInstallDlg::OnQueryDragIcon() {
367 return((HCURSOR)m_hIcon);
368 }
369
OnBrowse()370 void CBINDInstallDlg::OnBrowse() {
371
372 CDirBrowse browse;
373
374 if (browse.DoModal() == IDOK) {
375 //m_targetDir = browse.m_selectedDir;
376 UpdateData(FALSE);
377 }
378 }
379
380 /*
381 * User pressed the exit button
382 */
OnExit()383 void CBINDInstallDlg::OnExit() {
384 EndDialog(0);
385 }
386
387 /*
388 * User pressed the uninstall button. Make it go.
389 */
OnUninstall()390 void CBINDInstallDlg::OnUninstall() {
391 UpdateData();
392
393 if (MsgBox(IDS_UNINSTALL, MB_YESNO) == IDYES) {
394 if (CheckBINDService())
395 StopBINDService();
396
397 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL,
398 SC_MANAGER_ALL_ACCESS);
399 if (!hSCManager) {
400 MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
401 return;
402 }
403
404 SC_HANDLE hService = OpenService(hSCManager, BIND_SERVICE_NAME,
405 SERVICE_ALL_ACCESS);
406 if (!hService && GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST){
407 MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
408 return;
409 }
410
411 SERVICE_STATUS ss;
412 QueryServiceStatus(hService, &ss);
413 if (ss.dwCurrentState == SERVICE_RUNNING) {
414 BOOL rc = ControlService(hService,
415 SERVICE_CONTROL_STOP, &ss);
416 if (rc == FALSE || ss.dwCurrentState != SERVICE_STOPPED) {
417 MsgBox(IDS_ERR_STOP_SERVICE, GetErrMessage());
418 return;
419 }
420
421 }
422 CloseServiceHandle(hService);
423 CloseServiceHandle(hSCManager);
424
425 // Directories
426 m_etcDir = m_targetDir + "\\etc";
427 m_binDir = m_targetDir + "\\bin";
428
429 UninstallTags();
430 UnregisterMessages(TRUE);
431 UnregisterService(TRUE);
432 DeleteFiles(TRUE);
433 if (m_keepFiles == FALSE)
434 RemoveDirs(TRUE);
435 else
436 GetDlgItem(IDC_CREATE_DIR)->SetWindowText("Not Removed");
437
438
439 // Delete registry keys for named
440 RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SESSION_SUBKEY);
441 RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY);
442 RegDeleteKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY);
443
444 ProgramGroup(FALSE);
445
446 SetCurrent(IDS_UNINSTALL_DONE);
447 MsgBox(IDS_UNINSTALL_DONE);
448 }
449 }
450
451 /*
452 * User pressed the install button. Make it go.
453 */
OnInstall()454 void CBINDInstallDlg::OnInstall() {
455 #if _MSC_VER >= 1400
456 char Vcredist_x86[MAX_PATH];
457 #endif
458 BOOL success = FALSE;
459 int oldlen;
460
461 if (CheckBINDService())
462 StopBINDService();
463
464 InstallTags();
465
466 UpdateData();
467
468 if (!m_toolsOnly && m_accountName != LOCAL_SERVICE) {
469 /*
470 * Check that the Passwords entered match.
471 */
472 if (m_accountPassword != m_accountPasswordConfirm) {
473 MsgBox(IDS_ERR_PASSWORD);
474 return;
475 }
476
477 /*
478 * Check that there is not leading / trailing whitespace.
479 * This is for compatibility with the standard password dialog.
480 * Passwords really should be treated as opaque blobs.
481 */
482 oldlen = m_accountPassword.GetLength();
483 m_accountPassword.TrimLeft();
484 m_accountPassword.TrimRight();
485 if (m_accountPassword.GetLength() != oldlen) {
486 MsgBox(IDS_ERR_WHITESPACE);
487 return;
488 }
489
490 /*
491 * Check the entered account name.
492 */
493 if (ValidateServiceAccount() == FALSE)
494 return;
495
496 /*
497 * For Registration we need to know if account was changed.
498 */
499 if (m_accountName != m_currentAccount)
500 m_accountUsed = FALSE;
501
502 if (m_accountUsed == FALSE && m_serviceExists == FALSE)
503 {
504 /*
505 * Check that the Password is not null.
506 */
507 if (m_accountPassword.GetLength() == 0) {
508 MsgBox(IDS_ERR_NULLPASSWORD);
509 return;
510 }
511 }
512 } else if (m_accountName == LOCAL_SERVICE) {
513 /* The LocalService always exists. */
514 m_accountExists = TRUE;
515 if (m_accountName != m_currentAccount)
516 m_accountUsed = FALSE;
517 }
518
519 /* Directories */
520 m_etcDir = m_targetDir + "\\etc";
521 m_binDir = m_targetDir + "\\bin";
522
523 if (m_defaultDir != m_targetDir) {
524 if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
525 {
526 int install = MsgBox(IDS_DIREXIST,
527 MB_YESNO | MB_ICONQUESTION, m_targetDir);
528 if (install == IDNO)
529 return;
530 }
531 else {
532 int createDir = MsgBox(IDS_CREATEDIR,
533 MB_YESNO | MB_ICONQUESTION, m_targetDir);
534 if (createDir == IDNO)
535 return;
536 }
537 }
538
539 if (!m_toolsOnly) {
540 if (m_accountExists == FALSE) {
541 success = CreateServiceAccount(m_accountName.GetBuffer(30),
542 m_accountPassword.GetBuffer(30));
543 if (success == FALSE) {
544 MsgBox(IDS_CREATEACCOUNT_FAILED);
545 return;
546 }
547 m_accountExists = TRUE;
548 }
549 }
550
551 ProgramGroup(FALSE);
552
553 #if _MSC_VER >= 1400
554 /*
555 * Install Visual Studio libraries. As per:
556 * http://blogs.msdn.com/astebner/archive/2006/08/23/715755.aspx
557 *
558 * Vcredist_x86.exe /q:a /c:"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log"
559 */
560 /*system(".\\Vcredist_x86.exe /q:a /c:\"msiexec /i vcredist.msi /qn /l*v %temp%\vcredist_x86.log\"");*/
561
562 /*
563 * Enclose full path to Vcredist_x86.exe in quotes as
564 * m_currentDir may contain spaces.
565 */
566 #ifndef _WIN64
567 sprintf(Vcredist_x86, "\"%s\\Vcredist_x86.exe\"",
568 (LPCTSTR) m_currentDir);
569 #else
570 sprintf(Vcredist_x86, "\"%s\\Vcredist_x64.exe\"",
571 (LPCTSTR) m_currentDir);
572 #endif
573 system(Vcredist_x86);
574 #endif
575 try {
576 CreateDirs();
577 CopyFiles();
578 if (!m_toolsOnly)
579 RegisterService();
580 RegisterMessages();
581
582 HKEY hKey;
583
584 /* Create a new key for named */
585 SetCurrent(IDS_CREATE_KEY);
586 if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_SUBKEY,
587 &hKey) == ERROR_SUCCESS) {
588 // Get the install directory
589 RegSetValueEx(hKey, "InstallDir", 0, REG_SZ,
590 (LPBYTE)(LPCTSTR)m_targetDir,
591 m_targetDir.GetLength());
592 RegCloseKey(hKey);
593 }
594
595
596 SetCurrent(IDS_ADD_REMOVE);
597 if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_UNINSTALL_SUBKEY,
598 &hKey) == ERROR_SUCCESS) {
599 CString buf(BIND_DISPLAY_NAME);
600
601 RegSetValueEx(hKey, "DisplayName", 0, REG_SZ,
602 (LPBYTE)(LPCTSTR)buf, buf.GetLength());
603
604 buf.Format("%s\\BINDInstall.exe", m_binDir);
605 RegSetValueEx(hKey, "UninstallString", 0, REG_SZ,
606 (LPBYTE)(LPCTSTR)buf, buf.GetLength());
607 RegCloseKey(hKey);
608 }
609
610 ProgramGroup(FALSE);
611
612 if (m_startOnInstall)
613 StartBINDService();
614 }
615 catch(Exception e) {
616 MessageBox(e.resString);
617 SetCurrent(IDS_CLEANUP);
618 FailedInstall();
619 MsgBox(IDS_FAIL);
620 return;
621 }
622 catch(DWORD dw) {
623 CString msg;
624 msg.Format("A fatal error occured\n(%s)", GetErrMessage(dw));
625 MessageBox(msg);
626 SetCurrent(IDS_CLEANUP);
627 FailedInstall();
628 MsgBox(IDS_FAIL);
629 return;
630 }
631
632 SetCurrent(IDS_INSTALL_DONE);
633 MsgBox(IDS_SUCCESS);
634 }
635
636 /*
637 * Methods to do the work
638 */
CreateDirs()639 void CBINDInstallDlg::CreateDirs() {
640 /* s'OK if the directories already exist */
641 SetCurrent(IDS_CREATE_DIR, m_targetDir);
642 if (!CreateDirectory(m_targetDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
643 throw(Exception(IDS_ERR_CREATE_DIR, m_targetDir, GetErrMessage()));
644
645 SetCurrent(IDS_CREATE_DIR, m_etcDir);
646 if (!CreateDirectory(m_etcDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
647 throw(Exception(IDS_ERR_CREATE_DIR, m_etcDir, GetErrMessage()));
648
649 SetCurrent(IDS_CREATE_DIR, m_binDir);
650 if (!CreateDirectory(m_binDir, NULL) && GetLastError() != ERROR_ALREADY_EXISTS)
651 throw(Exception(IDS_ERR_CREATE_DIR, m_binDir, GetErrMessage()));
652
653 SetItemStatus(IDC_CREATE_DIR);
654 }
655
RemoveDirs(BOOL uninstall)656 void CBINDInstallDlg::RemoveDirs(BOOL uninstall) {
657 if (!m_keepFiles) {
658 SetCurrent(IDS_REMOVE_DIR, m_binDir);
659 // Check for existence then remove if present
660 if (GetFileAttributes(m_binDir) != 0xFFFFFFFF)
661 RemoveDirectory(m_binDir);
662
663 SetCurrent(IDS_REMOVE_DIR, m_etcDir);
664 if (GetFileAttributes(m_etcDir) != 0xFFFFFFFF)
665 RemoveDirectory(m_etcDir);
666
667 SetCurrent(IDS_REMOVE_DIR, m_targetDir);
668 if (GetFileAttributes(m_targetDir) != 0xFFFFFFFF)
669 RemoveDirectory(m_targetDir);
670 }
671
672 if (uninstall)
673 SetItemStatus(IDC_CREATE_DIR, TRUE);
674 }
675
CopyFiles()676 void CBINDInstallDlg::CopyFiles() {
677 CString destFile;
678
679 for (int i = 0; installFiles[i].filename; i++) {
680 if (m_toolsOnly && !installFiles[i].withTools)
681 continue;
682 SetCurrent(IDS_COPY_FILE, installFiles[i].filename);
683
684 destFile = DestDir(installFiles[i].destination) + "\\" +
685 installFiles[i].filename;
686 CString filespec = m_currentDir + "\\" + installFiles[i].filename;
687 CVersionInfo bindFile(destFile);
688
689 CVersionInfo origFile(filespec);
690 if (!origFile.IsValid() && installFiles[i].checkVer) {
691 if (MsgBox(IDS_FILE_BAD, MB_YESNO,
692 installFiles[i].filename) == IDNO)
693 throw(Exception(IDS_ERR_COPY_FILE,
694 installFiles[i].filename,
695 GetErrMessage()));
696 }
697
698 try {
699 /*
700 * Ignore Version checking. We need to make sure that all files get
701 * copied regardless of whether or not they are earlier or later
702 * versions since we cannot guarantee that we have either backward or
703 * forward compatibility between versions.
704 */
705 bindFile.CopyFileNoVersion(origFile);
706 }
707 catch(...) {
708 if (installFiles[i].importance != FileData::Trivial) {
709 if (installFiles[i].importance ==
710 FileData::Critical ||
711 MsgBox(IDS_ERR_NONCRIT_FILE, MB_YESNO,
712 installFiles[i].filename,
713 GetErrMessage()) == IDNO)
714 {
715 SetItemStatus(IDC_COPY_FILE, FALSE);
716 throw(Exception(IDS_ERR_COPY_FILE,
717 installFiles[i].filename,
718 GetErrMessage()));
719 }
720 }
721 }
722 }
723
724 SetItemStatus(IDC_COPY_FILE);
725 }
726
DeleteFiles(BOOL uninstall)727 void CBINDInstallDlg::DeleteFiles(BOOL uninstall) {
728 CString destFile;
729
730 for (int i = 0; installFiles[i].filename; i++) {
731 if (installFiles[i].checkVer)
732 continue;
733
734 destFile = DestDir(installFiles[i].destination) + "\\" +
735 installFiles[i].filename;
736
737 if (uninstall)
738 SetCurrent(IDS_DELETE_FILE, installFiles[i].filename);
739
740 DeleteFile(destFile);
741 }
742
743 if (!m_keepFiles) {
744 WIN32_FIND_DATA findData;
745 CString file = m_etcDir + "\\*.*";
746 BOOL rc;
747 HANDLE hFile;
748
749 hFile = FindFirstFile(file, &findData);
750 rc = hFile != INVALID_HANDLE_VALUE;
751
752 while (rc == TRUE) {
753 if (strcmp(findData.cFileName, ".") &&
754 strcmp(findData.cFileName, "..")) {
755 file = m_etcDir + "\\" + findData.cFileName;
756 SetCurrent(IDS_DELETE_FILE, file);
757 DeleteFile(file);
758 }
759 rc = FindNextFile(hFile, &findData);
760 }
761 FindClose(hFile);
762 }
763
764 if (uninstall)
765 SetItemStatus(IDC_COPY_FILE, TRUE);
766 }
767
768 /*
769 * Get the service account name out of the registry, if any
770 */
771 void
GetCurrentServiceAccountName()772 CBINDInstallDlg::GetCurrentServiceAccountName() {
773 HKEY hKey;
774 BOOL keyFound = FALSE;
775 char accountName[MAX_PATH];
776 DWORD nameLen = MAX_PATH;
777 CString Tmp;
778 m_accountUsed = FALSE;
779
780 memset(accountName, 0, nameLen);
781 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, BIND_SERVICE_SUBKEY, 0, KEY_READ,
782 &hKey) == ERROR_SUCCESS) {
783 keyFound = TRUE;
784 }
785 else {
786 m_serviceExists = FALSE;
787 }
788
789 if (keyFound == TRUE) {
790 /* Get the named service account, if one was specified */
791 if (RegQueryValueEx(hKey, "ObjectName", NULL, NULL,
792 (LPBYTE)accountName, &nameLen) != ERROR_SUCCESS)
793 keyFound = FALSE;
794 }
795
796 RegCloseKey(hKey);
797 if (keyFound == FALSE)
798 m_accountName = "";
799 else if (!strcmp(accountName, LOCAL_SERVICE)) {
800 m_accountName = LOCAL_SERVICE;
801 m_accountUsed = TRUE;
802 } else {
803 /*
804 * LocalSystem is not a regular account and is equivalent
805 * to no account but with lots of privileges
806 */
807 Tmp = accountName;
808 if (Tmp == ".\\LocalSystem")
809 m_accountName = "";
810 /* Found account strip any ".\" from it */
811 if (Tmp.Left(2) == ".\\") {
812 m_accountName = Tmp.Mid(2);
813 m_accountUsed = TRUE;
814 }
815 }
816 }
817
818 BOOL
ValidateServiceAccount()819 CBINDInstallDlg::ValidateServiceAccount() {
820 wchar_t *PrivList[MAX_PRIVS];
821 unsigned int PrivCount = 0;
822 char *Groups[MAX_GROUPS];
823 unsigned int totalGroups = 0;
824 int status;
825 char *name;
826
827 name = m_accountName.GetBuffer(30);
828
829 status = GetAccountPrivileges(name, PrivList, &PrivCount,
830 Groups, &totalGroups, MAX_GROUPS);
831 if (status == RTN_NOACCOUNT) {
832 m_accountExists = FALSE;
833 /* We need to do this in case an account was previously used */
834 m_accountUsed = FALSE;
835 return (TRUE);
836 }
837 if (status != RTN_OK) {
838 MsgBox(IDS_ERR_BADACCOUNT);
839 return (FALSE);
840 }
841
842 m_accountExists = TRUE;
843 if (PrivCount > 1) {
844 if (MsgBox(IDS_ERR_TOOPRIVED, MB_YESNO) == IDYES)
845 return (FALSE);
846 else
847 return (TRUE);
848 }
849
850 /* See if we have the correct privilege */
851 if (wcscmp(PrivList[0], SE_SERVICE_LOGON_PRIV) != 0) {
852 MsgBox(IDS_ERR_WRONGPRIV, PrivList[0]);
853 return (FALSE);
854 }
855 return (TRUE);
856 }
857
858 void
RegisterService()859 CBINDInstallDlg::RegisterService() {
860 SC_HANDLE hSCManager;
861 SC_HANDLE hService;
862 CString StartName;
863
864 if (m_accountName == LOCAL_SERVICE)
865 StartName = LOCAL_SERVICE;
866 else
867 StartName = ".\\" + m_accountName;
868 /*
869 * We need to change the service rather than create it
870 * if the service already exists. Do nothing if we are already
871 * using that account
872 */
873 if (m_serviceExists == TRUE) {
874 if (m_accountUsed == FALSE) {
875 UpdateService(StartName);
876 SetItemStatus(IDC_REG_SERVICE);
877 return;
878 } else {
879 SetItemStatus(IDC_REG_SERVICE);
880 return;
881 }
882 }
883
884 SetCurrent(IDS_OPEN_SCM);
885 hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
886 if (!hSCManager)
887 throw(Exception(IDS_ERR_OPEN_SCM, GetErrMessage()));
888
889 DWORD dwStart = SERVICE_DEMAND_START;
890 if (m_autoStart)
891 dwStart = SERVICE_AUTO_START;
892
893 DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
894
895 CString namedLoc;
896 namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
897
898 SetCurrent(IDS_CREATE_SERVICE);
899 hService = CreateService(hSCManager, BIND_SERVICE_NAME,
900 BIND_DISPLAY_NAME, SERVICE_ALL_ACCESS, dwServiceType, dwStart,
901 SERVICE_ERROR_NORMAL, namedLoc, NULL, NULL, NULL, StartName,
902 m_accountPassword);
903
904 if (!hService && GetLastError() != ERROR_SERVICE_EXISTS)
905 throw(Exception(IDS_ERR_CREATE_SERVICE, GetErrMessage()));
906
907 if (hService)
908 CloseServiceHandle(hService);
909
910 if (hSCManager)
911 CloseServiceHandle(hSCManager);
912
913 SetItemStatus(IDC_REG_SERVICE);
914 }
915
916 void
UpdateService(CString StartName)917 CBINDInstallDlg::UpdateService(CString StartName) {
918 SC_HANDLE hSCManager;
919 SC_HANDLE hService;
920
921 if(m_toolsOnly)
922 return;
923
924 SetCurrent(IDS_OPEN_SCM);
925 hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
926 if (!hSCManager) {
927 MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
928 return;
929 }
930
931 DWORD dwStart = SERVICE_DEMAND_START;
932 if (m_autoStart)
933 dwStart = SERVICE_AUTO_START;
934
935 DWORD dwServiceType = SERVICE_WIN32_OWN_PROCESS;
936
937 CString namedLoc;
938 namedLoc.Format("%s\\bin\\named.exe", m_targetDir);
939
940 SetCurrent(IDS_OPEN_SERVICE);
941 hService = OpenService(hSCManager, BIND_SERVICE_NAME,
942 SERVICE_CHANGE_CONFIG);
943 if (!hService)
944 {
945 MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
946 if (hSCManager)
947 CloseServiceHandle(hSCManager);
948 return;
949 } else {
950 if (ChangeServiceConfig(hService, dwServiceType, dwStart,
951 SERVICE_ERROR_NORMAL, namedLoc, NULL, NULL, NULL,
952 StartName, m_accountPassword, BIND_DISPLAY_NAME)
953 != TRUE) {
954 DWORD err = GetLastError();
955 MsgBox(IDS_ERR_UPDATE_SERVICE, GetErrMessage());
956 }
957 }
958
959 if (hService)
960 CloseServiceHandle(hService);
961
962 if (hSCManager)
963 CloseServiceHandle(hSCManager);
964
965 SetItemStatus(IDC_REG_SERVICE);
966 }
967
UnregisterService(BOOL uninstall)968 void CBINDInstallDlg::UnregisterService(BOOL uninstall) {
969 BOOL rc = FALSE;
970 SC_HANDLE hSCManager;
971 SC_HANDLE hService;
972
973 while(1) {
974 SetCurrent(IDS_OPEN_SCM);
975 hSCManager= OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
976 if (!hSCManager && uninstall == TRUE) {
977 MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
978 break;
979 }
980
981 SetCurrent(IDS_OPEN_SERVICE);
982 hService = OpenService(hSCManager, BIND_SERVICE_NAME,
983 STANDARD_RIGHTS_REQUIRED);
984 if (!hService && uninstall == TRUE)
985 {
986 if (GetLastError() != ERROR_SERVICE_DOES_NOT_EXIST) {
987 MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
988 break;
989 }
990 }
991 else {
992 SetCurrent(IDS_REMOVE_SERVICE);
993 if (!DeleteService(hService) && uninstall == TRUE) {
994 DWORD err = GetLastError();
995 if (err != ERROR_SERVICE_MARKED_FOR_DELETE &&
996 err != ERROR_SERVICE_DOES_NOT_EXIST) {
997 MsgBox(IDS_ERR_REMOVE_SERVICE,
998 GetErrMessage());
999 break;
1000 }
1001 }
1002 }
1003
1004 rc = TRUE;
1005 break;
1006 }
1007
1008 if (hService)
1009 CloseServiceHandle(hService);
1010
1011 if (hSCManager)
1012 CloseServiceHandle(hSCManager);
1013
1014 if (uninstall)
1015 SetItemStatus(IDC_REG_SERVICE, rc);
1016 }
1017
RegisterMessages()1018 void CBINDInstallDlg::RegisterMessages() {
1019 HKEY hKey;
1020 DWORD dwData;
1021 char pszMsgDLL[MAX_PATH];
1022
1023 sprintf(pszMsgDLL, "%s\\%s", (LPCTSTR)m_binDir, "bindevt.dll");
1024
1025 SetCurrent(IDS_REGISTER_MESSAGES);
1026 /* Create a new key for named */
1027 if (RegCreateKey(HKEY_LOCAL_MACHINE, BIND_MESSAGE_SUBKEY, &hKey)
1028 != ERROR_SUCCESS)
1029 throw(Exception(IDS_ERR_CREATE_KEY, GetErrMessage()));
1030
1031 /* Add the Event-ID message-file name to the subkey. */
1032 if (RegSetValueEx(hKey, "EventMessageFile", 0, REG_EXPAND_SZ,
1033 (LPBYTE)pszMsgDLL, (DWORD)(strlen(pszMsgDLL) + 1)) != ERROR_SUCCESS)
1034 throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
1035
1036 /* Set the supported types flags and addit to the subkey. */
1037 dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
1038 if (RegSetValueEx(hKey, "TypesSupported", 0, REG_DWORD,
1039 (LPBYTE)&dwData, sizeof(DWORD)) != ERROR_SUCCESS)
1040 throw(Exception(IDS_ERR_SET_VALUE, GetErrMessage()));
1041
1042 RegCloseKey(hKey);
1043
1044 SetItemStatus(IDC_REG_MESSAGE);
1045 }
1046
UnregisterMessages(BOOL uninstall)1047 void CBINDInstallDlg::UnregisterMessages(BOOL uninstall) {
1048 BOOL rc = FALSE;
1049 HKEY hKey = NULL;
1050
1051 while(1) {
1052 SetCurrent(IDS_UNREGISTER_MESSAGES);
1053 /* Open key for Application Event Log */
1054 if (RegOpenKey(HKEY_LOCAL_MACHINE, EVENTLOG_APP_SUBKEY, &hKey)
1055 != ERROR_SUCCESS)
1056 break;
1057
1058 /* Remove named from the list of messages sources */
1059 if (RegDeleteKey(hKey, BIND_MESSAGE_NAME) != ERROR_SUCCESS)
1060 break;
1061
1062 rc = TRUE;
1063 break;
1064 }
1065
1066 if (hKey)
1067 RegCloseKey(hKey);
1068
1069 if (uninstall)
1070 SetItemStatus(IDC_REG_MESSAGE, rc);
1071 }
1072
1073 /*
1074 * Install failed - clean up quietly
1075 */
FailedInstall()1076 void CBINDInstallDlg::FailedInstall() {
1077 UnregisterMessages(FALSE);
1078 UnregisterService(FALSE);
1079 DeleteFiles(FALSE);
1080 RemoveDirs(FALSE);
1081 }
1082
1083 /*
1084 * Set the checklist tags for install
1085 */
InstallTags()1086 void CBINDInstallDlg::InstallTags() {
1087 CString tag;
1088
1089 tag.LoadString(IDS_INSTALL_FILE);
1090 GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
1091 GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
1092
1093 tag.LoadString(IDS_INSTALL_DIR);
1094 GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
1095 GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
1096 GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
1097
1098 tag.LoadString(IDS_INSTALL_SERVICE);
1099 GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
1100
1101 tag.LoadString(IDS_INSTALL_MESSAGE);
1102 GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
1103 GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
1104 }
1105
1106 /*
1107 * Set the checklist tags for uninstall
1108 */
UninstallTags()1109 void CBINDInstallDlg::UninstallTags() {
1110 CString tag;
1111
1112 tag.LoadString(IDS_UNINSTALL_FILES);
1113 GetDlgItem(IDC_COPY_TAG)->SetWindowText(tag);
1114 GetDlgItem(IDC_COPY_FILE)->SetWindowText("");
1115
1116 tag.LoadString(IDS_UNINSTALL_DIR);
1117 GetDlgItem(IDC_DIR_TAG)->SetWindowText(tag);
1118 GetDlgItem(IDC_CREATE_DIR)->SetWindowText("");
1119
1120 tag.LoadString(IDS_UNINSTALL_SERVICE);
1121 GetDlgItem(IDC_SERVICE_TAG)->SetWindowText(tag);
1122 GetDlgItem(IDC_REG_SERVICE)->SetWindowText("");
1123
1124 tag.LoadString(IDS_UNINSTALL_MESSAGE);
1125 GetDlgItem(IDC_MESSAGE_TAG)->SetWindowText(tag);
1126 GetDlgItem(IDC_REG_MESSAGE)->SetWindowText("");
1127 }
1128
SetItemStatus(UINT nID,BOOL bSuccess)1129 void CBINDInstallDlg::SetItemStatus(UINT nID, BOOL bSuccess) {
1130 GetDlgItem(nID)->SetWindowText(bSuccess == TRUE ? "Done" : "Failed");
1131 }
1132
1133
1134 /*
1135 * Set the text in the current operation field - use a string table string
1136 */
SetCurrent(int id,...)1137 void CBINDInstallDlg::SetCurrent(int id, ...) {
1138 CString format;
1139 va_list va;
1140 char buf[128];
1141
1142 format.LoadString(id);
1143 memset(buf, 0, 128);
1144
1145 va_start(va, id);
1146 vsprintf(buf, format, va);
1147 va_end(va);
1148
1149 m_current.Format("%s", buf);
1150 UpdateData(FALSE);
1151 }
1152
1153 /*
1154 * Stop the BIND service
1155 */
StopBINDService()1156 void CBINDInstallDlg::StopBINDService() {
1157 SERVICE_STATUS svcStatus;
1158
1159 SetCurrent(IDS_STOP_SERVICE);
1160
1161 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1162 if (!hSCManager) {
1163 MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
1164 }
1165
1166 SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
1167 SERVICE_ALL_ACCESS);
1168 if (!hBINDSvc) {
1169 MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
1170 }
1171
1172 BOOL rc = ControlService(hBINDSvc, SERVICE_CONTROL_STOP, &svcStatus);
1173 }
1174
1175 /*
1176 * Start the BIND service
1177 */
StartBINDService()1178 void CBINDInstallDlg::StartBINDService() {
1179 SetCurrent(IDS_START_SERVICE);
1180
1181 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1182 if (!hSCManager) {
1183 MsgBox(IDS_ERR_OPEN_SCM, GetErrMessage());
1184 }
1185
1186 SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
1187 SERVICE_ALL_ACCESS);
1188 if (!hBINDSvc) {
1189 MsgBox(IDS_ERR_OPEN_SERVICE, GetErrMessage());
1190 }
1191 BOOL rc = StartService(hBINDSvc, 0, NULL);
1192 }
1193
1194 /*
1195 * Check to see if the BIND service is running or not
1196 */
CheckBINDService()1197 BOOL CBINDInstallDlg::CheckBINDService() {
1198 SERVICE_STATUS svcStatus;
1199
1200 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1201 if (hSCManager) {
1202 SC_HANDLE hBINDSvc = OpenService(hSCManager, BIND_SERVICE_NAME,
1203 SERVICE_ALL_ACCESS);
1204 if (hBINDSvc) {
1205 BOOL rc = ControlService(hBINDSvc,
1206 SERVICE_CONTROL_INTERROGATE, &svcStatus);
1207 if (!rc)
1208 DWORD err = GetLastError();
1209
1210 return (svcStatus.dwCurrentState == SERVICE_RUNNING);
1211 }
1212 }
1213 return (FALSE);
1214 }
1215
1216 /*
1217 * Display message boxes with variable args, using string table strings
1218 * for the format specifiers
1219 */
MsgBox(int id,...)1220 int CBINDInstallDlg::MsgBox(int id, ...) {
1221 CString format;
1222 va_list va;
1223 char buf[BUFSIZ];
1224
1225 format.LoadString(id);
1226 memset(buf, 0, BUFSIZ);
1227
1228 va_start(va, id);
1229 vsprintf(buf, format, va);
1230 va_end(va);
1231
1232 return (MessageBox(buf));
1233 }
1234
MsgBox(int id,UINT type,...)1235 int CBINDInstallDlg::MsgBox(int id, UINT type, ...) {
1236 CString format;
1237 va_list va;
1238 char buf[BUFSIZ];
1239
1240 format.LoadString(id);
1241 memset(buf, 0, BUFSIZ);
1242
1243 va_start(va, type);
1244 vsprintf(buf, format, va);
1245 va_end(va);
1246
1247 return(MessageBox(buf, NULL, type));
1248 }
1249
1250 /*
1251 * Call GetLastError(), retrieve the message associated with the error
1252 */
GetErrMessage(DWORD err)1253 CString CBINDInstallDlg::GetErrMessage(DWORD err) {
1254 LPVOID msgBuf;
1255 static char buf[BUFSIZ];
1256
1257 DWORD len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
1258 NULL, err == -1 ? GetLastError() : err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msgBuf, 0, NULL );
1259
1260
1261 strcpy(buf, (LPTSTR)msgBuf);
1262 LocalFree(msgBuf);
1263 /* Strip off the period and the \n */
1264 buf[len - 3] = 0;
1265 return(buf);
1266 }
1267
ProgramGroup(BOOL create)1268 void CBINDInstallDlg::ProgramGroup(BOOL create) {
1269 TCHAR path[MAX_PATH], commonPath[MAX_PATH], fileloc[MAX_PATH], linkpath[MAX_PATH];
1270 HRESULT hres;
1271 IShellLink *psl = NULL;
1272 LPMALLOC pMalloc = NULL;
1273 ITEMIDLIST *itemList = NULL;
1274
1275 HRESULT hr = SHGetMalloc(&pMalloc);
1276 if (hr != NOERROR) {
1277 MessageBox("Could not get a handle to Shell memory object");
1278 return;
1279 }
1280
1281 hr = SHGetSpecialFolderLocation(m_hWnd, CSIDL_COMMON_PROGRAMS, &itemList);
1282 if (hr != NOERROR) {
1283 MessageBox("Could not get a handle to the Common Programs folder");
1284 if (itemList) {
1285 pMalloc->Free(itemList);
1286 }
1287 return;
1288 }
1289
1290 hr = SHGetPathFromIDList(itemList, commonPath);
1291 pMalloc->Free(itemList);
1292
1293 if (create) {
1294 sprintf(path, "%s\\ISC", commonPath);
1295 CreateDirectory(path, NULL);
1296
1297 sprintf(path, "%s\\ISC\\BIND", commonPath);
1298 CreateDirectory(path, NULL);
1299
1300 hres = CoInitialize(NULL);
1301
1302 if (SUCCEEDED(hres)) {
1303 // Get a pointer to the IShellLink interface.
1304 hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID *)&psl);
1305 if (SUCCEEDED(hres))
1306 {
1307 IPersistFile* ppf;
1308 sprintf(linkpath, "%s\\BINDCtrl.lnk", path);
1309 sprintf(fileloc, "%s\\BINDCtrl.exe", m_binDir);
1310
1311 psl->SetPath(fileloc);
1312 psl->SetDescription("BIND Control Panel");
1313
1314 hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
1315 if (SUCCEEDED(hres)) {
1316 WCHAR wsz[MAX_PATH];
1317
1318 MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
1319 hres = ppf->Save(wsz, TRUE);
1320 ppf->Release();
1321 }
1322
1323 if (GetFileAttributes("readme.txt") != -1) {
1324 sprintf(fileloc, "%s\\Readme.txt", m_targetDir);
1325 sprintf(linkpath, "%s\\Readme.lnk", path);
1326
1327 psl->SetPath(fileloc);
1328 psl->SetDescription("BIND Readme");
1329
1330 hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
1331 if (SUCCEEDED(hres)) {
1332 WCHAR wsz[MAX_PATH];
1333
1334 MultiByteToWideChar(CP_ACP, 0, linkpath, -1, wsz, MAX_PATH);
1335 hres = ppf->Save(wsz, TRUE);
1336 ppf->Release();
1337 }
1338 psl->Release();
1339 }
1340 }
1341 CoUninitialize();
1342 }
1343 }
1344 else {
1345 TCHAR filename[MAX_PATH];
1346 WIN32_FIND_DATA fd;
1347
1348 sprintf(path, "%s\\ISC\\BIND", commonPath);
1349
1350 sprintf(filename, "%s\\*.*", path);
1351 HANDLE hFind = FindFirstFile(filename, &fd);
1352 if (hFind != INVALID_HANDLE_VALUE) {
1353 do {
1354 if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) {
1355 sprintf(filename, "%s\\%s", path, fd.cFileName);
1356 DeleteFile(filename);
1357 }
1358 } while (FindNextFile(hFind, &fd));
1359 FindClose(hFind);
1360 }
1361 RemoveDirectory(path);
1362 sprintf(path, "%s\\ISC", commonPath);
1363 RemoveDirectory(path);
1364 }
1365 }
1366
DestDir(int destination)1367 CString CBINDInstallDlg::DestDir(int destination) {
1368 switch(destination) {
1369 case FileData::TargetDir:
1370 return m_targetDir;
1371 case FileData::BinDir:
1372 return m_binDir;
1373 case FileData::EtcDir:
1374 return m_etcDir;
1375 case FileData::WinSystem:
1376 return m_winSysDir;
1377 }
1378 return("");
1379 }
1380