468 lines
9.2 KiB
C
468 lines
9.2 KiB
C
/*++
|
||
|
||
Copyright (c) 1996-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
oscheck.c
|
||
|
||
Abstract:
|
||
|
||
Checks all the nooks and crannies of the OS to make sure
|
||
it is ok to run a cluster on it.
|
||
|
||
Author:
|
||
|
||
John Vert (jvert) 11/11/1996
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
#include <clusrtlp.h>
|
||
|
||
#include <winbase.h>
|
||
|
||
static
|
||
DWORD
|
||
GetEnableClusterRegValue(
|
||
DWORD * pdwValue
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Read the registry override registry value for enabling clusters.
|
||
|
||
Arguments:
|
||
|
||
pdwValue - Return value read from the registry.
|
||
|
||
Return Value:
|
||
|
||
ERROR_SUCCESS if the operation was successful.
|
||
|
||
Win32 error code on failure.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD sc;
|
||
HKEY hkey = NULL;
|
||
DWORD dwType;
|
||
DWORD cbValue = sizeof( DWORD );
|
||
|
||
if ( !ARGUMENT_PRESENT( pdwValue ) ) {
|
||
return ERROR_INVALID_PARAMETER;
|
||
}
|
||
|
||
//
|
||
// Default to the value 0 - not Enabled!
|
||
//
|
||
*pdwValue = 0;
|
||
|
||
//
|
||
// Open the registry key containing the value.
|
||
//
|
||
|
||
sc = RegOpenKeyEx(
|
||
HKEY_LOCAL_MACHINE,
|
||
TEXT("Software\\Microsoft\\Windows NT\\CurrentVersion\\Cluster Server"),
|
||
0,
|
||
KEY_READ,
|
||
&hkey );
|
||
if ( sc != ERROR_SUCCESS ) {
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// Read the override value.
|
||
//
|
||
|
||
sc = RegQueryValueEx(
|
||
hkey,
|
||
TEXT("EnableCluster"),
|
||
0,
|
||
&dwType,
|
||
(LPBYTE) pdwValue,
|
||
&cbValue );
|
||
if ( sc != ERROR_SUCCESS ) {
|
||
goto Cleanup;
|
||
}
|
||
|
||
Cleanup:
|
||
if ( hkey != NULL ) {
|
||
RegCloseKey( hkey );
|
||
}
|
||
|
||
return( sc );
|
||
|
||
} // GetEnableClusterRegValue
|
||
|
||
|
||
|
||
DWORD
|
||
GetServicePack(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Figures out what service pack is installed
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
The service pack number.
|
||
|
||
--*/
|
||
|
||
{
|
||
OSVERSIONINFOW Version;
|
||
LPWSTR p;
|
||
DWORD sp;
|
||
|
||
//
|
||
// Check for required operating system version.
|
||
//
|
||
Version.dwOSVersionInfoSize = sizeof(Version);
|
||
GetVersionExW(&Version);
|
||
if (lstrlenW(Version.szCSDVersion) < lstrlenW(L"Service Pack ")) {
|
||
return(0);
|
||
}
|
||
|
||
p = &Version.szCSDVersion[0] + lstrlenW(L"Service Pack ");
|
||
|
||
sp = wcstoul(p, NULL, 10);
|
||
|
||
return(sp);
|
||
|
||
} // GetServicePack
|
||
|
||
|
||
|
||
BOOL
|
||
ClRtlIsOSValid(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks all the nooks and crannies of the OS to see if it is OK to have
|
||
a cluster there.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
TRUE if it's ok.
|
||
|
||
FALSE if it's not ok.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fIsValid = FALSE;
|
||
OSVERSIONINFOEX osiv;
|
||
DWORDLONG dwlConditionMask;
|
||
|
||
ZeroMemory( &osiv, sizeof( OSVERSIONINFOEX ) );
|
||
|
||
osiv.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
|
||
|
||
// The following call to VerifyVersionInfo() will test the OS level and that the
|
||
// product suite is Enterprise.
|
||
|
||
osiv.dwMajorVersion = 5;
|
||
osiv.dwMinorVersion = 1;
|
||
osiv.wServicePackMajor = 0;
|
||
osiv.wSuiteMask = VER_SUITE_ENTERPRISE;
|
||
|
||
dwlConditionMask = (DWORDLONG) 0L;
|
||
|
||
VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
|
||
VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL );
|
||
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
|
||
VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
|
||
|
||
if ( VerifyVersionInfo( &osiv,
|
||
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR |
|
||
VER_SUITENAME,
|
||
dwlConditionMask ) ) {
|
||
fIsValid = TRUE;
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// Check if embedded
|
||
//
|
||
osiv.wSuiteMask = VER_SUITE_EMBEDDEDNT;
|
||
if ( VerifyVersionInfo( &osiv,
|
||
VER_MAJORVERSION | VER_MINORVERSION | VER_SERVICEPACKMAJOR |
|
||
VER_SUITENAME,
|
||
dwlConditionMask ) ) {
|
||
fIsValid = TRUE;
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// Is the default node limit greater than 0?
|
||
//
|
||
if ( ClRtlGetDefaultNodeLimit( ClRtlGetSuiteType() ) > 0 ) {
|
||
fIsValid = TRUE;
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// If we get here, the this version of the OS won't support clustering.
|
||
//
|
||
SetLastError( ERROR_CLUSTER_WRONG_OS_VERSION );
|
||
|
||
Cleanup:
|
||
return( fIsValid );
|
||
|
||
} // ClRtlIsOSValid
|
||
|
||
|
||
BOOL
|
||
ClRtlIsOSTypeValid(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Checks to see if the operating system type (server, Enterprise, whatever) is
|
||
ok to install a cluster.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
TRUE if it's ok.
|
||
|
||
FALSE if it's not ok.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fIsValid = FALSE;
|
||
OSVERSIONINFOEX osiv;
|
||
DWORDLONG dwlConditionMask;
|
||
|
||
ZeroMemory( &osiv, sizeof( OSVERSIONINFOEX ) );
|
||
|
||
osiv.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
|
||
|
||
// The call to VerifyVersionInfo will test whether product suite is Advanced
|
||
// Server, aka "Enterprise".
|
||
|
||
osiv.wSuiteMask = VER_SUITE_ENTERPRISE;
|
||
|
||
dwlConditionMask = (DWORDLONG) 0L;
|
||
|
||
VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
|
||
|
||
// Is this Datacenter or Advanced Server?
|
||
|
||
if ( VerifyVersionInfo( &osiv, VER_SUITENAME, dwlConditionMask ) ) {
|
||
fIsValid = TRUE;
|
||
goto Cleanup;
|
||
}
|
||
|
||
// Is this Embedded NT?
|
||
|
||
osiv.wSuiteMask = VER_SUITE_EMBEDDEDNT;
|
||
if ( VerifyVersionInfo( &osiv, VER_SUITENAME, dwlConditionMask ) ) {
|
||
fIsValid = TRUE;
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// Is the default node limit greater than 0?
|
||
//
|
||
if ( ClRtlGetDefaultNodeLimit( ClRtlGetSuiteType() ) > 0 ) {
|
||
fIsValid = TRUE;
|
||
goto Cleanup;
|
||
}
|
||
|
||
//
|
||
// If we get here, the this version of the OS won't support clustering.
|
||
//
|
||
SetLastError( ERROR_CLUSTER_WRONG_OS_VERSION );
|
||
|
||
Cleanup:
|
||
return( fIsValid );
|
||
|
||
} // ClRtlIsOSTypeValid
|
||
|
||
//*********************************************************
|
||
|
||
#define DATACENTER_DEFAULT_NODE_LIMIT 8
|
||
#define ADVANCEDSERVER_DEFAULT_NODE_LIMIT 4
|
||
#define EMBEDDED_DEFAULT_NODE_LIMIT 4
|
||
#define SERVER_DEFAULT_NODE_LIMIT 0 // ** not used currently **
|
||
|
||
//*********************************************************
|
||
|
||
DWORD
|
||
ClRtlGetDefaultNodeLimit(
|
||
DWORD SuiteType
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Determines the default maximum number of nodes allowed in the cluster, based
|
||
on the product suite.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
The default maximum number of nodes allowed in the cluster.
|
||
|
||
Note that this function will return ZERO if the product suite is neither
|
||
DataCenter, Advanced Server (aka Enterprise), nor Embedded.
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD NodeLimit;
|
||
|
||
switch( SuiteType )
|
||
{
|
||
case DataCenter:
|
||
NodeLimit = DATACENTER_DEFAULT_NODE_LIMIT;
|
||
break;
|
||
|
||
case Enterprise:
|
||
NodeLimit = ADVANCEDSERVER_DEFAULT_NODE_LIMIT;
|
||
break;
|
||
|
||
case EmbeddedNT:
|
||
NodeLimit = EMBEDDED_DEFAULT_NODE_LIMIT;
|
||
break;
|
||
|
||
case VER_SERVER_NT:
|
||
default:
|
||
{
|
||
DWORD dwOverride;
|
||
|
||
//
|
||
// Check the override registry value.
|
||
//
|
||
GetEnableClusterRegValue( &dwOverride );
|
||
if ( dwOverride != 0 ) {
|
||
NodeLimit = 2;
|
||
} else {
|
||
NodeLimit = 0;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
return( NodeLimit );
|
||
|
||
} // ClRtlGetDefaultNodeLimit
|
||
|
||
|
||
|
||
DWORD
|
||
ClRtlGetSuiteType(
|
||
void
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the current product suite type.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
Returns the product suite type DataCenter or Enterprise (aka Advanced Server)
|
||
Returns zero if not DataCenter or Enterprise
|
||
|
||
--*/
|
||
|
||
{
|
||
DWORD dwSuiteType = 0;
|
||
OSVERSIONINFOEX osiv;
|
||
DWORDLONG dwlConditionMask;
|
||
|
||
ZeroMemory( &osiv, sizeof( OSVERSIONINFOEX ) );
|
||
osiv.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
|
||
|
||
// First check if product suite is DataCenter.
|
||
|
||
osiv.wSuiteMask = VER_SUITE_DATACENTER;
|
||
dwlConditionMask = (DWORDLONG) 0L;
|
||
|
||
VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
|
||
|
||
if ( VerifyVersionInfo( &osiv, VER_SUITENAME, dwlConditionMask ) == TRUE )
|
||
{
|
||
// This is DataCenter.
|
||
|
||
dwSuiteType = DataCenter;
|
||
goto Cleanup;
|
||
}
|
||
|
||
ZeroMemory( &osiv, sizeof( OSVERSIONINFOEX ) );
|
||
osiv.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
|
||
|
||
// Next check if this is Advanced Server (Enterprise).
|
||
|
||
osiv.wSuiteMask = VER_SUITE_ENTERPRISE;
|
||
dwlConditionMask = (DWORDLONG) 0L;
|
||
|
||
VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
|
||
|
||
if ( VerifyVersionInfo( &osiv, VER_SUITENAME, dwlConditionMask ) == TRUE )
|
||
{
|
||
dwSuiteType = Enterprise;
|
||
goto Cleanup;
|
||
}
|
||
|
||
// Next check if this is Embedded.
|
||
|
||
osiv.wSuiteMask = VER_SUITE_EMBEDDEDNT;
|
||
dwlConditionMask = (DWORDLONG) 0L;
|
||
|
||
VER_SET_CONDITION( dwlConditionMask, VER_SUITENAME, VER_AND );
|
||
|
||
if ( VerifyVersionInfo( &osiv, VER_SUITENAME, dwlConditionMask ) == TRUE )
|
||
{
|
||
dwSuiteType = EmbeddedNT;
|
||
goto Cleanup;
|
||
}
|
||
|
||
// Finally check if this is any Server.
|
||
|
||
if ( GetVersionEx( (LPOSVERSIONINFO) &osiv ) ) {
|
||
if ( osiv.wProductType == VER_NT_SERVER ) {
|
||
dwSuiteType = VER_SERVER_NT;
|
||
goto Cleanup;
|
||
}
|
||
}
|
||
|
||
Cleanup:
|
||
return( dwSuiteType );
|
||
|
||
} // ClRtlGetSuiteType
|