OLD | NEW |
| (Empty) |
1 // Copyright 2009 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 // This class allows for implementing two dual interfaces, ReadOnly being a | |
17 // read-only dual interface, and ReadWrite being a read-write dual interface. | |
18 // Based on the value returned from is_read_only(), the ReadOnly or the | |
19 // ReadWrite dual interface is exposed at runtime. | |
20 // | |
21 // An ATL class needs to | |
22 // (a) derive from DualInterfaceSwitch | |
23 // | |
24 // (b) implement the is_read_only() method. For instance: | |
25 // bool is_read_only() { return is_read_only_; } | |
26 // | |
27 // (c) add entries similar to below for the dual interfaces as well as IDispatch | |
28 // to the COM map: | |
29 // BEGIN_COM_MAP(AppData) | |
30 // COM_INTERFACE_ENTRY2(IUnknown, IAppData) | |
31 // COM_INTERFACE_ENTRY_FUNC(__uuidof(IAppDataReadOnly), 0, DualInterfaceQI) | |
32 // COM_INTERFACE_ENTRY_FUNC(__uuidof(IAppData), 0, DualInterfaceQI) | |
33 // COM_INTERFACE_ENTRY_FUNC(__uuidof(IDispatch), 0, DualInterfaceQI) | |
34 // END_COM_MAP() | |
35 | |
36 #ifndef OMAHA_BASE_DUAL_INTERFACE_SWITCH_H_ | |
37 #define OMAHA_BASE_DUAL_INTERFACE_SWITCH_H_ | |
38 | |
39 #include <windows.h> | |
40 #include <atlbase.h> | |
41 #include "base/basictypes.h" | |
42 #include "omaha/base/debug.h" | |
43 | |
44 namespace omaha { | |
45 | |
46 template <class T, class ReadOnly, REFIID iid_read_only, | |
47 class ReadWrite, REFIID iid_read_write> | |
48 class ATL_NO_VTABLE DualInterfaceSwitch : public ReadOnly, | |
49 public ReadWrite { | |
50 protected: | |
51 // DualInterfaceQI gives out either the ReadOnly or ReadWrite interface | |
52 // pointer, based on the value of is_read_only() that class T implements. | |
53 // The signature of this function has to be | |
54 // HRESULT WINAPI func(void* pv, REFIID riid, LPVOID* ppv, DWORD dw); | |
55 // for it to work with COM_INTERFACE_ENTRY_FUNC. | |
56 static HRESULT WINAPI DualInterfaceQI(void* p, | |
57 REFIID riid, | |
58 LPVOID* v, | |
59 DWORD) { | |
60 // Ensure that ReadOnly and ReadWrite are derived from IDispatch. | |
61 ASSERT1(static_cast<IDispatch*>(reinterpret_cast<ReadOnly*>(1))); | |
62 ASSERT1(static_cast<IDispatch*>(reinterpret_cast<ReadWrite*>(1))); | |
63 | |
64 if (riid != iid_read_only && | |
65 riid != iid_read_write && | |
66 riid != __uuidof(IDispatch)) { | |
67 // Returning S_FALSE allows COM map processing to continue. Another entry | |
68 // in the COM map might match the interface requested. | |
69 return S_FALSE; | |
70 } | |
71 | |
72 T* t = reinterpret_cast<T*>(p); | |
73 if (t->is_read_only() && riid == iid_read_write) { | |
74 return S_FALSE; | |
75 } | |
76 | |
77 t->AddRef(); | |
78 if (t->is_read_only() || riid == iid_read_only) { | |
79 *v = static_cast<ReadOnly*>(t); | |
80 return S_OK; | |
81 } | |
82 | |
83 *v = static_cast<ReadWrite*>(t); | |
84 return S_OK; | |
85 } | |
86 }; | |
87 | |
88 } // namespace omaha | |
89 | |
90 #endif // OMAHA_BASE_DUAL_INTERFACE_SWITCH_H_ | |
OLD | NEW |