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