1 : // Copyright 2012 Google Inc. All Rights Reserved.
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 : // Helper functions to wrap RPC invocations.
16 :
17 : #ifndef SYZYGY_COMMON_RPC_HELPERS_H_
18 : #define SYZYGY_COMMON_RPC_HELPERS_H_
19 :
20 : #include <rpc.h>
21 : #include <wtypes.h>
22 :
23 : #include "base/macros.h"
24 : #include "base/process/process_handle.h"
25 : #include "base/strings/string_piece.h"
26 :
27 : // TODO(rogerm): Is there directly usable stuff in base/callback.h that
28 : // might make this simpler/cleaner?
29 :
30 : namespace common {
31 : namespace rpc {
32 :
33 : // Create an RPC binding.
34 : //
35 : // @param protocol The RPC protocol to bind.
36 : // @param endpoint The endpoint/address to bind.
37 : // @param out_handle A handle to the rpc binding will be returned here.
38 : //
39 : // @returns true on success.
40 : bool CreateRpcBinding(const base::StringPiece16& protocol,
41 : const base::StringPiece16& endpoint,
42 : handle_t* out_handle);
43 :
44 : // Retrieves the PID for the RPC client process.
45 : //
46 : // @param binding An RPC binding.
47 : // @returns The client PID on success, or 0.
48 : base::ProcessId GetClientProcessID(handle_t binding);
49 :
50 : // Structure returned by RPC calls
51 : struct RpcStatus {
52 : boolean exception_occurred;
53 : boolean result;
54 :
55 E : bool succeeded() const {
56 E : return exception_occurred == FALSE && result == TRUE;
57 E : }
58 : };
59 :
60 : // Helper to invoke an RPC function taking one parameter.
61 : template<typename Func, typename T1>
62 i : RpcStatus InvokeRpc(const Func& func, const T1& p1) {
63 i : RpcStatus status = { FALSE, FALSE };
64 i : RpcTryExcept {
65 i : status.result = func(p1);
66 i : } RpcExcept(1) {
67 i : status.exception_occurred = TRUE;
68 i : } RpcEndExcept;
69 i : return status;
70 i : }
71 :
72 : // Helper to invoke an RPC function taking two parameters.
73 : template<typename Func, typename T1, typename T2>
74 i : RpcStatus InvokeRpc(const Func& func, const T1& p1, const T2& p2) {
75 i : RpcStatus status = { FALSE, FALSE };
76 i : RpcTryExcept {
77 i : status.result = func(p1, p2);
78 i : } RpcExcept(1) {
79 i : status.exception_occurred = TRUE;
80 i : } RpcEndExcept;
81 i : return status;
82 i : }
83 :
84 : // Helper to invoke an RPC function taking three parameters.
85 : template<typename Func, typename T1, typename T2, typename T3>
86 : RpcStatus InvokeRpc(const Func& func,
87 i : const T1& p1, const T2& p2, const T3& p3) {
88 i : RpcStatus status = { FALSE, FALSE };
89 i : RpcTryExcept {
90 i : status.result = func(p1, p2, p3);
91 i : } RpcExcept(1) {
92 i : status.exception_occurred = TRUE;
93 i : } RpcEndExcept;
94 i : return status;
95 i : }
96 :
97 : // Helper to invoke an RPC function taking four parameters.
98 : template<typename Func, typename T1, typename T2, typename T3, typename T4>
99 : RpcStatus InvokeRpc(const Func& func,
100 i : const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
101 i : RpcStatus status = { FALSE, FALSE };
102 i : RpcTryExcept {
103 i : status.result = func(p1, p2, p3, p4);
104 i : } RpcExcept(1) {
105 i : status.exception_occurred = TRUE;
106 i : } RpcEndExcept;
107 i : return status;
108 i : }
109 :
110 : // Helper to invoke an RPC function taking five parameters.
111 : template<typename Func,
112 : typename T1, typename T2, typename T3, typename T4, typename T5>
113 : RpcStatus InvokeRpc(const Func& func,
114 : const T1& p1, const T2& p2, const T3& p3, const T4& p4,
115 : const T5& p5) {
116 : RpcStatus status = { FALSE, FALSE };
117 : RpcTryExcept {
118 : status.result = func(p1, p2, p3, p4, p5);
119 : } RpcExcept(1) {
120 : status.exception_occurred = TRUE;
121 : } RpcEndExcept;
122 : return status;
123 : }
124 :
125 : // Helper to invoke an RPC function taking six parameters.
126 : template <typename Func,
127 : typename T1,
128 : typename T2,
129 : typename T3,
130 : typename T4,
131 : typename T5,
132 : typename T6>
133 : RpcStatus InvokeRpc(const Func& func,
134 : const T1& p1,
135 : const T2& p2,
136 : const T3& p3,
137 : const T4& p4,
138 : const T5& p5,
139 : const T6& p6) {
140 : RpcStatus status = { FALSE, FALSE };
141 : RpcTryExcept {
142 : status.result = func(p1, p2, p3, p4, p5, p6);
143 : } RpcExcept(1) {
144 : status.exception_occurred = TRUE;
145 : } RpcEndExcept;
146 : return status;
147 : }
148 :
149 : // Helper to invoke an RPC function taking seven parameters.
150 : template <typename Func,
151 : typename T1,
152 : typename T2,
153 : typename T3,
154 : typename T4,
155 : typename T5,
156 : typename T6,
157 : typename T7>
158 : RpcStatus InvokeRpc(const Func& func,
159 : const T1& p1,
160 : const T2& p2,
161 : const T3& p3,
162 : const T4& p4,
163 : const T5& p5,
164 : const T6& p6,
165 : const T7& p7) {
166 : RpcStatus status = { FALSE, FALSE };
167 : RpcTryExcept {
168 : status.result = func(p1, p2, p3, p4, p5, p6, p7);
169 : } RpcExcept(1) {
170 : status.exception_occurred = TRUE;
171 : } RpcEndExcept;
172 : return status;
173 : }
174 :
175 : // Helper to invoke an RPC function taking eight parameters.
176 : template <typename Func,
177 : typename T1,
178 : typename T2,
179 : typename T3,
180 : typename T4,
181 : typename T5,
182 : typename T6,
183 : typename T7,
184 : typename T8>
185 : RpcStatus InvokeRpc(const Func& func,
186 : const T1& p1,
187 : const T2& p2,
188 : const T3& p3,
189 : const T4& p4,
190 : const T5& p5,
191 : const T6& p6,
192 : const T7& p7,
193 i : const T8& p8) {
194 i : RpcStatus status = { FALSE, FALSE };
195 i : RpcTryExcept {
196 i : status.result = func(p1, p2, p3, p4, p5, p6, p7, p8);
197 i : } RpcExcept(1) {
198 i : status.exception_occurred = TRUE;
199 i : } RpcEndExcept;
200 i : return status;
201 i : }
202 :
203 : // A helper function to get an @p instance_id specialized version of the
204 : // given @p root string.
205 : std::wstring GetInstanceString(const base::StringPiece16& root,
206 : const base::StringPiece16& instance_id);
207 :
208 : // A helper class to manage an RPC binding handle.
209 : class ScopedRpcBinding {
210 : public:
211 : ScopedRpcBinding();
212 : ~ScopedRpcBinding();
213 :
214 : // @returns the underlying RPC handle.
215 E : handle_t Get() const { return rpc_binding_; }
216 :
217 : // Opens an RPC connection to @p endpoint using @p protocol.
218 : bool Open(const base::StringPiece16& protocol,
219 : const base::StringPiece16& endpoint);
220 :
221 : // Closes this RPC connection.
222 : bool Close();
223 :
224 : protected:
225 : // The OS level binding to the RPC layer.
226 : handle_t rpc_binding_;
227 :
228 : private:
229 : DISALLOW_COPY_AND_ASSIGN(ScopedRpcBinding);
230 : };
231 :
232 : // A helper to manage an RPC interface registration.
233 : class ScopedRpcInterfaceRegistration {
234 : public:
235 : explicit ScopedRpcInterfaceRegistration(RPC_IF_HANDLE if_spec);
236 : ~ScopedRpcInterfaceRegistration();
237 :
238 E : RPC_STATUS status() { return status_; }
239 :
240 : private:
241 : RPC_IF_HANDLE if_spec_;
242 : RPC_STATUS status_;
243 : };
244 :
245 : namespace internal {
246 :
247 : template <class T>
248 : struct dereference_pointer;
249 :
250 : template <class T>
251 : struct dereference_pointer<T*> {
252 : typedef T value;
253 : };
254 :
255 : } // namespace internal
256 :
257 : template <class T>
258 E : RPC_WSTR AsRpcWstr(T* value) {
259 : static_assert(
260 : sizeof(internal::dereference_pointer<RPC_WSTR>::value) == sizeof(T),
261 : "Type is incompatible.");
262 E : return reinterpret_cast<RPC_WSTR>(value);
263 E : }
264 :
265 : } // namespace rpc
266 : } // namespace common
267 :
268 : #endif // SYZYGY_COMMON_RPC_HELPERS_H_
|