GME
13
|
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