VirtualBox

source: vbox/trunk/src/VBox/Main/src-server/USBDeviceFilterImpl.cpp

Last change on this file was 100772, checked in by vboxsync, 10 months ago

include/VBox/usbfilter.h,HostDrivers/VBoxUSB/USBFilter: IUSBDeviceFilter:
USB device interval filters don't work. bugref:10452

Main/Host,Main/USBDeviceFilter: Adding or removing global USB device
filters causes memory corruption wihch can lead to a deadlock or a SEGV
as the list of global USB device filters (llChildren) changes while
the list is being walked.

Frontends/VBoxManage: 'VBoxManage list usbfilters' doesn't display the
'Port' value of the device filter.

Frontends/VBoxManage: 'VBoxManage add usbfilter' and 'VBoxManage modify
usbfilter' both ignore the --product="Value" option.

Main/VirtualBox.xidl: Improve the IUSBDeviceFilter wording to make
things clearer in the 'VirtualBox Programming Guide and Reference Guide'
aka SDKRef.pdf.

HostDrivers/VBoxUSB/testcase/tstUSBFilter: Include a variety of USB
device filter entries which include the 'int:' prefix to fully exercise
the interval filter parsing code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 35.6 KB
RevLine 
[31891]1/* $Id: USBDeviceFilterImpl.cpp 100772 2023-08-01 17:34:48Z vboxsync $ */
2/** @file
3 * Implementation of VirtualBox COM components: USBDeviceFilter and HostUSBDeviceFilter
4 */
5
6/*
[98103]7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
[31891]8 *
[96407]9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
[31891]26 */
27
[76592]28#define LOG_GROUP LOG_GROUP_MAIN_USBDEVICEFILTER
[31891]29#include "USBDeviceFilterImpl.h"
[47376]30#include "USBDeviceFiltersImpl.h"
[31891]31#include "MachineImpl.h"
32#include "HostImpl.h"
33
34#include <iprt/cpp/utils.h>
35#include <VBox/settings.h>
36
37#include "AutoStateDep.h"
38#include "AutoCaller.h"
[76592]39#include "LoggingNew.h"
[31891]40
41////////////////////////////////////////////////////////////////////////////////
42// Internal Helpers
43////////////////////////////////////////////////////////////////////////////////
44
45/**
46 * Converts a USBFilter field into a string.
47 *
48 * (This function is also used by HostUSBDeviceFilter.)
49 *
50 * @param aFilter The filter.
51 * @param aIdx The field index.
[65088]52 * @param rstrOut The output string.
[31891]53 */
[63174]54static void i_usbFilterFieldToString(PCUSBFILTER aFilter, USBFILTERIDX aIdx, Utf8Str &rstrOut)
[31891]55{
56 const USBFILTERMATCH matchingMethod = USBFilterGetMatchingMethod(aFilter, aIdx);
57 Assert(matchingMethod != USBFILTERMATCH_INVALID);
58
59 if (USBFilterIsMethodNumeric(matchingMethod))
60 {
61 int value = USBFilterGetNum(aFilter, aIdx);
62 Assert(value >= 0 && value <= 0xffff);
63
[97890]64 rstrOut.printf("%04RX16", (uint16_t)value);
[31891]65 }
66 else if (USBFilterIsMethodString(matchingMethod))
[63174]67 rstrOut = USBFilterGetString(aFilter, aIdx);
[31891]68 else
[63174]69 rstrOut.setNull();
[31891]70}
71
72/*static*/
[49951]73const char* USBDeviceFilter::i_describeUSBFilterIdx(USBFILTERIDX aIdx)
[31891]74{
75 switch (aIdx)
76 {
[63174]77 case USBFILTERIDX_VENDOR_ID: return tr("Vendor ID");
78 case USBFILTERIDX_PRODUCT_ID: return tr("Product ID");
79 case USBFILTERIDX_DEVICE: return tr("Revision");
80 case USBFILTERIDX_MANUFACTURER_STR: return tr("Manufacturer");
81 case USBFILTERIDX_PRODUCT_STR: return tr("Product");
82 case USBFILTERIDX_SERIAL_NUMBER_STR: return tr("Serial number");
83 case USBFILTERIDX_PORT: return tr("Port number");
84 default: return "";
[31891]85 }
[63174]86 /* not reached. */
[31891]87}
88
89/**
90 * Interprets a string and assigns it to a USBFilter field.
91 *
92 * (This function is also used by HostUSBDeviceFilter.)
93 *
94 * @param aFilter The filter.
95 * @param aIdx The field index.
[65103]96 * @param aValue The input string.
[31891]97 * @param aErrStr Where to return the error string on failure.
98 *
99 * @return COM status code.
100 * @remark The idea was to have this as a static function, but tr() doesn't wanna work without a class :-/
101 */
[49951]102/*static*/ HRESULT USBDeviceFilter::i_usbFilterFieldFromString(PUSBFILTER aFilter,
103 USBFILTERIDX aIdx,
104 const Utf8Str &aValue,
105 Utf8Str &aErrStr)
[31891]106{
107 int vrc;
108 if (aValue.isEmpty())
109 vrc = USBFilterSetIgnore(aFilter, aIdx);
110 else
111 {
112 const char *pcszValue = aValue.c_str();
113 if (USBFilterIsNumericField(aIdx))
114 {
115 /* Is it a lonely number? */
116 char *pszNext;
117 uint64_t u64;
[97889]118 vrc = RTStrToUInt64Ex(pcszValue, &pszNext, 16, &u64);
[31891]119 if (RT_SUCCESS(vrc))
[61667]120 pszNext = RTStrStripL(pszNext);
[31891]121 if ( vrc == VINF_SUCCESS
122 && !*pszNext)
123 {
124 if (u64 > 0xffff)
125 {
126 // there was a bug writing out "-1" values in earlier versions, which got
127 // written as "FFFFFFFF"; make sure we don't fail on those
128 if (u64 == 0xffffffff)
129 u64 = 0xffff;
130 else
131 {
[97890]132 aErrStr.printf(tr("The %s value '%s' is too big (max 0xFFFF)"), i_describeUSBFilterIdx(aIdx), pcszValue);
[31891]133 return E_INVALIDARG;
134 }
135 }
136
137 vrc = USBFilterSetNumExact(aFilter, aIdx, (uint16_t)u64, true /* fMustBePresent */);
138 }
139 else
140 vrc = USBFilterSetNumExpression(aFilter, aIdx, pcszValue, true /* fMustBePresent */);
141 }
142 else
143 {
144 /* Any wildcard in the string? */
145 Assert(USBFilterIsStringField(aIdx));
[97890]146 if ( strchr(pcszValue, '*')
147 || strchr(pcszValue, '?')
[31891]148 /* || strchr (psz, '[') - later */
149 )
[60161]150 vrc = USBFilterSetStringPattern(aFilter, aIdx, pcszValue, true /*fMustBePresent*/);
[31891]151 else
[60159]152 vrc = USBFilterSetStringExact(aFilter, aIdx, pcszValue, true /*fMustBePresent*/, false /*fPurge*/);
[31891]153 }
154 }
155
156 if (RT_FAILURE(vrc))
157 {
158 if (vrc == VERR_INVALID_PARAMETER)
159 {
[97890]160 aErrStr.printf(tr("The %s filter expression '%s' is not valid"), i_describeUSBFilterIdx(aIdx), aValue.c_str());
[31891]161 return E_INVALIDARG;
162 }
163 if (vrc == VERR_BUFFER_OVERFLOW)
164 {
[97890]165 aErrStr.printf(tr("Insufficient expression space for the '%s' filter expression '%s'"),
166 i_describeUSBFilterIdx(aIdx), aValue.c_str());
[31891]167 return E_FAIL;
168 }
169 AssertRC(vrc);
[97890]170 aErrStr.printf(tr("Encountered unexpected status %Rrc when setting '%s' to '%s'"),
171 vrc, i_describeUSBFilterIdx(aIdx), aValue.c_str());
[31891]172 return E_FAIL;
173 }
174
175 return S_OK;
176}
177
178
179////////////////////////////////////////////////////////////////////////////////
180// USBDeviceFilter
181////////////////////////////////////////////////////////////////////////////////
182
183// constructor / destructor
184////////////////////////////////////////////////////////////////////////////////
185
186USBDeviceFilter::USBDeviceFilter()
187 : mParent(NULL),
188 mPeer(NULL)
189{
190}
191
192USBDeviceFilter::~USBDeviceFilter()
193{
194}
195
196HRESULT USBDeviceFilter::FinalConstruct()
197{
[35638]198 return BaseFinalConstruct();
[31891]199}
200
201void USBDeviceFilter::FinalRelease()
202{
203 uninit();
[35638]204 BaseFinalRelease();
[31891]205}
206
207// public initializer/uninitializer for internal purposes only
208////////////////////////////////////////////////////////////////////////////////
209
210/**
211 * Initializes the USB device filter object.
212 *
213 * @param aParent Handle of the parent object.
[58132]214 * @param data Reference filter settings.
[31891]215 */
[47376]216HRESULT USBDeviceFilter::init(USBDeviceFilters *aParent,
[31891]217 const settings::USBDeviceFilter &data)
218{
219 LogFlowThisFunc(("aParent=%p\n", aParent));
220
221 ComAssertRet(aParent && !data.strName.isEmpty(), E_INVALIDARG);
222
223 /* Enclose the state transition NotReady->InInit->Ready */
224 AutoInitSpan autoInitSpan(this);
225 AssertReturn(autoInitSpan.isOk(), E_FAIL);
226
227 unconst(mParent) = aParent;
228 /* mPeer is left null */
229
230 m_fModified = false;
231
[61667]232 bd.allocate();
233 bd->mData.strName = data.strName;
234 bd->mData.fActive = data.fActive;
235 bd->mData.ulMaskedInterfaces = 0;
[31891]236
237 /* initialize all filters to any match using null string */
[61667]238 USBFilterInit(&bd->mUSBFilter, USBFILTERTYPE_CAPTURE);
239 bd->mRemote = NULL;
[31891]240
241 mInList = false;
242
243 /* use setters for the attributes below to reuse parsing errors
244 * handling */
245
[98292]246 HRESULT hrc = i_usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, data.strVendorId);
247 if (FAILED(hrc)) return hrc;
[31891]248
[98292]249 hrc = i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, data.strProductId);
250 if (FAILED(hrc)) return hrc;
[31891]251
[98292]252 hrc = i_usbFilterFieldSetter(USBFILTERIDX_DEVICE, data.strRevision);
253 if (FAILED(hrc)) return hrc;
[31891]254
[98292]255 hrc = i_usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer);
256 if (FAILED(hrc)) return hrc;
[31891]257
[98292]258 hrc = i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_STR, data.strProduct);
259 if (FAILED(hrc)) return hrc;
[31891]260
[98292]261 hrc = i_usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber);
262 if (FAILED(hrc)) return hrc;
[31891]263
[98292]264 hrc = i_usbFilterFieldSetter(USBFILTERIDX_PORT, data.strPort);
265 if (FAILED(hrc)) return hrc;
[31891]266
[98292]267 hrc = COMSETTER(Remote)(Bstr(data.strRemote).raw());
268 if (FAILED(hrc)) return hrc;
[31891]269
[98292]270 hrc = COMSETTER(MaskedInterfaces)(data.ulMaskedInterfaces);
271 if (FAILED(hrc)) return hrc;
[31891]272
[98292]273 /* Confirm successful initialization */
274 autoInitSpan.setSucceeded();
[31891]275
[98292]276 return S_OK;
[31891]277}
278
279/**
280 * Initializes the USB device filter object (short version).
281 *
282 * @param aParent Handle of the parent object.
[65103]283 * @param aName Name of the filter.
[31891]284 */
[47376]285HRESULT USBDeviceFilter::init(USBDeviceFilters *aParent, IN_BSTR aName)
[31891]286{
287 LogFlowThisFunc(("aParent=%p\n", aParent));
288
289 ComAssertRet(aParent && aName && *aName, E_INVALIDARG);
290
291 /* Enclose the state transition NotReady->InInit->Ready */
292 AutoInitSpan autoInitSpan(this);
293 AssertReturn(autoInitSpan.isOk(), E_FAIL);
294
295 unconst(mParent) = aParent;
296 /* mPeer is left null */
297
298 m_fModified = false;
299
[61667]300 bd.allocate();
[31891]301
[61667]302 bd->mData.strName = Utf8Str(aName);
303 bd->mData.fActive = FALSE;
304 bd->mData.ulMaskedInterfaces = 0;
[31891]305
306 /* initialize all filters to any match using null string */
[61667]307 USBFilterInit(&bd->mUSBFilter, USBFILTERTYPE_CAPTURE);
308 bd->mRemote = NULL;
[31891]309
310 mInList = false;
311
312 /* Confirm successful initialization */
313 autoInitSpan.setSucceeded();
314
315 return S_OK;
316}
317
318/**
319 * Initializes the object given another object
320 * (a kind of copy constructor). This object shares data with
321 * the object passed as an argument.
322 *
[65103]323 * @param aParent Handle of the parent object.
324 * @param aThat
[31891]325 * @param aReshare
326 * When false, the original object will remain a data owner.
327 * Otherwise, data ownership will be transferred from the original
328 * object to this one.
329 *
330 * @note This object must be destroyed before the original object
331 * it shares data with is destroyed.
332 *
333 * @note Locks @a aThat object for writing if @a aReshare is @c true, or for
334 * reading if @a aReshare is false.
335 */
[61667]336HRESULT USBDeviceFilter::init(USBDeviceFilters *aParent, USBDeviceFilter *aThat,
337 bool aReshare /* = false */)
[31891]338{
339 LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n",
340 aParent, aThat, aReshare));
341
342 ComAssertRet(aParent && aThat, E_INVALIDARG);
343
344 /* Enclose the state transition NotReady->InInit->Ready */
345 AutoInitSpan autoInitSpan(this);
346 AssertReturn(autoInitSpan.isOk(), E_FAIL);
347
348 unconst(mParent) = aParent;
349
350 m_fModified = false;
351
352 /* sanity */
[61667]353 AutoCaller thatCaller(aThat);
[98262]354 AssertComRCReturnRC(thatCaller.hrc());
[31891]355
356 if (aReshare)
357 {
358 AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
359
360 unconst(aThat->mPeer) = this;
[61667]361 bd.attach(aThat->bd);
[31891]362 }
363 else
364 {
365 unconst(mPeer) = aThat;
366
367 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[61667]368 bd.share(aThat->bd);
[31891]369 }
370
371 /* the arbitrary ID field is not reset because
372 * the copy is a shadow of the original */
373
374 mInList = aThat->mInList;
375
376 /* Confirm successful initialization */
377 autoInitSpan.setSucceeded();
378
379 return S_OK;
380}
381
382/**
383 * Initializes the guest object given another guest object
384 * (a kind of copy constructor). This object makes a private copy of data
385 * of the original object passed as an argument.
386 *
387 * @note Locks @a aThat object for reading.
388 */
[61667]389HRESULT USBDeviceFilter::initCopy(USBDeviceFilters *aParent, USBDeviceFilter *aThat)
[31891]390{
391 LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
392
393 ComAssertRet(aParent && aThat, E_INVALIDARG);
394
395 /* Enclose the state transition NotReady->InInit->Ready */
396 AutoInitSpan autoInitSpan(this);
397 AssertReturn(autoInitSpan.isOk(), E_FAIL);
398
399 unconst(mParent) = aParent;
400 /* mPeer is left null */
401
402 m_fModified = false;
403
404 /* sanity */
[61667]405 AutoCaller thatCaller(aThat);
[98262]406 AssertComRCReturnRC(thatCaller.hrc());
[31891]407
408 AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
[61667]409 bd.attachCopy(aThat->bd);
[31891]410
411 /* reset the arbitrary ID field
412 * (this field is something unique that two distinct objects, even if they
413 * are deep copies of each other, should not share) */
[61667]414 bd->mId = NULL;
[31891]415
416 mInList = aThat->mInList;
417
418 /* Confirm successful initialization */
419 autoInitSpan.setSucceeded();
420
421 return S_OK;
422}
423
424/**
425 * Uninitializes the instance and sets the ready flag to FALSE.
426 * Called either from FinalRelease() or by the parent when it gets destroyed.
427 */
428void USBDeviceFilter::uninit()
429{
430 LogFlowThisFunc(("\n"));
431
432 /* Enclose the state transition Ready->InUninit->NotReady */
433 AutoUninitSpan autoUninitSpan(this);
434 if (autoUninitSpan.uninitDone())
435 return;
436
437 mInList = false;
438
[61667]439 bd.free();
[31891]440
441 unconst(mPeer) = NULL;
442 unconst(mParent) = NULL;
443}
444
445
446// IUSBDeviceFilter properties
447////////////////////////////////////////////////////////////////////////////////
448
[49951]449HRESULT USBDeviceFilter::getName(com::Utf8Str &aName)
[31891]450{
451 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
452
[97890]453 return aName.assignEx(bd->mData.strName);
[31891]454}
455
[49951]456HRESULT USBDeviceFilter::setName(const com::Utf8Str &aName)
[31891]457{
458 /* the machine needs to be mutable */
[54971]459 AutoMutableOrSavedOrRunningStateDependency adep(mParent->i_getMachine());
[98262]460 if (FAILED(adep.hrc())) return adep.hrc();
[31891]461
462 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
463
[61667]464 if (bd->mData.strName != aName)
[31891]465 {
466 m_fModified = true;
[49951]467 ComObjPtr<Machine> pMachine = mParent->i_getMachine();
[31891]468
[61667]469 bd.backup();
470 bd->mData.strName = aName;
[31891]471
472 // leave the lock before informing callbacks
473 alock.release();
474
475 AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
[51498]476 pMachine->i_setModified(Machine::IsModified_USB);
[31891]477 mlock.release();
478
[49951]479 return mParent->i_onDeviceFilterChange(this);
[31891]480 }
481
482 return S_OK;
483}
484
[49951]485HRESULT USBDeviceFilter::getActive(BOOL *aActive)
[31891]486{
487 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
488
[61667]489 *aActive = bd->mData.fActive;
[31891]490
491 return S_OK;
492}
493
[49951]494HRESULT USBDeviceFilter::setActive(const BOOL aActive)
[31891]495{
496 /* the machine needs to be mutable */
[54971]497 AutoMutableOrSavedOrRunningStateDependency adep(mParent->i_getMachine());
[98262]498 if (FAILED(adep.hrc())) return adep.hrc();
[31891]499
500 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
501
[61667]502 if (bd->mData.fActive != RT_BOOL(aActive))
[31891]503 {
504 m_fModified = true;
[49951]505 ComObjPtr<Machine> pMachine = mParent->i_getMachine();
[31891]506
[61667]507 bd.backup();
508 bd->mData.fActive = RT_BOOL(aActive);
[31891]509
510 // leave the lock before informing callbacks
511 alock.release();
512
513 AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
[51498]514 pMachine->i_setModified(Machine::IsModified_USB);
[31891]515 mlock.release();
516
[49951]517 return mParent->i_onDeviceFilterChange(this, TRUE /* aActiveChanged */);
[31891]518 }
519
520 return S_OK;
521}
522
[49951]523HRESULT USBDeviceFilter::getVendorId(com::Utf8Str &aVendorId)
[31891]524{
[49951]525 return i_usbFilterFieldGetter(USBFILTERIDX_VENDOR_ID, aVendorId);
[31891]526}
527
[49951]528HRESULT USBDeviceFilter::setVendorId(const com::Utf8Str &aVendorId)
[31891]529{
[49961]530 return i_usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, aVendorId);
[31891]531}
532
[49951]533HRESULT USBDeviceFilter::getProductId(com::Utf8Str &aProductId)
[31891]534{
[49951]535 return i_usbFilterFieldGetter(USBFILTERIDX_PRODUCT_ID, aProductId);
[31891]536}
537
[49951]538HRESULT USBDeviceFilter::setProductId(const com::Utf8Str &aProductId)
[31891]539{
[49951]540 return i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, aProductId);
541}
[31891]542
[49951]543HRESULT USBDeviceFilter::getRevision(com::Utf8Str &aRevision)
[31891]544{
[49951]545 return i_usbFilterFieldGetter(USBFILTERIDX_DEVICE, aRevision);
[31891]546}
547
[49951]548HRESULT USBDeviceFilter::setRevision(const com::Utf8Str &aRevision)
[31891]549{
[49961]550 return i_usbFilterFieldSetter(USBFILTERIDX_DEVICE, aRevision);
[31891]551}
552
[49951]553HRESULT USBDeviceFilter::getManufacturer(com::Utf8Str &aManufacturer)
[31891]554{
[49951]555 return i_usbFilterFieldGetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
[31891]556}
557
[49951]558HRESULT USBDeviceFilter::setManufacturer(const com::Utf8Str &aManufacturer)
[31891]559{
[49961]560 return i_usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
[31891]561}
562
[49951]563HRESULT USBDeviceFilter::getProduct(com::Utf8Str &aProduct)
[31891]564{
[49951]565 return i_usbFilterFieldGetter(USBFILTERIDX_PRODUCT_STR, aProduct);
[31891]566}
567
[49951]568HRESULT USBDeviceFilter::setProduct(const com::Utf8Str &aProduct)
[31891]569{
[49961]570 return i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_STR, aProduct);
[31891]571}
572
[49951]573HRESULT USBDeviceFilter::getSerialNumber(com::Utf8Str &aSerialNumber)
[31891]574{
[49951]575 return i_usbFilterFieldGetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
[31891]576}
577
[49951]578HRESULT USBDeviceFilter::setSerialNumber(const com::Utf8Str &aSerialNumber)
[31891]579{
[49961]580 return i_usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
[31891]581}
582
[49951]583HRESULT USBDeviceFilter::getPort(com::Utf8Str &aPort)
[31891]584{
[49951]585 return i_usbFilterFieldGetter(USBFILTERIDX_PORT, aPort);
[31891]586}
587
[49951]588HRESULT USBDeviceFilter::setPort(const com::Utf8Str &aPort)
[31891]589{
[49961]590 return i_usbFilterFieldSetter(USBFILTERIDX_PORT, aPort);
[31891]591}
592
[49951]593
594HRESULT USBDeviceFilter::getRemote(com::Utf8Str &aRemote)
[31891]595{
596 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
597
[61667]598 aRemote = bd->mRemote.string();
[31891]599
600 return S_OK;
601}
602
[49951]603HRESULT USBDeviceFilter::setRemote(const com::Utf8Str &aRemote)
[31891]604{
605 /* the machine needs to be mutable */
[54971]606 AutoMutableOrSavedOrRunningStateDependency adep(mParent->i_getMachine());
[98262]607 if (FAILED(adep.hrc())) return adep.hrc();
[31891]608 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
[49951]609 Bstr bRemote = Bstr(aRemote).raw();
[31891]610
[61667]611 if (bd->mRemote.string() != bRemote)
[31891]612 {
[61667]613 BackupableUSBDeviceFilterData::BOOLFilter flt = bRemote;
[31891]614 ComAssertRet(!flt.isNull(), E_FAIL);
615 if (!flt.isValid())
616 return setError(E_INVALIDARG,
[50472]617 tr("Remote state filter string '%s' is not valid (error at position %d)"),
618 aRemote.c_str(), flt.errorPosition() + 1);
[31891]619
620 m_fModified = true;
[49951]621 ComObjPtr<Machine> pMachine = mParent->i_getMachine();
[31891]622
[61667]623 bd.backup();
624 bd->mRemote = flt;
[31891]625
626 // leave the lock before informing callbacks
627 alock.release();
628
629 AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
[51498]630 pMachine->i_setModified(Machine::IsModified_USB);
[31891]631 mlock.release();
632
[49951]633 return mParent->i_onDeviceFilterChange(this);
[31891]634 }
635 return S_OK;
636}
637
[49951]638
639HRESULT USBDeviceFilter::getMaskedInterfaces(ULONG *aMaskedIfs)
[31891]640{
641 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
642
[61667]643 *aMaskedIfs = bd->mData.ulMaskedInterfaces;
[31891]644
645 return S_OK;
646}
647
[49951]648HRESULT USBDeviceFilter::setMaskedInterfaces(ULONG aMaskedIfs)
[31891]649{
650 /* the machine needs to be mutable */
[54971]651 AutoMutableOrSavedOrRunningStateDependency adep(mParent->i_getMachine());
[98262]652 if (FAILED(adep.hrc())) return adep.hrc();
[31891]653
654 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
655
[61667]656 if (bd->mData.ulMaskedInterfaces != aMaskedIfs)
[31891]657 {
658 m_fModified = true;
[49951]659 ComObjPtr<Machine> pMachine = mParent->i_getMachine();
[31891]660
[61667]661 bd.backup();
662 bd->mData.ulMaskedInterfaces = aMaskedIfs;
[31891]663 // leave the lock before informing callbacks
664 alock.release();
665
666 AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
[51498]667 pMachine->i_setModified(Machine::IsModified_USB);
[31891]668 mlock.release();
669
[49951]670 return mParent->i_onDeviceFilterChange(this);
[31891]671 }
672
673 return S_OK;
674}
675
676// public methods only for internal purposes
677////////////////////////////////////////////////////////////////////////////////
678
[49951]679bool USBDeviceFilter::i_isModified()
[31891]680{
681 AutoCaller autoCaller(this);
[98262]682 AssertComRCReturn(autoCaller.hrc(), false);
[31891]683
684 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
685 return m_fModified;
686}
687
688/**
689 * @note Locks this object for writing.
690 */
[49951]691void USBDeviceFilter::i_rollback()
[31891]692{
693 /* sanity */
694 AutoCaller autoCaller(this);
[98262]695 AssertComRCReturnVoid(autoCaller.hrc());
[31891]696
697 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
698
[61667]699 bd.rollback();
[31891]700}
701
702/**
703 * @note Locks this object for writing, together with the peer object (also
704 * for writing) if there is one.
705 */
[49951]706void USBDeviceFilter::i_commit()
[31891]707{
708 /* sanity */
709 AutoCaller autoCaller(this);
[98262]710 AssertComRCReturnVoid(autoCaller.hrc());
[31891]711
712 /* sanity too */
[61667]713 AutoCaller peerCaller(mPeer);
[98262]714 AssertComRCReturnVoid(peerCaller.hrc());
[31891]715
716 /* lock both for writing since we modify both (mPeer is "master" so locked
717 * first) */
718 AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
719
[61667]720 if (bd.isBackedUp())
[31891]721 {
[61667]722 bd.commit();
[31891]723 if (mPeer)
724 {
725 /* attach new data to the peer and reshare it */
[61667]726 mPeer->bd.attach(bd);
[31891]727 }
728 }
729}
730
731/**
732 * Cancels sharing (if any) by making an independent copy of data.
733 * This operation also resets this object's peer to NULL.
734 *
735 * @note Locks this object for writing, together with the peer object
736 * represented by @a aThat (locked for reading).
737 */
738void USBDeviceFilter::unshare()
739{
740 /* sanity */
741 AutoCaller autoCaller(this);
[98262]742 AssertComRCReturnVoid(autoCaller.hrc());
[31891]743
744 /* sanity too */
[61667]745 AutoCaller peerCaller(mPeer);
[98262]746 AssertComRCReturnVoid(peerCaller.hrc());
[31891]747
748 /* peer is not modified, lock it for reading (mPeer is "master" so locked
749 * first) */
750 AutoReadLock rl(mPeer COMMA_LOCKVAL_SRC_POS);
751 AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
752
[61667]753 if (bd.isShared())
[31891]754 {
[61667]755 if (!bd.isBackedUp())
756 bd.backup();
[31891]757
[61667]758 bd.commit();
[31891]759 }
760
761 unconst(mPeer) = NULL;
762}
763
764/**
765 * Generic USB filter field getter; converts the field value to UTF-16.
766 *
767 * @param aIdx The field index.
768 * @param aStr Where to store the value.
769 *
770 * @return COM status.
771 */
[49951]772HRESULT USBDeviceFilter::i_usbFilterFieldGetter(USBFILTERIDX aIdx, com::Utf8Str &aStr)
[31891]773{
774 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
775
[61667]776 i_usbFilterFieldToString(&bd->mUSBFilter, aIdx, aStr);
[31891]777 return S_OK;
778}
779
780/**
781 * Generic USB filter field setter, expects UTF-8 input.
782 *
783 * @param aIdx The field index.
[65103]784 * @param strNew The new value.
[31891]785 *
786 * @return COM status.
787 */
[49951]788HRESULT USBDeviceFilter::i_usbFilterFieldSetter(USBFILTERIDX aIdx,
789 const com::Utf8Str &strNew)
[31891]790{
791 /* the machine needs to be mutable */
[54971]792 AutoMutableOrSavedOrRunningStateDependency adep(mParent->i_getMachine());
[98262]793 if (FAILED(adep.hrc())) return adep.hrc();
[31891]794
795 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
796
[49951]797
798 com::Utf8Str strOld;
[61667]799 i_usbFilterFieldToString(&bd->mUSBFilter, aIdx, strOld);
[31891]800 if (strOld != strNew)
801 {
802 m_fModified = true;
[49951]803 ComObjPtr<Machine> pMachine = mParent->i_getMachine();
[31891]804
[61667]805 bd.backup();
[31891]806
[49951]807 com::Utf8Str errStr;
[98292]808 HRESULT hrc = i_usbFilterFieldFromString(&bd->mUSBFilter, aIdx, strNew, errStr);
809 if (FAILED(hrc))
[31891]810 {
[61667]811 bd.rollback();
[98292]812 return setError(hrc, "%s", errStr.c_str());
[31891]813 }
814
815 // leave the lock before informing callbacks
816 alock.release();
817
818 AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
[51498]819 pMachine->i_setModified(Machine::IsModified_USB);
[31891]820 mlock.release();
821
[49951]822 return mParent->i_onDeviceFilterChange(this);
[31891]823 }
824
825 return S_OK;
826}
827
828
829////////////////////////////////////////////////////////////////////////////////
830// HostUSBDeviceFilter
831////////////////////////////////////////////////////////////////////////////////
832
833// constructor / destructor
834////////////////////////////////////////////////////////////////////////////////
835
836HostUSBDeviceFilter::HostUSBDeviceFilter()
837 : mParent(NULL)
838{
839}
840
841HostUSBDeviceFilter::~HostUSBDeviceFilter()
842{
843}
844
845
846HRESULT HostUSBDeviceFilter::FinalConstruct()
847{
848 return S_OK;
849}
850
851void HostUSBDeviceFilter::FinalRelease()
852{
853 uninit();
854}
855
856// public initializer/uninitializer for internal purposes only
857////////////////////////////////////////////////////////////////////////////////
858
859/**
860 * Initializes the USB device filter object.
861 *
862 * @param aParent Handle of the parent object.
[65120]863 * @param data Settings data.
[31891]864 */
865HRESULT HostUSBDeviceFilter::init(Host *aParent,
866 const settings::USBDeviceFilter &data)
867{
868 LogFlowThisFunc(("aParent=%p\n", aParent));
869
870 ComAssertRet(aParent && !data.strName.isEmpty(), E_INVALIDARG);
871
872 /* Enclose the state transition NotReady->InInit->Ready */
873 AutoInitSpan autoInitSpan(this);
874 AssertReturn(autoInitSpan.isOk(), E_FAIL);
875
876 unconst(mParent) = aParent;
877
878 /* register with parent early, since uninit() will unconditionally
879 * unregister on failure */
[49742]880 mParent->i_addChild(this);
[31891]881
[61667]882 bd.allocate();
883 bd->mData.strName = data.strName;
884 bd->mData.fActive = data.fActive;
885 USBFilterInit (&bd->mUSBFilter, USBFILTERTYPE_IGNORE);
886 bd->mRemote = NULL;
887 bd->mData.ulMaskedInterfaces = 0;
[31891]888
889 mInList = false;
890
891 /* use setters for the attributes below to reuse parsing errors
892 * handling */
893
[98292]894 HRESULT hrc = setAction(data.action);
895 if (FAILED(hrc)) return hrc;
[31891]896
[98292]897 hrc = i_usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, data.strVendorId);
898 if (FAILED(hrc)) return hrc;
[31891]899
[98292]900 hrc = i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, data.strProductId);
901 if (FAILED(hrc)) return hrc;
[31891]902
[98292]903 hrc = i_usbFilterFieldSetter(USBFILTERIDX_DEVICE, data.strRevision);
904 if (FAILED(hrc)) return hrc;
[31891]905
[98292]906 hrc = i_usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer);
907 if (FAILED(hrc)) return hrc;
[31891]908
[98292]909 hrc = i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, data.strProduct);
910 if (FAILED(hrc)) return hrc;
[31891]911
[98292]912 hrc = i_usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber);
913 if (FAILED(hrc)) return hrc;
[31891]914
[98292]915 hrc = i_usbFilterFieldSetter(USBFILTERIDX_PORT, data.strPort);
916 if (FAILED(hrc)) return hrc;
[31891]917
[98292]918 /* Confirm successful initialization */
919 autoInitSpan.setSucceeded();
[31891]920
[98292]921 return S_OK;
[31891]922}
923
924/**
925 * Initializes the USB device filter object (short version).
926 *
927 * @param aParent Handle of the parent object.
[65120]928 * @param aName Filter name.
[31891]929 */
[61667]930HRESULT HostUSBDeviceFilter::init(Host *aParent, IN_BSTR aName)
[31891]931{
932 LogFlowThisFunc(("aParent=%p\n", aParent));
933
934 ComAssertRet(aParent && aName && *aName, E_INVALIDARG);
935
936 /* Enclose the state transition NotReady->InInit->Ready */
937 AutoInitSpan autoInitSpan(this);
938 AssertReturn(autoInitSpan.isOk(), E_FAIL);
939
940 unconst(mParent) = aParent;
941
942 /* register with parent early, since uninit() will unconditionally
943 * unregister on failure */
[49742]944 mParent->i_addChild(this);
[31891]945
[61667]946 bd.allocate();
[31891]947
[61667]948 bd->mData.strName = Utf8Str(aName);
949 bd->mData.fActive = FALSE;
[31891]950 mInList = false;
[61667]951 USBFilterInit(&bd->mUSBFilter, USBFILTERTYPE_IGNORE);
952 bd->mRemote = NULL;
953 bd->mData.ulMaskedInterfaces = 0;
[31891]954
955 /* Confirm successful initialization */
956 autoInitSpan.setSucceeded();
957
958 return S_OK;
959}
960
961/**
962 * Uninitializes the instance and sets the ready flag to FALSE.
963 * Called either from FinalRelease() or by the parent when it gets destroyed.
964 */
965void HostUSBDeviceFilter::uninit()
966{
967 LogFlowThisFunc(("\n"));
968
969 /* Enclose the state transition Ready->InUninit->NotReady */
970 AutoUninitSpan autoUninitSpan(this);
971 if (autoUninitSpan.uninitDone())
972 return;
973
974 mInList = false;
975
[61667]976 bd.free();
[31891]977
978 unconst(mParent) = NULL;
979}
980
981/**
982 * Most of the USB bits are protect by one lock to simplify things.
983 * This lock is currently the one of the Host object, which happens
984 * to be our parent.
985 */
[51498]986RWLockHandle *HostUSBDeviceFilter::lockHandle() const
[31891]987{
988 return mParent->lockHandle();
989}
990
991
992// IUSBDeviceFilter properties
993////////////////////////////////////////////////////////////////////////////////
[49951]994HRESULT HostUSBDeviceFilter::getName(com::Utf8Str &aName)
[31891]995{
996 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
997
[61667]998 aName = bd->mData.strName;
[31891]999
1000 return S_OK;
1001}
1002
[49951]1003
1004HRESULT HostUSBDeviceFilter::setName(const com::Utf8Str &aName)
[31891]1005{
1006 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1007
[61667]1008 if (bd->mData.strName != aName)
[31891]1009 {
[61667]1010 bd->mData.strName = aName;
[31891]1011
1012 /* leave the lock before informing callbacks */
1013 alock.release();
1014
[61667]1015 return mParent->i_onUSBDeviceFilterChange(this);
[31891]1016 }
1017
1018 return S_OK;
1019}
1020
[49951]1021
1022HRESULT HostUSBDeviceFilter::getActive(BOOL *aActive)
[31891]1023{
1024 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1025
[61667]1026 *aActive = bd->mData.fActive;
[31891]1027
1028 return S_OK;
1029}
1030
[49951]1031
1032HRESULT HostUSBDeviceFilter::setActive(BOOL aActive)
[31891]1033{
1034 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1035
[61667]1036 if (bd->mData.fActive != RT_BOOL(aActive))
[31891]1037 {
[61667]1038 bd->mData.fActive = RT_BOOL(aActive);
[31891]1039
1040 /* leave the lock before informing callbacks */
1041 alock.release();
1042
[61667]1043 return mParent->i_onUSBDeviceFilterChange(this, TRUE /* aActiveChanged */);
[31891]1044 }
1045
1046 return S_OK;
1047}
1048
[49951]1049HRESULT HostUSBDeviceFilter::getVendorId(com::Utf8Str &aVendorId)
[31891]1050{
[49951]1051 return i_usbFilterFieldGetter(USBFILTERIDX_VENDOR_ID, aVendorId);
[31891]1052}
1053
[49951]1054HRESULT HostUSBDeviceFilter::setVendorId(const com::Utf8Str &aVendorId)
[31891]1055{
[49951]1056 return i_usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, aVendorId);
[31891]1057}
1058
[49951]1059HRESULT HostUSBDeviceFilter::getProductId(com::Utf8Str &aProductId)
[31891]1060{
[49951]1061 return i_usbFilterFieldGetter(USBFILTERIDX_PRODUCT_ID, aProductId);
[31891]1062}
1063
[49951]1064HRESULT HostUSBDeviceFilter::setProductId(const com::Utf8Str &aProductId)
[31891]1065{
[49951]1066 return i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, aProductId);
[31891]1067}
1068
[49951]1069HRESULT HostUSBDeviceFilter::getRevision(com::Utf8Str &aRevision)
[31891]1070{
[49951]1071 return i_usbFilterFieldGetter(USBFILTERIDX_DEVICE, aRevision);
[31891]1072}
1073
[49951]1074HRESULT HostUSBDeviceFilter::setRevision(const com::Utf8Str &aRevision)
[31891]1075{
[49951]1076 return i_usbFilterFieldSetter(USBFILTERIDX_DEVICE, aRevision);
[31891]1077}
1078
[49951]1079HRESULT HostUSBDeviceFilter::getManufacturer(com::Utf8Str &aManufacturer)
[31891]1080{
[49951]1081 return i_usbFilterFieldGetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
[31891]1082}
1083
[49951]1084HRESULT HostUSBDeviceFilter::setManufacturer(const com::Utf8Str &aManufacturer)
[31891]1085{
[49951]1086 return i_usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
[31891]1087}
1088
[49951]1089HRESULT HostUSBDeviceFilter::getProduct(com::Utf8Str &aProduct)
[31891]1090{
[49951]1091 return i_usbFilterFieldGetter(USBFILTERIDX_PRODUCT_STR, aProduct);
[31891]1092}
1093
[49951]1094HRESULT HostUSBDeviceFilter::setProduct(const com::Utf8Str &aProduct)
[31891]1095{
[49951]1096 return i_usbFilterFieldSetter(USBFILTERIDX_PRODUCT_STR, aProduct);
[31891]1097}
1098
[49951]1099HRESULT HostUSBDeviceFilter::getSerialNumber(com::Utf8Str &aSerialNumber)
[31891]1100{
[49951]1101 return i_usbFilterFieldGetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
[31891]1102}
1103
[49951]1104HRESULT HostUSBDeviceFilter::setSerialNumber(const com::Utf8Str &aSerialNumber)
[31891]1105{
[49951]1106 return i_usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
[31891]1107}
1108
[49951]1109HRESULT HostUSBDeviceFilter::getPort(com::Utf8Str &aPort)
[31891]1110{
[49951]1111 return i_usbFilterFieldGetter(USBFILTERIDX_PORT, aPort);
[31891]1112}
1113
[49951]1114HRESULT HostUSBDeviceFilter::setPort(const com::Utf8Str &aPort)
[31891]1115{
[49951]1116 return i_usbFilterFieldSetter(USBFILTERIDX_PORT, aPort);
[31891]1117}
1118
[49951]1119HRESULT HostUSBDeviceFilter::getRemote(com::Utf8Str &aRemote)
[31891]1120{
1121 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1122
[61667]1123 aRemote = bd->mRemote.string();
[31891]1124
1125 return S_OK;
1126}
1127
[49951]1128HRESULT HostUSBDeviceFilter::setRemote(const com::Utf8Str & /* aRemote */)
[31891]1129{
1130 return setError(E_NOTIMPL,
1131 tr("The remote state filter is not supported by IHostUSBDeviceFilter objects"));
1132}
1133
[49951]1134
1135HRESULT HostUSBDeviceFilter::getMaskedInterfaces(ULONG *aMaskedIfs)
[31891]1136{
1137 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1138
[61667]1139 *aMaskedIfs = bd->mData.ulMaskedInterfaces;
[31891]1140
1141 return S_OK;
1142}
[49951]1143HRESULT HostUSBDeviceFilter::setMaskedInterfaces(ULONG /* aMaskedIfs */)
[31891]1144{
1145 return setError(E_NOTIMPL,
1146 tr("The masked interfaces property is not applicable to IHostUSBDeviceFilter objects"));
1147}
1148
[49951]1149// wrapped IHostUSBDeviceFilter properties
[31891]1150////////////////////////////////////////////////////////////////////////////////
[49951]1151HRESULT HostUSBDeviceFilter::getAction(USBDeviceFilterAction_T *aAction)
[31891]1152{
1153 CheckComArgOutPointerValid(aAction);
1154
1155 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1156
[61667]1157 switch (USBFilterGetFilterType(&bd->mUSBFilter))
[31891]1158 {
1159 case USBFILTERTYPE_IGNORE: *aAction = USBDeviceFilterAction_Ignore; break;
1160 case USBFILTERTYPE_CAPTURE: *aAction = USBDeviceFilterAction_Hold; break;
1161 default: *aAction = USBDeviceFilterAction_Null; break;
1162 }
1163
1164 return S_OK;
1165}
1166
[49951]1167
1168HRESULT HostUSBDeviceFilter::setAction(USBDeviceFilterAction_T aAction)
[31891]1169{
1170 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1171
1172 USBFILTERTYPE filterType;
1173 switch (aAction)
1174 {
1175 case USBDeviceFilterAction_Ignore: filterType = USBFILTERTYPE_IGNORE; break;
1176 case USBDeviceFilterAction_Hold: filterType = USBFILTERTYPE_CAPTURE; break;
1177 case USBDeviceFilterAction_Null:
1178 return setError(E_INVALIDARG,
1179 tr("Action value InvalidUSBDeviceFilterAction is not permitted"));
1180 default:
1181 return setError(E_INVALIDARG,
1182 tr("Invalid action %d"),
1183 aAction);
1184 }
[61667]1185 if (USBFilterGetFilterType(&bd->mUSBFilter) != filterType)
[31891]1186 {
[61667]1187 int vrc = USBFilterSetFilterType(&bd->mUSBFilter, filterType);
[31891]1188 if (RT_FAILURE(vrc))
1189 return setError(E_INVALIDARG,
1190 tr("Unexpected error %Rrc"),
1191 vrc);
1192
1193 /* leave the lock before informing callbacks */
1194 alock.release();
1195
[61667]1196 return mParent->i_onUSBDeviceFilterChange(this);
[31891]1197 }
1198
1199 return S_OK;
1200}
1201
[49951]1202
1203// IHostUSBDeviceFilter properties
1204////////////////////////////////////////////////////////////////////////////////
[31891]1205/**
1206 * Generic USB filter field getter.
1207 *
1208 * @param aIdx The field index.
1209 * @param aStr Where to store the value.
1210 *
1211 * @return COM status.
1212 */
[49951]1213HRESULT HostUSBDeviceFilter::i_usbFilterFieldGetter(USBFILTERIDX aIdx, com::Utf8Str &aStr)
[31891]1214{
1215 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[61667]1216 i_usbFilterFieldToString(&bd->mUSBFilter, aIdx, aStr);
[31891]1217 return S_OK;
1218}
1219
[49951]1220void HostUSBDeviceFilter::i_saveSettings(settings::USBDeviceFilter &data)
[31891]1221{
1222 AutoCaller autoCaller(this);
[98262]1223 AssertComRCReturnVoid(autoCaller.hrc());
[31891]1224
1225 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
[61667]1226 data.strName = bd->mData.strName;
1227 data.fActive = bd->mData.fActive;
1228 i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_VENDOR_ID, data.strVendorId);
1229 i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_PRODUCT_ID, data.strProductId);
1230 i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_DEVICE, data.strRevision);
1231 i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer);
1232 i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_PRODUCT_STR, data.strProduct);
1233 i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber);
1234 i_usbFilterFieldToString(&bd->mUSBFilter, USBFILTERIDX_PORT, data.strPort);
[31891]1235
1236 COMGETTER(Action)(&data.action);
1237}
1238
1239
1240/**
1241 * Generic USB filter field setter.
1242 *
1243 * @param aIdx The field index.
1244 * @param aStr The new value.
1245 *
1246 * @return COM status.
1247 */
[49951]1248HRESULT HostUSBDeviceFilter::i_usbFilterFieldSetter(USBFILTERIDX aIdx, const com::Utf8Str &aStr)
[31891]1249{
1250 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1251 Utf8Str strOld;
[61667]1252 i_usbFilterFieldToString(&bd->mUSBFilter, aIdx, strOld);
[49951]1253 if (strOld != aStr)
[31891]1254 {
[61667]1255 //bd.backup();
[49951]1256 com::Utf8Str errStr;
[98292]1257 HRESULT hrc = USBDeviceFilter::i_usbFilterFieldFromString(&bd->mUSBFilter, aIdx, aStr, errStr);
1258 if (FAILED(hrc))
[31891]1259 {
[61667]1260 //bd.rollback();
[98292]1261 return setError(hrc, "%s", errStr.c_str());
[31891]1262 }
1263
1264 /* leave the lock before informing callbacks */
1265 alock.release();
1266
[49742]1267 return mParent->i_onUSBDeviceFilterChange(this);
[31891]1268 }
1269
1270 return S_OK;
1271}
1272/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use