518 lines
10 KiB
C++
518 lines
10 KiB
C++
// stdafx.h : include file for standard system include files,
|
|
// or project specific include files that are used frequently,
|
|
// but are changed infrequently
|
|
|
|
#if !defined(AFX_STDAFX_H__B7E9C4D4_B8E5_48DE_A578_B75F8096FB42__INCLUDED_)
|
|
#define AFX_STDAFX_H__B7E9C4D4_B8E5_48DE_A578_B75F8096FB42__INCLUDED_
|
|
|
|
#if _MSC_VER > 1000
|
|
#pragma once
|
|
#endif // _MSC_VER > 1000
|
|
|
|
#define STRICT
|
|
#ifndef _WIN32_WINNT
|
|
#define _WIN32_WINNT 0x0400
|
|
#endif
|
|
#define _ATL_APARTMENT_THREADED
|
|
#if 0
|
|
#define _ATL_DEBUG_INTERFACES 1
|
|
#endif
|
|
|
|
#include <atlbase.h>
|
|
//You may derive a class from CComModule and use it if you want to override
|
|
//something, but do not change the name of _Module
|
|
extern CComModule _Module;
|
|
#include <atlcom.h>
|
|
#include <comdef.h>
|
|
|
|
#import "msado21.tlb" rename("EOF", "EndOfFile") raw_method_prefix("") high_method_prefix("_")
|
|
#import "sqldmo.rll" raw_method_prefix("") high_method_prefix("_") rename("GetUserName", "_GetUserName")
|
|
#import "msadox.dll" raw_method_prefix("") high_method_prefix("_")
|
|
|
|
#include <icrsint.h>
|
|
#undef END_ADO_BINDING
|
|
#define END_ADO_BINDING() {0, ADODB::adEmpty, 0, 0, 0, 0, 0, 0, 0, FALSE}};\
|
|
return rgADOBindingEntries;}
|
|
#include <oledb.h>
|
|
|
|
#include <map>
|
|
#include <list>
|
|
#include <vector>
|
|
using namespace std;
|
|
|
|
#define THIS_FILE __FILE__
|
|
|
|
#define sizeofarray(a) (sizeof(a)/sizeof((a)[0]))
|
|
|
|
//{{AFX_INSERT_LOCATION}}
|
|
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
|
|
|
|
class ILRUCache
|
|
{
|
|
public:
|
|
virtual void Lock() = 0;
|
|
virtual void Unlock() = 0;
|
|
virtual void AddToCache(IUnknown *punk) = 0;
|
|
virtual void RemoveFromCache(IUnknown *punk) = 0;
|
|
};
|
|
|
|
class DECLSPEC_UUID("321ADAAD-5334-4227-8982-585A9A3F4C02") ILRUCachedObject : public IUnknown
|
|
{
|
|
public:
|
|
virtual HRESULT put_Cache(ILRUCache *pcache) = 0;
|
|
#if 0
|
|
virtual ULONG RefCount() = 0;
|
|
#endif
|
|
};
|
|
|
|
template <class T>
|
|
class CComObjectCachedLRU : public T, public ILRUCachedObject
|
|
{
|
|
public:
|
|
CComObjectCachedLRU<T>()
|
|
{
|
|
m_pcache = NULL;
|
|
}
|
|
|
|
// Set refcount to 1 to protect destruction
|
|
~CComObjectCachedLRU()
|
|
{
|
|
m_dwRef = 1L;
|
|
FinalRelease();
|
|
#ifdef _ATL_DEBUG_INTERFACES
|
|
_Module.DeleteNonAddRefThunk(_GetRawUnknown());
|
|
#endif
|
|
}
|
|
//If InternalAddRef or InternalRelease is undefined then your class
|
|
//doesn't derive from CComObjectRoot
|
|
STDMETHOD_(ULONG, AddRef)()
|
|
{
|
|
m_csCached.Lock();
|
|
ULONG l = InternalAddRef();
|
|
if (m_dwRef == 2)
|
|
{
|
|
_Module.Lock();
|
|
if (m_pcache != NULL)
|
|
m_pcache->RemoveFromCache(GetControllingUnknown());
|
|
}
|
|
m_csCached.Unlock();
|
|
return l;
|
|
}
|
|
STDMETHOD_(ULONG, Release)()
|
|
{
|
|
m_csCached.Lock();
|
|
InternalRelease();
|
|
ULONG l = m_dwRef;
|
|
|
|
if (l > 1)
|
|
{
|
|
m_csCached.Unlock();
|
|
return l;
|
|
}
|
|
|
|
if (l == 1)
|
|
{
|
|
if (m_pcache != NULL)
|
|
{
|
|
_Module.Unlock();
|
|
// Can't reference any member variables after call to AddToCache()
|
|
// because AddToCache() might Release() this object down to
|
|
// zero refs... that would cause the object to be deleted.
|
|
ILRUCache *pcache = m_pcache;
|
|
|
|
pcache->Lock();
|
|
m_csCached.Unlock();
|
|
pcache->AddToCache(GetControllingUnknown());
|
|
pcache->Unlock();
|
|
}
|
|
else
|
|
{
|
|
m_csCached.Unlock();
|
|
}
|
|
|
|
return l;
|
|
}
|
|
|
|
if (l == 0)
|
|
{
|
|
m_csCached.Unlock();
|
|
delete this;
|
|
// Return right away so member variables aren't accidently referenced.
|
|
return l;
|
|
}
|
|
|
|
_ASSERTE(TRUE); // Should never get here.
|
|
return 0;
|
|
}
|
|
//if _InternalQueryInterface is undefined then you forgot BEGIN_COM_MAP
|
|
STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
|
|
{
|
|
HRESULT hr;
|
|
hr = _InternalQueryInterface(iid, ppvObject);
|
|
if (hr == E_NOINTERFACE)
|
|
{
|
|
if (iid == __uuidof(ILRUCachedObject))
|
|
{
|
|
*ppvObject = (void *)(ILRUCachedObject *)this;
|
|
AddRef();
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI CreateInstance(CComObjectCachedLRU<T>** pp);
|
|
|
|
// ILRUCachedObject
|
|
virtual HRESULT put_Cache(ILRUCache *pcache)
|
|
{
|
|
// NOTE: No reference count
|
|
m_pcache = pcache;
|
|
return S_OK;
|
|
}
|
|
|
|
#if 0
|
|
virtual ULONG RefCount()
|
|
{
|
|
return m_dwRef;
|
|
}
|
|
#endif
|
|
|
|
protected:
|
|
CComGlobalsThreadModel::AutoCriticalSection m_csCached;
|
|
ILRUCache *m_pcache;
|
|
};
|
|
|
|
template <class T>
|
|
HRESULT WINAPI CComObjectCachedLRU<T>::CreateInstance(CComObjectCachedLRU<T>** pp)
|
|
{
|
|
ATLASSERT(pp != NULL);
|
|
HRESULT hRes = E_OUTOFMEMORY;
|
|
CComObjectCachedLRU<T>* p = NULL;
|
|
ATLTRY(p = new CComObjectCachedLRU<T>())
|
|
if (p != NULL)
|
|
{
|
|
p->SetVoid(NULL);
|
|
p->InternalFinalConstructAddRef();
|
|
hRes = p->FinalConstruct();
|
|
p->InternalFinalConstructRelease();
|
|
if (hRes != S_OK)
|
|
{
|
|
delete p;
|
|
p = NULL;
|
|
}
|
|
}
|
|
*pp = p;
|
|
return hRes;
|
|
}
|
|
|
|
class CComObjectCacheByID : public ILRUCache
|
|
{
|
|
typedef map<long, IUnknown *> t_mapIdUnk;
|
|
typedef map<IUnknown *, long> t_mapUnkId;
|
|
typedef list<IUnknown *> t_listCache;
|
|
public:
|
|
CComObjectCacheByID(long cKeep)
|
|
{
|
|
m_cKeep = cKeep;
|
|
}
|
|
|
|
void _Lock()
|
|
{
|
|
m_csCached.Lock();
|
|
}
|
|
void _Unlock()
|
|
{
|
|
m_csCached.Unlock();
|
|
}
|
|
|
|
long Count()
|
|
{
|
|
return m_mapIdUnk.size();
|
|
}
|
|
|
|
IUnknown * Item(long i)
|
|
{
|
|
t_mapIdUnk::iterator it;
|
|
it = m_mapIdUnk.begin();
|
|
while (i--)
|
|
it++;
|
|
if (it == m_mapIdUnk.end())
|
|
return NULL;
|
|
IUnknown *punk = ((*it).second);
|
|
|
|
// If it is in the cache then return NULL
|
|
t_listCache::iterator it2;
|
|
it2 = m_listCache.begin();
|
|
while (it2 != m_listCache.end())
|
|
{
|
|
if (*it2 == punk)
|
|
return NULL;
|
|
it2++;
|
|
}
|
|
|
|
punk->AddRef();
|
|
return punk;
|
|
}
|
|
|
|
long CachedCount()
|
|
{
|
|
return m_listCache.size();
|
|
}
|
|
|
|
HRESULT Cache(long id, IUnknown *punk)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
Lock();
|
|
|
|
// Need the canonical IUnknown
|
|
punk->QueryInterface(__uuidof(IUnknown), (void **) &punk);
|
|
|
|
t_mapIdUnk::iterator it = m_mapIdUnk.find(id);
|
|
if (it != m_mapIdUnk.end())
|
|
{
|
|
// If it is already there... just return...
|
|
|
|
hr = (punk == ((*it).second)) ? S_FALSE : E_INVALIDARG;
|
|
|
|
// ... but don't forget to release the ref count
|
|
// from the above QueryInterface() call.
|
|
punk->Release();
|
|
}
|
|
else
|
|
{
|
|
CComQIPtr<ILRUCachedObject> pobj(punk);
|
|
|
|
pobj->put_Cache(this);
|
|
|
|
// Just keep one ref count (from QueryInterface() above) for both pointers.
|
|
m_mapIdUnk[id] = punk;
|
|
m_mapUnkId[punk] = id;
|
|
}
|
|
Unlock();
|
|
|
|
return hr;
|
|
}
|
|
|
|
long get_ID(IUnknown *pobj)
|
|
{
|
|
long id = 0;
|
|
Lock();
|
|
CComPtr<IUnknown> punk;
|
|
pobj->QueryInterface(__uuidof(IUnknown), (void **) &punk);
|
|
t_mapUnkId::iterator it = m_mapUnkId.find(punk);
|
|
if (it != m_mapUnkId.end())
|
|
id = (*it).second;
|
|
Unlock();
|
|
return id;
|
|
}
|
|
|
|
IUnknown * get_Unknown(long idObj)
|
|
{
|
|
CComPtr<IUnknown> punk;
|
|
Lock();
|
|
t_mapIdUnk::iterator it = m_mapIdUnk.find(idObj);
|
|
if (it != m_mapIdUnk.end())
|
|
punk = ((*it).second);
|
|
Unlock();
|
|
return punk.Detach();
|
|
}
|
|
|
|
void Uncache(IUnknown *punk)
|
|
{
|
|
Lock();
|
|
t_mapUnkId::iterator it = m_mapUnkId.find(punk);
|
|
if (it != m_mapUnkId.end())
|
|
{
|
|
long idObj = ((*it).second);
|
|
|
|
t_mapIdUnk::iterator it2 = m_mapIdUnk.find(idObj);
|
|
if (it2 != m_mapIdUnk.end())
|
|
m_mapIdUnk.erase(it2);
|
|
|
|
m_mapUnkId.erase(it);
|
|
|
|
RemoveFromCache(punk);
|
|
|
|
// Just one Release for both maps because only one ref count is held
|
|
// for all references from the cache.
|
|
punk->Release();
|
|
}
|
|
Unlock();
|
|
}
|
|
|
|
void Uncache(long idObj)
|
|
{
|
|
Lock();
|
|
t_mapIdUnk::iterator it = m_mapIdUnk.find(idObj);
|
|
if (it != m_mapIdUnk.end())
|
|
{
|
|
IUnknown *punk = ((*it).second);
|
|
|
|
t_mapUnkId::iterator it2 = m_mapUnkId.find(punk);
|
|
if (it2 != m_mapUnkId.end())
|
|
m_mapUnkId.erase(it2);
|
|
|
|
m_mapIdUnk.erase(it);
|
|
|
|
RemoveFromCache(punk);
|
|
|
|
// Just one Release for both maps because only one ref count is held
|
|
// for all references from the cache.
|
|
punk->Release();
|
|
}
|
|
Unlock();
|
|
}
|
|
|
|
void Keep(long cKeep)
|
|
{
|
|
m_cKeep = cKeep;
|
|
if (m_cKeep >= 0)
|
|
{
|
|
long cPurge = m_listCache.size() - m_cKeep;
|
|
while (cPurge-- > 0)
|
|
{
|
|
Uncache(m_listCache.back());
|
|
}
|
|
}
|
|
}
|
|
|
|
// ILRUCache interface
|
|
|
|
virtual void Lock()
|
|
{
|
|
_Lock();
|
|
}
|
|
virtual void Unlock()
|
|
{
|
|
_Unlock();
|
|
}
|
|
virtual void AddToCache(IUnknown *punk)
|
|
{
|
|
// if m_cKeep < 0 then keep infinite
|
|
// if m_cKeep == 0 then keep none
|
|
// else keep m_cKeep
|
|
if (m_cKeep == 0)
|
|
{
|
|
// Not keeping any, so just release it.
|
|
Uncache(punk);
|
|
}
|
|
else
|
|
{
|
|
m_listCache.push_front(punk);
|
|
Keep(m_cKeep);
|
|
}
|
|
}
|
|
|
|
virtual void RemoveFromCache(IUnknown *punk)
|
|
{
|
|
t_listCache::iterator it;
|
|
it = m_listCache.begin();
|
|
while (it != m_listCache.end())
|
|
{
|
|
if (*it == punk)
|
|
{
|
|
m_listCache.erase(it);
|
|
return;
|
|
}
|
|
it++;
|
|
}
|
|
}
|
|
|
|
protected:
|
|
|
|
CComGlobalsThreadModel::AutoCriticalSection m_csCached;
|
|
t_mapIdUnk m_mapIdUnk;
|
|
t_mapUnkId m_mapUnkId;
|
|
t_listCache m_listCache;
|
|
long m_cKeep;
|
|
};
|
|
|
|
#if 0 && defined(_DEBUG)
|
|
#define NewComObject(T) _NewComObject<T>(THIS_FILE, __LINE__)
|
|
template<class T>
|
|
T * _NewComObject(LPCSTR lpszFileName, int nLine)
|
|
{
|
|
T* pT = NULL;
|
|
try
|
|
{
|
|
pT = new(lpszFileName, nLine) CComObject<T>;
|
|
}
|
|
catch (CMemoryException *pe)
|
|
{
|
|
pe->Delete();
|
|
}
|
|
|
|
return pT;
|
|
}
|
|
#define NewComObjectCachedLRU(T) _NewComObjectCachedLRU<T>(THIS_FILE, __LINE__)
|
|
template<class T>
|
|
T * _NewComObjectCachedLRU(LPCSTR lpszFileName, int nLine)
|
|
{
|
|
CComObjectCachedLRU<T> *pT = NULL;
|
|
try
|
|
{
|
|
pT = new(lpszFileName, nLine) CComObjectCachedLRU<T>();
|
|
}
|
|
catch (CMemoryException *pe)
|
|
{
|
|
pe->Delete();
|
|
}
|
|
|
|
return pT;
|
|
}
|
|
#else
|
|
#define NewComObject(T) _NewComObject<T>()
|
|
template<class T>
|
|
T * _NewComObject()
|
|
{
|
|
CComObject<T> *pT = NULL;
|
|
HRESULT hr = CComObject<T>::CreateInstance(&pT);
|
|
|
|
return pT;
|
|
}
|
|
#define NewComObjectCachedLRU(T) _NewComObjectCachedLRU<T>()
|
|
template<class T>
|
|
T * _NewComObjectCachedLRU()
|
|
{
|
|
CComObjectCachedLRU<T> *pT = NULL;
|
|
HRESULT hr = CComObjectCachedLRU<T>::CreateInstance(&pT);
|
|
|
|
return pT;
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
#define new DEBUG_NEW
|
|
#endif
|
|
|
|
template<class T> class MemCmpLess // : binary_function<T, T, bool>
|
|
{
|
|
public:
|
|
bool operator()(const T & _X, const T & _Y) const
|
|
{
|
|
return (memcmp(&_X, &_Y, sizeof(T)) < 0);
|
|
}
|
|
};
|
|
|
|
class BSTRCmpLess // : binary_function<BSTR, BSTR, bool>
|
|
{
|
|
public:
|
|
bool operator()(const BSTR & _X, const BSTR _Y) const
|
|
{
|
|
return (wcscmp(_X, _Y) < 0);
|
|
}
|
|
};
|
|
|
|
#define TRACE AtlTrace
|
|
#define TIMING 0
|
|
#include "timing.h"
|
|
|
|
#include "valid.h"
|
|
|
|
#include <mstvgs.h>
|
|
#include "_GuideStore.h"
|
|
#define LIBID_GUIDESTORELib LIBID_MSTVGS //UNDONE when cpp files that ref this are fixed.
|
|
|
|
#endif // !defined(AFX_STDAFX_H__B7E9C4D4_B8E5_48DE_A578_B75F8096FB42__INCLUDED)
|