1 /* Copyright (C) 1999-2002, Ghostgum Software Pty Ltd. All rights reserved. 2 3 This software is provided AS-IS with no warranty, either express or 4 implied. 5 6 This software is distributed under license and may not be copied, 7 modified or distributed except as expressly authorized under the terms 8 of the license contained in the file LICENSE in this distribution. 9 10 For more information about licensing, please refer to 11 http://www.ghostscript.com/licensing/. For information on 12 commercial licensing, go to http://www.artifex.com/licensing/ or 13 contact Artifex Software, Inc., 101 Lucas Valley Road #110, 14 San Rafael, CA 94903, U.S.A., +1(415)492-9861. 15 */ 16 17 // $Id: dwinst.cpp,v 1.6 2004/11/18 06:48:41 ghostgum Exp $ 18 19 #define STRICT 20 #include <windows.h> 21 #include <objbase.h> 22 #include <shlobj.h> 23 #include <stdio.h> 24 #include <io.h> 25 #include <direct.h> 26 27 #include "dwinst.h" 28 29 #define UNINSTALLKEY TEXT("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall") 30 #define UNINSTALLSTRINGKEY TEXT("UninstallString") 31 #define DISPLAYNAMEKEY TEXT("DisplayName") 32 #define UNINSTALL_FILE "uninstal.txt" 33 char szSection[] = "////////////////////////////////\n"; 34 35 #ifdef _MSC_VER 36 #define mktemp(x) _mktemp(x) 37 #define chdir(x) _chdir(x) 38 #define mkdir(x) _mkdir(x) 39 #endif 40 41 42 43 ////////////////////////////////////////////////////////////////////// 44 // Construction/Destruction 45 ////////////////////////////////////////////////////////////////////// 46 47 CInstall::CInstall() 48 { 49 CoInitialize(NULL); 50 51 m_szTargetDir[0] = '\0'; 52 m_szTargetGroup[0] = '\0'; 53 m_szPrograms[0] = '\0'; 54 m_szMainDir[0] = '\0'; 55 AddMessageFn = NULL; 56 SetAllUsers(FALSE); 57 } 58 59 CInstall::~CInstall() 60 { 61 CoUninitialize(); 62 } 63 64 void CInstall::CleanUp(void) 65 { 66 // delete all temporary files 67 if (m_fLogNew) 68 fclose(m_fLogNew); 69 m_fLogNew = NULL; 70 if (m_fLogOld) 71 fclose(m_fLogOld); 72 m_fLogOld = NULL; 73 74 if (strlen(m_szRegistryNew)) 75 DeleteFile(m_szRegistryNew); 76 m_szRegistryNew[0] = '\0'; 77 78 if (strlen(m_szRegistryOld)) 79 DeleteFile(m_szRegistryOld); 80 m_szRegistryOld[0] = '\0'; 81 82 if (strlen(m_szShellNew)) 83 DeleteFile(m_szShellNew); 84 m_szShellNew[0] = '\0'; 85 86 if (strlen(m_szShellOld)) 87 DeleteFile(m_szShellOld); 88 m_szShellOld[0] = '\0'; 89 90 if (strlen(m_szFileNew)) 91 DeleteFile(m_szFileNew); 92 m_szFileNew[0] = '\0'; 93 } 94 95 96 void CInstall::SetMessageFunction(void(*fn)(const char *)) 97 { 98 AddMessageFn = fn; 99 } 100 101 void CInstall::AddMessage(const char *message) 102 { 103 if (AddMessageFn) 104 (*AddMessageFn)(message); 105 } 106 107 void CInstall::SetTargetDir(const char *szTargetDir) 108 { 109 strcpy(m_szTargetDir, szTargetDir); 110 // remove trailing backslash 111 char *p; 112 p = m_szTargetDir + strlen(m_szTargetDir) - 1; 113 if (*p == '\\') 114 *p = '\0'; 115 } 116 117 void CInstall::SetTargetGroup(const char *szTargetGroup) 118 { 119 strcpy(m_szTargetGroup, szTargetGroup); 120 // remove trailing backslash 121 char *p; 122 p = m_szTargetGroup + strlen(m_szTargetGroup) - 1; 123 if (*p == '\\') 124 *p = '\0'; 125 } 126 127 const char *CInstall::GetMainDir() 128 { 129 return m_szMainDir; 130 } 131 132 const char *CInstall::GetUninstallName() 133 { 134 return m_szUninstallName; 135 } 136 137 BOOL CInstall::Init(const char *szSourceDir, const char *szFileList) 138 { 139 FILE *f; 140 141 strcpy(m_szSourceDir, szSourceDir); 142 // remove trailing backslash 143 char *p; 144 p = m_szSourceDir + strlen(m_szSourceDir) - 1; 145 if (*p == '\\') 146 *p = '\0'; 147 strcpy(m_szFileList, szFileList); 148 149 m_szRegistryNew[0] = m_szRegistryOld[0] = 150 m_szShellNew[0] = m_szShellOld[0] = 151 m_szFileNew[0] = '\0'; 152 153 // Open list of files 154 SetCurrentDirectory(m_szSourceDir); 155 f = fopen(m_szFileList, "r"); 156 if (f == (FILE *)NULL) { 157 char buf[MAXSTR]; 158 wsprintf(buf, "Failed to open \042%s\042\n", m_szFileList); 159 AddMessage(buf); 160 return FALSE; 161 } 162 163 // get application and directory name 164 m_szUninstallName[0] = '\0'; 165 if (!fgets(m_szUninstallName, sizeof(m_szUninstallName), f)) { 166 AddMessage("Invalid file list\n"); 167 fclose(f); 168 return FALSE; 169 } 170 if (*m_szUninstallName ) 171 m_szUninstallName[strlen(m_szUninstallName)-1] = '\0'; 172 173 m_szMainDir[0] = '\0'; 174 if (!fgets(m_szMainDir, sizeof(m_szMainDir), f)) { 175 AddMessage("Invalid file list\n"); 176 fclose(f); 177 return FALSE; 178 } 179 if (*m_szMainDir ) 180 m_szMainDir[strlen(m_szMainDir)-1] = '\0'; 181 fclose(f); 182 183 // Create log directory 184 strcpy(m_szLogDir, m_szTargetDir); 185 strcat(m_szLogDir, "\\"); 186 strcat(m_szLogDir, m_szMainDir); 187 MakeDir(m_szLogDir); 188 189 return TRUE; 190 } 191 192 193 ////////////////////////////////////////// 194 // File installation methods 195 196 BOOL CInstall::InstallFiles(BOOL bNoCopy, BOOL *pbQuit) 197 { 198 char szLogNew[MAXSTR]; 199 200 AddMessage(bNoCopy ? "Checking" : "Copying"); 201 AddMessage(" files listed in "); 202 AddMessage(m_szFileList); 203 AddMessage("\n"); 204 205 // Open list of files 206 SetCurrentDirectory(m_szSourceDir); 207 FILE *f = fopen(m_szFileList, "r"); 208 if (f == (FILE *)NULL) { 209 AddMessage("Failed to open \042"); 210 AddMessage(m_szFileList); 211 AddMessage("\042\n"); 212 return FALSE; 213 } 214 215 // skip application and directory name 216 fgets(szLogNew, sizeof(szLogNew), f); 217 fgets(szLogNew, sizeof(szLogNew), f); 218 219 // Create target log 220 221 m_fLogNew = MakeTemp(m_szFileNew); 222 if (!m_fLogNew) { 223 AddMessage("Failed to create FileNew temporary file\n"); 224 return FALSE; 225 } 226 227 // Copy files 228 char line[MAXSTR]; 229 while (fgets(line, sizeof(line), f) != (char *)NULL) { 230 if (*pbQuit) 231 return FALSE; 232 if (*line) 233 line[strlen(line)-1] = '\0'; 234 if (!InstallFile(line, bNoCopy)) { 235 fclose(f); 236 fclose(m_fLogNew); 237 return FALSE; 238 } 239 } 240 fclose(f); 241 fclose(m_fLogNew); 242 m_fLogNew = NULL; 243 return TRUE; 244 } 245 246 247 void CInstall::AppendFileNew(const char *filename) 248 { 249 FILE *f; 250 /* mark backup file for uninstall */ 251 if ((f = fopen(m_szFileNew, "a")) != (FILE *)NULL) { 252 fputs(filename, f); 253 fputs("\n", f); 254 fclose(f); 255 } 256 } 257 258 // recursive mkdir 259 // requires a full path to be specified, so ignores root \ 260 // apart from root \, must not contain trailing \ 261 // Examples: 262 // c:\ (OK, but useless) 263 // c:\gstools (OK) 264 // c:\gstools\ (incorrect) 265 // c:gstools (incorrect) 266 // gstools (incorrect) 267 // The following UNC names should work, 268 // but didn't under Win3.1 because gs_chdir wouldn't accept UNC names 269 // Needs to be tested under Windows 95. 270 // \\server\sharename\gstools (OK) 271 // \\server\sharename\ (OK, but useless) 272 // 273 274 BOOL CInstall::MakeDir(const char *dirname) 275 { 276 char newdir[MAXSTR]; 277 const char *p; 278 if (strlen(dirname) < 3) 279 return -1; 280 281 if (isalpha(dirname[0]) && dirname[1]==':' && dirname[2]=='\\') { 282 // drive mapped path 283 p = dirname+3; 284 } 285 else if (dirname[1]=='\\' && dirname[1]=='\\') { 286 // UNC path 287 p = strchr(dirname+2, '\\'); // skip servername 288 if (p == NULL) 289 return -1; 290 p++; 291 p = strchr(p, '\\'); // skip sharename 292 if (p == NULL) 293 return -1; 294 } 295 else { 296 // not full path so error 297 return -1; 298 } 299 300 while (1) { 301 strncpy(newdir, dirname, (int)(p-dirname)); 302 newdir[(int)(p-dirname)] = '\0'; 303 if (chdir(newdir)) { 304 if (mkdir(newdir)) 305 return -1; 306 } 307 p++; 308 if (p >= dirname + strlen(dirname)) 309 break; // all done 310 p = strchr(p, '\\'); 311 if (p == NULL) 312 p = dirname + strlen(dirname); 313 } 314 315 return SetCurrentDirectory(dirname); 316 } 317 318 void CInstall::ResetReadonly(const char *filename) 319 { 320 DWORD dwAttr = GetFileAttributes(filename); 321 if (dwAttr & FILE_ATTRIBUTE_READONLY) 322 SetFileAttributes(filename, dwAttr & (~FILE_ATTRIBUTE_READONLY)); 323 } 324 325 BOOL CInstall::InstallFile(char *filename, BOOL bNoCopy) 326 { 327 char existing_name[MAXSTR]; 328 char new_name[MAXSTR]; 329 char dir_name[MAXSTR]; 330 331 strcpy(existing_name, m_szSourceDir); 332 strcat(existing_name, "\\"); 333 strcat(existing_name, filename); 334 strcpy(new_name, m_szTargetDir); 335 strcat(new_name, "\\"); 336 strcat(new_name, filename); 337 strcpy(dir_name, new_name); 338 char *p = strrchr(dir_name, '\\'); 339 if (p) { 340 *p = '\0'; 341 if (!MakeDir(dir_name)) { 342 AddMessage("Failed to make directory "); 343 AddMessage(dir_name); 344 AddMessage("\n"); 345 return FALSE; 346 } 347 } 348 AddMessage(" "); 349 AddMessage(new_name); 350 AddMessage("\n"); 351 352 if (bNoCopy) { 353 // Don't copy files. Leave them where they are. 354 // Check that all files exist 355 FILE *f; 356 if ((f = fopen(existing_name, "r")) == (FILE *)NULL) { 357 AddMessage("Missing file "); 358 AddMessage(existing_name); 359 AddMessage("\n"); 360 return FALSE; 361 } 362 fclose(f); 363 } 364 else { 365 if (!CopyFile(existing_name, new_name, FALSE)) { 366 char message[MAXSTR+MAXSTR+100]; 367 wsprintf(message, "Failed to copy file %s to %s\n", 368 existing_name, new_name); 369 AddMessage(message); 370 return FALSE; 371 } 372 ResetReadonly(new_name); 373 fputs(new_name, m_fLogNew); 374 fputs("\n", m_fLogNew); 375 } 376 377 378 return TRUE; 379 } 380 381 ////////////////////////////////////////// 382 // Shell methods 383 384 BOOL CInstall::StartMenuBegin() 385 { 386 m_fLogNew = MakeTemp(m_szShellNew); 387 if (!m_fLogNew) { 388 AddMessage("Failed to create ShellNew temporary file\n"); 389 return FALSE; 390 } 391 392 m_fLogOld = MakeTemp(m_szShellOld); 393 if (!m_fLogOld) { 394 AddMessage("Failed to create ShellNew temporary file\n"); 395 return FALSE; 396 } 397 398 // make folder if needed 399 char szLink[MAXSTR]; 400 strcpy(szLink, m_szPrograms); 401 strcat(szLink, "\\"); 402 strcat(szLink, m_szTargetGroup); 403 if (chdir(szLink) != 0) { 404 if (mkdir(szLink) != 0) { 405 char buf[MAXSTR+64]; 406 wsprintf(buf, "Couldn't make Programs folder \042%s'042", szLink); 407 AddMessage(buf); 408 StartMenuEnd(); 409 return FALSE; 410 } 411 } 412 else { 413 fprintf(m_fLogOld, "Group=%s\n\n", szLink); 414 } 415 fprintf(m_fLogNew, "Group=%s\n\n", szLink); 416 417 return TRUE; 418 } 419 420 BOOL CInstall::StartMenuEnd() 421 { 422 if (m_fLogOld) 423 fclose(m_fLogOld); 424 m_fLogOld = NULL; 425 if (m_fLogNew) 426 fclose(m_fLogNew); 427 m_fLogNew = NULL; 428 return TRUE; 429 } 430 431 BOOL CInstall::StartMenuAdd(const char *szDescription, 432 const char *szProgram, const char *szArguments) 433 { 434 if (!CreateShellLink(szDescription, szProgram, szArguments)) { 435 AddMessage("Couldn't make shell link for "); 436 AddMessage(szDescription); 437 AddMessage("\n"); 438 StartMenuEnd(); 439 return FALSE; 440 } 441 442 return TRUE; 443 } 444 445 446 BOOL CInstall::CreateShellLink(LPCSTR description, LPCSTR program, 447 LPCSTR arguments, LPCSTR icon, int nIconIndex) 448 { 449 HRESULT hres; 450 IShellLink* psl; 451 CHAR szLink[MAXSTR]; 452 strcpy(szLink, m_szPrograms); 453 strcat(szLink, "\\"); 454 strcat(szLink, m_szTargetGroup); 455 strcat(szLink, "\\"); 456 strcat(szLink, description); 457 strcat(szLink, ".LNK"); 458 AddMessage("Adding shell link\n "); 459 AddMessage(szLink); 460 AddMessage("\n"); 461 462 // Ensure string is UNICODE. 463 WCHAR wsz[MAX_PATH]; 464 MultiByteToWideChar(CP_ACP, 0, szLink, -1, wsz, MAX_PATH); 465 466 // Save old shell link 467 468 // Get a pointer to the IShellLink interface. 469 hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 470 IID_IShellLink, (void **)&psl); 471 if (SUCCEEDED(hres)) { 472 IPersistFile* ppf; 473 // Query IShellLink for the IPersistFile interface. 474 hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); 475 if (SUCCEEDED(hres)) { 476 // Load the shell link. 477 hres = ppf->Load(wsz, STGM_READ); 478 if (SUCCEEDED(hres)) { 479 // Resolve the link. 480 hres = psl->Resolve(HWND_DESKTOP, SLR_ANY_MATCH); 481 if (SUCCEEDED(hres)) { 482 // found it, so save details 483 CHAR szTemp[MAXSTR]; 484 WIN32_FIND_DATA wfd; 485 int i; 486 487 488 fprintf(m_fLogOld, "Name=%s\n", szLink); 489 hres = psl->GetPath(szTemp, MAXSTR, (WIN32_FIND_DATA *)&wfd, 490 SLGP_SHORTPATH ); 491 if (SUCCEEDED(hres)) 492 fprintf(m_fLogOld, "Path=%s\n", szTemp); 493 hres = psl->GetDescription(szTemp, MAXSTR); 494 if (SUCCEEDED(hres)) 495 fprintf(m_fLogOld, "Description=%s\n", szTemp); 496 hres = psl->GetArguments(szTemp, MAXSTR); 497 if (SUCCEEDED(hres) && (szTemp[0] != '\0')) 498 fprintf(m_fLogOld, "Arguments=%s\n", szTemp); 499 hres = psl->GetWorkingDirectory(szTemp, MAXSTR); 500 if (SUCCEEDED(hres) && (szTemp[0] != '\0')) 501 fprintf(m_fLogOld, "Directory=%s\n", szTemp); 502 hres = psl->GetIconLocation(szTemp, MAXSTR, &i); 503 if (SUCCEEDED(hres) && (szTemp[0] != '\0')) { 504 fprintf(m_fLogOld, "IconLocation=%s\n", szTemp); 505 fprintf(m_fLogOld, "IconIndex=%d\n", i); 506 } 507 fprintf(m_fLogOld, "\n"); 508 } 509 } 510 // Release pointer to IPersistFile. 511 ppf->Release(); 512 } 513 // Release pointer to IShellLink. 514 psl->Release(); 515 } 516 517 518 // Save new shell link 519 520 // Get a pointer to the IShellLink interface. 521 hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, 522 IID_IShellLink, (void **)&psl); 523 if (SUCCEEDED(hres)) { 524 IPersistFile* ppf; 525 // Query IShellLink for the IPersistFile interface for 526 // saving the shell link in persistent storage. 527 hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf); 528 if (SUCCEEDED(hres)) { 529 fprintf(m_fLogNew, "Name=%s\n", szLink); 530 531 // Set the path to the shell link target. 532 hres = psl->SetPath(program); 533 if (!SUCCEEDED(hres)) 534 AddMessage("SetPath failed!"); 535 fprintf(m_fLogNew, "Path=%s\n", program); 536 // Set the description of the shell link. 537 hres = psl->SetDescription(description); 538 if (!SUCCEEDED(hres)) 539 AddMessage("SetDescription failed!"); 540 fprintf(m_fLogNew, "Description=%s\n", description); 541 if (arguments != (LPCSTR)NULL) { 542 // Set the arguments of the shell link target. 543 hres = psl->SetArguments(arguments); 544 if (!SUCCEEDED(hres)) 545 AddMessage("SetArguments failed!"); 546 fprintf(m_fLogNew, "Arguments=%s\n", arguments); 547 } 548 if (icon != (LPCSTR)NULL) { 549 // Set the arguments of the shell link target. 550 hres = psl->SetIconLocation(icon, nIconIndex); 551 if (!SUCCEEDED(hres)) 552 AddMessage("SetIconLocation failed!"); 553 fprintf(m_fLogNew, "IconLocation=%s\n", icon); 554 fprintf(m_fLogNew, "IconIndex=%d\n", nIconIndex); 555 } 556 557 // Save the link via the IPersistFile::Save method. 558 hres = ppf->Save(wsz, TRUE); 559 // Release pointer to IPersistFile. 560 ppf->Release(); 561 } 562 // Release pointer to IShellLink. 563 psl->Release(); 564 fprintf(m_fLogNew, "\n"); 565 } 566 567 return (hres == 0); 568 } 569 570 571 ////////////////////////////////////////// 572 // Registry methods 573 574 void 575 reg_quote(char *d, const char *s) 576 { 577 while (*s) { 578 if (*s == '\\') 579 *d++ = '\\'; 580 *d++ = *s++; 581 } 582 *d = *s; 583 } 584 585 BOOL CInstall::UpdateRegistryBegin() 586 { 587 const char regheader[]="REGEDIT4\n"; 588 m_fLogNew = MakeTemp(m_szRegistryNew); 589 if (!m_fLogNew) { 590 AddMessage("Failed to create RegistryNew temporary file\n"); 591 return FALSE; 592 } 593 fputs(regheader, m_fLogNew); 594 595 m_fLogOld = MakeTemp(m_szRegistryOld); 596 if (!m_fLogOld) { 597 AddMessage("Failed to create RegistryOld temporary file\n"); 598 UpdateRegistryEnd(); 599 return FALSE; 600 } 601 fputs(regheader, m_fLogOld); 602 603 return TRUE; 604 } 605 606 BOOL CInstall::UpdateRegistryEnd() 607 { 608 if (m_fLogNew) 609 fclose(m_fLogNew); 610 m_fLogNew = NULL; 611 if (m_fLogOld) 612 fclose(m_fLogOld); 613 m_fLogOld = NULL; 614 return TRUE; 615 } 616 617 BOOL CInstall::UpdateRegistryKey(const char *product, const char *version) 618 { 619 const char hkey_name[] = "HKEY_LOCAL_MACHINE"; 620 const HKEY hkey_key = HKEY_LOCAL_MACHINE; 621 const char key_format[] = "\n[%s\\%s]\n"; 622 623 /* Create default registry entries */ 624 HKEY hkey; 625 LONG lrc; 626 char name[MAXSTR]; 627 628 // Create/Open application key 629 sprintf(name, "SOFTWARE\\%s", product); 630 lrc = RegOpenKey(hkey_key, name, &hkey); 631 if (lrc == ERROR_SUCCESS) { 632 fprintf(m_fLogOld, key_format, hkey_name, name); 633 } 634 else { 635 lrc = RegCreateKey(hkey_key, name, &hkey); 636 if (lrc == ERROR_SUCCESS) 637 fprintf(m_fLogNew, key_format, hkey_name, name); 638 } 639 if (lrc == ERROR_SUCCESS) 640 RegCloseKey(hkey); 641 642 // Create/Open application version key 643 sprintf(name, "SOFTWARE\\%s\\%s", product, version); 644 645 AddMessage(" "); 646 AddMessage(hkey_name); 647 AddMessage("\\"); 648 AddMessage(name); 649 AddMessage("\n"); 650 lrc = RegOpenKey(hkey_key, name, &hkey); 651 if (lrc == ERROR_SUCCESS) 652 fprintf(m_fLogOld, key_format, hkey_name, name); 653 else 654 lrc = RegCreateKey(hkey_key, name, &hkey); 655 if (lrc == ERROR_SUCCESS) { 656 fprintf(m_fLogNew, key_format, hkey_name, name); 657 } 658 else { 659 UpdateRegistryEnd(); 660 } 661 return TRUE; 662 } 663 664 BOOL CInstall::UpdateRegistryValue(const char *product, const char *version, 665 const char *name, const char *value) 666 { 667 char appver[MAXSTR]; 668 BOOL flag = FALSE; 669 HKEY hkey; 670 // Open application/version key 671 sprintf(appver, "SOFTWARE\\%s\\%s", product, version); 672 673 if (RegOpenKey(HKEY_LOCAL_MACHINE, appver, &hkey) 674 == ERROR_SUCCESS) { 675 flag = SetRegistryValue(hkey, name, value); 676 RegCloseKey(hkey); 677 } 678 679 return flag; 680 } 681 682 BOOL CInstall::SetRegistryValue(HKEY hkey, const char *value_name, const char *value) 683 { 684 char buf[MAXSTR]; 685 char qbuf[MAXSTR]; 686 DWORD cbData; 687 DWORD keytype; 688 689 cbData = sizeof(buf); 690 keytype = REG_SZ; 691 if (RegQueryValueEx(hkey, value_name, 0, &keytype, 692 (LPBYTE)buf, &cbData) == ERROR_SUCCESS) { 693 reg_quote(qbuf, buf); 694 fprintf(m_fLogOld, "\042%s\042=\042%s\042\n", value_name, qbuf); 695 } 696 reg_quote(qbuf, value); 697 fprintf(m_fLogNew, "\042%s\042=\042%s\042\n", value_name, qbuf); 698 AddMessage(" "); 699 AddMessage(value_name); 700 AddMessage("="); 701 AddMessage(value); 702 AddMessage("\n"); 703 if (RegSetValueEx(hkey, value_name, 0, REG_SZ, 704 (CONST BYTE *)value, strlen(value)+1) != ERROR_SUCCESS) 705 return FALSE; 706 return TRUE; 707 } 708 709 //////////////////////////////////// 710 // Uninstall 711 712 713 BOOL CInstall::WriteUninstall(const char *szProg, BOOL bNoCopy) 714 { 715 LONG rc; 716 HKEY hkey; 717 HKEY hsubkey; 718 char buffer[MAXSTR]; 719 char ungsprog[MAXSTR]; 720 721 lstrcpy(ungsprog, m_szTargetDir); 722 lstrcat(ungsprog, "\\"); 723 lstrcat(ungsprog, szProg); 724 725 lstrcpy(buffer, m_szSourceDir); 726 lstrcat(buffer, "\\"); 727 lstrcat(buffer, szProg); 728 729 if (bNoCopy) { 730 // Don't copy files. Leave them where they are. 731 // Check that all files exist 732 FILE *f; 733 if ((f = fopen(buffer, "r")) == (FILE *)NULL) { 734 AddMessage("Missing file "); 735 AddMessage(buffer); 736 AddMessage("\n"); 737 return FALSE; 738 } 739 fclose(f); 740 } 741 else if (!CopyFile(buffer, ungsprog, FALSE)) { 742 char message[MAXSTR+MAXSTR+100]; 743 wsprintf(message, "Failed to copy file %s to %s", buffer, ungsprog); 744 AddMessage(message); 745 return FALSE; 746 } 747 ResetReadonly(ungsprog); 748 749 /* write registry entries for uninstall */ 750 if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, UNINSTALLKEY, 0, 751 KEY_ALL_ACCESS, &hkey)) != ERROR_SUCCESS) { 752 /* failed to open key, so try to create it */ 753 rc = RegCreateKey(HKEY_LOCAL_MACHINE, UNINSTALLKEY, &hkey); 754 } 755 if (rc == ERROR_SUCCESS) { 756 // Uninstall key for program 757 if (RegCreateKey(hkey, m_szUninstallName, &hsubkey) == ERROR_SUCCESS) { 758 RegSetValueEx(hsubkey, DISPLAYNAMEKEY, 0, REG_SZ, 759 (CONST BYTE *)m_szUninstallName, lstrlen(m_szUninstallName)+1); 760 lstrcpy(buffer, ungsprog); 761 lstrcat(buffer, " \042"); 762 lstrcat(buffer, m_szTargetDir); 763 lstrcat(buffer, "\\"); 764 lstrcat(buffer, m_szMainDir); 765 lstrcat(buffer, "\\"); 766 lstrcat(buffer, UNINSTALL_FILE); 767 lstrcat(buffer, "\042"); 768 AddMessage(" "); 769 AddMessage(m_szUninstallName); 770 AddMessage("="); 771 AddMessage(buffer); 772 AddMessage("\n"); 773 RegSetValueEx(hsubkey, UNINSTALLSTRINGKEY, 0, REG_SZ, 774 (CONST BYTE *)buffer, lstrlen(buffer)+1); 775 RegCloseKey(hsubkey); 776 } 777 778 RegCloseKey(hkey); 779 } 780 return TRUE; 781 } 782 783 784 void 785 CInstall::CopyFileContents(FILE *df, FILE *sf) 786 { 787 char buf[MAXSTR]; 788 int count; 789 while ((count = fread(buf, 1, sizeof(buf), sf)) != 0) 790 fwrite(buf, 1, count, df); 791 } 792 793 FILE *CInstall::MakeTemp(char *fname) 794 { 795 char *temp; 796 if ( (temp = getenv("TEMP")) == NULL ) 797 strcpy(fname, m_szTargetDir); 798 else 799 strcpy(fname, temp); 800 801 /* Prevent X's in path from being converted by mktemp. */ 802 for ( temp = fname; *temp; temp++ ) { 803 *temp = (char)tolower(*temp); 804 if (*temp == '/') 805 *temp = '\\'; 806 } 807 if ( strlen(fname) && (fname[strlen(fname)-1] != '\\') ) 808 strcat(fname, "\\"); 809 810 strcat(fname, "gsXXXXXX"); 811 mktemp(fname); 812 AddMessage("Creating temporary file "); 813 AddMessage(fname); 814 AddMessage("\n"); 815 return fopen(fname, "w"); 816 } 817 818 BOOL CInstall::MakeLog() 819 { 820 FILE *f, *lf; 821 char szFileName[MAXSTR]; 822 char szLogDir[MAXSTR]; 823 strcpy(szLogDir, m_szTargetDir); 824 strcat(szLogDir, "\\"); 825 strcat(szLogDir, m_szMainDir); 826 strcat(szLogDir, "\\"); 827 828 strcpy(szFileName, szLogDir); 829 strcat(szFileName, UNINSTALL_FILE); 830 lf = fopen(szFileName, "w"); 831 if (lf == (FILE *)NULL) { 832 AddMessage("Can't create uninstall log"); 833 CleanUp(); 834 return FALSE; 835 } 836 fputs(szSection, lf); 837 fputs("UninstallName\n", lf); 838 fputs(m_szUninstallName, lf); 839 fputs("\n\n", lf); 840 841 if (strlen(m_szRegistryNew) && 842 (f = fopen(m_szRegistryNew, "r")) != (FILE *)NULL) { 843 fputs(szSection, lf); 844 fputs("RegistryNew\n", lf); 845 CopyFileContents(lf, f); 846 fputs("\n", lf); 847 fclose(f); 848 DeleteFile(m_szRegistryNew); 849 m_szRegistryNew[0] = '\0'; 850 } 851 852 if (strlen(m_szRegistryOld) && 853 (f = fopen(m_szRegistryOld, "r")) != (FILE *)NULL) { 854 fputs(szSection, lf); 855 fputs("RegistryOld\n", lf); 856 CopyFileContents(lf, f); 857 fputs("\n", lf); 858 fclose(f); 859 DeleteFile(m_szRegistryOld); 860 m_szRegistryOld[0] = '\0'; 861 } 862 863 if (strlen(m_szShellNew) && 864 (f = fopen(m_szShellNew, "r")) != (FILE *)NULL) { 865 fputs(szSection, lf); 866 fputs("ShellNew\n", lf); 867 CopyFileContents(lf, f); 868 fputs("\n", lf); 869 fclose(f); 870 DeleteFile(m_szShellNew); 871 m_szShellNew[0] = '\0'; 872 } 873 874 if (strlen(m_szShellOld) && 875 (f = fopen(m_szShellOld, "r")) != (FILE *)NULL) { 876 fputs(szSection, lf); 877 fputs("ShellOld\n", lf); 878 CopyFileContents(lf, f); 879 fputs("\n", lf); 880 fclose(f); 881 DeleteFile(m_szShellOld); 882 m_szShellOld[0] = '\0'; 883 } 884 885 if (strlen(m_szFileNew) && 886 (f = fopen(m_szFileNew, "r")) != (FILE *)NULL) { 887 fputs(szSection, lf); 888 fputs("FileNew\n", lf); 889 CopyFileContents(lf, f); 890 fputs("\n", lf); 891 fclose(f); 892 DeleteFile(m_szFileNew); 893 m_szFileNew[0] = '\0'; 894 } 895 896 fputs(szSection, lf); 897 fclose(lf); 898 899 return TRUE; 900 } 901 902 BOOL CInstall::GetPrograms(BOOL bUseCommon, char *buf, int buflen) 903 { 904 // Get the directory for the Program menu. This is 905 // stored in the Registry under HKEY_CURRENT_USER\Software\ 906 // Microsoft\Windows\CurrentVersion\Explorer\Shell Folders\Programs. 907 LONG rc; 908 HKEY hCU; 909 DWORD dwType; 910 ULONG ulSize = buflen; 911 HKEY hrkey = HKEY_CURRENT_USER; 912 if (bUseCommon) 913 hrkey = HKEY_LOCAL_MACHINE; 914 if (RegOpenKeyEx(hrkey, 915 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", 916 0,KEY_QUERY_VALUE, 917 &hCU) == ERROR_SUCCESS) { 918 rc = RegQueryValueEx( hCU, 919 bUseCommon ? "Common Programs" : "Programs", 920 NULL, 921 &dwType, 922 (unsigned char *)buf, 923 &ulSize); 924 RegCloseKey(hCU); 925 return TRUE; 926 } 927 return FALSE; 928 929 #ifdef NOTUSED 930 // This is an alternate version, but it needs 931 // Internet Explorer 4.0 with Web Integrated Desktop. 932 // It does not work with the standard 933 // Windows 95, Windows NT 4.0, Internet Explorer 3.0, 934 // and Internet Explorer 4.0 without Web Integrated Desktop. 935 936 HRESULT rc; 937 m_szPrograms[0] = '\0'; 938 int nFolder = CSIDL_PROGRAMS; 939 if (bUseCommon) 940 nFolder = CSIDL_COMMON_PROGRAMS; 941 942 rc = SHGetSpecialFolderPath(HWND_DESKTOP, m_szPrograms, 943 nFolder, FALSE); 944 return (rc == NOERROR); 945 #endif 946 947 } 948 949 BOOL CInstall::SetAllUsers(BOOL bUseCommon) 950 { 951 m_bUseCommon = bUseCommon; 952 return GetPrograms(bUseCommon, m_szPrograms, sizeof(m_szPrograms)); 953 } 954 955 956 ////////////////////////////////////////////////////////////////////// 957