GME  13
CommonSmart.h
Go to the documentation of this file.
00001 
00002 #ifndef MGA_COMMONSMART_H
00003 #define MGA_COMMONSMART_H
00004 
00005 #ifndef MGA_COMMONERROR_H
00006 #include "CommonError.h"
00007 #endif
00008 
00009 #ifndef __ATLBASE_H__
00010 #include <AtlBase.h>
00011 #endif
00012 
00013 #include<string>
00014 
00015 // --------------------------- CComObjPtr
00016 
00017 // in containers we need the default "operator &",
00018 // so we don't use the built in ATL CComPtr class
00019 
00020 template<class T>
00021 class CComObjPtr
00022 {
00023 public:
00024         CComObjPtr() { p = NULL; }
00025         CComObjPtr(T *q) { if ((p = q) != NULL) q->AddRef(); }
00026         CComObjPtr(const CComObjPtr<T> &q) { if((p = q.p) != NULL) p->AddRef(); }
00027         CComObjPtr(CComObjPtr<T>&& q)
00028         {
00029                 p = q.p;
00030                 q.p = NULL;
00031         }
00032         CComObjPtr& operator=(CComObjPtr<T>&& q)
00033         {
00034                 if (p)
00035                         p->Release();
00036                 p = q.p;
00037                 q.p = NULL;
00038                 return *this;
00039         }
00040 #ifdef _DEBUG
00041         ~CComObjPtr() { if(p) p->Release(); p = NULL; }
00042 #else
00043         ~CComObjPtr() { if(p) p->Release(); }
00044 #endif
00045         void Release() { if(p) { p->Release(); p = NULL; } }
00046 
00047         operator T*() const { return p; }
00048         T& operator*() const { ASSERT( p != NULL ); return *p; }
00049         T* operator->() const { ASSERT( p != NULL ); return p; }
00050         T* operator=(T *q) { if(q) q->AddRef(); if(p) p->Release(); p = q; return q; }
00051         T* operator=(const CComObjPtr<T> &q) { return operator=(q.p); }
00052         bool operator==(T *q) const { return p == q; }
00053         bool operator!=(T *q) const { return p != q; }
00054 
00055         T* Detach() { T* r = p; p = NULL; return r; }
00056         void Attach(T* q) { if(p) p->Release(); p = q; }
00057 
00058         template<class Q>
00059         HRESULT QueryInterface(CComObjPtr<Q> &q) const 
00060         {
00061                 ASSERT( p != NULL && q == NULL );
00062                 return p->QueryInterface(__uuidof(Q), (void**)&q.p);
00063         }
00064 
00065         HRESULT CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
00066         {
00067                 ASSERT( p == NULL );
00068                 return ::CoCreateInstance(rclsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);
00069         }
00070 
00071         HRESULT CoCreateInstance(LPCOLESTR szProgID, LPUNKNOWN pUnkOuter = NULL, DWORD dwClsContext = CLSCTX_ALL)
00072         {
00073                 CLSID clsid;
00074                 HRESULT hr = CLSIDFromProgID(szProgID, &clsid);
00075                 ASSERT(p == NULL);
00076                 if (SUCCEEDED(hr))
00077                         hr = ::CoCreateInstance(clsid, pUnkOuter, dwClsContext, __uuidof(T), (void**)&p);
00078                 return hr;
00079         }
00080 
00081 public:
00082         T *p;
00083 };
00084 
00085 // use these inline functions to pass CComObjPtr arguments to COM functions
00086 // like in role->get_Kind(PutOut(kind))
00087 
00088 template<class T>
00089 T **PutOut(CComObjPtr<T> &p) { ASSERT( p == NULL ); return &p.p; }
00090 
00091 template<class T>
00092 T **PutInOut(CComObjPtr<T> &p) { return &p.p; }
00093 
00094 // use these inline functions to transfer ownership to another COM pointer
00095 
00096 template<class T, class Q>
00097 void MoveTo(CComObjPtr<T> &p, Q **q)
00098 { ASSERT( q != NULL ); if(*q) (*q)->Release(); *q = p.p; p.p = NULL; }
00099 
00100 template<class T, class Q>
00101 void MoveTo(CComObjPtr<T> &p, CComObjPtr<Q> &q) { q.Attach(p.p); p.p = NULL; }
00102 
00103 // use these inline functions to copy COM pointers
00104 
00105 template<class T, class Q>
00106 void CopyTo(T *p, Q **q)
00107 { ASSERT( q != NULL ); if(p) p->AddRef(); if(*q) (*q)->Release(); *q = p; }
00108 
00109 template<class T, class Q>
00110 void CopyTo(const CComObjPtr<T> &p, Q **q) 
00111 { ASSERT( q != NULL ); if(p) p->AddRef(); if(*q) (*q)->Release(); *q = p; }
00112 
00113 // global QueryInterface
00114 
00115 template<class T>
00116 inline HRESULT QueryInterface(IUnknown *p, T **q)
00117 { ASSERT( p != NULL ); return p->QueryInterface(__uuidof(T), (void**)q); }
00118 
00119 template<class T>
00120 inline HRESULT QueryInterface(IUnknown *p, CComObjPtr<T> &q)
00121 { ASSERT( p != NULL ); return p->QueryInterface(__uuidof(T), (void**)PutOut(q)); }
00122 
00123 // note: T should not be derived from CComObject
00124 template<class T>
00125 inline void CreateComObject(CComObjPtr<T> &p)
00126 {
00127         CComObject<T> *q = NULL;
00128         COMTHROW( CComObject<T>::CreateInstance(&q) );
00129         ASSERT( q != NULL );
00130 
00131         p = q;
00132 }
00133 
00134 // note: T should not be derived from CComPartObject
00135 template<class T>
00136 inline void CreateComPartObject(LPUNKNOWN pUnkOuter, CComObjPtr<T> &p)
00137 {
00138         CComPartObject<T> *q = NULL;
00139         COMTHROW( CComPartObject<T>::CreateInstance(pUnkOuter, &q) );
00140         ASSERT( q != NULL );
00141 
00142         p = q;
00143 }
00144 
00145 // --------------------------- CComPtr
00146 
00147 // note: T should not be derived from CComObject
00148 template<class T>
00149 inline void CreateComObject(CComPtr<T> &p)
00150 {
00151         CComObject<T> *q = NULL;
00152         COMTHROW( CComObject<T>::CreateInstance(&q) );
00153         ASSERT( q != NULL );
00154 
00155         q->AddRef();
00156         p.Attach(q);
00157 }
00158 
00159 // --------------------------- CComBstrObj
00160 
00161 class CComBstrObj
00162 {
00163 public:
00164         CComBstrObj() : p(NULL) { }
00165         explicit CComBstrObj(LPCOLESTR q) { p = SysAllocString(q); }
00166         CComBstrObj(const CComBstrObj &q) : p(NULL) { if(q.p) { p = SysAllocStringLen(q, q.Length()); } }
00167         CComBstrObj(CComBstrObj &&q) { p = q.p; q.p = NULL; }
00168         ~CComBstrObj() { if(p) SysFreeString(p); }
00169 
00170         const CComBstrObj &operator=(const CComBstrObj &q) { if(p) SysFreeString(p);
00171                 p = SysAllocStringLen(q, q.Length()); return *this; }
00172         CComBstrObj& operator=(CComBstrObj&& q) {
00173                 if (p) SysFreeString(p);
00174                 p = q.p;
00175                 q.p = NULL;
00176                 return *this;
00177         }
00178         operator BSTR() const { return p; }
00179         unsigned int Length() const { return p ? SysStringLen(p) : 0; }
00180         void Empty() { if( p ) { SysFreeString(p); p = NULL; } }
00181 
00182         int Compare(BSTR q) const;
00183         bool operator==(BSTR q) const { return Compare(q) == 0; }
00184         bool operator!=(BSTR q) const { return Compare(q) != 0; }
00185         bool operator<(BSTR q) const { return Compare(q) < 0; }
00186         bool operator>(BSTR q) const { return Compare(q) > 0; }
00187         bool operator<=(BSTR q) const { return Compare(q) <= 0; }
00188         bool operator>=(BSTR q) const { return Compare(q) >= 0; }
00189 
00190         BSTR Detach() { BSTR q = p; p = NULL; return q; }
00191         void Attach(BSTR q) { if(p) SysFreeString(p); p = q; }
00192 
00193 public:
00194         BSTR p;
00195 };
00196 
00197 inline BSTR *PutOut(CComBstrObj &s) { ASSERT( s.p == NULL ); return &s.p; }
00198 inline BSTR *PutInOut(CComBstrObj &s) { return &s.p; }
00199 
00200 // we use "BSTR" for [in], and "BSTR *" for [in, out]
00201 // we use "const CComBstrObj &" for [in] and "CComBstrObj &" for [in, out]
00202 
00203 inline void CopyTo(BSTR p, BSTR *q)
00204 {
00205         ASSERT( q != NULL );
00206 
00207         if (*q)
00208                 SysFreeString(*q);
00209         *q = SysAllocStringLen(p, SysStringLen(p));
00210         if (*q == NULL && p != NULL)
00211                 COMTHROW(E_OUTOFMEMORY);
00212 }
00213 
00214 inline void CopyTo(const CComBstrObj &b, BSTR *q) { CopyTo(b.p, q); }
00215 inline void CopyTo(BSTR p, CComBstrObj &b) { CopyTo(p, &b.p); }
00216 
00217 inline void MoveTo(BSTR *p, BSTR *q)
00218 {
00219         ASSERT( p != NULL );
00220         ASSERT( q != NULL );
00221 
00222         if(*q) SysFreeString(*q);
00223         (*q) = (*p); (*p) = NULL;
00224 }
00225 
00226 inline void MoveTo(CComBstrObj &b, BSTR *q) { MoveTo(&b.p, q); }
00227 inline void MoveTo(BSTR *p, CComBstrObj &b) { MoveTo(p, &b.p); }
00228 
00229 // these THROW exceptions
00230 
00231 void CopyTo(const char *p, int len, BSTR *b, UINT codepage=CP_ACP);
00232 
00233 // if olelen is -1, then OLECHAR is NULL terminated and the charlen includes this NULL
00234 int GetCharLength(const OLECHAR *p, int olelen, UINT codepage=CP_ACP);
00235 
00236 void CopyTo(const OLECHAR *p, int olelen, char *s, int charlen, UINT codepage=CP_ACP);
00237 
00238 void CopyTo(const OLECHAR *p, GUID &guid);
00239 void CopyTo(const GUID &guid, BSTR *p);
00240 
00241 // ------- inlines
00242 
00243 inline void CopyTo(const char *p, int len, CComBstrObj &b) { CopyTo(p, len, &b.p); }
00244 inline int GetCharLength(BSTR p) { return GetCharLength(p, SysStringLen(p)); }
00245 inline void CopyTo(BSTR p, char *s, int charlen, UINT codepage=CP_ACP) { CopyTo(p, SysStringLen(p), s, charlen, codepage); }
00246 inline void CopyTo(const GUID &guid, CComBstrObj &b) { CopyTo(guid, &b.p); }
00247 
00248 // --------------------------- CComBSTR
00249 
00250 inline void CopyTo(const CComBSTR &b, BSTR *q) { CopyTo(b.m_str, q); }
00251 inline void CopyTo(BSTR p, CComBSTR &b) { CopyTo(p, &b.m_str); }
00252 
00253 inline void MoveTo(CComBSTR &b, BSTR *q) { MoveTo(&b.m_str, q); }
00254 inline void MoveTo(BSTR *p, CComBSTR &b) { MoveTo(p, &b.m_str); }
00255 
00256 // --------------------------- CComSafeArray
00257 
00258 class CComSafeArray
00259 {
00260 public:
00261         CComSafeArray() { p = NULL; }
00262         ~CComSafeArray() { if( p ) SafeArrayDestroy(p); }
00263         operator SAFEARRAY*() { return p; }
00264 
00265 public:
00266         SAFEARRAY *p;
00267 };
00268 
00269 inline SAFEARRAY **PutOut(CComSafeArray &a) { ASSERT( a.p == NULL ); return &a.p; }
00270 inline SAFEARRAY **PutInOut(CComSafeArray &a) { return &a.p; }
00271 
00272 // we use "SAFEARRAY *" for [in], "SAFEARRAY **" for [out], and "SAFEARRAY *" for [in, out]
00273 // we use "const CComSafeArray &" for [in] and "CComSafeArray &" for [in, out]
00274 
00275 // these THROW exceptions
00276 
00277 void CopyTo(const CComBstrObj *start, const CComBstrObj *end, SAFEARRAY **p);
00278 void CopyTo(const unsigned char *start, const unsigned char *end, SAFEARRAY **p);
00279 void CopyTo(const long *start, const long *end, SAFEARRAY **p);
00280 void CopyTo(const GUID *start, const GUID *end, SAFEARRAY **p);
00281 
00282 void MoveTo(CComBstrObj *start, CComBstrObj *end, SAFEARRAY **p);
00283 
00284 long GetArrayLength(SAFEARRAY *p);
00285 
00286 // not safe for multiple access
00287 void GetArrayStart(SAFEARRAY *p, CComBstrObj *&start);
00288 void GetArrayStart(SAFEARRAY *p, unsigned char *&start);
00289 void GetArrayStart(SAFEARRAY *p, long *&start);
00290 void GetArrayStart(SAFEARRAY *p, GUID *&start);
00291 
00292 void CopyTo(SAFEARRAY *p, CComBstrObj *start, CComBstrObj *end);
00293 void CopyTo(SAFEARRAY *p, unsigned char *start, unsigned char *end);
00294 void CopyTo(SAFEARRAY *p, long *start, long *end);
00295 void CopyTo(SAFEARRAY *p, GUID *start, GUID *end);
00296 
00297 void MoveTo(SAFEARRAY *p, CComBstrObj *start, CComBstrObj *end);
00298 
00299 // --------------------------- CComVariant
00300 
00301 inline VARIANT *PutOut(CComVariant &v) { ASSERT( v.vt == VT_EMPTY ); return &v; }
00302 inline VARIANT *PutInOut(CComVariant &v) { return &v; }
00303 
00304 // we use "const VARIANT &" for [in] and "VARIANT *" for [in, out]
00305 // we use "const CComVariant &" for [in] and "CComVariant &" for [in, out]
00306 
00307 // these THROW exceptions
00308 
00309 // ------- scalar
00310 
00311 void CopyTo(unsigned char a, VARIANT *v);
00312 void CopyTo(short a, VARIANT *v);
00313 void CopyTo(long a, VARIANT *v);
00314 void CopyTo(double a, VARIANT *v);
00315 void CopyTo(BSTR a, VARIANT *v);
00316 void CopyTo(IDispatch *p, VARIANT *v);
00317 
00318 template<class T>
00319 void CopyTo(const CComObjPtr<T> &p, VARIANT *v) { CopyTo(p.p, v); }
00320 
00321 void CopyTo(const VARIANT &v, unsigned char &a);
00322 void CopyTo(const VARIANT &v, short &a);
00323 void CopyTo(const VARIANT &v, long &a);
00324 void CopyTo(const VARIANT &v, double &a);
00325 void CopyTo(const VARIANT &v, BSTR *a);
00326 
00327 void MoveTo(BSTR b, VARIANT *v);
00328 void MoveTo(const VARIANT &v, BSTR *b);
00329 
00330 void MoveTo(IDispatch **p, VARIANT *v);
00331 
00332 template<class T>
00333 void MoveTo(const CComObjPtr<T> &p, VARIANT *v) { MoveTo(p.p, v); }
00334 
00335 inline void MoveTo(VARIANT *p, VARIANT *q)
00336 {
00337         ASSERT( p != NULL );
00338         ASSERT( q != NULL );
00339 
00340         (*q) = (*p);
00341         p->vt = VT_EMPTY;
00342 }
00343 
00344 // ------- string conversion
00345 
00346 void CopyTo(const char *p, int len, VARIANT *v);
00347 
00348 // we cannot use "const VARIANT &", we might have to change
00349 // the type of the variant from VT_DISPATCH to VT_BSTR
00350 int GetCharLength(VARIANT &v);
00351 
00352 void CopyTo(const VARIANT &v, char *s, int charlen);
00353 
00354 // ------- array conversion
00355 
00356 void CopyTo(const CComBstrObj *start, const CComBstrObj *end, VARIANT *v);
00357 void CopyTo(const unsigned char *start, const unsigned char *end, VARIANT *v);
00358 void CopyTo(const long *start, const long *end, VARIANT *v);
00359 
00360 void MoveTo(CComBstrObj *start, CComBstrObj *end, VARIANT *v);
00361 
00362 long GetArrayLength(const VARIANT &v);
00363 
00364 // not safe for multiple access
00365 void GetArrayStart(const VARIANT &v, CComBstrObj *&start);
00366 void GetArrayStart(const VARIANT &v, unsigned char *&start);
00367 void GetArrayStart(const VARIANT &v, long *&start);
00368 
00369 void CopyTo(const VARIANT &v, CComBstrObj *start, CComBstrObj *end);
00370 void CopyTo(const VARIANT &v, unsigned char *start, unsigned char *end);
00371 void CopyTo(const VARIANT &v, long *start, long *end);
00372 
00373 void MoveTo(VARIANT *v, CComBstrObj *start, CComBstrObj *end);
00374 
00375 void CopyTo(const VARIANT &v, GUID &guid);
00376 
00377 // ------- inlines
00378 
00379 inline void CopyTo(const unsigned char *start, int len, VARIANT *p) { CopyTo(start, start + len, p); }
00380 inline void CopyTo(const long *start, int len, VARIANT *p) { CopyTo(start, start + len, p); }
00381 
00382 inline void CopyTo(const GUID &guid, VARIANT *v) { CopyTo((unsigned char*)&guid, sizeof(GUID), v); }
00383 inline void CopyTo(const OBJECTID &objid, VARIANT *v) { CopyTo((unsigned char*)&objid, sizeof(OBJECTID), v); }
00384 
00385 inline void CopyTo(const VARIANT &v, CComBstrObj &b) { CopyTo(v, &b.p); }
00386 
00387 template<class T>
00388 void CopyTo(T t, CComVariant &v) { CopyTo(t, &v); }
00389 
00390 template<class T, class S>
00391 void CopyTo(T t, S s, CComVariant &v) { CopyTo(t, s, &v); }
00392 
00393 // --------------------------- COM Helper functions
00394 
00395 // these THROW exceptions
00396 
00397 bool IsEqualObject(IUnknown *p, IUnknown *q);
00398 
00399 // --------------------------- PutInVariant
00400 
00401 class PutInVariant
00402 {
00403 public:
00404         template<class T>
00405         PutInVariant(T t) { CopyTo(t, v); }
00406 
00407         template<> PutInVariant(int a) : v(a) { }
00408         template<> PutInVariant(short a) : v(a) { }
00409         template<> PutInVariant(unsigned char a) : v(a) { }
00410         template<> PutInVariant(IDispatch *p) : v(p) { }
00411         template<> PutInVariant(BSTR p) : v(p) { }
00412 
00413         operator VARIANT () { return v; }
00414         operator CComVariant &() { return v; }
00415 
00416         CComVariant v;
00417 };
00418 
00419 // --------------------------- PutInBstr
00420 
00421 class PutInBstr
00422 {
00423 public:
00424         template<class T>
00425         PutInBstr(const T& t) { CopyTo(t, b); }
00426 
00427         template<> PutInBstr(const BSTR& a) : b(a) { }
00428 
00429         template<> PutInBstr(const std::wstring& t) {
00430                 b.p = SysAllocStringLen(t.c_str(), t.length());
00431         }
00432 
00433         operator BSTR () { return b; }
00434 
00435         CComBstrObj b;
00436 };
00437 
00438 // --------------------------- CComPartObject
00439 
00440 template <class BASE>
00441 class CComPartObject : public BASE
00442 {
00443 public:
00444         typedef BASE _BaseClass;
00445 
00446         CComPartObject(void* pv)
00447         {
00448                 ATLASSERT( pv != NULL );
00449                 m_pOuterUnknown = (IUnknown*)pv;
00450         }
00451 
00452         ~CComPartObject()
00453         {
00454                 FinalRelease();
00455 #ifdef _ATL_DEBUG_INTERFACES
00456                 _Module.DeleteNonAddRefThunk(_GetRawUnknown());
00457 #endif
00458         }
00459 
00460         STDMETHOD_(ULONG, AddRef)() { return OuterAddRef(); }
00461         STDMETHOD_(ULONG, Release)() { return OuterRelease(); }
00462 
00463         STDMETHOD(QueryInterface)(REFIID iid, void ** ppvObject)
00464                 { return _InternalQueryInterface(iid, ppvObject); }
00465 
00466         template <class Q>
00467         HRESULT STDMETHODCALLTYPE QueryInterface(Q** pp)
00468         {
00469                 return QueryInterface(__uuidof(Q), (void**)pp);
00470         }
00471 
00472         IUnknown* GetControllingUnknown()
00473         {
00474 #ifdef _ATL_DEBUG_INTERFACES
00475                 IUnknown* p;
00476                 _Module.AddNonAddRefThunk(m_pOuterUnknown, _T("CComContainedObject"), &p);
00477                 return p;
00478 #else
00479                 return m_pOuterUnknown;
00480 #endif
00481         }
00482 
00483         static HRESULT WINAPI CreateInstance(LPUNKNOWN pUnkOuter, CComPartObject<BASE>** pp)
00484         {
00485                 ATLASSERT(pp != NULL);
00486                 HRESULT hRes = E_OUTOFMEMORY;
00487                 CComPartObject<BASE>* p = NULL;
00488                 ATLTRY(p = new CComPartObject<BASE>(pUnkOuter))
00489                 if (p != NULL)
00490                 {
00491                         p->SetVoid(NULL);
00492                         hRes = p->FinalConstruct();
00493                         if (hRes != S_OK)
00494                         {
00495                                 delete p;
00496                                 p = NULL;
00497                         }
00498                 }
00499                 *pp = p;
00500                 return hRes;
00501         }
00502 };
00503 
00504 #endif//MGA_COMMONSMART_H