/*++ Copyright (C) 1996-2001 Microsoft Corporation Module Name: Abstract: History: --*/ #include "precomp.h" #include #include #include #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; }