Leaked source code of windows server 2003
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.

449 lines
14 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CClusDB.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CClusDB class.
  10. //
  11. // Maintained By:
  12. // David Potter (DavidP) 14-JUN-2001
  13. // Vij Vasu (Vvasu) 08-MAR-2000
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. //////////////////////////////////////////////////////////////////////////////
  17. // Include Files
  18. //////////////////////////////////////////////////////////////////////////////
  19. // The precompiled header.
  20. #include "Pch.h"
  21. // The header for this file
  22. #include "CClusDB.h"
  23. // For the CBaseClusterAction class
  24. #include "CBaseClusterAction.h"
  25. // For g_GenericSetupQueueCallback and other global functions
  26. #include "GlobalFuncs.h"
  27. // For CEnableThreadPrivilege
  28. #include "CEnableThreadPrivilege.h"
  29. // For ConvertStringSecurityDescriptorToSecurityDescriptor
  30. #include <sddl.h>
  31. //////////////////////////////////////////////////////////////////////////
  32. // Macros definitions
  33. //////////////////////////////////////////////////////////////////////////
  34. // Section in the INF file that deals with cleaning up the cluster database
  35. #define CLUSDB_CLEANUP_INF_SECTION_NAME L"ClusDB_Cleanup"
  36. //////////////////////////////////////////////////////////////////////////////
  37. //++
  38. //
  39. // CClusDB::CClusDB()
  40. //
  41. // Description:
  42. // Constructor of the CClusDB class
  43. //
  44. // Arguments:
  45. // pbcaParentActionIn
  46. // Pointer to the base cluster action of which this action is a part.
  47. //
  48. // Return Value:
  49. // None.
  50. //
  51. // Exceptions Thrown:
  52. // CAssert
  53. // If the parameters are incorrect.
  54. //
  55. // Any exceptions thrown by underlying functions
  56. //
  57. //--
  58. //////////////////////////////////////////////////////////////////////////////
  59. CClusDB::CClusDB(
  60. CBaseClusterAction * pbcaParentActionIn
  61. )
  62. : m_pbcaParentAction( pbcaParentActionIn )
  63. {
  64. TraceFunc( "" );
  65. if ( m_pbcaParentAction == NULL)
  66. {
  67. LogMsg( "[BC] Pointers to the parent action is NULL. Throwing an exception." );
  68. THROW_ASSERT(
  69. E_INVALIDARG
  70. , "CClusDB::CClusDB() => Required input pointer in NULL"
  71. );
  72. } // if: the parent action pointer is NULL
  73. TraceFuncExit();
  74. } //*** CClusDB::CClusDB
  75. //////////////////////////////////////////////////////////////////////////////
  76. //++
  77. //
  78. // CClusDB::~CClusDB
  79. //
  80. // Description:
  81. // Destructor of the CClusDB class.
  82. //
  83. // Arguments:
  84. // None.
  85. //
  86. // Return Value:
  87. // None.
  88. //
  89. // Exceptions Thrown:
  90. // Any exceptions thrown by underlying functions
  91. //
  92. //--
  93. //////////////////////////////////////////////////////////////////////////////
  94. CClusDB::~CClusDB( void )
  95. {
  96. TraceFunc( "" );
  97. TraceFuncExit();
  98. } //*** CClusDB::~CClusDB
  99. //////////////////////////////////////////////////////////////////////////////
  100. //++
  101. //
  102. // CClusDB::CreateHive
  103. //
  104. // Description:
  105. // Creates the cluster cluster hive in the registry.
  106. //
  107. // Arguments:
  108. // pbcaClusterActionIn
  109. // Pointer to the CBaseClusterAction object which contains this object.
  110. //
  111. // Return Value:
  112. // None.
  113. //
  114. // Exceptions Thrown:
  115. // CRuntimeError
  116. // If any of the APIs fail.
  117. //
  118. // Any that are thrown by the called functions.
  119. //
  120. //--
  121. //////////////////////////////////////////////////////////////////////////////
  122. void
  123. CClusDB::CreateHive( CBaseClusterAction * pbcaClusterActionIn )
  124. {
  125. TraceFunc( "" );
  126. LogMsg( "[BC] Attempting to create the cluster hive in the registry." );
  127. OBJECT_ATTRIBUTES oaClusterHiveKey;
  128. OBJECT_ATTRIBUTES oaClusterHiveFile;
  129. HRESULT hrStatus = STATUS_SUCCESS;
  130. CStr strClusterHiveFileName( pbcaClusterActionIn->RStrGetClusterInstallDirectory() );
  131. UNICODE_STRING ustrClusterHiveFileName;
  132. UNICODE_STRING ustrClusterHiveKeyName;
  133. PSECURITY_DESCRIPTOR psdHiveSecurityDescriptor = NULL;
  134. strClusterHiveFileName += L"\\" CLUSTER_DATABASE_NAME;
  135. LogMsg( "[BC] The cluster hive backing file is '%s'.", strClusterHiveFileName.PszData() );
  136. //
  137. // Enable the SE_RESTORE_PRIVILEGE.
  138. //
  139. // What we are doing here is that we are creating an object of
  140. // type CEnableThreadPrivilege. This object enables the privilege
  141. // in the constructor and restores it to its original state in the destructor.
  142. //
  143. CEnableThreadPrivilege etpAcquireRestorePrivilege( SE_RESTORE_NAME );
  144. //
  145. // Convert the DOS file name to NT file name.
  146. // WARNING: This function call allocates memory in the RTL heap and it is not being
  147. // assigned to a smart pointer. Make sure that we do not call any functions that
  148. // could throw an exception till this memory is freed.
  149. //
  150. if ( RtlDosPathNameToNtPathName_U(
  151. strClusterHiveFileName.PszData()
  152. , &ustrClusterHiveFileName
  153. , NULL
  154. , NULL
  155. )
  156. == FALSE
  157. )
  158. {
  159. LogMsg( "[BC] RtlDosPathNameToNtPathName failed. Returning %#08x as the error code.", STATUS_OBJECT_PATH_INVALID );
  160. // Use the most appropriate error code.
  161. hrStatus = STATUS_OBJECT_PATH_INVALID;
  162. goto Cleanup;
  163. } // if: we could not convert from the dos file name to the nt file name
  164. InitializeObjectAttributes(
  165. &oaClusterHiveFile
  166. , &ustrClusterHiveFileName
  167. , OBJ_CASE_INSENSITIVE
  168. , NULL
  169. , NULL
  170. );
  171. RtlInitUnicodeString( &ustrClusterHiveKeyName, L"\\Registry\\Machine\\" CLUSREG_KEYNAME_CLUSTER );
  172. InitializeObjectAttributes(
  173. &oaClusterHiveKey
  174. , &ustrClusterHiveKeyName
  175. , OBJ_CASE_INSENSITIVE
  176. , NULL
  177. , NULL
  178. );
  179. //
  180. // This function creates an empty hive and the backing file and log. The calling thread must
  181. // have the SE_RESTORE_PRIVILEGE privilege enabled.
  182. //
  183. hrStatus = THR( NtLoadKey2( &oaClusterHiveKey, &oaClusterHiveFile, REG_NO_LAZY_FLUSH ) );
  184. // Free allocated memory before throwing exception.
  185. RtlFreeHeap( RtlProcessHeap(), 0, ustrClusterHiveFileName.Buffer );
  186. if ( NT_ERROR( hrStatus ) )
  187. {
  188. LogMsg( "[BC] NtLoadKey2 returned error code %#08x.", hrStatus );
  189. goto Cleanup;
  190. } // if: something went wrong with NtLoadKey2
  191. TraceFlow( "NtLoadKey2 was successful." );
  192. // Set the security descriptor on the hive.
  193. {
  194. DWORD sc;
  195. BOOL fSuccess;
  196. PACL paclDacl;
  197. BOOL fIsDaclPresent;
  198. BOOL fDefaultDaclPresent;
  199. // Open the cluster hive key.
  200. CRegistryKey rkClusterHive( HKEY_LOCAL_MACHINE, CLUSREG_KEYNAME_CLUSTER, WRITE_DAC );
  201. // construct a DACL that is protected (P) from inheriting ACEs from
  202. // its parent key (MACHINE). Add access allowed (A) ACEs for Local
  203. // Admin (BA) and LocalSystem (SY) granting them full control (KA) and
  204. // an ACE for NetworkService (NS), LocalService (LS), and
  205. // authenticated users (AU) granting read only access (KR). Each ACE
  206. // has container inherit (CI) set so subkeys will inherit the ACEs
  207. // from this security descriptor.
  208. fSuccess = ConvertStringSecurityDescriptorToSecurityDescriptor(
  209. L"D:P(A;CI;KA;;;BA)(A;CI;KA;;;SY)(A;CI;KR;;;NS)(A;CI;KR;;;LS)(A;CI;KR;;;AU)"
  210. , SDDL_REVISION_1
  211. , &psdHiveSecurityDescriptor
  212. , NULL
  213. );
  214. if ( fSuccess == FALSE )
  215. {
  216. sc = TW32( GetLastError() );
  217. hrStatus = HRESULT_FROM_WIN32( sc );
  218. LogMsg( "[BC] Error %#08x occurred trying to compose the security descriptor for the cluster hive.", sc );
  219. goto Cleanup;
  220. }
  221. // get a pointer to the ACL in the SD and set the DACL on the root of
  222. // the cluster hive.
  223. fSuccess = GetSecurityDescriptorDacl(
  224. psdHiveSecurityDescriptor
  225. , &fIsDaclPresent
  226. , &paclDacl
  227. , &fDefaultDaclPresent
  228. );
  229. if ( fSuccess == FALSE )
  230. {
  231. sc = TW32( GetLastError() );
  232. hrStatus = HRESULT_FROM_WIN32( sc );
  233. LogMsg( "[BC] Error %#08x occurred trying to obtain the discretionary ACL from the cluster security descriptor.", sc );
  234. goto Cleanup;
  235. }
  236. // This should always be the case since we just constructed the ACL in
  237. // the Convert API call.
  238. if ( fIsDaclPresent && !fDefaultDaclPresent )
  239. {
  240. sc = TW32( SetSecurityInfo(
  241. rkClusterHive.HGetKey()
  242. , SE_REGISTRY_KEY
  243. , DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION
  244. , NULL // Owner SID
  245. , NULL // Group SID
  246. , paclDacl
  247. , NULL // SACL
  248. ) );
  249. if ( sc != ERROR_SUCCESS )
  250. {
  251. hrStatus = HRESULT_FROM_WIN32( sc );
  252. LogMsg( "[BC] Error %#08x occurred trying to set the cluster hive security.", sc );
  253. goto Cleanup;
  254. } // if: ClRtlSetObjSecurityInfo failed
  255. }
  256. else
  257. {
  258. hrStatus = HRESULT_FROM_WIN32( ERROR_INVALID_SECURITY_DESCR );
  259. LogMsg( "[BC] Cluster Hive discretionary ACL not correctly formatted." );
  260. goto Cleanup;
  261. }
  262. // Flush the changes to the registry.
  263. RegFlushKey( rkClusterHive.HGetKey() );
  264. }
  265. // At this point, the cluster hive has been created.
  266. LogMsg( "[BC] The cluster hive has been created." );
  267. Cleanup:
  268. if ( psdHiveSecurityDescriptor )
  269. {
  270. LocalFree( psdHiveSecurityDescriptor );
  271. }
  272. if ( NT_ERROR( hrStatus ) )
  273. {
  274. LogMsg( "[BC] Error %#08x occurred trying to create the cluster hive. Throwing an exception.", hrStatus );
  275. THROW_RUNTIME_ERROR(
  276. hrStatus
  277. , IDS_ERROR_CLUSDB_CREATE_HIVE
  278. );
  279. } // if: something went wrong.
  280. TraceFuncExit();
  281. } //*** CClusDB::CreateHive
  282. //////////////////////////////////////////////////////////////////////////////
  283. //++
  284. //
  285. // CClusDB::CleanupHive
  286. //
  287. // Description:
  288. // Unload the cluster hive and delete the cluster database.
  289. //
  290. // Arguments:
  291. // None.
  292. //
  293. // Return Value:
  294. // None.
  295. //
  296. // Exceptions Thrown:
  297. // CRuntimeError
  298. // If any of the APIs fail.
  299. //
  300. //--
  301. //////////////////////////////////////////////////////////////////////////////
  302. void
  303. CClusDB::CleanupHive( void )
  304. {
  305. TraceFunc( "" );
  306. DWORD sc = ERROR_SUCCESS;
  307. HKEY hTempKey;
  308. // Check if the cluster hive is loaded before attempting to unload it.
  309. if ( RegOpenKeyExW(
  310. HKEY_LOCAL_MACHINE
  311. , CLUSREG_KEYNAME_CLUSTER
  312. , 0
  313. , KEY_READ
  314. , &hTempKey
  315. )
  316. == ERROR_SUCCESS
  317. )
  318. {
  319. RegCloseKey( hTempKey );
  320. //
  321. // Enable the SE_RESTORE_PRIVILEGE.
  322. //
  323. // What we are doing here is that we are creating an object of
  324. // type CEnableThreadPrivilege. This object enables the privilege
  325. // in the constructor and restores it to its original state in the destructor.
  326. //
  327. CEnableThreadPrivilege etpAcquireRestorePrivilege( SE_RESTORE_NAME );
  328. //
  329. // Unload the cluster hive, so that it can be deleted. Note, thread must
  330. // have SE_RESTORE_PRIVILEGE enabled.
  331. //
  332. sc = RegUnLoadKey(
  333. HKEY_LOCAL_MACHINE
  334. , CLUSREG_KEYNAME_CLUSTER
  335. );
  336. // MUSTDO: Check if ERROR_FILE_NOT_FOUND is an acceptable return value.
  337. if ( sc != ERROR_SUCCESS )
  338. {
  339. LogMsg( "[BC] Error %#08x occurred while trying to unload the cluster hive.", sc );
  340. goto Cleanup;
  341. } // if: the hive could not be unloaded.
  342. LogMsg( "[BC] The cluster hive has been unloaded." );
  343. } // if: the cluster hive is loaded
  344. else
  345. {
  346. LogMsg( "[BC] The cluster hive was not loaded." );
  347. } // else: the cluster hive is not loaded
  348. //
  349. // Process ClusDB cleanup section in the INF file.
  350. // This will delete the cluster database file and the log file.
  351. //
  352. if ( SetupInstallFromInfSection(
  353. NULL // optional, handle of a parent window
  354. , m_pbcaParentAction->HGetMainInfFileHandle() // handle to the INF file
  355. , CLUSDB_CLEANUP_INF_SECTION_NAME // name of the Install section
  356. , SPINST_FILES // which lines to install from section
  357. , NULL // optional, key for registry installs
  358. , NULL // optional, path for source files
  359. , 0 // optional, specifies copy behavior
  360. , g_GenericSetupQueueCallback // optional, specifies callback routine
  361. , NULL // optional, callback routine context
  362. , NULL // optional, device information set
  363. , NULL // optional, device info structure
  364. ) == FALSE
  365. )
  366. {
  367. sc = GetLastError();
  368. LogMsg( "[BC] Error %#08x returned from SetupInstallFromInfSection() while trying to clean up the cluster database files.", sc );
  369. goto Cleanup;
  370. } // if: SetupInstallServicesFromInfSection failed
  371. LogMsg( "[BC] The cluster database files have been cleaned up." );
  372. Cleanup:
  373. if ( sc != ERROR_SUCCESS )
  374. {
  375. LogMsg( "[BC] Error %#08x occurred while trying to cleanup the cluster database. Throwing an exception.", sc );
  376. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( sc ), IDS_ERROR_CLUSDB_CLEANUP );
  377. }
  378. TraceFuncExit();
  379. } //*** CClusDB::CleanupHive