/*++ 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 #include 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