1/** 2 * This file has no copyright assigned and is placed in the Public Domain. 3 * This file is part of the mingw-w64 runtime package. 4 * No warranty is given; refer to the file DISCLAIMER.PD within this package. 5 */ 6#ifndef _INC_COMIP 7#define _INC_COMIP 8 9#include <_mingw.h> 10 11#include <ole2.h> 12#include <malloc.h> 13 14#include <comutil.h> 15 16#ifdef __cplusplus 17 18#pragma push_macro("new") 19#undef new 20 21#include <new.h> 22 23class _com_error; 24 25#ifndef WINAPI 26#if defined(_ARM_) 27#define WINAPI 28#else 29#define WINAPI __stdcall 30#endif 31#endif 32 33void WINAPI _com_issue_error(HRESULT); 34struct IUnknown; 35 36template<typename _Interface,const IID *_IID > 37class _com_IIID { 38public: 39 typedef _Interface Interface; 40 static _Interface *GetInterfacePtr() throw() { return NULL; } 41 static _Interface& GetInterface() throw() { return *GetInterfacePtr(); } 42 static const IID& GetIID() throw() { return *_IID; } 43}; 44 45/* This is needed for _COM_SMARTPTR_TYPEDEF using emulated __uuidof. Since we can't pass 46 * IID as a template argument, it's passed as a wrapper function. */ 47template<typename _Interface,const IID &(*iid_getter)() > 48class _com_IIID_getter { 49public: 50 typedef _Interface Interface; 51 static _Interface *GetInterfacePtr() throw() { return NULL; } 52 static _Interface& GetInterface() throw() { return *GetInterfacePtr(); } 53 static const IID& GetIID() throw() { return iid_getter(); } 54}; 55 56template<typename _IIID> class _com_ptr_t { 57public: 58 typedef _IIID ThisIIID; 59 typedef typename _IIID::Interface Interface; 60 static const IID& GetIID() throw() { return ThisIIID::GetIID(); } 61 template<typename _OtherIID> _com_ptr_t(const _com_ptr_t<_OtherIID> &p) : m_pInterface(NULL) { 62 HRESULT hr = _QueryInterface(p); 63 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 64 } 65 template<typename _InterfaceType> _com_ptr_t(_InterfaceType *p) : m_pInterface(NULL) { 66 HRESULT hr = _QueryInterface(p); 67 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 68 } 69 _com_ptr_t(LPSTR str) { new(this) _com_ptr_t(static_cast<LPCSTR> (str),NULL); } 70 _com_ptr_t(LPWSTR str) { new(this) _com_ptr_t(static_cast<LPCWSTR> (str),NULL); } 71 explicit _com_ptr_t(_com_ptr_t *p) : m_pInterface(NULL) { 72 if(!p) { _com_issue_error(E_POINTER); } 73 else { 74 m_pInterface = p->m_pInterface; 75 AddRef(); 76 } 77 } 78 _com_ptr_t() throw() : m_pInterface(NULL) { } 79 _com_ptr_t(int null) : m_pInterface(NULL) { 80 if(null!=0) { _com_issue_error(E_POINTER); } 81 } 82 83#ifdef _NATIVE_NULLPTR_SUPPORTED 84 _com_ptr_t(decltype(nullptr)) : m_pInterface(NULL) {} 85#endif 86 87 _com_ptr_t(const _com_ptr_t &cp) throw() : m_pInterface(cp.m_pInterface) { _AddRef(); } 88 _com_ptr_t(Interface *pInterface) throw() : m_pInterface(pInterface) { _AddRef(); } 89 _com_ptr_t(Interface *pInterface,bool fAddRef) throw() : m_pInterface(pInterface) { 90 if(fAddRef) _AddRef(); 91 } 92 _com_ptr_t(const _variant_t& varSrc) : m_pInterface(NULL) { 93 HRESULT hr = QueryStdInterfaces(varSrc); 94 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 95 } 96 explicit _com_ptr_t(const CLSID &clsid,IUnknown *pOuter = NULL,DWORD dwClsContext = CLSCTX_ALL) : m_pInterface(NULL) { 97 HRESULT hr = CreateInstance(clsid,pOuter,dwClsContext); 98 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 99 } 100 explicit _com_ptr_t(LPCWSTR str,IUnknown *pOuter = NULL,DWORD dwClsContext = CLSCTX_ALL) : m_pInterface(NULL) { 101 HRESULT hr = CreateInstance(str,pOuter,dwClsContext); 102 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 103 } 104 explicit _com_ptr_t(LPCSTR str,IUnknown *pOuter = NULL,DWORD dwClsContext = CLSCTX_ALL) : m_pInterface(NULL) { 105 HRESULT hr = CreateInstance(str,pOuter,dwClsContext); 106 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 107 } 108 template<typename _OtherIID> _com_ptr_t &operator=(const _com_ptr_t<_OtherIID> &p) { 109 HRESULT hr = _QueryInterface(p); 110 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 111 return *this; 112 } 113 template<typename _InterfaceType> _com_ptr_t &operator=(_InterfaceType *p) { 114 HRESULT hr = _QueryInterface(p); 115 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 116 return *this; 117 } 118 _com_ptr_t &operator=(Interface *pInterface) throw() { 119 if(m_pInterface!=pInterface) { 120 Interface *pOldInterface = m_pInterface; 121 m_pInterface = pInterface; 122 _AddRef(); 123 if(pOldInterface!=NULL) pOldInterface->Release(); 124 } 125 return *this; 126 } 127 _com_ptr_t &operator=(const _com_ptr_t &cp) throw() { return operator=(cp.m_pInterface); } 128 _com_ptr_t &operator=(int null) { 129 if(null!=0) { _com_issue_error(E_POINTER); } 130 return operator=(reinterpret_cast<Interface*>(NULL)); 131 } 132 _com_ptr_t &operator=(long long null) { 133 if(null!=0) { _com_issue_error(E_POINTER); } 134 return operator=(reinterpret_cast<Interface*>(NULL)); 135 } 136 _com_ptr_t &operator=(const _variant_t& varSrc) { 137 HRESULT hr = QueryStdInterfaces(varSrc); 138 if(FAILED(hr) && (hr!=E_NOINTERFACE)) { _com_issue_error(hr); } 139 return *this; 140 } 141 ~_com_ptr_t() throw() { _Release(); } 142 void Attach(Interface *pInterface) throw() { 143 _Release(); 144 m_pInterface = pInterface; 145 } 146 void Attach(Interface *pInterface,bool fAddRef) throw() { 147 _Release(); 148 m_pInterface = pInterface; 149 if(fAddRef) { 150 if(!pInterface) { _com_issue_error(E_POINTER); } 151 else pInterface->AddRef(); 152 } 153 } 154 Interface *Detach() throw() { 155 Interface *const old = m_pInterface; 156 m_pInterface = NULL; 157 return old; 158 } 159 operator Interface*() const throw() { return m_pInterface; } 160 operator Interface&() const { 161 if(!m_pInterface) { _com_issue_error(E_POINTER); } 162 return *m_pInterface; 163 } 164 Interface& operator*() const { 165 if(!m_pInterface) { _com_issue_error(E_POINTER); } 166 return *m_pInterface; 167 } 168 Interface **operator&() throw() { 169 _Release(); 170 m_pInterface = NULL; 171 return &m_pInterface; 172 } 173 Interface *operator->() const { 174 if(!m_pInterface) { _com_issue_error(E_POINTER); } 175 return m_pInterface; 176 } 177 operator bool() const throw() { return m_pInterface!=NULL; } 178 template<typename _OtherIID> bool operator==(const _com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)==0; } 179 template<typename _OtherIID> bool operator==(_com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)==0; } 180 template<typename _InterfaceType> bool operator==(_InterfaceType *p) { return _CompareUnknown(p)==0; } 181 bool operator==(Interface *p) { return (m_pInterface==p) ? true : _CompareUnknown(p)==0; } 182 bool operator==(const _com_ptr_t &p) throw() { return operator==(p.m_pInterface); } 183 bool operator==(_com_ptr_t &p) throw() { return operator==(p.m_pInterface); } 184 bool operator==(int null) { 185 if(null!=0) { _com_issue_error(E_POINTER); } 186 return !m_pInterface; 187 } 188 bool operator==(long long null) { 189 if(null) { _com_issue_error(E_POINTER); } 190 return !m_pInterface; 191 } 192 template<typename _OtherIID> bool operator!=(const _com_ptr_t<_OtherIID> &p) { return !(operator==(p)); } 193 template<typename _OtherIID> bool operator!=(_com_ptr_t<_OtherIID> &p) { return !(operator==(p)); } 194 template<typename _InterfaceType> bool operator!=(_InterfaceType *p) { return !(operator==(p)); } 195 bool operator!=(int null) { return !(operator==(null)); } 196 bool operator!=(long long null) { return !(operator==(null)); } 197 template<typename _OtherIID> bool operator<(const _com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)<0; } 198 template<typename _OtherIID> bool operator<(_com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)<0; } 199 template<typename _InterfaceType> bool operator<(_InterfaceType *p) { return _CompareUnknown(p)<0; } 200 template<typename _OtherIID> bool operator>(const _com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)>0; } 201 template<typename _OtherIID> bool operator>(_com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)>0; } 202 template<typename _InterfaceType> bool operator>(_InterfaceType *p) { return _CompareUnknown(p)>0; } 203 template<typename _OtherIID> bool operator<=(const _com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)<=0; } 204 template<typename _OtherIID> bool operator<=(_com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)<=0; } 205 template<typename _InterfaceType> bool operator<=(_InterfaceType *p) { return _CompareUnknown(p)<=0; } 206 template<typename _OtherIID> bool operator>=(const _com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)>=0; } 207 template<typename _OtherIID> bool operator>=(_com_ptr_t<_OtherIID> &p) { return _CompareUnknown(p)>=0; } 208 template<typename _InterfaceType> bool operator>=(_InterfaceType *p) { return _CompareUnknown(p)>=0; } 209 void Release() { 210 if(!m_pInterface) { _com_issue_error(E_POINTER); } 211 else { 212 m_pInterface->Release(); 213 m_pInterface = NULL; 214 } 215 } 216 void AddRef() { 217 if(!m_pInterface) { _com_issue_error(E_POINTER); } 218 else m_pInterface->AddRef(); 219 } 220 Interface *GetInterfacePtr() const throw() { return m_pInterface; } 221 Interface*& GetInterfacePtr() throw() { return m_pInterface; } 222 HRESULT CreateInstance(const CLSID &rclsid,IUnknown *pOuter = NULL,DWORD dwClsContext = CLSCTX_ALL) throw() { 223 HRESULT hr; 224 _Release(); 225 if(dwClsContext & (CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER)) { 226 IUnknown *pIUnknown; 227 hr = CoCreateInstance(rclsid,pOuter,dwClsContext,__uuidof(IUnknown),reinterpret_cast<void**>(&pIUnknown)); 228 if(SUCCEEDED(hr)) { 229 hr = OleRun(pIUnknown); 230 if(SUCCEEDED(hr)) hr = pIUnknown->QueryInterface(GetIID(),reinterpret_cast<void**>(&m_pInterface)); 231 pIUnknown->Release(); 232 } 233 } else hr = CoCreateInstance(rclsid,pOuter,dwClsContext,GetIID(),reinterpret_cast<void**>(&m_pInterface)); 234 if(FAILED(hr)) m_pInterface = NULL; 235 return hr; 236 } 237 HRESULT CreateInstance(LPCWSTR clsidString,IUnknown *pOuter = NULL,DWORD dwClsContext = CLSCTX_ALL) throw() { 238 if(!clsidString) return E_INVALIDARG; 239 CLSID clsid; 240 HRESULT hr; 241 if(clsidString[0]==L'{') hr = CLSIDFromString(const_cast<LPWSTR> (clsidString),&clsid); 242 else hr = CLSIDFromProgID(const_cast<LPWSTR> (clsidString),&clsid); 243 if(FAILED(hr)) return hr; 244 return CreateInstance(clsid,pOuter,dwClsContext); 245 } 246 HRESULT CreateInstance(LPCSTR clsidStringA,IUnknown *pOuter = NULL,DWORD dwClsContext = CLSCTX_ALL) throw() { 247 if(!clsidStringA) return E_INVALIDARG; 248 int size = lstrlenA(clsidStringA) + 1; 249 int destSize = MultiByteToWideChar(CP_ACP,0,clsidStringA,size,NULL,0); 250 if(destSize==0) return HRESULT_FROM_WIN32(GetLastError()); 251 LPWSTR clsidStringW; 252 clsidStringW = static_cast<LPWSTR>(_malloca(destSize*sizeof(WCHAR))); 253 if(!clsidStringW) return E_OUTOFMEMORY; 254 if(MultiByteToWideChar(CP_ACP,0,clsidStringA,size,clsidStringW,destSize)==0) { 255 _freea(clsidStringW); 256 return HRESULT_FROM_WIN32(GetLastError()); 257 } 258 HRESULT hr=CreateInstance(clsidStringW,pOuter,dwClsContext); 259 _freea(clsidStringW); 260 return hr; 261 } 262 HRESULT GetActiveObject(const CLSID &rclsid) throw() { 263 _Release(); 264 IUnknown *pIUnknown; 265 HRESULT hr = ::GetActiveObject(rclsid,NULL,&pIUnknown); 266 if(SUCCEEDED(hr)) { 267 hr = pIUnknown->QueryInterface(GetIID(),reinterpret_cast<void**>(&m_pInterface)); 268 pIUnknown->Release(); 269 } 270 if(FAILED(hr)) m_pInterface = NULL; 271 return hr; 272 } 273 HRESULT GetActiveObject(LPCWSTR clsidString) throw() { 274 if(!clsidString) return E_INVALIDARG; 275 CLSID clsid; 276 HRESULT hr; 277 if(clsidString[0]=='{') hr = CLSIDFromString(const_cast<LPWSTR> (clsidString),&clsid); 278 else hr = CLSIDFromProgID(const_cast<LPWSTR> (clsidString),&clsid); 279 if(FAILED(hr)) return hr; 280 return GetActiveObject(clsid); 281 } 282 HRESULT GetActiveObject(LPCSTR clsidStringA) throw() { 283 if(!clsidStringA) return E_INVALIDARG; 284 int size = lstrlenA(clsidStringA) + 1; 285 int destSize = MultiByteToWideChar(CP_ACP,0,clsidStringA,size,NULL,0); 286 LPWSTR clsidStringW; 287 try { 288 clsidStringW = static_cast<LPWSTR>(_alloca(destSize*sizeof(WCHAR))); 289 } catch (...) { 290 clsidStringW = NULL; 291 } 292 if(!clsidStringW) return E_OUTOFMEMORY; 293 if(MultiByteToWideChar(CP_ACP,0,clsidStringA,size,clsidStringW,destSize)==0) return HRESULT_FROM_WIN32(GetLastError()); 294 return GetActiveObject(clsidStringW); 295 } 296 template<typename _InterfaceType> HRESULT QueryInterface(const IID& iid,_InterfaceType*& p) throw () { 297 if(m_pInterface!=NULL) return m_pInterface->QueryInterface(iid,reinterpret_cast<void**>(&p)); 298 return E_POINTER; 299 } 300 template<typename _InterfaceType> HRESULT QueryInterface(const IID& iid,_InterfaceType **p) throw() { return QueryInterface(iid,*p); } 301private: 302 Interface *m_pInterface; 303 void _Release() throw() { 304 if(m_pInterface!=NULL) m_pInterface->Release(); 305 } 306 void _AddRef() throw() { 307 if(m_pInterface!=NULL) m_pInterface->AddRef(); 308 } 309 template<typename _InterfacePtr> HRESULT _QueryInterface(_InterfacePtr p) throw() { 310 HRESULT hr; 311 if(p!=NULL) { 312 Interface *pInterface; 313 hr = p->QueryInterface(GetIID(),reinterpret_cast<void**>(&pInterface)); 314 Attach(SUCCEEDED(hr)? pInterface: NULL); 315 } else { 316 operator=(static_cast<Interface*>(NULL)); 317 hr = E_NOINTERFACE; 318 } 319 return hr; 320 } 321 template<typename _InterfacePtr> int _CompareUnknown(_InterfacePtr p) { 322 IUnknown *pu1,*pu2; 323 if(m_pInterface!=NULL) { 324 HRESULT hr = m_pInterface->QueryInterface(__uuidof(IUnknown),reinterpret_cast<void**>(&pu1)); 325 if(FAILED(hr)) { 326 _com_issue_error(hr); 327 pu1 = NULL; 328 } else pu1->Release(); 329 } else pu1 = NULL; 330 if(p!=NULL) { 331 HRESULT hr = p->QueryInterface(__uuidof(IUnknown),reinterpret_cast<void**>(&pu2)); 332 if(FAILED(hr)) { 333 _com_issue_error(hr); 334 pu2 = NULL; 335 } else pu2->Release(); 336 } else pu2 = NULL; 337 return pu1 - pu2; 338 } 339 HRESULT QueryStdInterfaces(const _variant_t& varSrc) throw() { 340 if(V_VT(&varSrc)==VT_DISPATCH) return _QueryInterface(V_DISPATCH(&varSrc)); 341 if(V_VT(&varSrc)==VT_UNKNOWN) return _QueryInterface(V_UNKNOWN(&varSrc)); 342 VARIANT varDest; 343 VariantInit(&varDest); 344 HRESULT hr = VariantChangeType(&varDest,const_cast<VARIANT*>(static_cast<const VARIANT*>(&varSrc)),0,VT_DISPATCH); 345 if(SUCCEEDED(hr)) hr = _QueryInterface(V_DISPATCH(&varSrc)); 346 if(hr==E_NOINTERFACE) { 347 VariantInit(&varDest); 348 hr = VariantChangeType(&varDest,const_cast<VARIANT*>(static_cast<const VARIANT*>(&varSrc)),0,VT_UNKNOWN); 349 if(SUCCEEDED(hr)) hr = _QueryInterface(V_UNKNOWN(&varSrc)); 350 } 351 VariantClear(&varDest); 352 return hr; 353 } 354}; 355 356template<typename _InterfaceType> bool operator==(int null,_com_ptr_t<_InterfaceType> &p) { 357 if(null!=0) { _com_issue_error(E_POINTER); } 358 return !p; 359} 360 361template<typename _Interface,typename _InterfacePtr> bool operator==(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p==i; } 362 363template<typename _Interface> bool operator!=(int null,_com_ptr_t<_Interface> &p) { 364 if(null!=0) { _com_issue_error(E_POINTER); } 365 return p!=NULL; 366} 367 368template<typename _Interface,typename _InterfacePtr> bool operator!=(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p!=i; } 369 370template<typename _Interface> bool operator<(int null,_com_ptr_t<_Interface> &p) { 371 if(null!=0) { _com_issue_error(E_POINTER); } 372 return p>NULL; 373} 374 375template<typename _Interface,typename _InterfacePtr> bool operator<(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p>i; } 376 377template<typename _Interface> bool operator>(int null,_com_ptr_t<_Interface> &p) { 378 if(null!=0) { _com_issue_error(E_POINTER); } 379 return p<NULL; 380} 381 382template<typename _Interface,typename _InterfacePtr> bool operator>(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p<i; } 383 384template<typename _Interface> bool operator<=(int null,_com_ptr_t<_Interface> &p) { 385 if(null!=0) { _com_issue_error(E_POINTER); } 386 return p>=NULL; 387} 388 389template<typename _Interface,typename _InterfacePtr> bool operator<=(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p>=i; } 390 391template<typename _Interface> bool operator>=(int null,_com_ptr_t<_Interface> &p) { 392 if(null!=0) { _com_issue_error(E_POINTER); } 393 return p<=NULL; 394} 395 396template<typename _Interface,typename _InterfacePtr> bool operator>=(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p<=i; } 397 398#pragma pop_macro("new") 399 400#endif /* __cplusplus */ 401 402#endif /* _INC_COMIP */ 403