/*** *ptr.h * * Copyright (c) Microsoft Corporation. All rights reserved. * *Purpose: COM Wrapper for the Managed World * * [Public] * ****/ #pragma once #if !defined (_INC_MSCLR_COM_PTR) #ifndef __cplusplus_cli #error ERROR: msclr libraries are not compatible with /clr:oldSyntax #endif /* __cplusplus_cli */ #include #include namespace msclr { namespace _detail { // COM::ptr::operator->() returns a smart_com_ptr instead of // a regular interface pointer so that a Release is done automatically // when the temporary is destroyed template ref class smart_com_ptr { public: smart_com_ptr(_interface_type * p) { ptr= p; } smart_com_ptr(smart_com_ptr % ip) { ptr = ip.ptr; ptr->AddRef(); } _interface_type * operator ->() { return ptr; } ~smart_com_ptr() { ptr->Release(); } private: _interface_type * ptr; }; } //namespace _detail namespace com { template ref class ptr { public: ptr():obj_rcw(nullptr) { } // Construct from interface pointer ptr(_interface_type * p) { obj_rcw = nullptr; assign(p); } // Attach to an interface pointer void Attach(_interface_type * _right) { if (valid()) { throw gcnew System::InvalidOperationException("COM::ptr.Attach"); } assign(_right); } // Assign an interface pointer ptr<_interface_type> % operator=(_interface_type * _right) { Attach(_right); return *this; } // All CreateInstance methods create an instance of a COM Object // by calling CoCreateInstance void CreateInstance(System::String ^ prog_id, LPUNKNOWN pouter, DWORD cls_context) { wchar_t * pwszprog_id = NULL; if(prog_id != nullptr) { pin_ptr _pinned_ptr = PtrToStringChars( prog_id ); pwszprog_id = _wcsdup(_pinned_ptr); } try { CreateInstance(pwszprog_id, pouter, cls_context); } finally { free(pwszprog_id); } } void CreateInstance(System::String ^ prog_id, LPUNKNOWN pouter) { CreateInstance(prog_id, pouter, CLSCTX_ALL); } void CreateInstance(System::String ^ prog_id) { CreateInstance(prog_id, NULL, CLSCTX_ALL); } void CreateInstance(const wchar_t* progid, LPUNKNOWN pouter, DWORD cls_context) { CLSID clsid; System::Runtime::InteropServices::Marshal::ThrowExceptionForHR( CLSIDFromProgID(progid, &clsid)); CreateInstance(clsid, pouter, cls_context); } void CreateInstance(const wchar_t * progid, LPUNKNOWN pouter) { CreateInstance(progid, pouter, CLSCTX_ALL); } void CreateInstance(const wchar_t * progid) { CreateInstance(progid, NULL, CLSCTX_ALL); } void CreateInstance(REFCLSID rclsid,LPUNKNOWN pouter,DWORD cls_context) { if (valid()) { throw gcnew System::InvalidOperationException("COM::ptr.CreateInstance"); } _interface_type * interface_ptr = NULL; System::Runtime::InteropServices::Marshal::ThrowExceptionForHR(CoCreateInstance( rclsid, pouter, cls_context, __uuidof(_interface_type), (void**)&interface_ptr)); if (interface_ptr) { assign(interface_ptr); interface_ptr->Release(); } } void CreateInstance(REFCLSID rclsid,LPUNKNOWN pouter) { CreateInstance(rclsid, pouter, CLSCTX_ALL); } void CreateInstance(REFCLSID rclsid) { CreateInstance(rclsid, NULL, CLSCTX_ALL); } // Give up ownership of the interface pointer & return the // interface pointer _interface_type * Detach() { if(valid()) { _interface_type * interface_ptr = GetInterface(); destroy(); return interface_ptr; } return NULL; } // Give up ownership of the interface pointer void Release() { if(valid()) { destroy(); } } // Operator ->() - to be used to call methods on the owned COM Object // We return a smart_com_ptr instead of an interface pointer so that // the reference is released automatically _detail::smart_com_ptr<_interface_type> operator->() { _detail::smart_com_ptr<_interface_type> interface_ptr(GetInterface()); return interface_ptr; } // Return an interface pointer _interface_type * GetInterface() { if(!valid()) { return NULL; } System::IntPtr iface_intptr = System::Runtime::InteropServices::Marshal::GetIUnknownForObject(obj_rcw); IUnknown * iunk = static_cast(static_cast(iface_intptr)); _interface_type * interface_ptr = NULL; System::Runtime::InteropServices::Marshal::ThrowExceptionForHR(iunk->QueryInterface(__uuidof(_interface_type), (void **)&interface_ptr)); iunk->Release(); interface_ptr->AddRef(); System::Runtime::InteropServices::Marshal::Release(iface_intptr); return interface_ptr; } // QueryInteface & fillup up the passed it COM::ptr with the result template void QueryInterface(ptr<_other_type> % other) { QueryInterface<_other_type>(__uuidof(_other_type), other); } // for use when com::ptr appears in a conditional operator _detail_class::_safe_bool() { return valid() ? _detail_class::_safe_true : _detail_class::_safe_false; } // for use when com::ptr appears in a conditional bool operator!() { return ! valid(); } ~ptr() { if(valid()) { destroy(); } } private: void destroy() { System::Runtime::InteropServices::Marshal::ReleaseComObject(obj_rcw); obj_rcw = nullptr; } bool valid() { return (obj_rcw != nullptr); } void assign(_interface_type *p) { if(p) { obj_rcw = System::Runtime::InteropServices::Marshal::GetUniqueObjectForIUnknown(System::IntPtr(p)); } } template void QueryInterface(REFIID riid, ptr<_other_type> % other) { _detail::smart_com_ptr<_interface_type> interface_ptr(GetInterface()); _other_type * other_ptr = NULL; System::Runtime::InteropServices::Marshal::ThrowExceptionForHR(interface_ptr->QueryInterface(riid,(void **)&other_ptr)); other.Attach(other_ptr); other_ptr->Release(); } Object ^obj_rcw; }; } // namespace com } // namespace msclr #define _INC_MSCLR_COM_PTR #endif /* !defined (_INC_MSCLR_COM_PTR) */