xref: /aoo41x/main/sal/inc/systools/win32/comtools.hxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #pragma once
29 
30 #include <string>
31 #include <stdexcept>
32 #if defined _MSC_VER
33 #pragma warning(push,1)
34 #endif
35 #include <objbase.h>
36 #if defined _MSC_VER
37 #pragma warning(pop)
38 #endif
39 
40 namespace sal
41 {
42 namespace systools
43 {
44     typedef int HRESULT;
45 
46     /* Simple exception class for propagating COM errors */
47     class ComError : public std::runtime_error
48     {
49     public:
50         ComError(const std::string& message, HRESULT hr) :
51             std::runtime_error(message),
52             hr_(hr)
53         {}
54 
55         HRESULT GetHresult() const
56         {
57             return hr_;
58         }
59 
60     private:
61         HRESULT hr_;
62     };
63 
64     /* A simple COM smart pointer template */
65     template <typename T>
66     class COMReference
67     {
68     public:
69         COMReference() :
70             com_ptr_(NULL)
71         {
72         }
73 
74         explicit COMReference(T* comptr) :
75             com_ptr_(comptr)
76         {
77             addRef();
78         }
79 
80         /* Explicitly controllable whether AddRef will be called or not */
81         COMReference(T* comptr, bool bAddRef) :
82             com_ptr_(comptr)
83         {
84             if (bAddRef)
85                 addRef();
86         }
87 
88         COMReference(const COMReference<T>& other) :
89             com_ptr_(other.com_ptr_)
90         {
91             addRef();
92         }
93 
94         COMReference<T>& operator=(const COMReference<T>& other)
95         {
96             if (other.com_ptr_)
97                 other.com_ptr_->AddRef();
98             release();
99             com_ptr_ = other.com_ptr_;
100             return *this;
101         }
102 
103         COMReference<T>& operator=(T* comptr)
104         {
105             release();
106             com_ptr_ = comptr;
107             addRef();
108             return *this;
109         }
110 
111         ~COMReference()
112         {
113             release();
114         }
115 
116         template<typename InterfaceType>
117         COMReference<InterfaceType> QueryInterface(REFIID iid)
118         {
119             COMReference<InterfaceType> ip;
120             HRESULT hr = E_FAIL;
121             if (com_ptr_)
122                 hr = com_ptr_->QueryInterface(iid, reinterpret_cast<LPVOID*>(&ip));
123 
124             if (FAILED(hr))
125                 throw ComError("QueryInterface failed: Interface not supported!", hr);
126 
127             return ip;
128         }
129 
130         T* operator->() const
131         {
132             return com_ptr_;
133         }
134 
135         T& operator*() const
136         {
137             return *com_ptr_;
138         }
139 
140         /* Necessary for assigning com_ptr_ from functions like
141            CoCreateInstance which require a 'void**' */
142         T** operator&()
143         {
144             release();
145             com_ptr_ = NULL;
146             return &com_ptr_;
147         }
148 
149         T* get() const
150         {
151             return com_ptr_;
152         }
153 
154         COMReference<T>& clear()
155         {
156             release();
157             com_ptr_ = NULL;
158             return *this;
159         }
160 
161         bool is() const
162         {
163             return (com_ptr_ != NULL);
164         }
165 
166     private:
167         ULONG addRef()
168         {
169             ULONG cnt = 0;
170             if (com_ptr_)
171                 cnt = com_ptr_->AddRef();
172             return cnt;
173         }
174 
175         ULONG release()
176         {
177             ULONG cnt = 0;
178             if (com_ptr_)
179                 cnt = com_ptr_->Release();
180             return cnt;
181         }
182 
183     private:
184         T* com_ptr_;
185     };
186 
187 } // systools
188 } // sal
189 
190 /* Typedefs for some popular COM interfaces */
191 typedef sal::systools::COMReference<IDataObject> IDataObjectPtr;
192 typedef sal::systools::COMReference<IStream> IStreamPtr;
193 typedef sal::systools::COMReference<IEnumFORMATETC> IEnumFORMATETCPtr;
194 
195