1
/* $Id: USBDeviceFilterImpl.cpp 35368 2010-12-30 13:38:23Z vboxsync $ */
3
* Implementation of VirtualBox COM components: USBDeviceFilter and HostUSBDeviceFilter
7
* Copyright (C) 2006-2007 Oracle Corporation
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.
18
#include "USBDeviceFilterImpl.h"
19
#include "USBControllerImpl.h"
20
#include "MachineImpl.h"
23
#include <iprt/cpp/utils.h>
24
#include <VBox/settings.h>
26
#include "AutoStateDep.h"
27
#include "AutoCaller.h"
30
////////////////////////////////////////////////////////////////////////////////
32
////////////////////////////////////////////////////////////////////////////////
35
* Converts a USBFilter field into a string.
37
* (This function is also used by HostUSBDeviceFilter.)
39
* @param aFilter The filter.
40
* @param aIdx The field index.
41
* @param aStr The output string.
43
static void usbFilterFieldToString(PCUSBFILTER aFilter, USBFILTERIDX aIdx, Utf8Str &out)
45
const USBFILTERMATCH matchingMethod = USBFilterGetMatchingMethod(aFilter, aIdx);
46
Assert(matchingMethod != USBFILTERMATCH_INVALID);
48
if (USBFilterIsMethodNumeric(matchingMethod))
50
int value = USBFilterGetNum(aFilter, aIdx);
51
Assert(value >= 0 && value <= 0xffff);
53
out = Utf8StrFmt("%04RX16", (uint16_t)value);
55
else if (USBFilterIsMethodString(matchingMethod))
57
out = USBFilterGetString(aFilter, aIdx);
64
const char* USBDeviceFilter::describeUSBFilterIdx(USBFILTERIDX aIdx)
68
case USBFILTERIDX_VENDOR_ID: return tr("Vendor ID");
69
case USBFILTERIDX_PRODUCT_ID: return tr("Product ID");
70
case USBFILTERIDX_DEVICE: return tr("Revision");
71
case USBFILTERIDX_MANUFACTURER_STR: return tr("Manufacturer");
72
case USBFILTERIDX_PRODUCT_STR: return tr("Product");
73
case USBFILTERIDX_SERIAL_NUMBER_STR: return tr("Serial number");
74
case USBFILTERIDX_PORT: return tr("Port number");
81
* Interprets a string and assigns it to a USBFilter field.
83
* (This function is also used by HostUSBDeviceFilter.)
85
* @param aFilter The filter.
86
* @param aIdx The field index.
87
* @param aStr The input string.
88
* @param aName The field name for use in the error string.
89
* @param aErrStr Where to return the error string on failure.
91
* @return COM status code.
92
* @remark The idea was to have this as a static function, but tr() doesn't wanna work without a class :-/
94
/*static*/ HRESULT USBDeviceFilter::usbFilterFieldFromString(PUSBFILTER aFilter,
96
const Utf8Str &aValue,
100
// Utf8Str str (aStr);
101
if (aValue.isEmpty())
102
vrc = USBFilterSetIgnore(aFilter, aIdx);
105
const char *pcszValue = aValue.c_str();
106
if (USBFilterIsNumericField(aIdx))
108
/* Is it a lonely number? */
111
vrc = RTStrToUInt64Ex(pcszValue, &pszNext, 16, &u64);
113
pszNext = RTStrStripL (pszNext);
114
if ( vrc == VINF_SUCCESS
119
// there was a bug writing out "-1" values in earlier versions, which got
120
// written as "FFFFFFFF"; make sure we don't fail on those
121
if (u64 == 0xffffffff)
125
aErrStr = Utf8StrFmt(tr("The %s value '%s' is too big (max 0xFFFF)"), describeUSBFilterIdx(aIdx), pcszValue);
130
vrc = USBFilterSetNumExact(aFilter, aIdx, (uint16_t)u64, true /* fMustBePresent */);
133
vrc = USBFilterSetNumExpression(aFilter, aIdx, pcszValue, true /* fMustBePresent */);
137
/* Any wildcard in the string? */
138
Assert(USBFilterIsStringField(aIdx));
139
if ( strchr(pcszValue, '*')
140
|| strchr(pcszValue, '?')
141
/* || strchr (psz, '[') - later */
143
vrc = USBFilterSetStringPattern(aFilter, aIdx, pcszValue, true /* fMustBePresent */);
145
vrc = USBFilterSetStringExact(aFilter, aIdx, pcszValue, true /* fMustBePresent */);
151
if (vrc == VERR_INVALID_PARAMETER)
153
aErrStr = Utf8StrFmt(tr("The %s filter expression '%s' is not valid"), describeUSBFilterIdx(aIdx), aValue.c_str());
156
if (vrc == VERR_BUFFER_OVERFLOW)
158
aErrStr = Utf8StrFmt(tr("Insufficient expression space for the '%s' filter expression '%s'"), describeUSBFilterIdx(aIdx), aValue.c_str());
162
aErrStr = Utf8StrFmt(tr("Encountered unexpected status %Rrc when setting '%s' to '%s'"), vrc, describeUSBFilterIdx(aIdx), aValue.c_str());
170
////////////////////////////////////////////////////////////////////////////////
172
////////////////////////////////////////////////////////////////////////////////
174
// constructor / destructor
175
////////////////////////////////////////////////////////////////////////////////
177
USBDeviceFilter::USBDeviceFilter()
183
USBDeviceFilter::~USBDeviceFilter()
187
HRESULT USBDeviceFilter::FinalConstruct()
192
void USBDeviceFilter::FinalRelease()
197
// public initializer/uninitializer for internal purposes only
198
////////////////////////////////////////////////////////////////////////////////
201
* Initializes the USB device filter object.
203
* @param aParent Handle of the parent object.
205
HRESULT USBDeviceFilter::init(USBController *aParent,
206
const settings::USBDeviceFilter &data)
208
LogFlowThisFunc(("aParent=%p\n", aParent));
210
ComAssertRet(aParent && !data.strName.isEmpty(), E_INVALIDARG);
212
/* Enclose the state transition NotReady->InInit->Ready */
213
AutoInitSpan autoInitSpan(this);
214
AssertReturn(autoInitSpan.isOk(), E_FAIL);
216
unconst(mParent) = aParent;
217
/* mPeer is left null */
222
mData->mName = data.strName;
223
mData->mActive = data.fActive;
224
mData->mMaskedIfs = 0;
226
/* initialize all filters to any match using null string */
227
USBFilterInit(&mData->mUSBFilter, USBFILTERTYPE_CAPTURE);
228
mData->mRemote = NULL;
232
/* use setters for the attributes below to reuse parsing errors
238
rc = usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, data.strVendorId);
239
if (FAILED(rc)) break;
241
rc = usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, data.strProductId);
242
if (FAILED(rc)) break;
244
rc = usbFilterFieldSetter(USBFILTERIDX_DEVICE, data.strRevision);
245
if (FAILED(rc)) break;
247
rc = usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer);
248
if (FAILED(rc)) break;
250
rc = usbFilterFieldSetter(USBFILTERIDX_PRODUCT_STR, data.strProduct);
251
if (FAILED(rc)) break;
253
rc = usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber);
254
if (FAILED(rc)) break;
256
rc = usbFilterFieldSetter(USBFILTERIDX_PORT, data.strPort);
257
if (FAILED(rc)) break;
259
rc = COMSETTER(Remote)(Bstr(data.strRemote).raw());
260
if (FAILED(rc)) break;
262
rc = COMSETTER(MaskedInterfaces)(data.ulMaskedInterfaces);
263
if (FAILED(rc)) break;
267
/* Confirm successful initialization when it's the case */
269
autoInitSpan.setSucceeded();
275
* Initializes the USB device filter object (short version).
277
* @param aParent Handle of the parent object.
279
HRESULT USBDeviceFilter::init(USBController *aParent, IN_BSTR aName)
281
LogFlowThisFunc(("aParent=%p\n", aParent));
283
ComAssertRet(aParent && aName && *aName, E_INVALIDARG);
285
/* Enclose the state transition NotReady->InInit->Ready */
286
AutoInitSpan autoInitSpan(this);
287
AssertReturn(autoInitSpan.isOk(), E_FAIL);
289
unconst(mParent) = aParent;
290
/* mPeer is left null */
296
mData->mName = aName;
297
mData->mActive = FALSE;
298
mData->mMaskedIfs = 0;
300
/* initialize all filters to any match using null string */
301
USBFilterInit (&mData->mUSBFilter, USBFILTERTYPE_CAPTURE);
302
mData->mRemote = NULL;
306
/* Confirm successful initialization */
307
autoInitSpan.setSucceeded();
313
* Initializes the object given another object
314
* (a kind of copy constructor). This object shares data with
315
* the object passed as an argument.
318
* When false, the original object will remain a data owner.
319
* Otherwise, data ownership will be transferred from the original
320
* object to this one.
322
* @note This object must be destroyed before the original object
323
* it shares data with is destroyed.
325
* @note Locks @a aThat object for writing if @a aReshare is @c true, or for
326
* reading if @a aReshare is false.
328
HRESULT USBDeviceFilter::init (USBController *aParent, USBDeviceFilter *aThat,
329
bool aReshare /* = false */)
331
LogFlowThisFunc(("aParent=%p, aThat=%p, aReshare=%RTbool\n",
332
aParent, aThat, aReshare));
334
ComAssertRet(aParent && aThat, E_INVALIDARG);
336
/* Enclose the state transition NotReady->InInit->Ready */
337
AutoInitSpan autoInitSpan(this);
338
AssertReturn(autoInitSpan.isOk(), E_FAIL);
340
unconst(mParent) = aParent;
345
AutoCaller thatCaller (aThat);
346
AssertComRCReturnRC(thatCaller.rc());
350
AutoWriteLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
352
unconst(aThat->mPeer) = this;
353
mData.attach (aThat->mData);
357
unconst(mPeer) = aThat;
359
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
360
mData.share (aThat->mData);
363
/* the arbitrary ID field is not reset because
364
* the copy is a shadow of the original */
366
mInList = aThat->mInList;
368
/* Confirm successful initialization */
369
autoInitSpan.setSucceeded();
375
* Initializes the guest object given another guest object
376
* (a kind of copy constructor). This object makes a private copy of data
377
* of the original object passed as an argument.
379
* @note Locks @a aThat object for reading.
381
HRESULT USBDeviceFilter::initCopy (USBController *aParent, USBDeviceFilter *aThat)
383
LogFlowThisFunc(("aParent=%p, aThat=%p\n", aParent, aThat));
385
ComAssertRet(aParent && aThat, E_INVALIDARG);
387
/* Enclose the state transition NotReady->InInit->Ready */
388
AutoInitSpan autoInitSpan(this);
389
AssertReturn(autoInitSpan.isOk(), E_FAIL);
391
unconst(mParent) = aParent;
392
/* mPeer is left null */
397
AutoCaller thatCaller (aThat);
398
AssertComRCReturnRC(thatCaller.rc());
400
AutoReadLock thatLock(aThat COMMA_LOCKVAL_SRC_POS);
401
mData.attachCopy (aThat->mData);
403
/* reset the arbitrary ID field
404
* (this field is something unique that two distinct objects, even if they
405
* are deep copies of each other, should not share) */
408
mInList = aThat->mInList;
410
/* Confirm successful initialization */
411
autoInitSpan.setSucceeded();
417
* Uninitializes the instance and sets the ready flag to FALSE.
418
* Called either from FinalRelease() or by the parent when it gets destroyed.
420
void USBDeviceFilter::uninit()
422
LogFlowThisFunc(("\n"));
424
/* Enclose the state transition Ready->InUninit->NotReady */
425
AutoUninitSpan autoUninitSpan(this);
426
if (autoUninitSpan.uninitDone())
433
unconst(mPeer) = NULL;
434
unconst(mParent) = NULL;
438
// IUSBDeviceFilter properties
439
////////////////////////////////////////////////////////////////////////////////
441
STDMETHODIMP USBDeviceFilter::COMGETTER(Name) (BSTR *aName)
443
CheckComArgOutPointerValid(aName);
445
AutoCaller autoCaller(this);
446
if (FAILED(autoCaller.rc())) return autoCaller.rc();
448
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
450
mData->mName.cloneTo(aName);
455
STDMETHODIMP USBDeviceFilter::COMSETTER(Name) (IN_BSTR aName)
457
CheckComArgStrNotEmptyOrNull(aName);
459
AutoCaller autoCaller(this);
460
if (FAILED(autoCaller.rc())) return autoCaller.rc();
462
/* the machine needs to be mutable */
463
AutoMutableStateDependency adep(mParent->getMachine());
464
if (FAILED(adep.rc())) return adep.rc();
466
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
468
if (mData->mName != aName)
471
ComObjPtr<Machine> pMachine = mParent->getMachine();
474
mData->mName = aName;
476
// leave the lock before informing callbacks
479
AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
480
pMachine->setModified(Machine::IsModified_USB);
483
return mParent->onDeviceFilterChange(this);
489
STDMETHODIMP USBDeviceFilter::COMGETTER(Active) (BOOL *aActive)
491
CheckComArgOutPointerValid(aActive);
493
AutoCaller autoCaller(this);
494
if (FAILED(autoCaller.rc())) return autoCaller.rc();
496
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
498
*aActive = mData->mActive;
503
STDMETHODIMP USBDeviceFilter::COMSETTER(Active) (BOOL aActive)
505
AutoCaller autoCaller(this);
506
if (FAILED(autoCaller.rc())) return autoCaller.rc();
508
/* the machine needs to be mutable */
509
AutoMutableStateDependency adep(mParent->getMachine());
510
if (FAILED(adep.rc())) return adep.rc();
512
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
514
if (mData->mActive != aActive)
517
ComObjPtr<Machine> pMachine = mParent->getMachine();
520
mData->mActive = aActive;
522
// leave the lock before informing callbacks
525
AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
526
pMachine->setModified(Machine::IsModified_USB);
529
return mParent->onDeviceFilterChange(this, TRUE /* aActiveChanged */);
535
STDMETHODIMP USBDeviceFilter::COMGETTER(VendorId) (BSTR *aVendorId)
537
return usbFilterFieldGetter(USBFILTERIDX_VENDOR_ID, aVendorId);
540
STDMETHODIMP USBDeviceFilter::COMSETTER(VendorId) (IN_BSTR aVendorId)
542
return usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, aVendorId);
545
STDMETHODIMP USBDeviceFilter::COMGETTER(ProductId) (BSTR *aProductId)
547
return usbFilterFieldGetter(USBFILTERIDX_PRODUCT_ID, aProductId);
550
STDMETHODIMP USBDeviceFilter::COMSETTER(ProductId) (IN_BSTR aProductId)
552
return usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, aProductId);
555
STDMETHODIMP USBDeviceFilter::COMGETTER(Revision) (BSTR *aRevision)
557
return usbFilterFieldGetter(USBFILTERIDX_DEVICE, aRevision);
560
STDMETHODIMP USBDeviceFilter::COMSETTER(Revision) (IN_BSTR aRevision)
562
return usbFilterFieldSetter(USBFILTERIDX_DEVICE, aRevision);
565
STDMETHODIMP USBDeviceFilter::COMGETTER(Manufacturer) (BSTR *aManufacturer)
567
return usbFilterFieldGetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
570
STDMETHODIMP USBDeviceFilter::COMSETTER(Manufacturer) (IN_BSTR aManufacturer)
572
return usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
575
STDMETHODIMP USBDeviceFilter::COMGETTER(Product) (BSTR *aProduct)
577
return usbFilterFieldGetter(USBFILTERIDX_PRODUCT_STR, aProduct);
580
STDMETHODIMP USBDeviceFilter::COMSETTER(Product) (IN_BSTR aProduct)
582
return usbFilterFieldSetter(USBFILTERIDX_PRODUCT_STR, aProduct);
585
STDMETHODIMP USBDeviceFilter::COMGETTER(SerialNumber) (BSTR *aSerialNumber)
587
return usbFilterFieldGetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
590
STDMETHODIMP USBDeviceFilter::COMSETTER(SerialNumber) (IN_BSTR aSerialNumber)
592
return usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
595
STDMETHODIMP USBDeviceFilter::COMGETTER(Port) (BSTR *aPort)
597
return usbFilterFieldGetter(USBFILTERIDX_PORT, aPort);
600
STDMETHODIMP USBDeviceFilter::COMSETTER(Port) (IN_BSTR aPort)
602
return usbFilterFieldSetter(USBFILTERIDX_PORT, aPort);
605
STDMETHODIMP USBDeviceFilter::COMGETTER(Remote) (BSTR *aRemote)
607
CheckComArgOutPointerValid(aRemote);
609
AutoCaller autoCaller(this);
610
if (FAILED(autoCaller.rc())) return autoCaller.rc();
612
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
614
mData->mRemote.string().cloneTo(aRemote);
619
STDMETHODIMP USBDeviceFilter::COMSETTER(Remote) (IN_BSTR aRemote)
621
AutoCaller autoCaller(this);
622
if (FAILED(autoCaller.rc())) return autoCaller.rc();
624
/* the machine needs to be mutable */
625
AutoMutableStateDependency adep(mParent->getMachine());
626
if (FAILED(adep.rc())) return adep.rc();
628
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
630
if (mData->mRemote.string() != aRemote)
632
Data::BOOLFilter flt = aRemote;
633
ComAssertRet(!flt.isNull(), E_FAIL);
635
return setError(E_INVALIDARG,
636
tr("Remote state filter string '%ls' is not valid (error at position %d)"),
637
aRemote, flt.errorPosition() + 1);
640
ComObjPtr<Machine> pMachine = mParent->getMachine();
643
mData->mRemote = flt;
645
// leave the lock before informing callbacks
648
AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
649
pMachine->setModified(Machine::IsModified_USB);
652
return mParent->onDeviceFilterChange(this);
658
STDMETHODIMP USBDeviceFilter::COMGETTER(MaskedInterfaces) (ULONG *aMaskedIfs)
660
CheckComArgOutPointerValid(aMaskedIfs);
662
AutoCaller autoCaller(this);
663
if (FAILED(autoCaller.rc())) return autoCaller.rc();
665
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
667
*aMaskedIfs = mData->mMaskedIfs;
672
STDMETHODIMP USBDeviceFilter::COMSETTER(MaskedInterfaces) (ULONG aMaskedIfs)
674
AutoCaller autoCaller(this);
675
if (FAILED(autoCaller.rc())) return autoCaller.rc();
677
/* the machine needs to be mutable */
678
AutoMutableStateDependency adep(mParent->getMachine());
679
if (FAILED(adep.rc())) return adep.rc();
681
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
683
if (mData->mMaskedIfs != aMaskedIfs)
686
ComObjPtr<Machine> pMachine = mParent->getMachine();
689
mData->mMaskedIfs = aMaskedIfs;
691
// leave the lock before informing callbacks
694
AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
695
pMachine->setModified(Machine::IsModified_USB);
698
return mParent->onDeviceFilterChange(this);
704
// public methods only for internal purposes
705
////////////////////////////////////////////////////////////////////////////////
707
bool USBDeviceFilter::isModified()
709
AutoCaller autoCaller(this);
710
AssertComRCReturn (autoCaller.rc(), false);
712
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
717
* @note Locks this object for writing.
719
void USBDeviceFilter::rollback()
722
AutoCaller autoCaller(this);
723
AssertComRCReturnVoid(autoCaller.rc());
725
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
731
* @note Locks this object for writing, together with the peer object (also
732
* for writing) if there is one.
734
void USBDeviceFilter::commit()
737
AutoCaller autoCaller(this);
738
AssertComRCReturnVoid (autoCaller.rc());
741
AutoCaller peerCaller (mPeer);
742
AssertComRCReturnVoid (peerCaller.rc());
744
/* lock both for writing since we modify both (mPeer is "master" so locked
746
AutoMultiWriteLock2 alock(mPeer, this COMMA_LOCKVAL_SRC_POS);
748
if (mData.isBackedUp())
753
/* attach new data to the peer and reshare it */
754
mPeer->mData.attach (mData);
760
* Cancels sharing (if any) by making an independent copy of data.
761
* This operation also resets this object's peer to NULL.
763
* @note Locks this object for writing, together with the peer object
764
* represented by @a aThat (locked for reading).
766
void USBDeviceFilter::unshare()
769
AutoCaller autoCaller(this);
770
AssertComRCReturnVoid (autoCaller.rc());
773
AutoCaller peerCaller (mPeer);
774
AssertComRCReturnVoid (peerCaller.rc());
776
/* peer is not modified, lock it for reading (mPeer is "master" so locked
778
AutoReadLock rl(mPeer COMMA_LOCKVAL_SRC_POS);
779
AutoWriteLock wl(this COMMA_LOCKVAL_SRC_POS);
781
if (mData.isShared())
783
if (!mData.isBackedUp())
789
unconst(mPeer) = NULL;
793
* Generic USB filter field getter; converts the field value to UTF-16.
795
* @param aIdx The field index.
796
* @param aStr Where to store the value.
798
* @return COM status.
800
HRESULT USBDeviceFilter::usbFilterFieldGetter(USBFILTERIDX aIdx, BSTR *aStr)
802
CheckComArgOutPointerValid(aStr);
804
AutoCaller autoCaller(this);
805
if (FAILED(autoCaller.rc())) return autoCaller.rc();
807
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
810
usbFilterFieldToString(&mData->mUSBFilter, aIdx, str);
818
* Generic USB filter field setter, expects UTF-8 input.
820
* @param aIdx The field index.
821
* @param aStr The new value.
823
* @return COM status.
825
HRESULT USBDeviceFilter::usbFilterFieldSetter(USBFILTERIDX aIdx,
826
const Utf8Str &strNew)
828
AutoCaller autoCaller(this);
829
if (FAILED(autoCaller.rc())) return autoCaller.rc();
831
/* the machine needs to be mutable */
832
AutoMutableStateDependency adep(mParent->getMachine());
833
if (FAILED(adep.rc())) return adep.rc();
835
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
838
usbFilterFieldToString(&mData->mUSBFilter, aIdx, strOld);
839
if (strOld != strNew)
842
ComObjPtr<Machine> pMachine = mParent->getMachine();
847
HRESULT rc = usbFilterFieldFromString(&mData->mUSBFilter, aIdx, strNew, errStr);
851
return setError(rc, "%s", errStr.c_str());
854
// leave the lock before informing callbacks
857
AutoWriteLock mlock(pMachine COMMA_LOCKVAL_SRC_POS);
858
pMachine->setModified(Machine::IsModified_USB);
861
return mParent->onDeviceFilterChange(this);
868
* Generic USB filter field setter, expects UTF-16 input.
870
* @param aIdx The field index.
871
* @param aStr The new value.
873
* @return COM status.
875
HRESULT USBDeviceFilter::usbFilterFieldSetter(USBFILTERIDX aIdx,
878
return usbFilterFieldSetter(aIdx, Utf8Str(aStr));
882
////////////////////////////////////////////////////////////////////////////////
883
// HostUSBDeviceFilter
884
////////////////////////////////////////////////////////////////////////////////
886
// constructor / destructor
887
////////////////////////////////////////////////////////////////////////////////
889
HostUSBDeviceFilter::HostUSBDeviceFilter()
894
HostUSBDeviceFilter::~HostUSBDeviceFilter()
899
HRESULT HostUSBDeviceFilter::FinalConstruct()
904
void HostUSBDeviceFilter::FinalRelease()
909
// public initializer/uninitializer for internal purposes only
910
////////////////////////////////////////////////////////////////////////////////
913
* Initializes the USB device filter object.
915
* @param aParent Handle of the parent object.
917
HRESULT HostUSBDeviceFilter::init(Host *aParent,
918
const settings::USBDeviceFilter &data)
920
LogFlowThisFunc(("aParent=%p\n", aParent));
922
ComAssertRet(aParent && !data.strName.isEmpty(), E_INVALIDARG);
924
/* Enclose the state transition NotReady->InInit->Ready */
925
AutoInitSpan autoInitSpan(this);
926
AssertReturn(autoInitSpan.isOk(), E_FAIL);
928
unconst(mParent) = aParent;
930
/* register with parent early, since uninit() will unconditionally
931
* unregister on failure */
932
mParent->addChild(this);
935
mData->mName = data.strName;
936
mData->mActive = data.fActive;
937
USBFilterInit (&mData->mUSBFilter, USBFILTERTYPE_IGNORE);
938
mData->mRemote = NULL;
939
mData->mMaskedIfs = 0;
943
/* use setters for the attributes below to reuse parsing errors
949
rc = COMSETTER(Action)(data.action);
950
if (FAILED(rc)) break;
952
rc = usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, data.strVendorId);
953
if (FAILED(rc)) break;
955
rc = usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, data.strProductId);
956
if (FAILED(rc)) break;
958
rc = usbFilterFieldSetter(USBFILTERIDX_DEVICE, data.strRevision);
959
if (FAILED(rc)) break;
961
rc = usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer);
962
if (FAILED(rc)) break;
964
rc = usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, data.strProduct);
965
if (FAILED(rc)) break;
967
rc = usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber);
968
if (FAILED(rc)) break;
970
rc = usbFilterFieldSetter(USBFILTERIDX_PORT, data.strPort);
971
if (FAILED(rc)) break;
975
/* Confirm successful initialization when it's the case */
977
autoInitSpan.setSucceeded();
983
* Initializes the USB device filter object (short version).
985
* @param aParent Handle of the parent object.
987
HRESULT HostUSBDeviceFilter::init (Host *aParent, IN_BSTR aName)
989
LogFlowThisFunc(("aParent=%p\n", aParent));
991
ComAssertRet(aParent && aName && *aName, E_INVALIDARG);
993
/* Enclose the state transition NotReady->InInit->Ready */
994
AutoInitSpan autoInitSpan(this);
995
AssertReturn(autoInitSpan.isOk(), E_FAIL);
997
unconst(mParent) = aParent;
999
/* register with parent early, since uninit() will unconditionally
1000
* unregister on failure */
1001
mParent->addChild(this);
1005
mData->mName = aName;
1006
mData->mActive = FALSE;
1008
USBFilterInit (&mData->mUSBFilter, USBFILTERTYPE_IGNORE);
1009
mData->mRemote = NULL;
1010
mData->mMaskedIfs = 0;
1012
/* Confirm successful initialization */
1013
autoInitSpan.setSucceeded();
1019
* Uninitializes the instance and sets the ready flag to FALSE.
1020
* Called either from FinalRelease() or by the parent when it gets destroyed.
1022
void HostUSBDeviceFilter::uninit()
1024
LogFlowThisFunc(("\n"));
1026
/* Enclose the state transition Ready->InUninit->NotReady */
1027
AutoUninitSpan autoUninitSpan(this);
1028
if (autoUninitSpan.uninitDone())
1035
mParent->removeChild(this);
1037
unconst(mParent) = NULL;
1041
* Most of the USB bits are protect by one lock to simplify things.
1042
* This lock is currently the one of the Host object, which happens
1045
RWLockHandle *HostUSBDeviceFilter::lockHandle() const
1047
return mParent->lockHandle();
1051
// IUSBDeviceFilter properties
1052
////////////////////////////////////////////////////////////////////////////////
1054
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Name) (BSTR *aName)
1056
CheckComArgOutPointerValid(aName);
1058
AutoCaller autoCaller(this);
1059
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1061
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1063
mData->mName.cloneTo(aName);
1068
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Name) (IN_BSTR aName)
1070
CheckComArgStrNotEmptyOrNull(aName);
1072
AutoCaller autoCaller(this);
1073
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1075
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1077
if (mData->mName != aName)
1079
mData->mName = aName;
1081
/* leave the lock before informing callbacks */
1084
return mParent->onUSBDeviceFilterChange (this);
1090
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Active) (BOOL *aActive)
1092
CheckComArgOutPointerValid(aActive);
1094
AutoCaller autoCaller(this);
1095
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1097
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1099
*aActive = mData->mActive;
1104
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Active) (BOOL aActive)
1106
AutoCaller autoCaller(this);
1107
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1109
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1111
if (mData->mActive != aActive)
1113
mData->mActive = aActive;
1115
/* leave the lock before informing callbacks */
1118
return mParent->onUSBDeviceFilterChange (this, TRUE /* aActiveChanged */);
1124
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(VendorId) (BSTR *aVendorId)
1126
return usbFilterFieldGetter(USBFILTERIDX_VENDOR_ID, aVendorId);
1129
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(VendorId) (IN_BSTR aVendorId)
1131
return usbFilterFieldSetter(USBFILTERIDX_VENDOR_ID, aVendorId);
1134
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(ProductId) (BSTR *aProductId)
1136
return usbFilterFieldGetter(USBFILTERIDX_PRODUCT_ID, aProductId);
1139
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(ProductId) (IN_BSTR aProductId)
1141
return usbFilterFieldSetter(USBFILTERIDX_PRODUCT_ID, aProductId);
1144
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Revision) (BSTR *aRevision)
1146
return usbFilterFieldGetter(USBFILTERIDX_DEVICE, aRevision);
1149
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Revision) (IN_BSTR aRevision)
1151
return usbFilterFieldSetter(USBFILTERIDX_DEVICE, aRevision);
1154
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Manufacturer) (BSTR *aManufacturer)
1156
return usbFilterFieldGetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
1159
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Manufacturer) (IN_BSTR aManufacturer)
1161
return usbFilterFieldSetter(USBFILTERIDX_MANUFACTURER_STR, aManufacturer);
1164
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Product) (BSTR *aProduct)
1166
return usbFilterFieldGetter(USBFILTERIDX_PRODUCT_STR, aProduct);
1169
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Product) (IN_BSTR aProduct)
1171
return usbFilterFieldSetter(USBFILTERIDX_PRODUCT_STR, aProduct);
1174
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(SerialNumber) (BSTR *aSerialNumber)
1176
return usbFilterFieldGetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
1179
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(SerialNumber) (IN_BSTR aSerialNumber)
1181
return usbFilterFieldSetter(USBFILTERIDX_SERIAL_NUMBER_STR, aSerialNumber);
1184
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Port) (BSTR *aPort)
1186
return usbFilterFieldGetter(USBFILTERIDX_PORT, aPort);
1189
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Port) (IN_BSTR aPort)
1191
return usbFilterFieldSetter(USBFILTERIDX_PORT, aPort);
1194
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Remote) (BSTR *aRemote)
1196
CheckComArgOutPointerValid(aRemote);
1198
AutoCaller autoCaller(this);
1199
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1201
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1203
mData->mRemote.string().cloneTo(aRemote);
1208
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Remote) (IN_BSTR /* aRemote */)
1210
return setError(E_NOTIMPL,
1211
tr("The remote state filter is not supported by IHostUSBDeviceFilter objects"));
1214
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(MaskedInterfaces) (ULONG *aMaskedIfs)
1216
CheckComArgOutPointerValid(aMaskedIfs);
1218
AutoCaller autoCaller(this);
1219
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1221
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1223
*aMaskedIfs = mData->mMaskedIfs;
1228
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(MaskedInterfaces) (ULONG /* aMaskedIfs */)
1230
return setError(E_NOTIMPL,
1231
tr("The masked interfaces property is not applicable to IHostUSBDeviceFilter objects"));
1234
// IHostUSBDeviceFilter properties
1235
////////////////////////////////////////////////////////////////////////////////
1237
STDMETHODIMP HostUSBDeviceFilter::COMGETTER(Action) (USBDeviceFilterAction_T *aAction)
1239
CheckComArgOutPointerValid(aAction);
1241
AutoCaller autoCaller(this);
1242
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1244
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1246
switch (USBFilterGetFilterType (&mData->mUSBFilter))
1248
case USBFILTERTYPE_IGNORE: *aAction = USBDeviceFilterAction_Ignore; break;
1249
case USBFILTERTYPE_CAPTURE: *aAction = USBDeviceFilterAction_Hold; break;
1250
default: *aAction = USBDeviceFilterAction_Null; break;
1256
STDMETHODIMP HostUSBDeviceFilter::COMSETTER(Action) (USBDeviceFilterAction_T aAction)
1258
AutoCaller autoCaller(this);
1259
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1261
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1263
USBFILTERTYPE filterType;
1266
case USBDeviceFilterAction_Ignore: filterType = USBFILTERTYPE_IGNORE; break;
1267
case USBDeviceFilterAction_Hold: filterType = USBFILTERTYPE_CAPTURE; break;
1268
case USBDeviceFilterAction_Null:
1269
return setError(E_INVALIDARG,
1270
tr("Action value InvalidUSBDeviceFilterAction is not permitted"));
1272
return setError(E_INVALIDARG,
1273
tr("Invalid action %d"),
1276
if (USBFilterGetFilterType (&mData->mUSBFilter) != filterType)
1278
int vrc = USBFilterSetFilterType (&mData->mUSBFilter, filterType);
1279
if (RT_FAILURE(vrc))
1280
return setError(E_INVALIDARG,
1281
tr("Unexpected error %Rrc"),
1284
/* leave the lock before informing callbacks */
1287
return mParent->onUSBDeviceFilterChange (this);
1294
* Generic USB filter field getter.
1296
* @param aIdx The field index.
1297
* @param aStr Where to store the value.
1299
* @return COM status.
1301
HRESULT HostUSBDeviceFilter::usbFilterFieldGetter(USBFILTERIDX aIdx, BSTR *aStr)
1303
CheckComArgOutPointerValid(aStr);
1305
AutoCaller autoCaller(this);
1306
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1308
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1311
usbFilterFieldToString(&mData->mUSBFilter, aIdx, str);
1318
void HostUSBDeviceFilter::saveSettings(settings::USBDeviceFilter &data)
1320
AutoCaller autoCaller(this);
1321
AssertComRCReturnVoid(autoCaller.rc());
1323
AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
1325
data.strName = mData->mName;
1326
data.fActive = !!mData->mActive;
1328
usbFilterFieldToString(&mData->mUSBFilter, USBFILTERIDX_VENDOR_ID, data.strVendorId);
1329
usbFilterFieldToString(&mData->mUSBFilter, USBFILTERIDX_PRODUCT_ID, data.strProductId);
1330
usbFilterFieldToString(&mData->mUSBFilter, USBFILTERIDX_DEVICE, data.strRevision);
1331
usbFilterFieldToString(&mData->mUSBFilter, USBFILTERIDX_MANUFACTURER_STR, data.strManufacturer);
1332
usbFilterFieldToString(&mData->mUSBFilter, USBFILTERIDX_PRODUCT_STR, data.strProduct);
1333
usbFilterFieldToString(&mData->mUSBFilter, USBFILTERIDX_SERIAL_NUMBER_STR, data.strSerialNumber);
1334
usbFilterFieldToString(&mData->mUSBFilter, USBFILTERIDX_PORT, data.strPort);
1336
COMGETTER(Action)(&data.action);
1341
* Generic USB filter field setter.
1343
* @param aIdx The field index.
1344
* @param aStr The new value.
1345
* @param aName The translated field name (for error messages).
1347
* @return COM status.
1349
HRESULT HostUSBDeviceFilter::usbFilterFieldSetter(USBFILTERIDX aIdx, Bstr aStr)
1351
AutoCaller autoCaller(this);
1352
if (FAILED(autoCaller.rc())) return autoCaller.rc();
1354
AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
1357
Utf8Str strNew(aStr);
1358
usbFilterFieldToString(&mData->mUSBFilter, aIdx, strOld);
1359
if (strOld != strNew)
1364
HRESULT rc = USBDeviceFilter::usbFilterFieldFromString(&mData->mUSBFilter, aIdx, aStr, errStr);
1368
return setError(rc, "%s", errStr.c_str());
1371
/* leave the lock before informing callbacks */
1374
return mParent->onUSBDeviceFilterChange(this);
1379
/* vi: set tabstop=4 shiftwidth=4 expandtab: */