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 
23 class _com_error;
24 
25 #ifndef WINAPI
26 #if defined(_ARM_)
27 #define WINAPI
28 #else
29 #define WINAPI __stdcall
30 #endif
31 #endif
32 
33 void WINAPI _com_issue_error(HRESULT);
34 struct IUnknown;
35 
36 template<typename _Interface,const IID *_IID >
37 class _com_IIID {
38 public:
39   typedef _Interface Interface;
GetInterfacePtr()40   static _Interface *GetInterfacePtr() throw() { return NULL; }
GetInterface()41   static _Interface& GetInterface() throw() { return *GetInterfacePtr(); }
GetIID()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. */
47 template<typename _Interface,const IID &(*iid_getter)() >
48 class _com_IIID_getter {
49 public:
50   typedef _Interface Interface;
GetInterfacePtr()51   static _Interface *GetInterfacePtr() throw() { return NULL; }
GetInterface()52   static _Interface& GetInterface() throw() { return *GetInterfacePtr(); }
GetIID()53   static const IID& GetIID() throw() { return iid_getter(); }
54 };
55 
56 template<typename _IIID> class _com_ptr_t {
57 public:
58   typedef _IIID ThisIIID;
59   typedef typename _IIID::Interface Interface;
GetIID()60   static const IID& GetIID() throw() { return ThisIIID::GetIID(); }
_com_ptr_t(const _com_ptr_t<_OtherIID> & p)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   }
_com_ptr_t(_InterfaceType * p)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   }
_com_ptr_t(LPSTR str)69   _com_ptr_t(LPSTR str) { new(this) _com_ptr_t(static_cast<LPCSTR> (str),NULL); }
_com_ptr_t(LPWSTR str)70   _com_ptr_t(LPWSTR str) { new(this) _com_ptr_t(static_cast<LPCWSTR> (str),NULL); }
_com_ptr_t(_com_ptr_t * p)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   }
throw()78   _com_ptr_t() throw() : m_pInterface(NULL) { }
_com_ptr_t(int 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
_com_ptr_t(decltype (nullptr))84   _com_ptr_t(decltype(nullptr)) : m_pInterface(NULL) {}
85 #endif
86 
throw()87   _com_ptr_t(const _com_ptr_t &cp) throw() : m_pInterface(cp.m_pInterface) { _AddRef(); }
throw()88   _com_ptr_t(Interface *pInterface) throw() : m_pInterface(pInterface) { _AddRef(); }
_com_ptr_t(Interface * pInterface,bool fAddRef)89   _com_ptr_t(Interface *pInterface,bool fAddRef) throw() : m_pInterface(pInterface) {
90     if(fAddRef) _AddRef();
91   }
_com_ptr_t(const _variant_t & varSrc)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   }
m_pInterface(NULL)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   }
m_pInterface(NULL)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   }
m_pInterface(NULL)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   }
throw()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   }
throw()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   }
throw()141   ~_com_ptr_t() throw() { _Release(); }
Attach(Interface * pInterface)142   void Attach(Interface *pInterface) throw() {
143     _Release();
144     m_pInterface = pInterface;
145   }
Attach(Interface * pInterface,bool fAddRef)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   }
Detach()154   Interface *Detach() throw() {
155     Interface *const old = m_pInterface;
156     m_pInterface = NULL;
157     return old;
158   }
throw()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   }
throw()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   }
throw()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; }
Release()209   void Release() {
210     if(!m_pInterface) { _com_issue_error(E_POINTER); }
211     else {
212       m_pInterface->Release();
213       m_pInterface = NULL;
214     }
215   }
AddRef()216   void AddRef() {
217     if(!m_pInterface) { _com_issue_error(E_POINTER); }
218     else m_pInterface->AddRef();
219   }
GetInterfacePtr()220   Interface *GetInterfacePtr() const throw() { return m_pInterface; }
GetInterfacePtr()221   Interface*& GetInterfacePtr() throw() { return m_pInterface; }
throw()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   }
throw()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   }
throw()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   }
GetActiveObject(const CLSID & rclsid)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   }
GetActiveObject(LPCWSTR clsidString)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   }
GetActiveObject(LPCSTR clsidStringA)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   }
QueryInterface(const IID & iid,_InterfaceType * & p)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   }
QueryInterface(const IID & iid,_InterfaceType ** p)300   template<typename _InterfaceType> HRESULT QueryInterface(const IID& iid,_InterfaceType **p) throw() { return QueryInterface(iid,*p); }
301 private:
302   Interface *m_pInterface;
_Release()303   void _Release() throw() {
304     if(m_pInterface!=NULL) m_pInterface->Release();
305   }
_AddRef()306   void _AddRef() throw() {
307     if(m_pInterface!=NULL) m_pInterface->AddRef();
308   }
_QueryInterface(_InterfacePtr p)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   }
_CompareUnknown(_InterfacePtr p)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   }
QueryStdInterfaces(const _variant_t & varSrc)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 
356 template<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 
361 template<typename _Interface,typename _InterfacePtr> bool operator==(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p==i; }
362 
363 template<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 
368 template<typename _Interface,typename _InterfacePtr> bool operator!=(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p!=i; }
369 
370 template<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 
375 template<typename _Interface,typename _InterfacePtr> bool operator<(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p>i; }
376 
377 template<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 
382 template<typename _Interface,typename _InterfacePtr> bool operator>(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p<i; }
383 
384 template<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 
389 template<typename _Interface,typename _InterfacePtr> bool operator<=(_Interface *i,_com_ptr_t<_InterfacePtr> &p) { return p>=i; }
390 
391 template<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 
396 template<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