xref: /trunk/main/sal/inc/systools/win32/comtools.hxx (revision 565d668c)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #pragma once
25 
26 #include <string>
27 #include <stdexcept>
28 #if defined _MSC_VER
29 #pragma warning(push,1)
30 #endif
31 #include <objbase.h>
32 #if defined _MSC_VER
33 #pragma warning(pop)
34 #endif
35 
36 namespace sal
37 {
38 namespace systools
39 {
40     typedef int HRESULT;
41 
42     /* Simple exception class for propagating COM errors */
43     class ComError : public std::runtime_error
44     {
45     public:
ComError(const std::string & message,HRESULT hr)46         ComError(const std::string& message, HRESULT hr) :
47             std::runtime_error(message),
48             hr_(hr)
49         {}
50 
GetHresult() const51         HRESULT GetHresult() const
52         {
53             return hr_;
54         }
55 
56     private:
57         HRESULT hr_;
58     };
59 
60     /* A simple COM smart pointer template */
61     template <typename T>
62     class COMReference
63     {
64     public:
COMReference()65         COMReference() :
66             com_ptr_(NULL)
67         {
68         }
69 
COMReference(T * comptr)70         explicit COMReference(T* comptr) :
71             com_ptr_(comptr)
72         {
73             addRef();
74         }
75 
76         /* Explicitly controllable whether AddRef will be called or not */
COMReference(T * comptr,bool bAddRef)77         COMReference(T* comptr, bool bAddRef) :
78             com_ptr_(comptr)
79         {
80             if (bAddRef)
81                 addRef();
82         }
83 
COMReference(const COMReference<T> & other)84         COMReference(const COMReference<T>& other) :
85             com_ptr_(other.com_ptr_)
86         {
87             addRef();
88         }
89 
operator =(const COMReference<T> & other)90         COMReference<T>& operator=(const COMReference<T>& other)
91         {
92             if (other.com_ptr_)
93                 other.com_ptr_->AddRef();
94             release();
95             com_ptr_ = other.com_ptr_;
96             return *this;
97         }
98 
operator =(T * comptr)99         COMReference<T>& operator=(T* comptr)
100         {
101             release();
102             com_ptr_ = comptr;
103             addRef();
104             return *this;
105         }
106 
~COMReference()107         ~COMReference()
108         {
109             release();
110         }
111 
112         template<typename InterfaceType>
QueryInterface(REFIID iid)113         COMReference<InterfaceType> QueryInterface(REFIID iid)
114         {
115             COMReference<InterfaceType> ip;
116             HRESULT hr = E_FAIL;
117             if (com_ptr_)
118                 hr = com_ptr_->QueryInterface(iid, reinterpret_cast<LPVOID*>(&ip));
119 
120             if (FAILED(hr))
121                 throw ComError("QueryInterface failed: Interface not supported!", hr);
122 
123             return ip;
124         }
125 
operator ->() const126         T* operator->() const
127         {
128             return com_ptr_;
129         }
130 
operator *() const131         T& operator*() const
132         {
133             return *com_ptr_;
134         }
135 
136         /* Necessary for assigning com_ptr_ from functions like
137            CoCreateInstance which require a 'void**' */
operator &()138         T** operator&()
139         {
140             release();
141             com_ptr_ = NULL;
142             return &com_ptr_;
143         }
144 
get() const145         T* get() const
146         {
147             return com_ptr_;
148         }
149 
clear()150         COMReference<T>& clear()
151         {
152             release();
153             com_ptr_ = NULL;
154             return *this;
155         }
156 
is() const157         bool is() const
158         {
159             return (com_ptr_ != NULL);
160         }
161 
162     private:
addRef()163         ULONG addRef()
164         {
165             ULONG cnt = 0;
166             if (com_ptr_)
167                 cnt = com_ptr_->AddRef();
168             return cnt;
169         }
170 
release()171         ULONG release()
172         {
173             ULONG cnt = 0;
174             if (com_ptr_)
175                 cnt = com_ptr_->Release();
176             return cnt;
177         }
178 
179     private:
180         T* com_ptr_;
181     };
182 
183 } // systools
184 } // sal
185 
186 /* Typedefs for some popular COM interfaces */
187 typedef sal::systools::COMReference<IDataObject> IDataObjectPtr;
188 typedef sal::systools::COMReference<IStream> IStreamPtr;
189 typedef sal::systools::COMReference<IEnumFORMATETC> IEnumFORMATETCPtr;
190 
191