/****************************************************************************** Copyright (c) 2000 Microsoft Corporation Module Name: pftn.cpp Abstract: Thread neutral COM ptrs. This is stolen from dmassare's MPC_Common class pretty much intact (with tracing & some stylistic changes added in) Revision History: created derekm 04/12/00 ******************************************************************************/ #include "stdafx.h" #include "pftn.h" #include ///////////////////////////////////////////////////////////////////////////// // tracing #ifdef THIS_FILE #undef THIS_FILE #endif static char __szTraceSourceFile[] = __FILE__; #define THIS_FILE __szTraceSourceFile ///////////////////////////////////////////////////////////////////////////// // CPFComPtrThreadNeutral_GIT construct / term // ************************************************************************** CPFComPtrThreadNeutral_GIT::CPFComPtrThreadNeutral_GIT(void) { m_pGIT = NULL; ::InitializeCriticalSection(&m_cs); } // ************************************************************************** CPFComPtrThreadNeutral_GIT::~CPFComPtrThreadNeutral_GIT(void) { this->Term(); ::DeleteCriticalSection(&m_cs); } ///////////////////////////////////////////////////////////////////////////// // CPFComPtrThreadNeutral_GIT exposed // ************************************************************************** void CPFComPtrThreadNeutral_GIT::Lock(void) { ::EnterCriticalSection(&m_cs); } // ************************************************************************** void CPFComPtrThreadNeutral_GIT::Unlock(void) { ::LeaveCriticalSection(&m_cs); } // ************************************************************************** HRESULT CPFComPtrThreadNeutral_GIT::GetGIT(IGlobalInterfaceTable **ppGIT) { USE_TRACING("CPFComPtrThreadNeutral_GIT::GetGIT"); // this will automatcially unlock when the fn exits CAutoUnlockCS aucs(&m_cs); HRESULT hr = NOERROR; VALIDATEPARM(hr, (ppGIT == NULL)); if (FAILED(hr)) goto done; aucs.Lock(); VALIDATEEXPR(hr, (m_pGIT == NULL), E_FAIL); if (FAILED(hr)) goto done; if (*ppGIT = m_pGIT) { m_pGIT->AddRef(); hr = NOERROR; } aucs.Unlock(); done: return hr; } // ************************************************************************** HRESULT CPFComPtrThreadNeutral_GIT::Init(void) { USE_TRACING("CPFComPtrThreadNeutral_GIT::Init"); HRESULT hr = NOERROR; this->Lock(); if (m_pGIT == NULL) { TESTHR(hr, CoCreateInstance(CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, IID_IGlobalInterfaceTable, (LPVOID *)&m_pGIT)); } this->Unlock(); return hr; } // ************************************************************************** HRESULT CPFComPtrThreadNeutral_GIT::Term(void) { USE_TRACING("CPFComPtrThreadNeutral_GIT::Term"); HRESULT hr = NOERROR; this->Lock(); if (m_pGIT != NULL) { m_pGIT->Release(); m_pGIT = NULL; } this->Unlock(); return hr; } // ************************************************************************** HRESULT CPFComPtrThreadNeutral_GIT::RegisterInterface(IUnknown *pUnk, REFIID riid, DWORD *pdwCookie) { USE_TRACING("CPFComPtrThreadNeutral_GIT::RegisterInterface"); CComPtr pGIT; HRESULT hr = NOERROR; VALIDATEPARM(hr, (pUnk == NULL || pdwCookie == NULL)); if (FAILED(hr)) return hr; TESTHR(hr, GetGIT(&pGIT)); if (FAILED(hr)) return hr; TESTHR(hr, pGIT->RegisterInterfaceInGlobal(pUnk, riid, pdwCookie)); return hr; } // ************************************************************************** HRESULT CPFComPtrThreadNeutral_GIT::RevokeInterface(DWORD dwCookie) { USE_TRACING("CPFComPtrThreadNeutral_GIT::RevokeInterface"); CComPtr pGIT; HRESULT hr = NOERROR; TESTHR(hr, GetGIT(&pGIT)); if (FAILED(hr)) return hr; TESTHR(hr, pGIT->RevokeInterfaceFromGlobal(dwCookie)); return hr; } // ************************************************************************** HRESULT CPFComPtrThreadNeutral_GIT::GetInterface(DWORD dwCookie, REFIID riid, void **ppv) { USE_TRACING("CPFComPtrThreadNeutral_GIT::GetInterface"); CComPtr pGIT; HRESULT hr; TESTHR(hr, GetGIT(&pGIT)); if (FAILED(hr)) return hr; TESTHR(hr, pGIT->GetInterfaceFromGlobal(dwCookie, riid, ppv)); return hr; } ///////////////////////////////////////////////////////////////////////////// // CPFCallItem // ************************************************************************** CPFCallItem::CPFCallItem() { m_vt = VT_EMPTY; // VARTYPE m_vt; // CComPtrThreadNeutral m_Unknown; // CComPtrThreadNeutral m_Dispatch; // CComVariant m_Other; } // ************************************************************************** CPFCallItem& CPFCallItem::operator=(const CComVariant& var) { switch(m_vt = var.vt) { case VT_UNKNOWN: m_Unknown = var.punkVal; break; case VT_DISPATCH: m_Dispatch = var.pdispVal; break; default: m_Other = var; break; } return *this; } // ************************************************************************** CPFCallItem::operator CComVariant() const { CComVariant res; switch(m_vt) { case VT_UNKNOWN: res = (CComPtr)m_Unknown; break; case VT_DISPATCH: res = (CComPtr)m_Dispatch; break; default: res = m_Other; break; } return res; } ///////////////////////////////////////////////////////////////////////////// // CPFCallDesc // ************************************************************************** CPFCallDesc::CPFCallDesc(void) { m_rgciVars = NULL; m_dwVars = 0; } // ************************************************************************** CPFCallDesc::~CPFCallDesc(void) { if (m_rgciVars != NULL) delete [] m_rgciVars; } // ************************************************************************** HRESULT CPFCallDesc::Init(IDispatch *dispTarget, DISPID dispidMethod, const CComVariant *rgvVars, int dwVars) { USE_TRACING("CPFCallDesc::Init"); HRESULT hr = NOERROR; m_rgciVars = new CPFCallItem[dwVars]; VALIDATEEXPR(hr, (m_rgciVars == NULL), E_OUTOFMEMORY); if (FAILED(hr)) return hr; m_dispTarget = dispTarget; m_dwVars = dwVars; m_dispidMethod = dispidMethod; if (m_rgciVars != NULL) { int i; for(i = 0; i < dwVars; i++) m_rgciVars[i] = rgvVars[i]; } return hr; } // ************************************************************************** HRESULT CPFCallDesc::Call(void) { USE_TRACING("CPFCallDesc::Call"); CComPtr dispTarget = m_dispTarget; CComVariant* pvars; CComVariant vResult; DISPPARAMS disp; HRESULT hr; DWORD i; VALIDATEEXPR(hr, (dispTarget == NULL), E_POINTER); if (FAILED(hr)) return hr; pvars = new CComVariant[m_dwVars]; VALIDATEEXPR(hr, (pvars == NULL), E_OUTOFMEMORY); if (FAILED(hr)) return hr; for(i = 0; i < m_dwVars; i++) pvars[i] = m_rgciVars[i]; ZeroMemory(&disp, sizeof(disp)); disp.cArgs = m_dwVars; disp.rgvarg = pvars; TESTHR(hr, dispTarget->Invoke(m_dispidMethod, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &vResult, NULL, NULL)); delete [] pvars; return hr; } ///////////////////////////////////////////////////////////////////////////// // CPFModule // ************************************************************************** HRESULT CPFModule::Init(void) { USE_TRACING("CPFModule::Init"); HRESULT hr = NULL; TESTHR(hr, m_GITHolder.Init()); return hr; } // ************************************************************************** HRESULT CPFModule::Term(void) { USE_TRACING("CPFModule::Init"); HRESULT hr = NULL; TESTHR(hr, m_GITHolder.Term()); return hr; }