You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
910 lines
23 KiB
910 lines
23 KiB
|
|
#include "stdafx.h"
|
|
|
|
#include "userenv.h"
|
|
#include "userenvp.h"
|
|
|
|
#include "shlobj.h"
|
|
#include "utils.h"
|
|
|
|
#include "mddefw.h"
|
|
#include "mdkey.h"
|
|
|
|
#include "wizpages.h"
|
|
|
|
#include "ocmanage.h"
|
|
#include "setupapi.h"
|
|
#include "k2suite.h"
|
|
|
|
extern OCMANAGER_ROUTINES gHelperRoutines;
|
|
|
|
DWORD GetUnattendedMode(HANDLE hUnattended, LPCTSTR szSubcomponent)
|
|
{
|
|
BOOL b = FALSE;
|
|
TCHAR szLine[1024];
|
|
DWORD dwMode = SubcompUseOcManagerDefault;
|
|
CString csMsg;
|
|
|
|
csMsg = _T("GetUnattendedMode ");
|
|
csMsg += szSubcomponent;
|
|
csMsg += _T("\n");
|
|
DebugOutput((LPCTSTR)csMsg);
|
|
|
|
// Try to get the line of interest
|
|
if (hUnattended && (hUnattended != INVALID_HANDLE_VALUE))
|
|
{
|
|
b = SetupGetLineText(NULL, hUnattended, _T("Components"),
|
|
szSubcomponent, szLine, sizeof(szLine)/sizeof(szLine[0]), NULL);
|
|
if (b)
|
|
{
|
|
csMsg = szSubcomponent;
|
|
csMsg += _T(" = ");
|
|
csMsg += szLine;
|
|
csMsg += _T("\n");
|
|
DebugOutput((LPCTSTR)csMsg);
|
|
|
|
// Parse the line
|
|
if (!lstrcmpi(szLine, _T("on")))
|
|
{
|
|
dwMode = SubcompOn;
|
|
}
|
|
else if (!lstrcmpi(szLine, _T("off")))
|
|
{
|
|
dwMode = SubcompOff;
|
|
}
|
|
else if (!lstrcmpi(szLine, _T("default")))
|
|
{
|
|
dwMode = SubcompUseOcManagerDefault;
|
|
}
|
|
}
|
|
else
|
|
DebugOutput(_T("SetupGetLineText failed."));
|
|
}
|
|
|
|
return(dwMode);
|
|
}
|
|
|
|
DWORD GetUnattendedModeFromSetupMode(
|
|
HANDLE hUnattended,
|
|
DWORD dwComponent,
|
|
LPCTSTR szSubcomponent)
|
|
{
|
|
BOOL b = FALSE;
|
|
TCHAR szProperty[64];
|
|
TCHAR szLine[1024];
|
|
DWORD dwMode = SubcompUseOcManagerDefault;
|
|
DWORD dwSetupMode;
|
|
|
|
DebugOutput(_T("GetUnattendedModeFromSetupMode %s"), szSubcomponent);
|
|
|
|
// Try to get the line of interest
|
|
if (hUnattended && (hUnattended != INVALID_HANDLE_VALUE))
|
|
{
|
|
dwSetupMode = GetIMSSetupMode();
|
|
switch (dwSetupMode)
|
|
{
|
|
case IIS_SETUPMODE_MINIMUM:
|
|
case IIS_SETUPMODE_TYPICAL:
|
|
case IIS_SETUPMODE_CUSTOM:
|
|
// One of the fresh modes
|
|
lstrcpy(szProperty, _T("FreshMode"));
|
|
break;
|
|
|
|
case IIS_SETUPMODE_UPGRADEONLY:
|
|
case IIS_SETUPMODE_ADDEXTRACOMPS:
|
|
// One of the upgrade modes
|
|
lstrcpy(szProperty, _T("UpgradeMode"));
|
|
break;
|
|
|
|
case IIS_SETUPMODE_ADDREMOVE:
|
|
case IIS_SETUPMODE_REINSTALL:
|
|
case IIS_SETUPMODE_REMOVEALL:
|
|
// One of the maintenance modes
|
|
lstrcpy(szProperty, _T("MaintenanceMode"));
|
|
break;
|
|
|
|
default:
|
|
// Error! Use defaults
|
|
return(SubcompUseOcManagerDefault);
|
|
}
|
|
|
|
// Get the specified line
|
|
b = SetupGetLineText(
|
|
NULL,
|
|
hUnattended,
|
|
_T("Global"),
|
|
szProperty,
|
|
szLine,
|
|
sizeof(szLine)/sizeof(szLine[0]),
|
|
NULL);
|
|
if (b)
|
|
{
|
|
DWORD dwOriginalMode;
|
|
|
|
DebugOutput(_T("%s = %s"), szProperty, szLine);
|
|
|
|
// See which setup mode we will end up with
|
|
if (!lstrcmpi(szLine, _T("Minimal")))
|
|
dwSetupMode = IIS_SETUPMODE_MINIMUM;
|
|
else if (!lstrcmpi(szLine, _T("Typical")))
|
|
dwSetupMode = IIS_SETUPMODE_TYPICAL;
|
|
else if (!lstrcmpi(szLine, _T("Custom")))
|
|
dwSetupMode = IIS_SETUPMODE_CUSTOM;
|
|
else if (!lstrcmpi(szLine, _T("AddRemove")))
|
|
dwSetupMode = IIS_SETUPMODE_ADDREMOVE;
|
|
else if (!lstrcmpi(szLine, _T("RemoveAll")))
|
|
dwSetupMode = IIS_SETUPMODE_REMOVEALL;
|
|
else if (!lstrcmpi(szLine, _T("UpgradeOnly")))
|
|
dwSetupMode = IIS_SETUPMODE_UPGRADEONLY;
|
|
else if (!lstrcmpi(szLine, _T("AddExtraComps")))
|
|
dwSetupMode = IIS_SETUPMODE_ADDEXTRACOMPS;
|
|
else
|
|
return(SubcompUseOcManagerDefault);
|
|
|
|
// Get the custom unattended setting
|
|
dwMode = GetUnattendedMode(hUnattended, szSubcomponent);
|
|
|
|
// Do the right thing based on the setup mode
|
|
SetIMSSetupMode(dwSetupMode);
|
|
switch (dwSetupMode)
|
|
{
|
|
case IIS_SETUPMODE_MINIMUM:
|
|
case IIS_SETUPMODE_TYPICAL:
|
|
// Minimum & typical means the same:
|
|
// Install all for SMTP, none for NNTP
|
|
DebugOutput(_T("Unattended mode is MINIMUM/TYPICAL"));
|
|
if (dwComponent == MC_IMS)
|
|
dwMode = SubcompOn;
|
|
else
|
|
dwMode = SubcompOff;
|
|
break;
|
|
|
|
case IIS_SETUPMODE_CUSTOM:
|
|
// For custom we use the custom setting
|
|
DebugOutput(_T("Unattended mode is CUSTOM"));
|
|
break;
|
|
|
|
case IIS_SETUPMODE_UPGRADEONLY:
|
|
// Return the original state
|
|
DebugOutput(_T("Unattended mode is UPGRADEONLY"));
|
|
dwMode = gHelperRoutines.QuerySelectionState(
|
|
gHelperRoutines.OcManagerContext,
|
|
szSubcomponent,
|
|
OCSELSTATETYPE_ORIGINAL) ? SubcompOn : SubcompOff;
|
|
break;
|
|
|
|
case IIS_SETUPMODE_ADDEXTRACOMPS:
|
|
// Turn it on only if the old state is off and the
|
|
// custom state is on
|
|
DebugOutput(_T("Unattended mode is ADDEXTRACOMPS"));
|
|
dwOriginalMode = gHelperRoutines.QuerySelectionState(
|
|
gHelperRoutines.OcManagerContext,
|
|
szSubcomponent,
|
|
OCSELSTATETYPE_ORIGINAL) ? SubcompOn : SubcompOff;
|
|
if (dwOriginalMode == SubcompOff &&
|
|
dwMode == SubcompOn)
|
|
dwMode = SubcompOn;
|
|
else
|
|
dwMode = dwOriginalMode;
|
|
break;
|
|
|
|
case IIS_SETUPMODE_ADDREMOVE:
|
|
// Return the custom setting
|
|
DebugOutput(_T("Unattended mode is ADDREMOVE"));
|
|
break;
|
|
|
|
case IIS_SETUPMODE_REMOVEALL:
|
|
// Kill everything
|
|
DebugOutput(_T("Unattended mode is REMOVEALL"));
|
|
dwMode = SubcompOff;
|
|
break;
|
|
}
|
|
|
|
DebugOutput(_T("Unattended state for %s is %s"),
|
|
szSubcomponent,
|
|
(dwMode == SubcompOn)?_T("ON"):_T("OFF"));
|
|
}
|
|
else
|
|
{
|
|
if (GetLastError() != ERROR_LINE_NOT_FOUND)
|
|
DebugOutput(_T("SetupGetLineText failed (%x)."), GetLastError());
|
|
}
|
|
}
|
|
|
|
return(dwMode);
|
|
}
|
|
|
|
BOOL DetectExistingSmtpServers()
|
|
{
|
|
// Detect other mail servers
|
|
CRegKey regMachine = HKEY_LOCAL_MACHINE;
|
|
|
|
// System\CurrentControlSet\Services\MsExchangeIMC\Parameters
|
|
CRegKey regSMTPParam( regMachine, REG_EXCHANGEIMCPARAMETERS, KEY_READ );
|
|
if ((HKEY) regSMTPParam )
|
|
{
|
|
CString csCaption;
|
|
|
|
DebugOutput(_T("IMC detected, suppressing SMTP"));
|
|
|
|
if (!theApp.m_fIsUnattended && !theApp.m_fNTGuiMode)
|
|
{
|
|
MyLoadString(IDS_MESSAGEBOX_TEXT, csCaption);
|
|
PopupOkMessageBox(IDS_SUPPRESS_SMTP, csCaption);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
DebugOutput(_T("No other SMTP servers detected, installing IMS."));
|
|
return(FALSE);
|
|
}
|
|
|
|
BOOL DetectExistingIISADMIN()
|
|
{
|
|
//
|
|
// Detect is IISADMIN service exists
|
|
//
|
|
// This is to make sure we don't do any metabase operation if
|
|
// IISADMIN doesn't exists, especially in the uninstall cases.
|
|
//
|
|
DWORD dwStatus = 0;
|
|
dwStatus = InetQueryServiceStatus(SZ_MD_SERVICENAME);
|
|
if (0 == dwStatus)
|
|
{
|
|
// some kind of error occur during InetQueryServiceStatus.
|
|
DebugOutput(_T("DetectExistingIISADMIN() return FALSE"));
|
|
return (FALSE);
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL InsertSetupString( LPCSTR REG_PARAMETERS )
|
|
{
|
|
// set up registry values
|
|
CRegKey regMachine = HKEY_LOCAL_MACHINE;
|
|
|
|
// System\CurrentControlSet\Services\NNTPSVC\Parameters
|
|
CRegKey regParam( (LPCTSTR) REG_PARAMETERS, regMachine );
|
|
if ((HKEY) regParam) {
|
|
regParam.SetValue( _T("MajorVersion"), (DWORD)STAXNT5MAJORVERSION );
|
|
regParam.SetValue( _T("MinorVersion"), (DWORD)STAXNT5MINORVERSION );
|
|
regParam.SetValue( _T("InstallPath"), theApp.m_csPathInetsrv );
|
|
|
|
switch (theApp.m_eNTOSType) {
|
|
case OT_NTW:
|
|
regParam.SetValue( _T("SetupString"), REG_SETUP_STRING_NT5WKSB3 );
|
|
break;
|
|
|
|
default:
|
|
_ASSERT(!"Unknown OS type");
|
|
// Fall through
|
|
|
|
case OT_NTS:
|
|
case OT_PDC_OR_BDC:
|
|
case OT_PDC:
|
|
case OT_BDC:
|
|
regParam.SetValue( _T("SetupString"), REG_SETUP_STRING_NT5SRVB3 );
|
|
break;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Scans a multi-sz and finds the first occurrence of the
|
|
// specified string
|
|
LPTSTR ScanMultiSzForSz(LPTSTR szMultiSz, LPTSTR szSz)
|
|
{
|
|
LPTSTR lpTemp = szMultiSz;
|
|
|
|
do
|
|
{
|
|
if (!lstrcmpi(lpTemp, szSz))
|
|
return(lpTemp);
|
|
|
|
lpTemp += lstrlen(lpTemp);
|
|
lpTemp++;
|
|
|
|
} while (*lpTemp != _T('\0'));
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
// Removes the said string from a MultiSz
|
|
// This places a lot of faith in the caller!
|
|
void RemoveSzFromMultiSz(LPTSTR szSz)
|
|
{
|
|
LPTSTR lpScan = szSz;
|
|
TCHAR tcLastChar;
|
|
|
|
lpScan += lstrlen(szSz);
|
|
lpScan++;
|
|
|
|
tcLastChar = _T('x');
|
|
while ((tcLastChar != _T('\0')) ||
|
|
(*lpScan != _T('\0')))
|
|
{
|
|
tcLastChar = *lpScan;
|
|
*szSz++ = *lpScan++;
|
|
}
|
|
|
|
*szSz++ = _T('\0');
|
|
|
|
// Properly terminate it if it's the last one
|
|
if (*lpScan == _T('\0'))
|
|
*szSz = _T('\0');
|
|
}
|
|
|
|
// This walks the multi-sz and returns a pointer between
|
|
// the last string of a multi-sz and the second terminating
|
|
// NULL
|
|
LPTSTR GetEndOfMultiSz(LPTSTR szMultiSz)
|
|
{
|
|
LPTSTR lpTemp = szMultiSz;
|
|
|
|
do
|
|
{
|
|
lpTemp += lstrlen(lpTemp);
|
|
lpTemp++;
|
|
|
|
} while (*lpTemp != _T('\0'));
|
|
|
|
return(lpTemp);
|
|
}
|
|
|
|
// This appends a string to the end of a multi-sz
|
|
// The buffer must be long enough
|
|
BOOL AppendSzToMultiSz(LPTSTR szMultiSz, LPTSTR szSz, DWORD dwMaxSize)
|
|
{
|
|
LPTSTR szTemp = szMultiSz;
|
|
DWORD dwLength = lstrlen(szSz);
|
|
|
|
// If the string is empty, do not append!
|
|
if (*szMultiSz == _T('\0') &&
|
|
*(szMultiSz + 1) == _T('\0'))
|
|
szTemp = szMultiSz;
|
|
else
|
|
{
|
|
szTemp = GetEndOfMultiSz(szMultiSz);
|
|
dwLength += (DWORD)(szTemp - szMultiSz);
|
|
}
|
|
|
|
if (dwLength >= dwMaxSize)
|
|
return(FALSE);
|
|
|
|
lstrcpy(szTemp, szSz);
|
|
szMultiSz += dwLength;
|
|
*szMultiSz = _T('\0');
|
|
*(szMultiSz + 1) = _T('\0');
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL AddServiceToDispatchList(LPTSTR szServiceName)
|
|
{
|
|
TCHAR szMultiSz[4096];
|
|
DWORD dwSize = 4096;
|
|
|
|
CRegKey RegInetInfo(REG_INETINFOPARAMETERS, HKEY_LOCAL_MACHINE);
|
|
if ((HKEY)RegInetInfo)
|
|
{
|
|
// Default to empty string if not exists
|
|
szMultiSz[0] = _T('\0');
|
|
szMultiSz[1] = _T('\0');
|
|
|
|
if (RegInetInfo.QueryValue(SZ_INETINFODISPATCH, szMultiSz, dwSize) == NO_ERROR)
|
|
{
|
|
// Walk the list to see if the value is already there
|
|
if (ScanMultiSzForSz(szMultiSz, szServiceName))
|
|
return(TRUE);
|
|
}
|
|
|
|
// Create the value and add it to the list
|
|
if (!AppendSzToMultiSz(szMultiSz, szServiceName, dwSize))
|
|
return(FALSE);
|
|
|
|
// Get the size of the new Multi-sz
|
|
dwSize = (DWORD)(GetEndOfMultiSz(szMultiSz) - szMultiSz) + 1;
|
|
|
|
// Write the value back to the registry
|
|
if (RegInetInfo.SetValue(SZ_INETINFODISPATCH, szMultiSz, dwSize * (DWORD) sizeof(TCHAR)) == NO_ERROR)
|
|
return(TRUE);
|
|
}
|
|
|
|
// If the InetInfo key is not here, there isn't much we can do ...
|
|
return(FALSE);
|
|
}
|
|
|
|
BOOL RemoveServiceFromDispatchList(LPTSTR szServiceName)
|
|
{
|
|
TCHAR szMultiSz[4096];
|
|
DWORD dwSize = 4096;
|
|
LPTSTR szTemp;
|
|
BOOL fFound = FALSE;
|
|
|
|
CRegKey RegInetInfo(HKEY_LOCAL_MACHINE, REG_INETINFOPARAMETERS);
|
|
if ((HKEY)RegInetInfo)
|
|
{
|
|
if (RegInetInfo.QueryValue(SZ_INETINFODISPATCH, szMultiSz, dwSize) == NO_ERROR)
|
|
{
|
|
// Walk the list to see if the value is already there
|
|
while (szTemp = ScanMultiSzForSz(szMultiSz, szServiceName))
|
|
{
|
|
RemoveSzFromMultiSz(szTemp);
|
|
fFound = TRUE;
|
|
}
|
|
}
|
|
|
|
// Write the value back to the registry if necessary, note we
|
|
// will indicate success if the string is not found
|
|
if (!fFound)
|
|
return(TRUE);
|
|
|
|
// Get the size of the new Multi-sz
|
|
dwSize = (DWORD)(GetEndOfMultiSz(szMultiSz) - szMultiSz) + 1;
|
|
|
|
// Write the value back to the registry
|
|
if (RegInetInfo.SetValue(SZ_INETINFODISPATCH, szMultiSz, dwSize * (DWORD) sizeof(TCHAR)) == NO_ERROR)
|
|
return(TRUE);
|
|
}
|
|
|
|
// If the InetInfo key is not here, there isn't much we can do ...
|
|
return(FALSE);
|
|
}
|
|
|
|
void GetIISProgramGroup(CString &csGroupName, BOOL fIsMcisGroup)
|
|
{
|
|
TCHAR szName[_MAX_PATH];
|
|
CString csTempName;
|
|
UINT uType, uSize;
|
|
|
|
if (fIsMcisGroup) {
|
|
csGroupName = "";
|
|
} else {
|
|
// Get the NT program group name from the private data
|
|
uSize = _MAX_PATH * sizeof(TCHAR);
|
|
{
|
|
// We use the default group name
|
|
MyLoadString(IDS_DEFAULT_NT_PROGRAM_GROUP, csTempName);
|
|
lstrcpy(szName, csTempName.GetBuffer(_MAX_PATH));
|
|
csTempName.ReleaseBuffer();
|
|
}
|
|
csGroupName = szName;
|
|
csGroupName += _T("\\");
|
|
|
|
// Get the IIS program group name from the private data
|
|
uSize = _MAX_PATH * sizeof(TCHAR);
|
|
{
|
|
// We use the default group name
|
|
MyLoadString(IDS_DEFAULT_IIS_PROGRAM_GROUP, csTempName);
|
|
lstrcpy(szName, csTempName.GetBuffer(_MAX_PATH));
|
|
csTempName.ReleaseBuffer();
|
|
}
|
|
csGroupName += szName;
|
|
}
|
|
}
|
|
|
|
void MyGetGroupPath(LPCTSTR szGroupName, LPTSTR szPath);
|
|
|
|
BOOL GetFullPathToProgramGroup(DWORD dwMainComponent, CString &csGroupName, BOOL fIsMcisGroup)
|
|
{
|
|
// add items to the program group
|
|
CString csTemp;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
// Get the program group name from the private data
|
|
GetIISProgramGroup(csTemp, fIsMcisGroup);
|
|
|
|
// Get the system path to this menu item
|
|
MyGetGroupPath((LPCTSTR)csTemp, szPath);
|
|
csGroupName = szPath;
|
|
|
|
// Load up the resource string for the group
|
|
if (fIsMcisGroup)
|
|
MyLoadString(IDS_PROGGROUP_MCIS_MAIL_AND_NEWS, csTemp);
|
|
else
|
|
MyLoadString(dwMainComponent == MC_IMS?IDS_PROGGROUP_MAIL:IDS_PROGGROUP_NEWS, csTemp);
|
|
|
|
// Build the program group
|
|
csGroupName += csTemp;
|
|
|
|
DebugOutput(_T("Program group loaded: %s"), (LPCTSTR)csGroupName);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL GetFullPathToAdminGroup(DWORD dwMainComponent, CString &csGroupName)
|
|
{
|
|
// add items to the program group
|
|
CString csTemp;
|
|
TCHAR szPath[MAX_PATH];
|
|
|
|
// Get the program group name from the private data
|
|
MyLoadString( IDS_PROGGROUP_ADMINTOOLS, csTemp );
|
|
|
|
// Get the system path to this menu item
|
|
MyGetGroupPath((LPCTSTR)csTemp, szPath);
|
|
csGroupName = szPath;
|
|
|
|
DebugOutput(_T("Program group loaded: %s"), (LPCTSTR)csGroupName);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL RemoveProgramGroupIfEmpty(DWORD dwMainComponent, BOOL fIsMcisGroup)
|
|
{
|
|
// add items to the program group
|
|
CString csGroupName;
|
|
CString csTemp;
|
|
TCHAR szPath[MAX_PATH];
|
|
BOOL fResult;
|
|
|
|
// Get the program group name from the private data
|
|
GetIISProgramGroup(csTemp, fIsMcisGroup);
|
|
|
|
// Get the system path to this menu item
|
|
MyGetGroupPath((LPCTSTR)csTemp, szPath);
|
|
csGroupName = szPath;
|
|
|
|
// Load up the resource string for the group
|
|
if (fIsMcisGroup)
|
|
MyLoadString(IDS_PROGGROUP_MCIS_MAIL_AND_NEWS, csTemp);
|
|
else
|
|
MyLoadString(dwMainComponent == MC_IMS?IDS_PROGGROUP_MAIL:IDS_PROGGROUP_NEWS, csTemp);
|
|
|
|
// Build the program group
|
|
csGroupName += csTemp;
|
|
|
|
DebugOutput(_T("Removing Program group: %s"), (LPCTSTR)csGroupName);
|
|
|
|
fResult = RemoveDirectory((LPCTSTR)csGroupName);
|
|
if (fResult && fIsMcisGroup)
|
|
{
|
|
SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, (LPCTSTR)csGroupName, 0);
|
|
|
|
csGroupName = szPath;
|
|
MyLoadString(IDS_MCIS_2_0, csTemp);
|
|
csGroupName += csTemp;
|
|
fResult = RemoveDirectory((LPCTSTR)csGroupName);
|
|
}
|
|
if (fResult)
|
|
{
|
|
SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, (LPCTSTR)csGroupName, 0);
|
|
}
|
|
|
|
return(fResult);
|
|
}
|
|
|
|
BOOL RemoveInternetShortcut(DWORD dwMainComponent, int dwDisplayNameId, BOOL fIsMcisGroup)
|
|
{
|
|
CString csItemPath;
|
|
CString csDisplayName;
|
|
|
|
MyLoadString(dwDisplayNameId, csDisplayName);
|
|
|
|
// Build the full path to the program link
|
|
GetFullPathToProgramGroup(dwMainComponent, csItemPath, fIsMcisGroup);
|
|
csItemPath += _T("\\");
|
|
csItemPath += csDisplayName;
|
|
csItemPath += _T(".url");
|
|
|
|
DebugOutput(_T("Removing shortcut file: %s"), (LPCTSTR)csItemPath);
|
|
|
|
DeleteFile((LPCTSTR)csItemPath);
|
|
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, (LPCTSTR)csItemPath, 0);
|
|
|
|
RemoveProgramGroupIfEmpty(dwMainComponent, fIsMcisGroup);
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL RemoveNt5InternetShortcut(DWORD dwMainComponent, int dwDisplayNameId)
|
|
{
|
|
CString csItemPath;
|
|
CString csDisplayName;
|
|
|
|
MyLoadString(dwDisplayNameId, csDisplayName);
|
|
|
|
// Build the full path to the program link
|
|
GetFullPathToAdminGroup(dwMainComponent, csItemPath);
|
|
csItemPath += _T("\\");
|
|
csItemPath += csDisplayName;
|
|
csItemPath += _T(".url");
|
|
|
|
DebugOutput(_T("Removing shortcut file: %s"), (LPCTSTR)csItemPath);
|
|
|
|
DeleteFile((LPCTSTR)csItemPath);
|
|
SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, (LPCTSTR)csItemPath, 0);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL RemoveMCIS10MailProgramGroup()
|
|
{
|
|
CString csGroupName;
|
|
CString csNiceName;
|
|
|
|
MyLoadString(IDS_PROGGROUP_MCIS10_MAIL, csGroupName);
|
|
|
|
MyLoadString(IDS_PROGITEM_MCIS10_MAIL_STARTPAGE, csNiceName);
|
|
MyDeleteItem(csGroupName, csNiceName);
|
|
|
|
MyLoadString(IDS_PROGITEM_MCIS10_MAIL_WEBADMIN, csNiceName);
|
|
MyDeleteItemEx(csGroupName, csNiceName);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL RemoveMCIS10NewsProgramGroup()
|
|
{
|
|
CString csGroupName;
|
|
CString csNiceName;
|
|
|
|
// BINLIN:
|
|
// BUGBUG: need to figure out how to get
|
|
// the old MCIS 1.0 program group path
|
|
MyLoadString(IDS_PROGGROUP_MCIS10_NEWS, csGroupName);
|
|
|
|
MyLoadString(IDS_PROGITEM_MCIS10_NEWS_STARTPAGE, csNiceName);
|
|
MyDeleteItem(csGroupName, csNiceName);
|
|
|
|
MyLoadString(IDS_PROGITEM_MCIS10_NEWS_WEBADMIN, csNiceName);
|
|
MyDeleteItemEx(csGroupName, csNiceName);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL RemoveUninstallEntries(LPCTSTR szInfFile)
|
|
{
|
|
// All components are removed, we will have to remove
|
|
// the Add/Remove option from the control panel
|
|
CRegKey regUninstall( HKEY_LOCAL_MACHINE, REG_UNINSTALL);
|
|
if ((HKEY)regUninstall)
|
|
regUninstall.DeleteTree(szInfFile);
|
|
else
|
|
return(FALSE);
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL MyDeleteLink(LPTSTR lpszShortcut)
|
|
{
|
|
TCHAR szFile[_MAX_PATH];
|
|
SHFILEOPSTRUCT fos;
|
|
|
|
ZeroMemory(szFile, sizeof(szFile));
|
|
lstrcpy(szFile, lpszShortcut);
|
|
|
|
// only call SHFileOperation if this file/link exists
|
|
if (0xFFFFFFFF != GetFileAttributes(szFile))
|
|
{
|
|
ZeroMemory(&fos, sizeof(fos));
|
|
fos.hwnd = NULL;
|
|
fos.wFunc = FO_DELETE;
|
|
fos.pFrom = szFile;
|
|
fos.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;
|
|
SHFileOperation(&fos);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void MyGetGroupPath(LPCTSTR szGroupName, LPTSTR szPath)
|
|
{
|
|
int nLen = 0;
|
|
LPITEMIDLIST pidlPrograms;
|
|
|
|
szPath[0] = NULL;
|
|
|
|
if (NOERROR != SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_PROGRAMS, &pidlPrograms)) return;
|
|
|
|
if (!SHGetPathFromIDList(pidlPrograms, szPath)) return;
|
|
nLen = lstrlen(szPath);
|
|
if (szGroupName) {
|
|
if (nLen == 0 || szPath[nLen-1] != _T('\\'))
|
|
lstrcat(szPath, _T("\\"));
|
|
lstrcat(szPath, szGroupName);
|
|
}
|
|
return;
|
|
}
|
|
|
|
BOOL MyAddGroup(LPCTSTR szGroupName)
|
|
{
|
|
TCHAR szPath[MAX_PATH];
|
|
CString csPath;
|
|
|
|
MyGetGroupPath(szGroupName, szPath);
|
|
csPath = szPath;
|
|
CreateLayerDirectory(csPath);
|
|
SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, szPath, 0);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL MyIsGroupEmpty(LPCTSTR szGroupName)
|
|
{
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szFile[MAX_PATH];
|
|
WIN32_FIND_DATA FindData;
|
|
HANDLE hFind;
|
|
BOOL bFindFile = TRUE;
|
|
BOOL fReturn = TRUE;
|
|
|
|
MyGetGroupPath(szGroupName, szPath);
|
|
|
|
lstrcpy(szFile, szPath);
|
|
lstrcat(szFile, _T("\\*.*"));
|
|
|
|
hFind = FindFirstFile(szFile, &FindData);
|
|
if (INVALID_HANDLE_VALUE != hFind)
|
|
{
|
|
while (bFindFile)
|
|
{
|
|
if(*(FindData.cFileName) != _T('.'))
|
|
{
|
|
fReturn = FALSE;
|
|
break;
|
|
}
|
|
|
|
//find the next file
|
|
bFindFile = FindNextFile(hFind, &FindData);
|
|
}
|
|
|
|
FindClose(hFind);
|
|
}
|
|
|
|
return fReturn;
|
|
}
|
|
|
|
BOOL MyDeleteGroup(LPCTSTR szGroupName)
|
|
{
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szFile[MAX_PATH];
|
|
SHFILEOPSTRUCT fos;
|
|
WIN32_FIND_DATA FindData;
|
|
HANDLE hFind;
|
|
BOOL bFindFile = TRUE;
|
|
BOOL fResult;
|
|
|
|
MyGetGroupPath(szGroupName, szPath);
|
|
|
|
//we can't remove a directory that is not empty, so we need to empty this one
|
|
|
|
lstrcpy(szFile, szPath);
|
|
lstrcat(szFile, _T("\\*.*"));
|
|
|
|
ZeroMemory(&fos, sizeof(fos));
|
|
fos.hwnd = NULL;
|
|
fos.wFunc = FO_DELETE;
|
|
fos.fFlags = FOF_SILENT | FOF_NOCONFIRMATION;
|
|
|
|
hFind = FindFirstFile(szFile, &FindData);
|
|
if (INVALID_HANDLE_VALUE != hFind)
|
|
{
|
|
while (bFindFile)
|
|
{
|
|
if(*(FindData.cFileName) != _T('.'))
|
|
{
|
|
//copy the path and file name to our temp buffer
|
|
lstrcpy(szFile, szPath);
|
|
lstrcat(szFile, _T("\\"));
|
|
lstrcat(szFile, FindData.cFileName);
|
|
//add a second NULL because SHFileOperation is looking for this
|
|
lstrcat(szFile, _T("\0"));
|
|
|
|
//delete the file
|
|
fos.pFrom = szFile;
|
|
SHFileOperation(&fos);
|
|
}
|
|
//find the next file
|
|
bFindFile = FindNextFile(hFind, &FindData);
|
|
}
|
|
FindClose(hFind);
|
|
}
|
|
|
|
fResult = RemoveDirectory(szPath);
|
|
if (fResult)
|
|
{
|
|
SHChangeNotify(SHCNE_RMDIR, SHCNF_PATH, szPath, 0);
|
|
}
|
|
|
|
return(fResult);
|
|
}
|
|
|
|
void MyDeleteItem(LPCTSTR szGroupName, LPCTSTR szAppName)
|
|
{
|
|
TCHAR szPath[_MAX_PATH];
|
|
|
|
MyGetGroupPath(szGroupName, szPath);
|
|
lstrcat(szPath, _T("\\"));
|
|
lstrcat(szPath, szAppName);
|
|
lstrcat(szPath, _T(".lnk"));
|
|
|
|
MyDeleteLink(szPath);
|
|
|
|
if (MyIsGroupEmpty(szGroupName))
|
|
MyDeleteGroup(szGroupName);
|
|
}
|
|
|
|
// Use to delete files with extension other than ".lnk"
|
|
void MyDeleteItemEx(LPCTSTR szGroupName, LPCTSTR szAppName)
|
|
{
|
|
TCHAR szPath[_MAX_PATH];
|
|
|
|
MyGetGroupPath(szGroupName, szPath);
|
|
lstrcat(szPath, _T("\\"));
|
|
lstrcat(szPath, szAppName);
|
|
|
|
MyDeleteLink(szPath);
|
|
|
|
if (MyIsGroupEmpty(szGroupName))
|
|
MyDeleteGroup(szGroupName);
|
|
}
|
|
|
|
BOOL RemoveISMLink()
|
|
{
|
|
// add items to the program group
|
|
CString csGroupName;
|
|
CString csNiceName;
|
|
CString csTemp;
|
|
|
|
DebugOutput(_T("Removing ISM link ..."));
|
|
|
|
// Get the program group name from the private data
|
|
GetIISProgramGroup(csGroupName, TRUE);
|
|
|
|
MyLoadString(IDS_PROGGROUP_MCIS_MAIL_AND_NEWS, csTemp);
|
|
|
|
// Build the program group
|
|
csGroupName += csTemp;
|
|
|
|
MyLoadString(IDS_PROGITEM_ISM, csNiceName);
|
|
MyDeleteItem(csGroupName, csNiceName);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
void GetInetpubPathFromMD(CString& csPathInetpub)
|
|
{
|
|
TCHAR szw3root[] = _T("\\wwwroot");
|
|
TCHAR szPathInetpub[_MAX_PATH];
|
|
|
|
ZeroMemory( szPathInetpub, sizeof(szPathInetpub) );
|
|
|
|
CMDKey W3Key;
|
|
DWORD dwScratch;
|
|
DWORD dwType;
|
|
DWORD dwLength;
|
|
|
|
// Get W3Root path
|
|
W3Key.OpenNode(_T("LM/W3Svc/1/Root"));
|
|
if ( (METADATA_HANDLE)W3Key )
|
|
{
|
|
dwLength = _MAX_PATH;
|
|
|
|
if (W3Key.GetData(3001, &dwScratch, &dwScratch,
|
|
&dwType, &dwLength, (LPBYTE)szPathInetpub))
|
|
{
|
|
if (dwType == STRING_METADATA)
|
|
{
|
|
dwScratch = lstrlen(szw3root);
|
|
dwLength = lstrlen(szPathInetpub);
|
|
|
|
// If it ends with "\\wwwroot", then we copy the prefix into csPathInetpub
|
|
if ((dwLength > dwScratch) &&
|
|
!lstrcmpi(szPathInetpub + (dwLength - dwScratch), szw3root))
|
|
{
|
|
csPathInetpub.Empty();
|
|
lstrcpyn( csPathInetpub.GetBuffer(512), szPathInetpub, (dwLength - dwScratch + 1));
|
|
csPathInetpub.ReleaseBuffer();
|
|
}
|
|
|
|
// otherwise fall back to use the default...
|
|
}
|
|
}
|
|
W3Key.Close();
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|