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