VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/win/RpcChannelHook.cpp@ 72353

Last change on this file since 72353 was 71719, checked in by vboxsync, 7 years ago

RpcChannelHook.cpp: @todo wrt reliablity.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 6.6 KB
Line 
1/* $Id: RpcChannelHook.cpp 71719 2018-04-06 18:48:26Z vboxsync $ */
2/** @file
3* VBox Global COM Class implementation.
4*/
5
6/*
7 * Copyright (C) 2017-2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19#include <iprt\assert.h>
20#include <iprt\process.h>
21#include <iprt\string.h>
22#include <iprt/asm.h>
23#include "Logging.h"
24#include <VBox/com/VirtualBox.h>
25
26#include <string>
27
28#include "VirtualBox.h"
29#include "RpcChannelHook.h"
30
31#ifdef RT_OS_WINDOWS
32
33volatile bool CRpcChannelHook::s_fChannelRegistered = false;
34volatile bool CRpcChannelHook::s_fVBpoxSDSCalledOnce = false;
35CRpcChannelHook CRpcChannelHook::s_RpcChannelHook;
36
37
38/*
39 * RpcChannelHook IUnknown interface implementation.
40 */
41
42STDMETHODIMP CRpcChannelHook::QueryInterface(REFIID riid, void **ppv)
43{
44 if (riid == IID_IUnknown)
45 {
46 *ppv = (IUnknown*)this;
47 }
48 else if (riid == IID_IChannelHook)
49 {
50 *ppv = (IChannelHook*)this;
51 }
52 else
53 {
54 *ppv = 0;
55 return E_NOINTERFACE;
56 }
57 this->AddRef();
58 return S_OK;
59}
60
61STDMETHODIMP_(ULONG) CRpcChannelHook::AddRef(void)
62{
63 return 2;
64}
65
66STDMETHODIMP_(ULONG) CRpcChannelHook::Release(void)
67{
68 return 1;
69}
70
71
72/**
73 * This is a function that we can call from non-C++ proxy stub code.
74 *
75 * @note Warning! function is not thread safe!
76 * @todo Consider using RTONCE to serialize this (though it's likely unncessary
77 * due to COM).
78 *
79 * @todo r=bird: Failure here must be fatal to VBoxProxyStub loading, or we can
80 * kiss the reliablity of VBoxSVC good bye!
81 */
82void SetupClientRpcChannelHook(void)
83{
84 // register single hook only
85 /** @todo r=bird: This is called from DllMain/AttachProcess, so it should
86 * only happen once. OTOH, do we need to do anything on detach? */
87 if (!CRpcChannelHook::IsChannelHookRegistered())
88 {
89 HRESULT hr = CoRegisterChannelHook(RPC_CHANNEL_EXTENSION_GUID, &CRpcChannelHook::s_RpcChannelHook);
90 NOREF(hr);
91 Assert(SUCCEEDED(hr));
92 CRpcChannelHook::RegisterChannelHook();
93 LogFunc(("Registered RPC client channel hook \n"));
94 }
95}
96
97
98/*
99 * Internal methods.
100 */
101
102bool CRpcChannelHook::IsChannelHookRegistered()
103{
104 return ASMAtomicReadBool(&s_fChannelRegistered);
105}
106
107
108void CRpcChannelHook::RegisterChannelHook()
109{
110 ASMAtomicWriteBool(&s_fChannelRegistered, true);
111}
112
113/* RpcChannelHook IChannelHook interface implementation.*/
114
115
116STDMETHODIMP_(void) CRpcChannelHook::ClientGetSize(REFGUID uExtent, REFIID riid, ULONG *pDataSize)
117{
118 NOREF(riid);
119 Assert(uExtent == m_ChannelHookID);
120 Assert(pDataSize);
121 if (uExtent == m_ChannelHookID)
122 {
123 if (pDataSize)
124 {
125 *pDataSize = 0;
126 }
127 }
128}
129
130/**
131 * This is callback of RPC channel hook called on COM client when COM method call
132 * finished on server and response returned.
133 * We use it to catch a moment when a new VirtualBox object sucessfully instantiated.
134 * This callback is called in client process - VirtualBox.exe, VBoxManage or custom client
135 * If it happend we register new API client in VBoxSDS.
136 * Parameters:
137 * @param uExtent Unique ID of our RPC channel.
138 * @param riid Interface ID of called server interface (IVirtualBox
139 * in our case).
140 * @param cbDataBuffer ???????????????????
141 * @param pDataBuffer NULL, such as we have nothing to transfer from
142 * server side.
143 * @param lDataRep ???????????
144 * @param hrFault result of called COM server method.
145 */
146STDMETHODIMP_(void) CRpcChannelHook::ClientNotify(REFGUID uExtent, REFIID riid, ULONG cbDataSize, void *pDataBuffer,
147 DWORD lDataRep, HRESULT hrFault)
148{
149 NOREF(cbDataSize);
150 NOREF(pDataBuffer);
151 NOREF(lDataRep);
152
153 /*
154 * Check that it created VirtualBox and this is first method called on server
155 * (CreateInstance)
156 */
157 if ( riid == IID_IVirtualBox
158 && uExtent == m_ChannelHookID
159 && SUCCEEDED(hrFault)
160 && !ASMAtomicReadBool(&s_fVBpoxSDSCalledOnce) )
161 {
162 LogFunc(("Finished call of VirtualBox method\n"));
163
164 ASMAtomicWriteBool(&s_fVBpoxSDSCalledOnce, true);
165
166 /*
167 * Connect to VBoxSDS.
168 * Note: VBoxSDS can handle duplicate calls
169 */
170 ComPtr<IVirtualBoxClientList> ptrClientList;
171 HRESULT hrc = CoCreateInstance(CLSID_VirtualBoxClientList, NULL, CLSCTX_LOCAL_SERVER, IID_IVirtualBoxClientList,
172 (void **)ptrClientList.asOutParam());
173 if (SUCCEEDED(hrc))
174 {
175 RTPROCESS pid = RTProcSelf();
176 hrc = ptrClientList->RegisterClient(pid);
177 if (SUCCEEDED(hrc))
178 LogFunc(("Called VBoxSDS RegisterClient() : hr=%Rhrf\n", hrc));
179 else
180 LogRel(("ERROR! Call to VBoxSDS::RegisterClient failed: hr=%Rhrf\n", hrc));
181 }
182 else
183 {
184 LogRel(("ERROR! Failed to connect to VBoxSDS: hr=%Rhrf\n", hrc));
185 }
186 /** @todo r=bird: Failure of any of above calls shall result in
187 * failure to get IVirtualBox! Because the alternative is that VBoxSVC
188 * will quit early on us and potentally mess up the VM. Much better
189 * to fail before its even started. */
190 }
191}
192
193STDMETHODIMP_(void) CRpcChannelHook::ClientFillBuffer(REFGUID uExtent, REFIID riid, ULONG *pDataSize, void *pDataBuffer)
194{
195 RT_NOREF(uExtent, riid, pDataSize, pDataBuffer);
196}
197
198STDMETHODIMP_(void) CRpcChannelHook::ServerGetSize(REFGUID uExtent, REFIID riid, HRESULT hrFault, ULONG *pDataSize)
199{
200 // Nothing to send to client side from server side
201 RT_NOREF(uExtent, riid, hrFault);
202 *pDataSize = 0;
203}
204
205STDMETHODIMP_(void) CRpcChannelHook::ServerNotify(REFGUID uExtent, REFIID riid, ULONG cbDataSize, void *pDataBuffer,
206 DWORD lDataRep)
207{
208 // Nothing to do on server side
209 RT_NOREF(uExtent, riid, cbDataSize, pDataBuffer, lDataRep);
210}
211
212STDMETHODIMP_(void) CRpcChannelHook::ServerFillBuffer(REFGUID uExtent, REFIID riid, ULONG *pDataSize, void *pDataBuffer,
213 HRESULT hrFault)
214{
215 // Nothing to send to client side from server side
216 RT_NOREF(uExtent, riid, pDataSize, pDataBuffer, hrFault);
217}
218
219#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette