Source code of Windows XP (NT5)
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.

470 lines
13 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998.
  5. //
  6. // File: boscomp.cpp
  7. //
  8. // Contents: DllMain
  9. //
  10. // Notes: modified from windows\setup\winnt32\apmupgrd.cpp by wnelson
  11. //
  12. // Author: wnelson 2 Apr 99
  13. //
  14. // ShaoYin 9 Sep 99 revised, add support for Exchange Server
  15. //
  16. //----------------------------------------------------------------------------
  17. #include <winnt32.h>
  18. #include "boscomp.h"
  19. #include "resource.h"
  20. HINSTANCE g_hinst;
  21. // help text files
  22. TCHAR szErrorHTM[] = TEXT("compdata\\boserror.htm");
  23. TCHAR szErrorTXT[] = TEXT("compdata\\boserror.txt");
  24. // help text files (Exchange Server)
  25. TCHAR szExchangeHTM[] = TEXT("compdata\\exchange.htm");
  26. TCHAR szExchangeTXT[] = TEXT("compdata\\exchange.txt");
  27. // bos/sbs 4.5 reg keys, value names, and possible values
  28. const TCHAR szBosKey[] = TEXT("Software\\Microsoft\\Backoffice");
  29. const TCHAR szFamilyIdKey[] = TEXT("FamilyID");
  30. const TCHAR szBosFamilyId[] = TEXT("8D4BCD88-3236-11d2-AB4E-00C04FB1799F");
  31. const TCHAR szSbsFamilyId[] = TEXT("EE2D3727-33C0-11d2-AB50-00C04FB1799F");
  32. const TCHAR szSuiteVersionKey[] = TEXT("SuiteVersion");
  33. const TCHAR szSuiteNameKey[] = TEXT("SuiteName");
  34. const TCHAR sz45Version[] = TEXT("4.5");
  35. const TCHAR szBosName[] = TEXT("BackOffice Server");
  36. const TCHAR szSbsName[] = TEXT("Small Business Server");
  37. // sbs 4.0x reg keys, value names, and values
  38. const TCHAR szSbsKey[] = TEXT("Software\\Microsoft\\Small Business");
  39. const TCHAR szSbsVersionKey[] = TEXT("Version");
  40. const TCHAR szSbs40AVersion[] = TEXT("4.0a");
  41. const TCHAR szProductOptionsKey[] = TEXT("System\\CurrentControlSet\\Control\\ProductOptions");
  42. //const TCHAR szProductOptionsKey[] = TEXT("software\\test");
  43. const TCHAR szProductSuiteKey[] = TEXT("ProductSuite");
  44. const TCHAR szSbsProductSuiteValue[] = TEXT("Small Business");
  45. const TCHAR szSbsRestrictedProductSuiteValue[] = TEXT("Small Business(Restricted)");
  46. // bos 4.0 version
  47. TCHAR szBos40VersionKey[] = TEXT("Version");
  48. TCHAR szBos40Version[] = TEXT("4.0");
  49. // bos 2.5 key
  50. TCHAR szBos25Key[] = TEXT("2.5");
  51. // Exchange 5.5 reg keys, value names.
  52. const TCHAR szExchangeKey[] = TEXT("Software\\Microsoft\\Exchange\\Setup");
  53. const TCHAR szExchangeVerKey[] = TEXT("NewestBuild");
  54. const DWORD dwExchangeVer55 = 0x7a8;
  55. // Exchange 5.5 Server Pack reg key and value name.
  56. const TCHAR szExchangeSvcPackKey[] = TEXT("ServicePackBuild");
  57. const DWORD dwExchangeSvcPack3 = 0xa5a;
  58. //+---------------------------------------------------------------------------
  59. //
  60. // Function: DllMain
  61. //
  62. // Purpose: constructor
  63. //
  64. // Arguments: Standard DLL entry point arguments
  65. //
  66. // Author: wnelson 2 Apr 99
  67. //
  68. // Notes: from kumarp 12 April 97
  69. //
  70. extern "C"
  71. BOOL WINAPI DllMain(HINSTANCE hInstance,
  72. DWORD dwReasonForCall,
  73. LPVOID lpReserved)
  74. {
  75. BOOL status = TRUE;
  76. switch( dwReasonForCall )
  77. {
  78. case DLL_PROCESS_ATTACH:
  79. {
  80. g_hinst = hInstance;
  81. DisableThreadLibraryCalls(hInstance);
  82. }
  83. break;
  84. case DLL_PROCESS_DETACH:
  85. case DLL_THREAD_ATTACH:
  86. case DLL_THREAD_DETACH:
  87. break;
  88. }
  89. return status;
  90. }
  91. //+----------------------------------------------------------------------
  92. //
  93. // Function: BosHardBlockCheck
  94. //
  95. // Purpose: This function is called by winnt32.exe so that we
  96. // can check for installed bos/sbs suites that cannot be upgraded to Win2k.
  97. //
  98. //
  99. //
  100. // Arguments:
  101. // CompatibilityCallback [in] pointer to COMPATIBILITYCALLBACK fn
  102. // Context [in] pointer to compatibility context
  103. //
  104. // FALSE if Win2k setup can continue.
  105. // TRUE if Win2k cannot upgrade the installed suite.
  106. //
  107. // Author: wnelson 2 Apr 99
  108. //
  109. // Notes:
  110. // TRUE is returned in the following cases: BOS 2.5; SBS 4.0,4.0a; BOS 4.0
  111. // For SBS, it does not matter if they've upgraded to full NT Server; they still have to
  112. // upgrade their suite to BackOffice 4.5 in order to continue.
  113. //
  114. BOOL WINAPI BosHardBlockCheck(IN PCOMPAIBILITYCALLBACK CompatibilityCallback,IN LPVOID Context)
  115. {
  116. SuiteVersion eVersion=DetermineInstalledSuite();
  117. if (eVersion==VER_NONE || eVersion==VER_BOS45 || eVersion==VER_POST45) return FALSE;
  118. TCHAR szMsg[1024];
  119. GetSuiteMessage(eVersion,szMsg,1024);
  120. // Use the callback function to send the signal
  121. COMPATIBILITY_ENTRY ce;
  122. ZeroMemory(&ce,sizeof(COMPATIBILITY_ENTRY));
  123. ce.Description = szMsg;
  124. ce.HtmlName = szErrorHTM; // defined above
  125. ce.TextName = szErrorTXT; // defined above
  126. ce.RegKeyName = NULL;
  127. ce.RegValName = NULL;
  128. ce.RegValDataSize = 0;
  129. ce.RegValData = NULL;
  130. ce.SaveValue = NULL;
  131. ce.Flags = 0;
  132. CompatibilityCallback(&ce, Context);
  133. return TRUE;
  134. }
  135. //+----------------------------------------------------------------------
  136. //
  137. // Function: BosSoftBlockCheck
  138. //
  139. // Purpose: This function is called by winnt32.exe so that we
  140. // can check for an installed sbs/bos suite with possible upgrade problems.
  141. //
  142. //
  143. //
  144. // Arguments:
  145. // CompatibilityCallback [in] pointer to COMPATIBILITYCALLBACK fn
  146. // Context [in] pointer to compatibility context
  147. //
  148. // FALSE if Win2k setup can continue.
  149. // TRUE if Win2k setup needs to warn the user that upgrade may impair functionality of installed suite.
  150. //
  151. // Author: wnelson 2 Apr 99
  152. //
  153. // ShaoYin 9 Sep 99, add support for Exchange Server
  154. //
  155. // Notes:
  156. // TRUE is returned in the following cases: BOS 4.5
  157. //
  158. BOOL WINAPI BosSoftBlockCheck(IN PCOMPAIBILITYCALLBACK CompatibilityCallback,IN LPVOID Context)
  159. {
  160. BOOL result = FALSE;
  161. SuiteVersion eVersion=DetermineInstalledSuite();
  162. if (eVersion==VER_BOS45)
  163. {
  164. TCHAR szMsg[1024];
  165. GetSuiteMessage(eVersion,szMsg,1024);
  166. // Use the callback function to send the signal
  167. COMPATIBILITY_ENTRY ce;
  168. ZeroMemory(&ce,sizeof(COMPATIBILITY_ENTRY));
  169. ce.Description = szMsg;
  170. ce.HtmlName = szErrorHTM; // defined above
  171. ce.TextName = szErrorTXT; // defined above
  172. ce.RegKeyName = NULL;
  173. ce.RegValName = NULL;
  174. ce.RegValDataSize = 0;
  175. ce.RegValData = NULL;
  176. ce.SaveValue = NULL;
  177. ce.Flags = 0;
  178. CompatibilityCallback(&ce, Context);
  179. result = TRUE;
  180. }
  181. ExchangeVersion exVersion = DetermineExchangeVersion();
  182. if (exVersion == EXCHANGE_VER_PRE55SP3)
  183. {
  184. TCHAR szMsgExchange[1024];
  185. COMPATIBILITY_ENTRY cExchange;
  186. LoadResString(IDS_Exchange, szMsgExchange, 1024);
  187. ZeroMemory(&cExchange, sizeof(COMPATIBILITY_ENTRY));
  188. cExchange.Description = szMsgExchange;
  189. cExchange.HtmlName = szExchangeHTM;
  190. cExchange.TextName = szExchangeTXT;
  191. cExchange.RegKeyName = NULL;
  192. cExchange.RegValName = NULL;
  193. cExchange.RegValData = NULL;
  194. cExchange.RegValDataSize = 0;
  195. cExchange.SaveValue = NULL;
  196. cExchange.Flags = 0;
  197. CompatibilityCallback(&cExchange, Context);
  198. result = TRUE;
  199. }
  200. return( result );
  201. }
  202. SuiteVersion DetermineInstalledSuite()
  203. {
  204. SuiteVersion eVersion=VER_NONE;
  205. HKEY hKey,hKey25;
  206. TCHAR szFamilyId[256], szVersion[256], szSuiteName[256];
  207. DWORD dwVerLen1=256, dwVerLen2=256, dwNameLen=256, dwIdLen=256;
  208. DWORD dwDataType=REG_SZ;
  209. //
  210. // First look for versions using the bos key (i.e., all bos versions and sbs 4.5 or later)
  211. //
  212. if (ERROR_SUCCESS==RegOpenKey(HKEY_LOCAL_MACHINE,szBosKey,&hKey))
  213. {
  214. if(ERROR_SUCCESS==RegQueryValueEx(hKey,szSuiteVersionKey,0,&dwDataType,(LPBYTE)szVersion,&dwVerLen1))
  215. {
  216. if(0==_tcsicmp(szVersion,sz45Version))
  217. {
  218. // Some 4.5 version is on the box.
  219. if (ERROR_SUCCESS==RegQueryValueEx(hKey,szFamilyIdKey,0,&dwDataType,(LPBYTE)szFamilyId,&dwIdLen))
  220. {
  221. if (0==_tcsicmp(szFamilyId,szBosFamilyId) )
  222. {
  223. eVersion=VER_BOS45;
  224. }
  225. else if (0==_tcsicmp(szFamilyId,szSbsFamilyId) )
  226. {
  227. eVersion=VER_SBS45;
  228. }
  229. }
  230. else
  231. {
  232. // The guid just checked is the official version marker; however, 4.5 beta 1 did
  233. // not use the guids. This version is timebombed and should be dead, but just in case
  234. // we'll check the suite name string also.
  235. if (ERROR_SUCCESS==RegQueryValueEx(hKey,szSuiteNameKey,0,&dwDataType, (LPBYTE)szSuiteName,&dwNameLen))
  236. {
  237. if (0==_tcsicmp(szSuiteName,szBosName))
  238. {
  239. eVersion=VER_BOS45;
  240. }
  241. else if (0==_tcsicmp(szSuiteName,szSbsName))
  242. {
  243. eVersion=VER_SBS45;
  244. }
  245. }
  246. }
  247. }
  248. else
  249. {
  250. // A later version is on the box
  251. eVersion=VER_POST45;
  252. }
  253. }
  254. // look for bos 4.0
  255. else if (ERROR_SUCCESS==RegQueryValueEx(hKey,szBos40VersionKey,0,&dwDataType,(LPBYTE)szVersion,&dwVerLen2) && 0==_tcsicmp(szBos40Version,szVersion))
  256. {
  257. eVersion=VER_BOS40;
  258. }
  259. // look for bos 2.5
  260. else if (ERROR_SUCCESS==RegOpenKey(hKey,szBos25Key,&hKey25))
  261. {
  262. eVersion=VER_BOS25;
  263. RegCloseKey(hKey25);
  264. }
  265. RegCloseKey(hKey);
  266. }
  267. //
  268. // Look for SBS versions 4.0a, and 4.0.
  269. //
  270. else if (ProductSuiteContains(szSbsProductSuiteValue))
  271. {
  272. //
  273. // If we get here, SBS 4.0 or 4.0a is on the box.
  274. //
  275. if (ERROR_SUCCESS==RegOpenKey(HKEY_LOCAL_MACHINE,szSbsKey,&hKey))
  276. {
  277. TCHAR szVersion[256];
  278. DWORD dwVerLen=256;
  279. DWORD dwDataType=REG_SZ;
  280. if (ERROR_SUCCESS==RegQueryValueEx(hKey,szSbsVersionKey,0,&dwDataType,(LPBYTE)szVersion,&dwVerLen) &&
  281. 0==_tcsicmp(szVersion,szSbs40AVersion))
  282. {
  283. eVersion=VER_SBS40A;
  284. }
  285. else
  286. {
  287. eVersion=VER_SBS40;
  288. }
  289. RegCloseKey(hKey);
  290. }
  291. }
  292. // We have to make sure the user isn't tricking us into allowing Win2k to upgrade
  293. // restricted sbs nt.
  294. if (eVersion==VER_NONE || eVersion==VER_BOS45 || eVersion==VER_POST45)
  295. {
  296. if (ProductSuiteContains(szSbsRestrictedProductSuiteValue))
  297. {
  298. // User tried to fool us by altering version info.
  299. eVersion=VER_SBSREST;
  300. }
  301. }
  302. return eVersion;
  303. }
  304. // return the display string for the version in question.
  305. void GetSuiteMessage(SuiteVersion eSV, TCHAR* szMsg, UINT nLen)
  306. {
  307. szMsg[0]=0;
  308. switch (eSV)
  309. {
  310. case VER_NONE:
  311. break;
  312. case VER_BOS45:
  313. LoadResString(IDS_Bos45Msg,szMsg,nLen);
  314. break;
  315. case VER_BOS40:
  316. LoadResString(IDS_Bos40Msg,szMsg,nLen);
  317. break;
  318. case VER_BOS25:
  319. LoadResString(IDS_Bos25Msg,szMsg,nLen);
  320. break;
  321. case VER_SBS45:
  322. LoadResString(IDS_Sbs45Msg,szMsg,nLen);
  323. break;
  324. case VER_SBS40:
  325. LoadResString(IDS_Sbs40Msg,szMsg,nLen);
  326. break;
  327. case VER_SBS40A:
  328. LoadResString(IDS_Sbs40AMsg,szMsg,nLen);
  329. break;
  330. case VER_SBSREST:
  331. LoadResString(IDS_SbsRestMsg,szMsg,nLen);
  332. break;
  333. }
  334. }
  335. void LoadResString(UINT nRes, TCHAR* szString, UINT nLen)
  336. {
  337. if(!LoadString(g_hinst, nRes, szString, nLen))
  338. {
  339. szString[0] = 0;
  340. }
  341. }
  342. // Check the ProductOptions\ProductSuite multi-sz value for the string szTest.
  343. bool ProductSuiteContains(const TCHAR* szTest)
  344. {
  345. bool bRet=false;
  346. HKEY hKey;
  347. unsigned char* Value=NULL;
  348. TCHAR* szValue;
  349. DWORD dwDataLen=0;
  350. DWORD dwDataType=REG_MULTI_SZ;
  351. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE,szProductOptionsKey,&hKey) )
  352. {
  353. // see how big the data will be
  354. if (ERROR_SUCCESS == RegQueryValueEx(hKey,szProductSuiteKey,0,&dwDataType,NULL,&dwDataLen))
  355. {
  356. Value=new unsigned char[dwDataLen];
  357. if (Value != NULL && dwDataLen != 1) // if the multi-sz is empty, we get back dataLen=1 and don't need to go further
  358. {
  359. if (RegQueryValueEx(hKey,szProductSuiteKey,0,&dwDataType,Value,&dwDataLen) == ERROR_SUCCESS)
  360. {
  361. szValue=(TCHAR*)Value;
  362. for (UINT n = 1 ; *szValue != 0 ; szValue += _tcslen(szValue) + 1)
  363. {
  364. if ( _tcsstr(szValue, szTest) != 0)
  365. {
  366. bRet=true;
  367. break;
  368. }
  369. }
  370. }
  371. }
  372. if (Value != NULL) delete[] Value;
  373. }
  374. RegCloseKey(hKey);
  375. }
  376. return bRet;
  377. }
  378. ExchangeVersion DetermineExchangeVersion()
  379. {
  380. ExchangeVersion eVersion=EXCHANGE_VER_NONE;
  381. HKEY hExchangeKey;
  382. DWORD dwCurrentVer, dwCurrentSvcPackVer;
  383. DWORD dwVerLen=sizeof(DWORD);
  384. DWORD dwDataType=REG_DWORD;
  385. //
  386. // First look for versions using the Exchange key
  387. //
  388. if (ERROR_SUCCESS==RegOpenKey(HKEY_LOCAL_MACHINE,szExchangeKey,&hExchangeKey))
  389. {
  390. if(ERROR_SUCCESS==RegQueryValueEx(hExchangeKey,szExchangeVerKey,0,&dwDataType,(LPBYTE)&dwCurrentVer,&dwVerLen))
  391. {
  392. if (dwCurrentVer < dwExchangeVer55)
  393. {
  394. // prior Exchange 5.5
  395. eVersion=EXCHANGE_VER_PRE55SP3;
  396. }
  397. else if (dwCurrentVer == dwExchangeVer55)
  398. {
  399. // Exchange 5.5 version is on the box.
  400. if (ERROR_SUCCESS==RegQueryValueEx(hExchangeKey,szExchangeSvcPackKey,0,&dwDataType,(LPBYTE)&dwCurrentSvcPackVer,&dwVerLen))
  401. {
  402. if (dwCurrentSvcPackVer >= dwExchangeSvcPack3)
  403. {
  404. // has Service Pack 3 installed
  405. eVersion=EXCHANGE_VER_POST55SP3;
  406. }
  407. else
  408. {
  409. // no Service Pack 3
  410. eVersion=EXCHANGE_VER_PRE55SP3;
  411. }
  412. }
  413. else
  414. {
  415. // no Servie Pack 3
  416. eVersion=EXCHANGE_VER_PRE55SP3;
  417. }
  418. }
  419. }
  420. RegCloseKey(hExchangeKey);
  421. }
  422. return eVersion;
  423. }