ptr.h

Go to the documentation of this file.
00001 00004 /* 00005 * Copyright © 2000-2002 Sofus Mortensen, Michael Geddes 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00021 00132 00133 #ifndef COMET_PTR_H 00134 #define COMET_PTR_H 00135 00136 #include <comet/config.h> 00137 00138 #include <algorithm> 00139 00140 #include <comet/error_fwd.h> 00141 #include <comet/typelist.h> 00142 #include <comet/interface.h> 00143 #include <comet/common.h> 00144 #include <comet/uuid_fwd.h> 00145 00146 // Primary namespace for comet 00147 namespace comet { 00148 class uuid_t; 00149 00150 template<typename Itf> struct wrap_t : public Itf {}; 00151 00152 template<> struct wrap_t<::IUnknown> {}; 00153 00154 template<typename Itf> Itf* raw( wrap_t<Itf>* p ) { return reinterpret_cast<Itf*>(p); } 00155 00156 // template<typename Itf> struct prop_wrapper : public Itf {}; 00157 00158 // Forward declaration 00159 class variant_t; 00160 template<typename Itf> class com_ptr; 00161 class identity_ptr; 00162 namespace thread_model{ 00163 enum thread_model_t; 00164 }; 00165 template<typename T, enum thread_model::thread_model_t TM, COMET_LIST_TEMPLATE_0 > struct coclass; 00166 template<class C> struct aggregate_inner_unknown ; 00167 00168 // comet implementation details 00169 namespace impl { 00170 00171 template<typename Itf> class com_cast_t { 00172 public: 00173 explicit com_cast_t(Itf* p) : ptr_(p) {}; 00174 Itf* get() const { return ptr_; } 00175 private: 00176 Itf* ptr_; 00177 com_cast_t& operator=(const com_cast_t&); 00178 }; 00179 00180 template<> class com_cast_t<variant_t> { 00181 public: 00182 explicit com_cast_t(const variant_t& v) : val_(v) {}; 00183 const variant_t& get() const { return val_; } 00184 private: 00185 const variant_t& val_; 00186 com_cast_t& operator=(const com_cast_t&); 00187 }; 00188 00192 template <bool B> 00193 struct IUnknown_caller 00194 { 00195 template< typename T > static inline long AddRef( T *y) 00196 { return y->AddRef(); } 00197 template <typename T> static inline long Release( T *y) 00198 { return y->Release(); } 00199 template <typename T> static inline HRESULT QueryInterface( T *y, REFIID iid, void **NewIface) 00200 { return y->QueryInterface(iid, (void **)NewIface); } 00201 }; 00202 00203 template <> 00204 struct IUnknown_caller<true> 00205 { 00206 template<typename T> static inline long AddRef( T *y) 00207 { return y->get_unknown()->AddRef(); } 00208 template< typename T> static inline long Release( T *y) 00209 { return y->get_unknown()->Release(); } 00210 template <typename T> static inline HRESULT QueryInterface( T *y, REFIID iid, void **NewIface) 00211 { return y->get_unknown()->QueryInterface(iid, NewIface); } 00212 }; 00213 // template<typename ITF_LIST> struct implement_internal_qi; 00214 00218 namespace unknown_choice 00219 { 00220 // template<typename T, enum thread_model::thread_model_t TM> long dummy_( coclass<T,TM> *); 00221 // template<typename ITF_LIST> long dummy_(implement_internal_qi<ITF_LIST> *); 00222 template<class C> long dummy_(aggregate_inner_unknown<C> *); 00223 char dummy_( ... ); 00224 }; 00225 00228 template <typename C> 00229 struct iunknown_chooser 00230 { 00231 00232 enum { matches = (sizeof( unknown_choice::dummy_( static_cast< C *>(0) ))==sizeof(long)) }; 00233 }; 00234 00235 } 00239 00241 00254 template<typename Itf> inline impl::com_cast_t<Itf> com_cast(const com_ptr<Itf>& t) { return impl::com_cast_t<Itf>(t.get()); } 00255 template<typename Itf> inline impl::com_cast_t<Itf> com_cast(Itf* t) { return impl::com_cast_t<Itf>(t); } 00256 inline impl::com_cast_t<variant_t> com_cast(const variant_t& v) { return impl::com_cast_t<variant_t>(v); } 00257 00258 namespace impl { 00259 template<typename Itf> class try_cast_t { 00260 public: 00261 explicit try_cast_t(Itf* p) : ptr_(p) {}; 00262 Itf* get() const { return ptr_; } 00263 private: 00264 Itf* ptr_; 00265 try_cast_t& operator=(const try_cast_t&); 00266 }; 00267 00268 template<> class try_cast_t<variant_t> { 00269 public: 00270 explicit try_cast_t(const variant_t& v) : val_(v) {}; 00271 const variant_t& get() const { return val_; } 00272 private: 00273 const variant_t& val_; 00274 try_cast_t& operator=(const try_cast_t&); 00275 }; 00276 } 00277 00278 00279 namespace impl { 00280 00282 00285 template<typename Itf> class safe_interface : public Itf { 00286 private: 00287 HRESULT __stdcall QueryInterface(REFIID, void**); 00288 ULONG __stdcall AddRef(); 00289 ULONG __stdcall Release(); 00290 }; 00291 00292 } 00293 00295 00298 class identity_ptr 00299 { 00300 public: 00302 00304 identity_ptr() throw() : ptr_(NULL){} 00306 00308 ~identity_ptr() throw() { release();} 00309 00311 00313 identity_ptr( const identity_ptr &rhs) : ptr_(rhs.ptr_) {addref();} 00314 00316 00319 template<typename Itf> 00320 explicit identity_ptr( const impl::try_cast_t<Itf> &x ) throw(com_error) 00321 : ptr_(NULL) 00322 { 00323 IUnknown *p=static_cast<IUnknown*>(x.get()); 00324 if (p != NULL) 00325 p->QueryInterface(uuidof< ::IUnknown >(), reinterpret_cast<void**>(&ptr_)) | raise_exception; 00326 } 00327 00329 00332 inline explicit identity_ptr(const impl::try_cast_t<variant_t>& v) throw(com_error); 00333 00335 00338 template<typename Itf> 00339 explicit identity_ptr( const impl::com_cast_t<Itf> &x ) throw(com_error) 00340 : ptr_(NULL) 00341 { 00342 IUnknown *p=static_cast<IUnknown*>(x.get()); 00343 if (p != NULL) 00344 p->QueryInterface(uuidof< ::IUnknown >(), reinterpret_cast<void**>(&ptr_)); 00345 } 00347 00350 inline explicit identity_ptr(const impl::com_cast_t<variant_t>& v) throw(com_error); 00351 00353 00360 explicit identity_ptr(int null) throw(com_error) 00361 : ptr_(NULL) 00362 { if(null != 0) raise_exception(E_POINTER); } 00363 00365 00367 identity_ptr &operator =( const identity_ptr &rhs) throw() 00368 { 00369 identity_ptr tmp(rhs); 00370 swap(tmp); 00371 return *this; 00372 } 00373 00375 00378 template<typename T> 00379 identity_ptr &operator =(const T &rhs) throw(com_error) 00380 { 00381 identity_ptr tmp(rhs); 00382 swap(tmp); 00383 return *this; 00384 } 00386 00392 identity_ptr& operator=(int null) throw(com_error) 00393 { if(null != 0) raise_exception(E_POINTER); release(); return *this; } 00394 00396 IUnknown *get() const throw() { return ptr_; } 00398 IUnknown *in() const throw() { return ptr_; } 00400 IUnknown *raw() const throw() { return ptr_; } 00401 00403 bool is_null() const throw() 00404 { return (ptr_ ==NULL); } 00405 00407 00413 bool operator==(int null) const 00414 { if (null != 0) raise_exception(E_POINTER); return is_null(); } 00416 00422 bool operator!=(int null) const 00423 { if (null != 0) raise_exception(E_POINTER); return !is_null(); } 00424 00428 bool operator<(const identity_ptr& x) const throw() 00429 { return ptr_ < x.ptr_; } 00430 00431 bool operator>(const identity_ptr& x) const throw() 00432 { return ptr_ > x.ptr_; } 00433 00434 00435 bool operator<=(const identity_ptr& x) const throw() 00436 { return ptr_ <= x.ptr_; } 00437 00438 bool operator>=(const identity_ptr& x) const throw() 00439 { return ptr_ >= x.ptr_; } 00440 00441 bool operator==(const identity_ptr& x) const throw() 00442 { return (ptr_ == x.ptr_); } 00443 00444 bool operator!=(const identity_ptr& x) const throw() 00445 { return ptr_ != x.ptr_; } 00447 00448 protected: 00449 IUnknown *ptr_; 00450 00451 void swap(identity_ptr& x) throw() 00452 { std::swap(ptr_, x.ptr_); } 00453 00454 void addref() const throw() 00455 { if (ptr_ != NULL) ptr_->AddRef(); } 00456 00457 void release() throw() 00458 { if (ptr_ != NULL) { ptr_->Release(); ptr_ = NULL; } } 00459 00460 private: 00461 // Can't use an identity_ptr for out, inout, use com_ptr<IUnknown> 00462 IUnknown **inout(); 00463 IUnknown *out(); 00464 00465 }; 00466 00468 00471 template<typename Itf> class com_ptr 00472 { 00473 const uuid_t& iid() const throw() 00474 { return uuidof<Itf>(); } 00475 00476 enum{ chooser_matches_= impl::iunknown_chooser<Itf>::matches }; 00477 typedef typename impl::IUnknown_caller< chooser_matches_ > Unknown_caller_; 00478 00479 void addref() const throw() 00480 { if (ptr_) Unknown_caller_::AddRef(ptr_); } 00481 00482 void release() throw() 00483 { if (ptr_) { Unknown_caller_::Release(ptr_); ptr_ = 0; } } 00484 00485 public: 00487 typedef Itf* interface_pointer; 00488 00490 00493 #ifndef COMET_USE_RAW_WRAPPERS 00494 typedef wrap_t<Itf>* safe_interface_pointer; 00495 #else 00496 typedef impl::safe_interface< Itf >* safe_interface_pointer; 00497 #endif 00498 00499 private: 00500 interface_pointer ptr_; 00501 00502 public: 00504 00507 com_ptr() throw() : ptr_(NULL) {} 00508 00510 00513 ~com_ptr() throw() 00514 { release(); } 00515 00517 00526 // If you are getting: 00527 // error C2440: '=' : cannot convert from 'struct ... 00528 // 00529 // Use either try_cast or com_cast to cast from one interface to another 00530 // example: 00531 // 00532 // com_ptr<IFoo> p = try_cast( q ); 00533 // 00534 // or 00535 // 00536 // com_ptr<IFoo> p = com_cast( q ); 00537 template<typename Itf2> com_ptr(const com_ptr<Itf2>& x) throw() 00538 { ptr_ = (Itf2*)x.get(); addref(); } 00539 00541 00552 template<typename Itf2> com_ptr(const impl::com_cast_t<Itf2>& x) throw() 00553 { ptr_ = NULL; Itf2* p = x.get(); if (p != NULL) Unknown_caller_::QueryInterface(p, iid(), reinterpret_cast<void**>(&ptr_)); } 00554 // ^ Note: no error checking!!! 00555 00557 00572 template<typename Itf2> com_ptr(const impl::try_cast_t<Itf2>& x) throw(com_error) 00573 : ptr_(NULL) 00574 { 00575 Itf2* p = x.get(); if (p == NULL) return; 00576 Unknown_caller_::QueryInterface(p, iid(), reinterpret_cast<void**>(&ptr_)) | raise_exception; 00577 if (ptr_ == NULL) raise_exception(E_NOINTERFACE); 00578 } 00579 00581 00584 com_ptr(const com_ptr& x) throw() 00585 : ptr_(x.ptr_) 00586 { addref(); } 00587 00589 00592 com_ptr( const identity_ptr &x) throw() 00593 : ptr_(x.ptr_) 00594 { addref(); } 00595 00596 private: 00597 // If you are getting: 00598 // error C2248: '=' : cannot access private member ... 00599 // 00600 // Use either try_cast or com_cast to convert a variant_t to a com_ptr. 00601 // example: 00602 // 00603 // com_ptr<IFoo> p = try_cast( v ); 00604 // 00605 // or 00606 // 00607 // com_ptr<IFoo> p = com_cast( v ); 00608 com_ptr(const variant_t&); 00609 com_ptr& operator=(const variant_t&); 00610 00611 public: 00612 00614 00620 com_ptr(const impl::com_cast_t<variant_t>& v) throw() 00621 { create_nothrow(v.get()); } 00622 00624 00633 com_ptr(const impl::try_cast_t<variant_t>& v) throw(com_error) 00634 { create(v.get()); } 00635 00637 00643 com_ptr(interface_pointer p) throw() 00644 : ptr_(p) 00645 { addref(); } 00646 00648 00655 com_ptr(const impl::auto_attach_t<interface_pointer>& p) throw() 00656 : ptr_( p.get() ) 00657 {} 00658 00660 00668 explicit com_ptr(const uuid_t& clsid, DWORD dwClsContext = CLSCTX_ALL) throw(com_error) 00669 { create(clsid, NULL, dwClsContext); } 00670 00672 00682 /*template<typename Itf2>*/ com_ptr(const uuid_t& clsid, const com_ptr<::IUnknown>& outer, DWORD dwClsContext = CLSCTX_ALL) throw(com_error) 00683 { create(clsid, outer, dwClsContext); } 00684 00686 00693 explicit com_ptr(int null) throw(com_error) 00694 : ptr_(NULL) 00695 { if(null != 0) raise_exception(E_POINTER); } 00696 00698 00706 explicit com_ptr(const wchar_t* progid, DWORD dwClsContext = CLSCTX_ALL) throw(com_error) 00707 { create(progid, 0, dwClsContext); } 00708 00710 00720 /*template<typename Itf2> */com_ptr(const wchar_t* progid, const com_ptr<::IUnknown>& outer, DWORD dwClsContext = CLSCTX_ALL) throw(com_error) 00721 { create(progid, outer, dwClsContext); } 00722 00724 explicit com_ptr(const wchar_t* name, BIND_OPTS& bind_opts) 00725 { create(name, bind_opts); } 00726 00728 00733 safe_interface_pointer operator->() const throw(com_error) 00734 { if( ptr_ == NULL) raise_exception(E_POINTER); return get_safe_ptr(); } 00735 00737 com_ptr& operator=(interface_pointer x) throw() 00738 { com_ptr t(x); swap(t); return *this; } 00739 00741 00756 template<typename Itfx> com_ptr& operator=(const impl::com_cast_t<Itfx>& x) throw() 00757 { com_ptr t(x); swap(t); return *this; } 00758 00760 00779 template<typename Itf2> com_ptr& operator=(const impl::try_cast_t<Itf2>& x) throw(com_error) 00780 { com_ptr t(x); swap(t); return *this; } 00781 00782 template<typename Itf2> 00783 com_ptr& operator=(const com_ptr<Itf2>& x) throw() 00784 { com_ptr t(x); swap(t); return *this; } 00785 00787 com_ptr& operator=(const com_ptr& x) throw() 00788 { com_ptr t(x); swap(t); return *this; } 00789 00791 00797 com_ptr& operator=(int null) throw(com_error) 00798 { if(null != 0) raise_exception(E_POINTER); release(); return *this; } 00799 00801 00809 com_ptr& operator=(const impl::auto_attach_t<interface_pointer>& p) throw() 00810 { release(); ptr_ = p.get(); return *this; } 00811 00812 private: 00813 template<typename Itf2> 00814 int compare_unknown(const com_ptr<Itf2>& x) const throw(com_error) 00815 { 00816 if ( (void *)ptr_ == (void *)x.get()) return 0; 00817 ::IUnknown* p1 = 0; 00818 ::IUnknown* p2 = 0; 00819 00820 if (ptr_ != NULL) { 00821 Unknown_caller_::QueryInterface(ptr_,uuidof< ::IUnknown >(), reinterpret_cast<void**>(&p1)) | raise_exception; 00822 p1->Release(); 00823 } 00824 00825 if (x.get()) { 00826 Unknown_caller_::QueryInterface(x.get(), uuidof< ::IUnknown >(), reinterpret_cast<void**>(&p2)) | raise_exception; 00827 p2->Release(); 00828 } 00829 00830 return p1 - p2; 00831 } 00832 int compare_unknown(const identity_ptr& x) const throw(com_error) 00833 { 00834 if (ptr_ == x.get()) return 0; 00835 ::IUnknown* p1 = 0; 00836 00837 if (ptr_ != NULL) { 00838 Unknown_caller_::QueryInterface(x.get(), uuidof< ::IUnknown >(), reinterpret_cast<void**>(&p2)) | raise_exception; 00839 p2->Release(); 00840 } 00841 00842 return p1 - p2; 00843 } 00844 public: 00848 template<typename T> bool operator<(const T& x) const throw(com_error) 00849 { return compare_unknown(x) < 0; } 00850 00851 template<typename T> bool operator>(const T& x) const throw(com_error) 00852 { return compare_unknown(x) > 0; } 00853 00854 template<typename T> bool operator<=(const T& x) const throw(com_error) 00855 { return compare_unknown(x) <= 0; } 00856 00857 template<typename T> bool operator>=(const T& x) const throw(com_error) 00858 { return compare_unknown(x) >= 0; } 00859 00862 template<typename Itf2> bool operator==(const com_ptr<Itf2>& x) const throw(com_error) 00863 { return compare_unknown(x) == 0; } 00864 00865 template<typename Itf2> bool operator!=(const com_ptr<Itf2>& x) const throw(com_error) 00866 { return compare_unknown(x) != 0; } 00867 00869 00871 bool is_null() const throw() 00872 { return (ptr_ ==NULL); } 00873 00875 bool operator!() const throw() 00876 { return is_null(); } 00877 00879 00885 bool operator==(int null) const 00886 { if (null != 0) raise_exception(E_POINTER); return is_null(); } 00887 00889 00895 bool operator!=(int null) const 00896 { if (null != 0) raise_exception(E_POINTER); return !is_null(); } 00897 00899 00902 template<typename Itf2> inline bool same_pointer( const com_ptr<Itf2> &x) const throw(com_error) 00903 { return (IUnknown *) ptr_ == (IUnknown *)x.ptr_; } 00904 00906 00909 void swap(com_ptr& x) throw() 00910 { std::swap(ptr_, x.ptr_); } 00911 00913 00918 interface_pointer detach() throw() 00919 { interface_pointer t = ptr_; ptr_ = 0; return t; } 00920 00922 00924 static interface_pointer detach(com_ptr& x) throw() 00925 { return x.detach(); } 00926 00930 static const com_ptr& create_const_reference(const interface_pointer& x) 00931 { return *reinterpret_cast<const com_ptr*>(&x); } 00932 00936 static com_ptr& create_reference(interface_pointer& x) 00937 { return *reinterpret_cast<com_ptr*>(&x); } 00938 00940 00941 00943 00953 interface_pointer in() const throw() 00954 { return ptr_; } 00955 00956 interface_pointer raw() const throw() 00957 { return ptr_; } 00958 00959 interface_pointer get() const throw() 00960 { return ptr_; } 00961 00963 00973 interface_pointer* out() throw() 00974 { release(); return &ptr_; } 00975 00977 00987 interface_pointer* inout() throw() 00988 { return &ptr_; } 00989 00991 00992 private: 00993 class bool_tester 00994 { void operator delete(void*); }; 00995 00996 public: 00997 operator bool_tester*() const throw() 00998 { if (is_null()) return 0; static bool_tester test; return &test; } 00999 01000 private: 01001 safe_interface_pointer get_safe_ptr() const throw() 01002 { return reinterpret_cast<safe_interface_pointer>(ptr_); } 01003 01004 inline void create_nothrow(const variant_t& v) throw(); 01005 01006 inline void create(const variant_t& v) throw(com_error); 01007 01008 void create(const uuid_t& clsid, const com_ptr<::IUnknown>& outer, DWORD dwClsContext = CLSCTX_ALL) throw(com_error) 01009 { CoCreateInstance(clsid, outer.in(), dwClsContext, iid(), reinterpret_cast<void**>(&ptr_)) | raise_exception; } 01010 01011 void create(const wchar_t* clsidString, const com_ptr<::IUnknown>& outer, DWORD dwClsContext = CLSCTX_ALL) throw(com_error) 01012 { 01013 if (clsidString == NULL) raise_exception(E_INVALIDARG); 01014 01015 CLSID clsid; 01016 01017 if (clsidString[0] == '{') 01018 CLSIDFromString(const_cast<LPOLESTR>(clsidString), &clsid) | raise_exception; 01019 else 01020 CLSIDFromProgID(clsidString, &clsid) | raise_exception; 01021 01022 create(clsid, outer, dwClsContext);; 01023 } 01024 01025 void create(const wchar_t* name, BIND_OPTS& bind_opts) throw(com_error) 01026 { CoGetObject(name, &bind_opts, iid(), reinterpret_cast<void**>(&ptr_)) | raise_exception; } 01027 }; // class 01028 01030 01037 template<typename Itf2> inline bool operator==(int null, const com_ptr<Itf2>& x) throw(com_error) 01038 { if(null != 0) raise_exception(E_POINTER); return x.is_null(); } 01039 01041 01048 static inline bool operator==(int null, const identity_ptr& x) throw(com_error) 01049 { if(null != 0) raise_exception(E_POINTER); return x.is_null(); } 01050 01052 01059 template<typename Itf> inline bool operator!=(int null, const com_ptr<Itf>& x) throw(com_error) 01060 { return x != null; } 01061 01063 01070 inline static bool operator!=(int null, const identity_ptr& x) throw(com_error) 01071 { if(null != 0) raise_exception(E_POINTER); return !x.is_null(); } 01072 01073 namespace impl { 01074 template <typename Itf> 01075 class try_caster_t 01076 { 01077 com_ptr<Itf> ptr_; 01078 public: 01079 template <typename Itf2 > 01080 try_caster_t( const com_ptr<Itf2> &ptr2) 01081 : ptr_(try_cast(ptr2)) 01082 {} 01083 01084 const com_ptr<Itf> &get() const { return ptr_; } 01085 01086 }; 01087 }; 01100 template<typename Itf> inline com_ptr<Itf> try_cast_ptr( const impl::try_caster_t<Itf> &caster) 01101 { return (com_ptr<Itf>)caster.get(); } 01102 01104 01119 template<typename Itf> inline impl::try_cast_t<Itf> try_cast(const com_ptr<Itf>& t) { return impl::try_cast_t<Itf>(t.get()); } 01120 static inline impl::try_cast_t<::IUnknown> try_cast(const identity_ptr& t) { return impl::try_cast_t<::IUnknown>(t.get()); } 01121 template<typename Itf> inline impl::try_cast_t<Itf> try_cast(Itf* t) { return impl::try_cast_t<Itf>(t); } 01122 inline impl::try_cast_t<variant_t> try_cast(const variant_t& v) { return impl::try_cast_t<variant_t>(v); } 01124 01125 } // namespace 01126 01127 #include <comet/variant.h> 01128 #include <comet/error.h> 01129 01130 namespace comet { 01131 template<typename Itf> 01132 inline void com_ptr<Itf>::create_nothrow(const variant_t& v) throw() 01133 { 01134 ptr_ = 0; 01135 ::IUnknown *pUnk; 01136 switch (v.get_vt()) { 01137 case VT_DISPATCH: 01138 pUnk = V_DISPATCH(&v.get()); 01139 break; 01140 case VT_UNKNOWN: 01141 pUnk = V_UNKNOWN(&v.get()); 01142 break; 01143 case VT_DISPATCH|VT_BYREF: 01144 pUnk = *V_DISPATCHREF(&v.get()); 01145 break; 01146 case VT_UNKNOWN|VT_BYREF: 01147 pUnk = *V_UNKNOWNREF(&v.get()); 01148 break; 01149 default: 01150 // don't try anything fancy. 01151 return; 01152 } 01153 if( pUnk ==NULL) return; 01154 Unknown_caller_::QueryInterface(pUnk,iid(), reinterpret_cast<void**>(&ptr_)); 01155 } 01156 template<typename Itf> 01157 inline void com_ptr<Itf>::create(const variant_t& v) throw(com_error) 01158 { 01159 ptr_ = 0; 01160 ::IUnknown *pUnk; 01161 switch (v.get_vt()) { 01162 case VT_DISPATCH: 01163 pUnk = V_DISPATCH(&v.get()); 01164 break; 01165 case VT_UNKNOWN: 01166 pUnk = V_UNKNOWN(&v.get()); 01167 break; 01168 case VT_DISPATCH|VT_BYREF: 01169 pUnk = *V_DISPATCHREF(&v.get()); 01170 break; 01171 case VT_UNKNOWN|VT_BYREF: 01172 pUnk = *V_UNKNOWNREF(&v.get()); 01173 break; 01174 case VT_EMPTY: 01175 case VT_NULL: 01176 pUnk = NULL; 01177 break; 01178 default: 01179 // don't try anything fancy. 01180 raise_exception( E_INVALIDARG ); 01181 } 01182 if( pUnk ==NULL) return; 01183 Unknown_caller_::QueryInterface(pUnk,iid(), reinterpret_cast<void**>(&ptr_)) | raise_exception; 01184 } 01185 01186 inline identity_ptr::identity_ptr(const impl::try_cast_t<variant_t>& v) throw(com_error) 01187 : ptr_(NULL) 01188 { 01189 VARIANT vv = v.get().get(); 01190 ::IUnknown *pUnk; 01191 switch (V_VT(&vv)) { 01192 case VT_DISPATCH: 01193 pUnk = V_DISPATCH(&vv); 01194 break; 01195 case VT_UNKNOWN: 01196 pUnk = V_UNKNOWN(&vv); 01197 break; 01198 case VT_DISPATCH|VT_BYREF: 01199 pUnk = *V_DISPATCHREF(&vv); 01200 break; 01201 case VT_UNKNOWN|VT_BYREF: 01202 pUnk = *V_UNKNOWNREF(&vv); 01203 break; 01204 case VT_EMPTY: 01205 case VT_NULL: 01206 pUnk = NULL; 01207 break; 01208 default: 01209 // don't try anything fancy. 01210 raise_exception( E_INVALIDARG ); 01211 } 01212 if( pUnk ==NULL) return; 01213 pUnk->QueryInterface( IID_IUnknown, reinterpret_cast<void **>(&ptr_)) | raise_exception; 01214 } 01215 01216 inline identity_ptr::identity_ptr(const impl::com_cast_t<variant_t>& v) throw(com_error) 01217 : ptr_(NULL) 01218 { 01219 VARIANT vv = v.get().get(); 01220 ::IUnknown *pUnk; 01221 switch (V_VT(&vv)) { 01222 case VT_DISPATCH: 01223 pUnk = V_DISPATCH(&vv); 01224 break; 01225 case VT_UNKNOWN: 01226 pUnk = V_UNKNOWN(&vv); 01227 break; 01228 case VT_DISPATCH|VT_BYREF: 01229 pUnk = *V_DISPATCHREF(&vv); 01230 break; 01231 case VT_UNKNOWN|VT_BYREF: 01232 pUnk = *V_UNKNOWNREF(&vv); 01233 break; 01234 default: 01235 // don't try anything fancy. 01236 return; 01237 } 01238 if( pUnk ==NULL) return; 01239 pUnk->QueryInterface( IID_IUnknown, reinterpret_cast<void **>(&ptr_)); 01240 } 01241 }; 01242 01243 namespace boost { 01244 template<typename Itf> inline Itf* get_pointer(const comet::com_ptr<Itf>& sp) 01245 { 01246 return sp.raw(); 01247 } 01248 static inline IUnknown* get_pointer(const comet::identity_ptr &sp) 01249 { 01250 return sp.raw(); 01251 } 01252 } 01253 01255 #define COMET_SPECIALISE_STD_SWAP_ITF(Itf) namespace std { inline void swap(comet::com_ptr<Itf>& x, comet::com_ptr<Itf>& y) {x.swap(y); } } 01256 01257 #endif 01258