windows-nt/Source/XPSP1/NT/admin/wmi/wbem/winmgmt/msg/msmqcomn.cpp
2020-09-26 16:20:57 +08:00

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;
}