LINUX: afs_create infinite fetchStatus loop
[pkg-k5-afs_openafs.git] / src / WINNT / afs_setup_utils / afs_setup_utils.cpp
blobb7d809db81debbdc5bdac4e3378ad189d4039c0f
1 /*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
11 * INCLUDES _________________________________________________________________
15 extern "C" {
16 #include <afs/param.h>
17 #include <afs/stds.h>
18 #include <afs/fileutil.h>
21 #include <windows.h>
22 #include <stdio.h>
23 #include <time.h>
24 #include <assert.h>
25 #include <stdlib.h>
26 #include <io.h>
27 #include <string.h>
28 #include <SYS\STAT.H>
29 #include <shellapi.h>
31 #include <WINNT/afsreg.h>
32 #include <WINNT/afssw.h>
33 #include <WINNT/talocale.h>
35 #include "resource.h"
36 #include "progress_dlg.h"
37 #include "sutil.h"
38 #include "forceremove.h"
42 * PROTOTYPES _________________________________________________________________
45 static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered);
46 BOOL UninstallCredsTool();
47 BOOL ServerSpecificUninstall();
48 BOOL ClientSpecificUninstall();
53 * DEFINITIONS _________________________________________________________________
56 #define SUCALLCONV WINAPI
58 #define UNINSTALL_TEMP_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsUninstallTempInfo"
59 #define INSTALL_DIR_VALUE_NAME "InstallDir"
61 #define AFS_PRESERVED_CFG_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsPreservedConfigInfo"
63 #define MS_SHARED_FILES_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs"
65 // Log file to use when running in silent mode
66 #define UNINSTALL_ERROR_LOG_NAME "\\AfsUninstallErrorLog.txt"
67 #define INSTALL_ERROR_LOG_NAME "\\AfsInstallErrorLog.txt"
69 #define TARGETDIR "<TARGETDIR>"
70 #define WINDIR "<WINDIR>"
71 #define WINSYSDIR "<WINSYSDIR>"
73 #define WIN9X_START_MENU_REG_KEY "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
74 #define WIN9X_START_MENU_REG_VALUE "Programs"
76 #define WINNT_START_MENU_REG_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
77 #define WINNT_START_MENU_REG_VALUE "Common Programs"
79 #define LOCALE_ID_LEN 4
81 struct REGVALUE {
82 char *pszKey;
83 char *pszValue;
87 typedef BOOL (APP_UNINSTALL_FUNC)();
91 struct APPINFO {
92 char *pszAppName;
94 // Service Info
95 char *pszSvcName;
96 char *pszSvcKey;
97 char *pszSvcDependOn;
98 char *pszSvcDisplayName;
100 char *pszNetworkProviderOrder;
102 // Message to use to tell the user that we have to stop the service
103 int nServiceShutdownMsgID;
105 // Message to use for the progress dialog that is shown while
106 // waiting for the service to stop.
107 int nServiceShutdownProgressMsgID;
109 // Location in registry of a key we can use to know that the app is installed
110 char *pszAppKey;
112 // Location in registry of this app's install dir
113 struct REGVALUE regInstallDir;
115 // Path Info
116 char *pszLocalRoot; // The root dir below the install dir
117 char *pszBinPath; // Path to remove from the system path
119 // Generated files and directories to delete. These are both multistring lists.
120 char *pszDirsToDel; // All files in these dirs will be deleted
121 char *pszFilesToDel; // Use this if you want to delete files but leave the dir. Wildcards can be used.
123 // Registry values to remove
124 struct REGVALUE *pRegValues;
125 struct REGVALUE *pWinNTRegValues; // Only remove these if running WinNT
126 struct REGVALUE *pWin9XRegValues; // Only remove these if running Win9X
128 // Start menu entries to delete
129 char *pszStartMenuEntries;
131 // Registry keys to save if a user wants to preserve config info during uninstall
132 char *pszRegKeysToPreserve;
133 int nPreserveConfigInfoMsgID;
135 // Uninstall func - used for things specific to this app
136 APP_UNINSTALL_FUNC *pUninstallFunc;
141 * App info structure for the Server product
143 struct APPINFO appServer = {
144 "AFS Server",
146 AFSREG_SVR_SVC_NAME,
147 AFSREG_SVR_SVC_KEY,
148 0, // No depend on
149 AFSREG_SVR_SVC_DISPLAYNAME_DATA,
151 0, // No network provider order
153 IDS_MUST_STOP_SERVER,
154 IDS_WAITING_FOR_SERVER_TO_STOP,
156 AFSREG_SVR_SW_VERSION_KEY,
158 { AFSREG_SVR_SW_VERSION_KEY, AFSREG_SVR_SW_VERSION_DIR_VALUE },
160 "\\Server",
161 "\\usr\\afs\\bin",
163 // Dirs to delete
164 TARGETDIR"\\Server\\usr\\afs\\bin\\backup\0"
165 TARGETDIR"\\Server\\usr\\afs\\bin\0"
166 TARGETDIR"\\Server\\usr\\afs\\db\0"
167 TARGETDIR"\\Server\\usr\\afs\\logs\0"
168 TARGETDIR"\\Server\\usr\\afs\\etc\0"
169 TARGETDIR"\\Server\\usr\\afs\\local\0"
170 TARGETDIR"\\Server\\usr\\afs\0"
171 TARGETDIR"\\Server\\usr\0",
173 // Files to delete
174 TARGETDIR"\\Common\\*.gid\0"
175 TARGETDIR"\\Common\\*.fts\0",
177 0, // No reg values
178 0, // No NT only reg values
179 0, // No 9x only reg values
181 "Server\0",
183 // Config info to preserve
184 AFSREG_SVR_SVC_KEY"\0",
185 IDS_PRESERVE_SERVER_CONFIG_INFO,
187 0 // No special uninstall function
190 // Registry values to remove for the Client
191 struct REGVALUE clientRegValues[] = {
192 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", "{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}" },
193 { 0, 0 } // This indicates there are no more entries
196 struct REGVALUE clientWinNTRegValues[] = {
197 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\File Manager\\AddOns", "AFS Client FME" },
198 { "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\NetBT\\Parameters", "SMBDeviceEnabled" },
199 { 0, 0 }
202 struct REGVALUE clientWin9XRegValues[] = {
203 { "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", "TransarcAFSDaemon" },
204 { 0, 0 }
208 * App info structure for the Client product
210 struct APPINFO appClient = {
211 "AFS Client",
213 AFSREG_CLT_SVC_NAME,
214 AFSREG_CLT_SVC_KEY,
215 "5250435353004E657462696F730000",
216 AFSREG_CLT_SVC_DISPLAYNAME_DATA,
218 AFSREG_CLT_SVC_NAME,
220 IDS_MUST_STOP_CLIENT,
221 IDS_WAITING_FOR_CLIENT_TO_STOP,
223 AFSREG_CLT_SW_VERSION_KEY,
225 { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },
227 "\\Client",
228 "\\Program",
230 // No dirs to delete
233 // Files to delete
234 TARGETDIR"\\Common\\*.gid\0"
235 TARGETDIR"\\Common\\*.fts\0"
236 WINDIR"\\..\\AFSCache\0"
237 WINDIR"\\TEMP\\afsd.log\0"
238 TARGETDIR"\\Client\\afsd.ini\0"
239 TARGETDIR"\\Client\\afsdsbmt.ini\0"
240 TARGETDIR"\\Client\\afsdcell.ini\0"
241 WINDIR"\\TEMP\\afsd_init.log\0",
243 clientRegValues,
244 clientWinNTRegValues,
245 clientWin9XRegValues,
247 // Start menu entries to remove
248 "Client\0",
250 // Config info to preserve
251 AFSREG_CLT_SVC_KEY"\0",
252 IDS_PRESERVE_CLIENT_CONFIG_INFO,
254 ClientSpecificUninstall
259 * App info structure for the Light Client product
261 struct APPINFO appLightClient = {
262 "AFS Light",
264 // No service info
270 AFSREG_CLT_SVC_NAME,
272 // No service shutdown messages
276 "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Light Client",
278 { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },
280 "\\Client",
281 "\\Program",
283 // No dirs to delete
286 // Files to delete
287 TARGETDIR"\\Common\\*.gid\0"
288 TARGETDIR"\\Common\\*.fts\0",
290 clientRegValues,
291 clientWinNTRegValues,
292 clientWin9XRegValues,
294 // Start menu entries to remove
295 "Light\0",
297 // Config info to preserve
298 AFSREG_CLT_SVC_KEY"\0",
299 IDS_PRESERVE_LIGHT_CLIENT_CONFIG_INFO,
301 UninstallCredsTool
306 * App info structure for the Control Center product
308 struct APPINFO appControlCenter = {
309 "AFS Control Center",
311 // No service info
317 // No network provider order
320 // No service shutdown messages
324 "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center",
326 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center\\CurrentVersion", "PathName" },
328 "\\Control Center",
331 // No dirs to delete
334 // Files to delete
335 TARGETDIR"\\Common\\*.gid\0"
336 TARGETDIR"\\Common\\*.fts\0",
338 0, // No reg values
339 0, // No NT only reg values
340 0, // No 9x only reg values
342 // Start menu entries to remove
343 "Control Center\0",
345 // Config info to preserve
346 AFSREG_CLT_SVC_KEY"\0",
347 IDS_PRESERVE_CC_CONFIG_INFO,
349 0 // No uninstall function
354 * App info structure for the Sys Admin Doc files
356 struct APPINFO appDocs = {
357 "AFS Supplemental Documentation",
359 // No service info
365 // No network provider order
368 // No service shutdown messages
372 "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation",
374 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation\\CurrentVersion", "PathName" },
376 "\\Documentation",
379 // No dirs to delete
382 // Files to delete
383 TARGETDIR"\\Common\\*.gid\0"
384 TARGETDIR"\\Common\\*.fts\0",
386 0, // No reg values
387 0, // No NT only reg values
388 0, // No 9x only reg values
390 // Start menu entries to remove
391 "Documentation\\AFS for Windows Backup Command Reference.lnk\0Documentation\\AFS Command Reference Manual.lnk\0Documentation\\AFS System Administrator's Guide.lnk\0",
393 0, // No config info to preserve
395 0 // No uninstall function
399 // Shared and in-use files
400 struct FILEINFO {
401 char *pszName;
402 int nUsedBy;
405 #define SERVER 1
406 #define CLIENT 2
407 #define LCLIENT 4
408 #define CC 8
409 #define DOCS 16
412 struct FILEINFO fileInfo[] = {
413 { TARGETDIR"\\Common\\afsbosadmin.dll", SERVER | CC },
414 { TARGETDIR"\\Common\\afscfgadmin.dll", SERVER | CC },
415 { TARGETDIR"\\Common\\afsclientadmin.dll", SERVER | CLIENT | LCLIENT | CC },
416 { TARGETDIR"\\Common\\afskasadmin.dll", SERVER | CC },
417 { TARGETDIR"\\Common\\afsptsadmin.dll", SERVER | CC },
418 { TARGETDIR"\\Common\\afsvosadmin.dll", SERVER | CC },
419 { TARGETDIR"\\Common\\afsadminutil.dll", SERVER | CLIENT | LCLIENT | CC },
420 { TARGETDIR"\\Common\\afsrpc.dll", SERVER | CLIENT | LCLIENT | CC },
421 { TARGETDIR"\\Common\\afsauthent.dll", SERVER | CLIENT | LCLIENT | CC },
422 { TARGETDIR"\\Common\\afspthread.dll", SERVER | CLIENT | LCLIENT | CC },
423 { TARGETDIR"\\Common\\TaAfsAppLib.dll", SERVER | CLIENT | LCLIENT | CC },
424 { TARGETDIR"\\Common\\afsprocmgmt.dll", SERVER | CLIENT | LCLIENT },
425 { TARGETDIR"\\Common\\afs_config.exe", CLIENT | LCLIENT| CC },
426 { TARGETDIR"\\Common\\afseventmsg_????.dll", SERVER | CLIENT | LCLIENT | CC },
427 { TARGETDIR"\\Common\\afslegal_????.dll", SERVER | CLIENT | LCLIENT | CC },
428 { TARGETDIR"\\Common\\afsserver_????.dll", SERVER | CLIENT | LCLIENT | CC },
429 { TARGETDIR"\\Common\\afssvrcfg_????.dll", SERVER | CLIENT | LCLIENT | CC },
430 { TARGETDIR"\\Common\\TaAfsAccountManager_????.dll",SERVER | CLIENT | LCLIENT | CC },
431 { TARGETDIR"\\Common\\TaAfsAppLib_????.dll", SERVER | CLIENT | LCLIENT | CC },
432 { TARGETDIR"\\Common\\TaAfsServerManager_????.dll", SERVER | CLIENT | LCLIENT | CC },
433 { TARGETDIR"\\Common\\afscreds_????.dll", SERVER | CLIENT | LCLIENT | CC },
434 { TARGETDIR"\\Common\\afs_config_????.dll", SERVER | CLIENT | LCLIENT | CC },
435 { TARGETDIR"\\Common\\afs_cpa_????.dll", SERVER | CLIENT | LCLIENT | CC },
436 { TARGETDIR"\\Common\\afs_shl_ext_????.dll", SERVER | CLIENT | LCLIENT | CC },
437 { TARGETDIR"\\Common\\afs-nt.hlp", SERVER | CLIENT | LCLIENT | CC },
438 { TARGETDIR"\\Common\\afs-nt.cnt", SERVER | CLIENT | LCLIENT | CC },
439 { TARGETDIR"\\Common\\taafssvrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },
440 { TARGETDIR"\\Common\\taafssvrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },
441 { TARGETDIR"\\Common\\taafsusrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },
442 { TARGETDIR"\\Common\\taafsusrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },
443 { TARGETDIR"\\Common\\afs-cc.cnt", SERVER | CLIENT | LCLIENT | CC },
444 { TARGETDIR"\\Common\\afs-cc.hlp", SERVER | CLIENT | LCLIENT | CC },
445 { TARGETDIR"\\Common\\afs-light.cnt", SERVER | CLIENT | LCLIENT | CC },
446 { TARGETDIR"\\Common\\afs-light.hlp", SERVER | CLIENT | LCLIENT | CC },
447 { TARGETDIR"\\Common\\taafscfg.cnt", SERVER | CLIENT | LCLIENT | CC },
448 { TARGETDIR"\\Common\\taafscfg.hlp", SERVER | CLIENT | LCLIENT | CC },
449 { TARGETDIR"\\Client\\PROGRAM\\afs_shl_ext.dll", CLIENT | LCLIENT },
450 { TARGETDIR"\\Client\\PROGRAM\\libafsconf.dll", CLIENT | LCLIENT },
451 { TARGETDIR"\\Client\\PROGRAM\\afslogon.dll", CLIENT },
452 { TARGETDIR"\\Client\\PROGRAM\\afslog95.dll", LCLIENT },
453 { TARGETDIR"\\Control Center\\TaAfsAdmSvr.exe", CC },
454 { WINSYSDIR"\\afs_cpa.cpl", CLIENT | LCLIENT | CC },
455 { WINSYSDIR"\\afsserver.cpl", SERVER },
456 { TARGETDIR"\\Common\\afsdcell.ini", CLIENT | LCLIENT | CC },
457 { TARGETDIR"\\Documentation\\Html\\banner.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
458 { TARGETDIR"\\Documentation\\Html\\books.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
459 { TARGETDIR"\\Documentation\\Html\\bot.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
460 { TARGETDIR"\\Documentation\\Html\\index.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
461 { TARGETDIR"\\Documentation\\Html\\index.htm", SERVER | CLIENT | LCLIENT | CC | DOCS },
462 { TARGETDIR"\\Documentation\\Html\\next.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
463 { TARGETDIR"\\Documentation\\Html\\prev.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
464 { TARGETDIR"\\Documentation\\Html\\toc.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
465 { TARGETDIR"\\Documentation\\Html\\top.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
466 { TARGETDIR"\\Documentation\\Html\\ReleaseNotes\\relnotes.htm",
467 SERVER | CLIENT | LCLIENT | CC },
468 { TARGETDIR"\\Documentation\\Html\\InstallGd\\afsnt35i.htm",
469 SERVER | CLIENT | LCLIENT | CC },
470 { 0, 0 } // End of list
475 * VARIABLES _________________________________________________________________
478 HINSTANCE hinst;
480 static HWND hDlg;
481 static BOOL bPreserveConfigInfo;
482 static BOOL bSilentMode;
483 static char *pszInstallDir;
487 * FUNCTIONS _________________________________________________________________
491 static BOOL UpgradeClientIntParm(HKEY hKey, char *pszOldParm, char *pszNewParm)
493 int nData;
494 LONG result = ERROR_SUCCESS;
496 nData = GetPrivateProfileInt("AFS Client", pszOldParm, -1, "afsd.ini");
497 if (nData > -1)
498 result = RegSetValueEx(hKey, pszNewParm, 0, REG_DWORD, (BYTE *)&nData, sizeof(nData));
500 return (result == ERROR_SUCCESS);
503 static BOOL UpgradeClientStringParm(HKEY hKey, char *pszOldParm, char *pszNewParm)
505 char szData[1024];
506 LONG result = ERROR_SUCCESS;
508 GetPrivateProfileString("AFS Client", pszOldParm, "", szData, sizeof(szData), "afsd.ini");
509 if (szData[0])
510 result = RegSetValueEx(hKey, pszNewParm, 0, REG_SZ, (PBYTE)szData, strlen(szData) + 1);
512 return (result == ERROR_SUCCESS);
515 int SUCALLCONV Upgrade34ClientConfigInfo()
517 HKEY hKey;
518 LONG result;
519 int nData;
521 result = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_CLT_SVC_PARAM_KEY, KEY_WRITE, TRUE, &hKey, 0);
522 if (result != ERROR_SUCCESS)
523 return -1;
525 UpgradeClientIntParm(hKey, "CacheSize", "CacheSize");
526 UpgradeClientIntParm(hKey, "Stats", "Stats");
527 UpgradeClientIntParm(hKey, "LogoffTokenTransfer", "LogoffTokenTransfer");
528 UpgradeClientIntParm(hKey, "LogoffTokenTransferTimeout", "LogoffTokenTransferTimeout");
529 UpgradeClientIntParm(hKey, "TrapOnPanic", "TrapOnPanic");
530 UpgradeClientIntParm(hKey, "TraceBufferSize", "TraceBufferSize");
531 UpgradeClientIntParm(hKey, "TraceOnShutdown", "TraceOnShutdown");
532 UpgradeClientIntParm(hKey, "ReportSessionStartups", "ReportSessionStartups");
534 UpgradeClientStringParm(hKey, "MountRoot", "MountRoot");
535 UpgradeClientStringParm(hKey, "Cell", "Cell");
537 /* BlockSize to ChunkSize requires convertion */
538 nData = GetPrivateProfileInt("AFS Client", "BlockSize", -1, "afsd.ini");
539 if (nData > -1) {
540 DWORD chunkSize;
541 for (chunkSize = 0; (1 << chunkSize) < nData; chunkSize++);
542 (void) RegSetValueEx(hKey, "ChunkSize", 0, REG_DWORD, (BYTE *)&chunkSize, sizeof(chunkSize));
545 RegCloseKey(hKey);
547 return 0;
550 int SUCALLCONV Eradicate34Client()
552 if (Client34Eradicate(TRUE) != ERROR_SUCCESS)
553 return -1;
555 return 0;
558 // This function was written a long time ago by Mike Comer for use by the
559 // original DFS Client for NT install program.
560 int SUCALLCONV CheckIfAdmin(void)
562 HANDLE token = INVALID_HANDLE_VALUE;
563 PVOID buffer = 0;
564 DWORD bufLength;
565 DWORD realBufLength;
566 TOKEN_PRIMARY_GROUP *pgroup;
567 TOKEN_GROUPS *groups;
568 int result = -1;
569 DWORD groupCount;
570 LONG status;
571 PSID AdministratorSID = NULL;
572 SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
574 // allocate the SID for the Administrators group
575 if (!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorSID)) {
576 status = GetLastError();
577 goto getout;
580 // open the process token
581 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) {
582 status = GetLastError();
583 token = INVALID_HANDLE_VALUE;
584 goto getout;
587 // check primary group first
588 buffer = GlobalAlloc(GMEM_FIXED, sizeof(TOKEN_PRIMARY_GROUP));
589 if (!buffer) {
590 goto getout;
593 bufLength = sizeof(TOKEN_PRIMARY_GROUP);
594 while(1) {
595 if (!GetTokenInformation(token, TokenPrimaryGroup, buffer, bufLength, &realBufLength)) {
596 if (realBufLength > bufLength) {
597 // not enough space
598 GlobalFree(buffer);
599 bufLength = realBufLength;
600 buffer = GlobalAlloc(GMEM_FIXED, realBufLength);
601 if (!buffer) {
602 goto getout;
604 continue;
607 goto getout;
609 break;
612 pgroup = (TOKEN_PRIMARY_GROUP *)buffer;
613 if (EqualSid(pgroup->PrimaryGroup, AdministratorSID)) {
614 result = 0;
615 } else {
616 // okay, try the secondary groups
617 while(1) {
618 if (!GetTokenInformation(token, TokenGroups, buffer, bufLength, &realBufLength)) {
619 if (realBufLength > bufLength) {
620 // not enough space
621 GlobalFree(buffer);
622 bufLength = realBufLength;
623 buffer = GlobalAlloc(GMEM_FIXED, realBufLength);
624 if (!buffer) {
625 goto getout;
627 continue;
630 // a real error
631 goto getout;
633 break;
636 // we have the list of groups here. Process them:
637 groups = (TOKEN_GROUPS *)buffer;
638 for(groupCount = 0; groupCount < groups->GroupCount; groupCount++) {
639 if (EqualSid(groups->Groups[groupCount].Sid, AdministratorSID)) {
640 result = 0;
641 break;
646 getout:
648 if (token != INVALID_HANDLE_VALUE) {
649 CloseHandle(token);
652 if (buffer) {
653 GlobalFree(buffer);
656 if (AdministratorSID) {
657 FreeSid(AdministratorSID);
660 return result;
663 static void SetSharedFileRefCount(char *pszFile, int nRefCount)
665 LONG result;
666 HKEY hKey;
668 result = RegOpenKeyAlt(AFSREG_NULL_KEY, MS_SHARED_FILES_KEY, KEY_WRITE, FALSE, &hKey, 0);
669 if (result != ERROR_SUCCESS)
670 return;
672 if (nRefCount <= 0)
673 RegDeleteValue(hKey, pszFile);
674 else
675 RegSetValueEx(hKey, pszFile, 0, REG_DWORD, (BYTE *)&nRefCount, sizeof(int));
677 RegCloseKey(hKey);
680 static char *GetTimeStamp()
682 char szTime[64], szDate[64];
683 static char szTimeDate[128];
685 _strtime(szTime);
686 _strdate(szDate);
688 sprintf(szTimeDate, "[%s %s] ", szTime, szDate);
690 return szTimeDate;
693 int SUCALLCONV WriteToInstallErrorLog(char *pszMsg)
695 static BOOL bWritten = FALSE;
696 FILE *fp;
698 // On the first write, recreate the file
699 fp = fopen(INSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");
700 if (!fp)
701 return -1;
703 fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);
705 fclose(fp);
707 bWritten = TRUE;
709 return 0;
712 static void WriteToUninstallErrorLog(char *pszMsg)
714 static BOOL bWritten = FALSE;
715 FILE *fp;
717 // On the first write, recreate the file
718 fp = fopen(UNINSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");
719 if (!fp)
720 return;
722 fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);
724 fclose(fp);
726 bWritten = TRUE;
729 static char *LoadResString(UINT uID)
731 static char str[256];
732 GetString (str, uID);
733 return str;
736 static void ShowError(UINT nResID, LONG nError)
738 char szErr[256];
739 char szPrompt[256];
740 char szMsg[256];
741 char szTitle[256];
742 char *psz;
744 psz = LoadResString(nResID);
745 if (psz)
746 strcpy(szErr, psz);
747 else
748 sprintf(szErr, "unknown error msg (Msg ID = %d)", nResID);
750 psz = LoadResString(IDS_INSTALLATION_FAILURE);
751 strcpy(szPrompt, psz ? psz : "An error has occurred: %s (Last Error = %ld).");
753 sprintf(szMsg, szPrompt, szErr, nError);
755 psz = LoadResString(IDS_TITLE);
756 strcpy(szTitle, psz ? psz : "AFS");
758 if (bSilentMode)
759 WriteToUninstallErrorLog(szMsg);
760 else
761 MessageBox(hDlg, szMsg, szTitle, MB_OK);
764 static int ShowMsg(UINT nResID, int nType)
766 char szTitle[256];
767 char *psz;
769 psz = LoadResString(IDS_TITLE);
770 strcpy(szTitle, psz ? psz : "AFS");
772 return MessageBox(hDlg, LoadResString(nResID), szTitle, nType);
775 static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered)
777 HKEY hKey;
778 LONG nResult;
779 DWORD dwType;
780 static char szInstallDir[256];
781 DWORD dwSize;
782 char *pszKey;
783 char *pszValue;
785 pszKey = bRemembered ? UNINSTALL_TEMP_INFO_KEY : pApp->regInstallDir.pszKey;
786 pszValue = bRemembered ? INSTALL_DIR_VALUE_NAME : pApp->regInstallDir.pszValue;
788 dwSize = sizeof(szInstallDir);
790 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
791 if (nResult == ERROR_SUCCESS) {
792 nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szInstallDir, &dwSize);
793 RegCloseKey(hKey);
796 if (nResult != ERROR_SUCCESS) {
797 ShowError(IDS_CANT_DETERMINE_APP_PATH, nResult);
798 return 0;
801 FilepathNormalizeEx(szInstallDir, FPN_BACK_SLASHES);
803 return szInstallDir;
806 static BOOL DoesRegKeyExist(char *pszKey)
808 HKEY hKey;
809 LONG nResult;
811 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
812 if (nResult == ERROR_SUCCESS) {
813 RegCloseKey(hKey);
814 return TRUE;
817 return FALSE;
820 static BOOL IsAppInstalled(struct APPINFO *pApp)
822 return DoesRegKeyExist(pApp->pszAppKey);
825 static void BuildShortPath(char *pszShortPath, UINT nShortPathLen, char *pszInstallDir, char *pszPath)
827 strncpy(pszShortPath, pszInstallDir, nShortPathLen);
828 strncat(pszShortPath, pszPath, nShortPathLen);
830 GetShortPathName(pszShortPath, pszShortPath, nShortPathLen);
833 static BOOL IsWin95()
835 OSVERSIONINFO versionInformation;
837 versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
839 GetVersionEx(&versionInformation);
841 if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
842 (versionInformation.dwMinorVersion == 0))
843 return TRUE;
845 return FALSE;
848 int IsWin98()
850 OSVERSIONINFO versionInformation;
852 versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
854 GetVersionEx(&versionInformation);
856 if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
857 (versionInformation.dwMinorVersion == 10))
858 return 0;
860 return -1;
863 static BOOL IsServiceInstalled(char *pszServiceKey)
865 HKEY hKey;
867 if (RegOpenKeyAlt(0, pszServiceKey, KEY_READ, FALSE, &hKey, 0) == ERROR_SUCCESS) {
868 RegCloseKey(hKey);
869 return TRUE;
872 return FALSE;
875 // If this fails in anyway we just return. No error is displayed.
876 static void MakeSureServiceDoesNotExist(char *pszName)
878 SC_HANDLE hServer = 0, hSCM = 0;
879 SERVICE_STATUS status;
881 hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
882 if (hSCM) {
883 hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS | DELETE);
884 if (hServer) {
885 if (QueryServiceStatus(hServer, &status)) {
886 if (status.dwCurrentState != SERVICE_STOPPED) {
887 if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {
888 CloseServiceHandle(hServer);
889 CloseServiceHandle(hSCM);
890 return;
895 // Try to delete even if status query fails
896 DeleteService(hServer);
900 if (hServer)
901 CloseServiceHandle(hServer);
902 if (hSCM)
903 CloseServiceHandle(hSCM);
906 static int InstallService(char *pszName, char *pszDependOn, char *pszDisplayName, char *pszServicePath, BOOL bInteractive)
908 SC_HANDLE hServer = 0, hSCM;
909 BOOL bRestoreOldConfig = FALSE;
911 if (!AddToProviderOrder(AFSREG_CLT_SVC_NAME)) {
912 ShowError(ERROR_FILE_NOT_FOUND, GetLastError());
913 return -1;
915 hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
916 if (!hSCM) {
917 ShowError(IDS_SCM_OPEN_FAILED, GetLastError());
918 return -1;
921 /* This code is not used, but it could be handy in the future so I am keeping it here.
923 // If the service exists, then we (most probably) are in the middle of an upgrade or reinstall.
924 bRestoreOldConfig = IsServiceInstalled(pszName);
926 if (bRestoreOldConfig) {
927 hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS);
928 if (!hServer || !ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0)) {
929 ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, GetLastError());
930 bRestoreOldConfig = FALSE;
931 // Fall through to service creation below
936 if (!bRestoreOldConfig) {
937 DWORD dwServiceType;
939 // If the service already exists, the create call will fail. This can
940 // happen if uninstall failed (which is not infrequent). Making sure the
941 // service does not exist makes it easier for a user to install over top of
942 // a previously failed uninstall.
943 MakeSureServiceDoesNotExist(pszName);
945 dwServiceType = SERVICE_WIN32_OWN_PROCESS;
946 if (bInteractive)
947 dwServiceType |= SERVICE_INTERACTIVE_PROCESS;
949 hServer = CreateService(hSCM, pszName, pszDisplayName,
950 SERVICE_ALL_ACCESS, dwServiceType, SERVICE_AUTO_START,
951 SERVICE_ERROR_NORMAL, pszServicePath, 0, 0, "RPCSS\0Netbios\0\0", 0, 0);
953 if (!hServer)
954 ShowError(IDS_SERVICE_CREATE_FAILED, GetLastError());
957 if (hServer)
958 CloseServiceHandle(hServer);
960 CloseServiceHandle(hSCM);
962 return 0;
965 int SUCALLCONV InstallServerService(char *pszServicePath)
967 return InstallService(appServer.pszSvcName, 0, appServer.pszSvcDisplayName, pszServicePath, TRUE);
970 int SUCALLCONV InstallClientService(char *pszServicePath)
972 return InstallService(appClient.pszSvcName, appClient.pszSvcDependOn, appClient.pszSvcDisplayName, pszServicePath, FALSE);
975 static int UninstallService(struct APPINFO *pAppInfo)
977 SC_HANDLE hServer, hSCM;
978 SERVICE_STATUS status;
979 BOOL bOk;
980 BOOL bServer = FALSE;
981 BOOL bShowingProgressDlg = FALSE;
983 if (!RemoveFromProviderOrder(AFSREG_CLT_SVC_NAME)) {
984 ShowError(ERROR_FILE_NOT_FOUND, GetLastError());
985 return -1;
987 hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
988 if (!hSCM) {
989 ShowError(IDS_SCM_OPEN_FAILED, GetLastError());
990 return -1;
993 hServer = OpenService(hSCM, pAppInfo->pszSvcName, SERVICE_ALL_ACCESS | DELETE);
994 if (!hServer) {
995 ShowError(IDS_SERVICE_OPEN_FAILED, GetLastError());
996 CloseServiceHandle(hSCM);
997 return -1;
1000 if (!QueryServiceStatus(hServer, &status)) {
1001 ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());
1002 CloseServiceHandle(hServer);
1003 CloseServiceHandle(hSCM);
1004 return -1;
1007 if (status.dwCurrentState != SERVICE_STOPPED) {
1008 if (pAppInfo->nServiceShutdownMsgID) {
1009 if (!bSilentMode && (ShowMsg(pAppInfo->nServiceShutdownMsgID, MB_YESNO | MB_ICONQUESTION) == IDNO)) {
1010 CloseServiceHandle(hServer);
1011 CloseServiceHandle(hSCM);
1012 return 1;
1016 if (!bSilentMode)
1017 bShowingProgressDlg = ShowProgressDialog(LoadResString(pAppInfo->nServiceShutdownProgressMsgID));
1019 if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {
1020 if (bShowingProgressDlg)
1021 HideProgressDialog();
1022 ShowError(IDS_SERVICE_STOP_FAILED, GetLastError());
1023 CloseServiceHandle(hServer);
1024 CloseServiceHandle(hSCM);
1025 return -1;
1029 // Wait for the service to stop
1030 while (status.dwCurrentState != SERVICE_STOPPED) {
1031 // I stopped waiting on dwWaitHint because it seemed the wait hint was too long.
1032 // The service would be stopped but we'd still be asleep for a long time yet.
1033 Sleep(5000); //status.dwWaitHint);
1035 if (!QueryServiceStatus(hServer, &status)) {
1036 if (bShowingProgressDlg)
1037 HideProgressDialog();
1038 ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());
1039 CloseServiceHandle(hServer);
1040 CloseServiceHandle(hSCM);
1041 return -1;
1045 // The service has been stopped
1046 if (bShowingProgressDlg)
1047 HideProgressDialog();
1049 // This code to disable the service may be of use some day so I am keeping it here.
1050 // bOk = ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0);
1052 bOk = DeleteService(hServer);
1054 if (!bOk)
1055 ShowError(IDS_SERVICE_DELETE_FAILED, GetLastError());
1057 CloseServiceHandle(hServer);
1058 CloseServiceHandle(hSCM);
1060 return (bOk ? 0 : -1);
1063 int SUCALLCONV AddToNetworkProviderOrder(char *pszWhatToAdd)
1065 return AddToProviderOrder(pszWhatToAdd) ? 0 : -1;
1068 static int RemoveFromNetworkProviderOrder(char *pszWhatToDel)
1070 return RemoveFromProviderOrder(pszWhatToDel) ? 0 : -1;
1073 int SUCALLCONV AddToPath(char *pszPath)
1075 return AddToSystemPath(pszPath) ? 0 : -1;
1078 static int RemoveFromPath(char *pszPath)
1080 return RemoveFromSystemPath(pszPath) ? 0 : -1;
1083 static void RemoveFiles(char *pszFileSpec)
1085 struct _finddata_t fileinfo;
1086 long hSearch;
1087 char szDel[MAX_PATH];
1088 char szDir[MAX_PATH];
1089 char *p;
1091 strcpy(szDir, pszFileSpec);
1092 p = strrchr(szDir, '\\');
1093 if (p)
1094 *p = 0;
1096 hSearch = _findfirst(pszFileSpec, &fileinfo);
1097 if (hSearch == -1)
1098 return;
1100 while (1) {
1101 if ((strcmp(fileinfo.name, ".") != 0) && (strcmp(fileinfo.name, "..") != 0)) {
1102 sprintf(szDel, "%s\\%s", szDir, fileinfo.name);
1103 DeleteFile(szDel);
1106 if (_findnext(hSearch, &fileinfo) == -1)
1107 break;
1110 _findclose(hSearch);
1113 static void RemoveDir(char *pszDir)
1115 char szFileSpec[MAX_PATH];
1117 sprintf(szFileSpec, "%s\\*.*", pszDir);
1119 RemoveFiles(szFileSpec);
1120 RemoveDirectory(pszDir);
1123 static void RemoveRegValues(struct REGVALUE *pRegValues)
1125 struct REGVALUE *pCurValue;
1126 HKEY hKey;
1127 LONG nResult;
1129 if (!pRegValues)
1130 return;
1132 for (pCurValue = pRegValues; pCurValue->pszKey; pCurValue++) {
1133 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pCurValue->pszKey, KEY_ALL_ACCESS, FALSE, &hKey, 0);
1135 if (nResult == ERROR_SUCCESS) {
1136 nResult = RegDeleteValue(hKey, pCurValue->pszValue);
1137 RegCloseKey(hKey);
1140 if (nResult != ERROR_SUCCESS)
1141 ShowError(IDS_REG_DELETE_VALUE_ERROR, nResult);
1145 static BOOL UninstallCredsTool()
1147 int nResult = WinExec("afscreds /uninstall", SW_HIDE);
1149 if (nResult <= 31) {
1150 if (nResult != ERROR_FILE_NOT_FOUND)
1151 ShowError(IDS_CANT_UNINSTALL_AFSCREDS, nResult);
1154 // Always return true. We don't want the uninstall to completely fail just
1155 // because the creds tool didn't uninstall.
1156 return TRUE;
1160 static char *GetTempDir()
1162 DWORD result;
1163 static char szTempDir[MAX_PATH];
1165 result = GetTempPath(sizeof(szTempDir) - 1, szTempDir);
1166 if (result == 0)
1167 return "\\";
1169 return szTempDir;
1172 static char *GetRootInstallDir()
1174 char *psz;
1175 static char szRootInstallDir[MAX_PATH] = "";
1177 if (szRootInstallDir[0] == 0) {
1178 strcpy(szRootInstallDir, pszInstallDir);
1180 // Strip off the app specific part of the install dir
1181 psz = strrchr(szRootInstallDir, '\\');
1182 if (psz)
1183 *psz = 0;
1186 return szRootInstallDir;
1189 static BOOL ClientSpecificUninstall()
1191 int nChoice;
1193 // This function needs to do two things. First it needs to see if the server is
1194 // installed, and if it is, ask the user if they really want to uninstall the
1195 // client given that the server needs the client. Second, if we are uninstalling
1196 // the client, we need to uninstall the creds tool.
1198 if (!bSilentMode) {
1199 if (IsAppInstalled(&appServer)) {
1200 nChoice = ShowMsg(IDS_CLIENT_NEEDED_BY_SERVER, MB_ICONQUESTION | MB_YESNO);
1201 if (nChoice == IDNO)
1202 return FALSE; // Cancel the uninstall
1206 UninstallCredsTool();
1208 return TRUE;
1211 static struct APPINFO *GetApp()
1213 #ifdef SERVER_UNINST
1214 return &appServer;
1215 #elif CLIENT_UNINST
1216 return &appClient;
1217 #elif CC_UNINST
1218 return &appControlCenter;
1219 #elif LIGHT_CLIENT_UNINST
1220 return &appLightClient;
1221 #elif DOCS_UNINST
1222 return &appDocs;
1223 #else
1224 return 0;
1225 #endif;
1228 static void RememberInstallDir(char *pszInstallDir)
1230 HKEY hKey;
1232 // We remember the install dir so that when the UninstUninitialize function is called
1233 // by the InstallShield uninstaller, we can find out where we were installed to. We
1234 // have to do this because by the time that function is called, the registry values
1235 // created at install time are already gone. We need to be able to find out where we
1236 // were installed so we can clean up anything IS couldn't uninstall. If this fails in
1237 // any way then we don't care. The only consequence is that some junk might be left on
1238 // the users' system after an uninstall.
1240 LONG result = RegOpenKeyAlt(AFSREG_NULL_KEY, UNINSTALL_TEMP_INFO_KEY, KEY_WRITE, TRUE, &hKey, 0);
1241 if (result != ERROR_SUCCESS)
1242 return;
1244 RegSetValueEx(hKey, INSTALL_DIR_VALUE_NAME, 0, REG_SZ, (PBYTE)pszInstallDir, strlen(pszInstallDir) + 1);
1246 RegCloseKey(hKey);
1249 int SUCALLCONV SetSilentMode()
1251 bSilentMode = TRUE;
1253 return 0;
1256 static char *GetWinDir()
1258 static char szWinDir[MAX_PATH] = "";
1260 if (!szWinDir[0])
1261 GetWindowsDirectory(szWinDir, sizeof(szWinDir));
1263 return szWinDir;
1266 static char *GetWinSysDir()
1268 static char szWinSysDir[MAX_PATH] = "";
1270 if (!szWinSysDir[0])
1271 GetSystemDirectory(szWinSysDir, sizeof(szWinSysDir));
1273 return szWinSysDir;
1276 static char *GetLocaleID()
1278 static char szID[25] = "";
1280 if (szID[0] == 0) {
1281 LCID dwID = GetSystemDefaultLCID();
1283 // Nuke the high word. It contains a sort ID.
1284 dwID &= 0x0000FFFF;
1286 // Convert locale ID to a string
1287 itoa(dwID, szID, 10);
1289 // This thing should never be more than LOCALE_ID_LEN characters long.
1290 szID[LOCALE_ID_LEN] = 0;
1293 return szID;
1296 static char *ExpandPath(char *pszFile)
1298 static char szPath[MAX_PATH];
1299 char *psz;
1301 szPath[0] = 0;
1303 // Convert a path containing TARGETDIR, WINDIR, or WINSYSDIR to a
1304 // real path in the file system. One of these MUST be the start of
1305 // the file path passed in. Also convert the string ???? to an
1306 // actual locale number.
1307 if (strncmp(pszFile, TARGETDIR, strlen(TARGETDIR)) == 0)
1308 strcpy(szPath, GetRootInstallDir());
1309 else if (strncmp(pszFile, WINDIR, strlen(WINDIR)) == 0)
1310 strcpy(szPath, GetWinDir());
1311 else if (strncmp(pszFile, WINSYSDIR, strlen(WINSYSDIR)) == 0)
1312 strcpy(szPath, GetWinSysDir());
1314 if (szPath[0]) {
1315 psz = strchr(pszFile, '\\');
1316 if (psz)
1317 strcat(szPath, psz);
1318 } else
1319 strcpy(szPath, pszFile);
1321 // Is this a language dll?
1322 psz = strstr(szPath, "????.");
1324 // If it is, replace ???? with the locale number
1325 if (psz)
1326 strncpy(psz, GetLocaleID(), LOCALE_ID_LEN);
1328 return szPath;
1331 static BOOL FileNeededByOtherApp(struct APPINFO *pApp, struct FILEINFO *pFileInfo)
1333 // If the file is used by the server, the app being uninstalled is not the server, and
1334 // the server is installed, then this file is used by another app.
1335 if (!IsWinNT()) {
1336 if ((pFileInfo->nUsedBy & LCLIENT) && (pApp != &appLightClient) && IsAppInstalled(&appLightClient))
1337 return TRUE;
1338 return FALSE;
1341 if ((pFileInfo->nUsedBy & SERVER) && (pApp != &appServer) && IsAppInstalled(&appServer))
1342 return TRUE;
1344 if ((pFileInfo->nUsedBy & CLIENT) && (pApp != &appClient) && IsAppInstalled(&appClient))
1345 return TRUE;
1347 if ((pFileInfo->nUsedBy & CC) && (pApp != &appControlCenter) && IsAppInstalled(&appControlCenter))
1348 return TRUE;
1350 return FALSE;
1353 static void DeleteInUseFiles(struct APPINFO *pAppInfo, struct FILEINFO *pFileInfo)
1355 char szSrcPath[MAX_PATH];
1356 char szDestPath[MAX_PATH];
1357 char szTempDir[MAX_PATH];
1358 int ii;
1360 // If some app's file has been loaded before the app is uninstalled, then
1361 // when an uninstall is attempted, the application and all of the dlls that
1362 // its uses will be in use and IS will not be able to delete them. Normally this
1363 // is not a problem because IS will tell the user to reboot to finish the uninstall.
1364 // However, we must support the ability to perform a silent uninstall followed
1365 // immediatly by an install of the same product to the same directories. If we let
1366 // IS handle the uninstall of these files, this is not possible. The reason is that
1367 // when IS fails to remove these in use files, it marks them for deletion after the
1368 // next reboot, which is fine. Unfortunately, it leaves them in the dirs they were
1369 // installed to. So if we don't immediately reboot and perform an install to the
1370 // same dirs, once a reboot is performed, those files get deleted and we have a
1371 // broken installation.
1373 // What we will do to fix all of this, is when the client is uninstalled, but
1374 // before IS does anything, we will move the in use files and associated dlls
1375 // into the temp dir and mark them for delete after a reboot. Then an install
1376 // that follows will succeed.
1378 // Delete the files that may be in use. If they are we actually move
1379 // them to the temp dir and mark them for deletion after the next reboot.
1380 for (ii = 0; pFileInfo[ii].pszName != 0; ii++) {
1381 // Get the source path
1382 strcpy(szSrcPath, ExpandPath(pFileInfo[ii].pszName));
1384 // Only delete the file if it is not used by some other app
1385 if (FileNeededByOtherApp(pAppInfo, &pFileInfo[ii]))
1386 continue;
1388 // If the file doesn't exist then go on to the next file.
1389 if (_access(szSrcPath, 0) != 0)
1390 continue;
1392 // See if we can do a regular delete of the file
1393 if (DeleteFile(szSrcPath)) {
1394 SetSharedFileRefCount(szSrcPath, 0);
1395 continue;
1398 // Get a temp dir that is on the same drive as the src path.
1399 // We can't move an in use file to a different drive.
1400 strcpy(szTempDir, GetTempDir());
1401 if (szTempDir[0] != szSrcPath[0]) {
1402 // Get the drive, colon, and slash of the src path
1403 strncpy(szTempDir, szSrcPath, 3);
1404 szTempDir[3] = 0;
1407 // Get the dest path - we will rename the file during the move
1408 GetTempFileName(szTempDir, "AFS", 0, szDestPath);
1410 // Move from source to dest, marking the file for deletion after a reboot
1411 if (IsWin95()) {
1412 if (MoveFile(szSrcPath, szDestPath)) {
1413 WritePrivateProfileString("rename", szSrcPath, szDestPath, "wininit.ini");
1414 SetSharedFileRefCount(szSrcPath, 0);
1416 } else { // WinNT or Win98
1417 if (MoveFileEx(szSrcPath, szDestPath, MOVEFILE_REPLACE_EXISTING)) {
1418 SetFileAttributes(szDestPath, FILE_ATTRIBUTE_NORMAL);
1419 MoveFileEx(szDestPath, 0, MOVEFILE_DELAY_UNTIL_REBOOT);
1420 SetSharedFileRefCount(szSrcPath, 0);
1426 // Delete a directory and all its files and subdirectories - Yee haaa!
1427 static void RemoveDirectoryTree(char *pszDir)
1429 HANDLE hFind;
1430 WIN32_FIND_DATA findFileData;
1431 char szSpec[MAX_PATH];
1432 char szSubFileOrDir[MAX_PATH];
1433 BOOL bContinue;
1435 sprintf(szSpec, "%s\\*.*", pszDir);
1437 // First delete the contents of the dir
1438 hFind = FindFirstFile(szSpec, &findFileData);
1439 bContinue = (hFind != INVALID_HANDLE_VALUE);
1441 while (bContinue) {
1442 if ((strcmp(findFileData.cFileName, ".") != 0) && (strcmp(findFileData.cFileName, "..") != 0)) {
1443 sprintf(szSubFileOrDir, "%s\\%s", pszDir, findFileData.cFileName);
1445 if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1446 RemoveDirectoryTree(szSubFileOrDir);
1447 else
1448 DeleteFile(szSubFileOrDir);
1451 bContinue = FindNextFile(hFind, &findFileData);
1454 FindClose(hFind);
1456 // Now remove the dir
1457 RemoveDirectory(pszDir);
1460 static char *GetStartMenuRoot()
1462 HKEY hKey;
1463 LONG nResult;
1464 DWORD dwType;
1465 DWORD dwSize;
1466 char *pszKey;
1467 char *pszValue;
1469 static char szStartMenuRoot[MAX_PATH] = "";
1471 if (szStartMenuRoot[0] == 0) {
1472 dwSize = sizeof(szStartMenuRoot);
1474 if (IsWinNT()) {
1475 pszKey = WINNT_START_MENU_REG_KEY;
1476 pszValue = WINNT_START_MENU_REG_VALUE;
1477 } else {
1478 pszKey = WIN9X_START_MENU_REG_KEY;
1479 pszValue = WIN9X_START_MENU_REG_VALUE;
1482 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
1483 if (nResult == ERROR_SUCCESS) {
1484 nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szStartMenuRoot, &dwSize);
1485 RegCloseKey(hKey);
1488 if (nResult != ERROR_SUCCESS)
1489 return 0;
1492 FilepathNormalizeEx(szStartMenuRoot, FPN_BACK_SLASHES);
1494 return szStartMenuRoot;
1497 static char *GetAfsStartMenuRoot()
1499 static char szAfsStartMenuRoot[MAX_PATH] = "";
1500 char *pszStartMenuRoot;
1502 if (szAfsStartMenuRoot[0] == 0) {
1503 pszStartMenuRoot = GetStartMenuRoot();
1504 if (!pszStartMenuRoot)
1505 return 0;
1507 if (bSilentMode)
1508 sprintf(szAfsStartMenuRoot, "%s\\IBM WebSphere\\Performance Pack\\AFS", pszStartMenuRoot );
1509 else
1510 sprintf(szAfsStartMenuRoot, "%s\\IBM AFS", pszStartMenuRoot );
1513 return szAfsStartMenuRoot;
1516 static BOOL IsADir(char *pszName)
1518 struct _stat statbuf;
1520 if (_stat(pszName, &statbuf) < 0)
1521 return FALSE;
1523 return statbuf.st_mode & _S_IFDIR;
1526 static void DeleteStartMenuEntries(char *pszEntries)
1528 char szStartMenuPath[MAX_PATH];
1529 char *pszAfsStartMenuRoot;
1530 char *pszCurEntry;
1532 pszAfsStartMenuRoot = GetAfsStartMenuRoot();
1534 if (!pszAfsStartMenuRoot)
1535 return;
1537 for (pszCurEntry = pszEntries; *pszCurEntry; pszCurEntry += strlen(pszCurEntry) + 1) {
1538 sprintf(szStartMenuPath, "%s\\%s", pszAfsStartMenuRoot, pszCurEntry);
1539 if (IsADir(szStartMenuPath))
1540 RemoveDirectoryTree(szStartMenuPath);
1541 else
1542 DeleteFile(szStartMenuPath);
1546 static void RefreshStartMenu()
1548 char *pszAfsStartMenuRoot;
1549 char szTemp[MAX_PATH];
1551 pszAfsStartMenuRoot = GetAfsStartMenuRoot();
1552 if (!pszAfsStartMenuRoot)
1553 return;
1555 sprintf(szTemp, "%s - Refresh Attempt", pszAfsStartMenuRoot);
1557 // Deleting items from below the root level of the start menu does not
1558 // cause it to refresh. In order that users can see changes without
1559 // rebooting we will temporarily rename our root most entry, which
1560 // does cause a refresh of the start menu.
1561 MoveFileEx(pszAfsStartMenuRoot, szTemp, MOVEFILE_REPLACE_EXISTING);
1562 MoveFileEx(szTemp, pszAfsStartMenuRoot, MOVEFILE_REPLACE_EXISTING);
1565 static BOOL PreserveConfigInfo(struct APPINFO *pApp)
1567 char *pszRegKey;
1568 char szDestKey[256];
1569 LONG result;
1571 bPreserveConfigInfo = TRUE;
1573 // If not in silent mode, ask user if they want to preserve the cfg info
1574 if (!bSilentMode) {
1575 int nChoice = ShowMsg(pApp->nPreserveConfigInfoMsgID, MB_ICONQUESTION | MB_YESNOCANCEL);
1576 if (nChoice == IDCANCEL)
1577 return FALSE; // Cancel the uninstall
1578 else if (nChoice == IDNO) {
1579 bPreserveConfigInfo = FALSE; // User doesn't want to preserve the config info
1580 return TRUE;
1584 // Copy each reg key (and all of its subkeys and values) to another place in the registry.
1585 for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {
1586 if (!DoesRegKeyExist(pszRegKey))
1587 continue;
1589 // Create the destination path for the copy
1590 sprintf(szDestKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);
1592 // Try to copy it
1593 result = RegDupKeyAlt(pszRegKey, szDestKey);
1595 if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND)) {
1596 // If the copy failed, then delete any copies that succeeded
1597 sprintf(szDestKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
1598 RegDeleteEntryAlt(szDestKey, REGENTRY_KEY);
1599 goto done;
1603 // Remember the integrated login setting if this app supports that and it was turned on
1604 if (pApp->pszNetworkProviderOrder) {
1605 // Was integerated login turned on?
1606 BOOL bOn, bOk;
1607 bOk = InNetworkProviderOrder(pApp->pszNetworkProviderOrder, &bOn);
1608 if (bOk && bOn) {
1609 HKEY hKey;
1610 sprintf(szDestKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
1611 result = RegOpenKeyAlt(AFSREG_NULL_KEY, szDestKey, KEY_WRITE, TRUE, &hKey, 0);
1612 // The existance of the key is a flag indicating that integrated login was turned on
1613 RegCloseKey(hKey);
1617 done:
1618 if ((result == ERROR_SUCCESS) || bSilentMode)
1619 return TRUE; // Continue with uninstall
1621 // Report the error and ask the user if they want to continue the uninstall
1622 return (ShowMsg(IDS_SAVE_OF_CONFIG_INFO_FAILED, MB_ICONEXCLAMATION | MB_YESNO) == IDYES);
1625 int SUCALLCONV RestoreConfigInfo(int nApp)
1627 char *pszRegKey;
1628 char szSrcKey[256];
1629 struct APPINFO *pApp = 0;
1630 BOOL bError = FALSE;
1631 LONG result;
1633 switch (nApp) {
1634 case SERVER: pApp = &appServer; break;
1635 case CLIENT: pApp = &appClient; break;
1636 case LCLIENT: pApp = &appLightClient; break;
1637 case CC: pApp = &appControlCenter; break;
1640 if (!pApp)
1641 return -1;
1643 // Copy each reg key (and all of its subkeys and values) back to its original place in the registry.
1644 for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {
1645 // Create the source path for the copy
1646 sprintf(szSrcKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);
1648 if (!DoesRegKeyExist(szSrcKey))
1649 continue;
1651 // Try to restore as many of the keys as possible. Report any errors at the end.
1653 // Try to copy it
1654 result = RegDupKeyAlt(szSrcKey, pszRegKey);
1655 if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND))
1656 bError = TRUE;
1659 // Restore integrated login if this app was using it
1660 if (pApp->pszNetworkProviderOrder) {
1661 // Check if integrated login was turned on. The IntegratedLogin key is a flag
1662 // telling us that it was on. If the key does not exist, integrated login was
1663 // not on.
1664 sprintf(szSrcKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
1665 if (DoesRegKeyExist(szSrcKey)) {
1666 if (!AddToProviderOrder(pApp->pszNetworkProviderOrder))
1667 bError = TRUE;
1671 // Remove our saved copies of the config info
1672 sprintf(szSrcKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
1673 RegDeleteEntryAlt(szSrcKey, REGENTRY_KEY);
1675 if (bError)
1676 ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, 0);
1678 return TRUE;
1681 static BOOL DoSubKeysExist(char *pszKey)
1683 LONG result;
1684 HKEY hKey;
1685 char *pszSubKeys = 0;
1686 BOOL bExist;
1688 result = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
1689 if (result != ERROR_SUCCESS)
1690 return FALSE;
1692 result = RegEnumKeyAlt(hKey, &pszSubKeys);
1693 RegCloseKey(hKey);
1695 if (result != ERROR_SUCCESS)
1696 return FALSE;
1698 if (pszSubKeys) {
1699 bExist = TRUE;
1700 free(pszSubKeys);
1701 } else
1702 bExist = FALSE;
1704 return bExist;
1708 * The following definitions are taken from richedit.h:
1712 #define EM_SETBKGNDCOLOR (WM_USER + 67) // from Richedit.h
1713 #define EM_STREAMIN (WM_USER + 73) // from Richedit.h
1714 #define SF_RTF 0x0002
1716 typedef DWORD (CALLBACK *EDITSTREAMCALLBACK)(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
1718 typedef struct _editstream {
1719 DWORD dwCookie; /* user value passed to callback as first parameter */
1720 DWORD dwError; /* last error */
1721 EDITSTREAMCALLBACK pfnCallback;
1722 } EDITSTREAM;
1728 DWORD CALLBACK License_StreamText (DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
1730 LPTSTR psz = (LPTSTR)dwCookie;
1731 LONG cchAvail = lstrlen(psz);
1732 if ((*pcb = min(cchAvail, cb)) != 0) {
1733 memcpy (pbBuff, psz, *pcb);
1734 memmove (psz, &psz[*pcb], cchAvail - *pcb + 1);
1736 return 0;
1740 void License_OnInitDialog (HWND hDlg, LPTSTR pszFile)
1742 // Open the license file and shove its text in our RichEdit control
1744 HANDLE hFile;
1745 if ((hFile = CreateFile (pszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) {
1747 size_t cbText;
1748 if ((cbText = GetFileSize (hFile, NULL)) != 0) {
1750 LPTSTR abText = (LPTSTR)GlobalAlloc (GMEM_FIXED, cbText + 3);
1752 DWORD cbRead;
1753 if (ReadFile (hFile, abText, cbText, &cbRead, NULL)) {
1754 abText[ cbRead ] = 0;
1756 EDITSTREAM Stream;
1757 memset (&Stream, 0x00, sizeof(Stream));
1758 Stream.dwCookie = (DWORD)abText;
1759 Stream.pfnCallback = License_StreamText;
1761 SendDlgItemMessage (hDlg, IDC_TEXT, EM_STREAMIN, SF_RTF, (LPARAM)&Stream);
1764 GlobalFree (abText);
1767 CloseHandle (hFile);
1770 // Make the control's background be gray
1772 SendDlgItemMessage (hDlg, IDC_TEXT, EM_SETBKGNDCOLOR, FALSE, (LPARAM)GetSysColor(COLOR_BTNFACE));
1775 BOOL CALLBACK License_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
1777 switch (msg) {
1778 case WM_INITDIALOG:
1779 SetWindowLong (hDlg, DWL_USER, lp);
1780 License_OnInitDialog (hDlg, (LPTSTR)lp);
1781 break;
1783 case WM_COMMAND:
1784 switch (LOWORD(wp)) {
1785 case IDCANCEL:
1786 case IDOK:
1787 EndDialog (hDlg, LOWORD(wp));
1788 break;
1790 case IDC_PRINT:
1791 TCHAR szDir[ MAX_PATH ];
1792 GetCurrentDirectory (MAX_PATH, szDir);
1793 ShellExecute (hDlg, TEXT("print"), (LPTSTR)GetWindowLong (hDlg, DWL_USER), NULL, szDir, SW_HIDE);
1794 break;
1796 break;
1798 return FALSE;
1801 BOOL FindAfsInstallationPathByComponent (LPTSTR pszInstallationPath, LPTSTR pszComponent)
1803 *pszInstallationPath = 0;
1805 TCHAR szRegPath[ MAX_PATH ];
1806 wsprintf (szRegPath, TEXT("Software\\TransarcCorporation\\%s\\CurrentVersion"), pszComponent);
1808 HKEY hk;
1809 if (RegOpenKey (HKEY_LOCAL_MACHINE, szRegPath, &hk) == 0) {
1810 DWORD dwType = REG_SZ;
1811 DWORD dwSize = MAX_PATH;
1813 if (RegQueryValueEx (hk, TEXT("PathName"), NULL, &dwType, (PBYTE)pszInstallationPath, &dwSize) == 0) {
1814 *(LPTSTR)FindBaseFileName (pszInstallationPath) = TEXT('\0');
1816 if (pszInstallationPath[0] && (pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] == TEXT('\\')))
1817 pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] = TEXT('\0');
1820 RegCloseKey (hk);
1823 return !!*pszInstallationPath;
1826 BOOL FindAfsInstallationPath (LPTSTR pszInstallationPath)
1828 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Client")))
1829 return TRUE;
1830 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Control Center")))
1831 return TRUE;
1832 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Server")))
1833 return TRUE;
1834 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Supplemental Documentation")))
1835 return TRUE;
1836 return FALSE;
1839 HINSTANCE LoadRichTextControl (void)
1841 HINSTANCE hInst;
1842 if ((hInst = LoadLibrary ("riched20.dll")) != NULL)
1843 return hInst;
1844 if ((hInst = LoadLibrary ("riched32.dll")) != NULL)
1845 return hInst;
1846 if ((hInst = LoadLibrary ("riched.dll")) != NULL)
1847 return hInst;
1848 if ((hInst = LoadLibrary ("richedit.dll")) != NULL)
1849 return hInst;
1850 return NULL;
1853 int SUCALLCONV ShowLicense (char *pszTarget, char *pszSource)
1855 // If the license already lives on this user's machine, don't show
1856 // it again. This only has to be done if the user has never
1857 // accepted the license agreement before (it's part of the setup
1858 // program, so it gets installed if they've accepted it).
1860 // We were handed a relative path of the form:
1861 // Documentation/html/license.rtf
1863 // We'll need to find the AFS installation directory, in order to
1864 // find that Documentation subtree.
1866 BOOL fShowLicense = TRUE;
1868 TCHAR szInstallationPath[ MAX_PATH ];
1869 if (FindAfsInstallationPath (szInstallationPath)) {
1870 TCHAR szLicensePath[ MAX_PATH ];
1871 wsprintf (szLicensePath, TEXT("%s\\%s"), szInstallationPath, pszTarget);
1873 if (GetFileAttributes (szLicensePath) != (DWORD)-1) {
1874 fShowLicense = FALSE;
1878 // Before we can show the license file, we have to prepare the RichEdit
1879 // control. That means loading the appropriate library and calling its
1880 // initialization functions.
1882 HINSTANCE hRichEdit;
1883 if ((hRichEdit = LoadRichTextControl()) != NULL) {
1885 // If we must show the license, do so now. This is a modal dialog,
1886 // so we'll know whether or not the user accepts the license.
1888 if (ModalDialogParam (IDD_LICENSE, GetActiveWindow(), License_DlgProc, (LPARAM)pszSource) == IDCANCEL) {
1889 // The user rejected the license; fail setup
1890 return FALSE;
1893 FreeLibrary (hRichEdit);
1896 // The user accepted the license, so we can continue with Setup.
1897 // The license file is installed as part of Setup.
1898 return TRUE;
1901 int SUCALLCONV UninstInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)
1903 char szPath[MAX_PATH];
1904 struct APPINFO *pAppInfo;
1905 char *pszFile = 0;
1906 char *pszSubDir = 0;
1908 hDlg = hIS;
1910 bSilentMode = !IsWindowVisible(hIS);
1912 // Which app are we uninstalling?
1913 pAppInfo = GetApp();
1914 if (!pAppInfo) {
1915 ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);
1916 return -1;
1919 // Get the app's install dir
1920 pszInstallDir = GetAppInstallDir(pAppInfo, FALSE);
1921 if (!pszInstallDir)
1922 return -1;
1924 // If this app has a custom uninstall func, call it here
1925 if (pAppInfo->pUninstallFunc)
1926 if (!pAppInfo->pUninstallFunc())
1927 return -1;
1929 if (pAppInfo->pszRegKeysToPreserve)
1930 if (!PreserveConfigInfo(pAppInfo))
1931 return -1;
1933 // Unconfigure the service, if there is one for this app
1934 if (pAppInfo->pszSvcKey) {
1935 if (IsServiceInstalled(pAppInfo->pszSvcKey))
1936 if (UninstallService(pAppInfo) == 1)
1937 return -1;
1940 RememberInstallDir(pszInstallDir);
1942 DeleteInUseFiles(pAppInfo, fileInfo);
1944 // Remove the app's bin path from the system path
1945 if (pAppInfo->pszBinPath) {
1946 BuildShortPath(szPath, sizeof(szPath), pszInstallDir, pAppInfo->pszBinPath);
1947 RemoveFromPath(szPath);
1950 // Remove entry from NetworkProvider\Order key in registry
1951 if (pAppInfo->pszNetworkProviderOrder)
1952 RemoveFromNetworkProviderOrder(pAppInfo->pszNetworkProviderOrder);
1954 // Remove any generated subdirectories
1955 if (!bPreserveConfigInfo && pAppInfo->pszDirsToDel) {
1956 for (pszSubDir = pAppInfo->pszDirsToDel; *pszSubDir; pszSubDir += strlen(pszSubDir) + 1)
1957 RemoveDir(ExpandPath(pszSubDir));
1960 // Remove any generated files
1961 if (!bPreserveConfigInfo && pAppInfo->pszFilesToDel) {
1962 for (pszFile = pAppInfo->pszFilesToDel; *pszFile; pszFile += strlen(pszFile) + 1)
1963 RemoveFiles(ExpandPath(pszFile));
1966 // Remove any registry values that IS can't handle
1967 RemoveRegValues(pAppInfo->pRegValues);
1968 if (IsWinNT())
1969 RemoveRegValues(pAppInfo->pWinNTRegValues);
1970 else
1971 RemoveRegValues(pAppInfo->pWin9XRegValues);
1973 // Remove the start menu entries for this app
1974 if (pAppInfo->pszStartMenuEntries) {
1975 DeleteStartMenuEntries(pAppInfo->pszStartMenuEntries);
1976 RefreshStartMenu();
1979 // Remove the install dir
1980 RemoveDirectory(pszInstallDir);
1982 return 0;
1985 void SUCALLCONV UninstUnInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)
1987 char *pszInstallDir;
1988 char szDirPath[MAX_PATH];
1989 char *psz;
1990 struct APPINFO *pAppInfo;
1992 // If we just uninstalled the last AFS app, then do some cleanup.
1993 if (IsAppInstalled(&appServer) || IsAppInstalled(&appClient) ||
1994 IsAppInstalled(&appControlCenter) || IsAppInstalled(&appLightClient) ||
1995 IsAppInstalled(&appDocs))
1997 return;
2000 bSilentMode = !IsWindowVisible(hIS);
2002 // Which app did we just uninstall?
2003 pAppInfo = GetApp();
2004 if (!pAppInfo) {
2005 ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);
2006 return;
2009 // Get the app's install dir
2010 pszInstallDir = GetAppInstallDir(pAppInfo, TRUE);
2011 if (!pszInstallDir)
2012 return;
2014 // Remove the reg key we used to remember the app install dir
2015 RegDeleteEntryAlt(UNINSTALL_TEMP_INFO_KEY, REGENTRY_KEY);
2017 // Try to remove the reg key used to store config info, but only
2018 // if there are no app config info sub keys present.
2019 if (!DoSubKeysExist(AFS_PRESERVED_CFG_INFO_KEY))
2020 RegDeleteEntryAlt(AFS_PRESERVED_CFG_INFO_KEY, REGENTRY_KEY);
2022 // Remove the install dir
2023 RemoveDirectory(pszInstallDir);
2025 // Attempt to remove the install root and common directories. The are
2026 // shared and so no single app knows to delete them.
2028 // Strip off the app specific part of the install dir
2029 psz = strrchr(pszInstallDir, '\\');
2030 if (psz)
2031 *psz = 0;
2033 sprintf(szDirPath, "%s\\%s", pszInstallDir, "Common");
2034 RemoveDirectory(szDirPath);
2036 // Remove the Common directory from the system path
2037 RemoveFromPath(szDirPath);
2039 // Remove all of the documentation dirs
2040 sprintf(szDirPath, "%s\\%s", pszInstallDir, "Documentation");
2041 RemoveDirectoryTree(szDirPath);
2043 // Ok, up to this point we have been removing files we know we
2044 // created. However, after this point we are into the path
2045 // that the user chose for our install root. The default for
2046 // this is IBM/Afs, but they could have chosen anything,
2047 // including a dir or dirs that have other products in them.
2048 // We will check to see if it is IBM\AFS and if it is then we
2049 // will attempt to remove them.
2051 // Back up a level and look for AFS
2052 psz = strrchr(pszInstallDir, '\\');
2053 if (psz) {
2054 if (stricmp(psz + 1, "AFS") == 0) {
2055 RemoveDirectory(pszInstallDir);
2056 *psz = 0;
2060 // Back up a level and look for IBM
2061 psz = strrchr(pszInstallDir, '\\');
2062 if (psz) {
2063 if (stricmp(psz + 1, "IBM") == 0) {
2064 RemoveDirectory(pszInstallDir);
2065 *psz = 0;
2069 // Remove the root afs start menu entry
2070 psz = GetStartMenuRoot();
2071 if (psz) {
2072 if (bSilentMode) {
2073 // Remove everything under our branch
2074 sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack\\AFS", psz);
2075 RemoveDirectoryTree(szDirPath);
2077 // Remove the IBM stuff only if the dirs are empty
2078 sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack", psz);
2079 if (RemoveDirectory(szDirPath)) {
2080 sprintf(szDirPath, "%s\\IBM WebSphere", psz);
2081 RemoveDirectory(szDirPath);
2083 } else {
2084 sprintf(szDirPath, "%s\\IBM AFS", psz);
2085 RemoveDirectoryTree(szDirPath);
2090 BOOLEAN _stdcall DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
2092 if (reason == DLL_PROCESS_ATTACH) {
2093 hinst = (HINSTANCE)dll;
2094 TaLocale_LoadCorrespondingModuleByName (hinst, "afs_setup_utils.dll");
2097 return TRUE;
2100 extern "C" int WINAPI Test (HINSTANCE hInst, HINSTANCE hPrev, LPSTR psz, int nCmdShow)
2102 ShowLicense ("TEST", "\\\\fury\\afssetup\\license\\ja_JP.rtf");
2103 return 0;