PageRenderTime 48ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/VBox/Frontends/VBoxManage/VBoxManageUSB.cpp

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