GME  13
ComHelp.h
Go to the documentation of this file.
00001 
00002 #ifndef __COMHELP_H
00003 #define __COMHELP_H
00004 
00005 #ifndef __AFXTEMPL_H__
00006 #include <afxtempl.h>
00007 #endif
00008 
00009 #ifndef __unknwn_h__
00010 #include <unknwn.h>
00011 #endif
00012 
00013 
00014 // --------------------------- MACROS
00015 
00016 //inline void COMVERIFY(HRESULT hr)
00017 //{
00018 //      VERIFY(SUCCEEDED(hr));
00019 //}
00020 
00021 inline void COMASSERT(HRESULT hr)
00022 {
00023         ASSERT(SUCCEEDED(hr));
00024 }
00025 
00026 // --------------------------- CBstr
00027 
00028 class CBstr
00029 {
00030 public:
00031         CBstr() : s(NULL) { }
00032         CBstr(const CString &str) : s(str.AllocSysString()) { }
00033         ~CBstr() { Free(); }
00034 
00035         void operator = (const CString &str) { Free(); s = str.AllocSysString(); }
00036 
00037         void Free() { SysFreeString(s); }
00038 
00039         BSTR Send() { return s; }
00040         operator BSTR* () { return &s; }
00041         operator CString () { return s; }
00042 
00043 private:
00044         BSTR s;
00045 };
00046 
00047 class CBstrRef
00048 {
00049 public:
00050         CBstrRef(BSTR str) : s(str) { }
00051 
00052         void operator = (const CString& str) { Free(); s = str.AllocSysString(); }
00053 
00054         void Free() { SysFreeString(s); }
00055 
00056         operator BSTR () { return s; }
00057         operator CString () { return s; }
00058 
00059 private:
00060         BSTR &s;
00061 };
00062 
00063 class CBstrIn
00064 {
00065 public:
00066         CBstrIn(const CString &str) : s(str.AllocSysString()) { }
00067         ~CBstrIn() { SysFreeString(s); }
00068 
00069         operator BSTR () { return s; }
00070 
00071 private:
00072         BSTR s;
00073 };
00074 
00075 // --------------------------- CIUnknownPtrList
00076 
00077 class CIUnknownPtrList : public CList<IUnknown*, IUnknown*>
00078 {
00079 public:
00080         CIUnknownPtrList() { };
00081 
00082         void Load(SAFEARRAY** ppsa);
00083         void Copy(SAFEARRAY* ppsa);
00084         SAFEARRAY* Store();
00085 
00086         void AddRefAll();
00087         void ReleaseAll();
00088 };
00089 
00090 // --------------------------- CInterfacePtrList
00091 // ex. CInterfacePtrList<IMgaModel*> icategories(psa);
00092 // ex. CInterfacePtrList<IMgaModel*> icategories(categories);
00093 
00094 template<class TYPE>
00095 class CInterfacePtrList : public CIUnknownPtrList
00096 {
00097 public:
00098         // Construction
00099         CInterfacePtrList() : CIUnknownPtrList() { };
00100 
00101         template<class SOURCE>
00102         void AddInterfaces(SOURCE &source)
00103         {
00104                 POSITION pos = source.GetHeadPosition();
00105                 while(pos)
00106                 {
00107                         TYPE i = source.GetNext(pos)->GetInterface();
00108                         ASSERT(i);
00109                         AddTail(i);
00110                 }
00111         }
00112 
00113         // peek at head or tail
00114         TYPE& GetHead()
00115                 { return (TYPE&)CIUnknownPtrList::GetHead(); }
00116         TYPE GetHead() const
00117                 { return (TYPE)CIUnknownPtrList::GetHead(); }
00118         TYPE& GetTail()
00119                 { return (TYPE&)CIUnknownPtrList::GetTail(); }
00120         TYPE GetTail() const
00121                 { return (TYPE)CIUnknownPtrList::GetTail(); }
00122 
00123         // get head or tail (and remove it) - don't call on empty list!
00124         TYPE RemoveHead()
00125                 { return (TYPE)CIUnknownPtrList::RemoveHead(); }
00126         TYPE RemoveTail()
00127                 { return (TYPE)CIUnknownPtrList::RemoveTail(); }
00128 
00129         // add before head or after tail
00130         POSITION AddHead(TYPE newElement)
00131                 { return CIUnknownPtrList::AddHead(newElement); }
00132         POSITION AddTail(TYPE newElement)
00133                 { return CIUnknownPtrList::AddTail(newElement); }
00134 
00135         // add another list of elements before head or after tail
00136         void AddHead(CInterfacePtrList<TYPE>* pNewList)
00137                 { CIUnknownPtrList::AddHead(pNewList); }
00138         void AddTail(CInterfacePtrList<TYPE>* pNewList)
00139                 { CIUnknownPtrList::AddTail(pNewList); }
00140 
00141         // iteration
00142         TYPE& GetNext(POSITION& rPosition)
00143                 { return (TYPE&)CIUnknownPtrList::GetNext(rPosition); }
00144         TYPE GetNext(POSITION& rPosition) const
00145                 { return (TYPE)CIUnknownPtrList::GetNext(rPosition); }
00146         TYPE& GetPrev(POSITION& rPosition)
00147                 { return (TYPE&)CIUnknownPtrList::GetPrev(rPosition); }
00148         TYPE GetPrev(POSITION& rPosition) const
00149                 { return (TYPE)CIUnknownPtrList::GetPrev(rPosition); }
00150 
00151         // getting/modifying an element at a given position
00152         TYPE& GetAt(POSITION position)
00153                 { return (TYPE&)CIUnknownPtrList::GetAt(position); }
00154         TYPE GetAt(POSITION position) const
00155                 { return (TYPE)CIUnknownPtrList::GetAt(position); }
00156         void SetAt(POSITION pos, TYPE newElement)
00157                 { CIUnknownPtrList::SetAt(pos, newElement); }
00158 
00159 };
00160 
00161 // --------------------------- SafeArray
00162 // ex. CreateSafeArray<IMgaCategory*>(categories);
00163 
00164 template<class TYPE, class SOURCE>
00165 SAFEARRAY* CreateInterfaceSafeArray(SOURCE &source)
00166 {
00167         SAFEARRAY *psa;
00168 
00169         psa = SafeArrayCreateVector(VT_UNKNOWN, 0, source.GetCount());
00170         ASSERT(psa);
00171 
00172         IUnknown* *p;
00173         COMVERIFY(SafeArrayAccessData(psa,(void**)&p));
00174 
00175         POSITION pos = source.GetHeadPosition();
00176         while(pos)
00177         {
00178                 TYPE i = source.GetNext(pos)->GetInterface();
00179                 ASSERT(i);
00180                 i->AddRef();
00181                 *(p++) = i;
00182         }
00183 
00184         COMVERIFY(SafeArrayUnaccessData(psa));
00185 
00186         return psa;
00187 }
00188 
00189 HRESULT SafeArrayDestroyNoRelease(SAFEARRAY* psa);
00190 void LoadBstrSafeArray(CStringList& dest, SAFEARRAY** ppsa);
00191 SAFEARRAY* StoreBstrSafeArray(CStringList& source);
00192 
00193 typedef CList<float, float&> FloatList;
00194 void LoadFloatSafeArray(FloatList& dest, SAFEARRAY** ppsa);
00195 SAFEARRAY* StoreFloatSafeArray(FloatList& source);
00196 
00197 // --------------------------- CComPtrList
00198 //
00199 // This is the preferred way to store interface pointers.
00200 // Use the MoveTo functions below to transfer lists of
00201 // interface pointers between CComPtrLists and SAFEARRAYs
00202 //
00203 
00204 #include <atlbase.h>
00205 
00206 template<class INTERFACE> 
00207 class CComPtrList : public CList< CAdapt< CComPtr<INTERFACE> >, CAdapt< CComPtr<INTERFACE> >& >
00208 {
00209 public:
00210         typedef CComPtr<INTERFACE> COMPTR;
00211         typedef CAdapt<COMPTR> CADAPT;
00212         typedef CList<CADAPT, CADAPT&> BASE;
00213         typedef CComPtrList<INTERFACE> SELF;
00214 
00215         static CADAPT &CastPtr(INTERFACE *&ptr) { return *(CADAPT*)&ptr; }
00216 
00217         // peek at head or tail
00218         COMPTR &GetHead() { return BASE::GetHead(); }
00219         COMPTR GetHead() const { return BASE::GetHead(); }
00220         COMPTR &GetTail() { return BASE::GetTail(); }
00221         COMPTR GetTail() const { return BASE::GetTail(); }
00222 
00223         // get head or tail (and remove it) - don't call on empty list!
00224         COMPTR RemoveHead() { return BASE::RemoveHead(); }
00225         COMPTR RemoveTail() { return BASE::RemoveTail(); }
00226 
00227         // add before head or after tail
00228         POSITION AddHead(INTERFACE *newElement) { return BASE::AddHead(CastPtr(newElement)); }
00229         POSITION AddTail(INTERFACE *newElement) { return BASE::AddTail(CastPtr(newElement)); }
00230 
00231         // iteration
00232         COMPTR &GetNext(POSITION& rPosition) { return BASE::GetNext(rPosition); }
00233         COMPTR GetNext(POSITION& rPosition) const { return BASE::GetNext(rPosition); }
00234         COMPTR &GetPrev(POSITION& rPosition) { return BASE::GetPrev(rPosition); }
00235         COMPTR GetPrev(POSITION& rPosition) const { return BASE::GetPrev(rPosition); }
00236 
00237         // getting/modifying an element at a given position
00238         COMPTR &GetAt(POSITION position) { return BASE::GetAt(position); }
00239         COMPTR GetAt(POSITION position) const { return BASE::GetAt(position); }
00240         void SetAt(POSITION pos, INTERFACE *newElement) { BASE::SetAt(pos, CastPtr(newElement)); }
00241 
00242         // inserting before or after a given position
00243         POSITION InsertBefore(POSITION position, INTERFACE *newElement)
00244                 { return BASE::InsertBefore(position, CastPtr(newElement)); }
00245         POSITION InsertAfter(POSITION position, INTERFACE *newElement)
00246                 { return BASE::InsertAfter(position, CastPtr(newElement)); }
00247 
00248         // helper functions (note: O(n) speed)
00249         POSITION Find(INTERFACE *searchValue, POSITION startAfter = NULL) const
00250                 { return BASE::Find(CastPtr(searchValue), startAfter); }
00251                 // defaults to starting at the HEAD, return NULL if not found
00252 };
00253 
00254 // --------------------------- CComPtrArray
00255 
00256 template<class INTERFACE> 
00257 class CComPtrArray : public CArray< CAdapt< CComPtr<INTERFACE> >, CComPtr<INTERFACE>& >
00258 {
00259 public:
00260         typedef CComPtr<INTERFACE> COMPTR;
00261         typedef CAdapt<COMPTR> CADAPT;
00262         typedef CArray<CADAPT, COMPTR&> BASE;
00263         typedef CComPtrArray<INTERFACE> SELF;
00264 
00265         static COMPTR &CastPtr(INTERFACE *&ptr) { return *(COMPTR*)&ptr; }
00266 
00267         // Accessing elements
00268         COMPTR GetAt(int nIndex) const { return BASE::GetAt(nIndex); }
00269         COMPTR& ElementAt(int nIndex) { return BASE::ElementAt(nIndex); }
00270 
00271         // Direct Access to the element data (may return NULL)
00272         const COMPTR* GetData() const { return BASE::GetData(); }
00273         COMPTR* GetData() { return BASE::GetData(); }
00274 
00275         // Potentially growing the array
00276         void SetAtGrow(int nIndex, INTERFACE *newElement)
00277                 { BASE::SetAtGrow(nIndex, CastPtr(newElement)); }
00278         int Add(INTERFACE *newElement) { return BASE::Add(CastPtr(newElement)); }
00279 
00280         // overloaded operator helpers
00281         COMPTR operator[](int nIndex) const { return BASE::operator[](nIndex); }
00282         COMPTR &operator[](int nIndex) { return BASE::operator[](nIndex); }
00283 
00284         // Operations that move elements around
00285         void InsertAt(int nIndex, INTERFACE *newElement, int nCount = 1)
00286                 { BASE::InsertAt(nIndex, CastPtr(newElement), nCount); }
00287 };
00288 
00289 // --------------------------- CopyTo & MoveTo
00290 
00291 template<class INTERFACE>
00292 void CopyTo(SAFEARRAY* psa, CComPtrList<INTERFACE> &container)
00293 {
00294         ASSERT(psa);
00295         container.RemoveAll();
00296 
00297         INTERFACE* *p;
00298         COMVERIFY(SafeArrayAccessData(psa, (void**)&p));
00299         ASSERT(p);
00300 
00301         long bound;
00302 
00303         ASSERT( (psa)->fFeatures | FADF_UNKNOWN );
00304         ASSERT( (psa)->cbElements == sizeof(IUnknown*) );
00305         ASSERT( SafeArrayGetDim(psa) == 1 );
00306         COMASSERT(SafeArrayGetLBound(psa, 1, &bound));
00307         ASSERT( bound == 0 );
00308 
00309         COMVERIFY(SafeArrayGetUBound(psa, 1, &bound));
00310         ASSERT( bound >= -1 );
00311 
00312         while( bound-- >= 0 )
00313                 container.AddTail(*(p++));
00314 
00315         COMVERIFY(SafeArrayUnaccessData(psa));
00316 }
00317 
00318 template<class INTERFACE>
00319 void MoveTo(SAFEARRAY** ppsa, CComPtrList<INTERFACE> &container)
00320 {
00321         ASSERT(ppsa && *ppsa);
00322 
00323         container.RemoveAll();
00324 
00325         INTERFACE* *p;
00326         COMVERIFY(SafeArrayAccessData(*ppsa, (void**)&p));
00327         ASSERT(p);
00328 
00329         long bound;
00330 
00331         ASSERT( (*ppsa)->fFeatures | FADF_UNKNOWN );
00332         ASSERT( (*ppsa)->cbElements == sizeof(IUnknown*) );
00333         ASSERT( SafeArrayGetDim(*ppsa) == 1 );
00334         COMASSERT(SafeArrayGetLBound(*ppsa, 1, &bound));
00335         ASSERT( bound == 0 );
00336 
00337         COMVERIFY(SafeArrayGetUBound(*ppsa, 1, &bound));
00338         ASSERT( bound >= -1 );
00339 
00340         while( bound-- >= 0 )
00341         {
00342                 container.AddTail(NULL);
00343                 container.GetTail().p = *(p++);
00344         }
00345 
00346         COMVERIFY(SafeArrayUnaccessData(*ppsa));
00347 
00348         COMVERIFY(SafeArrayDestroyNoRelease(*ppsa));
00349         *ppsa = NULL;
00350 }
00351 
00352 template<class INTERFACE>
00353 void CopyTo(CComPtrList<INTERFACE> &container, SAFEARRAY **ppsa)
00354 {
00355         ASSERT( *ppsa == NULL );
00356 
00357         *ppsa = SafeArrayCreateVector(VT_UNKNOWN, 0, container.GetCount());
00358         ASSERT(*ppsa);
00359 
00360         IUnknown* *p;
00361         COMVERIFY(SafeArrayAccessData(*ppsa,(void**)&p));
00362 
00363         POSITION pos = container.GetHeadPosition();
00364         while(pos)
00365         {
00366                 INTERFACE *a = container.GetNext(pos).p;
00367                 a->AddRef();
00368                 *(p++) = a;
00369         }
00370 
00371         COMVERIFY(SafeArrayUnaccessData(*ppsa));
00372 }
00373 
00374 template<class INTERFACE>
00375 void MoveTo(CComPtrList<INTERFACE> &container, SAFEARRAY **ppsa)
00376 {
00377         ASSERT( *ppsa == NULL );
00378 
00379         *ppsa = SafeArrayCreateVector(VT_UNKNOWN, 0, container.GetCount());
00380         ASSERT(*ppsa);
00381 
00382         IUnknown* *p;
00383         COMVERIFY(SafeArrayAccessData(*ppsa,(void**)&p));
00384 
00385         POSITION pos = container.GetHeadPosition();
00386         while(pos)
00387         {
00388                 CComPtr<INTERFACE> &a = container.GetNext(pos);
00389                 *(p++) = a;
00390                 a.p = NULL;
00391         }
00392         
00393         COMVERIFY(SafeArrayUnaccessData(*ppsa));
00394 
00395         container.RemoveAll();
00396 }
00397 
00398 #endif//__COMHELP_H