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