// Copyright (c) 1997-1999 Microsoft Corporation #include "precomp.h" #ifdef EXT_DEBUG #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #include "ServiceThread.h" #include #include "..\common\T_DataExtractor.h" #include #include "util.h" const wchar_t* MMC_SNAPIN_MACHINE_NAME = L"MMC_SNAPIN_MACHINE_NAME"; CLIPFORMAT WbemServiceThread::MACHINE_NAME = 0; // Allows user to manually leave critical section, checks if inside before leaving class CCheckedInCritSec { protected: CRITICAL_SECTION* m_pcs; BOOL m_fInside; public: CCheckedInCritSec(CRITICAL_SECTION* pcs) : m_pcs(pcs), m_fInside( FALSE ) { EnterCriticalSection(m_pcs); m_fInside = TRUE; } ~CCheckedInCritSec() { Leave(); } void Enter( void ) { if ( !m_fInside ) { EnterCriticalSection(m_pcs); m_fInside = TRUE; } } void Leave( void ) { if ( m_fInside ) { m_fInside = FALSE; LeaveCriticalSection(m_pcs); } } BOOL IsEntered( void ) { return m_fInside; } }; //-------------------------- WbemServiceThread::WbemServiceThread(): m_cRef(1), m_pStream(NULL) { m_hr = 0; m_status = notStarted; m_machineName = L"AGAINWITHTEKLINGONS"; MACHINE_NAME = (CLIPFORMAT) RegisterClipboardFormat(_T("MMC_SNAPIN_MACHINE_NAME")); m_credentials = 0; m_doWork = CreateEvent(NULL, FALSE, FALSE, NULL); m_ptrReady = CreateEvent(NULL, FALSE, FALSE, NULL); m_threadCmd = false; m_hThread = 0; InitializeCriticalSection(¬ifyLock); } //---------------------------------------------------------------- WbemServiceThread::~WbemServiceThread() { m_hr = 0; m_status = notStarted; m_notify.RemoveAll(); if(m_hThread) { m_threadCmd = CT_EXIT; SetEvent(m_doWork); WaitForSingleObject((HANDLE)m_hThread, 5000); } if(m_doWork) { CloseHandle(m_doWork); m_doWork = 0; } if(m_ptrReady) { CloseHandle(m_ptrReady); m_ptrReady = 0; } if (m_credentials) { WbemFreeAuthIdentity(m_credentials->authIdent); m_credentials->authIdent = 0; }; DeleteCriticalSection(¬ifyLock); if (m_pStream) m_pStream->Release(); } //---------------------------------------------------------------- typedef struct { wchar_t t[MAXCOMPUTER_NAME + 1]; } test; void WbemServiceThread::MachineName(IDataObject *_pDataObject, bstr_t *name) { HGLOBAL hMem = GlobalAlloc(GMEM_SHARE,sizeof(test)); wchar_t *pRet = NULL; HRESULT hr = 0; if(hMem != NULL) { STGMEDIUM stgmedium = { TYMED_HGLOBAL, (HBITMAP) hMem}; FORMATETC formatetc = { MACHINE_NAME, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; if((hr = _pDataObject->GetDataHere(&formatetc, &stgmedium)) == S_OK ) { *name = bstr_t((wchar_t *)hMem); } GlobalFree(hMem); } } //---------------------------------------------------------- HRESULT WbemServiceThread::EnsureThread(void) { HRESULT retval = S_OK; if(m_hThread == 0) { // let the thread do the connect. The CWbemService class will // handle marshalling as its used by other threads. if((m_hThread = _beginthread(WbemServiceConnectThread, 0, (LPVOID)this)) == -1) { m_status = threadError; retval = E_FAIL; } } return retval; } //---------------------------------------------------------- HRESULT WbemServiceThread::Connect(bstr_t machineName, bstr_t ns, bool threaded /* = true */, LOGIN_CREDENTIALS *credentials, HWND notifiedWnd) { if(ns.length() == 0) { ns = _T(""); //this allocates... if (&ns == NULL) return E_FAIL; } m_nameSpace = ns; if((m_credentials != credentials) && m_credentials && m_credentials->authIdent) { WbemFreeAuthIdentity(m_credentials->authIdent); m_credentials->authIdent = 0; } if(machineName.length() > 0) { m_credentials = credentials; } else { m_credentials = 0; m_WbemServices.m_authIdent = 0; m_realServices.m_authIdent = 0; } m_hr = 0; if(credentials) { m_machineName = _T("AGAINWITHTEKLINGONS"); // force a reconnect to // the same machine. } // put the name together. bstr_t newMachine; // if reconnecting to another machine... //if(machineName != m_machineName) { // disconnect from the old machine. DisconnectServer(); m_machineName = machineName; int x; // if machine is whacked already... if(_tcsncmp(m_machineName, _T("\\"), 1) == 0) { // use it. m_nameSpace = m_machineName; if(ns.length() > 0) { if(((LPCTSTR)ns)[0] != _T('\\')) // namespace is whacked. { m_nameSpace += _T("\\"); } } m_nameSpace += ns; } else if(((x = m_machineName.length()) > 0)) { // whack it myself. m_nameSpace = "\\\\"; m_nameSpace += m_machineName; if(((LPCTSTR)ns)[0] != _T('\\')) // namespace is whacked. { m_nameSpace += _T("\\"); } m_nameSpace += ns; } EnsureThread(); NotifyWhenDone(notifiedWnd); m_threadCmd = CT_CONNECT; SetEvent(m_doWork); } // else // { // // reconnecting to the same machine-- lie!! // return WBEM_S_SAME; // } return E_FAIL; } //---------------------------------------------------------- // TODO: merge the Connects() bool WbemServiceThread::Connect(IDataObject *_pDataObject, HWND hWnd ) { m_nameSpace = "root\\cimv2"; // put the name together. bstr_t newMachine; MachineName(_pDataObject, &newMachine); if(!newMachine) return false; // if reconnecting to another machine... if(newMachine != m_machineName) { // disconnect from the old machine. DisconnectServer(); m_machineName = newMachine; int x; // if its whacked already... if(_tcsncmp((LPCTSTR)m_machineName, _T("\\"), 1) == 0) { // use it. m_nameSpace = m_machineName; m_nameSpace += "\\root\\cimv2"; } else if(((x = m_machineName.length()) > 0)) { // whack it myself. m_nameSpace = "\\\\"; m_nameSpace += m_machineName; m_nameSpace += "\\root\\cimv2"; } EnsureThread(); NotifyWhenDone(hWnd); m_threadCmd = CT_CONNECT; SetEvent(m_doWork); } else { // reconnecting to the same machine-- lie!! return true; } return false; } //---------------------------------------------------------- // Returns true if a msg will be sent. // Returns false if its already over. bool WbemServiceThread::NotifyWhenDone(HWND dlg) { CCheckedInCritSec autoLock(¬ifyLock); for (int i=0;iAddRef(); IStream *pStream = 0; HRESULT hr = S_OK; HRESULT retval = E_FAIL; CWbemServices pServices; CoInitialize(NULL); MSG msg; while(true) { DWORD res = MsgWaitForMultipleObjects (1,&me->m_doWork, FALSE, -1, QS_ALLINPUT); if (res == WAIT_OBJECT_0 + 1) { while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { DispatchMessage(&msg); } continue; } switch(me->m_threadCmd) { case CT_CONNECT: pStream = 0; /****************** VINOTH *****************************/ me->m_status = WbemServiceThread::connecting; try { me->m_hr = pServices.ConnectServer(me->m_nameSpace, me->m_credentials); } catch(CWbemException &e) { me->m_status = WbemServiceThread::error; me->m_hr = e.GetErrorCode(); } if(SUCCEEDED(me->m_hr)) { if(me->m_status == WbemServiceThread::cancelled) { } else { me->m_status = WbemServiceThread::ready; retval = S_OK; } } else { me->m_status = WbemServiceThread::error; } /*************** END VINOTH ************************/ if(SUCCEEDED(me->m_hr)) { IWbemServices *service = 0; pServices.GetServices(&service); me->Notify(service); service->Release(); } else { me->NotifyError(); } break; case CT_SEND_PTR: if((bool)pServices) { IWbemServices *service = 0; pServices.GetServices(&service); if(me->m_threadCmd == CT_SEND_PTR) { hr = CoMarshalInterThreadInterfaceInStream(IID_IWbemServices, service, &pStream); PostMessage(me->m_hWndGetPtr, WM_ASYNC_CIMOM_CONNECTED, 0, (LPARAM)pStream); } service->Release(); } break; case CT_EXIT: pServices = (IWbemServices *)NULL; break; } //endswitch } //endwhile pServices = (IUnknown *)NULL; me->Release(); CoUninitialize(); }