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
19 KiB
682 lines
19 KiB
/*++
|
|
|
|
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
|
|
|
|
|