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.

518 lines
17 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. upgrade.c
  5. Abstract:
  6. code related to upgrade situations.
  7. This currently covers upgrades to Windows Server 2003 either from NT4 or W2K. In
  8. Windows Server 2003, netname now creates a computer object which is used by apps
  9. like MSMQ. In the upgrade case, MSMQ has already create the computer object. If
  10. Netname detects an existing computer object and Kerberos support is disabled, the
  11. netname resource will not go online. This code enums the MSMQ resources
  12. and enables Kerberos support on their dependent netname resources.
  13. Test for MSMQ DS vs workgroup mode supplied by IlanH
  14. Author:
  15. Charlie Wickham (charlwi) 07-Nov-2001
  16. Environment:
  17. User Mode
  18. Revision History:
  19. --*/
  20. #define UNICODE 1
  21. #include "clusres.h"
  22. #include "netname.h"
  23. #define FALCON_REG_KEY TEXT("SOFTWARE\\Microsoft\\MSMQ\\Parameters")
  24. #define MSMQ_WORKGROUP_REGNAME TEXT("Workgroup")
  25. //
  26. // private routines
  27. //
  28. DWORD
  29. NetNameMSMQEnumCallback(
  30. HRESOURCE hSelf,
  31. HRESOURCE MSMQRes,
  32. PVOID pParameter
  33. )
  34. /*++
  35. Routine Description:
  36. Callback routine for FixupNetnamesOnUpgrade. For a given MSMQ resource
  37. (MSMQRes), get its dependent netname resource and set the RequireKerberos
  38. property to one.
  39. REMOVE AFTER THE NEXT MAJOR RELEASE OF NT AFTER RELEASE OF
  40. WINDOWS XP/SERVER 2003
  41. Arguments:
  42. standard ResUtilEnumResources args - hSelf is not used; pParameter is a
  43. pointer to a DWORD which is incremented when the RequireKerberos property
  44. is set.
  45. Return Value:
  46. None
  47. --*/
  48. {
  49. #define RESNAME_CHARS 64
  50. WCHAR msmqResNameBuffer[ RESNAME_CHARS ];
  51. PWCHAR msmqResName = msmqResNameBuffer;
  52. DWORD msmqBufferSize = RESNAME_CHARS * sizeof( *msmqResName );
  53. WCHAR nnResName[ RESNAME_CHARS ];
  54. DWORD status;
  55. DWORD bytesReturned;
  56. DWORD bufSize;
  57. DWORD bytesRequired;
  58. PDWORD updateCount = pParameter;
  59. PVOID propList = NULL;
  60. DWORD propListSize = 0;
  61. HRESOURCE nnHandle = NULL;
  62. struct _RESOURCE_PRIVATEPROPS {
  63. DWORD RequireKerberos;
  64. } privateProps;
  65. RESUTIL_PROPERTY_ITEM privatePropTable[] = {
  66. { L"RequireKerberos", NULL, CLUSPROP_FORMAT_DWORD, 0, 0, 0, 0,
  67. FIELD_OFFSET( struct _RESOURCE_PRIVATEPROPS, RequireKerberos ) },
  68. { 0 }
  69. };
  70. //
  71. // get the name of the MSMQ resource
  72. //
  73. retry_get_msmq_resname:
  74. status = ClusterResourceControl( MSMQRes,
  75. NULL,
  76. CLUSCTL_RESOURCE_GET_NAME,
  77. NULL,
  78. 0,
  79. msmqResName,
  80. msmqBufferSize,
  81. &bytesReturned );
  82. if ( status == ERROR_MORE_DATA ) {
  83. msmqResName = (PWCHAR)LocalAlloc( LMEM_FIXED, bytesReturned );
  84. if ( msmqResName == NULL ) {
  85. status = GetLastError();
  86. } else {
  87. msmqBufferSize = bytesReturned;
  88. goto retry_get_msmq_resname;
  89. }
  90. }
  91. if ( status != ERROR_SUCCESS ) {
  92. (NetNameLogEvent)( L"rtNetwork Name",
  93. LOG_ERROR,
  94. L"Couldn't get name of MSMQ resource - status %u\n",
  95. status );
  96. msmqResName = NULL;
  97. }
  98. //
  99. // get a handle to its dependent netname resource
  100. //
  101. nnHandle = ResUtilGetResourceDependency( MSMQRes, L"Network Name" );
  102. if ( nnHandle != NULL ) {
  103. //
  104. // get the name of the netname resource
  105. //
  106. bufSize = RESNAME_CHARS;
  107. if ( !GetClusterResourceNetworkName( MSMQRes, nnResName, &bufSize )) {
  108. nnResName[ COUNT_OF( nnResName ) - 1 ] = UNICODE_NULL;
  109. _snwprintf( nnResName,
  110. COUNT_OF( nnResName ) - 1,
  111. L"Dependent network name resource of '%ws'",
  112. msmqResName);
  113. }
  114. //
  115. // set our unknown prop to one
  116. //
  117. privateProps.RequireKerberos = 1;
  118. //
  119. // get the size of the prop list buffer
  120. //
  121. status = ResUtilPropertyListFromParameterBlock(privatePropTable,
  122. NULL,
  123. &propListSize,
  124. (LPBYTE) &privateProps,
  125. &bytesReturned,
  126. &bytesRequired );
  127. if ( status == ERROR_MORE_DATA ) {
  128. propList = LocalAlloc( LMEM_FIXED, bytesRequired );
  129. if ( propList == NULL ) {
  130. (NetNameLogEvent)( L"rtNetwork Name",
  131. LOG_ERROR,
  132. L"Unable to create property list for resource '%1!ws!'. error %2!u!\n",
  133. nnResName,
  134. GetLastError());
  135. goto cleanup;
  136. }
  137. propListSize = bytesRequired;
  138. status = ResUtilPropertyListFromParameterBlock(privatePropTable,
  139. propList,
  140. &propListSize,
  141. (LPBYTE) &privateProps,
  142. &bytesReturned,
  143. &bytesRequired );
  144. }
  145. if ( status != ERROR_SUCCESS ) {
  146. (NetNameLogEvent)( L"rtNetwork Name",
  147. LOG_ERROR,
  148. L"Couldn't create property list for resource '%1!ws!'. error %2!u!\n",
  149. nnResName,
  150. status);
  151. goto cleanup;
  152. }
  153. //
  154. // set the RequireKerberos property to one for the netname resource
  155. //
  156. status = ClusterResourceControl( nnHandle,
  157. NULL,
  158. CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES,
  159. propList,
  160. propListSize,
  161. NULL,
  162. 0,
  163. NULL );
  164. if ( status == ERROR_SUCCESS || status == ERROR_RESOURCE_PROPERTIES_STORED ) {
  165. (NetNameLogEvent)( L"rtNetwork Name",
  166. LOG_INFORMATION,
  167. L"Successfully set RequireKerberos property for resource '%1!ws!'\n",
  168. nnResName );
  169. ++*updateCount;
  170. } else {
  171. (NetNameLogEvent)( L"rtNetwork Name",
  172. LOG_ERROR,
  173. L"Failed to set RequireKerberos property for resource '%1!ws!' - status %2!u!\n",
  174. nnResName,
  175. status );
  176. }
  177. }
  178. else {
  179. (NetNameLogEvent)( L"rtNetwork Name",
  180. LOG_ERROR,
  181. L"Unable to get handle to dependent network name resource of MSMQ "
  182. L"resource '%1!ws!' - status '%2!u!'. This resource may fail to go "
  183. L"online.\n",
  184. msmqResName,
  185. GetLastError() );
  186. }
  187. cleanup:
  188. if ( propList ) {
  189. LocalFree( propList );
  190. }
  191. if ( nnHandle ) {
  192. CloseClusterResource( nnHandle );
  193. }
  194. if ( msmqResName != NULL && msmqResName != msmqResNameBuffer ) {
  195. LocalFree( msmqResName );
  196. }
  197. return ERROR_SUCCESS;
  198. } // NetNameMSMQEnumCallback
  199. static BOOL
  200. GetMsmqDWORDKeyValue(
  201. LPCWSTR RegKey,
  202. LPCWSTR RegName,
  203. DWORD * Value
  204. )
  205. /*++
  206. Routine Description:
  207. Read falcon DWORD registry key.
  208. Arguments:
  209. RegName - Registry name (under HKLM\msmq\parameters)
  210. Return Value:
  211. DWORD key value (0 if the key not exist)
  212. --*/
  213. {
  214. HKEY hKey;
  215. LONG regStatus;
  216. DWORD valueType = REG_DWORD;
  217. DWORD valueSize = sizeof(DWORD);
  218. regStatus = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  219. RegKey,
  220. 0,
  221. KEY_READ,
  222. &hKey
  223. );
  224. if ( regStatus != ERROR_SUCCESS) {
  225. // printf("At this point MSMQ Registry must exist, rc = 0x%x\n", rc);
  226. return FALSE;
  227. }
  228. *Value = 0;
  229. regStatus = RegQueryValueEx( hKey,
  230. RegName,
  231. 0L,
  232. &valueType,
  233. (BYTE *)Value,
  234. &valueSize
  235. );
  236. RegCloseKey( hKey );
  237. if ( regStatus != ERROR_SUCCESS && regStatus != ERROR_FILE_NOT_FOUND ) {
  238. // printf("We should get either ERROR_SUCCESS or ERROR_FILE_NOT_FOUND, rc = 0x%x\n", rc);
  239. return FALSE;
  240. }
  241. // printf("%ls = %d\n", RegName, *Value);
  242. return TRUE;
  243. } // GetMsmqDWORDKeyValue
  244. //
  245. // public routines
  246. //
  247. BOOL
  248. DoesMsmqNeedComputerObject(
  249. VOID
  250. )
  251. {
  252. DWORD dwWorkGroup = 0;
  253. if( !GetMsmqDWORDKeyValue( FALCON_REG_KEY, MSMQ_WORKGROUP_REGNAME, &dwWorkGroup )) {
  254. return TRUE;
  255. }
  256. if(dwWorkGroup != 0) {
  257. // printf("MSMQ in workgroup mode, no need for computer object\n");
  258. return FALSE;
  259. }
  260. // printf("MSMQ in domain mode, need computer object\n");
  261. return TRUE;
  262. } // DoesMsmqNeedComputerObject
  263. DWORD
  264. UpgradeMSMQDependentNetnameToKerberos(
  265. PNETNAME_RESOURCE Resource
  266. )
  267. /*++
  268. Routine Description:
  269. After an upgrade to XP, check if this netname is a provider for an MSMQ
  270. resource. If so, set a flag that will set the RequireKerberos property to
  271. one during the next online. We can't set the property at this point in
  272. time since this routine is called when the API is read-only.
  273. REMOVE AFTER THE NEXT MAJOR RELEASE OF NT AFTER RELEASE OF
  274. WINDOWS XP/SERVER 2003
  275. Arguments:
  276. None
  277. Return Value:
  278. None
  279. --*/
  280. {
  281. HCLUSTER clusterHandle;
  282. HRESENUM providerEnum;
  283. DWORD status;
  284. (NetNameLogEvent)( Resource->ResourceHandle,
  285. LOG_INFORMATION,
  286. L"Kerberos Support Upgrade Check: this resource will be "
  287. L"checked for a dependent MSMQ resources.\n");
  288. //
  289. // get a handle to the cluster since we'll need it later on
  290. //
  291. clusterHandle = OpenCluster( NULL );
  292. if ( clusterHandle == NULL ) {
  293. (NetNameLogEvent)( Resource->ResourceHandle,
  294. LOG_ERROR,
  295. L"Unable to open handle to the cluster - status %1!u!. Any MSMQ resource "
  296. L"dependent on this resource may fail to go online.\n",
  297. status = GetLastError() );
  298. return status;
  299. }
  300. //
  301. // get a enum handle for this netname resource that will provide us a list
  302. // of the resources that are dependent on this resource
  303. //
  304. // THIS CALL REQUIRES WORKER THREAD ONLY!!!
  305. //
  306. providerEnum = ClusterResourceOpenEnum( Resource->ClusterResourceHandle,
  307. CLUSTER_RESOURCE_ENUM_PROVIDES );
  308. if ( providerEnum != NULL ) {
  309. DWORD enumIndex = 0;
  310. PWCHAR nameBuffer;
  311. WCHAR dependentResName[ 128 ];
  312. DWORD nameBufferSize;
  313. DWORD enumType;
  314. do {
  315. nameBuffer = dependentResName;
  316. nameBufferSize = COUNT_OF( dependentResName );
  317. enum_again:
  318. //
  319. // WORKER THREAD ONLY!!!!
  320. //
  321. status = ClusterResourceEnum( providerEnum,
  322. enumIndex,
  323. &enumType,
  324. nameBuffer,
  325. &nameBufferSize);
  326. if ( status == ERROR_MORE_DATA ) {
  327. //
  328. // need more space for this resource's name; it's very
  329. // unlikely that this code can be in a loop, but just in case,
  330. // we'll free any previously allocated memory
  331. //
  332. if ( nameBuffer != NULL && nameBuffer != dependentResName ) {
  333. LocalFree( nameBuffer );
  334. }
  335. nameBuffer = LocalAlloc( LMEM_FIXED, ++nameBufferSize * sizeof( WCHAR ));
  336. if ( nameBuffer != NULL ) {
  337. goto enum_again;
  338. }
  339. status = GetLastError();
  340. }
  341. else if ( status == ERROR_SUCCESS ) {
  342. HRESOURCE dependentResource;
  343. dependentResource = OpenClusterResource( clusterHandle, nameBuffer );
  344. if ( dependentResource != NULL ) {
  345. //
  346. // if this resource is MSMQ, then mark this netname for kerberos support
  347. //
  348. if ( ResUtilResourceTypesEqual( CLUS_RESTYPE_NAME_MSMQ, dependentResource ) ||
  349. ResUtilResourceTypesEqual( CLUS_RESTYPE_NAME_NEW_MSMQ, dependentResource ))
  350. {
  351. Resource->Params.RequireKerberos = TRUE;
  352. status = ResUtilSetDwordValue( Resource->ParametersKey,
  353. PARAM_NAME__REQUIRE_KERBEROS,
  354. 1,
  355. NULL);
  356. if ( status != ERROR_SUCCESS ) {
  357. (NetNameLogEvent)( Resource->ResourceHandle,
  358. LOG_ERROR,
  359. L"Unable to set RequireKerberos property after an "
  360. L"upgrade - status %1!u!. This resource requires that "
  361. L"the RequireKerberos property be set to one in order "
  362. L"for its dependent MSMQ resource to be successfully "
  363. L"brought online.\n",
  364. status);
  365. } else {
  366. (NetNameLogEvent)( Resource->ResourceHandle,
  367. LOG_INFORMATION,
  368. L"This resource has been upgraded for Kerberos Support due to "
  369. L"the presence of a dependent MSMQ resource\n");
  370. //
  371. // stop enum'ing dependent resources
  372. //
  373. status = ERROR_NO_MORE_ITEMS;
  374. }
  375. }
  376. CloseClusterResource( dependentResource );
  377. } else {
  378. (NetNameLogEvent)( Resource->ResourceHandle,
  379. LOG_ERROR,
  380. L"Unable to get a handle to cluster resource '%1!ws!' - status "
  381. L"'%2!u!'. Any MSMQ resource dependent on this Network Name resource "
  382. L"may fail to go online.\n",
  383. status = GetLastError() );
  384. }
  385. }
  386. else if ( status != ERROR_SUCCESS && status != ERROR_NO_MORE_ITEMS ) {
  387. (NetNameLogEvent)( Resource->ResourceHandle,
  388. LOG_ERROR,
  389. L"Unable to enumerate resources dependent on this Network Name resource "
  390. L" - status '%1!u!'. Any MSMQ resource dependent on this resource "
  391. L"may fail to go online.\n",
  392. status );
  393. }
  394. if ( nameBuffer != dependentResName ) {
  395. LocalFree( nameBuffer );
  396. }
  397. ++enumIndex;
  398. } while ( status == ERROR_SUCCESS );
  399. status = ClusterResourceCloseEnum( providerEnum );
  400. } else {
  401. (NetNameLogEvent)( Resource->ResourceHandle,
  402. LOG_ERROR,
  403. L"Unable to get handle enumerate the MSMQ dependent resources - status '%1!u!'. "
  404. L"Any MSMQ resource dependent on this resource may fail to go online.\n",
  405. GetLastError() );
  406. }
  407. CloseCluster( clusterHandle );
  408. return status;
  409. } // UpgradeMSMQDependentNetnameToKerberos
  410. /* end upgrade.c */