331 lines
9.1 KiB
C++
331 lines
9.1 KiB
C++
|
|
#include <tchar.h>
|
|
# include <nt.h>
|
|
# include <ntrtl.h>
|
|
# include <nturtl.h>
|
|
# include <windows.h>
|
|
// For the compatibility check function and types
|
|
#include <comp.h>
|
|
#include <clusapi.h>
|
|
#include "resource.h"
|
|
#include "iiscomp.hxx"
|
|
#include "disblwww.hxx"
|
|
|
|
HANDLE g_hMyHandle = NULL;
|
|
|
|
//
|
|
// Standard Win32 DLL Entry point
|
|
//
|
|
BOOL WINAPI DllMain(IN HANDLE DllHandle,IN DWORD Reason,IN LPVOID Reserved)
|
|
{
|
|
BOOL bReturn = FALSE;
|
|
|
|
switch(Reason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
g_hMyHandle = DllHandle;
|
|
bReturn = TRUE;
|
|
break;
|
|
|
|
case DLL_THREAD_ATTACH:
|
|
bReturn = TRUE;
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
bReturn = TRUE;
|
|
break;
|
|
|
|
case DLL_THREAD_DETACH:
|
|
bReturn = TRUE;
|
|
break;
|
|
}
|
|
|
|
return(bReturn);
|
|
}
|
|
|
|
// function: IISUpgradeCompatibilityCheck
|
|
//
|
|
// Checks the IIS Upgrade Comapatability. At this time, this is only used to
|
|
// tell if the machine is clustered for IIS. Because this upgrade is not seemless
|
|
//
|
|
// Parameters:
|
|
// PCOMPAIBILITYCALLBACK pfnCompatibilityCallbackIn
|
|
// Points to the callback function used to supply compatibility
|
|
// information to WinNT32.exe
|
|
//
|
|
// LPVOID pvContextIn
|
|
// Pointer to the context buffer supplied by WinNT32.exe
|
|
//
|
|
// Return Values:
|
|
// TRUE - Everything worked fine
|
|
// FALSE - There was a failure
|
|
//
|
|
extern "C"
|
|
BOOL
|
|
IISUpgradeCompatibilityCheck(
|
|
PCOMPAIBILITYCALLBACK pfnCompatibilityCallbackIn
|
|
, LPVOID pvContextIn
|
|
)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
BOOL bDisableW3SVC;
|
|
BOOL bInstallingOnFat;
|
|
BOOL bIISIsInstalled;
|
|
COMPATIBILITY_ENTRY ceCompatibilityEntry;
|
|
|
|
if ( !IsIISInstalled( &bIISIsInstalled ) )
|
|
{
|
|
// Failed to do check, error out
|
|
return FALSE;
|
|
}
|
|
|
|
if ( !bIISIsInstalled )
|
|
{
|
|
// IIS is not installed, so there is nothing we need to do
|
|
return TRUE;
|
|
}
|
|
|
|
// Check for Clustering Compatability Issue
|
|
if ( IsClusterResourceInstalled( IISCOMPAT_RESOURCETYPE ) )
|
|
{
|
|
// Since we have the comaptabilty problem, we have to call the winnt32 callback funcion
|
|
SetCompatabilityContext( &ceCompatibilityEntry,
|
|
IDS_COMPATABILITY_DESCRIPTION_CLUSTER,
|
|
IISCOMPAT_TEXTNAME,
|
|
IISCOMPAT_HTMLNAME );
|
|
|
|
bRet = pfnCompatibilityCallbackIn( &ceCompatibilityEntry, pvContextIn );
|
|
}
|
|
|
|
// Check for disabling the W3SVC Service
|
|
if ( ShouldW3SVCBeDisabledOnUpgrade( &bDisableW3SVC ) )
|
|
{
|
|
if ( !NotifyIISToDisableW3SVCOnUpgrade( bDisableW3SVC ) )
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
if ( bDisableW3SVC )
|
|
{
|
|
// Since we have the comaptabilty problem, we have to call the winnt32 callback funcion
|
|
SetCompatabilityContext( &ceCompatibilityEntry,
|
|
IDS_COMPATABILITY_DESCRIPTION_W3SVCDISABLE,
|
|
IISCOMPAT_W3SVCDISABLE_TEXTNAME,
|
|
IISCOMPAT_W3SVCDISABLE_HTMLNAME );
|
|
|
|
if ( !pfnCompatibilityCallbackIn( &ceCompatibilityEntry, pvContextIn ) )
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Could not do check, so fail
|
|
bRet = FALSE;
|
|
}
|
|
|
|
// Warning about installing on FAT
|
|
if ( IsIISInstallingonFat( &bInstallingOnFat ) )
|
|
{
|
|
if ( bInstallingOnFat )
|
|
{
|
|
// Since we have the comaptabilty problem, we have to call the winnt32 callback funcion
|
|
SetCompatabilityContext( &ceCompatibilityEntry,
|
|
IDS_COMPATABILITY_DESCRIPTION_FAT,
|
|
IISCOMPAT_FAT_TEXTNAME,
|
|
IISCOMPAT_FAT_HTMLNAME );
|
|
|
|
if ( !pfnCompatibilityCallbackIn( &ceCompatibilityEntry, pvContextIn ) )
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Could not do check, so fail
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
// IsIISInstallingonFat
|
|
//
|
|
// Parameters:
|
|
// pbInstallingOnFat [out] - Is IIS installing on FAT?
|
|
//
|
|
// Return Values:
|
|
// TRUE - Successfully checked
|
|
// FALSE - Failure checking
|
|
//
|
|
BOOL
|
|
IsIISInstallingonFat( LPBOOL pbInstallingOnFat )
|
|
{
|
|
TCHAR szSystemDrive[ MAX_PATH ];
|
|
DWORD dwDriveFlags;
|
|
UINT iReturn;
|
|
|
|
iReturn = GetWindowsDirectory( szSystemDrive,
|
|
sizeof(szSystemDrive)/sizeof(szSystemDrive[0]) );
|
|
|
|
if ( ( iReturn == 0 ) || // Call failed
|
|
( iReturn >= MAX_PATH ) || // Buffer was not large enough
|
|
( iReturn < 3 ) || // sizeof 'x:\'
|
|
( szSystemDrive[1] != _T(':') ) || // Not in a format we expect
|
|
( szSystemDrive[2] != _T('\\') ) )
|
|
{
|
|
// Failure checking
|
|
return FALSE;
|
|
}
|
|
|
|
// Null terminate drive
|
|
szSystemDrive[3] = _T('\0');
|
|
|
|
if ( !GetVolumeInformation( szSystemDrive,
|
|
NULL, // Volume Name Buffer
|
|
0, // Size of Buffer
|
|
NULL, // Serial Number Buffer
|
|
NULL, // Max Component Lenght
|
|
&dwDriveFlags, // System Flags
|
|
NULL, // FS Type
|
|
0 ) )
|
|
{
|
|
// Failed to do query
|
|
return FALSE;
|
|
}
|
|
|
|
*pbInstallingOnFat = ( dwDriveFlags & FS_PERSISTENT_ACLS ) == 0;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// SetCompatabilityContext
|
|
//
|
|
// Set the Context of the Compatabilty stucrute that we must send back to
|
|
// the compat stuff
|
|
//
|
|
void
|
|
SetCompatabilityContext( COMPATIBILITY_ENTRY *pCE, DWORD dwDescriptionID, LPTSTR szTxtFile, LPTSTR szHtmlFile )
|
|
{
|
|
static WCHAR szDescriptionBuffer[ 100 ];
|
|
DWORD dwErr;
|
|
|
|
dwErr = LoadStringW( (HINSTANCE) g_hMyHandle,
|
|
dwDescriptionID,
|
|
szDescriptionBuffer,
|
|
sizeof(szDescriptionBuffer)/sizeof(szDescriptionBuffer[0]) );
|
|
|
|
if ( dwErr == 0 )
|
|
{
|
|
// This should not happen, since we control the length
|
|
// of the resource
|
|
ASSERT( ( sizeof(IISCOMPAT_DESCRIPTION)/sizeof(WCHAR) ) <
|
|
( sizeof(szDescriptionBuffer)/sizeof(szDescriptionBuffer[0]) ) );
|
|
ASSERT( dwErr != 0 /* FALSE */ );
|
|
|
|
_tcscpy(szDescriptionBuffer, IISCOMPAT_DESCRIPTION );
|
|
}
|
|
|
|
pCE->Description = szDescriptionBuffer;
|
|
pCE->HtmlName = szHtmlFile;
|
|
pCE->TextName = szTxtFile;
|
|
pCE->RegKeyName = NULL;
|
|
pCE->RegValName = NULL ;
|
|
pCE->RegValDataSize = 0;
|
|
pCE->RegValData = NULL;
|
|
pCE->SaveValue = NULL;
|
|
pCE->Flags = 0;
|
|
pCE->InfName = NULL;
|
|
pCE->InfSection = NULL;
|
|
}
|
|
|
|
// function: IsClusterResourceInstalled
|
|
//
|
|
// Check to see if there is a Cluster with a resource of a particular
|
|
// type that you are looking for.
|
|
//
|
|
// Parameters:
|
|
// szResourceType - The type of resource that you are looking for
|
|
//
|
|
// Return Values:
|
|
// TRUE - There is a cluster with that resource type
|
|
// FALSE - There is not a cluster with that resource type, or we
|
|
// failed during the search
|
|
//
|
|
BOOL
|
|
IsClusterResourceInstalled(LPWSTR szResourceType)
|
|
{
|
|
HCLUSTER hCluster;
|
|
HINSTANCE hClusApi = NULL;
|
|
HCLUSENUM hClusEnum = NULL;
|
|
BOOL bResourceFound = FALSE;
|
|
|
|
if (hCluster = OpenCluster(NULL))
|
|
{
|
|
// Open cluster resource
|
|
hClusEnum = ClusterOpenEnum(hCluster, CLUSTER_ENUM_RESOURCE);
|
|
}
|
|
|
|
if (hClusEnum != NULL)
|
|
{
|
|
DWORD dwEnumIndex = 0;
|
|
DWORD dwErr = ERROR_SUCCESS;
|
|
WCHAR szClusterName[CLUSTERNAME_MAXLENGTH];
|
|
WCHAR szClusterResourceType[CLUSTERNAME_MAXLENGTH];
|
|
DWORD dwType;
|
|
DWORD dwLen;
|
|
HRESOURCE hClusResource;
|
|
HKEY hResourceRoot;
|
|
HKEY hClusResourceKey;
|
|
|
|
while ( ( dwErr == ERROR_SUCCESS ) && !bResourceFound )
|
|
{
|
|
// Get the cluster name
|
|
dwLen = CLUSTERNAME_MAXLENGTH;
|
|
dwErr = ClusterEnum( hClusEnum, dwEnumIndex++, &dwType, szClusterName, &dwLen );
|
|
|
|
if ( ( dwErr == ERROR_SUCCESS ) && ( dwType == CLUSTER_ENUM_RESOURCE ) )
|
|
{
|
|
hClusResource = NULL;
|
|
hClusResourceKey = NULL;
|
|
dwLen = CLUSTERNAME_MAXLENGTH;
|
|
// For each cluster, check out the resources
|
|
if ( ( hClusResource = OpenClusterResource( hCluster, szClusterName ) ) &&
|
|
( hClusResourceKey = GetClusterResourceKey( hClusResource, KEY_READ ) ) &&
|
|
( ClusterRegQueryValue( hClusResourceKey, L"Type", &dwType, (LPBYTE) szClusterResourceType , &dwLen ) == ERROR_SUCCESS) &&
|
|
( dwType == REG_SZ ) &&
|
|
( !_wcsicmp( szClusterResourceType , szResourceType ) )
|
|
)
|
|
{
|
|
// Found the Resource we were looking for
|
|
bResourceFound = TRUE;
|
|
}
|
|
|
|
if ( hClusResourceKey )
|
|
{
|
|
ClusterRegCloseKey( hClusResourceKey );
|
|
}
|
|
|
|
if ( hClusResource )
|
|
{
|
|
CloseClusterResource( hClusResource );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( hClusEnum )
|
|
{
|
|
ClusterCloseEnum( hClusEnum );
|
|
}
|
|
|
|
if ( hCluster )
|
|
{
|
|
CloseCluster( hCluster);
|
|
}
|
|
|
|
return bResourceFound;
|
|
}
|