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 : // Declares utility functions used by the call trace client and its unit
16 : // tests.
17 :
18 : #include "syzygy/common/rpc/helpers.h"
19 :
20 : #include <windows.h>
21 :
22 : #include "base/logging.h"
23 : #include "base/win/windows_version.h"
24 : #include "syzygy/common/com_utils.h"
25 :
26 : namespace common {
27 : namespace rpc {
28 :
29 : bool CreateRpcBinding(const base::StringPiece16& protocol,
30 : const base::StringPiece16& endpoint,
31 E : handle_t* out_handle) {
32 E : DCHECK(!protocol.empty());
33 E : DCHECK(!endpoint.empty());
34 E : DCHECK(out_handle != NULL);
35 :
36 E : std::wstring protocol_temp(protocol.begin(), protocol.end());
37 E : std::wstring endpoint_temp(endpoint.begin(), endpoint.end());
38 E : RPC_WSTR string_binding = NULL;
39 :
40 : RPC_STATUS status = ::RpcStringBindingCompose(NULL, // UUID.
41 : AsRpcWstr(&protocol_temp[0]),
42 : NULL, // Address.
43 : AsRpcWstr(&endpoint_temp[0]),
44 : NULL, // Options.
45 E : &string_binding);
46 E : if (status != RPC_S_OK) {
47 i : LOG(ERROR) << "Can't compose RPC binding: " << ::common::LogWe(status)
48 : << ".";
49 i : return false;
50 : }
51 :
52 E : handle_t binding = NULL;
53 E : status = ::RpcBindingFromStringBinding(string_binding, &binding);
54 :
55 E : ignore_result(::RpcStringFree(&string_binding));
56 :
57 E : if (status != RPC_S_OK) {
58 i : LOG(ERROR) << "Can't create RPC binding: " << ::common::LogWe(status)
59 : << ".";
60 i : return false;
61 : }
62 :
63 E : *out_handle = binding;
64 E : return true;
65 E : }
66 :
67 E : base::ProcessId GetClientProcessID(handle_t binding) {
68 E : base::ProcessId result = 0;
69 E : RPC_STATUS status = 0;
70 : // RPC_CALL_ATTRIBUTES_V2 isn't available before Windows Vista.
71 E : if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
72 : // Get the RPC call attributes.
73 : static const int kVersion = 2;
74 E : RPC_CALL_ATTRIBUTES_V2 attribs = { kVersion, RPC_QUERY_CLIENT_PID };
75 E : status = ::RpcServerInqCallAttributes(binding, &attribs);
76 E : result = reinterpret_cast<base::ProcessId>(attribs.ClientPID);
77 E : } else {
78 : status = ::I_RpcBindingInqLocalClientPID(binding,
79 i : reinterpret_cast<unsigned long*>(&result));
80 : }
81 :
82 E : if (status == RPC_S_OK)
83 E : return result;
84 :
85 i : LOG(ERROR) << "Failed to query RPC call attributes: "
86 : << ::common::LogWe(status) << ".";
87 i : return 0;
88 E : }
89 :
90 : std::wstring GetInstanceString(
91 E : const base::StringPiece16& root, const base::StringPiece16& instance_id) {
92 E : std::wstring result(root.begin(), root.end());
93 E : if (!instance_id.empty()) {
94 E : result += L'-';
95 E : result.append(instance_id.begin(), instance_id.end());
96 : }
97 :
98 E : return result;
99 E : }
100 :
101 E : ScopedRpcBinding::ScopedRpcBinding() : rpc_binding_(NULL) {
102 E : }
103 :
104 E : ScopedRpcBinding::~ScopedRpcBinding() {
105 E : Close();
106 E : }
107 :
108 : bool ScopedRpcBinding::Open(const base::StringPiece16& protocol,
109 E : const base::StringPiece16& endpoint) {
110 E : if (!CreateRpcBinding(protocol, endpoint, &rpc_binding_)) {
111 i : DCHECK(rpc_binding_ == NULL);
112 i : return false;
113 : }
114 :
115 E : return true;
116 E : }
117 :
118 E : bool ScopedRpcBinding::Close() {
119 E : if (rpc_binding_ == NULL)
120 E : return true;
121 :
122 E : RPC_STATUS status = ::RpcBindingFree(&rpc_binding_);
123 E : rpc_binding_ = NULL;
124 E : if (status != RPC_S_OK)
125 i : return false;
126 :
127 E : return true;
128 E : }
129 :
130 : ScopedRpcInterfaceRegistration::ScopedRpcInterfaceRegistration(
131 : RPC_IF_HANDLE if_spec)
132 E : : if_spec_(if_spec), status_(::RpcServerRegisterIf(if_spec_, NULL, NULL)) {
133 E : if (status_ != RPC_S_OK) {
134 i : LOG(ERROR) << "Failed to register RPC interface: "
135 : << ::common::LogWe(status_) << ".";
136 : }
137 E : }
138 :
139 E : ScopedRpcInterfaceRegistration::~ScopedRpcInterfaceRegistration() {
140 E : if (status_ == RPC_S_OK) {
141 E : status_ = ::RpcServerUnregisterIf(NULL, NULL, FALSE);
142 E : if (status_ != RPC_S_OK) {
143 i : LOG(ERROR) << "Failed to unregister RPC interface: "
144 : << ::common::LogWe(status_) << ".";
145 : }
146 : }
147 E : }
148 :
149 : } // namespace rpc
150 : } // namespace common
|