windows-nt/Source/XPSP1/NT/base/ntsetup/winnt32/boscomp/boscomp.cpp
2020-09-26 16:20:57 +08:00

471 lines
13 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1998.
//
// File: boscomp.cpp
//
// Contents: DllMain
//
// Notes: modified from windows\setup\winnt32\apmupgrd.cpp by wnelson
//
// Author: wnelson 2 Apr 99
//
// ShaoYin 9 Sep 99 revised, add support for Exchange Server
//
//----------------------------------------------------------------------------
#include <winnt32.h>
#include "boscomp.h"
#include "resource.h"
HINSTANCE g_hinst;
// help text files
TCHAR szErrorHTM[] = TEXT("compdata\\boserror.htm");
TCHAR szErrorTXT[] = TEXT("compdata\\boserror.txt");
// help text files (Exchange Server)
TCHAR szExchangeHTM[] = TEXT("compdata\\exchange.htm");
TCHAR szExchangeTXT[] = TEXT("compdata\\exchange.txt");
// bos/sbs 4.5 reg keys, value names, and possible values
const TCHAR szBosKey[] = TEXT("Software\\Microsoft\\Backoffice");
const TCHAR szFamilyIdKey[] = TEXT("FamilyID");
const TCHAR szBosFamilyId[] = TEXT("8D4BCD88-3236-11d2-AB4E-00C04FB1799F");
const TCHAR szSbsFamilyId[] = TEXT("EE2D3727-33C0-11d2-AB50-00C04FB1799F");
const TCHAR szSuiteVersionKey[] = TEXT("SuiteVersion");
const TCHAR szSuiteNameKey[] = TEXT("SuiteName");
const TCHAR sz45Version[] = TEXT("4.5");
const TCHAR szBosName[] = TEXT("BackOffice Server");
const TCHAR szSbsName[] = TEXT("Small Business Server");
// sbs 4.0x reg keys, value names, and values
const TCHAR szSbsKey[] = TEXT("Software\\Microsoft\\Small Business");
const TCHAR szSbsVersionKey[] = TEXT("Version");
const TCHAR szSbs40AVersion[] = TEXT("4.0a");
const TCHAR szProductOptionsKey[] = TEXT("System\\CurrentControlSet\\Control\\ProductOptions");
//const TCHAR szProductOptionsKey[] = TEXT("software\\test");
const TCHAR szProductSuiteKey[] = TEXT("ProductSuite");
const TCHAR szSbsProductSuiteValue[] = TEXT("Small Business");
const TCHAR szSbsRestrictedProductSuiteValue[] = TEXT("Small Business(Restricted)");
// bos 4.0 version
TCHAR szBos40VersionKey[] = TEXT("Version");
TCHAR szBos40Version[] = TEXT("4.0");
// bos 2.5 key
TCHAR szBos25Key[] = TEXT("2.5");
// Exchange 5.5 reg keys, value names.
const TCHAR szExchangeKey[] = TEXT("Software\\Microsoft\\Exchange\\Setup");
const TCHAR szExchangeVerKey[] = TEXT("NewestBuild");
const DWORD dwExchangeVer55 = 0x7a8;
// Exchange 5.5 Server Pack reg key and value name.
const TCHAR szExchangeSvcPackKey[] = TEXT("ServicePackBuild");
const DWORD dwExchangeSvcPack3 = 0xa5a;
//+---------------------------------------------------------------------------
//
// Function: DllMain
//
// Purpose: constructor
//
// Arguments: Standard DLL entry point arguments
//
// Author: wnelson 2 Apr 99
//
// Notes: from kumarp 12 April 97
//
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance,
DWORD dwReasonForCall,
LPVOID lpReserved)
{
BOOL status = TRUE;
switch( dwReasonForCall )
{
case DLL_PROCESS_ATTACH:
{
g_hinst = hInstance;
DisableThreadLibraryCalls(hInstance);
}
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return status;
}
//+----------------------------------------------------------------------
//
// Function: BosHardBlockCheck
//
// Purpose: This function is called by winnt32.exe so that we
// can check for installed bos/sbs suites that cannot be upgraded to Win2k.
//
//
//
// Arguments:
// CompatibilityCallback [in] pointer to COMPATIBILITYCALLBACK fn
// Context [in] pointer to compatibility context
//
// FALSE if Win2k setup can continue.
// TRUE if Win2k cannot upgrade the installed suite.
//
// Author: wnelson 2 Apr 99
//
// Notes:
// TRUE is returned in the following cases: BOS 2.5; SBS 4.0,4.0a; BOS 4.0
// For SBS, it does not matter if they've upgraded to full NT Server; they still have to
// upgrade their suite to BackOffice 4.5 in order to continue.
//
BOOL WINAPI BosHardBlockCheck(IN PCOMPAIBILITYCALLBACK CompatibilityCallback,IN LPVOID Context)
{
SuiteVersion eVersion=DetermineInstalledSuite();
if (eVersion==VER_NONE || eVersion==VER_BOS45 || eVersion==VER_POST45) return FALSE;
TCHAR szMsg[1024];
GetSuiteMessage(eVersion,szMsg,1024);
// Use the callback function to send the signal
COMPATIBILITY_ENTRY ce;
ZeroMemory(&ce,sizeof(COMPATIBILITY_ENTRY));
ce.Description = szMsg;
ce.HtmlName = szErrorHTM; // defined above
ce.TextName = szErrorTXT; // defined above
ce.RegKeyName = NULL;
ce.RegValName = NULL;
ce.RegValDataSize = 0;
ce.RegValData = NULL;
ce.SaveValue = NULL;
ce.Flags = 0;
CompatibilityCallback(&ce, Context);
return TRUE;
}
//+----------------------------------------------------------------------
//
// Function: BosSoftBlockCheck
//
// Purpose: This function is called by winnt32.exe so that we
// can check for an installed sbs/bos suite with possible upgrade problems.
//
//
//
// Arguments:
// CompatibilityCallback [in] pointer to COMPATIBILITYCALLBACK fn
// Context [in] pointer to compatibility context
//
// FALSE if Win2k setup can continue.
// TRUE if Win2k setup needs to warn the user that upgrade may impair functionality of installed suite.
//
// Author: wnelson 2 Apr 99
//
// ShaoYin 9 Sep 99, add support for Exchange Server
//
// Notes:
// TRUE is returned in the following cases: BOS 4.5
//
BOOL WINAPI BosSoftBlockCheck(IN PCOMPAIBILITYCALLBACK CompatibilityCallback,IN LPVOID Context)
{
BOOL result = FALSE;
SuiteVersion eVersion=DetermineInstalledSuite();
if (eVersion==VER_BOS45)
{
TCHAR szMsg[1024];
GetSuiteMessage(eVersion,szMsg,1024);
// Use the callback function to send the signal
COMPATIBILITY_ENTRY ce;
ZeroMemory(&ce,sizeof(COMPATIBILITY_ENTRY));
ce.Description = szMsg;
ce.HtmlName = szErrorHTM; // defined above
ce.TextName = szErrorTXT; // defined above
ce.RegKeyName = NULL;
ce.RegValName = NULL;
ce.RegValDataSize = 0;
ce.RegValData = NULL;
ce.SaveValue = NULL;
ce.Flags = 0;
CompatibilityCallback(&ce, Context);
result = TRUE;
}
ExchangeVersion exVersion = DetermineExchangeVersion();
if (exVersion == EXCHANGE_VER_PRE55SP3)
{
TCHAR szMsgExchange[1024];
COMPATIBILITY_ENTRY cExchange;
LoadResString(IDS_Exchange, szMsgExchange, 1024);
ZeroMemory(&cExchange, sizeof(COMPATIBILITY_ENTRY));
cExchange.Description = szMsgExchange;
cExchange.HtmlName = szExchangeHTM;
cExchange.TextName = szExchangeTXT;
cExchange.RegKeyName = NULL;
cExchange.RegValName = NULL;
cExchange.RegValData = NULL;
cExchange.RegValDataSize = 0;
cExchange.SaveValue = NULL;
cExchange.Flags = 0;
CompatibilityCallback(&cExchange, Context);
result = TRUE;
}
return( result );
}
SuiteVersion DetermineInstalledSuite()
{
SuiteVersion eVersion=VER_NONE;
HKEY hKey,hKey25;
TCHAR szFamilyId[256], szVersion[256], szSuiteName[256];
DWORD dwVerLen1=256, dwVerLen2=256, dwNameLen=256, dwIdLen=256;
DWORD dwDataType=REG_SZ;
//
// First look for versions using the bos key (i.e., all bos versions and sbs 4.5 or later)
//
if (ERROR_SUCCESS==RegOpenKey(HKEY_LOCAL_MACHINE,szBosKey,&hKey))
{
if(ERROR_SUCCESS==RegQueryValueEx(hKey,szSuiteVersionKey,0,&dwDataType,(LPBYTE)szVersion,&dwVerLen1))
{
if(0==_tcsicmp(szVersion,sz45Version))
{
// Some 4.5 version is on the box.
if (ERROR_SUCCESS==RegQueryValueEx(hKey,szFamilyIdKey,0,&dwDataType,(LPBYTE)szFamilyId,&dwIdLen))
{
if (0==_tcsicmp(szFamilyId,szBosFamilyId) )
{
eVersion=VER_BOS45;
}
else if (0==_tcsicmp(szFamilyId,szSbsFamilyId) )
{
eVersion=VER_SBS45;
}
}
else
{
// The guid just checked is the official version marker; however, 4.5 beta 1 did
// not use the guids. This version is timebombed and should be dead, but just in case
// we'll check the suite name string also.
if (ERROR_SUCCESS==RegQueryValueEx(hKey,szSuiteNameKey,0,&dwDataType, (LPBYTE)szSuiteName,&dwNameLen))
{
if (0==_tcsicmp(szSuiteName,szBosName))
{
eVersion=VER_BOS45;
}
else if (0==_tcsicmp(szSuiteName,szSbsName))
{
eVersion=VER_SBS45;
}
}
}
}
else
{
// A later version is on the box
eVersion=VER_POST45;
}
}
// look for bos 4.0
else if (ERROR_SUCCESS==RegQueryValueEx(hKey,szBos40VersionKey,0,&dwDataType,(LPBYTE)szVersion,&dwVerLen2) && 0==_tcsicmp(szBos40Version,szVersion))
{
eVersion=VER_BOS40;
}
// look for bos 2.5
else if (ERROR_SUCCESS==RegOpenKey(hKey,szBos25Key,&hKey25))
{
eVersion=VER_BOS25;
RegCloseKey(hKey25);
}
RegCloseKey(hKey);
}
//
// Look for SBS versions 4.0a, and 4.0.
//
else if (ProductSuiteContains(szSbsProductSuiteValue))
{
//
// If we get here, SBS 4.0 or 4.0a is on the box.
//
if (ERROR_SUCCESS==RegOpenKey(HKEY_LOCAL_MACHINE,szSbsKey,&hKey))
{
TCHAR szVersion[256];
DWORD dwVerLen=256;
DWORD dwDataType=REG_SZ;
if (ERROR_SUCCESS==RegQueryValueEx(hKey,szSbsVersionKey,0,&dwDataType,(LPBYTE)szVersion,&dwVerLen) &&
0==_tcsicmp(szVersion,szSbs40AVersion))
{
eVersion=VER_SBS40A;
}
else
{
eVersion=VER_SBS40;
}
RegCloseKey(hKey);
}
}
// We have to make sure the user isn't tricking us into allowing Win2k to upgrade
// restricted sbs nt.
if (eVersion==VER_NONE || eVersion==VER_BOS45 || eVersion==VER_POST45)
{
if (ProductSuiteContains(szSbsRestrictedProductSuiteValue))
{
// User tried to fool us by altering version info.
eVersion=VER_SBSREST;
}
}
return eVersion;
}
// return the display string for the version in question.
void GetSuiteMessage(SuiteVersion eSV, TCHAR* szMsg, UINT nLen)
{
szMsg[0]=0;
switch (eSV)
{
case VER_NONE:
break;
case VER_BOS45:
LoadResString(IDS_Bos45Msg,szMsg,nLen);
break;
case VER_BOS40:
LoadResString(IDS_Bos40Msg,szMsg,nLen);
break;
case VER_BOS25:
LoadResString(IDS_Bos25Msg,szMsg,nLen);
break;
case VER_SBS45:
LoadResString(IDS_Sbs45Msg,szMsg,nLen);
break;
case VER_SBS40:
LoadResString(IDS_Sbs40Msg,szMsg,nLen);
break;
case VER_SBS40A:
LoadResString(IDS_Sbs40AMsg,szMsg,nLen);
break;
case VER_SBSREST:
LoadResString(IDS_SbsRestMsg,szMsg,nLen);
break;
}
}
void LoadResString(UINT nRes, TCHAR* szString, UINT nLen)
{
if(!LoadString(g_hinst, nRes, szString, nLen))
{
szString[0] = 0;
}
}
// Check the ProductOptions\ProductSuite multi-sz value for the string szTest.
bool ProductSuiteContains(const TCHAR* szTest)
{
bool bRet=false;
HKEY hKey;
unsigned char* Value=NULL;
TCHAR* szValue;
DWORD dwDataLen=0;
DWORD dwDataType=REG_MULTI_SZ;
if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE,szProductOptionsKey,&hKey) )
{
// see how big the data will be
if (ERROR_SUCCESS == RegQueryValueEx(hKey,szProductSuiteKey,0,&dwDataType,NULL,&dwDataLen))
{
Value=new unsigned char[dwDataLen];
if (Value != NULL && dwDataLen != 1) // if the multi-sz is empty, we get back dataLen=1 and don't need to go further
{
if (RegQueryValueEx(hKey,szProductSuiteKey,0,&dwDataType,Value,&dwDataLen) == ERROR_SUCCESS)
{
szValue=(TCHAR*)Value;
for (UINT n = 1 ; *szValue != 0 ; szValue += _tcslen(szValue) + 1)
{
if ( _tcsstr(szValue, szTest) != 0)
{
bRet=true;
break;
}
}
}
}
if (Value != NULL) delete[] Value;
}
RegCloseKey(hKey);
}
return bRet;
}
ExchangeVersion DetermineExchangeVersion()
{
ExchangeVersion eVersion=EXCHANGE_VER_NONE;
HKEY hExchangeKey;
DWORD dwCurrentVer, dwCurrentSvcPackVer;
DWORD dwVerLen=sizeof(DWORD);
DWORD dwDataType=REG_DWORD;
//
// First look for versions using the Exchange key
//
if (ERROR_SUCCESS==RegOpenKey(HKEY_LOCAL_MACHINE,szExchangeKey,&hExchangeKey))
{
if(ERROR_SUCCESS==RegQueryValueEx(hExchangeKey,szExchangeVerKey,0,&dwDataType,(LPBYTE)&dwCurrentVer,&dwVerLen))
{
if (dwCurrentVer < dwExchangeVer55)
{
// prior Exchange 5.5
eVersion=EXCHANGE_VER_PRE55SP3;
}
else if (dwCurrentVer == dwExchangeVer55)
{
// Exchange 5.5 version is on the box.
if (ERROR_SUCCESS==RegQueryValueEx(hExchangeKey,szExchangeSvcPackKey,0,&dwDataType,(LPBYTE)&dwCurrentSvcPackVer,&dwVerLen))
{
if (dwCurrentSvcPackVer >= dwExchangeSvcPack3)
{
// has Service Pack 3 installed
eVersion=EXCHANGE_VER_POST55SP3;
}
else
{
// no Service Pack 3
eVersion=EXCHANGE_VER_PRE55SP3;
}
}
else
{
// no Servie Pack 3
eVersion=EXCHANGE_VER_PRE55SP3;
}
}
}
RegCloseKey(hExchangeKey);
}
return eVersion;
}