*/
/*
- * INCLUDES _________________________________________________________________\r
- *\r
- */\r
-\r
-extern "C" {\r
-#include <afs/param.h>\r
-#include <afs/stds.h>\r
-#include <afs/fileutil.h>\r
-}\r
-\r
-#include <windows.h>\r
-#include <stdio.h>\r
-#include <time.h>\r
-#include <assert.h>\r
-#include <stdlib.h>\r
-#include <io.h>\r
-#include <string.h>\r
-#include <SYS\STAT.H>\r
-#include <shellapi.h>\r
-\r
-#include <WINNT/afsreg.h>\r
-#include <WINNT/afssw.h>\r
-#include <WINNT/talocale.h>\r
-\r
-#include "resource.h"\r
-#include "progress_dlg.h"\r
-#include "sutil.h"\r
-#include "forceremove.h"\r
-\r
-\r
-/*\r
- * PROTOTYPES _________________________________________________________________\r
- *\r
- */\r
-static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered);\r
-BOOL UninstallCredsTool();\r
-BOOL ServerSpecificUninstall();\r
-BOOL ClientSpecificUninstall();\r
-\r
-\r
-\r
-/*\r
- * DEFINITIONS _________________________________________________________________\r
- *\r
- */\r
-#define SUCALLCONV WINAPI\r
-\r
-#define UNINSTALL_TEMP_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsUninstallTempInfo"\r
-#define INSTALL_DIR_VALUE_NAME "InstallDir"\r
-\r
-#define AFS_PRESERVED_CFG_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsPreservedConfigInfo"\r
-\r
-#define MS_SHARED_FILES_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs"\r
-\r
-// Log file to use when running in silent mode\r
-#define UNINSTALL_ERROR_LOG_NAME "\\AfsUninstallErrorLog.txt"\r
-#define INSTALL_ERROR_LOG_NAME "\\AfsInstallErrorLog.txt"\r
-\r
-#define TARGETDIR "<TARGETDIR>"\r
-#define WINDIR "<WINDIR>"\r
-#define WINSYSDIR "<WINSYSDIR>"\r
-\r
-#define WIN9X_START_MENU_REG_KEY "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"\r
-#define WIN9X_START_MENU_REG_VALUE "Programs"\r
- \r
-#define WINNT_START_MENU_REG_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"\r
-#define WINNT_START_MENU_REG_VALUE "Common Programs"\r
-\r
-#define LOCALE_ID_LEN 4\r
-\r
-struct REGVALUE {\r
- char *pszKey;\r
- char *pszValue;\r
-};\r
-\r
-\r
-typedef BOOL (APP_UNINSTALL_FUNC)();\r
-\r
-\r
-\r
-struct APPINFO {\r
- char *pszAppName;\r
-\r
- // Service Info\r
- char *pszSvcName;\r
- char *pszSvcKey;\r
- char *pszSvcDependOn;\r
- char *pszSvcDisplayName;\r
-\r
- char *pszNetworkProviderOrder;\r
-\r
- // Message to use to tell the user that we have to stop the service\r
- int nServiceShutdownMsgID;\r
-\r
- // Message to use for the progress dialog that is shown while\r
- // waiting for the service to stop.\r
- int nServiceShutdownProgressMsgID;\r
-\r
- // Location in registry of a key we can use to know that the app is installed\r
- char *pszAppKey;\r
-\r
- // Location in registry of this app's install dir\r
- struct REGVALUE regInstallDir;\r
-\r
- // Path Info\r
- char *pszLocalRoot; // The root dir below the install dir\r
- char *pszBinPath; // Path to remove from the system path\r
-\r
- // Generated files and directories to delete. These are both multistring lists.\r
- char *pszDirsToDel; // All files in these dirs will be deleted\r
- char *pszFilesToDel; // Use this if you want to delete files but leave the dir. Wildcards can be used.\r
-\r
- // Registry values to remove\r
- struct REGVALUE *pRegValues;\r
- struct REGVALUE *pWinNTRegValues; // Only remove these if running WinNT\r
- struct REGVALUE *pWin9XRegValues; // Only remove these if running Win9X\r
-\r
- // Start menu entries to delete\r
- char *pszStartMenuEntries;\r
-\r
- // Registry keys to save if a user wants to preserve config info during uninstall\r
- char *pszRegKeysToPreserve;\r
- int nPreserveConfigInfoMsgID;\r
-\r
- // Uninstall func - used for things specific to this app\r
- APP_UNINSTALL_FUNC *pUninstallFunc;\r
-};\r
-\r
-\r
-/*\r
- * App info structure for the Server product\r
- */\r
-struct APPINFO appServer = {\r
- "AFS Server",\r
- \r
- AFSREG_SVR_SVC_NAME,\r
- AFSREG_SVR_SVC_KEY,\r
- 0, // No depend on\r
- AFSREG_SVR_SVC_DISPLAYNAME_DATA,\r
-\r
- 0, // No network provider order\r
-\r
- IDS_MUST_STOP_SERVER,\r
- IDS_WAITING_FOR_SERVER_TO_STOP,\r
-\r
- AFSREG_SVR_SW_VERSION_KEY,\r
- \r
- { AFSREG_SVR_SW_VERSION_KEY, AFSREG_SVR_SW_VERSION_DIR_VALUE },\r
-\r
- "\\Server",\r
- "\\usr\\afs\\bin",\r
-\r
- // Dirs to delete\r
- TARGETDIR"\\Server\\usr\\afs\\bin\\backup\0"\r
- TARGETDIR"\\Server\\usr\\afs\\bin\0"\r
- TARGETDIR"\\Server\\usr\\afs\\db\0"\r
- TARGETDIR"\\Server\\usr\\afs\\logs\0"\r
- TARGETDIR"\\Server\\usr\\afs\\etc\0"\r
- TARGETDIR"\\Server\\usr\\afs\\local\0"\r
- TARGETDIR"\\Server\\usr\\afs\0"\r
- TARGETDIR"\\Server\\usr\0",\r
- \r
- // Files to delete\r
- TARGETDIR"\\Common\\*.gid\0"\r
- TARGETDIR"\\Common\\*.fts\0",\r
-\r
- 0, // No reg values\r
- 0, // No NT only reg values\r
- 0, // No 9x only reg values\r
-\r
- "Server\0",\r
-\r
- // Config info to preserve\r
- AFSREG_SVR_SVC_KEY"\0", \r
- IDS_PRESERVE_SERVER_CONFIG_INFO,\r
-\r
- 0 // No special uninstall function\r
-};\r
-\r
-// Registry values to remove for the Client\r
-struct REGVALUE clientRegValues[] = {\r
- { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", "{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}" },\r
- { 0, 0 } // This indicates there are no more entries\r
-};\r
-\r
-struct REGVALUE clientWinNTRegValues[] = {\r
- { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\File Manager\\AddOns", "AFS Client FME" },\r
- { 0, 0 }\r
-};\r
-\r
-struct REGVALUE clientWin9XRegValues[] = {\r
- { "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", "TransarcAFSDaemon" },\r
- { 0, 0 }\r
-};\r
-\r
-/*\r
- * App info structure for the Client product\r
- */\r
-struct APPINFO appClient = {\r
- "AFS Client",\r
- \r
- AFSREG_CLT_SVC_NAME,\r
- AFSREG_CLT_SVC_KEY,\r
- "5250435353004E657462696F730000",\r
- AFSREG_CLT_SVC_DISPLAYNAME_DATA,\r
-\r
- AFSREG_CLT_SVC_NAME,\r
-\r
- IDS_MUST_STOP_CLIENT,\r
- IDS_WAITING_FOR_CLIENT_TO_STOP,\r
-\r
- AFSREG_CLT_SW_VERSION_KEY,\r
-\r
- { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },\r
-\r
- "\\Client",\r
- "\\Program",\r
-\r
- // No dirs to delete\r
- 0,\r
- \r
- // Files to delete\r
- TARGETDIR"\\Common\\*.gid\0"\r
- TARGETDIR"\\Common\\*.fts\0"\r
- WINDIR"\\..\\AFSCache\0"\r
- WINDIR"\\afsd.log\0"\r
- WINDIR"\\afsd.ini\0"\r
- WINDIR"\\afsdsbmt.ini\0"\r
- WINDIR"\\afsd_init.log\0",\r
- \r
- clientRegValues,\r
- clientWinNTRegValues,\r
- clientWin9XRegValues,\r
-\r
- // Start menu entries to remove\r
- "Client\0",\r
-\r
- // Config info to preserve\r
- AFSREG_CLT_SVC_KEY"\0",\r
- IDS_PRESERVE_CLIENT_CONFIG_INFO,\r
-\r
- ClientSpecificUninstall\r
-};\r
-\r
-\r
-/*\r
- * App info structure for the Light Client product\r
- */\r
-struct APPINFO appLightClient = {\r
- "AFS Light",\r
- \r
- // No service info \r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
-\r
- AFSREG_CLT_SVC_NAME,\r
-\r
- // No service shutdown messages\r
- 0,\r
- 0,\r
-\r
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Light Client",\r
-\r
- { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },\r
-\r
- "\\Client",\r
- "\\Program",\r
-\r
- // No dirs to delete\r
- 0,\r
- \r
- // Files to delete\r
- TARGETDIR"\\Common\\*.gid\0"\r
- TARGETDIR"\\Common\\*.fts\0",\r
-\r
- clientRegValues,\r
- clientWinNTRegValues,\r
- clientWin9XRegValues,\r
-\r
- // Start menu entries to remove\r
- "Light\0",\r
-\r
- // Config info to preserve\r
- AFSREG_CLT_SVC_KEY"\0",\r
- IDS_PRESERVE_LIGHT_CLIENT_CONFIG_INFO,\r
-\r
- UninstallCredsTool\r
-};\r
-\r
-\r
-/*\r
- * App info structure for the Control Center product\r
- */\r
-struct APPINFO appControlCenter = {\r
- "AFS Control Center",\r
- \r
- // No service info\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
-\r
- // No network provider order\r
- 0,\r
-\r
- // No service shutdown messages \r
- 0,\r
- 0,\r
-\r
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center",\r
- \r
- { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center\\CurrentVersion", "PathName" },\r
-\r
- "\\Control Center",\r
- "",\r
-\r
- // No dirs to delete\r
- 0,\r
- \r
- // Files to delete\r
- TARGETDIR"\\Common\\*.gid\0"\r
- TARGETDIR"\\Common\\*.fts\0",\r
- \r
- 0, // No reg values\r
- 0, // No NT only reg values\r
- 0, // No 9x only reg values\r
-\r
- // Start menu entries to remove\r
- "Control Center\0",\r
-\r
- // Config info to preserve\r
- AFSREG_CLT_SVC_KEY"\0",\r
- IDS_PRESERVE_CC_CONFIG_INFO,\r
-\r
- 0 // No uninstall function\r
-};\r
-\r
-\r
-/*\r
- * App info structure for the Sys Admin Doc files\r
- */\r
-struct APPINFO appDocs = {\r
- "AFS Supplemental Documentation",\r
-\r
- // No service info\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
-\r
- // No network provider order\r
- 0,\r
-\r
- // No service shutdown messages \r
- 0,\r
- 0,\r
-\r
- "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation",\r
- \r
- { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation\\CurrentVersion", "PathName" },\r
-\r
- "\\Documentation",\r
- "",\r
-\r
- // No dirs to delete\r
- 0,\r
- \r
- // Files to delete\r
- TARGETDIR"\\Common\\*.gid\0"\r
- TARGETDIR"\\Common\\*.fts\0",\r
-\r
- 0, // No reg values\r
- 0, // No NT only reg values\r
- 0, // No 9x only reg values\r
-\r
- // Start menu entries to remove\r
- "Documentation\\AFS for Windows Backup Command Reference.lnk\0Documentation\\AFS Command Reference Manual.lnk\0Documentation\\AFS System Administrator's Guide.lnk\0",\r
-\r
- 0, // No config info to preserve\r
-\r
- 0 // No uninstall function\r
-};\r
-\r
-\r
-// Shared and in-use files\r
-struct FILEINFO {\r
- char *pszName;\r
- int nUsedBy;\r
-};\r
-\r
-#define SERVER 1\r
-#define CLIENT 2\r
-#define LCLIENT 4\r
-#define CC 8\r
-#define DOCS 16\r
-\r
-\r
-struct FILEINFO fileInfo[] = {\r
- { TARGETDIR"\\Common\\afsbosadmin.dll", SERVER | CC },\r
- { TARGETDIR"\\Common\\afscfgadmin.dll", SERVER | CC },\r
- { TARGETDIR"\\Common\\afsclientadmin.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afskasadmin.dll", SERVER | CC },\r
- { TARGETDIR"\\Common\\afsptsadmin.dll", SERVER | CC },\r
- { TARGETDIR"\\Common\\afsvosadmin.dll", SERVER | CC },\r
- { TARGETDIR"\\Common\\afsadminutil.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afsrpc.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afsauthent.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\pthread.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\TaAfsAppLib.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afsprocmgmt.dll", SERVER | CLIENT | LCLIENT },\r
- { TARGETDIR"\\Common\\afs_config.exe", CLIENT | LCLIENT| CC },\r
- { TARGETDIR"\\Common\\afseventmsg_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afslegal_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afsserver_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afssvrcfg_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\TaAfsAccountManager_????.dll",SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\TaAfsAppLib_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\TaAfsServerManager_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afscreds_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs_config_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs_cpa_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs_shl_ext_????.dll", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs-nt.hlp", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs-nt.cnt", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\taafssvrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\taafssvrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\taafsusrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\taafsusrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs-cc.cnt", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs-cc.hlp", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs-light.cnt", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\afs-light.hlp", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\taafscfg.cnt", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Common\\taafscfg.hlp", SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Client\\PROGRAM\\afs_shl_ext.dll", CLIENT | LCLIENT },\r
- { TARGETDIR"\\Client\\PROGRAM\\libafsconf.dll", CLIENT | LCLIENT },\r
- { TARGETDIR"\\Client\\PROGRAM\\afslogon.dll", CLIENT },\r
- { TARGETDIR"\\Client\\PROGRAM\\afslog95.dll", LCLIENT },\r
- { TARGETDIR"\\Control Center\\TaAfsAdmSvr.exe", CC },\r
- { WINSYSDIR"\\afs_cpa.cpl", CLIENT | LCLIENT | CC },\r
- { WINSYSDIR"\\afsserver.cpl", SERVER },\r
- { TARGETDIR"\\Common\\afsdcell.ini", CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Documentation\\Html\\banner.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\books.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\bot.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\index.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\index.htm", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\next.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\prev.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\toc.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\top.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },\r
- { TARGETDIR"\\Documentation\\Html\\ReleaseNotes\\relnotes.htm",\r
- SERVER | CLIENT | LCLIENT | CC },\r
- { TARGETDIR"\\Documentation\\Html\\InstallGd\\afsnt35i.htm",\r
- SERVER | CLIENT | LCLIENT | CC },\r
- { 0, 0 } // End of list\r
-};\r
-\r
-\r
-/*\r
- * VARIABLES _________________________________________________________________\r
- *\r
- */\r
-HINSTANCE hinst;\r
-\r
-static HWND hDlg;\r
-static BOOL bPreserveConfigInfo;\r
-static BOOL bSilentMode;\r
-static char *pszInstallDir;\r
-\r
-\r
-/*\r
- * FUNCTIONS _________________________________________________________________\r
- *\r
- */\r
-\r
-static BOOL UpgradeClientIntParm(HKEY hKey, char *pszOldParm, char *pszNewParm)\r
-{\r
- int nData;\r
- LONG result = ERROR_SUCCESS;\r
-\r
- nData = GetPrivateProfileInt("AFS Client", pszOldParm, -1, "afsd.ini");\r
- if (nData > -1)\r
- result = RegSetValueEx(hKey, pszNewParm, 0, REG_DWORD, (BYTE *)&nData, sizeof(nData));\r
-\r
- return (result == ERROR_SUCCESS);\r
-}\r
-\r
-static BOOL UpgradeClientStringParm(HKEY hKey, char *pszOldParm, char *pszNewParm)\r
-{\r
- char szData[1024];\r
- LONG result = ERROR_SUCCESS;\r
-\r
- GetPrivateProfileString("AFS Client", pszOldParm, "", szData, sizeof(szData), "afsd.ini");\r
- if (szData[0])\r
- result = RegSetValueEx(hKey, pszNewParm, 0, REG_SZ, (PBYTE)szData, strlen(szData) + 1);\r
-\r
- return (result == ERROR_SUCCESS);\r
-}\r
-\r
-int SUCALLCONV Upgrade34ClientConfigInfo()\r
-{\r
- HKEY hKey;\r
- LONG result;\r
- int nData;\r
- \r
- result = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_CLT_SVC_PARAM_KEY, KEY_WRITE, TRUE, &hKey, 0);\r
- if (result != ERROR_SUCCESS)\r
- return -1;\r
-\r
- UpgradeClientIntParm(hKey, "CacheSize", "CacheSize");\r
- UpgradeClientIntParm(hKey, "Stats", "Stats");\r
- UpgradeClientIntParm(hKey, "LogoffTokenTransfer", "LogoffTokenTransfer");\r
- UpgradeClientIntParm(hKey, "LogoffTokenTransferTimeout", "LogoffTokenTransferTimeout");\r
- UpgradeClientIntParm(hKey, "TrapOnPanic", "TrapOnPanic");\r
- UpgradeClientIntParm(hKey, "TraceBufferSize", "TraceBufferSize");\r
- UpgradeClientIntParm(hKey, "TraceOnShutdown", "TraceOnShutdown");\r
- UpgradeClientIntParm(hKey, "ReportSessionStartups", "ReportSessionStartups");\r
- \r
- UpgradeClientStringParm(hKey, "MountRoot", "MountRoot");\r
- UpgradeClientStringParm(hKey, "Cell", "Cell");\r
-\r
- /* BlockSize to ChunkSize requires convertion */\r
- nData = GetPrivateProfileInt("AFS Client", "BlockSize", -1, "afsd.ini");\r
- if (nData > -1) {\r
- DWORD chunkSize;\r
- for (chunkSize = 0; (1 << chunkSize) < nData; chunkSize++);\r
- (void) RegSetValueEx(hKey, "ChunkSize", 0, REG_DWORD, (BYTE *)&chunkSize, sizeof(chunkSize));\r
- }\r
-\r
- RegCloseKey(hKey);\r
-\r
- return 0;\r
-}\r
-\r
-int SUCALLCONV Eradicate34Client()\r
-{\r
- if (Client34Eradicate(TRUE) != ERROR_SUCCESS)\r
- return -1;\r
-\r
- return 0;\r
-}\r
-\r
-// This function was written a long time ago by Mike Comer for use by the \r
-// original DFS Client for NT install program.\r
-int SUCALLCONV CheckIfAdmin(void)\r
-{\r
- HANDLE token = INVALID_HANDLE_VALUE;\r
- PVOID buffer = 0;\r
- DWORD bufLength;\r
- DWORD realBufLength;\r
- TOKEN_PRIMARY_GROUP *pgroup;\r
- TOKEN_GROUPS *groups;\r
- int result = -1;\r
- DWORD groupCount;\r
- LONG status;\r
- PSID AdministratorSID = NULL;\r
- SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;\r
-\r
- // allocate the SID for the Administrators group\r
- if (!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorSID)) {\r
- status = GetLastError();\r
- goto getout;\r
- }\r
-\r
- // open the process token\r
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) {\r
- status = GetLastError();\r
- token = INVALID_HANDLE_VALUE;\r
- goto getout;\r
- }\r
-\r
- // check primary group first\r
- buffer = GlobalAlloc(GMEM_FIXED, sizeof(TOKEN_PRIMARY_GROUP));\r
- if (!buffer) {\r
- goto getout;\r
- }\r
-\r
- bufLength = sizeof(TOKEN_PRIMARY_GROUP);\r
- while(1) {\r
- if (!GetTokenInformation(token, TokenPrimaryGroup, buffer, bufLength, &realBufLength)) {\r
- if (realBufLength > bufLength) {\r
- // not enough space\r
- GlobalFree(buffer);\r
- bufLength = realBufLength;\r
- buffer = GlobalAlloc(GMEM_FIXED, realBufLength);\r
- if (!buffer) {\r
- goto getout;\r
- }\r
- continue;\r
- }\r
-\r
- goto getout;\r
- }\r
- break;\r
- }\r
-\r
- pgroup = (TOKEN_PRIMARY_GROUP *)buffer;\r
- if (EqualSid(pgroup->PrimaryGroup, AdministratorSID)) {\r
- result = 0;\r
- } else {\r
- // okay, try the secondary groups\r
- while(1) {\r
- if (!GetTokenInformation(token, TokenGroups, buffer, bufLength, &realBufLength)) {\r
- if (realBufLength > bufLength) {\r
- // not enough space\r
- GlobalFree(buffer);\r
- bufLength = realBufLength;\r
- buffer = GlobalAlloc(GMEM_FIXED, realBufLength);\r
- if (!buffer) {\r
- goto getout;\r
- }\r
- continue;\r
- }\r
-\r
- // a real error\r
- goto getout;\r
- }\r
- break;\r
- }\r
-\r
- // we have the list of groups here. Process them:\r
- groups = (TOKEN_GROUPS *)buffer;\r
- for(groupCount = 0; groupCount < groups->GroupCount; groupCount++) {\r
- if (EqualSid(groups->Groups[groupCount].Sid, AdministratorSID)) {\r
- result = 0;\r
- break;\r
- }\r
- }\r
- }\r
-\r
-getout:\r
-\r
- if (token != INVALID_HANDLE_VALUE) {\r
- CloseHandle(token);\r
- }\r
-\r
- if (buffer) {\r
- GlobalFree(buffer);\r
- }\r
-\r
- if (AdministratorSID) {\r
- FreeSid(AdministratorSID);\r
- }\r
-\r
- return result;\r
-}\r
-\r
-static void SetSharedFileRefCount(char *pszFile, int nRefCount)\r
-{\r
- LONG result;\r
- HKEY hKey;\r
- \r
- result = RegOpenKeyAlt(AFSREG_NULL_KEY, MS_SHARED_FILES_KEY, KEY_WRITE, FALSE, &hKey, 0);\r
- if (result != ERROR_SUCCESS)\r
- return;\r
- \r
- if (nRefCount <= 0)\r
- RegDeleteValue(hKey, pszFile);\r
- else\r
- RegSetValueEx(hKey, pszFile, 0, REG_DWORD, (BYTE *)&nRefCount, sizeof(int)); \r
- \r
- RegCloseKey(hKey);\r
-}\r
-\r
-static char *GetTimeStamp()\r
-{\r
- char szTime[64], szDate[64];\r
- static char szTimeDate[128];\r
-\r
- _strtime(szTime);\r
- _strdate(szDate);\r
-\r
- sprintf(szTimeDate, "[%s %s] ", szTime, szDate);\r
- \r
- return szTimeDate;\r
-}\r
-\r
-int SUCALLCONV WriteToInstallErrorLog(char *pszMsg)\r
-{\r
- static BOOL bWritten = FALSE;\r
- FILE *fp;\r
-\r
- // On the first write, recreate the file \r
- fp = fopen(INSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");\r
- if (!fp)\r
- return -1;\r
- \r
- fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);\r
- \r
- fclose(fp);\r
- \r
- bWritten = TRUE;\r
- \r
- return 0;\r
-}\r
-\r
-static void WriteToUninstallErrorLog(char *pszMsg)\r
-{\r
- static BOOL bWritten = FALSE;\r
- FILE *fp;\r
-\r
- // On the first write, recreate the file \r
- fp = fopen(UNINSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");\r
- if (!fp)\r
- return;\r
- \r
- fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);\r
- \r
- fclose(fp);\r
- \r
- bWritten = TRUE;\r
-}\r
-\r
-static char *LoadResString(UINT uID)\r
-{\r
- static char str[256];\r
- GetString (str, uID);\r
- return str;\r
-}\r
-\r
-static void ShowError(UINT nResID, LONG nError)\r
-{\r
- char szErr[256];\r
- char szPrompt[256];\r
- char szMsg[256];\r
- char szTitle[256];\r
- char *psz;\r
-\r
- psz = LoadResString(nResID);\r
- if (psz)\r
- strcpy(szErr, psz);\r
- else\r
- sprintf(szErr, "unknown error msg (Msg ID = %d)", nResID);\r
- \r
- psz = LoadResString(IDS_INSTALLATION_FAILURE);\r
- strcpy(szPrompt, psz ? psz : "An error has occurred: %s (Last Error = %ld).");\r
-\r
- sprintf(szMsg, szPrompt, szErr, nError);\r
-\r
- psz = LoadResString(IDS_TITLE);\r
- strcpy(szTitle, psz ? psz : "AFS");\r
-\r
- if (bSilentMode)\r
- WriteToUninstallErrorLog(szMsg);\r
- else\r
- MessageBox(hDlg, szMsg, szTitle, MB_OK);\r
-}\r
-\r
-static int ShowMsg(UINT nResID, int nType)\r
-{\r
- char szTitle[256];\r
- char *psz;\r
-\r
- psz = LoadResString(IDS_TITLE);\r
- strcpy(szTitle, psz ? psz : "AFS");\r
-\r
- return MessageBox(hDlg, LoadResString(nResID), szTitle, nType);\r
-}\r
-\r
-static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered)\r
-{\r
- HKEY hKey;\r
- LONG nResult;\r
- DWORD dwType;\r
- static char szInstallDir[256];\r
- DWORD dwSize;\r
- char *pszKey;\r
- char *pszValue;\r
-\r
- pszKey = bRemembered ? UNINSTALL_TEMP_INFO_KEY : pApp->regInstallDir.pszKey;\r
- pszValue = bRemembered ? INSTALL_DIR_VALUE_NAME : pApp->regInstallDir.pszValue;\r
-\r
- dwSize = sizeof(szInstallDir);\r
-\r
- nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);\r
- if (nResult == ERROR_SUCCESS) {\r
- nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szInstallDir, &dwSize);\r
- RegCloseKey(hKey);\r
- }\r
-\r
- if (nResult != ERROR_SUCCESS) {\r
- ShowError(IDS_CANT_DETERMINE_APP_PATH, nResult);\r
- return 0;\r
- }\r
-\r
- FilepathNormalizeEx(szInstallDir, FPN_BACK_SLASHES);\r
-\r
- return szInstallDir;\r
-}\r
-\r
-static BOOL DoesRegKeyExist(char *pszKey)\r
-{\r
- HKEY hKey;\r
- LONG nResult;\r
-\r
- nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);\r
- if (nResult == ERROR_SUCCESS) {\r
- RegCloseKey(hKey);\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-static BOOL IsAppInstalled(struct APPINFO *pApp)\r
-{\r
- return DoesRegKeyExist(pApp->pszAppKey);\r
-}\r
-\r
-static void BuildShortPath(char *pszShortPath, UINT nShortPathLen, char *pszInstallDir, char *pszPath)\r
-{\r
- strncpy(pszShortPath, pszInstallDir, nShortPathLen);\r
- strncat(pszShortPath, pszPath, nShortPathLen);\r
- \r
- GetShortPathName(pszShortPath, pszShortPath, nShortPathLen);\r
-}\r
-\r
-static BOOL IsWin95()\r
-{\r
- OSVERSIONINFO versionInformation;\r
-\r
- versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
- \r
- GetVersionEx(&versionInformation);\r
- \r
- if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&\r
- (versionInformation.dwMinorVersion == 0))\r
- return TRUE;\r
- \r
- return FALSE;\r
-}\r
-\r
-int IsWin98()\r
-{\r
- OSVERSIONINFO versionInformation;\r
-\r
- versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);\r
- \r
- GetVersionEx(&versionInformation);\r
- \r
- if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&\r
- (versionInformation.dwMinorVersion == 10))\r
- return 0;\r
- \r
- return -1;\r
-}\r
-\r
-static BOOL IsServiceInstalled(char *pszServiceKey)\r
-{\r
- HKEY hKey;\r
-\r
- if (RegOpenKeyAlt(0, pszServiceKey, KEY_READ, FALSE, &hKey, 0) == ERROR_SUCCESS) {\r
- RegCloseKey(hKey);\r
- return TRUE;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-// If this fails in anyway we just return. No error is displayed.\r
-static void MakeSureServiceDoesNotExist(char *pszName)\r
-{\r
- SC_HANDLE hServer = 0, hSCM = 0;\r
- SERVICE_STATUS status;\r
-\r
- hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);\r
- if (hSCM) {\r
- hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS | DELETE);\r
- if (hServer) {\r
- if (QueryServiceStatus(hServer, &status)) {\r
- if (status.dwCurrentState != SERVICE_STOPPED) {\r
- if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {\r
- CloseServiceHandle(hServer);\r
- CloseServiceHandle(hSCM);\r
- return;\r
- }\r
- }\r
- }\r
- \r
- // Try to delete even if status query fails\r
- DeleteService(hServer);\r
- }\r
- }\r
-\r
- if (hServer)\r
- CloseServiceHandle(hServer);\r
- if (hSCM)\r
- CloseServiceHandle(hSCM);\r
-}\r
-\r
-static int InstallService(char *pszName, char *pszDependOn, char *pszDisplayName, char *pszServicePath, BOOL bInteractive)\r
-{\r
- SC_HANDLE hServer = 0, hSCM;\r
- BOOL bRestoreOldConfig = FALSE;\r
-\r
- hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);\r
- if (!hSCM) {\r
- ShowError(IDS_SCM_OPEN_FAILED, GetLastError());\r
- return -1;\r
- }\r
-\r
-/* This code is not used, but it could be handy in the future so I am keeping it here.\r
-\r
- // If the service exists, then we (most probably) are in the middle of an upgrade or reinstall.\r
- bRestoreOldConfig = IsServiceInstalled(pszName);\r
-\r
- if (bRestoreOldConfig) {\r
- hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS);\r
- if (!hServer || !ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0)) {\r
- ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, GetLastError());\r
- bRestoreOldConfig = FALSE;\r
- // Fall through to service creation below\r
- }\r
- } \r
-*/\r
- \r
- if (!bRestoreOldConfig) {\r
- DWORD dwServiceType;\r
-\r
- // If the service already exists, the create call will fail. This can\r
- // happen if uninstall failed (which is not infrequent). Making sure the\r
- // service does not exist makes it easier for a user to install over top of\r
- // a previously failed uninstall.\r
- MakeSureServiceDoesNotExist(pszName);\r
-\r
- dwServiceType = SERVICE_WIN32_OWN_PROCESS;\r
- if (bInteractive)\r
- dwServiceType |= SERVICE_INTERACTIVE_PROCESS;\r
- \r
- hServer = CreateService(hSCM, pszName, pszDisplayName,\r
- SERVICE_ALL_ACCESS, dwServiceType, SERVICE_AUTO_START, \r
- SERVICE_ERROR_NORMAL, pszServicePath, 0, 0, "RPCSS\0Netbios\0\0", 0, 0);\r
- \r
- if (!hServer)\r
- ShowError(IDS_SERVICE_CREATE_FAILED, GetLastError());\r
- }\r
-\r
- if (hServer)\r
- CloseServiceHandle(hServer);\r
-\r
- CloseServiceHandle(hSCM);\r
-\r
- return 0;\r
-}\r
-\r
-int SUCALLCONV InstallServerService(char *pszServicePath)\r
-{\r
- return InstallService(appServer.pszSvcName, 0, appServer.pszSvcDisplayName, pszServicePath, TRUE);\r
-}\r
-\r
-int SUCALLCONV InstallClientService(char *pszServicePath)\r
-{\r
- return InstallService(appClient.pszSvcName, appClient.pszSvcDependOn, appClient.pszSvcDisplayName, pszServicePath, FALSE);\r
-}\r
-\r
-static int UninstallService(struct APPINFO *pAppInfo)\r
-{\r
- SC_HANDLE hServer, hSCM;\r
- SERVICE_STATUS status;\r
- BOOL bOk;\r
- BOOL bServer = FALSE;\r
- BOOL bShowingProgressDlg = FALSE;\r
-\r
- hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);\r
- if (!hSCM) {\r
- ShowError(IDS_SCM_OPEN_FAILED, GetLastError());\r
- return -1;\r
- }\r
- \r
- hServer = OpenService(hSCM, pAppInfo->pszSvcName, SERVICE_ALL_ACCESS | DELETE);\r
- if (!hServer) {\r
- ShowError(IDS_SERVICE_OPEN_FAILED, GetLastError());\r
- CloseServiceHandle(hSCM);\r
- return -1;\r
- }\r
-\r
- if (!QueryServiceStatus(hServer, &status)) {\r
- ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());\r
- CloseServiceHandle(hServer);\r
- CloseServiceHandle(hSCM);\r
- return -1;\r
- }\r
-\r
- if (status.dwCurrentState != SERVICE_STOPPED) {\r
- if (pAppInfo->nServiceShutdownMsgID) {\r
- if (!bSilentMode && (ShowMsg(pAppInfo->nServiceShutdownMsgID, MB_YESNO | MB_ICONQUESTION) == IDNO)) {\r
- CloseServiceHandle(hServer);\r
- CloseServiceHandle(hSCM);\r
- return 1;\r
- }\r
- }\r
-\r
- if (!bSilentMode)\r
- bShowingProgressDlg = ShowProgressDialog(LoadResString(pAppInfo->nServiceShutdownProgressMsgID));\r
-\r
- if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {\r
- if (bShowingProgressDlg)\r
- HideProgressDialog();\r
- ShowError(IDS_SERVICE_STOP_FAILED, GetLastError());\r
- CloseServiceHandle(hServer);\r
- CloseServiceHandle(hSCM);\r
- return -1;\r
- }\r
- }\r
-\r
- // Wait for the service to stop\r
- while (status.dwCurrentState != SERVICE_STOPPED) {\r
- // I stopped waiting on dwWaitHint because it seemed the wait hint was too long.\r
- // The service would be stopped but we'd still be asleep for a long time yet.\r
- Sleep(5000); //status.dwWaitHint);\r
-\r
- if (!QueryServiceStatus(hServer, &status)) {\r
- if (bShowingProgressDlg)\r
- HideProgressDialog();\r
- ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());\r
- CloseServiceHandle(hServer);\r
- CloseServiceHandle(hSCM);\r
- return -1;\r
- }\r
- }\r
-\r
- // The service has been stopped\r
- if (bShowingProgressDlg)\r
- HideProgressDialog();\r
-\r
- // This code to disable the service may be of use some day so I am keeping it here.\r
- // bOk = ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0); \r
-\r
- bOk = DeleteService(hServer);\r
-\r
- if (!bOk)\r
- ShowError(IDS_SERVICE_DELETE_FAILED, GetLastError());\r
-\r
- CloseServiceHandle(hServer);\r
- CloseServiceHandle(hSCM);\r
-\r
- return (bOk ? 0 : -1);\r
-}\r
-\r
-int SUCALLCONV AddToNetworkProviderOrder(char *pszWhatToAdd)\r
-{\r
- return AddToProviderOrder(pszWhatToAdd) ? 0 : -1;\r
-}\r
-\r
-static int RemoveFromNetworkProviderOrder(char *pszWhatToDel)\r
-{\r
- return RemoveFromProviderOrder(pszWhatToDel) ? 0 : -1;\r
-}\r
-\r
-int SUCALLCONV AddToPath(char *pszPath)\r
-{\r
- return AddToSystemPath(pszPath) ? 0 : -1;\r
-}\r
-\r
-static int RemoveFromPath(char *pszPath)\r
-{\r
- return RemoveFromSystemPath(pszPath) ? 0 : -1;\r
-}\r
-\r
-static void RemoveFiles(char *pszFileSpec)\r
-{\r
- struct _finddata_t fileinfo;\r
- long hSearch;\r
- char szDel[MAX_PATH];\r
- char szDir[MAX_PATH];\r
- char *p;\r
-\r
- strcpy(szDir, pszFileSpec);\r
- p = strrchr(szDir, '\\');\r
- if (p)\r
- *p = 0;\r
- \r
- hSearch = _findfirst(pszFileSpec, &fileinfo);\r
- if (hSearch == -1)\r
- return;\r
-\r
- while (1) {\r
- if ((strcmp(fileinfo.name, ".") != 0) && (strcmp(fileinfo.name, "..") != 0)) {\r
- sprintf(szDel, "%s\\%s", szDir, fileinfo.name);\r
- DeleteFile(szDel);\r
- }\r
-\r
- if (_findnext(hSearch, &fileinfo) == -1)\r
- break;\r
- }\r
-\r
- _findclose(hSearch);\r
-}\r
-\r
-static void RemoveDir(char *pszDir)\r
-{\r
- char szFileSpec[MAX_PATH];\r
-\r
- sprintf(szFileSpec, "%s\\*.*", pszDir);\r
-\r
- RemoveFiles(szFileSpec);\r
- RemoveDirectory(pszDir);\r
-}\r
-\r
-static void RemoveRegValues(struct REGVALUE *pRegValues)\r
-{\r
- struct REGVALUE *pCurValue;\r
- HKEY hKey;\r
- LONG nResult;\r
-\r
- if (!pRegValues)\r
- return;\r
-\r
- for (pCurValue = pRegValues; pCurValue->pszKey; pCurValue++) {\r
- nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pCurValue->pszKey, KEY_ALL_ACCESS, FALSE, &hKey, 0);\r
-\r
- if (nResult == ERROR_SUCCESS) {\r
- nResult = RegDeleteValue(hKey, pCurValue->pszValue);\r
- RegCloseKey(hKey);\r
- }\r
-\r
- if (nResult != ERROR_SUCCESS)\r
- ShowError(IDS_REG_DELETE_VALUE_ERROR, nResult);\r
- }\r
-}\r
-\r
-static BOOL UninstallCredsTool()\r
-{\r
- int nResult = WinExec("afscreds /uninstall", SW_HIDE);\r
-\r
- if (nResult <= 31) {\r
- if (nResult != ERROR_FILE_NOT_FOUND)\r
- ShowError(IDS_CANT_UNINSTALL_AFSCREDS, nResult);\r
- }\r
-\r
- // Always return true. We don't want the uninstall to completely fail just\r
- // because the creds tool didn't uninstall.\r
- return TRUE;\r
-}\r
-\r
-\r
-static char *GetTempDir()\r
-{\r
- DWORD result;\r
- static char szTempDir[MAX_PATH];\r
-\r
- result = GetTempPath(sizeof(szTempDir) - 1, szTempDir);\r
- if (result == 0)\r
- return "\\";\r
- \r
- return szTempDir;\r
-}\r
-\r
-static char *GetRootInstallDir()\r
-{\r
- char *psz;\r
- static char szRootInstallDir[MAX_PATH] = "";\r
-\r
- if (szRootInstallDir[0] == 0) {\r
- strcpy(szRootInstallDir, pszInstallDir);\r
- \r
- // Strip off the app specific part of the install dir\r
- psz = strrchr(szRootInstallDir, '\\');\r
- if (psz)\r
- *psz = 0;\r
- }\r
-\r
- return szRootInstallDir;\r
-}\r
-\r
-static BOOL ClientSpecificUninstall()\r
-{\r
- int nChoice;\r
-\r
- // This function needs to do two things. First it needs to see if the server is\r
- // installed, and if it is, ask the user if they really want to uninstall the\r
- // client given that the server needs the client. Second, if we are uninstalling\r
- // the client, we need to uninstall the creds tool.\r
-\r
- if (!bSilentMode) {\r
- if (IsAppInstalled(&appServer)) {\r
- nChoice = ShowMsg(IDS_CLIENT_NEEDED_BY_SERVER, MB_ICONQUESTION | MB_YESNO);\r
- if (nChoice == IDNO)\r
- return FALSE; // Cancel the uninstall\r
- }\r
- }\r
- \r
- UninstallCredsTool();\r
-\r
- return TRUE;\r
-}\r
-\r
-static struct APPINFO *GetApp()\r
-{\r
-#ifdef SERVER_UNINST\r
- return &appServer;\r
-#elif CLIENT_UNINST\r
- return &appClient;\r
-#elif CC_UNINST\r
- return &appControlCenter;\r
-#elif LIGHT_CLIENT_UNINST\r
- return &appLightClient;\r
-#elif DOCS_UNINST\r
- return &appDocs;\r
-#else\r
- return 0;\r
-#endif;\r
-}\r
-\r
-static void RememberInstallDir(char *pszInstallDir)\r
-{\r
- HKEY hKey;\r
-\r
- // We remember the install dir so that when the UninstUninitialize function is called\r
- // by the InstallShield uninstaller, we can find out where we were installed to. We\r
- // have to do this because by the time that function is called, the registry values\r
- // created at install time are already gone. We need to be able to find out where we\r
- // were installed so we can clean up anything IS couldn't uninstall. If this fails in \r
- // any way then we don't care. The only consequence is that some junk might be left on\r
- // the users' system after an uninstall.\r
- \r
- LONG result = RegOpenKeyAlt(AFSREG_NULL_KEY, UNINSTALL_TEMP_INFO_KEY, KEY_WRITE, TRUE, &hKey, 0);\r
- if (result != ERROR_SUCCESS)\r
- return;\r
-\r
- RegSetValueEx(hKey, INSTALL_DIR_VALUE_NAME, 0, REG_SZ, (PBYTE)pszInstallDir, strlen(pszInstallDir) + 1); \r
-\r
- RegCloseKey(hKey);\r
-}\r
-\r
-int SUCALLCONV SetSilentMode()\r
-{\r
- bSilentMode = TRUE;\r
-\r
- return 0;\r
-}\r
-\r
-static char *GetWinDir()\r
-{\r
- static char szWinDir[MAX_PATH] = "";\r
-\r
- if (!szWinDir[0]) \r
- GetWindowsDirectory(szWinDir, sizeof(szWinDir));\r
- \r
- return szWinDir;\r
-}\r
-\r
-static char *GetWinSysDir()\r
-{\r
- static char szWinSysDir[MAX_PATH] = "";\r
-\r
- if (!szWinSysDir[0])\r
- GetSystemDirectory(szWinSysDir, sizeof(szWinSysDir));\r
- \r
- return szWinSysDir;\r
-} \r
-\r
-static char *GetLocaleID()\r
-{\r
- static char szID[25] = "";\r
-\r
- if (szID[0] == 0) {\r
- LCID dwID = GetSystemDefaultLCID();\r
- \r
- // Nuke the high word. It contains a sort ID.\r
- dwID &= 0x0000FFFF;\r
- \r
- // Convert locale ID to a string\r
- itoa(dwID, szID, 10);\r
-\r
- // This thing should never be more than LOCALE_ID_LEN characters long.\r
- szID[LOCALE_ID_LEN] = 0;\r
- }\r
-\r
- return szID;\r
-}\r
-\r
-static char *ExpandPath(char *pszFile)\r
-{\r
- static char szPath[MAX_PATH];\r
- char *psz;\r
-\r
- szPath[0] = 0;\r
-\r
- // Convert a path containing TARGETDIR, WINDIR, or WINSYSDIR to a \r
- // real path in the file system. One of these MUST be the start of\r
- // the file path passed in. Also convert the string ???? to an\r
- // actual locale number.\r
- if (strncmp(pszFile, TARGETDIR, strlen(TARGETDIR)) == 0)\r
- strcpy(szPath, GetRootInstallDir());\r
- else if (strncmp(pszFile, WINDIR, strlen(WINDIR)) == 0)\r
- strcpy(szPath, GetWinDir());\r
- else if (strncmp(pszFile, WINSYSDIR, strlen(WINSYSDIR)) == 0)\r
- strcpy(szPath, GetWinSysDir());\r
- \r
- if (szPath[0]) { \r
- psz = strchr(pszFile, '\\');\r
- if (psz)\r
- strcat(szPath, psz);\r
- } else\r
- strcpy(szPath, pszFile);\r
-\r
- // Is this a language dll?\r
- psz = strstr(szPath, "????.");\r
- \r
- // If it is, replace ???? with the locale number\r
- if (psz)\r
- strncpy(psz, GetLocaleID(), LOCALE_ID_LEN);\r
-\r
- return szPath;\r
-}\r
-\r
-static BOOL FileNeededByOtherApp(struct APPINFO *pApp, struct FILEINFO *pFileInfo)\r
-{\r
- // If the file is used by the server, the app being uninstalled is not the server, and\r
- // the server is installed, then this file is used by another app.\r
- if (!IsWinNT()) {\r
- if ((pFileInfo->nUsedBy & LCLIENT) && (pApp != &appLightClient) && IsAppInstalled(&appLightClient))\r
- return TRUE;\r
- return FALSE;\r
- }\r
-\r
- if ((pFileInfo->nUsedBy & SERVER) && (pApp != &appServer) && IsAppInstalled(&appServer))\r
- return TRUE;\r
-\r
- if ((pFileInfo->nUsedBy & CLIENT) && (pApp != &appClient) && IsAppInstalled(&appClient))\r
- return TRUE;\r
-\r
- if ((pFileInfo->nUsedBy & CC) && (pApp != &appControlCenter) && IsAppInstalled(&appControlCenter))\r
- return TRUE;\r
- \r
- return FALSE;\r
-}\r
-\r
-static void DeleteInUseFiles(struct APPINFO *pAppInfo, struct FILEINFO *pFileInfo)\r
-{\r
- char szSrcPath[MAX_PATH];\r
- char szDestPath[MAX_PATH];\r
- char szTempDir[MAX_PATH];\r
- int ii;\r
-\r
- // If some app's file has been loaded before the app is uninstalled, then\r
- // when an uninstall is attempted, the application and all of the dlls that\r
- // its uses will be in use and IS will not be able to delete them. Normally this\r
- // is not a problem because IS will tell the user to reboot to finish the uninstall.\r
- // However, we must support the ability to perform a silent uninstall followed\r
- // immediatly by an install of the same product to the same directories. If we let\r
- // IS handle the uninstall of these files, this is not possible. The reason is that\r
- // when IS fails to remove these in use files, it marks them for deletion after the\r
- // next reboot, which is fine. Unfortunately, it leaves them in the dirs they were\r
- // installed to. So if we don't immediately reboot and perform an install to the\r
- // same dirs, once a reboot is performed, those files get deleted and we have a \r
- // broken installation.\r
-\r
- // What we will do to fix all of this, is when the client is uninstalled, but\r
- // before IS does anything, we will move the in use files and associated dlls\r
- // into the temp dir and mark them for delete after a reboot. Then an install\r
- // that follows will succeed.\r
-\r
- // Delete the files that may be in use. If they are we actually move\r
- // them to the temp dir and mark them for deletion after the next reboot.\r
- for (ii = 0; pFileInfo[ii].pszName != 0; ii++) {\r
- // Get the source path\r
- strcpy(szSrcPath, ExpandPath(pFileInfo[ii].pszName));\r
-\r
- // Only delete the file if it is not used by some other app\r
- if (FileNeededByOtherApp(pAppInfo, &pFileInfo[ii]))\r
- continue;\r
-\r
- // If the file doesn't exist then go on to the next file.\r
- if (_access(szSrcPath, 0) != 0)\r
- continue;\r
- \r
- // See if we can do a regular delete of the file\r
- if (DeleteFile(szSrcPath)) {\r
- SetSharedFileRefCount(szSrcPath, 0);\r
- continue;\r
- }\r
-\r
- // Get a temp dir that is on the same drive as the src path.\r
- // We can't move an in use file to a different drive.\r
- strcpy(szTempDir, GetTempDir());\r
- if (szTempDir[0] != szSrcPath[0]) {\r
- // Get the drive, colon, and slash of the src path\r
- strncpy(szTempDir, szSrcPath, 3);\r
- szTempDir[3] = 0;\r
- }\r
- \r
- // Get the dest path - we will rename the file during the move\r
- GetTempFileName(szTempDir, "AFS", 0, szDestPath);\r
-\r
- // Move from source to dest, marking the file for deletion after a reboot\r
- if (IsWin95()) {\r
- if (MoveFile(szSrcPath, szDestPath)) { \r
- WritePrivateProfileString("rename", szSrcPath, szDestPath, "wininit.ini");\r
- SetSharedFileRefCount(szSrcPath, 0);\r
- }\r
- } else { // WinNT or Win98\r
- if (MoveFileEx(szSrcPath, szDestPath, MOVEFILE_REPLACE_EXISTING)) {\r
- SetFileAttributes(szDestPath, FILE_ATTRIBUTE_NORMAL);\r
- MoveFileEx(szDestPath, 0, MOVEFILE_DELAY_UNTIL_REBOOT);\r
- SetSharedFileRefCount(szSrcPath, 0);\r
- }\r
- }\r
- }\r
-}\r
-\r
-// Delete a directory and all its files and subdirectories - Yee haaa!\r
-static void RemoveDirectoryTree(char *pszDir)\r
-{\r
- HANDLE hFind;\r
- WIN32_FIND_DATA findFileData;\r
- char szSpec[MAX_PATH];\r
- char szSubFileOrDir[MAX_PATH];\r
- BOOL bContinue;\r
-\r
- sprintf(szSpec, "%s\\*.*", pszDir);\r
- \r
- // First delete the contents of the dir\r
- hFind = FindFirstFile(szSpec, &findFileData);\r
- bContinue = (hFind != INVALID_HANDLE_VALUE);\r
- \r
- while (bContinue) {\r
- if ((strcmp(findFileData.cFileName, ".") != 0) && (strcmp(findFileData.cFileName, "..") != 0)) {\r
- sprintf(szSubFileOrDir, "%s\\%s", pszDir, findFileData.cFileName);\r
- \r
- if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)\r
- RemoveDirectoryTree(szSubFileOrDir);\r
- else\r
- DeleteFile(szSubFileOrDir);\r
- }\r
-\r
- bContinue = FindNextFile(hFind, &findFileData);\r
- }\r
-\r
- FindClose(hFind);\r
- \r
- // Now remove the dir\r
- RemoveDirectory(pszDir);\r
-} \r
-\r
-static char *GetStartMenuRoot()\r
-{\r
- HKEY hKey;\r
- LONG nResult;\r
- DWORD dwType;\r
- DWORD dwSize;\r
- char *pszKey;\r
- char *pszValue;\r
-\r
- static char szStartMenuRoot[MAX_PATH] = "";\r
-\r
- if (szStartMenuRoot[0] == 0) {\r
- dwSize = sizeof(szStartMenuRoot);\r
- \r
- if (IsWinNT()) {\r
- pszKey = WINNT_START_MENU_REG_KEY;\r
- pszValue = WINNT_START_MENU_REG_VALUE;\r
- } else {\r
- pszKey = WIN9X_START_MENU_REG_KEY;\r
- pszValue = WIN9X_START_MENU_REG_VALUE;\r
- }\r
- \r
- nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);\r
- if (nResult == ERROR_SUCCESS) {\r
- nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szStartMenuRoot, &dwSize);\r
- RegCloseKey(hKey);\r
- }\r
-\r
- if (nResult != ERROR_SUCCESS)\r
- return 0;\r
- }\r
-\r
- FilepathNormalizeEx(szStartMenuRoot, FPN_BACK_SLASHES);\r
-\r
- return szStartMenuRoot;\r
-}\r
-\r
-static char *GetAfsStartMenuRoot()\r
-{\r
- static char szAfsStartMenuRoot[MAX_PATH] = "";\r
- char *pszStartMenuRoot;\r
- \r
- if (szAfsStartMenuRoot[0] == 0) { \r
- pszStartMenuRoot = GetStartMenuRoot();\r
- if (!pszStartMenuRoot)\r
- return 0;\r
-\r
- if (bSilentMode)\r
- sprintf(szAfsStartMenuRoot, "%s\\IBM WebSphere\\Performance Pack\\AFS", pszStartMenuRoot );\r
- else\r
- sprintf(szAfsStartMenuRoot, "%s\\IBM AFS", pszStartMenuRoot );\r
- }\r
-\r
- return szAfsStartMenuRoot;\r
-}\r
-\r
-static BOOL IsADir(char *pszName)\r
-{\r
- struct _stat statbuf;\r
-\r
- if (_stat(pszName, &statbuf) < 0)\r
- return FALSE;\r
-\r
- return statbuf.st_mode & _S_IFDIR;\r
-}\r
-\r
-static void DeleteStartMenuEntries(char *pszEntries)\r
-{\r
- char szStartMenuPath[MAX_PATH];\r
- char *pszAfsStartMenuRoot;\r
- char *pszCurEntry;\r
-\r
- pszAfsStartMenuRoot = GetAfsStartMenuRoot();\r
-\r
- if (!pszAfsStartMenuRoot)\r
- return;\r
- \r
- for (pszCurEntry = pszEntries; *pszCurEntry; pszCurEntry += strlen(pszCurEntry) + 1) {\r
- sprintf(szStartMenuPath, "%s\\%s", pszAfsStartMenuRoot, pszCurEntry);\r
- if (IsADir(szStartMenuPath))\r
- RemoveDirectoryTree(szStartMenuPath);\r
- else\r
- DeleteFile(szStartMenuPath);\r
- }\r
-}\r
-\r
-static void RefreshStartMenu()\r
-{\r
- char *pszAfsStartMenuRoot;\r
- char szTemp[MAX_PATH];\r
- \r
- pszAfsStartMenuRoot = GetAfsStartMenuRoot();\r
- if (!pszAfsStartMenuRoot)\r
- return;\r
-\r
- sprintf(szTemp, "%s - Refresh Attempt", pszAfsStartMenuRoot);\r
- \r
- // Deleting items from below the root level of the start menu does not \r
- // cause it to refresh. In order that users can see changes without\r
- // rebooting we will temporarily rename our root most entry, which \r
- // does cause a refresh of the start menu.\r
- MoveFileEx(pszAfsStartMenuRoot, szTemp, MOVEFILE_REPLACE_EXISTING);\r
- MoveFileEx(szTemp, pszAfsStartMenuRoot, MOVEFILE_REPLACE_EXISTING);\r
-}\r
-\r
-static BOOL PreserveConfigInfo(struct APPINFO *pApp)\r
-{\r
- char *pszRegKey;\r
- char szDestKey[256];\r
- LONG result;\r
-\r
- bPreserveConfigInfo = TRUE;\r
-\r
- // If not in silent mode, ask user if they want to preserve the cfg info\r
- if (!bSilentMode) {\r
- int nChoice = ShowMsg(pApp->nPreserveConfigInfoMsgID, MB_ICONQUESTION | MB_YESNOCANCEL);\r
- if (nChoice == IDCANCEL)\r
- return FALSE; // Cancel the uninstall\r
- else if (nChoice == IDNO) { \r
- bPreserveConfigInfo = FALSE; // User doesn't want to preserve the config info\r
- return TRUE;\r
- }\r
- }\r
-\r
- // Copy each reg key (and all of its subkeys and values) to another place in the registry.\r
- for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {\r
- if (!DoesRegKeyExist(pszRegKey))\r
- continue;\r
-\r
- // Create the destination path for the copy\r
- sprintf(szDestKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);\r
-\r
- // Try to copy it\r
- result = RegDupKeyAlt(pszRegKey, szDestKey);\r
-\r
- if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND)) {\r
- // If the copy failed, then delete any copies that succeeded\r
- sprintf(szDestKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);\r
- RegDeleteEntryAlt(szDestKey, REGENTRY_KEY);\r
- goto done;\r
- }\r
- }\r
-\r
- // Remember the integrated login setting if this app supports that and it was turned on\r
- if (pApp->pszNetworkProviderOrder) {\r
- // Was integerated login turned on?\r
- BOOL bOn, bOk;\r
- bOk = InNetworkProviderOrder(pApp->pszNetworkProviderOrder, &bOn);\r
- if (bOk && bOn) {\r
- HKEY hKey;\r
- sprintf(szDestKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);\r
- result = RegOpenKeyAlt(AFSREG_NULL_KEY, szDestKey, KEY_WRITE, TRUE, &hKey, 0);\r
- // The existance of the key is a flag indicating that integrated login was turned on\r
- RegCloseKey(hKey);\r
- }\r
- }\r
- \r
-done:\r
- if ((result == ERROR_SUCCESS) || bSilentMode)\r
- return TRUE; // Continue with uninstall\r
-\r
- // Report the error and ask the user if they want to continue the uninstall\r
- return (ShowMsg(IDS_SAVE_OF_CONFIG_INFO_FAILED, MB_ICONEXCLAMATION | MB_YESNO) == IDYES); \r
-}\r
-\r
-int SUCALLCONV RestoreConfigInfo(int nApp)\r
-{\r
- char *pszRegKey;\r
- char szSrcKey[256];\r
- struct APPINFO *pApp = 0;\r
- BOOL bError = FALSE;\r
- LONG result;\r
-\r
- switch (nApp) {\r
- case SERVER: pApp = &appServer; break;\r
- case CLIENT: pApp = &appClient; break;\r
- case LCLIENT: pApp = &appLightClient; break;\r
- case CC: pApp = &appControlCenter; break;\r
- }\r
- \r
- if (!pApp)\r
- return -1;\r
- \r
- // Copy each reg key (and all of its subkeys and values) back to its original place in the registry.\r
- for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {\r
- // Create the source path for the copy\r
- sprintf(szSrcKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);\r
-\r
- if (!DoesRegKeyExist(szSrcKey))\r
- continue;\r
-\r
- // Try to restore as many of the keys as possible. Report any errors at the end.\r
-\r
- // Try to copy it\r
- result = RegDupKeyAlt(szSrcKey, pszRegKey);\r
- if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND))\r
- bError = TRUE;\r
- }\r
-\r
- // Restore integrated login if this app was using it\r
- if (pApp->pszNetworkProviderOrder) {\r
- // Check if integrated login was turned on. The IntegratedLogin key is a flag\r
- // telling us that it was on. If the key does not exist, integrated login was\r
- // not on.\r
- sprintf(szSrcKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);\r
- if (DoesRegKeyExist(szSrcKey)) {\r
- if (!AddToProviderOrder(pApp->pszNetworkProviderOrder))\r
- bError = TRUE;\r
- }\r
- }\r
-\r
- // Remove our saved copies of the config info\r
- sprintf(szSrcKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);\r
- RegDeleteEntryAlt(szSrcKey, REGENTRY_KEY);\r
- \r
- if (bError)\r
- ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, 0);\r
-\r
- return TRUE;\r
-}\r
-\r
-static BOOL DoSubKeysExist(char *pszKey)\r
-{\r
- LONG result;\r
- HKEY hKey;\r
- char *pszSubKeys = 0;\r
- BOOL bExist;\r
- \r
- result = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);\r
- if (result != ERROR_SUCCESS)\r
- return FALSE;\r
- \r
- result = RegEnumKeyAlt(hKey, &pszSubKeys);\r
- RegCloseKey(hKey);\r
- \r
- if (result != ERROR_SUCCESS)\r
- return FALSE;\r
- \r
- if (pszSubKeys) {\r
- bExist = TRUE;\r
- free(pszSubKeys);\r
- } else\r
- bExist = FALSE; \r
-\r
- return bExist;\r
-}\r
-\r
-/*\r
- * The following definitions are taken from richedit.h:\r
- *\r
- */\r
-\r
-#define EM_SETBKGNDCOLOR (WM_USER + 67) // from Richedit.h\r
-#define EM_STREAMIN (WM_USER + 73) // from Richedit.h\r
-#define SF_RTF 0x0002\r
-\r
-typedef DWORD (CALLBACK *EDITSTREAMCALLBACK)(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);\r
-\r
-typedef struct _editstream {\r
- DWORD dwCookie; /* user value passed to callback as first parameter */\r
- DWORD dwError; /* last error */\r
- EDITSTREAMCALLBACK pfnCallback;\r
-} EDITSTREAM;\r
-\r
-/*\r
- *\r
- */\r
-\r
-DWORD CALLBACK License_StreamText (DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)\r
-{\r
- LPTSTR psz = (LPTSTR)dwCookie;\r
- LONG cchAvail = lstrlen(psz);\r
- if ((*pcb = min(cchAvail, cb)) != 0) {\r
- memcpy (pbBuff, psz, *pcb);\r
- memmove (psz, &psz[*pcb], cchAvail - *pcb + 1);\r
- }\r
- return 0;\r
-}\r
-\r
-\r
-void License_OnInitDialog (HWND hDlg, LPTSTR pszFile)\r
-{\r
- // Open the license file and shove its text in our RichEdit control\r
- //\r
- HANDLE hFile;\r
- if ((hFile = CreateFile (pszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) {\r
-\r
- size_t cbText;\r
- if ((cbText = GetFileSize (hFile, NULL)) != 0) {\r
-\r
- LPTSTR abText = (LPTSTR)GlobalAlloc (GMEM_FIXED, cbText + 3);\r
-\r
- DWORD cbRead;\r
- if (ReadFile (hFile, abText, cbText, &cbRead, NULL)) {\r
- abText[ cbRead ] = 0;\r
-\r
- EDITSTREAM Stream;\r
- memset (&Stream, 0x00, sizeof(Stream));\r
- Stream.dwCookie = (DWORD)abText;\r
- Stream.pfnCallback = License_StreamText;\r
-\r
- SendDlgItemMessage (hDlg, IDC_TEXT, EM_STREAMIN, SF_RTF, (LPARAM)&Stream);\r
- }\r
-\r
- GlobalFree (abText);\r
- }\r
-\r
- CloseHandle (hFile);\r
- }\r
-\r
- // Make the control's background be gray\r
- //\r
- SendDlgItemMessage (hDlg, IDC_TEXT, EM_SETBKGNDCOLOR, FALSE, (LPARAM)GetSysColor(COLOR_BTNFACE));\r
-}\r
-\r
-BOOL CALLBACK License_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)\r
-{\r
- switch (msg) {\r
- case WM_INITDIALOG:\r
- SetWindowLong (hDlg, DWL_USER, lp);\r
- License_OnInitDialog (hDlg, (LPTSTR)lp);\r
- break;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wp)) {\r
- case IDCANCEL:\r
- case IDOK:\r
- EndDialog (hDlg, LOWORD(wp));\r
- break;\r
-\r
- case IDC_PRINT:\r
- TCHAR szDir[ MAX_PATH ];\r
- GetCurrentDirectory (MAX_PATH, szDir);\r
- ShellExecute (hDlg, TEXT("print"), (LPTSTR)GetWindowLong (hDlg, DWL_USER), NULL, szDir, SW_HIDE);\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-BOOL FindAfsInstallationPathByComponent (LPTSTR pszInstallationPath, LPTSTR pszComponent)\r
-{\r
- *pszInstallationPath = 0;\r
-\r
- TCHAR szRegPath[ MAX_PATH ];\r
- wsprintf (szRegPath, TEXT("Software\\TransarcCorporation\\%s\\CurrentVersion"), pszComponent);\r
-\r
- HKEY hk;\r
- if (RegOpenKey (HKEY_LOCAL_MACHINE, szRegPath, &hk) == 0) {\r
- DWORD dwType = REG_SZ;\r
- DWORD dwSize = MAX_PATH;\r
-\r
- if (RegQueryValueEx (hk, TEXT("PathName"), NULL, &dwType, (PBYTE)pszInstallationPath, &dwSize) == 0) {\r
- *(LPTSTR)FindBaseFileName (pszInstallationPath) = TEXT('\0');\r
-\r
- if (pszInstallationPath[0] && (pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] == TEXT('\\')))\r
- pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] = TEXT('\0');\r
- }\r
-\r
- RegCloseKey (hk);\r
- }\r
-\r
- return !!*pszInstallationPath;\r
-}\r
-\r
-BOOL FindAfsInstallationPath (LPTSTR pszInstallationPath)\r
-{\r
- if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Client")))\r
- return TRUE;\r
- if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Control Center")))\r
- return TRUE;\r
- if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Server")))\r
- return TRUE;\r
- if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Supplemental Documentation")))\r
- return TRUE;\r
- return FALSE;\r
-}\r
-\r
-HINSTANCE LoadRichTextControl (void)\r
-{\r
- HINSTANCE hInst;\r
- if ((hInst = LoadLibrary ("riched20.dll")) != NULL)\r
- return hInst;\r
- if ((hInst = LoadLibrary ("riched32.dll")) != NULL)\r
- return hInst;\r
- if ((hInst = LoadLibrary ("riched.dll")) != NULL)\r
- return hInst;\r
- if ((hInst = LoadLibrary ("richedit.dll")) != NULL)\r
- return hInst;\r
- return NULL;\r
-}\r
-\r
-int SUCALLCONV ShowLicense (char *pszTarget, char *pszSource)\r
-{\r
- // If the license already lives on this user's machine, don't show\r
- // it again. This only has to be done if the user has never\r
- // accepted the license agreement before (it's part of the setup\r
- // program, so it gets installed if they've accepted it).\r
- //\r
- // We were handed a relative path of the form:\r
- // Documentation/html/license.rtf\r
- //\r
- // We'll need to find the AFS installation directory, in order to\r
- // find that Documentation subtree.\r
- //\r
- BOOL fShowLicense = TRUE;\r
-\r
- TCHAR szInstallationPath[ MAX_PATH ];\r
- if (FindAfsInstallationPath (szInstallationPath)) {\r
- TCHAR szLicensePath[ MAX_PATH ];\r
- wsprintf (szLicensePath, TEXT("%s\\%s"), szInstallationPath, pszTarget);\r
-\r
- if (GetFileAttributes (szLicensePath) != (DWORD)-1) {\r
- fShowLicense = FALSE;\r
- }\r
- }\r
-\r
- // Before we can show the license file, we have to prepare the RichEdit\r
- // control. That means loading the appropriate library and calling its\r
- // initialization functions.\r
- //\r
- HINSTANCE hRichEdit;\r
- if ((hRichEdit = LoadRichTextControl()) != NULL) {\r
-\r
- // If we must show the license, do so now. This is a modal dialog,\r
- // so we'll know whether or not the user accepts the license.\r
- //\r
- if (ModalDialogParam (IDD_LICENSE, GetActiveWindow(), License_DlgProc, (LPARAM)pszSource) == IDCANCEL) {\r
- // The user rejected the license; fail setup\r
- return FALSE;\r
- }\r
-\r
- FreeLibrary (hRichEdit);\r
- }\r
-\r
- // The user accepted the license, so we can continue with Setup.\r
- // The license file is installed as part of Setup.\r
- return TRUE;\r
-}\r
-\r
-int SUCALLCONV UninstInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)\r
-{\r
- char szPath[MAX_PATH];\r
- struct APPINFO *pAppInfo;\r
- char *pszFile = 0;\r
- char *pszSubDir = 0;\r
-\r
- hDlg = hIS;\r
-\r
- bSilentMode = !IsWindowVisible(hIS);\r
-\r
- // Which app are we uninstalling?\r
- pAppInfo = GetApp();\r
- if (!pAppInfo) {\r
- ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);\r
- return -1;\r
- }\r
-\r
- // Get the app's install dir\r
- pszInstallDir = GetAppInstallDir(pAppInfo, FALSE);\r
- if (!pszInstallDir)\r
- return -1;\r
-\r
- // If this app has a custom uninstall func, call it here\r
- if (pAppInfo->pUninstallFunc)\r
- if (!pAppInfo->pUninstallFunc())\r
- return -1;\r
-\r
- if (pAppInfo->pszRegKeysToPreserve)\r
- if (!PreserveConfigInfo(pAppInfo))\r
- return -1;\r
-\r
- // Unconfigure the service, if there is one for this app\r
- if (pAppInfo->pszSvcKey) {\r
- if (IsServiceInstalled(pAppInfo->pszSvcKey))\r
- if (UninstallService(pAppInfo) == 1)\r
- return -1;\r
- }\r
-\r
- RememberInstallDir(pszInstallDir);\r
-\r
- DeleteInUseFiles(pAppInfo, fileInfo);\r
-\r
- // Remove the app's bin path from the system path\r
- if (pAppInfo->pszBinPath) {\r
- BuildShortPath(szPath, sizeof(szPath), pszInstallDir, pAppInfo->pszBinPath);\r
- RemoveFromPath(szPath);\r
- }\r
-\r
- // Remove entry from NetworkProvider\Order key in registry\r
- if (pAppInfo->pszNetworkProviderOrder)\r
- RemoveFromNetworkProviderOrder(pAppInfo->pszNetworkProviderOrder);\r
-\r
- // Remove any generated subdirectories\r
- if (!bPreserveConfigInfo && pAppInfo->pszDirsToDel) {\r
- for (pszSubDir = pAppInfo->pszDirsToDel; *pszSubDir; pszSubDir += strlen(pszSubDir) + 1)\r
- RemoveDir(ExpandPath(pszSubDir));\r
- }\r
-\r
- // Remove any generated files\r
- if (!bPreserveConfigInfo && pAppInfo->pszFilesToDel) {\r
- for (pszFile = pAppInfo->pszFilesToDel; *pszFile; pszFile += strlen(pszFile) + 1)\r
- RemoveFiles(ExpandPath(pszFile));\r
- }\r
-\r
- // Remove any registry values that IS can't handle\r
- RemoveRegValues(pAppInfo->pRegValues);\r
- if (IsWinNT())\r
- RemoveRegValues(pAppInfo->pWinNTRegValues);\r
- else \r
- RemoveRegValues(pAppInfo->pWin9XRegValues);\r
-\r
- // Remove the start menu entries for this app\r
- if (pAppInfo->pszStartMenuEntries) {\r
- DeleteStartMenuEntries(pAppInfo->pszStartMenuEntries);\r
- RefreshStartMenu();\r
- }\r
-\r
- // Remove the install dir\r
- RemoveDirectory(pszInstallDir);\r
-\r
- return 0;\r
-}\r
-\r
-void SUCALLCONV UninstUnInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)\r
-{\r
- char *pszInstallDir;\r
- char szDirPath[MAX_PATH];\r
- char *psz;\r
- struct APPINFO *pAppInfo;\r
-\r
- // If we just uninstalled the last AFS app, then do some cleanup.\r
- if (IsAppInstalled(&appServer) || IsAppInstalled(&appClient) ||\r
- IsAppInstalled(&appControlCenter) || IsAppInstalled(&appLightClient) ||\r
- IsAppInstalled(&appDocs))\r
- {\r
- return;\r
- }\r
-\r
- bSilentMode = !IsWindowVisible(hIS);\r
- \r
- // Which app did we just uninstall?\r
- pAppInfo = GetApp();\r
- if (!pAppInfo) {\r
- ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);\r
- return;\r
- }\r
-\r
- // Get the app's install dir\r
- pszInstallDir = GetAppInstallDir(pAppInfo, TRUE);\r
- if (!pszInstallDir)\r
- return;\r
-\r
- // Remove the reg key we used to remember the app install dir\r
- RegDeleteEntryAlt(UNINSTALL_TEMP_INFO_KEY, REGENTRY_KEY);\r
-\r
- // Try to remove the reg key used to store config info, but only\r
- // if there are no app config info sub keys present.\r
- if (!DoSubKeysExist(AFS_PRESERVED_CFG_INFO_KEY))\r
- RegDeleteEntryAlt(AFS_PRESERVED_CFG_INFO_KEY, REGENTRY_KEY);\r
-\r
- // Remove the install dir\r
- RemoveDirectory(pszInstallDir);\r
-\r
- // Attempt to remove the install root and common directories. The are \r
- // shared and so no single app knows to delete them.\r
-\r
- // Strip off the app specific part of the install dir\r
- psz = strrchr(pszInstallDir, '\\');\r
- if (psz)\r
- *psz = 0;\r
-\r
- sprintf(szDirPath, "%s\\%s", pszInstallDir, "Common");\r
- RemoveDirectory(szDirPath);\r
-\r
- // Remove the Common directory from the system path\r
- RemoveFromPath(szDirPath);\r
-\r
- // Remove all of the documentation dirs\r
- sprintf(szDirPath, "%s\\%s", pszInstallDir, "Documentation");\r
- RemoveDirectoryTree(szDirPath);\r
-\r
- // Ok, up to this point we have been removing files we know we\r
- // created. However, after this point we are into the path\r
- // that the user chose for our install root. The default for\r
- // this is IBM/Afs, but they could have chosen anything,\r
- // including a dir or dirs that have other products in them.\r
- // We will check to see if it is IBM\AFS and if it is then we \r
- // will attempt to remove them.\r
- \r
- // Back up a level and look for AFS\r
- psz = strrchr(pszInstallDir, '\\');\r
- if (psz) {\r
- if (stricmp(psz + 1, "AFS") == 0) {\r
- RemoveDirectory(pszInstallDir);\r
- *psz = 0;\r
- }\r
- }\r
-\r
- // Back up a level and look for IBM\r
- psz = strrchr(pszInstallDir, '\\');\r
- if (psz) {\r
- if (stricmp(psz + 1, "IBM") == 0) {\r
- RemoveDirectory(pszInstallDir);\r
- *psz = 0;\r
- }\r
- }\r
-\r
- // Remove the root afs start menu entry\r
- psz = GetStartMenuRoot();\r
- if (psz) {\r
- if (bSilentMode) {\r
- // Remove everything under our branch\r
- sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack\\AFS", psz);\r
- RemoveDirectoryTree(szDirPath);\r
- \r
- // Remove the IBM stuff only if the dirs are empty\r
- sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack", psz);\r
- if (RemoveDirectory(szDirPath)) {\r
- sprintf(szDirPath, "%s\\IBM WebSphere", psz);\r
- RemoveDirectory(szDirPath);\r
- }\r
- } else {\r
- sprintf(szDirPath, "%s\\IBM AFS", psz);\r
- RemoveDirectoryTree(szDirPath);\r
- }\r
- }\r
-}\r
-\r
-BOOLEAN _stdcall DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)\r
-{\r
- if (reason == DLL_PROCESS_ATTACH) {\r
- hinst = (HINSTANCE)dll;\r
- TaLocale_LoadCorrespondingModuleByName (hinst, "afs_setup_utils.dll");\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-extern "C" int WINAPI Test (HINSTANCE hInst, HINSTANCE hPrev, LPSTR psz, int nCmdShow)\r
-{\r
- ShowLicense ("TEST", "\\\\fury\\afssetup\\license\\ja_JP.rtf");\r
- return 0;\r
-}\r
-\r
-\r
+ * INCLUDES _________________________________________________________________
+ *
+ */
+
+extern "C" {
+#include <afs/param.h>
+#include <afs/stds.h>
+#include <afs/fileutil.h>
+}
+
+#include <windows.h>
+#include <stdio.h>
+#include <time.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <io.h>
+#include <string.h>
+#include <SYS\STAT.H>
+#include <shellapi.h>
+
+#include <WINNT/afsreg.h>
+#include <WINNT/afssw.h>
+#include <WINNT/talocale.h>
+
+#include "resource.h"
+#include "progress_dlg.h"
+#include "sutil.h"
+#include "forceremove.h"
+
+
+/*
+ * PROTOTYPES _________________________________________________________________
+ *
+ */
+static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered);
+BOOL UninstallCredsTool();
+BOOL ServerSpecificUninstall();
+BOOL ClientSpecificUninstall();
+
+
+
+/*
+ * DEFINITIONS _________________________________________________________________
+ *
+ */
+#define SUCALLCONV WINAPI
+
+#define UNINSTALL_TEMP_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsUninstallTempInfo"
+#define INSTALL_DIR_VALUE_NAME "InstallDir"
+
+#define AFS_PRESERVED_CFG_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsPreservedConfigInfo"
+
+#define MS_SHARED_FILES_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs"
+
+// Log file to use when running in silent mode
+#define UNINSTALL_ERROR_LOG_NAME "\\AfsUninstallErrorLog.txt"
+#define INSTALL_ERROR_LOG_NAME "\\AfsInstallErrorLog.txt"
+
+#define TARGETDIR "<TARGETDIR>"
+#define WINDIR "<WINDIR>"
+#define WINSYSDIR "<WINSYSDIR>"
+
+#define WIN9X_START_MENU_REG_KEY "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+#define WIN9X_START_MENU_REG_VALUE "Programs"
+
+#define WINNT_START_MENU_REG_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+#define WINNT_START_MENU_REG_VALUE "Common Programs"
+
+#define LOCALE_ID_LEN 4
+
+struct REGVALUE {
+ char *pszKey;
+ char *pszValue;
+};
+
+
+typedef BOOL (APP_UNINSTALL_FUNC)();
+
+
+
+struct APPINFO {
+ char *pszAppName;
+
+ // Service Info
+ char *pszSvcName;
+ char *pszSvcKey;
+ char *pszSvcDependOn;
+ char *pszSvcDisplayName;
+
+ char *pszNetworkProviderOrder;
+
+ // Message to use to tell the user that we have to stop the service
+ int nServiceShutdownMsgID;
+
+ // Message to use for the progress dialog that is shown while
+ // waiting for the service to stop.
+ int nServiceShutdownProgressMsgID;
+
+ // Location in registry of a key we can use to know that the app is installed
+ char *pszAppKey;
+
+ // Location in registry of this app's install dir
+ struct REGVALUE regInstallDir;
+
+ // Path Info
+ char *pszLocalRoot; // The root dir below the install dir
+ char *pszBinPath; // Path to remove from the system path
+
+ // Generated files and directories to delete. These are both multistring lists.
+ char *pszDirsToDel; // All files in these dirs will be deleted
+ char *pszFilesToDel; // Use this if you want to delete files but leave the dir. Wildcards can be used.
+
+ // Registry values to remove
+ struct REGVALUE *pRegValues;
+ struct REGVALUE *pWinNTRegValues; // Only remove these if running WinNT
+ struct REGVALUE *pWin9XRegValues; // Only remove these if running Win9X
+
+ // Start menu entries to delete
+ char *pszStartMenuEntries;
+
+ // Registry keys to save if a user wants to preserve config info during uninstall
+ char *pszRegKeysToPreserve;
+ int nPreserveConfigInfoMsgID;
+
+ // Uninstall func - used for things specific to this app
+ APP_UNINSTALL_FUNC *pUninstallFunc;
+};
+
+
+/*
+ * App info structure for the Server product
+ */
+struct APPINFO appServer = {
+ "AFS Server",
+
+ AFSREG_SVR_SVC_NAME,
+ AFSREG_SVR_SVC_KEY,
+ 0, // No depend on
+ AFSREG_SVR_SVC_DISPLAYNAME_DATA,
+
+ 0, // No network provider order
+
+ IDS_MUST_STOP_SERVER,
+ IDS_WAITING_FOR_SERVER_TO_STOP,
+
+ AFSREG_SVR_SW_VERSION_KEY,
+
+ { AFSREG_SVR_SW_VERSION_KEY, AFSREG_SVR_SW_VERSION_DIR_VALUE },
+
+ "\\Server",
+ "\\usr\\afs\\bin",
+
+ // Dirs to delete
+ TARGETDIR"\\Server\\usr\\afs\\bin\\backup\0"
+ TARGETDIR"\\Server\\usr\\afs\\bin\0"
+ TARGETDIR"\\Server\\usr\\afs\\db\0"
+ TARGETDIR"\\Server\\usr\\afs\\logs\0"
+ TARGETDIR"\\Server\\usr\\afs\\etc\0"
+ TARGETDIR"\\Server\\usr\\afs\\local\0"
+ TARGETDIR"\\Server\\usr\\afs\0"
+ TARGETDIR"\\Server\\usr\0",
+
+ // Files to delete
+ TARGETDIR"\\Common\\*.gid\0"
+ TARGETDIR"\\Common\\*.fts\0",
+
+ 0, // No reg values
+ 0, // No NT only reg values
+ 0, // No 9x only reg values
+
+ "Server\0",
+
+ // Config info to preserve
+ AFSREG_SVR_SVC_KEY"\0",
+ IDS_PRESERVE_SERVER_CONFIG_INFO,
+
+ 0 // No special uninstall function
+};
+
+// Registry values to remove for the Client
+struct REGVALUE clientRegValues[] = {
+ { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", "{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}" },
+ { 0, 0 } // This indicates there are no more entries
+};
+
+struct REGVALUE clientWinNTRegValues[] = {
+ { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\File Manager\\AddOns", "AFS Client FME" },
+ { "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\NetBT\\Paramet
+ers", "SMBDeviceEnabled" },
+ { 0, 0 }
+};
+
+struct REGVALUE clientWin9XRegValues[] = {
+ { "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", "TransarcAFSDaemon" },
+ { 0, 0 }
+};
+
+/*
+ * App info structure for the Client product
+ */
+struct APPINFO appClient = {
+ "AFS Client",
+
+ AFSREG_CLT_SVC_NAME,
+ AFSREG_CLT_SVC_KEY,
+ "5250435353004E657462696F730000",
+ AFSREG_CLT_SVC_DISPLAYNAME_DATA,
+
+ AFSREG_CLT_SVC_NAME,
+
+ IDS_MUST_STOP_CLIENT,
+ IDS_WAITING_FOR_CLIENT_TO_STOP,
+
+ AFSREG_CLT_SW_VERSION_KEY,
+
+ { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },
+
+ "\\Client",
+ "\\Program",
+
+ // No dirs to delete
+ 0,
+
+ // Files to delete
+ TARGETDIR"\\Common\\*.gid\0"
+ TARGETDIR"\\Common\\*.fts\0"
+ WINDIR"\\..\\AFSCache\0"
+ WINDIR"\\afsd.log\0"
+ WINDIR"\\afsd.ini\0"
+ WINDIR"\\afsdsbmt.ini\0"
+ WINDIR"\\afsdcell.ini\0"
+ WINDIR"\\afsd_init.log\0",
+
+ clientRegValues,
+ clientWinNTRegValues,
+ clientWin9XRegValues,
+
+ // Start menu entries to remove
+ "Client\0",
+
+ // Config info to preserve
+ AFSREG_CLT_SVC_KEY"\0",
+ IDS_PRESERVE_CLIENT_CONFIG_INFO,
+
+ ClientSpecificUninstall
+};
+
+
+/*
+ * App info structure for the Light Client product
+ */
+struct APPINFO appLightClient = {
+ "AFS Light",
+
+ // No service info
+ 0,
+ 0,
+ 0,
+ 0,
+
+ AFSREG_CLT_SVC_NAME,
+
+ // No service shutdown messages
+ 0,
+ 0,
+
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Light Client",
+
+ { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },
+
+ "\\Client",
+ "\\Program",
+
+ // No dirs to delete
+ 0,
+
+ // Files to delete
+ TARGETDIR"\\Common\\*.gid\0"
+ TARGETDIR"\\Common\\*.fts\0",
+
+ clientRegValues,
+ clientWinNTRegValues,
+ clientWin9XRegValues,
+
+ // Start menu entries to remove
+ "Light\0",
+
+ // Config info to preserve
+ AFSREG_CLT_SVC_KEY"\0",
+ IDS_PRESERVE_LIGHT_CLIENT_CONFIG_INFO,
+
+ UninstallCredsTool
+};
+
+
+/*
+ * App info structure for the Control Center product
+ */
+struct APPINFO appControlCenter = {
+ "AFS Control Center",
+
+ // No service info
+ 0,
+ 0,
+ 0,
+ 0,
+
+ // No network provider order
+ 0,
+
+ // No service shutdown messages
+ 0,
+ 0,
+
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center",
+
+ { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center\\CurrentVersion", "PathName" },
+
+ "\\Control Center",
+ "",
+
+ // No dirs to delete
+ 0,
+
+ // Files to delete
+ TARGETDIR"\\Common\\*.gid\0"
+ TARGETDIR"\\Common\\*.fts\0",
+
+ 0, // No reg values
+ 0, // No NT only reg values
+ 0, // No 9x only reg values
+
+ // Start menu entries to remove
+ "Control Center\0",
+
+ // Config info to preserve
+ AFSREG_CLT_SVC_KEY"\0",
+ IDS_PRESERVE_CC_CONFIG_INFO,
+
+ 0 // No uninstall function
+};
+
+
+/*
+ * App info structure for the Sys Admin Doc files
+ */
+struct APPINFO appDocs = {
+ "AFS Supplemental Documentation",
+
+ // No service info
+ 0,
+ 0,
+ 0,
+ 0,
+
+ // No network provider order
+ 0,
+
+ // No service shutdown messages
+ 0,
+ 0,
+
+ "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation",
+
+ { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation\\CurrentVersion", "PathName" },
+
+ "\\Documentation",
+ "",
+
+ // No dirs to delete
+ 0,
+
+ // Files to delete
+ TARGETDIR"\\Common\\*.gid\0"
+ TARGETDIR"\\Common\\*.fts\0",
+
+ 0, // No reg values
+ 0, // No NT only reg values
+ 0, // No 9x only reg values
+
+ // Start menu entries to remove
+ "Documentation\\AFS for Windows Backup Command Reference.lnk\0Documentation\\AFS Command Reference Manual.lnk\0Documentation\\AFS System Administrator's Guide.lnk\0",
+
+ 0, // No config info to preserve
+
+ 0 // No uninstall function
+};
+
+
+// Shared and in-use files
+struct FILEINFO {
+ char *pszName;
+ int nUsedBy;
+};
+
+#define SERVER 1
+#define CLIENT 2
+#define LCLIENT 4
+#define CC 8
+#define DOCS 16
+
+
+struct FILEINFO fileInfo[] = {
+ { TARGETDIR"\\Common\\afsbosadmin.dll", SERVER | CC },
+ { TARGETDIR"\\Common\\afscfgadmin.dll", SERVER | CC },
+ { TARGETDIR"\\Common\\afsclientadmin.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afskasadmin.dll", SERVER | CC },
+ { TARGETDIR"\\Common\\afsptsadmin.dll", SERVER | CC },
+ { TARGETDIR"\\Common\\afsvosadmin.dll", SERVER | CC },
+ { TARGETDIR"\\Common\\afsadminutil.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afsrpc.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afsauthent.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\pthread.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\TaAfsAppLib.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afsprocmgmt.dll", SERVER | CLIENT | LCLIENT },
+ { TARGETDIR"\\Common\\afs_config.exe", CLIENT | LCLIENT| CC },
+ { TARGETDIR"\\Common\\afseventmsg_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afslegal_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afsserver_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afssvrcfg_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\TaAfsAccountManager_????.dll",SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\TaAfsAppLib_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\TaAfsServerManager_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afscreds_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs_config_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs_cpa_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs_shl_ext_????.dll", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs-nt.hlp", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs-nt.cnt", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\taafssvrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\taafssvrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\taafsusrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\taafsusrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs-cc.cnt", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs-cc.hlp", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs-light.cnt", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\afs-light.hlp", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\taafscfg.cnt", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Common\\taafscfg.hlp", SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Client\\PROGRAM\\afs_shl_ext.dll", CLIENT | LCLIENT },
+ { TARGETDIR"\\Client\\PROGRAM\\libafsconf.dll", CLIENT | LCLIENT },
+ { TARGETDIR"\\Client\\PROGRAM\\afslogon.dll", CLIENT },
+ { TARGETDIR"\\Client\\PROGRAM\\afslog95.dll", LCLIENT },
+ { TARGETDIR"\\Control Center\\TaAfsAdmSvr.exe", CC },
+ { WINSYSDIR"\\afs_cpa.cpl", CLIENT | LCLIENT | CC },
+ { WINSYSDIR"\\afsserver.cpl", SERVER },
+ { TARGETDIR"\\Common\\afsdcell.ini", CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Documentation\\Html\\banner.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\books.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\bot.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\index.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\index.htm", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\next.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\prev.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\toc.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\top.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
+ { TARGETDIR"\\Documentation\\Html\\ReleaseNotes\\relnotes.htm",
+ SERVER | CLIENT | LCLIENT | CC },
+ { TARGETDIR"\\Documentation\\Html\\InstallGd\\afsnt35i.htm",
+ SERVER | CLIENT | LCLIENT | CC },
+ { 0, 0 } // End of list
+};
+
+
+/*
+ * VARIABLES _________________________________________________________________
+ *
+ */
+HINSTANCE hinst;
+
+static HWND hDlg;
+static BOOL bPreserveConfigInfo;
+static BOOL bSilentMode;
+static char *pszInstallDir;
+
+
+/*
+ * FUNCTIONS _________________________________________________________________
+ *
+ */
+
+static BOOL UpgradeClientIntParm(HKEY hKey, char *pszOldParm, char *pszNewParm)
+{
+ int nData;
+ LONG result = ERROR_SUCCESS;
+
+ nData = GetPrivateProfileInt("AFS Client", pszOldParm, -1, "afsd.ini");
+ if (nData > -1)
+ result = RegSetValueEx(hKey, pszNewParm, 0, REG_DWORD, (BYTE *)&nData, sizeof(nData));
+
+ return (result == ERROR_SUCCESS);
+}
+
+static BOOL UpgradeClientStringParm(HKEY hKey, char *pszOldParm, char *pszNewParm)
+{
+ char szData[1024];
+ LONG result = ERROR_SUCCESS;
+
+ GetPrivateProfileString("AFS Client", pszOldParm, "", szData, sizeof(szData), "afsd.ini");
+ if (szData[0])
+ result = RegSetValueEx(hKey, pszNewParm, 0, REG_SZ, (PBYTE)szData, strlen(szData) + 1);
+
+ return (result == ERROR_SUCCESS);
+}
+
+int SUCALLCONV Upgrade34ClientConfigInfo()
+{
+ HKEY hKey;
+ LONG result;
+ int nData;
+
+ result = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_CLT_SVC_PARAM_KEY, KEY_WRITE, TRUE, &hKey, 0);
+ if (result != ERROR_SUCCESS)
+ return -1;
+
+ UpgradeClientIntParm(hKey, "CacheSize", "CacheSize");
+ UpgradeClientIntParm(hKey, "Stats", "Stats");
+ UpgradeClientIntParm(hKey, "LogoffTokenTransfer", "LogoffTokenTransfer");
+ UpgradeClientIntParm(hKey, "LogoffTokenTransferTimeout", "LogoffTokenTransferTimeout");
+ UpgradeClientIntParm(hKey, "TrapOnPanic", "TrapOnPanic");
+ UpgradeClientIntParm(hKey, "TraceBufferSize", "TraceBufferSize");
+ UpgradeClientIntParm(hKey, "TraceOnShutdown", "TraceOnShutdown");
+ UpgradeClientIntParm(hKey, "ReportSessionStartups", "ReportSessionStartups");
+
+ UpgradeClientStringParm(hKey, "MountRoot", "MountRoot");
+ UpgradeClientStringParm(hKey, "Cell", "Cell");
+
+ /* BlockSize to ChunkSize requires convertion */
+ nData = GetPrivateProfileInt("AFS Client", "BlockSize", -1, "afsd.ini");
+ if (nData > -1) {
+ DWORD chunkSize;
+ for (chunkSize = 0; (1 << chunkSize) < nData; chunkSize++);
+ (void) RegSetValueEx(hKey, "ChunkSize", 0, REG_DWORD, (BYTE *)&chunkSize, sizeof(chunkSize));
+ }
+
+ RegCloseKey(hKey);
+
+ return 0;
+}
+
+int SUCALLCONV Eradicate34Client()
+{
+ if (Client34Eradicate(TRUE) != ERROR_SUCCESS)
+ return -1;
+
+ return 0;
+}
+
+// This function was written a long time ago by Mike Comer for use by the
+// original DFS Client for NT install program.
+int SUCALLCONV CheckIfAdmin(void)
+{
+ HANDLE token = INVALID_HANDLE_VALUE;
+ PVOID buffer = 0;
+ DWORD bufLength;
+ DWORD realBufLength;
+ TOKEN_PRIMARY_GROUP *pgroup;
+ TOKEN_GROUPS *groups;
+ int result = -1;
+ DWORD groupCount;
+ LONG status;
+ PSID AdministratorSID = NULL;
+ SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
+
+ // allocate the SID for the Administrators group
+ if (!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorSID)) {
+ status = GetLastError();
+ goto getout;
+ }
+
+ // open the process token
+ if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) {
+ status = GetLastError();
+ token = INVALID_HANDLE_VALUE;
+ goto getout;
+ }
+
+ // check primary group first
+ buffer = GlobalAlloc(GMEM_FIXED, sizeof(TOKEN_PRIMARY_GROUP));
+ if (!buffer) {
+ goto getout;
+ }
+
+ bufLength = sizeof(TOKEN_PRIMARY_GROUP);
+ while(1) {
+ if (!GetTokenInformation(token, TokenPrimaryGroup, buffer, bufLength, &realBufLength)) {
+ if (realBufLength > bufLength) {
+ // not enough space
+ GlobalFree(buffer);
+ bufLength = realBufLength;
+ buffer = GlobalAlloc(GMEM_FIXED, realBufLength);
+ if (!buffer) {
+ goto getout;
+ }
+ continue;
+ }
+
+ goto getout;
+ }
+ break;
+ }
+
+ pgroup = (TOKEN_PRIMARY_GROUP *)buffer;
+ if (EqualSid(pgroup->PrimaryGroup, AdministratorSID)) {
+ result = 0;
+ } else {
+ // okay, try the secondary groups
+ while(1) {
+ if (!GetTokenInformation(token, TokenGroups, buffer, bufLength, &realBufLength)) {
+ if (realBufLength > bufLength) {
+ // not enough space
+ GlobalFree(buffer);
+ bufLength = realBufLength;
+ buffer = GlobalAlloc(GMEM_FIXED, realBufLength);
+ if (!buffer) {
+ goto getout;
+ }
+ continue;
+ }
+
+ // a real error
+ goto getout;
+ }
+ break;
+ }
+
+ // we have the list of groups here. Process them:
+ groups = (TOKEN_GROUPS *)buffer;
+ for(groupCount = 0; groupCount < groups->GroupCount; groupCount++) {
+ if (EqualSid(groups->Groups[groupCount].Sid, AdministratorSID)) {
+ result = 0;
+ break;
+ }
+ }
+ }
+
+getout:
+
+ if (token != INVALID_HANDLE_VALUE) {
+ CloseHandle(token);
+ }
+
+ if (buffer) {
+ GlobalFree(buffer);
+ }
+
+ if (AdministratorSID) {
+ FreeSid(AdministratorSID);
+ }
+
+ return result;
+}
+
+static void SetSharedFileRefCount(char *pszFile, int nRefCount)
+{
+ LONG result;
+ HKEY hKey;
+
+ result = RegOpenKeyAlt(AFSREG_NULL_KEY, MS_SHARED_FILES_KEY, KEY_WRITE, FALSE, &hKey, 0);
+ if (result != ERROR_SUCCESS)
+ return;
+
+ if (nRefCount <= 0)
+ RegDeleteValue(hKey, pszFile);
+ else
+ RegSetValueEx(hKey, pszFile, 0, REG_DWORD, (BYTE *)&nRefCount, sizeof(int));
+
+ RegCloseKey(hKey);
+}
+
+static char *GetTimeStamp()
+{
+ char szTime[64], szDate[64];
+ static char szTimeDate[128];
+
+ _strtime(szTime);
+ _strdate(szDate);
+
+ sprintf(szTimeDate, "[%s %s] ", szTime, szDate);
+
+ return szTimeDate;
+}
+
+int SUCALLCONV WriteToInstallErrorLog(char *pszMsg)
+{
+ static BOOL bWritten = FALSE;
+ FILE *fp;
+
+ // On the first write, recreate the file
+ fp = fopen(INSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");
+ if (!fp)
+ return -1;
+
+ fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);
+
+ fclose(fp);
+
+ bWritten = TRUE;
+
+ return 0;
+}
+
+static void WriteToUninstallErrorLog(char *pszMsg)
+{
+ static BOOL bWritten = FALSE;
+ FILE *fp;
+
+ // On the first write, recreate the file
+ fp = fopen(UNINSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");
+ if (!fp)
+ return;
+
+ fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);
+
+ fclose(fp);
+
+ bWritten = TRUE;
+}
+
+static char *LoadResString(UINT uID)
+{
+ static char str[256];
+ GetString (str, uID);
+ return str;
+}
+
+static void ShowError(UINT nResID, LONG nError)
+{
+ char szErr[256];
+ char szPrompt[256];
+ char szMsg[256];
+ char szTitle[256];
+ char *psz;
+
+ psz = LoadResString(nResID);
+ if (psz)
+ strcpy(szErr, psz);
+ else
+ sprintf(szErr, "unknown error msg (Msg ID = %d)", nResID);
+
+ psz = LoadResString(IDS_INSTALLATION_FAILURE);
+ strcpy(szPrompt, psz ? psz : "An error has occurred: %s (Last Error = %ld).");
+
+ sprintf(szMsg, szPrompt, szErr, nError);
+
+ psz = LoadResString(IDS_TITLE);
+ strcpy(szTitle, psz ? psz : "AFS");
+
+ if (bSilentMode)
+ WriteToUninstallErrorLog(szMsg);
+ else
+ MessageBox(hDlg, szMsg, szTitle, MB_OK);
+}
+
+static int ShowMsg(UINT nResID, int nType)
+{
+ char szTitle[256];
+ char *psz;
+
+ psz = LoadResString(IDS_TITLE);
+ strcpy(szTitle, psz ? psz : "AFS");
+
+ return MessageBox(hDlg, LoadResString(nResID), szTitle, nType);
+}
+
+static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered)
+{
+ HKEY hKey;
+ LONG nResult;
+ DWORD dwType;
+ static char szInstallDir[256];
+ DWORD dwSize;
+ char *pszKey;
+ char *pszValue;
+
+ pszKey = bRemembered ? UNINSTALL_TEMP_INFO_KEY : pApp->regInstallDir.pszKey;
+ pszValue = bRemembered ? INSTALL_DIR_VALUE_NAME : pApp->regInstallDir.pszValue;
+
+ dwSize = sizeof(szInstallDir);
+
+ nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
+ if (nResult == ERROR_SUCCESS) {
+ nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szInstallDir, &dwSize);
+ RegCloseKey(hKey);
+ }
+
+ if (nResult != ERROR_SUCCESS) {
+ ShowError(IDS_CANT_DETERMINE_APP_PATH, nResult);
+ return 0;
+ }
+
+ FilepathNormalizeEx(szInstallDir, FPN_BACK_SLASHES);
+
+ return szInstallDir;
+}
+
+static BOOL DoesRegKeyExist(char *pszKey)
+{
+ HKEY hKey;
+ LONG nResult;
+
+ nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
+ if (nResult == ERROR_SUCCESS) {
+ RegCloseKey(hKey);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static BOOL IsAppInstalled(struct APPINFO *pApp)
+{
+ return DoesRegKeyExist(pApp->pszAppKey);
+}
+
+static void BuildShortPath(char *pszShortPath, UINT nShortPathLen, char *pszInstallDir, char *pszPath)
+{
+ strncpy(pszShortPath, pszInstallDir, nShortPathLen);
+ strncat(pszShortPath, pszPath, nShortPathLen);
+
+ GetShortPathName(pszShortPath, pszShortPath, nShortPathLen);
+}
+
+static BOOL IsWin95()
+{
+ OSVERSIONINFO versionInformation;
+
+ versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ GetVersionEx(&versionInformation);
+
+ if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
+ (versionInformation.dwMinorVersion == 0))
+ return TRUE;
+
+ return FALSE;
+}
+
+int IsWin98()
+{
+ OSVERSIONINFO versionInformation;
+
+ versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+
+ GetVersionEx(&versionInformation);
+
+ if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
+ (versionInformation.dwMinorVersion == 10))
+ return 0;
+
+ return -1;
+}
+
+static BOOL IsServiceInstalled(char *pszServiceKey)
+{
+ HKEY hKey;
+
+ if (RegOpenKeyAlt(0, pszServiceKey, KEY_READ, FALSE, &hKey, 0) == ERROR_SUCCESS) {
+ RegCloseKey(hKey);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+// If this fails in anyway we just return. No error is displayed.
+static void MakeSureServiceDoesNotExist(char *pszName)
+{
+ SC_HANDLE hServer = 0, hSCM = 0;
+ SERVICE_STATUS status;
+
+ hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
+ if (hSCM) {
+ hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS | DELETE);
+ if (hServer) {
+ if (QueryServiceStatus(hServer, &status)) {
+ if (status.dwCurrentState != SERVICE_STOPPED) {
+ if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {
+ CloseServiceHandle(hServer);
+ CloseServiceHandle(hSCM);
+ return;
+ }
+ }
+ }
+
+ // Try to delete even if status query fails
+ DeleteService(hServer);
+ }
+ }
+
+ if (hServer)
+ CloseServiceHandle(hServer);
+ if (hSCM)
+ CloseServiceHandle(hSCM);
+}
+
+static int InstallService(char *pszName, char *pszDependOn, char *pszDisplayName, char *pszServicePath, BOOL bInteractive)
+{
+ SC_HANDLE hServer = 0, hSCM;
+ BOOL bRestoreOldConfig = FALSE;
+
+ hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
+ if (!hSCM) {
+ ShowError(IDS_SCM_OPEN_FAILED, GetLastError());
+ return -1;
+ }
+
+/* This code is not used, but it could be handy in the future so I am keeping it here.
+
+ // If the service exists, then we (most probably) are in the middle of an upgrade or reinstall.
+ bRestoreOldConfig = IsServiceInstalled(pszName);
+
+ if (bRestoreOldConfig) {
+ hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS);
+ if (!hServer || !ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0)) {
+ ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, GetLastError());
+ bRestoreOldConfig = FALSE;
+ // Fall through to service creation below
+ }
+ }
+*/
+
+ if (!bRestoreOldConfig) {
+ DWORD dwServiceType;
+
+ // If the service already exists, the create call will fail. This can
+ // happen if uninstall failed (which is not infrequent). Making sure the
+ // service does not exist makes it easier for a user to install over top of
+ // a previously failed uninstall.
+ MakeSureServiceDoesNotExist(pszName);
+
+ dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+ if (bInteractive)
+ dwServiceType |= SERVICE_INTERACTIVE_PROCESS;
+
+ hServer = CreateService(hSCM, pszName, pszDisplayName,
+ SERVICE_ALL_ACCESS, dwServiceType, SERVICE_AUTO_START,
+ SERVICE_ERROR_NORMAL, pszServicePath, 0, 0, "RPCSS\0Netbios\0\0", 0, 0);
+
+ if (!hServer)
+ ShowError(IDS_SERVICE_CREATE_FAILED, GetLastError());
+ }
+
+ if (hServer)
+ CloseServiceHandle(hServer);
+
+ CloseServiceHandle(hSCM);
+
+ return 0;
+}
+
+int SUCALLCONV InstallServerService(char *pszServicePath)
+{
+ return InstallService(appServer.pszSvcName, 0, appServer.pszSvcDisplayName, pszServicePath, TRUE);
+}
+
+int SUCALLCONV InstallClientService(char *pszServicePath)
+{
+ return InstallService(appClient.pszSvcName, appClient.pszSvcDependOn, appClient.pszSvcDisplayName, pszServicePath, FALSE);
+}
+
+static int UninstallService(struct APPINFO *pAppInfo)
+{
+ SC_HANDLE hServer, hSCM;
+ SERVICE_STATUS status;
+ BOOL bOk;
+ BOOL bServer = FALSE;
+ BOOL bShowingProgressDlg = FALSE;
+
+ hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
+ if (!hSCM) {
+ ShowError(IDS_SCM_OPEN_FAILED, GetLastError());
+ return -1;
+ }
+
+ hServer = OpenService(hSCM, pAppInfo->pszSvcName, SERVICE_ALL_ACCESS | DELETE);
+ if (!hServer) {
+ ShowError(IDS_SERVICE_OPEN_FAILED, GetLastError());
+ CloseServiceHandle(hSCM);
+ return -1;
+ }
+
+ if (!QueryServiceStatus(hServer, &status)) {
+ ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());
+ CloseServiceHandle(hServer);
+ CloseServiceHandle(hSCM);
+ return -1;
+ }
+
+ if (status.dwCurrentState != SERVICE_STOPPED) {
+ if (pAppInfo->nServiceShutdownMsgID) {
+ if (!bSilentMode && (ShowMsg(pAppInfo->nServiceShutdownMsgID, MB_YESNO | MB_ICONQUESTION) == IDNO)) {
+ CloseServiceHandle(hServer);
+ CloseServiceHandle(hSCM);
+ return 1;
+ }
+ }
+
+ if (!bSilentMode)
+ bShowingProgressDlg = ShowProgressDialog(LoadResString(pAppInfo->nServiceShutdownProgressMsgID));
+
+ if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {
+ if (bShowingProgressDlg)
+ HideProgressDialog();
+ ShowError(IDS_SERVICE_STOP_FAILED, GetLastError());
+ CloseServiceHandle(hServer);
+ CloseServiceHandle(hSCM);
+ return -1;
+ }
+ }
+
+ // Wait for the service to stop
+ while (status.dwCurrentState != SERVICE_STOPPED) {
+ // I stopped waiting on dwWaitHint because it seemed the wait hint was too long.
+ // The service would be stopped but we'd still be asleep for a long time yet.
+ Sleep(5000); //status.dwWaitHint);
+
+ if (!QueryServiceStatus(hServer, &status)) {
+ if (bShowingProgressDlg)
+ HideProgressDialog();
+ ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());
+ CloseServiceHandle(hServer);
+ CloseServiceHandle(hSCM);
+ return -1;
+ }
+ }
+
+ // The service has been stopped
+ if (bShowingProgressDlg)
+ HideProgressDialog();
+
+ // This code to disable the service may be of use some day so I am keeping it here.
+ // bOk = ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0);
+
+ bOk = DeleteService(hServer);
+
+ if (!bOk)
+ ShowError(IDS_SERVICE_DELETE_FAILED, GetLastError());
+
+ CloseServiceHandle(hServer);
+ CloseServiceHandle(hSCM);
+
+ return (bOk ? 0 : -1);
+}
+
+int SUCALLCONV AddToNetworkProviderOrder(char *pszWhatToAdd)
+{
+ return AddToProviderOrder(pszWhatToAdd) ? 0 : -1;
+}
+
+static int RemoveFromNetworkProviderOrder(char *pszWhatToDel)
+{
+ return RemoveFromProviderOrder(pszWhatToDel) ? 0 : -1;
+}
+
+int SUCALLCONV AddToPath(char *pszPath)
+{
+ return AddToSystemPath(pszPath) ? 0 : -1;
+}
+
+static int RemoveFromPath(char *pszPath)
+{
+ return RemoveFromSystemPath(pszPath) ? 0 : -1;
+}
+
+static void RemoveFiles(char *pszFileSpec)
+{
+ struct _finddata_t fileinfo;
+ long hSearch;
+ char szDel[MAX_PATH];
+ char szDir[MAX_PATH];
+ char *p;
+
+ strcpy(szDir, pszFileSpec);
+ p = strrchr(szDir, '\\');
+ if (p)
+ *p = 0;
+
+ hSearch = _findfirst(pszFileSpec, &fileinfo);
+ if (hSearch == -1)
+ return;
+
+ while (1) {
+ if ((strcmp(fileinfo.name, ".") != 0) && (strcmp(fileinfo.name, "..") != 0)) {
+ sprintf(szDel, "%s\\%s", szDir, fileinfo.name);
+ DeleteFile(szDel);
+ }
+
+ if (_findnext(hSearch, &fileinfo) == -1)
+ break;
+ }
+
+ _findclose(hSearch);
+}
+
+static void RemoveDir(char *pszDir)
+{
+ char szFileSpec[MAX_PATH];
+
+ sprintf(szFileSpec, "%s\\*.*", pszDir);
+
+ RemoveFiles(szFileSpec);
+ RemoveDirectory(pszDir);
+}
+
+static void RemoveRegValues(struct REGVALUE *pRegValues)
+{
+ struct REGVALUE *pCurValue;
+ HKEY hKey;
+ LONG nResult;
+
+ if (!pRegValues)
+ return;
+
+ for (pCurValue = pRegValues; pCurValue->pszKey; pCurValue++) {
+ nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pCurValue->pszKey, KEY_ALL_ACCESS, FALSE, &hKey, 0);
+
+ if (nResult == ERROR_SUCCESS) {
+ nResult = RegDeleteValue(hKey, pCurValue->pszValue);
+ RegCloseKey(hKey);
+ }
+
+ if (nResult != ERROR_SUCCESS)
+ ShowError(IDS_REG_DELETE_VALUE_ERROR, nResult);
+ }
+}
+
+static BOOL UninstallCredsTool()
+{
+ int nResult = WinExec("afscreds /uninstall", SW_HIDE);
+
+ if (nResult <= 31) {
+ if (nResult != ERROR_FILE_NOT_FOUND)
+ ShowError(IDS_CANT_UNINSTALL_AFSCREDS, nResult);
+ }
+
+ // Always return true. We don't want the uninstall to completely fail just
+ // because the creds tool didn't uninstall.
+ return TRUE;
+}
+
+
+static char *GetTempDir()
+{
+ DWORD result;
+ static char szTempDir[MAX_PATH];
+
+ result = GetTempPath(sizeof(szTempDir) - 1, szTempDir);
+ if (result == 0)
+ return "\\";
+
+ return szTempDir;
+}
+
+static char *GetRootInstallDir()
+{
+ char *psz;
+ static char szRootInstallDir[MAX_PATH] = "";
+
+ if (szRootInstallDir[0] == 0) {
+ strcpy(szRootInstallDir, pszInstallDir);
+
+ // Strip off the app specific part of the install dir
+ psz = strrchr(szRootInstallDir, '\\');
+ if (psz)
+ *psz = 0;
+ }
+
+ return szRootInstallDir;
+}
+
+static BOOL ClientSpecificUninstall()
+{
+ int nChoice;
+
+ // This function needs to do two things. First it needs to see if the server is
+ // installed, and if it is, ask the user if they really want to uninstall the
+ // client given that the server needs the client. Second, if we are uninstalling
+ // the client, we need to uninstall the creds tool.
+
+ if (!bSilentMode) {
+ if (IsAppInstalled(&appServer)) {
+ nChoice = ShowMsg(IDS_CLIENT_NEEDED_BY_SERVER, MB_ICONQUESTION | MB_YESNO);
+ if (nChoice == IDNO)
+ return FALSE; // Cancel the uninstall
+ }
+ }
+
+ UninstallCredsTool();
+
+ return TRUE;
+}
+
+static struct APPINFO *GetApp()
+{
+#ifdef SERVER_UNINST
+ return &appServer;
+#elif CLIENT_UNINST
+ return &appClient;
+#elif CC_UNINST
+ return &appControlCenter;
+#elif LIGHT_CLIENT_UNINST
+ return &appLightClient;
+#elif DOCS_UNINST
+ return &appDocs;
+#else
+ return 0;
+#endif;
+}
+
+static void RememberInstallDir(char *pszInstallDir)
+{
+ HKEY hKey;
+
+ // We remember the install dir so that when the UninstUninitialize function is called
+ // by the InstallShield uninstaller, we can find out where we were installed to. We
+ // have to do this because by the time that function is called, the registry values
+ // created at install time are already gone. We need to be able to find out where we
+ // were installed so we can clean up anything IS couldn't uninstall. If this fails in
+ // any way then we don't care. The only consequence is that some junk might be left on
+ // the users' system after an uninstall.
+
+ LONG result = RegOpenKeyAlt(AFSREG_NULL_KEY, UNINSTALL_TEMP_INFO_KEY, KEY_WRITE, TRUE, &hKey, 0);
+ if (result != ERROR_SUCCESS)
+ return;
+
+ RegSetValueEx(hKey, INSTALL_DIR_VALUE_NAME, 0, REG_SZ, (PBYTE)pszInstallDir, strlen(pszInstallDir) + 1);
+
+ RegCloseKey(hKey);
+}
+
+int SUCALLCONV SetSilentMode()
+{
+ bSilentMode = TRUE;
+
+ return 0;
+}
+
+static char *GetWinDir()
+{
+ static char szWinDir[MAX_PATH] = "";
+
+ if (!szWinDir[0])
+ GetWindowsDirectory(szWinDir, sizeof(szWinDir));
+
+ return szWinDir;
+}
+
+static char *GetWinSysDir()
+{
+ static char szWinSysDir[MAX_PATH] = "";
+
+ if (!szWinSysDir[0])
+ GetSystemDirectory(szWinSysDir, sizeof(szWinSysDir));
+
+ return szWinSysDir;
+}
+
+static char *GetLocaleID()
+{
+ static char szID[25] = "";
+
+ if (szID[0] == 0) {
+ LCID dwID = GetSystemDefaultLCID();
+
+ // Nuke the high word. It contains a sort ID.
+ dwID &= 0x0000FFFF;
+
+ // Convert locale ID to a string
+ itoa(dwID, szID, 10);
+
+ // This thing should never be more than LOCALE_ID_LEN characters long.
+ szID[LOCALE_ID_LEN] = 0;
+ }
+
+ return szID;
+}
+
+static char *ExpandPath(char *pszFile)
+{
+ static char szPath[MAX_PATH];
+ char *psz;
+
+ szPath[0] = 0;
+
+ // Convert a path containing TARGETDIR, WINDIR, or WINSYSDIR to a
+ // real path in the file system. One of these MUST be the start of
+ // the file path passed in. Also convert the string ???? to an
+ // actual locale number.
+ if (strncmp(pszFile, TARGETDIR, strlen(TARGETDIR)) == 0)
+ strcpy(szPath, GetRootInstallDir());
+ else if (strncmp(pszFile, WINDIR, strlen(WINDIR)) == 0)
+ strcpy(szPath, GetWinDir());
+ else if (strncmp(pszFile, WINSYSDIR, strlen(WINSYSDIR)) == 0)
+ strcpy(szPath, GetWinSysDir());
+
+ if (szPath[0]) {
+ psz = strchr(pszFile, '\\');
+ if (psz)
+ strcat(szPath, psz);
+ } else
+ strcpy(szPath, pszFile);
+
+ // Is this a language dll?
+ psz = strstr(szPath, "????.");
+
+ // If it is, replace ???? with the locale number
+ if (psz)
+ strncpy(psz, GetLocaleID(), LOCALE_ID_LEN);
+
+ return szPath;
+}
+
+static BOOL FileNeededByOtherApp(struct APPINFO *pApp, struct FILEINFO *pFileInfo)
+{
+ // If the file is used by the server, the app being uninstalled is not the server, and
+ // the server is installed, then this file is used by another app.
+ if (!IsWinNT()) {
+ if ((pFileInfo->nUsedBy & LCLIENT) && (pApp != &appLightClient) && IsAppInstalled(&appLightClient))
+ return TRUE;
+ return FALSE;
+ }
+
+ if ((pFileInfo->nUsedBy & SERVER) && (pApp != &appServer) && IsAppInstalled(&appServer))
+ return TRUE;
+
+ if ((pFileInfo->nUsedBy & CLIENT) && (pApp != &appClient) && IsAppInstalled(&appClient))
+ return TRUE;
+
+ if ((pFileInfo->nUsedBy & CC) && (pApp != &appControlCenter) && IsAppInstalled(&appControlCenter))
+ return TRUE;
+
+ return FALSE;
+}
+
+static void DeleteInUseFiles(struct APPINFO *pAppInfo, struct FILEINFO *pFileInfo)
+{
+ char szSrcPath[MAX_PATH];
+ char szDestPath[MAX_PATH];
+ char szTempDir[MAX_PATH];
+ int ii;
+
+ // If some app's file has been loaded before the app is uninstalled, then
+ // when an uninstall is attempted, the application and all of the dlls that
+ // its uses will be in use and IS will not be able to delete them. Normally this
+ // is not a problem because IS will tell the user to reboot to finish the uninstall.
+ // However, we must support the ability to perform a silent uninstall followed
+ // immediatly by an install of the same product to the same directories. If we let
+ // IS handle the uninstall of these files, this is not possible. The reason is that
+ // when IS fails to remove these in use files, it marks them for deletion after the
+ // next reboot, which is fine. Unfortunately, it leaves them in the dirs they were
+ // installed to. So if we don't immediately reboot and perform an install to the
+ // same dirs, once a reboot is performed, those files get deleted and we have a
+ // broken installation.
+
+ // What we will do to fix all of this, is when the client is uninstalled, but
+ // before IS does anything, we will move the in use files and associated dlls
+ // into the temp dir and mark them for delete after a reboot. Then an install
+ // that follows will succeed.
+
+ // Delete the files that may be in use. If they are we actually move
+ // them to the temp dir and mark them for deletion after the next reboot.
+ for (ii = 0; pFileInfo[ii].pszName != 0; ii++) {
+ // Get the source path
+ strcpy(szSrcPath, ExpandPath(pFileInfo[ii].pszName));
+
+ // Only delete the file if it is not used by some other app
+ if (FileNeededByOtherApp(pAppInfo, &pFileInfo[ii]))
+ continue;
+
+ // If the file doesn't exist then go on to the next file.
+ if (_access(szSrcPath, 0) != 0)
+ continue;
+
+ // See if we can do a regular delete of the file
+ if (DeleteFile(szSrcPath)) {
+ SetSharedFileRefCount(szSrcPath, 0);
+ continue;
+ }
+
+ // Get a temp dir that is on the same drive as the src path.
+ // We can't move an in use file to a different drive.
+ strcpy(szTempDir, GetTempDir());
+ if (szTempDir[0] != szSrcPath[0]) {
+ // Get the drive, colon, and slash of the src path
+ strncpy(szTempDir, szSrcPath, 3);
+ szTempDir[3] = 0;
+ }
+
+ // Get the dest path - we will rename the file during the move
+ GetTempFileName(szTempDir, "AFS", 0, szDestPath);
+
+ // Move from source to dest, marking the file for deletion after a reboot
+ if (IsWin95()) {
+ if (MoveFile(szSrcPath, szDestPath)) {
+ WritePrivateProfileString("rename", szSrcPath, szDestPath, "wininit.ini");
+ SetSharedFileRefCount(szSrcPath, 0);
+ }
+ } else { // WinNT or Win98
+ if (MoveFileEx(szSrcPath, szDestPath, MOVEFILE_REPLACE_EXISTING)) {
+ SetFileAttributes(szDestPath, FILE_ATTRIBUTE_NORMAL);
+ MoveFileEx(szDestPath, 0, MOVEFILE_DELAY_UNTIL_REBOOT);
+ SetSharedFileRefCount(szSrcPath, 0);
+ }
+ }
+ }
+}
+
+// Delete a directory and all its files and subdirectories - Yee haaa!
+static void RemoveDirectoryTree(char *pszDir)
+{
+ HANDLE hFind;
+ WIN32_FIND_DATA findFileData;
+ char szSpec[MAX_PATH];
+ char szSubFileOrDir[MAX_PATH];
+ BOOL bContinue;
+
+ sprintf(szSpec, "%s\\*.*", pszDir);
+
+ // First delete the contents of the dir
+ hFind = FindFirstFile(szSpec, &findFileData);
+ bContinue = (hFind != INVALID_HANDLE_VALUE);
+
+ while (bContinue) {
+ if ((strcmp(findFileData.cFileName, ".") != 0) && (strcmp(findFileData.cFileName, "..") != 0)) {
+ sprintf(szSubFileOrDir, "%s\\%s", pszDir, findFileData.cFileName);
+
+ if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ RemoveDirectoryTree(szSubFileOrDir);
+ else
+ DeleteFile(szSubFileOrDir);
+ }
+
+ bContinue = FindNextFile(hFind, &findFileData);
+ }
+
+ FindClose(hFind);
+
+ // Now remove the dir
+ RemoveDirectory(pszDir);
+}
+
+static char *GetStartMenuRoot()
+{
+ HKEY hKey;
+ LONG nResult;
+ DWORD dwType;
+ DWORD dwSize;
+ char *pszKey;
+ char *pszValue;
+
+ static char szStartMenuRoot[MAX_PATH] = "";
+
+ if (szStartMenuRoot[0] == 0) {
+ dwSize = sizeof(szStartMenuRoot);
+
+ if (IsWinNT()) {
+ pszKey = WINNT_START_MENU_REG_KEY;
+ pszValue = WINNT_START_MENU_REG_VALUE;
+ } else {
+ pszKey = WIN9X_START_MENU_REG_KEY;
+ pszValue = WIN9X_START_MENU_REG_VALUE;
+ }
+
+ nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
+ if (nResult == ERROR_SUCCESS) {
+ nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szStartMenuRoot, &dwSize);
+ RegCloseKey(hKey);
+ }
+
+ if (nResult != ERROR_SUCCESS)
+ return 0;
+ }
+
+ FilepathNormalizeEx(szStartMenuRoot, FPN_BACK_SLASHES);
+
+ return szStartMenuRoot;
+}
+
+static char *GetAfsStartMenuRoot()
+{
+ static char szAfsStartMenuRoot[MAX_PATH] = "";
+ char *pszStartMenuRoot;
+
+ if (szAfsStartMenuRoot[0] == 0) {
+ pszStartMenuRoot = GetStartMenuRoot();
+ if (!pszStartMenuRoot)
+ return 0;
+
+ if (bSilentMode)
+ sprintf(szAfsStartMenuRoot, "%s\\IBM WebSphere\\Performance Pack\\AFS", pszStartMenuRoot );
+ else
+ sprintf(szAfsStartMenuRoot, "%s\\IBM AFS", pszStartMenuRoot );
+ }
+
+ return szAfsStartMenuRoot;
+}
+
+static BOOL IsADir(char *pszName)
+{
+ struct _stat statbuf;
+
+ if (_stat(pszName, &statbuf) < 0)
+ return FALSE;
+
+ return statbuf.st_mode & _S_IFDIR;
+}
+
+static void DeleteStartMenuEntries(char *pszEntries)
+{
+ char szStartMenuPath[MAX_PATH];
+ char *pszAfsStartMenuRoot;
+ char *pszCurEntry;
+
+ pszAfsStartMenuRoot = GetAfsStartMenuRoot();
+
+ if (!pszAfsStartMenuRoot)
+ return;
+
+ for (pszCurEntry = pszEntries; *pszCurEntry; pszCurEntry += strlen(pszCurEntry) + 1) {
+ sprintf(szStartMenuPath, "%s\\%s", pszAfsStartMenuRoot, pszCurEntry);
+ if (IsADir(szStartMenuPath))
+ RemoveDirectoryTree(szStartMenuPath);
+ else
+ DeleteFile(szStartMenuPath);
+ }
+}
+
+static void RefreshStartMenu()
+{
+ char *pszAfsStartMenuRoot;
+ char szTemp[MAX_PATH];
+
+ pszAfsStartMenuRoot = GetAfsStartMenuRoot();
+ if (!pszAfsStartMenuRoot)
+ return;
+
+ sprintf(szTemp, "%s - Refresh Attempt", pszAfsStartMenuRoot);
+
+ // Deleting items from below the root level of the start menu does not
+ // cause it to refresh. In order that users can see changes without
+ // rebooting we will temporarily rename our root most entry, which
+ // does cause a refresh of the start menu.
+ MoveFileEx(pszAfsStartMenuRoot, szTemp, MOVEFILE_REPLACE_EXISTING);
+ MoveFileEx(szTemp, pszAfsStartMenuRoot, MOVEFILE_REPLACE_EXISTING);
+}
+
+static BOOL PreserveConfigInfo(struct APPINFO *pApp)
+{
+ char *pszRegKey;
+ char szDestKey[256];
+ LONG result;
+
+ bPreserveConfigInfo = TRUE;
+
+ // If not in silent mode, ask user if they want to preserve the cfg info
+ if (!bSilentMode) {
+ int nChoice = ShowMsg(pApp->nPreserveConfigInfoMsgID, MB_ICONQUESTION | MB_YESNOCANCEL);
+ if (nChoice == IDCANCEL)
+ return FALSE; // Cancel the uninstall
+ else if (nChoice == IDNO) {
+ bPreserveConfigInfo = FALSE; // User doesn't want to preserve the config info
+ return TRUE;
+ }
+ }
+
+ // Copy each reg key (and all of its subkeys and values) to another place in the registry.
+ for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {
+ if (!DoesRegKeyExist(pszRegKey))
+ continue;
+
+ // Create the destination path for the copy
+ sprintf(szDestKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);
+
+ // Try to copy it
+ result = RegDupKeyAlt(pszRegKey, szDestKey);
+
+ if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND)) {
+ // If the copy failed, then delete any copies that succeeded
+ sprintf(szDestKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
+ RegDeleteEntryAlt(szDestKey, REGENTRY_KEY);
+ goto done;
+ }
+ }
+
+ // Remember the integrated login setting if this app supports that and it was turned on
+ if (pApp->pszNetworkProviderOrder) {
+ // Was integerated login turned on?
+ BOOL bOn, bOk;
+ bOk = InNetworkProviderOrder(pApp->pszNetworkProviderOrder, &bOn);
+ if (bOk && bOn) {
+ HKEY hKey;
+ sprintf(szDestKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
+ result = RegOpenKeyAlt(AFSREG_NULL_KEY, szDestKey, KEY_WRITE, TRUE, &hKey, 0);
+ // The existance of the key is a flag indicating that integrated login was turned on
+ RegCloseKey(hKey);
+ }
+ }
+
+done:
+ if ((result == ERROR_SUCCESS) || bSilentMode)
+ return TRUE; // Continue with uninstall
+
+ // Report the error and ask the user if they want to continue the uninstall
+ return (ShowMsg(IDS_SAVE_OF_CONFIG_INFO_FAILED, MB_ICONEXCLAMATION | MB_YESNO) == IDYES);
+}
+
+int SUCALLCONV RestoreConfigInfo(int nApp)
+{
+ char *pszRegKey;
+ char szSrcKey[256];
+ struct APPINFO *pApp = 0;
+ BOOL bError = FALSE;
+ LONG result;
+
+ switch (nApp) {
+ case SERVER: pApp = &appServer; break;
+ case CLIENT: pApp = &appClient; break;
+ case LCLIENT: pApp = &appLightClient; break;
+ case CC: pApp = &appControlCenter; break;
+ }
+
+ if (!pApp)
+ return -1;
+
+ // Copy each reg key (and all of its subkeys and values) back to its original place in the registry.
+ for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {
+ // Create the source path for the copy
+ sprintf(szSrcKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);
+
+ if (!DoesRegKeyExist(szSrcKey))
+ continue;
+
+ // Try to restore as many of the keys as possible. Report any errors at the end.
+
+ // Try to copy it
+ result = RegDupKeyAlt(szSrcKey, pszRegKey);
+ if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND))
+ bError = TRUE;
+ }
+
+ // Restore integrated login if this app was using it
+ if (pApp->pszNetworkProviderOrder) {
+ // Check if integrated login was turned on. The IntegratedLogin key is a flag
+ // telling us that it was on. If the key does not exist, integrated login was
+ // not on.
+ sprintf(szSrcKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
+ if (DoesRegKeyExist(szSrcKey)) {
+ if (!AddToProviderOrder(pApp->pszNetworkProviderOrder))
+ bError = TRUE;
+ }
+ }
+
+ // Remove our saved copies of the config info
+ sprintf(szSrcKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
+ RegDeleteEntryAlt(szSrcKey, REGENTRY_KEY);
+
+ if (bError)
+ ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, 0);
+
+ return TRUE;
+}
+
+static BOOL DoSubKeysExist(char *pszKey)
+{
+ LONG result;
+ HKEY hKey;
+ char *pszSubKeys = 0;
+ BOOL bExist;
+
+ result = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
+ if (result != ERROR_SUCCESS)
+ return FALSE;
+
+ result = RegEnumKeyAlt(hKey, &pszSubKeys);
+ RegCloseKey(hKey);
+
+ if (result != ERROR_SUCCESS)
+ return FALSE;
+
+ if (pszSubKeys) {
+ bExist = TRUE;
+ free(pszSubKeys);
+ } else
+ bExist = FALSE;
+
+ return bExist;
+}
+
+/*
+ * The following definitions are taken from richedit.h:
+ *
+ */
+
+#define EM_SETBKGNDCOLOR (WM_USER + 67) // from Richedit.h
+#define EM_STREAMIN (WM_USER + 73) // from Richedit.h
+#define SF_RTF 0x0002
+
+typedef DWORD (CALLBACK *EDITSTREAMCALLBACK)(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
+
+typedef struct _editstream {
+ DWORD dwCookie; /* user value passed to callback as first parameter */
+ DWORD dwError; /* last error */
+ EDITSTREAMCALLBACK pfnCallback;
+} EDITSTREAM;
+
+/*
+ *
+ */
+
+DWORD CALLBACK License_StreamText (DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
+{
+ LPTSTR psz = (LPTSTR)dwCookie;
+ LONG cchAvail = lstrlen(psz);
+ if ((*pcb = min(cchAvail, cb)) != 0) {
+ memcpy (pbBuff, psz, *pcb);
+ memmove (psz, &psz[*pcb], cchAvail - *pcb + 1);
+ }
+ return 0;
+}
+
+
+void License_OnInitDialog (HWND hDlg, LPTSTR pszFile)
+{
+ // Open the license file and shove its text in our RichEdit control
+ //
+ HANDLE hFile;
+ if ((hFile = CreateFile (pszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) {
+
+ size_t cbText;
+ if ((cbText = GetFileSize (hFile, NULL)) != 0) {
+
+ LPTSTR abText = (LPTSTR)GlobalAlloc (GMEM_FIXED, cbText + 3);
+
+ DWORD cbRead;
+ if (ReadFile (hFile, abText, cbText, &cbRead, NULL)) {
+ abText[ cbRead ] = 0;
+
+ EDITSTREAM Stream;
+ memset (&Stream, 0x00, sizeof(Stream));
+ Stream.dwCookie = (DWORD)abText;
+ Stream.pfnCallback = License_StreamText;
+
+ SendDlgItemMessage (hDlg, IDC_TEXT, EM_STREAMIN, SF_RTF, (LPARAM)&Stream);
+ }
+
+ GlobalFree (abText);
+ }
+
+ CloseHandle (hFile);
+ }
+
+ // Make the control's background be gray
+ //
+ SendDlgItemMessage (hDlg, IDC_TEXT, EM_SETBKGNDCOLOR, FALSE, (LPARAM)GetSysColor(COLOR_BTNFACE));
+}
+
+BOOL CALLBACK License_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
+{
+ switch (msg) {
+ case WM_INITDIALOG:
+ SetWindowLong (hDlg, DWL_USER, lp);
+ License_OnInitDialog (hDlg, (LPTSTR)lp);
+ break;
+
+ case WM_COMMAND:
+ switch (LOWORD(wp)) {
+ case IDCANCEL:
+ case IDOK:
+ EndDialog (hDlg, LOWORD(wp));
+ break;
+
+ case IDC_PRINT:
+ TCHAR szDir[ MAX_PATH ];
+ GetCurrentDirectory (MAX_PATH, szDir);
+ ShellExecute (hDlg, TEXT("print"), (LPTSTR)GetWindowLong (hDlg, DWL_USER), NULL, szDir, SW_HIDE);
+ break;
+ }
+ break;
+ }
+ return FALSE;
+}
+
+BOOL FindAfsInstallationPathByComponent (LPTSTR pszInstallationPath, LPTSTR pszComponent)
+{
+ *pszInstallationPath = 0;
+
+ TCHAR szRegPath[ MAX_PATH ];
+ wsprintf (szRegPath, TEXT("Software\\TransarcCorporation\\%s\\CurrentVersion"), pszComponent);
+
+ HKEY hk;
+ if (RegOpenKey (HKEY_LOCAL_MACHINE, szRegPath, &hk) == 0) {
+ DWORD dwType = REG_SZ;
+ DWORD dwSize = MAX_PATH;
+
+ if (RegQueryValueEx (hk, TEXT("PathName"), NULL, &dwType, (PBYTE)pszInstallationPath, &dwSize) == 0) {
+ *(LPTSTR)FindBaseFileName (pszInstallationPath) = TEXT('\0');
+
+ if (pszInstallationPath[0] && (pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] == TEXT('\\')))
+ pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] = TEXT('\0');
+ }
+
+ RegCloseKey (hk);
+ }
+
+ return !!*pszInstallationPath;
+}
+
+BOOL FindAfsInstallationPath (LPTSTR pszInstallationPath)
+{
+ if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Client")))
+ return TRUE;
+ if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Control Center")))
+ return TRUE;
+ if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Server")))
+ return TRUE;
+ if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Supplemental Documentation")))
+ return TRUE;
+ return FALSE;
+}
+
+HINSTANCE LoadRichTextControl (void)
+{
+ HINSTANCE hInst;
+ if ((hInst = LoadLibrary ("riched20.dll")) != NULL)
+ return hInst;
+ if ((hInst = LoadLibrary ("riched32.dll")) != NULL)
+ return hInst;
+ if ((hInst = LoadLibrary ("riched.dll")) != NULL)
+ return hInst;
+ if ((hInst = LoadLibrary ("richedit.dll")) != NULL)
+ return hInst;
+ return NULL;
+}
+
+int SUCALLCONV ShowLicense (char *pszTarget, char *pszSource)
+{
+ // If the license already lives on this user's machine, don't show
+ // it again. This only has to be done if the user has never
+ // accepted the license agreement before (it's part of the setup
+ // program, so it gets installed if they've accepted it).
+ //
+ // We were handed a relative path of the form:
+ // Documentation/html/license.rtf
+ //
+ // We'll need to find the AFS installation directory, in order to
+ // find that Documentation subtree.
+ //
+ BOOL fShowLicense = TRUE;
+
+ TCHAR szInstallationPath[ MAX_PATH ];
+ if (FindAfsInstallationPath (szInstallationPath)) {
+ TCHAR szLicensePath[ MAX_PATH ];
+ wsprintf (szLicensePath, TEXT("%s\\%s"), szInstallationPath, pszTarget);
+
+ if (GetFileAttributes (szLicensePath) != (DWORD)-1) {
+ fShowLicense = FALSE;
+ }
+ }
+
+ // Before we can show the license file, we have to prepare the RichEdit
+ // control. That means loading the appropriate library and calling its
+ // initialization functions.
+ //
+ HINSTANCE hRichEdit;
+ if ((hRichEdit = LoadRichTextControl()) != NULL) {
+
+ // If we must show the license, do so now. This is a modal dialog,
+ // so we'll know whether or not the user accepts the license.
+ //
+ if (ModalDialogParam (IDD_LICENSE, GetActiveWindow(), License_DlgProc, (LPARAM)pszSource) == IDCANCEL) {
+ // The user rejected the license; fail setup
+ return FALSE;
+ }
+
+ FreeLibrary (hRichEdit);
+ }
+
+ // The user accepted the license, so we can continue with Setup.
+ // The license file is installed as part of Setup.
+ return TRUE;
+}
+
+int SUCALLCONV UninstInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)
+{
+ char szPath[MAX_PATH];
+ struct APPINFO *pAppInfo;
+ char *pszFile = 0;
+ char *pszSubDir = 0;
+
+ hDlg = hIS;
+
+ bSilentMode = !IsWindowVisible(hIS);
+
+ // Which app are we uninstalling?
+ pAppInfo = GetApp();
+ if (!pAppInfo) {
+ ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);
+ return -1;
+ }
+
+ // Get the app's install dir
+ pszInstallDir = GetAppInstallDir(pAppInfo, FALSE);
+ if (!pszInstallDir)
+ return -1;
+
+ // If this app has a custom uninstall func, call it here
+ if (pAppInfo->pUninstallFunc)
+ if (!pAppInfo->pUninstallFunc())
+ return -1;
+
+ if (pAppInfo->pszRegKeysToPreserve)
+ if (!PreserveConfigInfo(pAppInfo))
+ return -1;
+
+ // Unconfigure the service, if there is one for this app
+ if (pAppInfo->pszSvcKey) {
+ if (IsServiceInstalled(pAppInfo->pszSvcKey))
+ if (UninstallService(pAppInfo) == 1)
+ return -1;
+ }
+
+ RememberInstallDir(pszInstallDir);
+
+ DeleteInUseFiles(pAppInfo, fileInfo);
+
+ // Remove the app's bin path from the system path
+ if (pAppInfo->pszBinPath) {
+ BuildShortPath(szPath, sizeof(szPath), pszInstallDir, pAppInfo->pszBinPath);
+ RemoveFromPath(szPath);
+ }
+
+ // Remove entry from NetworkProvider\Order key in registry
+ if (pAppInfo->pszNetworkProviderOrder)
+ RemoveFromNetworkProviderOrder(pAppInfo->pszNetworkProviderOrder);
+
+ // Remove any generated subdirectories
+ if (!bPreserveConfigInfo && pAppInfo->pszDirsToDel) {
+ for (pszSubDir = pAppInfo->pszDirsToDel; *pszSubDir; pszSubDir += strlen(pszSubDir) + 1)
+ RemoveDir(ExpandPath(pszSubDir));
+ }
+
+ // Remove any generated files
+ if (!bPreserveConfigInfo && pAppInfo->pszFilesToDel) {
+ for (pszFile = pAppInfo->pszFilesToDel; *pszFile; pszFile += strlen(pszFile) + 1)
+ RemoveFiles(ExpandPath(pszFile));
+ }
+
+ // Remove any registry values that IS can't handle
+ RemoveRegValues(pAppInfo->pRegValues);
+ if (IsWinNT())
+ RemoveRegValues(pAppInfo->pWinNTRegValues);
+ else
+ RemoveRegValues(pAppInfo->pWin9XRegValues);
+
+ // Remove the start menu entries for this app
+ if (pAppInfo->pszStartMenuEntries) {
+ DeleteStartMenuEntries(pAppInfo->pszStartMenuEntries);
+ RefreshStartMenu();
+ }
+
+ // Remove the install dir
+ RemoveDirectory(pszInstallDir);
+
+ return 0;
+}
+
+void SUCALLCONV UninstUnInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)
+{
+ char *pszInstallDir;
+ char szDirPath[MAX_PATH];
+ char *psz;
+ struct APPINFO *pAppInfo;
+
+ // If we just uninstalled the last AFS app, then do some cleanup.
+ if (IsAppInstalled(&appServer) || IsAppInstalled(&appClient) ||
+ IsAppInstalled(&appControlCenter) || IsAppInstalled(&appLightClient) ||
+ IsAppInstalled(&appDocs))
+ {
+ return;
+ }
+
+ bSilentMode = !IsWindowVisible(hIS);
+
+ // Which app did we just uninstall?
+ pAppInfo = GetApp();
+ if (!pAppInfo) {
+ ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);
+ return;
+ }
+
+ // Get the app's install dir
+ pszInstallDir = GetAppInstallDir(pAppInfo, TRUE);
+ if (!pszInstallDir)
+ return;
+
+ // Remove the reg key we used to remember the app install dir
+ RegDeleteEntryAlt(UNINSTALL_TEMP_INFO_KEY, REGENTRY_KEY);
+
+ // Try to remove the reg key used to store config info, but only
+ // if there are no app config info sub keys present.
+ if (!DoSubKeysExist(AFS_PRESERVED_CFG_INFO_KEY))
+ RegDeleteEntryAlt(AFS_PRESERVED_CFG_INFO_KEY, REGENTRY_KEY);
+
+ // Remove the install dir
+ RemoveDirectory(pszInstallDir);
+
+ // Attempt to remove the install root and common directories. The are
+ // shared and so no single app knows to delete them.
+
+ // Strip off the app specific part of the install dir
+ psz = strrchr(pszInstallDir, '\\');
+ if (psz)
+ *psz = 0;
+
+ sprintf(szDirPath, "%s\\%s", pszInstallDir, "Common");
+ RemoveDirectory(szDirPath);
+
+ // Remove the Common directory from the system path
+ RemoveFromPath(szDirPath);
+
+ // Remove all of the documentation dirs
+ sprintf(szDirPath, "%s\\%s", pszInstallDir, "Documentation");
+ RemoveDirectoryTree(szDirPath);
+
+ // Ok, up to this point we have been removing files we know we
+ // created. However, after this point we are into the path
+ // that the user chose for our install root. The default for
+ // this is IBM/Afs, but they could have chosen anything,
+ // including a dir or dirs that have other products in them.
+ // We will check to see if it is IBM\AFS and if it is then we
+ // will attempt to remove them.
+
+ // Back up a level and look for AFS
+ psz = strrchr(pszInstallDir, '\\');
+ if (psz) {
+ if (stricmp(psz + 1, "AFS") == 0) {
+ RemoveDirectory(pszInstallDir);
+ *psz = 0;
+ }
+ }
+
+ // Back up a level and look for IBM
+ psz = strrchr(pszInstallDir, '\\');
+ if (psz) {
+ if (stricmp(psz + 1, "IBM") == 0) {
+ RemoveDirectory(pszInstallDir);
+ *psz = 0;
+ }
+ }
+
+ // Remove the root afs start menu entry
+ psz = GetStartMenuRoot();
+ if (psz) {
+ if (bSilentMode) {
+ // Remove everything under our branch
+ sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack\\AFS", psz);
+ RemoveDirectoryTree(szDirPath);
+
+ // Remove the IBM stuff only if the dirs are empty
+ sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack", psz);
+ if (RemoveDirectory(szDirPath)) {
+ sprintf(szDirPath, "%s\\IBM WebSphere", psz);
+ RemoveDirectory(szDirPath);
+ }
+ } else {
+ sprintf(szDirPath, "%s\\IBM AFS", psz);
+ RemoveDirectoryTree(szDirPath);
+ }
+ }
+}
+
+BOOLEAN _stdcall DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
+{
+ if (reason == DLL_PROCESS_ATTACH) {
+ hinst = (HINSTANCE)dll;
+ TaLocale_LoadCorrespondingModuleByName (hinst, "afs_setup_utils.dll");
+ }
+
+ return TRUE;
+}
+
+extern "C" int WINAPI Test (HINSTANCE hInst, HINSTANCE hPrev, LPSTR psz, int nCmdShow)
+{
+ ShowLicense ("TEST", "\\\\fury\\afssetup\\license\\ja_JP.rtf");
+ return 0;
+}
+
+