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