VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/HostVideoInputDeviceImpl.cpp@ 92154

Last change on this file since 92154 was 91514, checked in by vboxsync, 3 years ago

Main: bugref:9790 - Update the workaround for Clang nothrow/PPFN
issue. It was not fixed in 13.0 so drop that arm of the test. While
here, don't repeat the test two times in one file (though each file is
still on its own).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.2 KB
Line 
1/* $Id: HostVideoInputDeviceImpl.cpp 91514 2021-10-01 13:46:42Z vboxsync $ */
2/** @file
3 * Host video capture device implementation.
4 */
5
6/*
7 * Copyright (C) 2013-2020 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#define LOG_GROUP LOG_GROUP_MAIN_HOSTVIDEOINPUTDEVICE
19#include "HostVideoInputDeviceImpl.h"
20#include "LoggingNew.h"
21#include "VirtualBoxImpl.h"
22#ifdef VBOX_WITH_EXTPACK
23# include "ExtPackManagerImpl.h"
24#endif
25
26#include <iprt/err.h>
27#include <iprt/ldr.h>
28#include <iprt/path.h>
29
30#include <VBox/sup.h>
31
32/*
33 * HostVideoInputDevice implementation.
34 */
35DEFINE_EMPTY_CTOR_DTOR(HostVideoInputDevice)
36
37HRESULT HostVideoInputDevice::FinalConstruct()
38{
39 return BaseFinalConstruct();
40}
41
42void HostVideoInputDevice::FinalRelease()
43{
44 uninit();
45
46 BaseFinalRelease();
47}
48
49/*
50 * Initializes the instance.
51 */
52HRESULT HostVideoInputDevice::init(const com::Utf8Str &name, const com::Utf8Str &path, const com::Utf8Str &alias)
53{
54 LogFlowThisFunc(("\n"));
55
56 /* Enclose the state transition NotReady->InInit->Ready */
57 AutoInitSpan autoInitSpan(this);
58 AssertReturn(autoInitSpan.isOk(), E_FAIL);
59
60 m.name = name;
61 m.path = path;
62 m.alias = alias;
63
64 /* Confirm a successful initialization */
65 autoInitSpan.setSucceeded();
66
67 return S_OK;
68}
69
70/*
71 * Uninitializes the instance.
72 * Called either from FinalRelease() or by the parent when it gets destroyed.
73 */
74void HostVideoInputDevice::uninit()
75{
76 LogFlowThisFunc(("\n"));
77
78 /* Enclose the state transition Ready->InUninit->NotReady */
79 AutoUninitSpan autoUninitSpan(this);
80 if (autoUninitSpan.uninitDone())
81 return;
82
83 m.name.setNull();
84 m.path.setNull();
85 m.alias.setNull();
86}
87
88static HRESULT hostVideoInputDeviceAdd(HostVideoInputDeviceList *pList,
89 const com::Utf8Str &name,
90 const com::Utf8Str &path,
91 const com::Utf8Str &alias)
92{
93 ComObjPtr<HostVideoInputDevice> obj;
94 HRESULT hr = obj.createObject();
95 if (SUCCEEDED(hr))
96 {
97 hr = obj->init(name, path, alias);
98 if (SUCCEEDED(hr))
99 pList->push_back(obj);
100 }
101 return hr;
102}
103
104static DECLCALLBACK(int) hostWebcamAdd(void *pvUser,
105 const char *pszName,
106 const char *pszPath,
107 const char *pszAlias,
108 uint64_t *pu64Result)
109{
110 HostVideoInputDeviceList *pList = (HostVideoInputDeviceList *)pvUser;
111 HRESULT hr = hostVideoInputDeviceAdd(pList, pszName, pszPath, pszAlias);
112 if (FAILED(hr))
113 {
114 *pu64Result = (uint64_t)hr;
115 return VERR_NOT_SUPPORTED;
116 }
117 return VINF_SUCCESS;
118}
119
120/** @todo These typedefs must be in a header. */
121typedef DECLCALLBACKTYPE(int, FNVBOXHOSTWEBCAMADD,(void *pvUser,
122 const char *pszName,
123 const char *pszPath,
124 const char *pszAlias,
125 uint64_t *pu64Result));
126typedef FNVBOXHOSTWEBCAMADD *PFNVBOXHOSTWEBCAMADD;
127
128typedef DECLCALLBACKTYPE(int, FNVBOXHOSTWEBCAMLIST,(PFNVBOXHOSTWEBCAMADD pfnWebcamAdd,
129 void *pvUser,
130 uint64_t *pu64WebcamAddResult));
131typedef FNVBOXHOSTWEBCAMLIST *PFNVBOXHOSTWEBCAMLIST;
132
133
134/*
135 * Work around clang being unhappy about PFNVBOXHOSTWEBCAMLIST
136 * ("exception specifications are not allowed beyond a single level of
137 * indirection"). The original comment for 13.0 check said: "assuming
138 * this issue will be fixed eventually". Well, 13.0 is now out, and
139 * it was not.
140 */
141#define CLANG_EXCEPTION_SPEC_HACK (RT_CLANG_PREREQ(11, 0) /* && !RT_CLANG_PREREQ(13, 0) */)
142
143#if CLANG_EXCEPTION_SPEC_HACK
144static int loadHostWebcamLibrary(const char *pszPath, RTLDRMOD *phmod, void **ppfn)
145#else
146static int loadHostWebcamLibrary(const char *pszPath, RTLDRMOD *phmod, PFNVBOXHOSTWEBCAMLIST *ppfn)
147#endif
148{
149 int rc;
150 if (RTPathHavePath(pszPath))
151 {
152 RTLDRMOD hmod = NIL_RTLDRMOD;
153 RTERRINFOSTATIC ErrInfo;
154 rc = SUPR3HardenedLdrLoadPlugIn(pszPath, &hmod, RTErrInfoInitStatic(&ErrInfo));
155 if (RT_SUCCESS(rc))
156 {
157 static const char s_szSymbol[] = "VBoxHostWebcamList";
158 rc = RTLdrGetSymbol(hmod, s_szSymbol, (void **)ppfn);
159 if (RT_SUCCESS(rc))
160 *phmod = hmod;
161 else
162 {
163 if (rc != VERR_SYMBOL_NOT_FOUND)
164 LogRel(("Resolving symbol '%s': %Rrc\n", s_szSymbol, rc));
165 RTLdrClose(hmod);
166 hmod = NIL_RTLDRMOD;
167 }
168 }
169 else
170 {
171 LogRel(("Loading the library '%s': %Rrc\n", pszPath, rc));
172 if (RTErrInfoIsSet(&ErrInfo.Core))
173 LogRel((" %s\n", ErrInfo.Core.pszMsg));
174 }
175 }
176 else
177 {
178 LogRel(("Loading the library '%s': No path! Refusing to try loading it!\n", pszPath));
179 rc = VERR_INVALID_PARAMETER;
180 }
181 return rc;
182}
183
184
185static HRESULT fillDeviceList(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
186{
187 HRESULT hr;
188 Utf8Str strLibrary;
189
190#ifdef VBOX_WITH_EXTPACK
191 ExtPackManager *pExtPackMgr = pVirtualBox->i_getExtPackManager();
192 hr = pExtPackMgr->i_getLibraryPathForExtPack("VBoxHostWebcam", ORACLE_PUEL_EXTPACK_NAME, &strLibrary);
193#else
194 hr = E_NOTIMPL;
195#endif
196
197 if (SUCCEEDED(hr))
198 {
199 PFNVBOXHOSTWEBCAMLIST pfn = NULL;
200 RTLDRMOD hmod = NIL_RTLDRMOD;
201#if CLANG_EXCEPTION_SPEC_HACK
202 int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, (void **)&pfn);
203#else
204 int vrc = loadHostWebcamLibrary(strLibrary.c_str(), &hmod, &pfn);
205#endif
206
207 LogRel(("Load [%s] vrc=%Rrc\n", strLibrary.c_str(), vrc));
208
209 if (RT_SUCCESS(vrc))
210 {
211 uint64_t u64Result = S_OK;
212 vrc = pfn(hostWebcamAdd, pList, &u64Result);
213 Log(("VBoxHostWebcamList vrc %Rrc, result 0x%08RX64\n", vrc, u64Result));
214 if (RT_FAILURE(vrc))
215 {
216 hr = (HRESULT)u64Result;
217 }
218
219 RTLdrClose(hmod);
220 hmod = NIL_RTLDRMOD;
221 }
222
223 if (SUCCEEDED(hr))
224 {
225 if (RT_FAILURE(vrc))
226 hr = pVirtualBox->setErrorBoth(VBOX_E_IPRT_ERROR, vrc,
227 HostVideoInputDevice::tr("Failed to get webcam list: %Rrc"), vrc);
228 }
229 }
230
231 return hr;
232}
233
234/* static */ HRESULT HostVideoInputDevice::queryHostDevices(VirtualBox *pVirtualBox, HostVideoInputDeviceList *pList)
235{
236 HRESULT hr = fillDeviceList(pVirtualBox, pList);
237
238 if (FAILED(hr))
239 {
240 pList->clear();
241 }
242
243 return hr;
244}
245
246/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use