VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp@ 32718

Last change on this file since 32718 was 32718, checked in by vboxsync, 14 years ago

com/string: Remove bool conversion operator and other convenience error operators. They are hiding programming errors (like incorrect empty string checks, and in one case a free of the wrong pointer).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.4 KB
Line 
1/* $Id: VBoxManageUSB.cpp 32718 2010-09-23 12:57:52Z vboxsync $ */
2/** @file
3 * VBoxManage - VirtualBox's command-line interface.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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 <VBox/com/com.h>
19#include <VBox/com/string.h>
20#include <VBox/com/Guid.h>
21#include <VBox/com/array.h>
22#include <VBox/com/ErrorInfo.h>
23#include <VBox/com/errorprint.h>
24#include <VBox/com/EventQueue.h>
25
26#include <VBox/com/VirtualBox.h>
27
28#include "VBoxManage.h"
29
30#include <iprt/asm.h>
31
32/* missing XPCOM <-> COM wrappers */
33#ifndef STDMETHOD_
34# define STDMETHOD_(ret, meth) NS_IMETHOD_(ret) meth
35#endif
36#ifndef NS_GET_IID
37# define NS_GET_IID(I) IID_##I
38#endif
39#ifndef RT_OS_WINDOWS
40#define IUnknown nsISupports
41#endif
42
43using namespace com;
44
45/**
46 * Quick IUSBDevice implementation for detaching / attaching
47 * devices to the USB Controller.
48 */
49class MyUSBDevice : public IUSBDevice
50{
51public:
52 // public initializer/uninitializer for internal purposes only
53 MyUSBDevice(uint16_t a_u16VendorId, uint16_t a_u16ProductId, uint16_t a_bcdRevision, uint64_t a_u64SerialHash, const char *a_pszComment)
54 : m_usVendorId(a_u16VendorId), m_usProductId(a_u16ProductId),
55 m_bcdRevision(a_bcdRevision), m_u64SerialHash(a_u64SerialHash),
56 m_bstrComment(a_pszComment),
57 m_cRefs(0)
58 {
59 }
60
61 STDMETHOD_(ULONG, AddRef)(void)
62 {
63 return ASMAtomicIncU32(&m_cRefs);
64 }
65 STDMETHOD_(ULONG, Release)(void)
66 {
67 ULONG cRefs = ASMAtomicDecU32(&m_cRefs);
68 if (!cRefs)
69 delete this;
70 return cRefs;
71 }
72 STDMETHOD(QueryInterface)(const IID &iid, void **ppvObject)
73 {
74 Guid guid(iid);
75 if (guid == Guid(NS_GET_IID(IUnknown)))
76 *ppvObject = (IUnknown *)this;
77#ifdef RT_OS_WINDOWS
78 else if (guid == Guid(NS_GET_IID(IDispatch)))
79 *ppvObject = (IDispatch *)this;
80#endif
81 else if (guid == Guid(NS_GET_IID(IUSBDevice)))
82 *ppvObject = (IUSBDevice *)this;
83 else
84 return E_NOINTERFACE;
85 AddRef();
86 return S_OK;
87 }
88
89 STDMETHOD(COMGETTER(Id))(OUT_GUID a_pId) { return E_NOTIMPL; }
90 STDMETHOD(COMGETTER(VendorId))(USHORT *a_pusVendorId) { *a_pusVendorId = m_usVendorId; return S_OK; }
91 STDMETHOD(COMGETTER(ProductId))(USHORT *a_pusProductId) { *a_pusProductId = m_usProductId; return S_OK; }
92 STDMETHOD(COMGETTER(Revision))(USHORT *a_pusRevision) { *a_pusRevision = m_bcdRevision; return S_OK; }
93 STDMETHOD(COMGETTER(SerialHash))(ULONG64 *a_pullSerialHash) { *a_pullSerialHash = m_u64SerialHash; return S_OK; }
94 STDMETHOD(COMGETTER(Manufacturer))(BSTR *a_pManufacturer) { return E_NOTIMPL; }
95 STDMETHOD(COMGETTER(Product))(BSTR *a_pProduct) { return E_NOTIMPL; }
96 STDMETHOD(COMGETTER(SerialNumber))(BSTR *a_pSerialNumber) { return E_NOTIMPL; }
97 STDMETHOD(COMGETTER(Address))(BSTR *a_pAddress) { return E_NOTIMPL; }
98
99private:
100 /** The vendor id of this USB device. */
101 USHORT m_usVendorId;
102 /** The product id of this USB device. */
103 USHORT m_usProductId;
104 /** The product revision number of this USB device.
105 * (high byte = integer; low byte = decimal) */
106 USHORT m_bcdRevision;
107 /** The USB serial hash of the device. */
108 uint64_t m_u64SerialHash;
109 /** The user comment string. */
110 Bstr m_bstrComment;
111 /** Reference counter. */
112 uint32_t volatile m_cRefs;
113};
114
115
116// types
117///////////////////////////////////////////////////////////////////////////////
118
119template <typename T>
120class Nullable
121{
122public:
123
124 Nullable() : mIsNull(true) {}
125 Nullable(const T &aValue, bool aIsNull = false)
126 : mIsNull(aIsNull), mValue(aValue) {}
127
128 bool isNull() const { return mIsNull; };
129 void setNull(bool aIsNull = true) { mIsNull = aIsNull; }
130
131 operator const T&() const { return mValue; }
132
133 Nullable &operator= (const T &aValue)
134 {
135 mValue = aValue;
136 mIsNull = false;
137 return *this;
138 }
139
140private:
141
142 bool mIsNull;
143 T mValue;
144};
145
146/** helper structure to encapsulate USB filter manipulation commands */
147struct USBFilterCmd
148{
149 struct USBFilter
150 {
151 USBFilter()
152 : mAction(USBDeviceFilterAction_Null)
153 {}
154
155 Bstr mName;
156 Nullable <bool> mActive;
157 Bstr mVendorId;
158 Bstr mProductId;
159 Bstr mRevision;
160 Bstr mManufacturer;
161 Bstr mProduct;
162 Bstr mRemote;
163 Bstr mSerialNumber;
164 Nullable <ULONG> mMaskedInterfaces;
165 USBDeviceFilterAction_T mAction;
166 };
167
168 enum Action { Invalid, Add, Modify, Remove };
169
170 USBFilterCmd() : mAction(Invalid), mIndex(0), mGlobal(false) {}
171
172 Action mAction;
173 uint32_t mIndex;
174 /** flag whether the command target is a global filter */
175 bool mGlobal;
176 /** machine this command is targeted at (null for global filters) */
177 ComPtr<IMachine> mMachine;
178 USBFilter mFilter;
179};
180
181int handleUSBFilter(HandlerArg *a)
182{
183 HRESULT rc = S_OK;
184 USBFilterCmd cmd;
185
186 /* at least: 0: command, 1: index, 2: --target, 3: <target value> */
187 if (a->argc < 4)
188 return errorSyntax(USAGE_USBFILTER, "Not enough parameters");
189
190 /* which command? */
191 cmd.mAction = USBFilterCmd::Invalid;
192 if (!strcmp(a->argv[0], "add")) cmd.mAction = USBFilterCmd::Add;
193 else if (!strcmp(a->argv[0], "modify")) cmd.mAction = USBFilterCmd::Modify;
194 else if (!strcmp(a->argv[0], "remove")) cmd.mAction = USBFilterCmd::Remove;
195
196 if (cmd.mAction == USBFilterCmd::Invalid)
197 return errorSyntax(USAGE_USBFILTER, "Invalid parameter '%s'", a->argv[0]);
198
199 /* which index? */
200 if (VINF_SUCCESS != RTStrToUInt32Full(a->argv[1], 10, &cmd.mIndex))
201 return errorSyntax(USAGE_USBFILTER, "Invalid index '%s'", a->argv[1]);
202
203 switch (cmd.mAction)
204 {
205 case USBFilterCmd::Add:
206 case USBFilterCmd::Modify:
207 {
208 /* at least: 0: command, 1: index, 2: --target, 3: <target value>, 4: --name, 5: <name value> */
209 if (a->argc < 6)
210 {
211 if (cmd.mAction == USBFilterCmd::Add)
212 return errorSyntax(USAGE_USBFILTER_ADD, "Not enough parameters");
213
214 return errorSyntax(USAGE_USBFILTER_MODIFY, "Not enough parameters");
215 }
216
217 // set Active to true by default
218 // (assuming that the user sets up all necessary attributes
219 // at once and wants the filter to be active immediately)
220 if (cmd.mAction == USBFilterCmd::Add)
221 cmd.mFilter.mActive = true;
222
223 for (int i = 2; i < a->argc; i++)
224 {
225 if ( !strcmp(a->argv[i], "--target")
226 || !strcmp(a->argv[i], "-target"))
227 {
228 if (a->argc <= i + 1 || !*a->argv[i+1])
229 return errorArgument("Missing argument to '%s'", a->argv[i]);
230 i++;
231 if (!strcmp(a->argv[i], "global"))
232 cmd.mGlobal = true;
233 else
234 {
235 /* assume it's a UUID of a machine */
236 rc = a->virtualBox->GetMachine(Bstr(a->argv[i]).raw(),
237 cmd.mMachine.asOutParam());
238 if (FAILED(rc) || !cmd.mMachine)
239 {
240 /* must be a name */
241 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]).raw(),
242 cmd.mMachine.asOutParam()), 1);
243 }
244 }
245 }
246 else if ( !strcmp(a->argv[i], "--name")
247 || !strcmp(a->argv[i], "-name"))
248 {
249 if (a->argc <= i + 1 || !*a->argv[i+1])
250 return errorArgument("Missing argument to '%s'", a->argv[i]);
251 i++;
252 cmd.mFilter.mName = a->argv[i];
253 }
254 else if ( !strcmp(a->argv[i], "--active")
255 || !strcmp(a->argv[i], "-active"))
256 {
257 if (a->argc <= i + 1)
258 return errorArgument("Missing argument to '%s'", a->argv[i]);
259 i++;
260 if (!strcmp(a->argv[i], "yes"))
261 cmd.mFilter.mActive = true;
262 else if (!strcmp(a->argv[i], "no"))
263 cmd.mFilter.mActive = false;
264 else
265 return errorArgument("Invalid --active argument '%s'", a->argv[i]);
266 }
267 else if ( !strcmp(a->argv[i], "--vendorid")
268 || !strcmp(a->argv[i], "-vendorid"))
269 {
270 if (a->argc <= i + 1)
271 return errorArgument("Missing argument to '%s'", a->argv[i]);
272 i++;
273 cmd.mFilter.mVendorId = a->argv[i];
274 }
275 else if ( !strcmp(a->argv[i], "--productid")
276 || !strcmp(a->argv[i], "-productid"))
277 {
278 if (a->argc <= i + 1)
279 return errorArgument("Missing argument to '%s'", a->argv[i]);
280 i++;
281 cmd.mFilter.mProductId = a->argv[i];
282 }
283 else if ( !strcmp(a->argv[i], "--revision")
284 || !strcmp(a->argv[i], "-revision"))
285 {
286 if (a->argc <= i + 1)
287 return errorArgument("Missing argument to '%s'", a->argv[i]);
288 i++;
289 cmd.mFilter.mRevision = a->argv[i];
290 }
291 else if ( !strcmp(a->argv[i], "--manufacturer")
292 || !strcmp(a->argv[i], "-manufacturer"))
293 {
294 if (a->argc <= i + 1)
295 return errorArgument("Missing argument to '%s'", a->argv[i]);
296 i++;
297 cmd.mFilter.mManufacturer = a->argv[i];
298 }
299 else if ( !strcmp(a->argv[i], "--product")
300 || !strcmp(a->argv[i], "-product"))
301 {
302 if (a->argc <= i + 1)
303 return errorArgument("Missing argument to '%s'", a->argv[i]);
304 i++;
305 cmd.mFilter.mProduct = a->argv[i];
306 }
307 else if ( !strcmp(a->argv[i], "--remote")
308 || !strcmp(a->argv[i], "-remote"))
309 {
310 if (a->argc <= i + 1)
311 return errorArgument("Missing argument to '%s'", a->argv[i]);
312 i++;
313 cmd.mFilter.mRemote = a->argv[i];
314 }
315 else if ( !strcmp(a->argv[i], "--serialnumber")
316 || !strcmp(a->argv[i], "-serialnumber"))
317 {
318 if (a->argc <= i + 1)
319 return errorArgument("Missing argument to '%s'", a->argv[i]);
320 i++;
321 cmd.mFilter.mSerialNumber = a->argv[i];
322 }
323 else if ( !strcmp(a->argv[i], "--maskedinterfaces")
324 || !strcmp(a->argv[i], "-maskedinterfaces"))
325 {
326 if (a->argc <= i + 1)
327 return errorArgument("Missing argument to '%s'", a->argv[i]);
328 i++;
329 uint32_t u32;
330 int vrc = RTStrToUInt32Full(a->argv[i], 0, &u32);
331 if (RT_FAILURE(vrc))
332 return errorArgument("Failed to convert the --maskedinterfaces value '%s' to a number, vrc=%Rrc", a->argv[i], vrc);
333 cmd.mFilter.mMaskedInterfaces = u32;
334 }
335 else if ( !strcmp(a->argv[i], "--action")
336 || !strcmp(a->argv[i], "-action"))
337 {
338 if (a->argc <= i + 1)
339 return errorArgument("Missing argument to '%s'", a->argv[i]);
340 i++;
341 if (!strcmp(a->argv[i], "ignore"))
342 cmd.mFilter.mAction = USBDeviceFilterAction_Ignore;
343 else if (!strcmp(a->argv[i], "hold"))
344 cmd.mFilter.mAction = USBDeviceFilterAction_Hold;
345 else
346 return errorArgument("Invalid USB filter action '%s'", a->argv[i]);
347 }
348 else
349 return errorSyntax(cmd.mAction == USBFilterCmd::Add ? USAGE_USBFILTER_ADD : USAGE_USBFILTER_MODIFY,
350 "Unknown option '%s'", a->argv[i]);
351 }
352
353 if (cmd.mAction == USBFilterCmd::Add)
354 {
355 // mandatory/forbidden options
356 if ( cmd.mFilter.mName.isEmpty()
357 ||
358 ( cmd.mGlobal
359 && cmd.mFilter.mAction == USBDeviceFilterAction_Null
360 )
361 || ( !cmd.mGlobal
362 && !cmd.mMachine)
363 || ( cmd.mGlobal
364 && !cmd.mFilter.mRemote.isEmpty())
365 )
366 {
367 return errorSyntax(USAGE_USBFILTER_ADD, "Mandatory options not supplied");
368 }
369 }
370 break;
371 }
372
373 case USBFilterCmd::Remove:
374 {
375 /* at least: 0: command, 1: index, 2: --target, 3: <target value> */
376 if (a->argc < 4)
377 return errorSyntax(USAGE_USBFILTER_REMOVE, "Not enough parameters");
378
379 for (int i = 2; i < a->argc; i++)
380 {
381 if ( !strcmp(a->argv[i], "--target")
382 || !strcmp(a->argv[i], "-target"))
383 {
384 if (a->argc <= i + 1 || !*a->argv[i+1])
385 return errorArgument("Missing argument to '%s'", a->argv[i]);
386 i++;
387 if (!strcmp(a->argv[i], "global"))
388 cmd.mGlobal = true;
389 else
390 {
391 /* assume it's a UUID of a machine */
392 rc = a->virtualBox->GetMachine(Bstr(a->argv[i]).raw(),
393 cmd.mMachine.asOutParam());
394 if (FAILED(rc) || !cmd.mMachine)
395 {
396 /* must be a name */
397 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[i]).raw(),
398 cmd.mMachine.asOutParam()), 1);
399 }
400 }
401 }
402 }
403
404 // mandatory options
405 if (!cmd.mGlobal && !cmd.mMachine)
406 return errorSyntax(USAGE_USBFILTER_REMOVE, "Mandatory options not supplied");
407
408 break;
409 }
410
411 default: break;
412 }
413
414 USBFilterCmd::USBFilter &f = cmd.mFilter;
415
416 ComPtr <IHost> host;
417 ComPtr <IUSBController> ctl;
418 if (cmd.mGlobal)
419 CHECK_ERROR_RET(a->virtualBox, COMGETTER(Host)(host.asOutParam()), 1);
420 else
421 {
422 /* open a session for the VM */
423 CHECK_ERROR_RET(cmd.mMachine, LockMachine(a->session, LockType_Write), 1);
424 /* get the mutable session machine */
425 a->session->COMGETTER(Machine)(cmd.mMachine.asOutParam());
426 /* and get the USB controller */
427 CHECK_ERROR_RET(cmd.mMachine, COMGETTER(USBController)(ctl.asOutParam()), 1);
428 }
429
430 switch (cmd.mAction)
431 {
432 case USBFilterCmd::Add:
433 {
434 if (cmd.mGlobal)
435 {
436 ComPtr <IHostUSBDeviceFilter> flt;
437 CHECK_ERROR_BREAK(host, CreateUSBDeviceFilter(f.mName.raw(),
438 flt.asOutParam()));
439
440 if (!f.mActive.isNull())
441 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
442 if (!f.mVendorId.isEmpty())
443 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
444 if (!f.mProductId.isEmpty())
445 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
446 if (!f.mRevision.isEmpty())
447 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
448 if (!f.mManufacturer.isEmpty())
449 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
450 if (!f.mSerialNumber.isEmpty())
451 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
452 if (!f.mMaskedInterfaces.isNull())
453 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
454
455 if (f.mAction != USBDeviceFilterAction_Null)
456 CHECK_ERROR_BREAK(flt, COMSETTER(Action)(f.mAction));
457
458 CHECK_ERROR_BREAK(host, InsertUSBDeviceFilter(cmd.mIndex, flt));
459 }
460 else
461 {
462 ComPtr <IUSBDeviceFilter> flt;
463 CHECK_ERROR_BREAK(ctl, CreateDeviceFilter(f.mName.raw(),
464 flt.asOutParam()));
465
466 if (!f.mActive.isNull())
467 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
468 if (!f.mVendorId.isEmpty())
469 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
470 if (!f.mProductId.isEmpty())
471 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
472 if (!f.mRevision.isEmpty())
473 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
474 if (!f.mManufacturer.isEmpty())
475 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
476 if (!f.mRemote.isEmpty())
477 CHECK_ERROR_BREAK(flt, COMSETTER(Remote)(f.mRemote.raw()));
478 if (!f.mSerialNumber.isEmpty())
479 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
480 if (!f.mMaskedInterfaces.isNull())
481 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
482
483 CHECK_ERROR_BREAK(ctl, InsertDeviceFilter(cmd.mIndex, flt));
484 }
485 break;
486 }
487 case USBFilterCmd::Modify:
488 {
489 if (cmd.mGlobal)
490 {
491 SafeIfaceArray <IHostUSBDeviceFilter> coll;
492 CHECK_ERROR_BREAK(host, COMGETTER(USBDeviceFilters)(ComSafeArrayAsOutParam(coll)));
493
494 ComPtr <IHostUSBDeviceFilter> flt = coll[cmd.mIndex];
495
496 if (!f.mName.isEmpty())
497 CHECK_ERROR_BREAK(flt, COMSETTER(Name)(f.mName.raw()));
498 if (!f.mActive.isNull())
499 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
500 if (!f.mVendorId.isEmpty())
501 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
502 if (!f.mProductId.isEmpty())
503 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
504 if (!f.mRevision.isEmpty())
505 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
506 if (!f.mManufacturer.isEmpty())
507 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
508 if (!f.mSerialNumber.isEmpty())
509 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
510 if (!f.mMaskedInterfaces.isNull())
511 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
512
513 if (f.mAction != USBDeviceFilterAction_Null)
514 CHECK_ERROR_BREAK(flt, COMSETTER(Action)(f.mAction));
515 }
516 else
517 {
518 SafeIfaceArray <IUSBDeviceFilter> coll;
519 CHECK_ERROR_BREAK(ctl, COMGETTER(DeviceFilters)(ComSafeArrayAsOutParam(coll)));
520
521 ComPtr <IUSBDeviceFilter> flt = coll[cmd.mIndex];
522
523 if (!f.mName.isEmpty())
524 CHECK_ERROR_BREAK(flt, COMSETTER(Name)(f.mName.raw()));
525 if (!f.mActive.isNull())
526 CHECK_ERROR_BREAK(flt, COMSETTER(Active)(f.mActive));
527 if (!f.mVendorId.isEmpty())
528 CHECK_ERROR_BREAK(flt, COMSETTER(VendorId)(f.mVendorId.raw()));
529 if (!f.mProductId.isEmpty())
530 CHECK_ERROR_BREAK(flt, COMSETTER(ProductId)(f.mProductId.raw()));
531 if (!f.mRevision.isEmpty())
532 CHECK_ERROR_BREAK(flt, COMSETTER(Revision)(f.mRevision.raw()));
533 if (!f.mManufacturer.isEmpty())
534 CHECK_ERROR_BREAK(flt, COMSETTER(Manufacturer)(f.mManufacturer.raw()));
535 if (!f.mRemote.isEmpty())
536 CHECK_ERROR_BREAK(flt, COMSETTER(Remote)(f.mRemote.raw()));
537 if (!f.mSerialNumber.isEmpty())
538 CHECK_ERROR_BREAK(flt, COMSETTER(SerialNumber)(f.mSerialNumber.raw()));
539 if (!f.mMaskedInterfaces.isNull())
540 CHECK_ERROR_BREAK(flt, COMSETTER(MaskedInterfaces)(f.mMaskedInterfaces));
541 }
542 break;
543 }
544 case USBFilterCmd::Remove:
545 {
546 if (cmd.mGlobal)
547 {
548 ComPtr <IHostUSBDeviceFilter> flt;
549 CHECK_ERROR_BREAK(host, RemoveUSBDeviceFilter(cmd.mIndex));
550 }
551 else
552 {
553 ComPtr <IUSBDeviceFilter> flt;
554 CHECK_ERROR_BREAK(ctl, RemoveDeviceFilter(cmd.mIndex, flt.asOutParam()));
555 }
556 break;
557 }
558 default:
559 break;
560 }
561
562 if (cmd.mMachine)
563 {
564 if (SUCCEEDED(rc))
565 {
566 /* commit the session */
567 CHECK_ERROR(cmd.mMachine, SaveSettings());
568 }
569 /* close the session */
570 a->session->UnlockMachine();
571 }
572
573 return SUCCEEDED(rc) ? 0 : 1;
574}
575/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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