#include "pch.h"
#include "AGCEvent.h"
#include "AGCEventDef.h"
#include "AGCEventData.h"
#include <..\TCLib\UtilImpl.h>
#include <..\TCLib\BinString.h>
#include <..\TCAtl\SimpleStream.h>
TC_OBJECT_EXTERN_IMPL(CAGCEvent)
HRESULT CAGCEvent::FinalConstruct()
{
#ifdef CAGCEvent_TRACE_CONSTRUCTION
_TRACE_BEGIN
DWORD id = GetCurrentThreadId();
_TRACE_PART2("CAGCEvent::FinalConstruct(): ThreadId = %d (0x%X)\n", id, id);
_TRACE_PART1("\tRaw pointer = 0x%08X", this);
_TRACE_PART1(", IAGCEvent* = 0x%08X\n", static_cast<IAGCEvent*>(this));
_TRACE_END
#endif return S_OK;
}
void CAGCEvent::FinalRelease()
{
#if 0
#pragma pack(push, 4)
static long s_cIterations = 0;
#pragma pack(pop)
debugf("E:%06d\n", InterlockedIncrement(&s_cIterations));
#endif
}
HRESULT CAGCEvent::Init(AGCEventID idEvent, LPCSTR pszContext,
LPCOLESTR pszSubject, long idSubject, long cArgTriplets, va_list argptr)
{
XLock lock(this);
m_id = idEvent;
m_time = GetVariantDateTime();
m_idSubject = idSubject;
m_bstrSubjectName = pszSubject;
m_bstrContext = pszContext;
m_Properties.clear();
RETURN_FAILED(AddStaticFields());
return AddToDictionaryV(cArgTriplets, argptr);
}
HRESULT CAGCEvent::Init(const CAGCEventData& data)
{
XLock lock(this);
m_id = data.GetEventID();
m_time = data.GetTime();
m_idSubject = data.GetSubjectID();
m_Properties.clear();
data.GetVarData(&m_bstrContext, &m_bstrSubjectName, &m_Properties);
return AddStaticFields();
}
HRESULT CAGCEvent::AddToDictionary(long cArgTriplets, ...)
{
va_list argptr;
va_start(argptr, cArgTriplets);
HRESULT hr = AddToDictionaryV(cArgTriplets, argptr);
va_end(argptr);
return hr;
}
HRESULT CAGCEvent::AddToDictionaryV(long cArgTriplets, va_list argptr)
{
XLock lock(this);
for (long i = 0; i < cArgTriplets; ++i)
{
LPCSTR pszArgName = va_arg(argptr, LPCSTR);
assert(!IsBadStringPtrA(pszArgName, UINT(-1)));
CComVariant var;
VARTYPE vt = va_arg(argptr, VARTYPE);
switch (V_VT(&var) = vt)
{
case VT_BOOL:
V_BOOL(&var) = va_arg(argptr, VARIANT_BOOL);
break;
case VT_I1:
V_I1(&var) = va_arg(argptr, CHAR);
break;
case VT_I2:
V_I2(&var) = va_arg(argptr, SHORT);
break;
case VT_I4:
V_I4(&var) = va_arg(argptr, LONG);
break;
case VT_UI1:
V_UI1(&var) = va_arg(argptr, BYTE);
break;
case VT_UI2:
V_UI2(&var) = va_arg(argptr, USHORT);
break;
case VT_ERROR:
V_ERROR(&var) = va_arg(argptr, SCODE);
break;
case VT_R4:
{
DOUBLE dblTemp = va_arg(argptr, DOUBLE);
V_R4(&var) = (float)dblTemp;
break;
}
case VT_R8:
V_R8(&var) = va_arg(argptr, DOUBLE);
break;
case VT_DECIMAL:
V_DECIMAL(&var) = va_arg(argptr, DECIMAL);
break;
case VT_CY:
V_CY(&var) = va_arg(argptr, CY);
break;
case VT_DATE:
V_DATE(&var) = va_arg(argptr, DATE);
break;
case VT_BSTR:
V_BSTR(&var) = SysAllocString(va_arg(argptr, BSTR));
break;
case VT_UNKNOWN:
V_UNKNOWN(&var) = va_arg(argptr, IUnknown*);
V_UNKNOWN(&var)->AddRef();
break;
case VT_DISPATCH:
V_DISPATCH(&var) = va_arg(argptr, IDispatch*);
V_DISPATCH(&var)->AddRef();
break;
case VT_VARIANT:
var.Copy(va_arg(argptr, VARIANT*));
break;
case VT_LPSTR:
{
V_VT(&var) = VT_BSTR;
LPCSTR psz = va_arg(argptr, LPCSTR);
USES_CONVERSION;
V_BSTR(&var) = (psz && '\0' != *psz) ? ::SysAllocString(A2COLE(psz)) : NULL;
break;
}
case VT_LPWSTR:
{
V_VT(&var) = VT_BSTR;
LPCWSTR psz = va_arg(argptr, LPCWSTR);
V_BSTR(&var) = (psz && L'\0' != *psz) ? ::SysAllocString(psz) : NULL;
break;
}
default:
if (vt & VT_BYREF)
{
V_BYREF(&var) = va_arg(argptr, void*);
break;
}
debugf("CAGCEvent::Init(): Specified VARTYPE %hu (0x%04X) is unsupported\n", vt, vt);
assert(false);
}
m_Properties.insert(XProperties::value_type(CComBSTR(pszArgName), var));
}
return S_OK;
}
HRESULT CAGCEvent::AddStaticFields()
{
XLock lock(this);
RETURN_FAILED(get_ComputerName(NULL));
return AddToDictionary(6,
".ID" , VT_I4 , m_id,
".Time" , VT_DATE, m_time,
".ComputerName", VT_BSTR, (BSTR)m_bstrComputerName,
".SubjectID" , VT_I4 , m_idSubject,
".SubjectName" , VT_BSTR, (BSTR)m_bstrSubjectName,
".Context" , VT_BSTR, (BSTR)m_bstrContext);
}
bool CAGCEvent::IsStaticField(BSTR bstr)
{
if (!BSTRLen(bstr))
return false;
if (!_wcsicmp(bstr, OLESTR(".ID")))
return true;
if (!_wcsicmp(bstr, OLESTR(".Time")))
return true;
if (!_wcsicmp(bstr, OLESTR(".ComputerName")))
return true;
if (!_wcsicmp(bstr, OLESTR(".SubjectID")))
return true;
if (!_wcsicmp(bstr, OLESTR(".SubjectName")))
return true;
if (!_wcsicmp(bstr, OLESTR(".Context")))
return true;
return false;
}
HRESULT CAGCEvent::WriteStringToStream(IStream* pStm, BSTR bstr)
{
ULONG cchBSTR = BSTRLen(bstr);
ULONG cchAnsi = cchBSTR ?
WideCharToMultiByte(CP_ACP, 0, bstr, cchBSTR, NULL, 0, NULL, NULL) : 0;
BYTE bIndicator = GetSizePrefix(cchAnsi);
RETURN_FAILED(pStm->Write(&bIndicator, sizeof(bIndicator), NULL));
switch (bIndicator)
{
case LengthZero:
return S_OK;
case Length1Byte:
{
BYTE cch = cchAnsi;
RETURN_FAILED(pStm->Write(&cch, sizeof(cch), NULL));
break;
}
case Length2Bytes:
{
WORD cch = cchAnsi;
RETURN_FAILED(pStm->Write(&cch, sizeof(cch), NULL));
break;
}
case Length4Bytes:
{
RETURN_FAILED(pStm->Write(&cchAnsi, sizeof(cchAnsi), NULL));
break;
}
default:
ZError("bad switch case in WriteStringToStream");
}
LPSTR psz = (LPSTR)_alloca(cchAnsi);
if (!WideCharToMultiByte(CP_ACP, 0, bstr, cchBSTR, psz, cchAnsi, NULL, NULL))
return HRESULT_FROM_WIN32(GetLastError());
RETURN_FAILED(pStm->Write(psz, cchAnsi, NULL));
return S_OK;
}
HRESULT CAGCEvent::WriteVariantToStream(IStream* pStm, CComVariant& var)
{
if (VT_BSTR == V_VT(&var))
{
RETURN_FAILED(WriteStringToStream(pStm, V_BSTR(&var)));
}
else
{
BYTE bCustom = 0x00;
RETURN_FAILED(pStm->Write(&bCustom, sizeof(bCustom), NULL));
RETURN_FAILED(var.WriteToStream(pStm));
}
return S_OK;
}
HRESULT CAGCEvent::ReadStringFromStream(IStream* pStm, BSTR* pbstr, BYTE bIndicator)
{
assert(!*pbstr);
if (!bIndicator)
{
RETURN_FAILED(pStm->Read(&bIndicator, sizeof(bIndicator), NULL));
}
ULONG cchAnsi;
switch (bIndicator)
{
case LengthZero:
return S_OK;
case Length1Byte:
{
BYTE cch;
RETURN_FAILED(pStm->Read(&cch, sizeof(cch), NULL));
cchAnsi = cch;
break;
}
case Length2Bytes:
{
WORD cch;
RETURN_FAILED(pStm->Read(&cch, sizeof(cch), NULL));
cchAnsi = cch;
break;
}
case Length4Bytes:
{
RETURN_FAILED(pStm->Read(&cchAnsi, sizeof(cchAnsi), NULL));
break;
}
default:
ZError("bad switch case in ReadStringFromStream");
}
if (cchAnsi)
{
LPSTR pszAnsi = (LPSTR)_alloca(cchAnsi);
RETURN_FAILED(pStm->Read(pszAnsi, cchAnsi, NULL));
ULONG cchWide = MultiByteToWideChar(CP_ACP, 0, pszAnsi, cchAnsi, NULL, 0);
LPWSTR pszWide = (LPWSTR)_alloca(cchWide);
if (!MultiByteToWideChar(CP_ACP, 0, pszAnsi, cchAnsi, pszWide, cchWide))
return HRESULT_FROM_WIN32(GetLastError());
*pbstr = SysAllocStringLen(pszWide, cchWide);
if (!*pbstr)
return E_OUTOFMEMORY;
}
return S_OK;
}
HRESULT CAGCEvent::ReadVariantFromStream(IStream* pStm, CComVariant& var)
{
var.Clear();
BYTE bCustom;
RETURN_FAILED(pStm->Read(&bCustom, sizeof(bCustom), NULL));
if (bCustom)
{
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = NULL;
RETURN_FAILED(ReadStringFromStream(pStm, &V_BSTR(&var), bCustom));
}
else
{
RETURN_FAILED(var.ReadFromStream(pStm));
}
return S_OK;
}
HRESULT CAGCEvent::SaveToStream(IStream* pStm, BOOL fClearDirty)
{
XLock lock(this);
LPCSTR pszSignature = "1:";
RETURN_FAILED(pStm->Write(pszSignature, strlen(pszSignature), NULL));
RETURN_FAILED(pStm->Write(&m_id, sizeof(m_id), NULL));
RETURN_FAILED(pStm->Write(&m_time, sizeof(m_time), NULL));
long cPairs = 0;
XPropertyIt it;
for (it = m_Properties.begin(); m_Properties.end() != it; ++it)
if (!IsStaticField(it->first))
++cPairs;
RETURN_FAILED(pStm->Write(&cPairs, sizeof(cPairs), NULL));
for (it = m_Properties.begin(); m_Properties.end() != it; ++it)
{
CComBSTR& bstrKey = const_cast<CComBSTR&>(it->first);
CComVariant& varItem = it->second;
if (!IsStaticField(bstrKey))
{
RETURN_FAILED(WriteStringToStream(pStm, bstrKey));
RETURN_FAILED(WriteVariantToStream(pStm, varItem));
}
}
RETURN_FAILED(get_ComputerName(NULL));
RETURN_FAILED(WriteStringToStream(pStm, m_bstrComputerName));
RETURN_FAILED(pStm->Write(&m_idSubject, sizeof(m_idSubject), NULL));
RETURN_FAILED(WriteStringToStream(pStm, m_bstrSubjectName));
RETURN_FAILED(WriteStringToStream(pStm, m_bstrContext));
return S_OK;
}
HRESULT CAGCEvent::LoadFromStream(IStream* pStm)
{
XLock lock(this);
char szSignature[2];
RETURN_FAILED(pStm->Read(szSignature, sizeof(szSignature), NULL));
int iSignature = -1;
const static LPCSTR szSignatures[] = {"0:", "1:"};
for (int i = 0; i < sizeofArray(szSignatures); ++i)
{
if (0 == strncmp(szSignature, szSignatures[i], strlen(szSignatures[i])))
{
iSignature = i;
break;
}
}
if (-1 == iSignature)
return E_INVALIDARG;
RETURN_FAILED(pStm->Read(&m_id, sizeof(m_id), NULL));
RETURN_FAILED(pStm->Read(&m_time, sizeof(m_time), NULL));
long cCount = 0;
RETURN_FAILED(pStm->Read(&cCount, sizeof(cCount), NULL));
m_Properties.clear();
while (cCount--)
{
CComBSTR bstrKey;
CComVariant varItem;
RETURN_FAILED(ReadStringFromStream(pStm, &bstrKey));
RETURN_FAILED(ReadVariantFromStream(pStm, varItem));
m_Properties.insert(XProperties::value_type(bstrKey, varItem));
}
m_bstrComputerName.Empty();
RETURN_FAILED(ReadStringFromStream(pStm, &m_bstrComputerName));
RETURN_FAILED(pStm->Read(&m_idSubject, sizeof(m_idSubject), NULL));
m_bstrSubjectName.Empty();
RETURN_FAILED(ReadStringFromStream(pStm, &m_bstrSubjectName));
m_bstrContext.Empty();
if (iSignature >= 1)
{
RETURN_FAILED(ReadStringFromStream(pStm, &m_bstrContext));
}
RETURN_FAILED(AddStaticFields());
return S_OK;
}
STDMETHODIMP CAGCEvent::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IAGCEvent
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP CAGCEvent::GetClassID(CLSID* pClassID)
{
__try
{
*pClassID = GetObjectCLSID();
}
__except(1)
{
return E_POINTER;
}
return S_OK;
}
STDMETHODIMP CAGCEvent::IsDirty()
{
return S_OK;
}
STDMETHODIMP CAGCEvent::Load(LPSTREAM pStm)
{
XLock lock(this);
RETURN_FAILED(pStm->Read(&m_id, sizeof(m_id), NULL));
RETURN_FAILED(pStm->Read(&m_time, sizeof(m_time), NULL));
long cCount = 0;
RETURN_FAILED(pStm->Read(&cCount, sizeof(cCount), NULL));
m_Properties.clear();
while (cCount--)
{
CComBSTR bstrKey;
CComVariant varItem;
RETURN_FAILED(bstrKey.ReadFromStream(pStm));
RETURN_FAILED(varItem.ReadFromStream(pStm));
m_Properties.insert(XProperties::value_type(bstrKey, varItem));
}
m_bstrComputerName.Empty();
RETURN_FAILED(m_bstrComputerName.ReadFromStream(pStm));
RETURN_FAILED(pStm->Read(&m_idSubject, sizeof(m_idSubject), NULL));
m_bstrSubjectName.Empty();
RETURN_FAILED(m_bstrSubjectName.ReadFromStream(pStm));
m_bstrContext.Empty();
RETURN_FAILED(m_bstrContext.ReadFromStream(pStm));
RETURN_FAILED(AddStaticFields());
return S_OK;
}
STDMETHODIMP CAGCEvent::Save(LPSTREAM pStm, BOOL fClearDirty)
{
XLock lock(this);
RETURN_FAILED(pStm->Write(&m_id, sizeof(m_id), NULL));
RETURN_FAILED(pStm->Write(&m_time, sizeof(m_time), NULL));
long cPairs = 0;
XPropertyIt it;
for (it = m_Properties.begin(); m_Properties.end() != it; ++it)
if (!IsStaticField(it->first))
++cPairs;
RETURN_FAILED(pStm->Write(&cPairs, sizeof(cPairs), NULL));
for (it = m_Properties.begin(); m_Properties.end() != it; ++it)
{
CComBSTR& bstrKey = const_cast<CComBSTR&>(it->first);
CComVariant& varItem = it->second;
if (!IsStaticField(bstrKey))
{
RETURN_FAILED(bstrKey.WriteToStream(pStm));
RETURN_FAILED(varItem.WriteToStream(pStm));
}
}
RETURN_FAILED(get_ComputerName(NULL));
RETURN_FAILED(m_bstrComputerName.WriteToStream(pStm));
RETURN_FAILED(pStm->Write(&m_idSubject, sizeof(m_idSubject), NULL));
RETURN_FAILED(m_bstrSubjectName.WriteToStream(pStm));
RETURN_FAILED(m_bstrContext.WriteToStream(pStm));
return S_OK;
}
STDMETHODIMP CAGCEvent::GetSizeMax(ULARGE_INTEGER* pCbSize)
{
return TCGetPersistStreamSize(GetUnknown(), pCbSize);
}
STDMETHODIMP CAGCEvent::InitNew()
{
XLock lock(this);
m_id = EventID_Unknown;
m_time = GetVariantDateTime();
m_Properties.clear();
return S_OK;
}
STDMETHODIMP CAGCEvent::get_Description(BSTR* pbstrDisplayString)
{
return CAGCEventDef::GetEventDescription(this, pbstrDisplayString);
}
STDMETHODIMP CAGCEvent::get_ID(AGCEventID* pVal)
{
XLock lock(this);
CLEAROUT(pVal, m_id);
return S_OK;
}
STDMETHODIMP CAGCEvent::get_Time(DATE* pVal)
{
XLock lock(this);
CLEAROUT(pVal, m_time);
return S_OK;
}
STDMETHODIMP CAGCEvent::get_PropertyCount(long* pnCount)
{
XLock lock(this);
CLEAROUT(pnCount, (long)m_Properties.size());
return S_OK;
}
STDMETHODIMP CAGCEvent::get_PropertyExists(BSTR bstrKey,
VARIANT_BOOL* pbExists)
{
XLock lock(this);
XPropertyIt it = m_Properties.find(bstrKey);
CLEAROUT(pbExists, VARBOOL(m_Properties.end() != it));
return S_OK;
}
STDMETHODIMP CAGCEvent::get_Property(VARIANT* pvKey, VARIANT* pvValue)
{
CComVariant var;
if (pvKey)
{
CComVariant varKey(*pvKey);
if (SUCCEEDED(varKey.ChangeType(VT_UI4)))
{
XLock lock(this);
ULONG iIndex = V_UI4(&varKey);
bool bGetKey = !!(iIndex & 0x80000000);
iIndex &= 0x7FFFFFFF;
if (iIndex >= m_Properties.size())
return E_INVALIDARG;
if (iIndex < (m_Properties.size() + 1) / 2)
{
XPropertyIt it = m_Properties.begin();
for (ULONG i = 0; i < iIndex; ++i)
++it;
if (bGetKey)
var = it->first;
else
var = it->second;
}
else
{
XPropertyRevIt rit = m_Properties.rbegin();
for (ULONG i = m_Properties.size() - 1; i > iIndex; --i)
++rit;
if (bGetKey)
var = rit->first;
else
var = rit->second;
}
}
else
{
CComVariant varKey(*pvKey);
RETURN_FAILED(varKey.ChangeType(VT_BSTR));
CComBSTR bstrKey(V_BSTR(&varKey));
XLock lock(this);
XPropertyIt it = m_Properties.find(bstrKey);
if (m_Properties.end() != it)
{
var = it->second;
}
else
{
m_Properties.insert(XProperties::value_type(bstrKey, var));
}
}
}
else
{
RETURN_FAILED(get_Description(&V_BSTR(&var)));
V_VT(&var) = VT_BSTR;
}
return var.Detach(pvValue);
}
STDMETHODIMP CAGCEvent::get_ComputerName(BSTR* pbstrComputerName)
{
if (pbstrComputerName)
CLEAROUT(pbstrComputerName, (BSTR)NULL);
XLock lock(this);
if (!m_bstrComputerName.Length())
{
TCHAR szName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD cchName = sizeofArray(szName);
GetComputerName(szName, &cchName);
m_bstrComputerName = szName;
}
if (pbstrComputerName)
{
USES_CONVERSION;
*pbstrComputerName = m_bstrComputerName.Copy();
}
return S_OK;
}
STDMETHODIMP CAGCEvent::get_SubjectID(long* pidSubject)
{
XLock lock(this);
CLEAROUT(pidSubject, m_idSubject);
return S_OK;
}
STDMETHODIMP CAGCEvent::get_SubjectName(BSTR* pbstrSubject)
{
XLock lock(this);
CComBSTR bstrTemp(m_bstrSubjectName);
CLEAROUT(pbstrSubject, (BSTR)bstrTemp);
bstrTemp.Detach();
return S_OK;
}
STDMETHODIMP CAGCEvent::SaveToString(BSTR* pbstr)
{
IStreamPtr spStm;
RETURN_FAILED(CreateStreamOnHGlobal(NULL, true, &spStm));
RETURN_FAILED(SaveToStream(spStm, false));
ULARGE_INTEGER uli;
LARGE_INTEGER liMove = {0, 0};
ZSucceeded(spStm->Seek(liMove, STREAM_SEEK_CUR, &uli));
assert(0 == uli.HighPart);
DWORD cbData = uli.LowPart;
HGLOBAL hGlobal;
RETURN_FAILED(GetHGlobalFromStream(spStm, &hGlobal));
void* pvData = GlobalLock(hGlobal);
DWORD cch = TCBinString<OLECHAR>::GetEncodedStringLength(pvData, cbData);
LPOLESTR psz = (LPOLESTR)_alloca((cch + 1) * sizeof(OLECHAR));
HRESULT hr = TCBinString<OLECHAR>::EncodeToString(pvData, cbData, psz);
GlobalUnlock(hGlobal);
RETURN_FAILED(hr);
*pbstr = SysAllocStringLen(psz, cch);
if (!*pbstr)
return E_OUTOFMEMORY;
return S_OK;
}
STDMETHODIMP CAGCEvent::LoadFromString(BSTR bstr)
{
const static OLECHAR szObjRef[] = OLESTR("objref:");
const static int cchObjRef = sizeofArray(szObjRef) - 1;
if (0 == wcsncmp(bstr, szObjRef, cchObjRef))
{
IUnknownPtr spUnk;
RETURN_FAILED(TCUtilImpl::GetObject(bstr, VARIANT_FALSE, INFINITE, &spUnk));
return CopyObjectThruStream(GetUnknown(), spUnk);
}
DWORD cbData = TCBinString<OLECHAR>::GetDecodedDataSize(bstr);
if (0xFFFFFFFF == cbData)
return E_INVALIDARG;
void* pvData = _alloca(cbData);
RETURN_FAILED(TCBinString<OLECHAR>::DecodeFromString(bstr, pvData, NULL));
TCSimpleStream stm;
stm.Init(cbData, pvData);
RETURN_FAILED(LoadFromStream(&stm));
return S_OK;
}
STDMETHODIMP CAGCEvent::get_Context(BSTR* pbstrContext)
{
XLock lock(this);
CComBSTR bstrTemp(m_bstrContext);
CLEAROUT(pbstrContext, (BSTR)bstrTemp);
bstrTemp.Detach();
return S_OK;
}
STDMETHODIMP CAGCEvent::Init()
{
return InitNew();
}
STDMETHODIMP CAGCEvent::put_ID(AGCEventID Val)
{
XLock lock(this);
m_id = Val;
return S_OK;
}
STDMETHODIMP CAGCEvent::put_Time(DATE Val)
{
XLock lock(this);
m_time = Val;
return S_OK;
}
STDMETHODIMP CAGCEvent::SetTimeNow()
{
XLock lock(this);
m_time = GetVariantDateTime();
return S_OK;
}
STDMETHODIMP CAGCEvent::AddProperty(BSTR pbstrKey, VARIANT* pvValue)
{
if (!pbstrKey)
return E_INVALIDARG;
XLock lock(this);
m_Properties[pbstrKey] = *pvValue;
return S_OK;
}
STDMETHODIMP CAGCEvent::RemoveProperty(BSTR pbstrKey, VARIANT* pvValue)
{
if (!pbstrKey)
return E_INVALIDARG;
XLock lock(this);
XPropertyIt it = m_Properties.find(*pbstrKey);
if (m_Properties.end() != it)
m_Properties.erase(it);
return S_OK;
}
STDMETHODIMP CAGCEvent::put_SubjectID(long idSubject)
{
XLock lock(this);
m_idSubject = idSubject;
return S_OK;
}
STDMETHODIMP CAGCEvent::put_SubjectName(BSTR bstrSubject)
{
XLock lock(this);
m_bstrSubjectName = bstrSubject;
return S_OK;
}
STDMETHODIMP CAGCEvent::put_Context(BSTR bstrContext)
{
XLock lock(this);
m_bstrContext = bstrContext;
return S_OK;
}