2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * INCLUDES _________________________________________________________________
\r
16 #include <afs/param.h>
\r
17 #include <afs/stds.h>
\r
18 #include <afs/fileutil.h>
\r
21 #include <windows.h>
\r
28 #include <SYS\STAT.H>
\r
29 #include <shellapi.h>
\r
31 #include <WINNT/afsreg.h>
\r
32 #include <WINNT/afssw.h>
\r
33 #include <WINNT/talocale.h>
\r
35 #include "resource.h"
\r
36 #include "progress_dlg.h"
\r
38 #include "forceremove.h"
\r
42 * PROTOTYPES _________________________________________________________________
\r
45 static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered);
\r
46 BOOL UninstallCredsTool();
\r
47 BOOL ServerSpecificUninstall();
\r
48 BOOL ClientSpecificUninstall();
\r
53 * DEFINITIONS _________________________________________________________________
\r
56 #define SUCALLCONV WINAPI
\r
58 #define UNINSTALL_TEMP_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsUninstallTempInfo"
\r
59 #define INSTALL_DIR_VALUE_NAME "InstallDir"
\r
61 #define AFS_PRESERVED_CFG_INFO_KEY "HKEY_LOCAL_MACHINE\\Software\\AfsPreservedConfigInfo"
\r
63 #define MS_SHARED_FILES_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs"
\r
65 // Log file to use when running in silent mode
\r
66 #define UNINSTALL_ERROR_LOG_NAME "\\AfsUninstallErrorLog.txt"
\r
67 #define INSTALL_ERROR_LOG_NAME "\\AfsInstallErrorLog.txt"
\r
69 #define TARGETDIR "<TARGETDIR>"
\r
70 #define WINDIR "<WINDIR>"
\r
71 #define WINSYSDIR "<WINSYSDIR>"
\r
73 #define WIN9X_START_MENU_REG_KEY "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
\r
74 #define WIN9X_START_MENU_REG_VALUE "Programs"
\r
76 #define WINNT_START_MENU_REG_KEY "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
\r
77 #define WINNT_START_MENU_REG_VALUE "Common Programs"
\r
79 #define LOCALE_ID_LEN 4
\r
87 typedef BOOL (APP_UNINSTALL_FUNC)();
\r
97 char *pszSvcDependOn;
\r
98 char *pszSvcDisplayName;
\r
100 char *pszNetworkProviderOrder;
\r
102 // Message to use to tell the user that we have to stop the service
\r
103 int nServiceShutdownMsgID;
\r
105 // Message to use for the progress dialog that is shown while
\r
106 // waiting for the service to stop.
\r
107 int nServiceShutdownProgressMsgID;
\r
109 // Location in registry of a key we can use to know that the app is installed
\r
112 // Location in registry of this app's install dir
\r
113 struct REGVALUE regInstallDir;
\r
116 char *pszLocalRoot; // The root dir below the install dir
\r
117 char *pszBinPath; // Path to remove from the system path
\r
119 // Generated files and directories to delete. These are both multistring lists.
\r
120 char *pszDirsToDel; // All files in these dirs will be deleted
\r
121 char *pszFilesToDel; // Use this if you want to delete files but leave the dir. Wildcards can be used.
\r
123 // Registry values to remove
\r
124 struct REGVALUE *pRegValues;
\r
125 struct REGVALUE *pWinNTRegValues; // Only remove these if running WinNT
\r
126 struct REGVALUE *pWin9XRegValues; // Only remove these if running Win9X
\r
128 // Start menu entries to delete
\r
129 char *pszStartMenuEntries;
\r
131 // Registry keys to save if a user wants to preserve config info during uninstall
\r
132 char *pszRegKeysToPreserve;
\r
133 int nPreserveConfigInfoMsgID;
\r
135 // Uninstall func - used for things specific to this app
\r
136 APP_UNINSTALL_FUNC *pUninstallFunc;
\r
141 * App info structure for the Server product
\r
143 struct APPINFO appServer = {
\r
146 AFSREG_SVR_SVC_NAME,
\r
147 AFSREG_SVR_SVC_KEY,
\r
149 AFSREG_SVR_SVC_DISPLAYNAME_DATA,
\r
151 0, // No network provider order
\r
153 IDS_MUST_STOP_SERVER,
\r
154 IDS_WAITING_FOR_SERVER_TO_STOP,
\r
156 AFSREG_SVR_SW_VERSION_KEY,
\r
158 { AFSREG_SVR_SW_VERSION_KEY, AFSREG_SVR_SW_VERSION_DIR_VALUE },
\r
164 TARGETDIR"\\Server\\usr\\afs\\bin\\backup\0"
\r
165 TARGETDIR"\\Server\\usr\\afs\\bin\0"
\r
166 TARGETDIR"\\Server\\usr\\afs\\db\0"
\r
167 TARGETDIR"\\Server\\usr\\afs\\logs\0"
\r
168 TARGETDIR"\\Server\\usr\\afs\\etc\0"
\r
169 TARGETDIR"\\Server\\usr\\afs\\local\0"
\r
170 TARGETDIR"\\Server\\usr\\afs\0"
\r
171 TARGETDIR"\\Server\\usr\0",
\r
174 TARGETDIR"\\Common\\*.gid\0"
\r
175 TARGETDIR"\\Common\\*.fts\0",
\r
177 0, // No reg values
\r
178 0, // No NT only reg values
\r
179 0, // No 9x only reg values
\r
183 // Config info to preserve
\r
184 AFSREG_SVR_SVC_KEY"\0",
\r
185 IDS_PRESERVE_SERVER_CONFIG_INFO,
\r
187 0 // No special uninstall function
\r
190 // Registry values to remove for the Client
\r
191 struct REGVALUE clientRegValues[] = {
\r
192 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", "{DC515C27-6CAC-11D1-BAE7-00C04FD140D2}" },
\r
193 { 0, 0 } // This indicates there are no more entries
\r
196 struct REGVALUE clientWinNTRegValues[] = {
\r
197 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\File Manager\\AddOns", "AFS Client FME" },
\r
201 struct REGVALUE clientWin9XRegValues[] = {
\r
202 { "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\NetworkProvider\\Order", "TransarcAFSDaemon" },
\r
207 * App info structure for the Client product
\r
209 struct APPINFO appClient = {
\r
212 AFSREG_CLT_SVC_NAME,
\r
213 AFSREG_CLT_SVC_KEY,
\r
214 "5250435353004E657462696F730000",
\r
215 AFSREG_CLT_SVC_DISPLAYNAME_DATA,
\r
217 AFSREG_CLT_SVC_NAME,
\r
219 IDS_MUST_STOP_CLIENT,
\r
220 IDS_WAITING_FOR_CLIENT_TO_STOP,
\r
222 AFSREG_CLT_SW_VERSION_KEY,
\r
224 { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },
\r
229 // No dirs to delete
\r
233 TARGETDIR"\\Common\\*.gid\0"
\r
234 TARGETDIR"\\Common\\*.fts\0"
\r
235 WINDIR"\\..\\AFSCache\0"
\r
236 WINDIR"\\afsd.log\0"
\r
237 WINDIR"\\afsd.ini\0"
\r
238 WINDIR"\\afsdsbmt.ini\0"
\r
239 WINDIR"\\afsd_init.log\0",
\r
242 clientWinNTRegValues,
\r
243 clientWin9XRegValues,
\r
245 // Start menu entries to remove
\r
248 // Config info to preserve
\r
249 AFSREG_CLT_SVC_KEY"\0",
\r
250 IDS_PRESERVE_CLIENT_CONFIG_INFO,
\r
252 ClientSpecificUninstall
\r
257 * App info structure for the Light Client product
\r
259 struct APPINFO appLightClient = {
\r
262 // No service info
\r
268 AFSREG_CLT_SVC_NAME,
\r
270 // No service shutdown messages
\r
274 "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Light Client",
\r
276 { AFSREG_CLT_SW_VERSION_KEY, AFSREG_CLT_SW_VERSION_DIR_VALUE },
\r
281 // No dirs to delete
\r
285 TARGETDIR"\\Common\\*.gid\0"
\r
286 TARGETDIR"\\Common\\*.fts\0",
\r
289 clientWinNTRegValues,
\r
290 clientWin9XRegValues,
\r
292 // Start menu entries to remove
\r
295 // Config info to preserve
\r
296 AFSREG_CLT_SVC_KEY"\0",
\r
297 IDS_PRESERVE_LIGHT_CLIENT_CONFIG_INFO,
\r
304 * App info structure for the Control Center product
\r
306 struct APPINFO appControlCenter = {
\r
307 "AFS Control Center",
\r
315 // No network provider order
\r
318 // No service shutdown messages
\r
322 "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center",
\r
324 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Control Center\\CurrentVersion", "PathName" },
\r
326 "\\Control Center",
\r
329 // No dirs to delete
\r
333 TARGETDIR"\\Common\\*.gid\0"
\r
334 TARGETDIR"\\Common\\*.fts\0",
\r
336 0, // No reg values
\r
337 0, // No NT only reg values
\r
338 0, // No 9x only reg values
\r
340 // Start menu entries to remove
\r
341 "Control Center\0",
\r
343 // Config info to preserve
\r
344 AFSREG_CLT_SVC_KEY"\0",
\r
345 IDS_PRESERVE_CC_CONFIG_INFO,
\r
347 0 // No uninstall function
\r
352 * App info structure for the Sys Admin Doc files
\r
354 struct APPINFO appDocs = {
\r
355 "AFS Supplemental Documentation",
\r
363 // No network provider order
\r
366 // No service shutdown messages
\r
370 "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation",
\r
372 { "HKEY_LOCAL_MACHINE\\SOFTWARE\\TransarcCorporation\\AFS Supplemental Documentation\\CurrentVersion", "PathName" },
\r
377 // No dirs to delete
\r
381 TARGETDIR"\\Common\\*.gid\0"
\r
382 TARGETDIR"\\Common\\*.fts\0",
\r
384 0, // No reg values
\r
385 0, // No NT only reg values
\r
386 0, // No 9x only reg values
\r
388 // Start menu entries to remove
\r
389 "Documentation\\AFS for Windows Backup Command Reference.lnk\0Documentation\\AFS Command Reference Manual.lnk\0Documentation\\AFS System Administrator's Guide.lnk\0",
\r
391 0, // No config info to preserve
\r
393 0 // No uninstall function
\r
397 // Shared and in-use files
\r
410 struct FILEINFO fileInfo[] = {
\r
411 { TARGETDIR"\\Common\\afsbosadmin.dll", SERVER | CC },
\r
412 { TARGETDIR"\\Common\\afscfgadmin.dll", SERVER | CC },
\r
413 { TARGETDIR"\\Common\\afsclientadmin.dll", SERVER | CLIENT | LCLIENT | CC },
\r
414 { TARGETDIR"\\Common\\afskasadmin.dll", SERVER | CC },
\r
415 { TARGETDIR"\\Common\\afsptsadmin.dll", SERVER | CC },
\r
416 { TARGETDIR"\\Common\\afsvosadmin.dll", SERVER | CC },
\r
417 { TARGETDIR"\\Common\\afsadminutil.dll", SERVER | CLIENT | LCLIENT | CC },
\r
418 { TARGETDIR"\\Common\\afsrpc.dll", SERVER | CLIENT | LCLIENT | CC },
\r
419 { TARGETDIR"\\Common\\afsauthent.dll", SERVER | CLIENT | LCLIENT | CC },
\r
420 { TARGETDIR"\\Common\\pthread.dll", SERVER | CLIENT | LCLIENT | CC },
\r
421 { TARGETDIR"\\Common\\TaAfsAppLib.dll", SERVER | CLIENT | LCLIENT | CC },
\r
422 { TARGETDIR"\\Common\\afsprocmgmt.dll", SERVER | CLIENT | LCLIENT },
\r
423 { TARGETDIR"\\Common\\afs_config.exe", CLIENT | LCLIENT| CC },
\r
424 { TARGETDIR"\\Common\\afseventmsg_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
425 { TARGETDIR"\\Common\\afslegal_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
426 { TARGETDIR"\\Common\\afsserver_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
427 { TARGETDIR"\\Common\\afssvrcfg_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
428 { TARGETDIR"\\Common\\TaAfsAccountManager_????.dll",SERVER | CLIENT | LCLIENT | CC },
\r
429 { TARGETDIR"\\Common\\TaAfsAppLib_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
430 { TARGETDIR"\\Common\\TaAfsServerManager_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
431 { TARGETDIR"\\Common\\afscreds_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
432 { TARGETDIR"\\Common\\afs_config_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
433 { TARGETDIR"\\Common\\afs_cpa_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
434 { TARGETDIR"\\Common\\afs_shl_ext_????.dll", SERVER | CLIENT | LCLIENT | CC },
\r
435 { TARGETDIR"\\Common\\afs-nt.hlp", SERVER | CLIENT | LCLIENT | CC },
\r
436 { TARGETDIR"\\Common\\afs-nt.cnt", SERVER | CLIENT | LCLIENT | CC },
\r
437 { TARGETDIR"\\Common\\taafssvrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },
\r
438 { TARGETDIR"\\Common\\taafssvrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },
\r
439 { TARGETDIR"\\Common\\taafsusrmgr.cnt", SERVER | CLIENT | LCLIENT | CC },
\r
440 { TARGETDIR"\\Common\\taafsusrmgr.hlp", SERVER | CLIENT | LCLIENT | CC },
\r
441 { TARGETDIR"\\Common\\afs-cc.cnt", SERVER | CLIENT | LCLIENT | CC },
\r
442 { TARGETDIR"\\Common\\afs-cc.hlp", SERVER | CLIENT | LCLIENT | CC },
\r
443 { TARGETDIR"\\Common\\afs-light.cnt", SERVER | CLIENT | LCLIENT | CC },
\r
444 { TARGETDIR"\\Common\\afs-light.hlp", SERVER | CLIENT | LCLIENT | CC },
\r
445 { TARGETDIR"\\Common\\taafscfg.cnt", SERVER | CLIENT | LCLIENT | CC },
\r
446 { TARGETDIR"\\Common\\taafscfg.hlp", SERVER | CLIENT | LCLIENT | CC },
\r
447 { TARGETDIR"\\Client\\PROGRAM\\afs_shl_ext.dll", CLIENT | LCLIENT },
\r
448 { TARGETDIR"\\Client\\PROGRAM\\libafsconf.dll", CLIENT | LCLIENT },
\r
449 { TARGETDIR"\\Client\\PROGRAM\\afslogon.dll", CLIENT },
\r
450 { TARGETDIR"\\Client\\PROGRAM\\afslog95.dll", LCLIENT },
\r
451 { TARGETDIR"\\Control Center\\TaAfsAdmSvr.exe", CC },
\r
452 { WINSYSDIR"\\afs_cpa.cpl", CLIENT | LCLIENT | CC },
\r
453 { WINSYSDIR"\\afsserver.cpl", SERVER },
\r
454 { TARGETDIR"\\Common\\afsdcell.ini", CLIENT | LCLIENT | CC },
\r
455 { TARGETDIR"\\Documentation\\Html\\banner.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
456 { TARGETDIR"\\Documentation\\Html\\books.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
457 { TARGETDIR"\\Documentation\\Html\\bot.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
458 { TARGETDIR"\\Documentation\\Html\\index.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
459 { TARGETDIR"\\Documentation\\Html\\index.htm", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
460 { TARGETDIR"\\Documentation\\Html\\next.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
461 { TARGETDIR"\\Documentation\\Html\\prev.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
462 { TARGETDIR"\\Documentation\\Html\\toc.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
463 { TARGETDIR"\\Documentation\\Html\\top.gif", SERVER | CLIENT | LCLIENT | CC | DOCS },
\r
464 { TARGETDIR"\\Documentation\\Html\\ReleaseNotes\\relnotes.htm",
\r
465 SERVER | CLIENT | LCLIENT | CC },
\r
466 { TARGETDIR"\\Documentation\\Html\\InstallGd\\afsnt35i.htm",
\r
467 SERVER | CLIENT | LCLIENT | CC },
\r
468 { 0, 0 } // End of list
\r
473 * VARIABLES _________________________________________________________________
\r
479 static BOOL bPreserveConfigInfo;
\r
480 static BOOL bSilentMode;
\r
481 static char *pszInstallDir;
\r
485 * FUNCTIONS _________________________________________________________________
\r
489 static BOOL UpgradeClientIntParm(HKEY hKey, char *pszOldParm, char *pszNewParm)
\r
492 LONG result = ERROR_SUCCESS;
\r
494 nData = GetPrivateProfileInt("AFS Client", pszOldParm, -1, "afsd.ini");
\r
496 result = RegSetValueEx(hKey, pszNewParm, 0, REG_DWORD, (BYTE *)&nData, sizeof(nData));
\r
498 return (result == ERROR_SUCCESS);
\r
501 static BOOL UpgradeClientStringParm(HKEY hKey, char *pszOldParm, char *pszNewParm)
\r
504 LONG result = ERROR_SUCCESS;
\r
506 GetPrivateProfileString("AFS Client", pszOldParm, "", szData, sizeof(szData), "afsd.ini");
\r
508 result = RegSetValueEx(hKey, pszNewParm, 0, REG_SZ, (PBYTE)szData, strlen(szData) + 1);
\r
510 return (result == ERROR_SUCCESS);
\r
513 int SUCALLCONV Upgrade34ClientConfigInfo()
\r
519 result = RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_CLT_SVC_PARAM_KEY, KEY_WRITE, TRUE, &hKey, 0);
\r
520 if (result != ERROR_SUCCESS)
\r
523 UpgradeClientIntParm(hKey, "CacheSize", "CacheSize");
\r
524 UpgradeClientIntParm(hKey, "Stats", "Stats");
\r
525 UpgradeClientIntParm(hKey, "LogoffTokenTransfer", "LogoffTokenTransfer");
\r
526 UpgradeClientIntParm(hKey, "LogoffTokenTransferTimeout", "LogoffTokenTransferTimeout");
\r
527 UpgradeClientIntParm(hKey, "TrapOnPanic", "TrapOnPanic");
\r
528 UpgradeClientIntParm(hKey, "TraceBufferSize", "TraceBufferSize");
\r
529 UpgradeClientIntParm(hKey, "TraceOnShutdown", "TraceOnShutdown");
\r
530 UpgradeClientIntParm(hKey, "ReportSessionStartups", "ReportSessionStartups");
\r
532 UpgradeClientStringParm(hKey, "MountRoot", "MountRoot");
\r
533 UpgradeClientStringParm(hKey, "Cell", "Cell");
\r
535 /* BlockSize to ChunkSize requires convertion */
\r
536 nData = GetPrivateProfileInt("AFS Client", "BlockSize", -1, "afsd.ini");
\r
539 for (chunkSize = 0; (1 << chunkSize) < nData; chunkSize++);
\r
540 (void) RegSetValueEx(hKey, "ChunkSize", 0, REG_DWORD, (BYTE *)&chunkSize, sizeof(chunkSize));
\r
548 int SUCALLCONV Eradicate34Client()
\r
550 if (Client34Eradicate(TRUE) != ERROR_SUCCESS)
\r
556 // This function was written a long time ago by Mike Comer for use by the
\r
557 // original DFS Client for NT install program.
\r
558 int SUCALLCONV CheckIfAdmin(void)
\r
560 HANDLE token = INVALID_HANDLE_VALUE;
\r
563 DWORD realBufLength;
\r
564 TOKEN_PRIMARY_GROUP *pgroup;
\r
565 TOKEN_GROUPS *groups;
\r
569 PSID AdministratorSID = NULL;
\r
570 SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_AUTHORITY;
\r
572 // allocate the SID for the Administrators group
\r
573 if (!AllocateAndInitializeSid(&authority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &AdministratorSID)) {
\r
574 status = GetLastError();
\r
578 // open the process token
\r
579 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &token)) {
\r
580 status = GetLastError();
\r
581 token = INVALID_HANDLE_VALUE;
\r
585 // check primary group first
\r
586 buffer = GlobalAlloc(GMEM_FIXED, sizeof(TOKEN_PRIMARY_GROUP));
\r
591 bufLength = sizeof(TOKEN_PRIMARY_GROUP);
\r
593 if (!GetTokenInformation(token, TokenPrimaryGroup, buffer, bufLength, &realBufLength)) {
\r
594 if (realBufLength > bufLength) {
\r
595 // not enough space
\r
596 GlobalFree(buffer);
\r
597 bufLength = realBufLength;
\r
598 buffer = GlobalAlloc(GMEM_FIXED, realBufLength);
\r
610 pgroup = (TOKEN_PRIMARY_GROUP *)buffer;
\r
611 if (EqualSid(pgroup->PrimaryGroup, AdministratorSID)) {
\r
614 // okay, try the secondary groups
\r
616 if (!GetTokenInformation(token, TokenGroups, buffer, bufLength, &realBufLength)) {
\r
617 if (realBufLength > bufLength) {
\r
618 // not enough space
\r
619 GlobalFree(buffer);
\r
620 bufLength = realBufLength;
\r
621 buffer = GlobalAlloc(GMEM_FIXED, realBufLength);
\r
634 // we have the list of groups here. Process them:
\r
635 groups = (TOKEN_GROUPS *)buffer;
\r
636 for(groupCount = 0; groupCount < groups->GroupCount; groupCount++) {
\r
637 if (EqualSid(groups->Groups[groupCount].Sid, AdministratorSID)) {
\r
646 if (token != INVALID_HANDLE_VALUE) {
\r
647 CloseHandle(token);
\r
651 GlobalFree(buffer);
\r
654 if (AdministratorSID) {
\r
655 FreeSid(AdministratorSID);
\r
661 static void SetSharedFileRefCount(char *pszFile, int nRefCount)
\r
666 result = RegOpenKeyAlt(AFSREG_NULL_KEY, MS_SHARED_FILES_KEY, KEY_WRITE, FALSE, &hKey, 0);
\r
667 if (result != ERROR_SUCCESS)
\r
670 if (nRefCount <= 0)
\r
671 RegDeleteValue(hKey, pszFile);
\r
673 RegSetValueEx(hKey, pszFile, 0, REG_DWORD, (BYTE *)&nRefCount, sizeof(int));
\r
678 static char *GetTimeStamp()
\r
680 char szTime[64], szDate[64];
\r
681 static char szTimeDate[128];
\r
686 sprintf(szTimeDate, "[%s %s] ", szTime, szDate);
\r
691 int SUCALLCONV WriteToInstallErrorLog(char *pszMsg)
\r
693 static BOOL bWritten = FALSE;
\r
696 // On the first write, recreate the file
\r
697 fp = fopen(INSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");
\r
701 fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);
\r
710 static void WriteToUninstallErrorLog(char *pszMsg)
\r
712 static BOOL bWritten = FALSE;
\r
715 // On the first write, recreate the file
\r
716 fp = fopen(UNINSTALL_ERROR_LOG_NAME, bWritten ? "a" : "w");
\r
720 fprintf(fp, "%s%s\r\n", GetTimeStamp(), pszMsg);
\r
727 static char *LoadResString(UINT uID)
\r
729 static char str[256];
\r
730 GetString (str, uID);
\r
734 static void ShowError(UINT nResID, LONG nError)
\r
737 char szPrompt[256];
\r
742 psz = LoadResString(nResID);
\r
744 strcpy(szErr, psz);
\r
746 sprintf(szErr, "unknown error msg (Msg ID = %d)", nResID);
\r
748 psz = LoadResString(IDS_INSTALLATION_FAILURE);
\r
749 strcpy(szPrompt, psz ? psz : "An error has occurred: %s (Last Error = %ld).");
\r
751 sprintf(szMsg, szPrompt, szErr, nError);
\r
753 psz = LoadResString(IDS_TITLE);
\r
754 strcpy(szTitle, psz ? psz : "AFS");
\r
757 WriteToUninstallErrorLog(szMsg);
\r
759 MessageBox(hDlg, szMsg, szTitle, MB_OK);
\r
762 static int ShowMsg(UINT nResID, int nType)
\r
767 psz = LoadResString(IDS_TITLE);
\r
768 strcpy(szTitle, psz ? psz : "AFS");
\r
770 return MessageBox(hDlg, LoadResString(nResID), szTitle, nType);
\r
773 static char *GetAppInstallDir(struct APPINFO *pApp, BOOL bRemembered)
\r
778 static char szInstallDir[256];
\r
783 pszKey = bRemembered ? UNINSTALL_TEMP_INFO_KEY : pApp->regInstallDir.pszKey;
\r
784 pszValue = bRemembered ? INSTALL_DIR_VALUE_NAME : pApp->regInstallDir.pszValue;
\r
786 dwSize = sizeof(szInstallDir);
\r
788 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
\r
789 if (nResult == ERROR_SUCCESS) {
\r
790 nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szInstallDir, &dwSize);
\r
794 if (nResult != ERROR_SUCCESS) {
\r
795 ShowError(IDS_CANT_DETERMINE_APP_PATH, nResult);
\r
799 FilepathNormalizeEx(szInstallDir, FPN_BACK_SLASHES);
\r
801 return szInstallDir;
\r
804 static BOOL DoesRegKeyExist(char *pszKey)
\r
809 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
\r
810 if (nResult == ERROR_SUCCESS) {
\r
818 static BOOL IsAppInstalled(struct APPINFO *pApp)
\r
820 return DoesRegKeyExist(pApp->pszAppKey);
\r
823 static void BuildShortPath(char *pszShortPath, UINT nShortPathLen, char *pszInstallDir, char *pszPath)
\r
825 strncpy(pszShortPath, pszInstallDir, nShortPathLen);
\r
826 strncat(pszShortPath, pszPath, nShortPathLen);
\r
828 GetShortPathName(pszShortPath, pszShortPath, nShortPathLen);
\r
831 static BOOL IsWin95()
\r
833 OSVERSIONINFO versionInformation;
\r
835 versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
\r
837 GetVersionEx(&versionInformation);
\r
839 if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
\r
840 (versionInformation.dwMinorVersion == 0))
\r
848 OSVERSIONINFO versionInformation;
\r
850 versionInformation.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
\r
852 GetVersionEx(&versionInformation);
\r
854 if ((versionInformation.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
\r
855 (versionInformation.dwMinorVersion == 10))
\r
861 static BOOL IsServiceInstalled(char *pszServiceKey)
\r
865 if (RegOpenKeyAlt(0, pszServiceKey, KEY_READ, FALSE, &hKey, 0) == ERROR_SUCCESS) {
\r
873 // If this fails in anyway we just return. No error is displayed.
\r
874 static void MakeSureServiceDoesNotExist(char *pszName)
\r
876 SC_HANDLE hServer = 0, hSCM = 0;
\r
877 SERVICE_STATUS status;
\r
879 hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
\r
881 hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS | DELETE);
\r
883 if (QueryServiceStatus(hServer, &status)) {
\r
884 if (status.dwCurrentState != SERVICE_STOPPED) {
\r
885 if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {
\r
886 CloseServiceHandle(hServer);
\r
887 CloseServiceHandle(hSCM);
\r
893 // Try to delete even if status query fails
\r
894 DeleteService(hServer);
\r
899 CloseServiceHandle(hServer);
\r
901 CloseServiceHandle(hSCM);
\r
904 static int InstallService(char *pszName, char *pszDependOn, char *pszDisplayName, char *pszServicePath, BOOL bInteractive)
\r
906 SC_HANDLE hServer = 0, hSCM;
\r
907 BOOL bRestoreOldConfig = FALSE;
\r
909 hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
\r
911 ShowError(IDS_SCM_OPEN_FAILED, GetLastError());
\r
915 /* This code is not used, but it could be handy in the future so I am keeping it here.
\r
917 // If the service exists, then we (most probably) are in the middle of an upgrade or reinstall.
\r
918 bRestoreOldConfig = IsServiceInstalled(pszName);
\r
920 if (bRestoreOldConfig) {
\r
921 hServer = OpenService(hSCM, pszName, SERVICE_ALL_ACCESS);
\r
922 if (!hServer || !ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0)) {
\r
923 ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, GetLastError());
\r
924 bRestoreOldConfig = FALSE;
\r
925 // Fall through to service creation below
\r
930 if (!bRestoreOldConfig) {
\r
931 DWORD dwServiceType;
\r
933 // If the service already exists, the create call will fail. This can
\r
934 // happen if uninstall failed (which is not infrequent). Making sure the
\r
935 // service does not exist makes it easier for a user to install over top of
\r
936 // a previously failed uninstall.
\r
937 MakeSureServiceDoesNotExist(pszName);
\r
939 dwServiceType = SERVICE_WIN32_OWN_PROCESS;
\r
941 dwServiceType |= SERVICE_INTERACTIVE_PROCESS;
\r
943 hServer = CreateService(hSCM, pszName, pszDisplayName,
\r
944 SERVICE_ALL_ACCESS, dwServiceType, SERVICE_AUTO_START,
\r
945 SERVICE_ERROR_NORMAL, pszServicePath, 0, 0, "RPCSS\0Netbios\0\0", 0, 0);
\r
948 ShowError(IDS_SERVICE_CREATE_FAILED, GetLastError());
\r
952 CloseServiceHandle(hServer);
\r
954 CloseServiceHandle(hSCM);
\r
959 int SUCALLCONV InstallServerService(char *pszServicePath)
\r
961 return InstallService(appServer.pszSvcName, 0, appServer.pszSvcDisplayName, pszServicePath, TRUE);
\r
964 int SUCALLCONV InstallClientService(char *pszServicePath)
\r
966 return InstallService(appClient.pszSvcName, appClient.pszSvcDependOn, appClient.pszSvcDisplayName, pszServicePath, FALSE);
\r
969 static int UninstallService(struct APPINFO *pAppInfo)
\r
971 SC_HANDLE hServer, hSCM;
\r
972 SERVICE_STATUS status;
\r
974 BOOL bServer = FALSE;
\r
975 BOOL bShowingProgressDlg = FALSE;
\r
977 hSCM = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
\r
979 ShowError(IDS_SCM_OPEN_FAILED, GetLastError());
\r
983 hServer = OpenService(hSCM, pAppInfo->pszSvcName, SERVICE_ALL_ACCESS | DELETE);
\r
985 ShowError(IDS_SERVICE_OPEN_FAILED, GetLastError());
\r
986 CloseServiceHandle(hSCM);
\r
990 if (!QueryServiceStatus(hServer, &status)) {
\r
991 ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());
\r
992 CloseServiceHandle(hServer);
\r
993 CloseServiceHandle(hSCM);
\r
997 if (status.dwCurrentState != SERVICE_STOPPED) {
\r
998 if (pAppInfo->nServiceShutdownMsgID) {
\r
999 if (!bSilentMode && (ShowMsg(pAppInfo->nServiceShutdownMsgID, MB_YESNO | MB_ICONQUESTION) == IDNO)) {
\r
1000 CloseServiceHandle(hServer);
\r
1001 CloseServiceHandle(hSCM);
\r
1007 bShowingProgressDlg = ShowProgressDialog(LoadResString(pAppInfo->nServiceShutdownProgressMsgID));
\r
1009 if (!ControlService(hServer, SERVICE_CONTROL_STOP, &status)) {
\r
1010 if (bShowingProgressDlg)
\r
1011 HideProgressDialog();
\r
1012 ShowError(IDS_SERVICE_STOP_FAILED, GetLastError());
\r
1013 CloseServiceHandle(hServer);
\r
1014 CloseServiceHandle(hSCM);
\r
1019 // Wait for the service to stop
\r
1020 while (status.dwCurrentState != SERVICE_STOPPED) {
\r
1021 // I stopped waiting on dwWaitHint because it seemed the wait hint was too long.
\r
1022 // The service would be stopped but we'd still be asleep for a long time yet.
\r
1023 Sleep(5000); //status.dwWaitHint);
\r
1025 if (!QueryServiceStatus(hServer, &status)) {
\r
1026 if (bShowingProgressDlg)
\r
1027 HideProgressDialog();
\r
1028 ShowError(IDS_SERVICE_QUERY_FAILED, GetLastError());
\r
1029 CloseServiceHandle(hServer);
\r
1030 CloseServiceHandle(hSCM);
\r
1035 // The service has been stopped
\r
1036 if (bShowingProgressDlg)
\r
1037 HideProgressDialog();
\r
1039 // This code to disable the service may be of use some day so I am keeping it here.
\r
1040 // bOk = ChangeServiceConfig(hServer, SERVICE_NO_CHANGE, SERVICE_DISABLED, SERVICE_NO_CHANGE, 0, 0, 0, 0, 0, 0, 0);
\r
1042 bOk = DeleteService(hServer);
\r
1045 ShowError(IDS_SERVICE_DELETE_FAILED, GetLastError());
\r
1047 CloseServiceHandle(hServer);
\r
1048 CloseServiceHandle(hSCM);
\r
1050 return (bOk ? 0 : -1);
\r
1053 int SUCALLCONV AddToNetworkProviderOrder(char *pszWhatToAdd)
\r
1055 return AddToProviderOrder(pszWhatToAdd) ? 0 : -1;
\r
1058 static int RemoveFromNetworkProviderOrder(char *pszWhatToDel)
\r
1060 return RemoveFromProviderOrder(pszWhatToDel) ? 0 : -1;
\r
1063 int SUCALLCONV AddToPath(char *pszPath)
\r
1065 return AddToSystemPath(pszPath) ? 0 : -1;
\r
1068 static int RemoveFromPath(char *pszPath)
\r
1070 return RemoveFromSystemPath(pszPath) ? 0 : -1;
\r
1073 static void RemoveFiles(char *pszFileSpec)
\r
1075 struct _finddata_t fileinfo;
\r
1077 char szDel[MAX_PATH];
\r
1078 char szDir[MAX_PATH];
\r
1081 strcpy(szDir, pszFileSpec);
\r
1082 p = strrchr(szDir, '\\');
\r
1086 hSearch = _findfirst(pszFileSpec, &fileinfo);
\r
1087 if (hSearch == -1)
\r
1091 if ((strcmp(fileinfo.name, ".") != 0) && (strcmp(fileinfo.name, "..") != 0)) {
\r
1092 sprintf(szDel, "%s\\%s", szDir, fileinfo.name);
\r
1093 DeleteFile(szDel);
\r
1096 if (_findnext(hSearch, &fileinfo) == -1)
\r
1100 _findclose(hSearch);
\r
1103 static void RemoveDir(char *pszDir)
\r
1105 char szFileSpec[MAX_PATH];
\r
1107 sprintf(szFileSpec, "%s\\*.*", pszDir);
\r
1109 RemoveFiles(szFileSpec);
\r
1110 RemoveDirectory(pszDir);
\r
1113 static void RemoveRegValues(struct REGVALUE *pRegValues)
\r
1115 struct REGVALUE *pCurValue;
\r
1122 for (pCurValue = pRegValues; pCurValue->pszKey; pCurValue++) {
\r
1123 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pCurValue->pszKey, KEY_ALL_ACCESS, FALSE, &hKey, 0);
\r
1125 if (nResult == ERROR_SUCCESS) {
\r
1126 nResult = RegDeleteValue(hKey, pCurValue->pszValue);
\r
1127 RegCloseKey(hKey);
\r
1130 if (nResult != ERROR_SUCCESS)
\r
1131 ShowError(IDS_REG_DELETE_VALUE_ERROR, nResult);
\r
1135 static BOOL UninstallCredsTool()
\r
1137 int nResult = WinExec("afscreds /uninstall", SW_HIDE);
\r
1139 if (nResult <= 31) {
\r
1140 if (nResult != ERROR_FILE_NOT_FOUND)
\r
1141 ShowError(IDS_CANT_UNINSTALL_AFSCREDS, nResult);
\r
1144 // Always return true. We don't want the uninstall to completely fail just
\r
1145 // because the creds tool didn't uninstall.
\r
1150 static char *GetTempDir()
\r
1153 static char szTempDir[MAX_PATH];
\r
1155 result = GetTempPath(sizeof(szTempDir) - 1, szTempDir);
\r
1162 static char *GetRootInstallDir()
\r
1165 static char szRootInstallDir[MAX_PATH] = "";
\r
1167 if (szRootInstallDir[0] == 0) {
\r
1168 strcpy(szRootInstallDir, pszInstallDir);
\r
1170 // Strip off the app specific part of the install dir
\r
1171 psz = strrchr(szRootInstallDir, '\\');
\r
1176 return szRootInstallDir;
\r
1179 static BOOL ClientSpecificUninstall()
\r
1183 // This function needs to do two things. First it needs to see if the server is
\r
1184 // installed, and if it is, ask the user if they really want to uninstall the
\r
1185 // client given that the server needs the client. Second, if we are uninstalling
\r
1186 // the client, we need to uninstall the creds tool.
\r
1188 if (!bSilentMode) {
\r
1189 if (IsAppInstalled(&appServer)) {
\r
1190 nChoice = ShowMsg(IDS_CLIENT_NEEDED_BY_SERVER, MB_ICONQUESTION | MB_YESNO);
\r
1191 if (nChoice == IDNO)
\r
1192 return FALSE; // Cancel the uninstall
\r
1196 UninstallCredsTool();
\r
1201 static struct APPINFO *GetApp()
\r
1203 #ifdef SERVER_UNINST
\r
1204 return &appServer;
\r
1205 #elif CLIENT_UNINST
\r
1206 return &appClient;
\r
1208 return &appControlCenter;
\r
1209 #elif LIGHT_CLIENT_UNINST
\r
1210 return &appLightClient;
\r
1218 static void RememberInstallDir(char *pszInstallDir)
\r
1222 // We remember the install dir so that when the UninstUninitialize function is called
\r
1223 // by the InstallShield uninstaller, we can find out where we were installed to. We
\r
1224 // have to do this because by the time that function is called, the registry values
\r
1225 // created at install time are already gone. We need to be able to find out where we
\r
1226 // were installed so we can clean up anything IS couldn't uninstall. If this fails in
\r
1227 // any way then we don't care. The only consequence is that some junk might be left on
\r
1228 // the users' system after an uninstall.
\r
1230 LONG result = RegOpenKeyAlt(AFSREG_NULL_KEY, UNINSTALL_TEMP_INFO_KEY, KEY_WRITE, TRUE, &hKey, 0);
\r
1231 if (result != ERROR_SUCCESS)
\r
1234 RegSetValueEx(hKey, INSTALL_DIR_VALUE_NAME, 0, REG_SZ, (PBYTE)pszInstallDir, strlen(pszInstallDir) + 1);
\r
1236 RegCloseKey(hKey);
\r
1239 int SUCALLCONV SetSilentMode()
\r
1241 bSilentMode = TRUE;
\r
1246 static char *GetWinDir()
\r
1248 static char szWinDir[MAX_PATH] = "";
\r
1250 if (!szWinDir[0])
\r
1251 GetWindowsDirectory(szWinDir, sizeof(szWinDir));
\r
1256 static char *GetWinSysDir()
\r
1258 static char szWinSysDir[MAX_PATH] = "";
\r
1260 if (!szWinSysDir[0])
\r
1261 GetSystemDirectory(szWinSysDir, sizeof(szWinSysDir));
\r
1263 return szWinSysDir;
\r
1266 static char *GetLocaleID()
\r
1268 static char szID[25] = "";
\r
1270 if (szID[0] == 0) {
\r
1271 LCID dwID = GetSystemDefaultLCID();
\r
1273 // Nuke the high word. It contains a sort ID.
\r
1274 dwID &= 0x0000FFFF;
\r
1276 // Convert locale ID to a string
\r
1277 itoa(dwID, szID, 10);
\r
1279 // This thing should never be more than LOCALE_ID_LEN characters long.
\r
1280 szID[LOCALE_ID_LEN] = 0;
\r
1286 static char *ExpandPath(char *pszFile)
\r
1288 static char szPath[MAX_PATH];
\r
1293 // Convert a path containing TARGETDIR, WINDIR, or WINSYSDIR to a
\r
1294 // real path in the file system. One of these MUST be the start of
\r
1295 // the file path passed in. Also convert the string ???? to an
\r
1296 // actual locale number.
\r
1297 if (strncmp(pszFile, TARGETDIR, strlen(TARGETDIR)) == 0)
\r
1298 strcpy(szPath, GetRootInstallDir());
\r
1299 else if (strncmp(pszFile, WINDIR, strlen(WINDIR)) == 0)
\r
1300 strcpy(szPath, GetWinDir());
\r
1301 else if (strncmp(pszFile, WINSYSDIR, strlen(WINSYSDIR)) == 0)
\r
1302 strcpy(szPath, GetWinSysDir());
\r
1305 psz = strchr(pszFile, '\\');
\r
1307 strcat(szPath, psz);
\r
1309 strcpy(szPath, pszFile);
\r
1311 // Is this a language dll?
\r
1312 psz = strstr(szPath, "????.");
\r
1314 // If it is, replace ???? with the locale number
\r
1316 strncpy(psz, GetLocaleID(), LOCALE_ID_LEN);
\r
1321 static BOOL FileNeededByOtherApp(struct APPINFO *pApp, struct FILEINFO *pFileInfo)
\r
1323 // If the file is used by the server, the app being uninstalled is not the server, and
\r
1324 // the server is installed, then this file is used by another app.
\r
1326 if ((pFileInfo->nUsedBy & LCLIENT) && (pApp != &appLightClient) && IsAppInstalled(&appLightClient))
\r
1331 if ((pFileInfo->nUsedBy & SERVER) && (pApp != &appServer) && IsAppInstalled(&appServer))
\r
1334 if ((pFileInfo->nUsedBy & CLIENT) && (pApp != &appClient) && IsAppInstalled(&appClient))
\r
1337 if ((pFileInfo->nUsedBy & CC) && (pApp != &appControlCenter) && IsAppInstalled(&appControlCenter))
\r
1343 static void DeleteInUseFiles(struct APPINFO *pAppInfo, struct FILEINFO *pFileInfo)
\r
1345 char szSrcPath[MAX_PATH];
\r
1346 char szDestPath[MAX_PATH];
\r
1347 char szTempDir[MAX_PATH];
\r
1350 // If some app's file has been loaded before the app is uninstalled, then
\r
1351 // when an uninstall is attempted, the application and all of the dlls that
\r
1352 // its uses will be in use and IS will not be able to delete them. Normally this
\r
1353 // is not a problem because IS will tell the user to reboot to finish the uninstall.
\r
1354 // However, we must support the ability to perform a silent uninstall followed
\r
1355 // immediatly by an install of the same product to the same directories. If we let
\r
1356 // IS handle the uninstall of these files, this is not possible. The reason is that
\r
1357 // when IS fails to remove these in use files, it marks them for deletion after the
\r
1358 // next reboot, which is fine. Unfortunately, it leaves them in the dirs they were
\r
1359 // installed to. So if we don't immediately reboot and perform an install to the
\r
1360 // same dirs, once a reboot is performed, those files get deleted and we have a
\r
1361 // broken installation.
\r
1363 // What we will do to fix all of this, is when the client is uninstalled, but
\r
1364 // before IS does anything, we will move the in use files and associated dlls
\r
1365 // into the temp dir and mark them for delete after a reboot. Then an install
\r
1366 // that follows will succeed.
\r
1368 // Delete the files that may be in use. If they are we actually move
\r
1369 // them to the temp dir and mark them for deletion after the next reboot.
\r
1370 for (ii = 0; pFileInfo[ii].pszName != 0; ii++) {
\r
1371 // Get the source path
\r
1372 strcpy(szSrcPath, ExpandPath(pFileInfo[ii].pszName));
\r
1374 // Only delete the file if it is not used by some other app
\r
1375 if (FileNeededByOtherApp(pAppInfo, &pFileInfo[ii]))
\r
1378 // If the file doesn't exist then go on to the next file.
\r
1379 if (_access(szSrcPath, 0) != 0)
\r
1382 // See if we can do a regular delete of the file
\r
1383 if (DeleteFile(szSrcPath)) {
\r
1384 SetSharedFileRefCount(szSrcPath, 0);
\r
1388 // Get a temp dir that is on the same drive as the src path.
\r
1389 // We can't move an in use file to a different drive.
\r
1390 strcpy(szTempDir, GetTempDir());
\r
1391 if (szTempDir[0] != szSrcPath[0]) {
\r
1392 // Get the drive, colon, and slash of the src path
\r
1393 strncpy(szTempDir, szSrcPath, 3);
\r
1397 // Get the dest path - we will rename the file during the move
\r
1398 GetTempFileName(szTempDir, "AFS", 0, szDestPath);
\r
1400 // Move from source to dest, marking the file for deletion after a reboot
\r
1402 if (MoveFile(szSrcPath, szDestPath)) {
\r
1403 WritePrivateProfileString("rename", szSrcPath, szDestPath, "wininit.ini");
\r
1404 SetSharedFileRefCount(szSrcPath, 0);
\r
1406 } else { // WinNT or Win98
\r
1407 if (MoveFileEx(szSrcPath, szDestPath, MOVEFILE_REPLACE_EXISTING)) {
\r
1408 SetFileAttributes(szDestPath, FILE_ATTRIBUTE_NORMAL);
\r
1409 MoveFileEx(szDestPath, 0, MOVEFILE_DELAY_UNTIL_REBOOT);
\r
1410 SetSharedFileRefCount(szSrcPath, 0);
\r
1416 // Delete a directory and all its files and subdirectories - Yee haaa!
\r
1417 static void RemoveDirectoryTree(char *pszDir)
\r
1420 WIN32_FIND_DATA findFileData;
\r
1421 char szSpec[MAX_PATH];
\r
1422 char szSubFileOrDir[MAX_PATH];
\r
1425 sprintf(szSpec, "%s\\*.*", pszDir);
\r
1427 // First delete the contents of the dir
\r
1428 hFind = FindFirstFile(szSpec, &findFileData);
\r
1429 bContinue = (hFind != INVALID_HANDLE_VALUE);
\r
1431 while (bContinue) {
\r
1432 if ((strcmp(findFileData.cFileName, ".") != 0) && (strcmp(findFileData.cFileName, "..") != 0)) {
\r
1433 sprintf(szSubFileOrDir, "%s\\%s", pszDir, findFileData.cFileName);
\r
1435 if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
\r
1436 RemoveDirectoryTree(szSubFileOrDir);
\r
1438 DeleteFile(szSubFileOrDir);
\r
1441 bContinue = FindNextFile(hFind, &findFileData);
\r
1446 // Now remove the dir
\r
1447 RemoveDirectory(pszDir);
\r
1450 static char *GetStartMenuRoot()
\r
1459 static char szStartMenuRoot[MAX_PATH] = "";
\r
1461 if (szStartMenuRoot[0] == 0) {
\r
1462 dwSize = sizeof(szStartMenuRoot);
\r
1465 pszKey = WINNT_START_MENU_REG_KEY;
\r
1466 pszValue = WINNT_START_MENU_REG_VALUE;
\r
1468 pszKey = WIN9X_START_MENU_REG_KEY;
\r
1469 pszValue = WIN9X_START_MENU_REG_VALUE;
\r
1472 nResult = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
\r
1473 if (nResult == ERROR_SUCCESS) {
\r
1474 nResult = RegQueryValueEx(hKey, pszValue, 0, &dwType, (PBYTE)szStartMenuRoot, &dwSize);
\r
1475 RegCloseKey(hKey);
\r
1478 if (nResult != ERROR_SUCCESS)
\r
1482 FilepathNormalizeEx(szStartMenuRoot, FPN_BACK_SLASHES);
\r
1484 return szStartMenuRoot;
\r
1487 static char *GetAfsStartMenuRoot()
\r
1489 static char szAfsStartMenuRoot[MAX_PATH] = "";
\r
1490 char *pszStartMenuRoot;
\r
1492 if (szAfsStartMenuRoot[0] == 0) {
\r
1493 pszStartMenuRoot = GetStartMenuRoot();
\r
1494 if (!pszStartMenuRoot)
\r
1498 sprintf(szAfsStartMenuRoot, "%s\\IBM WebSphere\\Performance Pack\\AFS", pszStartMenuRoot );
\r
1500 sprintf(szAfsStartMenuRoot, "%s\\IBM AFS", pszStartMenuRoot );
\r
1503 return szAfsStartMenuRoot;
\r
1506 static BOOL IsADir(char *pszName)
\r
1508 struct _stat statbuf;
\r
1510 if (_stat(pszName, &statbuf) < 0)
\r
1513 return statbuf.st_mode & _S_IFDIR;
\r
1516 static void DeleteStartMenuEntries(char *pszEntries)
\r
1518 char szStartMenuPath[MAX_PATH];
\r
1519 char *pszAfsStartMenuRoot;
\r
1520 char *pszCurEntry;
\r
1522 pszAfsStartMenuRoot = GetAfsStartMenuRoot();
\r
1524 if (!pszAfsStartMenuRoot)
\r
1527 for (pszCurEntry = pszEntries; *pszCurEntry; pszCurEntry += strlen(pszCurEntry) + 1) {
\r
1528 sprintf(szStartMenuPath, "%s\\%s", pszAfsStartMenuRoot, pszCurEntry);
\r
1529 if (IsADir(szStartMenuPath))
\r
1530 RemoveDirectoryTree(szStartMenuPath);
\r
1532 DeleteFile(szStartMenuPath);
\r
1536 static void RefreshStartMenu()
\r
1538 char *pszAfsStartMenuRoot;
\r
1539 char szTemp[MAX_PATH];
\r
1541 pszAfsStartMenuRoot = GetAfsStartMenuRoot();
\r
1542 if (!pszAfsStartMenuRoot)
\r
1545 sprintf(szTemp, "%s - Refresh Attempt", pszAfsStartMenuRoot);
\r
1547 // Deleting items from below the root level of the start menu does not
\r
1548 // cause it to refresh. In order that users can see changes without
\r
1549 // rebooting we will temporarily rename our root most entry, which
\r
1550 // does cause a refresh of the start menu.
\r
1551 MoveFileEx(pszAfsStartMenuRoot, szTemp, MOVEFILE_REPLACE_EXISTING);
\r
1552 MoveFileEx(szTemp, pszAfsStartMenuRoot, MOVEFILE_REPLACE_EXISTING);
\r
1555 static BOOL PreserveConfigInfo(struct APPINFO *pApp)
\r
1558 char szDestKey[256];
\r
1561 bPreserveConfigInfo = TRUE;
\r
1563 // If not in silent mode, ask user if they want to preserve the cfg info
\r
1564 if (!bSilentMode) {
\r
1565 int nChoice = ShowMsg(pApp->nPreserveConfigInfoMsgID, MB_ICONQUESTION | MB_YESNOCANCEL);
\r
1566 if (nChoice == IDCANCEL)
\r
1567 return FALSE; // Cancel the uninstall
\r
1568 else if (nChoice == IDNO) {
\r
1569 bPreserveConfigInfo = FALSE; // User doesn't want to preserve the config info
\r
1574 // Copy each reg key (and all of its subkeys and values) to another place in the registry.
\r
1575 for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {
\r
1576 if (!DoesRegKeyExist(pszRegKey))
\r
1579 // Create the destination path for the copy
\r
1580 sprintf(szDestKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);
\r
1583 result = RegDupKeyAlt(pszRegKey, szDestKey);
\r
1585 if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND)) {
\r
1586 // If the copy failed, then delete any copies that succeeded
\r
1587 sprintf(szDestKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
\r
1588 RegDeleteEntryAlt(szDestKey, REGENTRY_KEY);
\r
1593 // Remember the integrated login setting if this app supports that and it was turned on
\r
1594 if (pApp->pszNetworkProviderOrder) {
\r
1595 // Was integerated login turned on?
\r
1597 bOk = InNetworkProviderOrder(pApp->pszNetworkProviderOrder, &bOn);
\r
1600 sprintf(szDestKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
\r
1601 result = RegOpenKeyAlt(AFSREG_NULL_KEY, szDestKey, KEY_WRITE, TRUE, &hKey, 0);
\r
1602 // The existance of the key is a flag indicating that integrated login was turned on
\r
1603 RegCloseKey(hKey);
\r
1608 if ((result == ERROR_SUCCESS) || bSilentMode)
\r
1609 return TRUE; // Continue with uninstall
\r
1611 // Report the error and ask the user if they want to continue the uninstall
\r
1612 return (ShowMsg(IDS_SAVE_OF_CONFIG_INFO_FAILED, MB_ICONEXCLAMATION | MB_YESNO) == IDYES);
\r
1615 int SUCALLCONV RestoreConfigInfo(int nApp)
\r
1618 char szSrcKey[256];
\r
1619 struct APPINFO *pApp = 0;
\r
1620 BOOL bError = FALSE;
\r
1624 case SERVER: pApp = &appServer; break;
\r
1625 case CLIENT: pApp = &appClient; break;
\r
1626 case LCLIENT: pApp = &appLightClient; break;
\r
1627 case CC: pApp = &appControlCenter; break;
\r
1633 // Copy each reg key (and all of its subkeys and values) back to its original place in the registry.
\r
1634 for (pszRegKey = pApp->pszRegKeysToPreserve; *pszRegKey; pszRegKey += strlen(pszRegKey) + 1) {
\r
1635 // Create the source path for the copy
\r
1636 sprintf(szSrcKey, "%s\\%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName, pszRegKey);
\r
1638 if (!DoesRegKeyExist(szSrcKey))
\r
1641 // Try to restore as many of the keys as possible. Report any errors at the end.
\r
1644 result = RegDupKeyAlt(szSrcKey, pszRegKey);
\r
1645 if ((result != ERROR_SUCCESS) && (result != ERROR_FILE_NOT_FOUND))
\r
1649 // Restore integrated login if this app was using it
\r
1650 if (pApp->pszNetworkProviderOrder) {
\r
1651 // Check if integrated login was turned on. The IntegratedLogin key is a flag
\r
1652 // telling us that it was on. If the key does not exist, integrated login was
\r
1654 sprintf(szSrcKey, "%s\\%s\\IntegratedLogin", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
\r
1655 if (DoesRegKeyExist(szSrcKey)) {
\r
1656 if (!AddToProviderOrder(pApp->pszNetworkProviderOrder))
\r
1661 // Remove our saved copies of the config info
\r
1662 sprintf(szSrcKey, "%s\\%s", AFS_PRESERVED_CFG_INFO_KEY, pApp->pszAppName);
\r
1663 RegDeleteEntryAlt(szSrcKey, REGENTRY_KEY);
\r
1666 ShowError(IDS_RESTORE_OF_PREVIOUS_CONFIG_FAILED, 0);
\r
1671 static BOOL DoSubKeysExist(char *pszKey)
\r
1675 char *pszSubKeys = 0;
\r
1678 result = RegOpenKeyAlt(AFSREG_NULL_KEY, pszKey, KEY_READ, FALSE, &hKey, 0);
\r
1679 if (result != ERROR_SUCCESS)
\r
1682 result = RegEnumKeyAlt(hKey, &pszSubKeys);
\r
1683 RegCloseKey(hKey);
\r
1685 if (result != ERROR_SUCCESS)
\r
1698 * The following definitions are taken from richedit.h:
\r
1702 #define EM_SETBKGNDCOLOR (WM_USER + 67) // from Richedit.h
\r
1703 #define EM_STREAMIN (WM_USER + 73) // from Richedit.h
\r
1704 #define SF_RTF 0x0002
\r
1706 typedef DWORD (CALLBACK *EDITSTREAMCALLBACK)(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
\r
1708 typedef struct _editstream {
\r
1709 DWORD dwCookie; /* user value passed to callback as first parameter */
\r
1710 DWORD dwError; /* last error */
\r
1711 EDITSTREAMCALLBACK pfnCallback;
\r
1718 DWORD CALLBACK License_StreamText (DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
\r
1720 LPTSTR psz = (LPTSTR)dwCookie;
\r
1721 LONG cchAvail = lstrlen(psz);
\r
1722 if ((*pcb = min(cchAvail, cb)) != 0) {
\r
1723 memcpy (pbBuff, psz, *pcb);
\r
1724 memmove (psz, &psz[*pcb], cchAvail - *pcb + 1);
\r
1730 void License_OnInitDialog (HWND hDlg, LPTSTR pszFile)
\r
1732 // Open the license file and shove its text in our RichEdit control
\r
1735 if ((hFile = CreateFile (pszFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL)) != INVALID_HANDLE_VALUE) {
\r
1738 if ((cbText = GetFileSize (hFile, NULL)) != 0) {
\r
1740 LPTSTR abText = (LPTSTR)GlobalAlloc (GMEM_FIXED, cbText + 3);
\r
1743 if (ReadFile (hFile, abText, cbText, &cbRead, NULL)) {
\r
1744 abText[ cbRead ] = 0;
\r
1746 EDITSTREAM Stream;
\r
1747 memset (&Stream, 0x00, sizeof(Stream));
\r
1748 Stream.dwCookie = (DWORD)abText;
\r
1749 Stream.pfnCallback = License_StreamText;
\r
1751 SendDlgItemMessage (hDlg, IDC_TEXT, EM_STREAMIN, SF_RTF, (LPARAM)&Stream);
\r
1754 GlobalFree (abText);
\r
1757 CloseHandle (hFile);
\r
1760 // Make the control's background be gray
\r
1762 SendDlgItemMessage (hDlg, IDC_TEXT, EM_SETBKGNDCOLOR, FALSE, (LPARAM)GetSysColor(COLOR_BTNFACE));
\r
1765 BOOL CALLBACK License_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
\r
1768 case WM_INITDIALOG:
\r
1769 SetWindowLong (hDlg, DWL_USER, lp);
\r
1770 License_OnInitDialog (hDlg, (LPTSTR)lp);
\r
1774 switch (LOWORD(wp)) {
\r
1777 EndDialog (hDlg, LOWORD(wp));
\r
1781 TCHAR szDir[ MAX_PATH ];
\r
1782 GetCurrentDirectory (MAX_PATH, szDir);
\r
1783 ShellExecute (hDlg, TEXT("print"), (LPTSTR)GetWindowLong (hDlg, DWL_USER), NULL, szDir, SW_HIDE);
\r
1791 BOOL FindAfsInstallationPathByComponent (LPTSTR pszInstallationPath, LPTSTR pszComponent)
\r
1793 *pszInstallationPath = 0;
\r
1795 TCHAR szRegPath[ MAX_PATH ];
\r
1796 wsprintf (szRegPath, TEXT("Software\\TransarcCorporation\\%s\\CurrentVersion"), pszComponent);
\r
1799 if (RegOpenKey (HKEY_LOCAL_MACHINE, szRegPath, &hk) == 0) {
\r
1800 DWORD dwType = REG_SZ;
\r
1801 DWORD dwSize = MAX_PATH;
\r
1803 if (RegQueryValueEx (hk, TEXT("PathName"), NULL, &dwType, (PBYTE)pszInstallationPath, &dwSize) == 0) {
\r
1804 *(LPTSTR)FindBaseFileName (pszInstallationPath) = TEXT('\0');
\r
1806 if (pszInstallationPath[0] && (pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] == TEXT('\\')))
\r
1807 pszInstallationPath[ lstrlen(pszInstallationPath)-1 ] = TEXT('\0');
\r
1813 return !!*pszInstallationPath;
\r
1816 BOOL FindAfsInstallationPath (LPTSTR pszInstallationPath)
\r
1818 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Client")))
\r
1820 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Control Center")))
\r
1822 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Server")))
\r
1824 if (FindAfsInstallationPathByComponent (pszInstallationPath, TEXT("AFS Supplemental Documentation")))
\r
1829 HINSTANCE LoadRichTextControl (void)
\r
1832 if ((hInst = LoadLibrary ("riched20.dll")) != NULL)
\r
1834 if ((hInst = LoadLibrary ("riched32.dll")) != NULL)
\r
1836 if ((hInst = LoadLibrary ("riched.dll")) != NULL)
\r
1838 if ((hInst = LoadLibrary ("richedit.dll")) != NULL)
\r
1843 int SUCALLCONV ShowLicense (char *pszTarget, char *pszSource)
\r
1845 // If the license already lives on this user's machine, don't show
\r
1846 // it again. This only has to be done if the user has never
\r
1847 // accepted the license agreement before (it's part of the setup
\r
1848 // program, so it gets installed if they've accepted it).
\r
1850 // We were handed a relative path of the form:
\r
1851 // Documentation/html/license.rtf
\r
1853 // We'll need to find the AFS installation directory, in order to
\r
1854 // find that Documentation subtree.
\r
1856 BOOL fShowLicense = TRUE;
\r
1858 TCHAR szInstallationPath[ MAX_PATH ];
\r
1859 if (FindAfsInstallationPath (szInstallationPath)) {
\r
1860 TCHAR szLicensePath[ MAX_PATH ];
\r
1861 wsprintf (szLicensePath, TEXT("%s\\%s"), szInstallationPath, pszTarget);
\r
1863 if (GetFileAttributes (szLicensePath) != (DWORD)-1) {
\r
1864 fShowLicense = FALSE;
\r
1868 // Before we can show the license file, we have to prepare the RichEdit
\r
1869 // control. That means loading the appropriate library and calling its
\r
1870 // initialization functions.
\r
1872 HINSTANCE hRichEdit;
\r
1873 if ((hRichEdit = LoadRichTextControl()) != NULL) {
\r
1875 // If we must show the license, do so now. This is a modal dialog,
\r
1876 // so we'll know whether or not the user accepts the license.
\r
1878 if (ModalDialogParam (IDD_LICENSE, GetActiveWindow(), License_DlgProc, (LPARAM)pszSource) == IDCANCEL) {
\r
1879 // The user rejected the license; fail setup
\r
1883 FreeLibrary (hRichEdit);
\r
1886 // The user accepted the license, so we can continue with Setup.
\r
1887 // The license file is installed as part of Setup.
\r
1891 int SUCALLCONV UninstInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)
\r
1893 char szPath[MAX_PATH];
\r
1894 struct APPINFO *pAppInfo;
\r
1895 char *pszFile = 0;
\r
1896 char *pszSubDir = 0;
\r
1900 bSilentMode = !IsWindowVisible(hIS);
\r
1902 // Which app are we uninstalling?
\r
1903 pAppInfo = GetApp();
\r
1905 ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);
\r
1909 // Get the app's install dir
\r
1910 pszInstallDir = GetAppInstallDir(pAppInfo, FALSE);
\r
1911 if (!pszInstallDir)
\r
1914 // If this app has a custom uninstall func, call it here
\r
1915 if (pAppInfo->pUninstallFunc)
\r
1916 if (!pAppInfo->pUninstallFunc())
\r
1919 if (pAppInfo->pszRegKeysToPreserve)
\r
1920 if (!PreserveConfigInfo(pAppInfo))
\r
1923 // Unconfigure the service, if there is one for this app
\r
1924 if (pAppInfo->pszSvcKey) {
\r
1925 if (IsServiceInstalled(pAppInfo->pszSvcKey))
\r
1926 if (UninstallService(pAppInfo) == 1)
\r
1930 RememberInstallDir(pszInstallDir);
\r
1932 DeleteInUseFiles(pAppInfo, fileInfo);
\r
1934 // Remove the app's bin path from the system path
\r
1935 if (pAppInfo->pszBinPath) {
\r
1936 BuildShortPath(szPath, sizeof(szPath), pszInstallDir, pAppInfo->pszBinPath);
\r
1937 RemoveFromPath(szPath);
\r
1940 // Remove entry from NetworkProvider\Order key in registry
\r
1941 if (pAppInfo->pszNetworkProviderOrder)
\r
1942 RemoveFromNetworkProviderOrder(pAppInfo->pszNetworkProviderOrder);
\r
1944 // Remove any generated subdirectories
\r
1945 if (!bPreserveConfigInfo && pAppInfo->pszDirsToDel) {
\r
1946 for (pszSubDir = pAppInfo->pszDirsToDel; *pszSubDir; pszSubDir += strlen(pszSubDir) + 1)
\r
1947 RemoveDir(ExpandPath(pszSubDir));
\r
1950 // Remove any generated files
\r
1951 if (!bPreserveConfigInfo && pAppInfo->pszFilesToDel) {
\r
1952 for (pszFile = pAppInfo->pszFilesToDel; *pszFile; pszFile += strlen(pszFile) + 1)
\r
1953 RemoveFiles(ExpandPath(pszFile));
\r
1956 // Remove any registry values that IS can't handle
\r
1957 RemoveRegValues(pAppInfo->pRegValues);
\r
1959 RemoveRegValues(pAppInfo->pWinNTRegValues);
\r
1961 RemoveRegValues(pAppInfo->pWin9XRegValues);
\r
1963 // Remove the start menu entries for this app
\r
1964 if (pAppInfo->pszStartMenuEntries) {
\r
1965 DeleteStartMenuEntries(pAppInfo->pszStartMenuEntries);
\r
1966 RefreshStartMenu();
\r
1969 // Remove the install dir
\r
1970 RemoveDirectory(pszInstallDir);
\r
1975 void SUCALLCONV UninstUnInitialize(HWND hIS, HINSTANCE hIS5, long Reserved)
\r
1977 char *pszInstallDir;
\r
1978 char szDirPath[MAX_PATH];
\r
1980 struct APPINFO *pAppInfo;
\r
1982 // If we just uninstalled the last AFS app, then do some cleanup.
\r
1983 if (IsAppInstalled(&appServer) || IsAppInstalled(&appClient) ||
\r
1984 IsAppInstalled(&appControlCenter) || IsAppInstalled(&appLightClient) ||
\r
1985 IsAppInstalled(&appDocs))
\r
1990 bSilentMode = !IsWindowVisible(hIS);
\r
1992 // Which app did we just uninstall?
\r
1993 pAppInfo = GetApp();
\r
1995 ShowError(IDS_CANT_DETERMINE_PRODUCT, 0);
\r
1999 // Get the app's install dir
\r
2000 pszInstallDir = GetAppInstallDir(pAppInfo, TRUE);
\r
2001 if (!pszInstallDir)
\r
2004 // Remove the reg key we used to remember the app install dir
\r
2005 RegDeleteEntryAlt(UNINSTALL_TEMP_INFO_KEY, REGENTRY_KEY);
\r
2007 // Try to remove the reg key used to store config info, but only
\r
2008 // if there are no app config info sub keys present.
\r
2009 if (!DoSubKeysExist(AFS_PRESERVED_CFG_INFO_KEY))
\r
2010 RegDeleteEntryAlt(AFS_PRESERVED_CFG_INFO_KEY, REGENTRY_KEY);
\r
2012 // Remove the install dir
\r
2013 RemoveDirectory(pszInstallDir);
\r
2015 // Attempt to remove the install root and common directories. The are
\r
2016 // shared and so no single app knows to delete them.
\r
2018 // Strip off the app specific part of the install dir
\r
2019 psz = strrchr(pszInstallDir, '\\');
\r
2023 sprintf(szDirPath, "%s\\%s", pszInstallDir, "Common");
\r
2024 RemoveDirectory(szDirPath);
\r
2026 // Remove the Common directory from the system path
\r
2027 RemoveFromPath(szDirPath);
\r
2029 // Remove all of the documentation dirs
\r
2030 sprintf(szDirPath, "%s\\%s", pszInstallDir, "Documentation");
\r
2031 RemoveDirectoryTree(szDirPath);
\r
2033 // Ok, up to this point we have been removing files we know we
\r
2034 // created. However, after this point we are into the path
\r
2035 // that the user chose for our install root. The default for
\r
2036 // this is IBM/Afs, but they could have chosen anything,
\r
2037 // including a dir or dirs that have other products in them.
\r
2038 // We will check to see if it is IBM\AFS and if it is then we
\r
2039 // will attempt to remove them.
\r
2041 // Back up a level and look for AFS
\r
2042 psz = strrchr(pszInstallDir, '\\');
\r
2044 if (stricmp(psz + 1, "AFS") == 0) {
\r
2045 RemoveDirectory(pszInstallDir);
\r
2050 // Back up a level and look for IBM
\r
2051 psz = strrchr(pszInstallDir, '\\');
\r
2053 if (stricmp(psz + 1, "IBM") == 0) {
\r
2054 RemoveDirectory(pszInstallDir);
\r
2059 // Remove the root afs start menu entry
\r
2060 psz = GetStartMenuRoot();
\r
2062 if (bSilentMode) {
\r
2063 // Remove everything under our branch
\r
2064 sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack\\AFS", psz);
\r
2065 RemoveDirectoryTree(szDirPath);
\r
2067 // Remove the IBM stuff only if the dirs are empty
\r
2068 sprintf(szDirPath, "%s\\IBM WebSphere\\Performance Pack", psz);
\r
2069 if (RemoveDirectory(szDirPath)) {
\r
2070 sprintf(szDirPath, "%s\\IBM WebSphere", psz);
\r
2071 RemoveDirectory(szDirPath);
\r
2074 sprintf(szDirPath, "%s\\IBM AFS", psz);
\r
2075 RemoveDirectoryTree(szDirPath);
\r
2080 BOOLEAN _stdcall DllEntryPoint(HANDLE dll, DWORD reason, PVOID reserved)
\r
2082 if (reason == DLL_PROCESS_ATTACH) {
\r
2083 hinst = (HINSTANCE)dll;
\r
2084 TaLocale_LoadCorrespondingModuleByName (hinst, "afs_setup_utils.dll");
\r
2090 extern "C" int WINAPI Test (HINSTANCE hInst, HINSTANCE hPrev, LPSTR psz, int nCmdShow)
\r
2092 ShowLicense ("TEST", "\\\\fury\\afssetup\\license\\ja_JP.rtf");
\r