OLD | NEW |
| (Empty) |
1 // Copyright 2007-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 // Defines SharedMemoryProxy to encapsulate marshaling and unmarshaling of | |
17 // IGoogleUpdate3 and other interface pointers across process boundaries. | |
18 // | |
19 // TODO(omaha): seems possible to make it general purpose and move it to common. | |
20 #ifndef OMAHA_GOOPDATE_GOOGLE_UPDATE_PROXY_H__ | |
21 #define OMAHA_GOOPDATE_GOOGLE_UPDATE_PROXY_H__ | |
22 | |
23 #include <atlbase.h> | |
24 #include <atlsecurity.h> | |
25 #include "base/basictypes.h" | |
26 #include "omaha/base/debug.h" | |
27 #include "omaha/base/error.h" | |
28 #include "omaha/base/logging.h" | |
29 #include "omaha/base/scoped_any.h" | |
30 #include "omaha/base/shared_memory_ptr.h" | |
31 #include "omaha/base/utils.h" | |
32 #include "omaha/base/vistautil.h" | |
33 | |
34 namespace omaha { | |
35 | |
36 // Constants | |
37 const size_t kMaxSizeInterfaceMarshalData = 256; | |
38 const TCHAR* const kBrowserHttpRequestShareName = _T("IBrowserRequest2_"); | |
39 | |
40 struct InterfaceMarshalData { | |
41 void InitializeSharedData(const CString&) { | |
42 SetZero(data_); | |
43 size_ = 0; | |
44 } | |
45 size_t size_; | |
46 uint8 data_[kMaxSizeInterfaceMarshalData]; | |
47 }; | |
48 | |
49 class SharedMemoryAttributes { | |
50 public: | |
51 SharedMemoryAttributes(const TCHAR* shared_memory_name, | |
52 const CSecurityDesc& security_attributes) | |
53 : shared_memory_name_(shared_memory_name), | |
54 security_attributes_(security_attributes) { | |
55 } | |
56 const CString& GetSharedMemoryName() { return shared_memory_name_; } | |
57 LPSECURITY_ATTRIBUTES GetSecurityAttributes() { | |
58 return &security_attributes_; | |
59 } | |
60 | |
61 private: | |
62 CString shared_memory_name_; | |
63 CSecurityAttributes security_attributes_; | |
64 DISALLOW_EVIL_CONSTRUCTORS(SharedMemoryAttributes); | |
65 }; | |
66 | |
67 extern SharedMemoryAttributes low_integrity_attributes; | |
68 extern SharedMemoryAttributes high_integrity_attributes; | |
69 | |
70 template <typename InterfaceType, typename LockType> | |
71 class SharedMemoryProxy { | |
72 public: | |
73 SharedMemoryProxy(bool read_only, SharedMemoryAttributes* attributes) | |
74 : shared_memory_ptr_(attributes->GetSharedMemoryName(), | |
75 attributes->GetSecurityAttributes(), | |
76 NULL, | |
77 read_only) { | |
78 CORE_LOG(L3, (_T("[SharedMemoryProxy::SharedMemoryProxy]"))); | |
79 } | |
80 | |
81 ~SharedMemoryProxy() { | |
82 CORE_LOG(L3, (_T("[SharedMemoryProxy::~SharedMemoryProxy]"))); | |
83 } | |
84 | |
85 HRESULT GetObject(InterfaceType** interface_ptr) { | |
86 ASSERT1(interface_ptr); | |
87 ASSERT1(*interface_ptr == NULL); | |
88 | |
89 CORE_LOG(L3, (_T("[SharedMemoryProxy::GetObject]"))); | |
90 | |
91 return UnmarshalInterface(interface_ptr); | |
92 } | |
93 | |
94 HRESULT RegisterObject(InterfaceType* interface_ptr) { | |
95 ASSERT1(interface_ptr); | |
96 CORE_LOG(L3, (_T("[SharedMemoryProxy::RegisterObject]"))); | |
97 | |
98 return MarshalInterface(interface_ptr); | |
99 } | |
100 | |
101 HRESULT RevokeObject() { | |
102 CORE_LOG(L3, (_T("[SharedMemoryProxy::RevokeObject]"))); | |
103 | |
104 if (!shared_memory_ptr_) { | |
105 OPT_LOG(LEVEL_ERROR, (_T("[Shared memory ptr error]"))); | |
106 return GOOPDATE_E_INVALID_SHARED_MEMORY_PTR; | |
107 } | |
108 | |
109 shared_memory_ptr_->size_ = 0; | |
110 SetZero(shared_memory_ptr_->data_); | |
111 | |
112 return S_OK; | |
113 } | |
114 | |
115 private: | |
116 // Helpers. | |
117 HRESULT MarshalInterface(InterfaceType* interface_ptr) { | |
118 CORE_LOG(L3, (_T("[SharedMemoryProxy::MarshalInterface]"))); | |
119 | |
120 if (!shared_memory_ptr_) { | |
121 OPT_LOG(LEVEL_ERROR, (_T("[Shared memory ptr error]"))); | |
122 return GOOPDATE_E_INVALID_SHARED_MEMORY_PTR; | |
123 } | |
124 | |
125 // Marshal the interface. | |
126 scoped_hglobal hglobal(::GlobalAlloc(GHND, 0)); | |
127 if (!valid(hglobal)) { | |
128 OPT_LOG(LEVEL_ERROR, (_T("[GlobalAlloc failed]"))); | |
129 return E_OUTOFMEMORY; | |
130 } | |
131 | |
132 CComPtr<IStream> stream; | |
133 HRESULT hr = ::CreateStreamOnHGlobal(get(hglobal), false, &stream); | |
134 if (FAILED(hr)) { | |
135 OPT_LOG(LEVEL_ERROR, (_T("[CreateStreamOnHGlobal failed][0x%08x]"), hr)); | |
136 return hr; | |
137 } | |
138 | |
139 // MSHLFLAGS_TABLEWEAK results in CO_E_OBJNOTREG if unmarshaling multiple | |
140 // times, so using MSHLFLAGS_TABLESTRONG. | |
141 hr = ::CoMarshalInterface(stream, | |
142 __uuidof(InterfaceType), | |
143 interface_ptr, | |
144 MSHCTX_LOCAL, | |
145 NULL, | |
146 MSHLFLAGS_TABLESTRONG); | |
147 if (FAILED(hr)) { | |
148 OPT_LOG(LEVEL_ERROR, (_T("[CoMarshalInterface failed][0x%08x]"), hr)); | |
149 return hr; | |
150 } | |
151 | |
152 // Copy out the marshaled data. | |
153 STATSTG stat = {0}; | |
154 hr = stream->Stat(&stat, STATFLAG_NONAME); | |
155 if (FAILED(hr)) { | |
156 OPT_LOG(LEVEL_ERROR, (_T("[IStream::Stat failed][0x%08x]"), hr)); | |
157 return hr; | |
158 } | |
159 int64 size = static_cast<int64>(stat.cbSize.QuadPart); | |
160 if (!size || size > kMaxSizeInterfaceMarshalData) { | |
161 OPT_LOG(LEVEL_ERROR, (_T("[Bad size][%I64d]"), size)); | |
162 return GOOPDATE_E_INVALID_INTERFACE_MARSHAL_SIZE; | |
163 } | |
164 | |
165 byte* data = reinterpret_cast<byte*>(::GlobalLock(get(hglobal))); | |
166 if (!data) { | |
167 return HRESULTFromLastError(); | |
168 } | |
169 memcpy(shared_memory_ptr_->data_, data, stat.cbSize.LowPart); | |
170 shared_memory_ptr_->size_ = stat.cbSize.LowPart; | |
171 | |
172 ::GlobalUnlock(get(hglobal)); | |
173 | |
174 return S_OK; | |
175 } | |
176 | |
177 HRESULT UnmarshalInterface(InterfaceType** interface_ptr) { | |
178 CORE_LOG(L3, (_T("[SharedMemoryProxy::UnmarshalInterface]"))); | |
179 | |
180 if (!shared_memory_ptr_) { | |
181 OPT_LOG(LEVEL_ERROR, (_T("[Shared memory ptr error]"))); | |
182 return GOOPDATE_E_INVALID_SHARED_MEMORY_PTR; | |
183 } | |
184 | |
185 size_t size = shared_memory_ptr_->size_; | |
186 if (!size || size > kMaxSizeInterfaceMarshalData) { | |
187 CORE_LOG(LEVEL_ERROR, (_T("[bad size][%d]"), size)); | |
188 return GOOPDATE_E_INVALID_INTERFACE_MARSHAL_SIZE; | |
189 } | |
190 | |
191 // Unmarshal the interface. | |
192 scoped_hglobal hglobal(::GlobalAlloc(GPTR, size)); | |
193 if (!valid(hglobal)) { | |
194 OPT_LOG(LEVEL_ERROR, (_T("[GlobalAlloc failed]"))); | |
195 return E_OUTOFMEMORY; | |
196 } | |
197 memcpy(get(hglobal), shared_memory_ptr_->data_, size); | |
198 | |
199 CComPtr<IStream> stream; | |
200 HRESULT hr = ::CreateStreamOnHGlobal(get(hglobal), false, &stream); | |
201 if (FAILED(hr)) { | |
202 OPT_LOG(LEVEL_ERROR, (_T("[CreateStreamOnHGlobal failed][0x%08x]"), hr)); | |
203 return hr; | |
204 } | |
205 | |
206 hr = ::CoUnmarshalInterface(stream, | |
207 __uuidof(InterfaceType), | |
208 reinterpret_cast<void **>(interface_ptr)); | |
209 if (FAILED(hr)) { | |
210 OPT_LOG(LEVEL_ERROR, (_T("[CoUnmarshalInterface failed][0x%08x]"), hr)); | |
211 return hr; | |
212 } | |
213 | |
214 return S_OK; | |
215 } | |
216 | |
217 SharedMemoryPtr<LockType, InterfaceMarshalData> shared_memory_ptr_; | |
218 DISALLOW_EVIL_CONSTRUCTORS(SharedMemoryProxy); | |
219 }; | |
220 | |
221 } // namespace omaha | |
222 | |
223 #endif // OMAHA_GOOPDATE_GOOGLE_UPDATE_PROXY_H__ | |
224 | |
OLD | NEW |