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.

380 lines
12 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1996-1998 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ClusComp.cpp
  7. //
  8. // Abstract:
  9. // This file implements the Clustering Service Upgrade Compatibility Check DLL.
  10. // The DLL gets executed by winnt32. It's purpose is to alert the user to possible
  11. // incompatibilities that may be encountered after performing an upgrade.
  12. //
  13. // At this time, 8/4/98, the only known incompatibility that may arise stems
  14. // from upgrading NTSE 4.0 with MSCS installed.
  15. //
  16. // Author:
  17. // C. Brent Thomas (a-brentt)
  18. //
  19. // Revision History:
  20. // 8/4/98 - original
  21. //
  22. // Notes:
  23. //
  24. /////////////////////////////////////////////////////////////////////////////
  25. #include <windows.h>
  26. #include <tchar.h>
  27. #include <winuser.h>
  28. #include <comp.h>
  29. #include <clusapi.h>
  30. #include <IsClusterServiceRegistered.h>
  31. #include "resource.h"
  32. HMODULE ghInstance;
  33. /////////////////////////////////////////////////////////////////////////////
  34. //++
  35. //
  36. // DllMain
  37. //
  38. // Routine Description:
  39. // DLL entry point
  40. //
  41. // Arguments:
  42. //
  43. //
  44. //
  45. // Return Value:
  46. //
  47. // Note:
  48. // This function was copied from msmqcomp.dll.
  49. //
  50. //--
  51. /////////////////////////////////////////////////////////////////////////////
  52. BOOL DllMain( IN const HANDLE DllHandle, IN const DWORD Reason, IN const LPVOID Reserved )
  53. {
  54. switch ( Reason )
  55. {
  56. case DLL_PROCESS_ATTACH:
  57. ghInstance = (HINSTANCE)DllHandle;
  58. break;
  59. case DLL_PROCESS_DETACH:
  60. break;
  61. default:
  62. break;
  63. }
  64. return TRUE;
  65. } //DllMain
  66. /////////////////////////////////////////////////////////////////////////////
  67. //++
  68. //
  69. // ClusterUpgradeCompatibilityCheck
  70. //
  71. // Routine Description:
  72. // This function is the exported function for cluscomp.dll, the Cluster Upgrade
  73. // Compatibility Check DLL called by winnt32 to handle incompatibilities when
  74. // upgrading the Clustering Service.
  75. //
  76. // Arguments:
  77. // pfnCompatibilityCallback - points to the callback function used to supply
  78. // compatibility information to winnt32.exe.
  79. // pvContext - points to a context buffer supplied by winnt32.exe.
  80. //
  81. //
  82. // Return Value:
  83. // TRUE - either indicates that no incompatibility was detected or that
  84. // *pfnComaptibilityCallback() returned TRUE.
  85. // FALSE - *pfnCompatibilityCallback() returned FALSE
  86. //
  87. //--
  88. /////////////////////////////////////////////////////////////////////////////
  89. BOOL ClusterUpgradeCompatibilityCheck( PCOMPAIBILITYCALLBACK pfnCompatibilityCallback,
  90. LPVOID pvContext )
  91. {
  92. BOOL IsCompatibilityWarningRequired( void );
  93. BOOL fReturnValue = (BOOL) TRUE;
  94. // Is the cluster service registered with the Service Control Manager?
  95. // If the cluster service is not registered that means that Clustering Service
  96. // has not been installed. That implies that there can be no incompatibility.
  97. if ( IsClusterServiceRegistered() == (BOOL) TRUE )
  98. {
  99. // Get the current operating system version. Note that this cannot call
  100. // VerifyVersionInfo() which requires Windows 2000.
  101. OSVERSIONINFO OsVersionInfo;
  102. OsVersionInfo.dwOSVersionInfoSize = sizeof( OsVersionInfo );
  103. GetVersionEx( &OsVersionInfo );
  104. // As per Bohdan R. and David P., 8/6/98, no compatibility warning is
  105. // required if the system being upgraded is already at NT 5 or later.
  106. if ( (OsVersionInfo.dwPlatformId == (DWORD) VER_PLATFORM_WIN32_NT) &&
  107. (OsVersionInfo.dwMajorVersion < (DWORD) 5) )
  108. {
  109. // Determine whether a compatibility warning is necessary.
  110. BOOL fCompatibilityWarningRequired;
  111. fCompatibilityWarningRequired = IsCompatibilityWarningRequired();
  112. // Is it necessary to display a compatibility warning?
  113. if ( fCompatibilityWarningRequired == (BOOL) TRUE )
  114. {
  115. // It is necessary to display a compatibility warning.
  116. TCHAR tszDescription[100]; // size is arbitrary
  117. TCHAR tszHtmlName[MAX_PATH];
  118. TCHAR tszTextName[MAX_PATH];
  119. // Set the Description string.
  120. *tszDescription = TEXT( '\0' );
  121. LoadString( ghInstance,
  122. IDS_UPGRADE_OTHER_NODES,
  123. tszDescription,
  124. 100 );
  125. // Set the HTML file name. Note that following the example of msmqcomp.cpp
  126. // this path is relative to the winnt32 directory.
  127. _tcscpy( tszHtmlName, TEXT( "CompData\\ClusComp.htm" ) );
  128. // Set the TEXT file name. Note that following the example of msmqcomp.cpp
  129. // this path is relative to the winnt32 directory.
  130. _tcscpy( tszTextName, TEXT( "CompData\\ClusComp.txt" ) );
  131. // Build the COMPATIBILITY_ENTRY structure to pass to *pfnCompatibilityCallback().
  132. COMPATIBILITY_ENTRY CompatibilityEntry;
  133. ZeroMemory( &CompatibilityEntry, sizeof( CompatibilityEntry ) );
  134. CompatibilityEntry.Description = tszDescription;
  135. CompatibilityEntry.HtmlName = tszHtmlName;
  136. CompatibilityEntry.TextName = tszTextName;
  137. CompatibilityEntry.RegKeyName = (LPTSTR) NULL;
  138. CompatibilityEntry.RegValName = (LPTSTR) NULL;
  139. CompatibilityEntry.RegValDataSize = (DWORD) 0L;
  140. CompatibilityEntry.RegValData = (LPVOID) NULL;
  141. CompatibilityEntry.SaveValue = (LPVOID) NULL;
  142. CompatibilityEntry.Flags = (DWORD) 0L;
  143. // Execute the callback function.
  144. fReturnValue = pfnCompatibilityCallback( (PCOMPATIBILITY_ENTRY) &CompatibilityEntry,
  145. pvContext );
  146. }
  147. else
  148. {
  149. // It is not necessary to display a compatibility warning.
  150. fReturnValue = (BOOL) TRUE;
  151. } // Is it necessary to display a compatibility warning?
  152. } // Is this system already running NT 5 or later?
  153. } // Is the cluster service registered?
  154. return ( fReturnValue );
  155. }
  156. /////////////////////////////////////////////////////////////////////////////
  157. //++
  158. //
  159. // IsCompatibilityWarningRequired
  160. //
  161. // Routine Description:
  162. // This function determines whether it is necessary to display the compatibility
  163. // warning message.
  164. //
  165. // Arguments:
  166. // none
  167. //
  168. //
  169. // Return Value:
  170. // TRUE - indicates that it compatibility warning message should be displayed.
  171. // FALSE - indicates that it is not necessary to display the compatibility
  172. // warning message.
  173. //
  174. //--
  175. /////////////////////////////////////////////////////////////////////////////
  176. BOOL IsCompatibilityWarningRequired( void )
  177. {
  178. BOOL fCompatibilityWarningRequired = (BOOL) FALSE;
  179. HCLUSTER hCluster;
  180. // Open a connection to the cluster to which the machine being upgraded belongs.
  181. hCluster = OpenCluster( NULL );
  182. // Was the connection to the cluster opened successfully?
  183. if ( hCluster != (HCLUSTER) NULL )
  184. {
  185. // A connection to the cluster was opened.
  186. DWORD dwClusterNameLength;
  187. DWORD dwErrorCode;
  188. LPWSTR lpwszClusterName;
  189. // Allocate a buffer for the cluster name.
  190. lpwszClusterName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT,
  191. (MAX_CLUSTERNAME_LENGTH + 1) * sizeof( WCHAR ) );
  192. // Was the allocation successfull?
  193. if ( lpwszClusterName != (LPWSTR) NULL )
  194. {
  195. CLUSTERVERSIONINFO ClusterVersionInfo;
  196. ClusterVersionInfo.dwVersionInfoSize = sizeof( CLUSTERVERSIONINFO );
  197. // Query the version information from the cluster.
  198. dwErrorCode = GetClusterInformation( hCluster,
  199. lpwszClusterName,
  200. &dwClusterNameLength,
  201. &ClusterVersionInfo );
  202. // Was the cluster version information obtained?
  203. if ( dwErrorCode == (DWORD) ERROR_MORE_DATA )
  204. {
  205. // The call to GetClusterInformation failed because the buffer for the
  206. // cluster name was too small. Get a larger buffer.
  207. LocalFree( lpwszClusterName );
  208. lpwszClusterName = (LPWSTR) LocalAlloc( LMEM_ZEROINIT,
  209. (dwClusterNameLength) * sizeof( WCHAR ) );
  210. // Was the reallocation successfull?
  211. if ( lpwszClusterName != (LPWSTR) NULL )
  212. {
  213. // Try a second time to get the version information.
  214. dwErrorCode = GetClusterInformation( hCluster,
  215. lpwszClusterName,
  216. &dwClusterNameLength,
  217. &ClusterVersionInfo );
  218. }
  219. else
  220. {
  221. // The reallocation failed
  222. fCompatibilityWarningRequired = (BOOL) TRUE;
  223. } // Was the reallocation succesfull?
  224. } // Did the initial call to GetClusterInformation succeed?
  225. // Was the cluster version information obtained?
  226. if ( dwErrorCode == (DWORD) ERROR_SUCCESS )
  227. {
  228. // Examine the cluster version information to determine whether the
  229. // compatibility warning should be displayed.
  230. // Note:
  231. // If this node is an SP3 node, then the ClusterVersionInfo returned by
  232. // GetClusterInformation will be of type CLUSTERVERSIONINFO_NT4.
  233. // If this node is an SP4 node or higher, then the ClusterVersionInfo returned by
  234. // GetClusterInformation will be of type CLUSTERVERSIONINFO.
  235. // ClusterVersionInfo.MajorVersion is being set to NT4_MAJOR_VERSION both on
  236. // SP4 and on SP3, so this field cannot be used to distinguish between the two.
  237. // So, we use the ClusterVersionInfo.szCSDVersion for the test.
  238. if ( ( ClusterVersionInfo.MajorVersion > NT4_MAJOR_VERSION ) ||
  239. ( _wcsicmp( ClusterVersionInfo.szCSDVersion, L"Service Pack 3" ) != 0 )
  240. )
  241. {
  242. // This node is an NT4SP4 or higher.
  243. // It is necessary to examing the dwNodeHighestVersion member of the
  244. // CLUSTERVERSIONINFO structure.
  245. if ( CLUSTER_GET_MAJOR_VERSION( ClusterVersionInfo.dwClusterHighestVersion ) >=
  246. NT4SP4_MAJOR_VERSION )
  247. {
  248. // There are no NT4/SP3 nodes in the cluster.
  249. fCompatibilityWarningRequired = (BOOL) FALSE;
  250. }
  251. else
  252. {
  253. // There is at least one NT4/SP3 node in the cluster.
  254. fCompatibilityWarningRequired = (BOOL) TRUE;
  255. }
  256. }
  257. else
  258. {
  259. // This node is an SP3 node. We cannot find out what the version information of
  260. // the other node in the cluster (if any). So, issue the warning.
  261. fCompatibilityWarningRequired = (BOOL) TRUE;
  262. }
  263. }
  264. else
  265. {
  266. // The cluster version information was not obtained.
  267. fCompatibilityWarningRequired = (BOOL) TRUE;
  268. } // Is the cluster version information available?
  269. LocalFree( lpwszClusterName );
  270. }
  271. else
  272. {
  273. // The buffer for the cluster name could not be allocated.
  274. fCompatibilityWarningRequired = (BOOL) TRUE;
  275. }
  276. // Close the connection to the cluster.
  277. CloseCluster( hCluster ); // Since there is no recovery possible on error,
  278. // the return value is irrelevant.
  279. }
  280. else
  281. {
  282. // Since a connection to the cluster that this machine belongs to could
  283. // not be opened no information about the OS version and service pack
  284. // level can be inferred. It is safest to display the compatibility warning.
  285. fCompatibilityWarningRequired = (BOOL) TRUE;
  286. } // Was the connection to the cluster opened successfully?
  287. return ( fCompatibilityWarningRequired );
  288. }