375 lines
7.8 KiB
C++
375 lines
7.8 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (C) 1996-2001 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#include <wbemcli.h>
|
||
|
#include <wmimsg.h>
|
||
|
#include <tchar.h>
|
||
|
#include "msmqcomn.h"
|
||
|
|
||
|
#define MAX_FORMAT_NAME 1024
|
||
|
#define CALLFUNC(FUNC) rApi.m_fp ## FUNC
|
||
|
|
||
|
HRESULT MqClassToWmiRes( DWORD dwClass )
|
||
|
{
|
||
|
switch( dwClass )
|
||
|
{
|
||
|
case MQMSG_CLASS_NACK_ACCESS_DENIED :
|
||
|
return WBEM_E_ACCESS_DENIED;
|
||
|
|
||
|
case MQMSG_CLASS_NACK_BAD_DST_Q :
|
||
|
return WMIMSG_E_INVALIDADDRESS;
|
||
|
|
||
|
case MQMSG_CLASS_NACK_BAD_ENCRYPTION :
|
||
|
case MQMSG_CLASS_NACK_COULD_NOT_ENCRYPT :
|
||
|
return WMIMSG_E_ENCRYPTFAILURE;
|
||
|
|
||
|
case MQMSG_CLASS_NACK_BAD_SIGNATURE :
|
||
|
case MQMSG_CLASS_NACK_UNSUPPORTED_CRYPTO_PROVIDER :
|
||
|
return WMIMSG_E_AUTHFAILURE;
|
||
|
|
||
|
case MQMSG_CLASS_NACK_NOT_TRANSACTIONAL_Q :
|
||
|
case MQMSG_CLASS_NACK_NOT_TRANSACTIONAL_MSG :
|
||
|
return WMIMSG_E_XACTFAILURE;
|
||
|
|
||
|
case MQMSG_CLASS_NACK_PURGED :
|
||
|
case MQMSG_CLASS_NACK_Q_DELETED :
|
||
|
case MQMSG_CLASS_NACK_Q_PURGED :
|
||
|
return WMIMSG_E_QUEUEPURGED;
|
||
|
|
||
|
case MQMSG_CLASS_NACK_RECEIVE_TIMEOUT :
|
||
|
case MQMSG_CLASS_NACK_RECEIVE_TIMEOUT_AT_SENDER :
|
||
|
return WMIMSG_E_TIMEDOUT;
|
||
|
};
|
||
|
|
||
|
return dwClass;
|
||
|
}
|
||
|
|
||
|
HRESULT MqResToWmiRes( HRESULT hr, HRESULT hrDefault )
|
||
|
{
|
||
|
switch( hr )
|
||
|
{
|
||
|
case MQ_ERROR_SHARING_VIOLATION :
|
||
|
case MQ_ERROR_ACCESS_DENIED :
|
||
|
|
||
|
return WBEM_E_ACCESS_DENIED;
|
||
|
|
||
|
case MQ_ERROR_ILLEGAL_SECURITY_DESCRIPTOR :
|
||
|
|
||
|
return WBEM_E_INVALID_PROPERTY;
|
||
|
|
||
|
case MQ_ERROR_SERVICE_NOT_AVAILABLE :
|
||
|
case MQ_ERROR_NO_DS :
|
||
|
case MQ_ERROR_DTC_CONNECT :
|
||
|
|
||
|
return WMIMSG_E_REQSVCNOTAVAIL;
|
||
|
|
||
|
case MQ_ERROR_QUEUE_NOT_FOUND :
|
||
|
|
||
|
return WMIMSG_E_TARGETNOTFOUND;
|
||
|
|
||
|
case MQ_ERROR_ILLEGAL_FORMATNAME :
|
||
|
case MQ_ERROR_ILLEGAL_QUEUE_PATHNAME :
|
||
|
case MQ_ERROR_UNSUPPORTED_FORMATNAME_OPERATION :
|
||
|
|
||
|
return WMIMSG_E_INVALIDADDRESS;
|
||
|
|
||
|
case MQ_ERROR_NO_INTERNAL_USER_CERT :
|
||
|
|
||
|
return WMIMSG_E_AUTHFAILURE;
|
||
|
|
||
|
case MQ_ERROR_TRANSACTION_USAGE :
|
||
|
|
||
|
return WMIMSG_E_XACTFAILURE;
|
||
|
|
||
|
case MQ_ERROR_INSUFFICIENT_RESOURCES :
|
||
|
|
||
|
return WMIMSG_E_MSGTOOLARGE;
|
||
|
|
||
|
case MQ_ERROR_QUEUE_EXISTS :
|
||
|
|
||
|
return WBEM_E_ALREADY_EXISTS;
|
||
|
|
||
|
case MQ_ERROR_IO_TIMEOUT :
|
||
|
|
||
|
return WMIMSG_E_TIMEDOUT;
|
||
|
};
|
||
|
|
||
|
return hrDefault == S_OK ? hr : hrDefault;
|
||
|
}
|
||
|
|
||
|
HRESULT StartMsmqServiceNT()
|
||
|
{
|
||
|
SC_HANDLE hSvcMgr;
|
||
|
|
||
|
hSvcMgr = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
|
||
|
|
||
|
if ( hSvcMgr == NULL )
|
||
|
{
|
||
|
return WBEM_E_ACCESS_DENIED;
|
||
|
}
|
||
|
|
||
|
SC_HANDLE hSvc;
|
||
|
|
||
|
hSvc = OpenServiceW( hSvcMgr, L"msmq", SERVICE_START );
|
||
|
|
||
|
if ( hSvc == NULL )
|
||
|
{
|
||
|
CloseServiceHandle( hSvcMgr );
|
||
|
return WBEM_E_ACCESS_DENIED;
|
||
|
}
|
||
|
|
||
|
BOOL bRes = StartService( hSvc, 0, NULL );
|
||
|
|
||
|
CloseServiceHandle( hSvc );
|
||
|
CloseServiceHandle( hSvcMgr );
|
||
|
|
||
|
return bRes ? S_OK : HRESULT_FROM_WIN32( GetLastError() );
|
||
|
}
|
||
|
|
||
|
HRESULT StartMsmqService9x()
|
||
|
{
|
||
|
//
|
||
|
// TODO: will probably have to exec process here.
|
||
|
//
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT EnsureMsmqService( CMsmqApi& rApi )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
//
|
||
|
// issue a call to find out if the msmq service is down.
|
||
|
//
|
||
|
|
||
|
hr = IsMsmqOnline( rApi );
|
||
|
|
||
|
if ( hr == WMIMSG_E_REQSVCNOTAVAIL )
|
||
|
{
|
||
|
//
|
||
|
// try to restart the service.
|
||
|
//
|
||
|
|
||
|
OSVERSIONINFO osi;
|
||
|
ZeroMemory( &osi, sizeof(OSVERSIONINFO) );
|
||
|
osi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
||
|
GetVersionEx( &osi );
|
||
|
|
||
|
if ( osi.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS )
|
||
|
{
|
||
|
hr = StartMsmqServiceNT();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
hr = StartMsmqService9x();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( rApi.m_fpMQRegisterCertificate != NULL )
|
||
|
{
|
||
|
//
|
||
|
// try to ensure that the calling user has an internal certificate
|
||
|
// registered.
|
||
|
//
|
||
|
|
||
|
CALLFUNC(MQRegisterCertificate)( MQCERT_REGISTER_IF_NOT_EXIST,
|
||
|
NULL,
|
||
|
0 );
|
||
|
}
|
||
|
|
||
|
return WBEM_S_NO_ERROR;
|
||
|
}
|
||
|
|
||
|
HRESULT IsMsmqWorkgroup( CMsmqApi& rApi )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
//
|
||
|
// if the MQGetPrivateComputerInformation is avaliable use it. if not,
|
||
|
// then we have to go to the registry.
|
||
|
//
|
||
|
|
||
|
if ( rApi.m_fpMQGetPrivateComputerInformation != NULL )
|
||
|
{
|
||
|
MQPROPVARIANT PropVar;
|
||
|
PropVar.vt = VT_BOOL;
|
||
|
QMPROPID PropID = PROPID_PC_DS_ENABLED;
|
||
|
|
||
|
MQPRIVATEPROPS PrivProps;
|
||
|
PrivProps.cProp = 1;
|
||
|
PrivProps.aPropID = &PropID;
|
||
|
PrivProps.aPropVar = &PropVar;
|
||
|
PrivProps.aStatus = NULL;
|
||
|
|
||
|
hr = CALLFUNC(MQGetPrivateComputerInformation)( NULL, &PrivProps );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
hr = PropVar.boolVal == VARIANT_TRUE ? S_OK : S_FALSE;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// TODO: Add non win2k version here ..
|
||
|
//
|
||
|
|
||
|
hr = S_FALSE;
|
||
|
}
|
||
|
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
HRESULT IsMsmqOnline( CMsmqApi& rApi )
|
||
|
{
|
||
|
//
|
||
|
// There is a public w2k func to do this, but we can't rely on it because
|
||
|
// this module needs to run on older platforms. Going to use internal
|
||
|
// method for now.
|
||
|
//
|
||
|
|
||
|
HRESULT hr;
|
||
|
|
||
|
MQPROPVARIANT MgmtPropVar;
|
||
|
QMPROPID MgmtPropID = PROPID_MGMT_MSMQ_CONNECTED;
|
||
|
|
||
|
MQMGMTPROPS MgmtProps;
|
||
|
MgmtProps.cProp = 1;
|
||
|
MgmtProps.aPropID = &MgmtPropID;
|
||
|
MgmtProps.aPropVar = &MgmtPropVar;
|
||
|
MgmtProps.aStatus = NULL;
|
||
|
|
||
|
hr = CALLFUNC(MQMgmtGetInfo)( NULL, L"MACHINE", &MgmtProps );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
return MqResToWmiRes( hr );
|
||
|
}
|
||
|
|
||
|
if ( _wcsicmp( MgmtPropVar.pwszVal, MSMQ_CONNECTED ) != 0 )
|
||
|
{
|
||
|
return S_FALSE;
|
||
|
}
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT NormalizeQueueName( CMsmqApi& rApi,
|
||
|
LPCWSTR wszEndpoint,
|
||
|
WString& rwsFormat )
|
||
|
{
|
||
|
HRESULT hr;
|
||
|
|
||
|
//
|
||
|
// if there is an '=' before any '\', then it is a format name.
|
||
|
// else it is a pathname.
|
||
|
//
|
||
|
|
||
|
WCHAR* pwchEquals = wcschr( wszEndpoint, '=' );
|
||
|
WCHAR* pwchSlash = wcschr( wszEndpoint, '\\' );
|
||
|
|
||
|
if ( pwchEquals != NULL )
|
||
|
{
|
||
|
if ( pwchSlash == NULL || pwchSlash > pwchEquals )
|
||
|
{
|
||
|
rwsFormat = wszEndpoint;
|
||
|
return S_OK;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WCHAR achFormat[MAX_FORMAT_NAME];
|
||
|
ULONG cFormat = MAX_FORMAT_NAME;
|
||
|
|
||
|
hr = CALLFUNC(MQPathNameToFormatName)( wszEndpoint, achFormat, &cFormat );
|
||
|
|
||
|
if ( FAILED(hr) )
|
||
|
{
|
||
|
return hr;
|
||
|
}
|
||
|
|
||
|
rwsFormat = achFormat;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
/**************************************************************************
|
||
|
CMsmqApi
|
||
|
***************************************************************************/
|
||
|
|
||
|
CMsmqApi::~CMsmqApi()
|
||
|
{
|
||
|
if ( m_hModule != NULL )
|
||
|
{
|
||
|
FreeLibrary( m_hModule );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define GETFUNC(FUNC) \
|
||
|
m_fp ##FUNC = (P ##FUNC) GetProcAddress( m_hModule, #FUNC ); \
|
||
|
if ( m_fp ##FUNC == NULL ) { return HRESULT_FROM_WIN32(GetLastError()); }
|
||
|
|
||
|
#define GETFUNC_OPT(FUNC) \
|
||
|
m_fp ##FUNC = (P ##FUNC) GetProcAddress( m_hModule, #FUNC );
|
||
|
|
||
|
|
||
|
HRESULT CMsmqApi::Initialize()
|
||
|
{
|
||
|
if ( m_hModule != NULL )
|
||
|
{
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
m_hModule = LoadLibrary( _T("mqrt") );
|
||
|
|
||
|
if ( m_hModule == NULL )
|
||
|
{
|
||
|
//
|
||
|
// msmq is not installed.
|
||
|
//
|
||
|
return WMIMSG_E_REQSVCNOTAVAIL;
|
||
|
}
|
||
|
|
||
|
GETFUNC( MQCreateQueue )
|
||
|
GETFUNC( MQOpenQueue )
|
||
|
GETFUNC( MQDeleteQueue )
|
||
|
GETFUNC( MQFreeMemory )
|
||
|
GETFUNC( MQSendMessage )
|
||
|
GETFUNC( MQReceiveMessage )
|
||
|
GETFUNC( MQCloseQueue )
|
||
|
GETFUNC( MQCreateCursor )
|
||
|
GETFUNC( MQCloseCursor )
|
||
|
GETFUNC( MQMgmtGetInfo )
|
||
|
GETFUNC( MQPathNameToFormatName )
|
||
|
GETFUNC( MQGetSecurityContext )
|
||
|
GETFUNC( MQGetQueueProperties)
|
||
|
GETFUNC( MQFreeSecurityContext )
|
||
|
GETFUNC_OPT( MQRegisterCertificate )
|
||
|
GETFUNC_OPT( MQGetPrivateComputerInformation )
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|