~ubuntu-branches/ubuntu/raring/virtualbox-ose/raring

« back to all changes in this revision

Viewing changes to src/VBox/Main/src-server/USBDeviceFilterImpl.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Felix Geyer
  • Date: 2011-01-30 23:27:25 UTC
  • mfrom: (0.3.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20110130232725-2ouajjd2ggdet0zd
Tags: 4.0.2-dfsg-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add Apport hook.
    - debian/virtualbox-ose.files/source_virtualbox-ose.py
    - debian/virtualbox-ose.install
  - Drop *-source packages.
* Drop ubuntu-01-fix-build-gcc45.patch, fixed upstream.
* Drop ubuntu-02-as-needed.patch, added to the Debian package.

Show diffs side-by-side

added added

removed removed

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