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.

682 lines
18 KiB

  1. /*++
  2. Copyright (c) 1992-1997 Microsoft Corporation
  3. Module Name:
  4. msmq.c
  5. Abstract:
  6. Resource DLL to control and monitor the NT DHCPServer service.
  7. Author:
  8. Robs 3/28/96, based on RodGa's generic resource dll
  9. Revision History:
  10. --*/
  11. #include "..\common\svc.c"
  12. #include "clusudef.h"
  13. #include "ntverp.h"
  14. extern CLRES_FUNCTION_TABLE MsMQFunctionTable;
  15. #define MSMQ_VERSION L"Version"
  16. #define MSMQ_DEFAULT_VERSION 0x04000000
  17. #define PARAM_NAME__VERSION L"Version"
  18. RESUTIL_PROPERTY_ITEM
  19. MsMQResourcePrivateProperties[] = {
  20. { PARAM_NAME__VERSION, NULL, CLUSPROP_FORMAT_DWORD, MSMQ_DEFAULT_VERSION, 0, 0xFFFFFFFF, 0, FIELD_OFFSET(COMMON_PARAMS,dwVersion) },
  21. { 0 }
  22. };
  23. //
  24. // Forward Functions
  25. //
  26. DWORD
  27. WINAPI
  28. MsMQResourceControl(
  29. IN RESID ResourceId,
  30. IN DWORD nControlCode,
  31. IN PVOID pvInBuffer,
  32. IN DWORD cbInBufferSize,
  33. OUT PVOID pvOutBuffer,
  34. IN DWORD cbOutBufferSize,
  35. OUT LPDWORD pcbBytesReturned
  36. );
  37. DWORD
  38. MsMQGetPrivateResProperties(
  39. IN OUT PCOMMON_RESOURCE pResourceEntry,
  40. OUT PVOID pvOutBuffer,
  41. IN DWORD cbOutBufferSize,
  42. OUT LPDWORD pcbBytesReturned
  43. );
  44. //
  45. // Local Functions
  46. //
  47. VOID
  48. MsMQResetCheckpoints(
  49. PCOMMON_RESOURCE ResourceEntry
  50. )
  51. /*++
  52. Routine Description
  53. Delete and then set registry checkpoints this will clean out old
  54. registry checkpoint settings.
  55. Arguments:
  56. None.
  57. Return Value:
  58. None.
  59. --*/
  60. {
  61. DWORD returnSize;
  62. DWORD idx;
  63. DWORD status;
  64. //
  65. // Delete old registry checkpoints that were set.
  66. //
  67. if ( RegSyncCount != 0 ) {
  68. returnSize = 0;
  69. //
  70. // Set registry sync keys if we need them.
  71. //
  72. for ( idx = 0; idx < RegSyncCount; idx++ ) {
  73. status = ClusterResourceControl( ResourceEntry->hResource,
  74. NULL,
  75. CLUSCTL_RESOURCE_DELETE_REGISTRY_CHECKPOINT,
  76. RegSync[idx],
  77. (lstrlenW( RegSync[idx] ) + 1) * sizeof(WCHAR),
  78. NULL,
  79. 0,
  80. &returnSize );
  81. if ( status != ERROR_SUCCESS ){
  82. if ( status == ERROR_ALREADY_EXISTS ){
  83. status = ERROR_SUCCESS;
  84. }
  85. else{
  86. (g_LogEvent)(
  87. ResourceEntry->ResourceHandle,
  88. LOG_ERROR,
  89. L"Failed to delete registry checkpoint, status %1!u!.\n",
  90. status );
  91. goto error_exit;
  92. }
  93. }
  94. }
  95. }
  96. //
  97. // Set new registry checkpoints that we need.
  98. //
  99. if ( RegSyncCount != 0 ) {
  100. returnSize = 0;
  101. //
  102. // Set registry sync keys if we need them.
  103. //
  104. for ( idx = 0; idx < RegSyncCount; idx++ ) {
  105. status = ClusterResourceControl( ResourceEntry->hResource,
  106. NULL,
  107. CLUSCTL_RESOURCE_ADD_REGISTRY_CHECKPOINT,
  108. RegSync[idx],
  109. (lstrlenW( RegSync[idx] ) + 1) * sizeof(WCHAR),
  110. NULL,
  111. 0,
  112. &returnSize );
  113. if ( status != ERROR_SUCCESS ){
  114. if ( status == ERROR_ALREADY_EXISTS ){
  115. status = ERROR_SUCCESS;
  116. }
  117. else{
  118. (g_LogEvent)(
  119. ResourceEntry->ResourceHandle,
  120. LOG_ERROR,
  121. L"Failed to set registry checkpoint, status %1!u!.\n",
  122. status );
  123. goto error_exit;
  124. }
  125. }
  126. }
  127. }
  128. //
  129. // Set any crypto checkpoints that we need.
  130. //
  131. if ( CryptoSyncCount != 0 ) {
  132. returnSize = 0;
  133. //
  134. // Set registry sync keys if we need them.
  135. //
  136. for ( idx = 0; idx < CryptoSyncCount; idx++ ) {
  137. status = ClusterResourceControl( ResourceEntry->hResource,
  138. NULL,
  139. CLUSCTL_RESOURCE_ADD_CRYPTO_CHECKPOINT,
  140. CryptoSync[idx],
  141. (lstrlenW( CryptoSync[idx] ) + 1) * sizeof(WCHAR),
  142. NULL,
  143. 0,
  144. &returnSize );
  145. if ( status != ERROR_SUCCESS ){
  146. if (status == ERROR_ALREADY_EXISTS){
  147. status = ERROR_SUCCESS;
  148. }
  149. else{
  150. (g_LogEvent)(
  151. ResourceEntry->ResourceHandle,
  152. LOG_ERROR,
  153. L"Failed to set crypto checkpoint, status %1!u!.\n",
  154. status );
  155. goto error_exit;
  156. }
  157. }
  158. }
  159. }
  160. //
  161. // Set any domestic crypto checkpoints that we need.
  162. //
  163. if ( DomesticCryptoSyncCount != 0 ) {
  164. HCRYPTPROV hProv = 0;
  165. //
  166. // check if domestic crypto is available
  167. //
  168. if (CryptAcquireContextA( &hProv,
  169. NULL,
  170. MS_ENHANCED_PROV_A,
  171. PROV_RSA_FULL,
  172. CRYPT_VERIFYCONTEXT)) {
  173. CryptReleaseContext( hProv, 0 );
  174. returnSize = 0;
  175. //
  176. // Set registry sync keys if we need them.
  177. //
  178. for ( idx = 0; idx < DomesticCryptoSyncCount; idx++ ) {
  179. status = ClusterResourceControl( ResourceEntry->hResource,
  180. NULL,
  181. CLUSCTL_RESOURCE_ADD_CRYPTO_CHECKPOINT,
  182. DomesticCryptoSync[idx],
  183. (lstrlenW( DomesticCryptoSync[idx] ) + 1) * sizeof(WCHAR),
  184. NULL,
  185. 0,
  186. &returnSize );
  187. if ( status != ERROR_SUCCESS ){
  188. if (status == ERROR_ALREADY_EXISTS){
  189. status = ERROR_SUCCESS;
  190. }
  191. else{
  192. (g_LogEvent)(
  193. ResourceEntry->ResourceHandle,
  194. LOG_ERROR,
  195. L"Failed to set domestic crypto checkpoint, status %1!u!.\n",
  196. status );
  197. goto error_exit;
  198. }
  199. }
  200. }
  201. }
  202. }
  203. error_exit:
  204. return;
  205. } // MsMQResetCheckpoints
  206. DWORD
  207. MsMQReadParametersEx(
  208. IN OUT PVOID pvResourceEntry,
  209. IN BOOL bCheckForRequiredProperties
  210. )
  211. /*++
  212. Routine Description:
  213. Reads all the parameters for a specied MsMQ resource.
  214. Arguments:
  215. pResourceEntry - Entry in the resource table.
  216. bCheckForRequiredProperties - TRUE = make sure required properties are
  217. present.
  218. Return Value:
  219. ERROR_SUCCESS if successful.
  220. Win32 error code if failure occurrs.
  221. --*/
  222. {
  223. DWORD status;
  224. COMMON_PARAMS params = { 0 };
  225. LPWSTR pszNameOfPropInError;
  226. PCOMMON_RESOURCE pResourceEntry = (PCOMMON_RESOURCE) pvResourceEntry;
  227. //
  228. // Read our parameters.
  229. //
  230. status = ResUtilGetPropertiesToParameterBlock(
  231. pResourceEntry->ParametersKey,
  232. MsMQResourcePrivateProperties,
  233. (LPBYTE) &pResourceEntry->Params,
  234. bCheckForRequiredProperties,
  235. &pszNameOfPropInError
  236. );
  237. if ( status != ERROR_SUCCESS ) {
  238. (g_LogEvent)(
  239. pResourceEntry->ResourceHandle,
  240. LOG_ERROR,
  241. L"Unable to read the '%1' property. Error: %2!u!.\n",
  242. (pszNameOfPropInError == NULL ? L"" : pszNameOfPropInError),
  243. status
  244. );
  245. }
  246. return(status);
  247. } // MsMQReadParametersEx
  248. VOID
  249. MsMQPerformFixup(
  250. IN OUT PCOMMON_RESOURCE pResourceEntry
  251. )
  252. {
  253. DWORD status;
  254. DWORD version;
  255. DWORD bytesReturned;
  256. DWORD bytesRequired;
  257. PVOID propBuffer;
  258. COMMON_PARAMS params;
  259. status = MsMQReadParametersEx(
  260. pResourceEntry,
  261. FALSE );
  262. if ( status != ERROR_SUCCESS ) {
  263. return;
  264. }
  265. version = pResourceEntry->Params.dwVersion;
  266. version = version >> 16;
  267. if ( version < 0x0500 ) {
  268. //
  269. // Delete Old Checkpoints and set new ones
  270. //
  271. MsMQResetCheckpoints( pResourceEntry );
  272. params.dwVersion = VER_PRODUCTVERSION_DW;
  273. //
  274. // Get version number as a property list
  275. //
  276. status = ResUtilGetProperties(
  277. pResourceEntry->ParametersKey,
  278. MsMQResourcePrivateProperties,
  279. NULL,
  280. 0,
  281. &bytesReturned,
  282. &bytesRequired
  283. );
  284. if ( status != ERROR_SUCCESS ) {
  285. (g_LogEvent)(
  286. pResourceEntry->ResourceHandle,
  287. LOG_ERROR,
  288. L"Unable to get properties. Error: %1!u!.\n",
  289. status
  290. );
  291. return;
  292. }
  293. propBuffer = LocalAlloc( LMEM_FIXED, bytesRequired + 2 );
  294. if ( !propBuffer ) {
  295. (g_LogEvent)(
  296. pResourceEntry->ResourceHandle,
  297. LOG_ERROR,
  298. L"Unable to allocate property buffer.\n"
  299. );
  300. return;
  301. }
  302. status = ResUtilGetProperties(
  303. pResourceEntry->ParametersKey,
  304. MsMQResourcePrivateProperties,
  305. propBuffer,
  306. bytesRequired+2,
  307. &bytesReturned,
  308. &bytesRequired
  309. );
  310. if ( status != ERROR_SUCCESS ) {
  311. (g_LogEvent)(
  312. pResourceEntry->ResourceHandle,
  313. LOG_ERROR,
  314. L"Unable to get properties. Error: %1!u!.\n",
  315. status
  316. );
  317. LocalFree( propBuffer );
  318. return;
  319. }
  320. //
  321. // Set Version Number
  322. //
  323. status = ResUtilSetPropertyParameterBlock(
  324. pResourceEntry->ParametersKey,
  325. MsMQResourcePrivateProperties,
  326. NULL,
  327. (LPBYTE) &params,
  328. propBuffer,
  329. bytesReturned,
  330. (LPBYTE) &pResourceEntry->Params
  331. );
  332. LocalFree( propBuffer );
  333. if ( status != ERROR_SUCCESS ) {
  334. (g_LogEvent)(
  335. pResourceEntry->ResourceHandle,
  336. LOG_ERROR,
  337. L"Unable to set the property parameter block. Error: %1!u!.\n",
  338. status
  339. );
  340. return;
  341. }
  342. }
  343. } //MsMQPerformFixup
  344. DWORD
  345. WINAPI
  346. MsMQResourceControl(
  347. IN RESID ResourceId,
  348. IN DWORD nControlCode,
  349. IN PVOID pvInBuffer,
  350. IN DWORD cbInBufferSize,
  351. OUT PVOID pvOutBuffer,
  352. IN DWORD cbOutBufferSize,
  353. OUT LPDWORD pcbBytesReturned
  354. )
  355. /*++
  356. Routine Description:
  357. ResourceControl routine for MsMQ Service resources.
  358. Perform the control request specified by ControlCode on the specified
  359. resource.
  360. Arguments:
  361. ResourceId - Supplies the resource id for the specific resource.
  362. nControlCode - Supplies the control code that defines the action
  363. to be performed.
  364. pvInBuffer - Supplies a pointer to a buffer containing input data.
  365. cbInBufferSize - Supplies the size, in bytes, of the data pointed
  366. to by pvInBuffer.
  367. pvOutBuffer - Supplies a pointer to the output buffer to be filled in.
  368. cbOutBufferSize - Supplies the size, in bytes, of the available space
  369. pointed to by pvOutBuffer.
  370. pcbBytesReturned - Returns the number of bytes of pvOutBuffer actually
  371. filled in by the resource. If pvOutBuffer is too small, pcbBytesReturned
  372. contains the total number of bytes for the operation to succeed.
  373. Return Value:
  374. ERROR_SUCCESS - The function completed successfully.
  375. ERROR_INVALID_FUNCTION - The requested control code is not supported.
  376. In some cases, this allows the cluster software to perform the work.
  377. Win32 error code - The function failed.
  378. --*/
  379. {
  380. DWORD status;
  381. DWORD cbRequired;
  382. PCOMMON_RESOURCE pResourceEntry = (PCOMMON_RESOURCE) ResourceId;
  383. switch ( nControlCode ) {
  384. case CLUSCTL_RESOURCE_ENUM_PRIVATE_PROPERTIES:
  385. case CLUSCTL_RESOURCE_UNKNOWN:
  386. *pcbBytesReturned = 0;
  387. status = ERROR_SUCCESS;
  388. break;
  389. case CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES:
  390. status = MsMQGetPrivateResProperties(
  391. pResourceEntry,
  392. pvOutBuffer,
  393. cbOutBufferSize,
  394. pcbBytesReturned );
  395. break;
  396. case CLUSCTL_RESOURCE_CLUSTER_VERSION_CHANGED:
  397. MsMQPerformFixup( pResourceEntry );
  398. status = ERROR_SUCCESS;
  399. break;
  400. case CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES:
  401. case CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES:
  402. status = ERROR_INVALID_PARAMETER;
  403. break;
  404. default:
  405. status = CommonResourceControl(
  406. ResourceId,
  407. nControlCode,
  408. pvInBuffer,
  409. cbInBufferSize,
  410. pvOutBuffer,
  411. cbOutBufferSize,
  412. pcbBytesReturned
  413. );
  414. break;
  415. }
  416. return(status);
  417. } // MsMQResourceControl
  418. DWORD
  419. MsMQGetPrivateResProperties(
  420. IN OUT PCOMMON_RESOURCE pResourceEntry,
  421. OUT PVOID pvOutBuffer,
  422. IN DWORD cbOutBufferSize,
  423. OUT LPDWORD pcbBytesReturned
  424. )
  425. /*++
  426. Routine Description:
  427. Processes the CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES control function
  428. for resources of type MsMQ Service.
  429. Arguments:
  430. pResourceEntry - Supplies the resource entry on which to operate.
  431. pvOutBuffer - Returns the output data.
  432. cbOutBufferSize - Supplies the size, in bytes, of the data pointed
  433. to by pvOutBuffer.
  434. pcbBytesReturned - The number of bytes returned in pvOutBuffer.
  435. Return Value:
  436. ERROR_SUCCESS - The function completed successfully.
  437. ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
  438. ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
  439. Win32 error code - The function failed.
  440. --*/
  441. {
  442. DWORD status;
  443. DWORD cbRequired;
  444. DWORD cbLocalOutBufferSize = cbOutBufferSize;
  445. do {
  446. //
  447. // Read our parameters.
  448. //
  449. status = MsMQReadParametersEx( pResourceEntry, FALSE /* bCheckForRequiredProperties */ );
  450. if ( status != ERROR_SUCCESS ) {
  451. break;
  452. }
  453. //
  454. // Construct a property list from the parameter block.
  455. //
  456. status = ResUtilPropertyListFromParameterBlock(
  457. MsMQResourcePrivateProperties,
  458. pvOutBuffer,
  459. &cbLocalOutBufferSize,
  460. (const LPBYTE) &pResourceEntry->Params,
  461. pcbBytesReturned,
  462. &cbRequired
  463. );
  464. if ( status == ERROR_SUCCESS ) {
  465. (g_LogEvent)(
  466. pResourceEntry->ResourceHandle,
  467. LOG_ERROR,
  468. L"Error constructing property list from parameter block. Error: %1!u!.\n",
  469. status
  470. );
  471. break;
  472. }
  473. //
  474. // Add unknown properties.
  475. //
  476. status = ResUtilAddUnknownProperties(
  477. pResourceEntry->ParametersKey,
  478. MsMQResourcePrivateProperties,
  479. pvOutBuffer,
  480. cbOutBufferSize,
  481. pcbBytesReturned,
  482. &cbRequired
  483. );
  484. if ( status != ERROR_SUCCESS ) {
  485. (g_LogEvent)(
  486. pResourceEntry->ResourceHandle,
  487. LOG_ERROR,
  488. L"Error adding unknown properties to the property list. Error: %1!u!.\n",
  489. status
  490. );
  491. break;
  492. }
  493. } while ( 0 );
  494. if ( status == ERROR_MORE_DATA ) {
  495. *pcbBytesReturned = cbRequired;
  496. }
  497. return(status);
  498. } // MsMQGetPrivateResProperties
  499. BOOLEAN
  500. WINAPI
  501. MsMQDllEntryPoint(
  502. IN HINSTANCE DllHandle,
  503. IN DWORD Reason,
  504. IN LPVOID Reserved
  505. )
  506. {
  507. switch ( Reason ) {
  508. case DLL_PROCESS_ATTACH:
  509. CommonSemaphore = CreateSemaphoreW( NULL,
  510. 0,
  511. 1,
  512. COMMON_SEMAPHORE );
  513. if ( CommonSemaphore == NULL ) {
  514. return(FALSE);
  515. }
  516. if (GetLastError() != ERROR_ALREADY_EXISTS)
  517. {
  518. //if the semaphore didnt exist, set its initial count to 1
  519. ReleaseSemaphore(CommonSemaphore, 1, NULL);
  520. }
  521. break;
  522. case DLL_PROCESS_DETACH:
  523. if ( CommonSemaphore ) {
  524. CloseHandle( CommonSemaphore );
  525. }
  526. break;
  527. default:
  528. break;
  529. }
  530. return(TRUE);
  531. } // MsMQDllEntryPoint
  532. //***********************************************************
  533. //
  534. // Define MsMQ Function Table
  535. //
  536. //***********************************************************
  537. CLRES_V1_FUNCTION_TABLE( MsMQFunctionTable, // Name
  538. CLRES_VERSION_V1_00, // Version
  539. Common, // Prefix
  540. NULL, // Arbitrate
  541. NULL, // Release
  542. MsMQResourceControl, // ResControl
  543. CommonResourceTypeControl ); // ResTypeControl