|
|
/*++
Copyright (c) 1992-1997 Microsoft Corporation
Module Name:
msmq.c
Abstract:
Resource DLL to control and monitor the NT DHCPServer service.
Author:
Robs 3/28/96, based on RodGa's generic resource dll
Revision History:
--*/
#include "..\common\svc.c"
#include "clusudef.h"
#include "ntverp.h"
extern CLRES_FUNCTION_TABLE MsMQFunctionTable;
#define MSMQ_VERSION L"Version"
#define MSMQ_DEFAULT_VERSION 0x04000000
#define PARAM_NAME__VERSION L"Version"
RESUTIL_PROPERTY_ITEM MsMQResourcePrivateProperties[] = { { PARAM_NAME__VERSION, NULL, CLUSPROP_FORMAT_DWORD, MSMQ_DEFAULT_VERSION, 0, 0xFFFFFFFF, 0, FIELD_OFFSET(COMMON_PARAMS,dwVersion) }, { 0 } };
//
// Forward Functions
//
DWORD WINAPI MsMQResourceControl( IN RESID ResourceId, IN DWORD nControlCode, IN PVOID pvInBuffer, IN DWORD cbInBufferSize, OUT PVOID pvOutBuffer, IN DWORD cbOutBufferSize, OUT LPDWORD pcbBytesReturned );
DWORD MsMQGetPrivateResProperties( IN OUT PCOMMON_RESOURCE pResourceEntry, OUT PVOID pvOutBuffer, IN DWORD cbOutBufferSize, OUT LPDWORD pcbBytesReturned );
//
// Local Functions
//
VOID MsMQResetCheckpoints( PCOMMON_RESOURCE ResourceEntry )
/*++
Routine Description
Delete and then set registry checkpoints this will clean out old registry checkpoint settings.
Arguments:
None.
Return Value:
None.
--*/
{ DWORD returnSize; DWORD idx; DWORD status;
//
// Delete old registry checkpoints that were set.
//
if ( RegSyncCount != 0 ) { returnSize = 0; //
// Set registry sync keys if we need them.
//
for ( idx = 0; idx < RegSyncCount; idx++ ) { status = ClusterResourceControl( ResourceEntry->hResource, NULL, CLUSCTL_RESOURCE_DELETE_REGISTRY_CHECKPOINT, RegSync[idx], (lstrlenW( RegSync[idx] ) + 1) * sizeof(WCHAR), NULL, 0, &returnSize ); if ( status != ERROR_SUCCESS ){ if ( status == ERROR_ALREADY_EXISTS ){ status = ERROR_SUCCESS; } else{ (g_LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Failed to delete registry checkpoint, status %1!u!.\n", status ); goto error_exit; } } } }
//
// Set new registry checkpoints that we need.
//
if ( RegSyncCount != 0 ) { returnSize = 0; //
// Set registry sync keys if we need them.
//
for ( idx = 0; idx < RegSyncCount; idx++ ) { status = ClusterResourceControl( ResourceEntry->hResource, NULL, CLUSCTL_RESOURCE_ADD_REGISTRY_CHECKPOINT, RegSync[idx], (lstrlenW( RegSync[idx] ) + 1) * sizeof(WCHAR), NULL, 0, &returnSize ); if ( status != ERROR_SUCCESS ){ if ( status == ERROR_ALREADY_EXISTS ){ status = ERROR_SUCCESS; } else{ (g_LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Failed to set registry checkpoint, status %1!u!.\n", status ); goto error_exit; } } } }
//
// Set any crypto checkpoints that we need.
//
if ( CryptoSyncCount != 0 ) { returnSize = 0; //
// Set registry sync keys if we need them.
//
for ( idx = 0; idx < CryptoSyncCount; idx++ ) { status = ClusterResourceControl( ResourceEntry->hResource, NULL, CLUSCTL_RESOURCE_ADD_CRYPTO_CHECKPOINT, CryptoSync[idx], (lstrlenW( CryptoSync[idx] ) + 1) * sizeof(WCHAR), NULL, 0, &returnSize ); if ( status != ERROR_SUCCESS ){ if (status == ERROR_ALREADY_EXISTS){ status = ERROR_SUCCESS; } else{ (g_LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Failed to set crypto checkpoint, status %1!u!.\n", status ); goto error_exit; } } } }
//
// Set any domestic crypto checkpoints that we need.
//
if ( DomesticCryptoSyncCount != 0 ) { HCRYPTPROV hProv = 0; //
// check if domestic crypto is available
//
if (CryptAcquireContextA( &hProv, NULL, MS_ENHANCED_PROV_A, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { CryptReleaseContext( hProv, 0 ); returnSize = 0; //
// Set registry sync keys if we need them.
//
for ( idx = 0; idx < DomesticCryptoSyncCount; idx++ ) { status = ClusterResourceControl( ResourceEntry->hResource, NULL, CLUSCTL_RESOURCE_ADD_CRYPTO_CHECKPOINT, DomesticCryptoSync[idx], (lstrlenW( DomesticCryptoSync[idx] ) + 1) * sizeof(WCHAR), NULL, 0, &returnSize ); if ( status != ERROR_SUCCESS ){ if (status == ERROR_ALREADY_EXISTS){ status = ERROR_SUCCESS; } else{ (g_LogEvent)( ResourceEntry->ResourceHandle, LOG_ERROR, L"Failed to set domestic crypto checkpoint, status %1!u!.\n", status ); goto error_exit; } } } } }
error_exit:
return;
} // MsMQResetCheckpoints
DWORD MsMQReadParametersEx( IN OUT PVOID pvResourceEntry, IN BOOL bCheckForRequiredProperties )
/*++
Routine Description:
Reads all the parameters for a specied MsMQ resource.
Arguments:
pResourceEntry - Entry in the resource table.
bCheckForRequiredProperties - TRUE = make sure required properties are present.
Return Value:
ERROR_SUCCESS if successful.
Win32 error code if failure occurrs.
--*/
{ DWORD status; COMMON_PARAMS params = { 0 }; LPWSTR pszNameOfPropInError; PCOMMON_RESOURCE pResourceEntry = (PCOMMON_RESOURCE) pvResourceEntry;
//
// Read our parameters.
//
status = ResUtilGetPropertiesToParameterBlock( pResourceEntry->ParametersKey, MsMQResourcePrivateProperties, (LPBYTE) &pResourceEntry->Params, bCheckForRequiredProperties, &pszNameOfPropInError );
if ( status != ERROR_SUCCESS ) { (g_LogEvent)( pResourceEntry->ResourceHandle, LOG_ERROR, L"Unable to read the '%1' property. Error: %2!u!.\n", (pszNameOfPropInError == NULL ? L"" : pszNameOfPropInError), status ); }
return(status);
} // MsMQReadParametersEx
VOID MsMQPerformFixup( IN OUT PCOMMON_RESOURCE pResourceEntry ) { DWORD status; DWORD version; DWORD bytesReturned; DWORD bytesRequired; PVOID propBuffer; COMMON_PARAMS params;
status = MsMQReadParametersEx( pResourceEntry, FALSE ); if ( status != ERROR_SUCCESS ) { return; }
version = pResourceEntry->Params.dwVersion; version = version >> 16;
if ( version < 0x0500 ) { //
// Delete Old Checkpoints and set new ones
//
MsMQResetCheckpoints( pResourceEntry );
params.dwVersion = VER_PRODUCTVERSION_DW;
//
// Get version number as a property list
//
status = ResUtilGetProperties( pResourceEntry->ParametersKey, MsMQResourcePrivateProperties, NULL, 0, &bytesReturned, &bytesRequired ); if ( status != ERROR_SUCCESS ) { (g_LogEvent)( pResourceEntry->ResourceHandle, LOG_ERROR, L"Unable to get properties. Error: %1!u!.\n", status ); return; }
propBuffer = LocalAlloc( LMEM_FIXED, bytesRequired + 2 ); if ( !propBuffer ) { (g_LogEvent)( pResourceEntry->ResourceHandle, LOG_ERROR, L"Unable to allocate property buffer.\n" ); return; }
status = ResUtilGetProperties( pResourceEntry->ParametersKey, MsMQResourcePrivateProperties, propBuffer, bytesRequired+2, &bytesReturned, &bytesRequired ); if ( status != ERROR_SUCCESS ) { (g_LogEvent)( pResourceEntry->ResourceHandle, LOG_ERROR, L"Unable to get properties. Error: %1!u!.\n", status ); LocalFree( propBuffer ); return; }
//
// Set Version Number
//
status = ResUtilSetPropertyParameterBlock( pResourceEntry->ParametersKey, MsMQResourcePrivateProperties, NULL, (LPBYTE) ¶ms, propBuffer, bytesReturned, (LPBYTE) &pResourceEntry->Params ); LocalFree( propBuffer ); if ( status != ERROR_SUCCESS ) { (g_LogEvent)( pResourceEntry->ResourceHandle, LOG_ERROR, L"Unable to set the property parameter block. Error: %1!u!.\n", status ); return; } }
} //MsMQPerformFixup
DWORD WINAPI MsMQResourceControl( IN RESID ResourceId, IN DWORD nControlCode, IN PVOID pvInBuffer, IN DWORD cbInBufferSize, OUT PVOID pvOutBuffer, IN DWORD cbOutBufferSize, OUT LPDWORD pcbBytesReturned )
/*++
Routine Description:
ResourceControl routine for MsMQ Service resources.
Perform the control request specified by ControlCode on the specified resource.
Arguments:
ResourceId - Supplies the resource id for the specific resource.
nControlCode - Supplies the control code that defines the action to be performed.
pvInBuffer - Supplies a pointer to a buffer containing input data.
cbInBufferSize - Supplies the size, in bytes, of the data pointed to by pvInBuffer.
pvOutBuffer - Supplies a pointer to the output buffer to be filled in.
cbOutBufferSize - Supplies the size, in bytes, of the available space pointed to by pvOutBuffer.
pcbBytesReturned - Returns the number of bytes of pvOutBuffer actually filled in by the resource. If pvOutBuffer is too small, pcbBytesReturned contains the total number of bytes for the operation to succeed.
Return Value:
ERROR_SUCCESS - The function completed successfully.
ERROR_INVALID_FUNCTION - The requested control code is not supported. In some cases, this allows the cluster software to perform the work.
Win32 error code - The function failed.
--*/
{ DWORD status; DWORD cbRequired; PCOMMON_RESOURCE pResourceEntry = (PCOMMON_RESOURCE) ResourceId;
switch ( nControlCode ) {
case CLUSCTL_RESOURCE_ENUM_PRIVATE_PROPERTIES: case CLUSCTL_RESOURCE_UNKNOWN: *pcbBytesReturned = 0; status = ERROR_SUCCESS; break;
case CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES: status = MsMQGetPrivateResProperties( pResourceEntry, pvOutBuffer, cbOutBufferSize, pcbBytesReturned ); break;
case CLUSCTL_RESOURCE_CLUSTER_VERSION_CHANGED: MsMQPerformFixup( pResourceEntry ); status = ERROR_SUCCESS; break;
case CLUSCTL_RESOURCE_SET_PRIVATE_PROPERTIES: case CLUSCTL_RESOURCE_VALIDATE_PRIVATE_PROPERTIES: status = ERROR_INVALID_PARAMETER; break;
default: status = CommonResourceControl( ResourceId, nControlCode, pvInBuffer, cbInBufferSize, pvOutBuffer, cbOutBufferSize, pcbBytesReturned ); break; }
return(status);
} // MsMQResourceControl
DWORD MsMQGetPrivateResProperties( IN OUT PCOMMON_RESOURCE pResourceEntry, OUT PVOID pvOutBuffer, IN DWORD cbOutBufferSize, OUT LPDWORD pcbBytesReturned )
/*++
Routine Description:
Processes the CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES control function for resources of type MsMQ Service.
Arguments:
pResourceEntry - Supplies the resource entry on which to operate.
pvOutBuffer - Returns the output data.
cbOutBufferSize - Supplies the size, in bytes, of the data pointed to by pvOutBuffer.
pcbBytesReturned - The number of bytes returned in pvOutBuffer.
Return Value:
ERROR_SUCCESS - The function completed successfully.
ERROR_INVALID_PARAMETER - The data is formatted incorrectly.
ERROR_NOT_ENOUGH_MEMORY - An error occurred allocating memory.
Win32 error code - The function failed.
--*/
{ DWORD status; DWORD cbRequired; DWORD cbLocalOutBufferSize = cbOutBufferSize;
do { //
// Read our parameters.
//
status = MsMQReadParametersEx( pResourceEntry, FALSE /* bCheckForRequiredProperties */ ); if ( status != ERROR_SUCCESS ) { break; }
//
// Construct a property list from the parameter block.
//
status = ResUtilPropertyListFromParameterBlock( MsMQResourcePrivateProperties, pvOutBuffer, &cbLocalOutBufferSize, (const LPBYTE) &pResourceEntry->Params, pcbBytesReturned, &cbRequired ); if ( status == ERROR_SUCCESS ) { (g_LogEvent)( pResourceEntry->ResourceHandle, LOG_ERROR, L"Error constructing property list from parameter block. Error: %1!u!.\n", status ); break; }
//
// Add unknown properties.
//
status = ResUtilAddUnknownProperties( pResourceEntry->ParametersKey, MsMQResourcePrivateProperties, pvOutBuffer, cbOutBufferSize, pcbBytesReturned, &cbRequired ); if ( status != ERROR_SUCCESS ) { (g_LogEvent)( pResourceEntry->ResourceHandle, LOG_ERROR, L"Error adding unknown properties to the property list. Error: %1!u!.\n", status ); break; }
} while ( 0 );
if ( status == ERROR_MORE_DATA ) { *pcbBytesReturned = cbRequired; }
return(status);
} // MsMQGetPrivateResProperties
BOOLEAN WINAPI MsMQDllEntryPoint( IN HINSTANCE DllHandle, IN DWORD Reason, IN LPVOID Reserved ) { switch ( Reason ) {
case DLL_PROCESS_ATTACH: CommonSemaphore = CreateSemaphoreW( NULL, 0, 1, COMMON_SEMAPHORE ); if ( CommonSemaphore == NULL ) { return(FALSE); } if (GetLastError() != ERROR_ALREADY_EXISTS) { //if the semaphore didnt exist, set its initial count to 1
ReleaseSemaphore(CommonSemaphore, 1, NULL); }
break;
case DLL_PROCESS_DETACH: if ( CommonSemaphore ) { CloseHandle( CommonSemaphore ); } break;
default: break; }
return(TRUE);
} // MsMQDllEntryPoint
//***********************************************************
//
// Define MsMQ Function Table
//
//***********************************************************
CLRES_V1_FUNCTION_TABLE( MsMQFunctionTable, // Name
CLRES_VERSION_V1_00, // Version
Common, // Prefix
NULL, // Arbitrate
NULL, // Release
MsMQResourceControl, // ResControl
CommonResourceTypeControl ); // ResTypeControl
|