VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageStorageController.cpp@ 23809

Last change on this file since 23809 was 23809, checked in by vboxsync, 15 years ago

VBoxManage: storagectl => name, floppy => fdd, type => controller

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 25.2 KB
Line 
1/* $Id: VBoxManageStorageController.cpp 23809 2009-10-15 16:07:58Z vboxsync $ */
2/** @file
3 * VBoxManage - The storage controller related commands.
4 */
5
6/*
7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22#ifndef VBOX_ONLY_DOCS
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#include <VBox/com/com.h>
28#include <VBox/com/array.h>
29#include <VBox/com/ErrorInfo.h>
30#include <VBox/com/errorprint.h>
31#include <VBox/com/VirtualBox.h>
32
33#include <iprt/path.h>
34#include <iprt/param.h>
35#include <iprt/string.h>
36#include <iprt/ctype.h>
37#include <iprt/stream.h>
38#include <iprt/getopt.h>
39#include <VBox/log.h>
40
41#include "VBoxManage.h"
42using namespace com;
43
44
45// funcs
46///////////////////////////////////////////////////////////////////////////////
47
48
49static const RTGETOPTDEF g_aAttachDiskOptions[] =
50{
51 { "--type", 't', RTGETOPT_REQ_STRING },
52 { "--file", 'f', RTGETOPT_REQ_STRING },
53 { "--controller", 'c', RTGETOPT_REQ_STRING },
54 { "--port", 'p', RTGETOPT_REQ_UINT32 },
55 { "--device", 'd', RTGETOPT_REQ_UINT32 },
56};
57
58int handleAttachDisk(HandlerArg *a)
59{
60 int c;
61 HRESULT rc = S_OK;
62 ULONG port = 0;
63 ULONG device = 0;
64 bool fRunTime = false;
65 const char *pszCtl = NULL;
66 const char *pszType = NULL;
67 const char *pszFile = NULL;
68 Bstr machineuuid (a->argv[0]);
69 RTGETOPTUNION ValueUnion;
70 RTGETOPTSTATE GetState;
71 ComPtr<IMachine> machine;
72 ComPtr<IStorageController> storageCtl;
73
74 if (a->argc < 11)
75 return errorSyntax(USAGE_ATTACHDISK, "Too few parameters");
76 else if (a->argc > 11)
77 return errorSyntax(USAGE_ATTACHDISK, "Too many parameters");
78
79 RTGetOptInit (&GetState, a->argc, a->argv, g_aAttachDiskOptions,
80 RT_ELEMENTS(g_aAttachDiskOptions), 1, 0 /* fFlags */);
81
82 while ( SUCCEEDED(rc)
83 && (c = RTGetOpt(&GetState, &ValueUnion)))
84 {
85 switch (c)
86 {
87 case 't': // type <dvd|hdd|fdd>
88 {
89 if (ValueUnion.psz)
90 pszType = ValueUnion.psz;
91 else
92 rc = E_FAIL;
93 break;
94 }
95
96 case 'f': // file <none|uuid|filename|host:<drive>>
97 {
98 if (ValueUnion.psz)
99 pszFile = ValueUnion.psz;
100 else
101 rc = E_FAIL;
102 break;
103 }
104
105 case 'c': // controller name
106 {
107 if (ValueUnion.psz)
108 pszCtl = ValueUnion.psz;
109 else
110 rc = E_FAIL;
111 break;
112 }
113
114 case 'p': // port
115 {
116 port = ValueUnion.u32;
117 break;
118 }
119
120 case 'd': // device
121 {
122 device = ValueUnion.u32;
123 break;
124 }
125
126 default:
127 {
128 errorGetOpt(USAGE_ATTACHDISK, c, &ValueUnion);
129 rc = E_FAIL;
130 break;
131 }
132 }
133 }
134
135 if (FAILED(rc))
136 return 1;
137
138 if ( fRunTime
139 && !RTStrICmp(pszType, "hdd"))
140 {
141 errorArgument("Harddisk's can't be changed while the VM is still running\n");
142 return 1;
143 }
144
145 /* try to find the given machine */
146 if (!Guid(machineuuid).isEmpty())
147 {
148 CHECK_ERROR_RET (a->virtualBox, GetMachine (machineuuid, machine.asOutParam()), 1);
149 }
150 else
151 {
152 CHECK_ERROR_RET (a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()), 1);
153 machine->COMGETTER(Id)(machineuuid.asOutParam());
154 }
155
156 /* open a session for the VM */
157 rc = a->virtualBox->OpenSession(a->session, machineuuid);
158 if (FAILED(rc))
159 {
160 /* try to open an existing session for the VM */
161 CHECK_ERROR_RET (a->virtualBox, OpenExistingSession (a->session, machineuuid), 1);
162 fRunTime = true;
163 }
164
165 /* get the mutable session machine */
166 a->session->COMGETTER(Machine)(machine.asOutParam());
167
168 /* check if the storage controller is present */
169 rc = machine->GetStorageControllerByName(Bstr(pszCtl), storageCtl.asOutParam());
170 if (FAILED(rc))
171 return errorSyntax(USAGE_ATTACHDISK, "Couldn't find the controller with the name: '%s'\n", pszCtl);
172
173 if (!RTStrICmp(pszType, "dvd"))
174 {
175 if (!RTStrICmp(pszFile, "null"))
176 {
177 if (fRunTime)
178 {
179 errorArgument("DVD Drive's can't be removed while the VM is still running\n");
180 rc = E_FAIL;
181 }
182 else
183 {
184 CHECK_ERROR (machine, DetachDevice(Bstr(pszCtl), port, device));
185 }
186 }
187 else
188 {
189 Bstr uuid;
190 ComPtr<IMedium> dvdMedium;
191
192 if (!fRunTime)
193 {
194 ComPtr<IMediumAttachment> mediumAttachement;
195
196 /* check if there is a dvd drive at the given location, if not attach one */
197 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachement.asOutParam());
198 if (SUCCEEDED(rc))
199 {
200 DeviceType_T deviceType;
201 mediumAttachement->COMGETTER(Type) (&deviceType);
202
203 if (deviceType != DeviceType_DVD)
204 {
205 machine->DetachDevice(Bstr(pszCtl), port, device);
206 rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, NULL);
207 }
208 }
209 else
210 {
211 rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, NULL);
212 }
213 }
214
215 /* Attach/Detach the dvd medium now */
216 do
217 {
218 /* unmount? */
219 if (!RTStrICmp(pszFile, "none"))
220 {
221 /* nothing to do, NULL object will cause unmount */
222 }
223 /* host drive? */
224 else if (!RTStrNICmp(pszFile, "host:", 5))
225 {
226 ComPtr<IHost> host;
227 CHECK_ERROR (a->virtualBox, COMGETTER(Host)(host.asOutParam()));
228 rc = host->FindHostDVDDrive(Bstr(pszFile + 5), dvdMedium.asOutParam());
229 if (!dvdMedium)
230 {
231 /* 2nd try: try with the real name, important on Linux+libhal */
232 char szPathReal[RTPATH_MAX];
233 if (RT_FAILURE(RTPathReal(pszFile + 5, szPathReal, sizeof(szPathReal))))
234 {
235 errorArgument("Invalid host DVD drive name \"%s\"", pszFile + 5);
236 rc = E_FAIL;
237 break;
238 }
239 rc = host->FindHostDVDDrive(Bstr(szPathReal), dvdMedium.asOutParam());
240 if (!dvdMedium)
241 {
242 errorArgument("Invalid host DVD drive name \"%s\"", pszFile + 5);
243 rc = E_FAIL;
244 break;
245 }
246 }
247 }
248 else
249 {
250 /* first assume it's a UUID */
251 uuid = pszFile;
252 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
253 if (FAILED(rc) || !dvdMedium)
254 {
255 /* must be a filename, check if it's in the collection */
256 rc = a->virtualBox->FindDVDImage(Bstr(pszFile), dvdMedium.asOutParam());
257 /* not registered, do that on the fly */
258 if (!dvdMedium)
259 {
260 Bstr emptyUUID;
261 CHECK_ERROR (a->virtualBox, OpenDVDImage(Bstr(pszFile),
262 emptyUUID, dvdMedium.asOutParam()));
263 }
264 }
265 if (!dvdMedium)
266 {
267 rc = E_FAIL;
268 break;
269 }
270 }
271 }
272 while (0);
273
274 if (dvdMedium)
275 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
276 if (SUCCEEDED(rc))
277 CHECK_ERROR (machine, MountMedium(Bstr(pszCtl), port, device, uuid));
278 }
279 }
280 else if ( !RTStrICmp(pszType, "hdd")
281 && !fRunTime)
282 {
283 Bstr uuid(pszFile);
284
285 if ( !RTStrICmp(pszFile, "none")
286 || !RTStrICmp(pszFile, "null"))
287 {
288 machine->DetachDevice(Bstr(pszCtl), port, device);
289 }
290 else
291 {
292 ComPtr<IMediumAttachment> mediumAttachement;
293
294 /* if there is a dvd drive at the given location, remove it */
295 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachement.asOutParam());
296 if (SUCCEEDED(rc))
297 {
298 DeviceType_T deviceType;
299 mediumAttachement->COMGETTER(Type) (&deviceType);
300
301 if (deviceType != DeviceType_HardDisk)
302 machine->DetachDevice(Bstr(pszCtl), port, device);
303 }
304
305 /* first guess is that it's a UUID */
306 ComPtr<IMedium> hardDisk;
307 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
308
309 /* not successful? Then it must be a filename */
310 if (!hardDisk)
311 {
312 rc = a->virtualBox->FindHardDisk(Bstr(pszFile), hardDisk.asOutParam());
313 if (FAILED(rc))
314 {
315 /* open the new hard disk object */
316 CHECK_ERROR (a->virtualBox,
317 OpenHardDisk(Bstr(pszFile),
318 AccessMode_ReadWrite, false, Bstr(""),
319 false, Bstr(""), hardDisk.asOutParam()));
320 }
321 }
322
323 if (hardDisk)
324 {
325 hardDisk->COMGETTER(Id)(uuid.asOutParam());
326 CHECK_ERROR (machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_HardDisk, uuid));
327 }
328 else
329 rc = E_FAIL;
330 }
331 }
332 else if (!RTStrICmp(pszType, "fdd"))
333 {
334 ComPtr<IMediumAttachment> floppyAttachment;
335 machine->GetMediumAttachment(Bstr(pszCtl), port, device, floppyAttachment.asOutParam());
336
337 if (!RTStrICmp(pszFile, "null"))
338 {
339 if (fRunTime)
340 {
341 errorArgument("Floppy Drive's can't be removed while the VM is still running\n");
342 rc = E_FAIL;
343 }
344 else
345 {
346 if (floppyAttachment)
347 CHECK_ERROR (machine, DetachDevice(Bstr(pszCtl), port, device));
348 }
349 }
350 else
351 {
352 Bstr uuid;
353 ComPtr<IMedium> floppyMedium;
354
355 if ( !fRunTime
356 && !floppyAttachment)
357 CHECK_ERROR (machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_Floppy, NULL));
358
359 /* unmount? */
360 if (!RTStrICmp(pszFile, "none"))
361 {
362 /* nothing to do, NULL object will cause unmount */
363 }
364 /* host drive? */
365 else if (!RTStrNICmp(pszFile, "host:", 5))
366 {
367 ComPtr<IHost> host;
368
369 CHECK_ERROR (a->virtualBox, COMGETTER(Host)(host.asOutParam()));
370 rc = host->FindHostFloppyDrive(Bstr(pszFile + 5), floppyMedium.asOutParam());
371 if (!floppyMedium)
372 {
373 errorArgument("Invalid host floppy drive name \"%s\"", pszFile + 5);
374 rc = E_FAIL;
375 }
376 }
377 else
378 {
379 /* first assume it's a UUID */
380 uuid = pszFile;
381 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
382 if (FAILED(rc) || !floppyMedium)
383 {
384 /* must be a filename, check if it's in the collection */
385 rc = a->virtualBox->FindFloppyImage(Bstr(pszFile), floppyMedium.asOutParam());
386 /* not registered, do that on the fly */
387 if (!floppyMedium)
388 {
389 Bstr emptyUUID;
390 CHECK_ERROR (a->virtualBox,
391 OpenFloppyImage(Bstr(pszFile),
392 emptyUUID,
393 floppyMedium.asOutParam()));
394 }
395 }
396
397 if (!floppyMedium)
398 rc = E_FAIL;
399 }
400
401 if (floppyMedium)
402 floppyMedium->COMGETTER(Id)(uuid.asOutParam());
403 if (SUCCEEDED(rc))
404 CHECK_ERROR (machine, MountMedium(Bstr(pszCtl), port, device, uuid));
405 }
406 }
407
408 /* commit changes */
409 if (SUCCEEDED(rc))
410 CHECK_ERROR (machine, SaveSettings());
411
412 /* it's important to always close sessions */
413 a->session->Close();
414
415 return SUCCEEDED(rc) ? 0 : 1;
416}
417
418
419static const RTGETOPTDEF g_aStorageControllerOptions[] =
420{
421 { "--name", 'n', RTGETOPT_REQ_STRING },
422 { "--add", 'a', RTGETOPT_REQ_STRING },
423 { "--controller", 't', RTGETOPT_REQ_STRING },
424 { "--port", 'p', RTGETOPT_REQ_UINT32 },
425 { "--device", 'd', RTGETOPT_REQ_UINT32 },
426 { "--passthrough", 'h', RTGETOPT_REQ_STRING },
427 { "--sataideemulation", 'e', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX },
428 { "--sataportcount", 'c', RTGETOPT_REQ_UINT32 },
429 { "--remove", 'r', RTGETOPT_REQ_NOTHING },
430};
431
432int handleStorageController(HandlerArg *a)
433{
434 int c;
435 HRESULT rc = S_OK;
436 const char *pszCtl = NULL;
437 const char *pszBusType = NULL;
438 const char *pszCtlType = NULL;
439 const char *pszPassThrough = NULL;
440 ULONG cPass = 0;
441 ULONG satabootdev = ~0U;
442 ULONG sataidedev = ~0U;
443 ULONG sataportcount = ~0U;
444 ULONG port = ~0U;
445 ULONG device = ~0U;
446 bool fRemoveCtl = false;
447 Bstr machineuuid (a->argv[0]);
448 ComPtr<IMachine> machine;
449 RTGETOPTUNION ValueUnion;
450 RTGETOPTSTATE GetState;
451
452 if (a->argc < 4)
453 return errorSyntax(USAGE_STORAGECONTROLLER, "Too few parameters");
454
455 RTGetOptInit (&GetState, a->argc, a->argv, g_aStorageControllerOptions,
456 RT_ELEMENTS(g_aStorageControllerOptions), 1, 0 /* fFlags */);
457
458 while ( SUCCEEDED(rc)
459 && (c = RTGetOpt(&GetState, &ValueUnion)))
460 {
461 switch (c)
462 {
463 case 'n': // controller name
464 {
465 if (ValueUnion.psz)
466 pszCtl = ValueUnion.psz;
467 else
468 rc = E_FAIL;
469 break;
470 }
471
472 case 'a': // controller bus type <ide/sata/scsi/floppy>
473 {
474 if (ValueUnion.psz)
475 pszBusType = ValueUnion.psz;
476 else
477 rc = E_FAIL;
478 break;
479 }
480
481 case 't': // controller <lsilogic/buslogic/intelahci/piix3/piix4/ich6/i82078>
482 {
483 if (ValueUnion.psz)
484 pszCtlType = ValueUnion.psz;
485 else
486 rc = E_FAIL;
487 break;
488 }
489
490 case 'p': // port
491 {
492 port = ValueUnion.u32;
493 cPass++;
494 break;
495 }
496
497 case 'd': // device
498 {
499 device = ValueUnion.u32;
500 cPass++;
501 break;
502 }
503
504 case 'h': // passthrough
505 {
506 if (ValueUnion.psz)
507 {
508 pszPassThrough = ValueUnion.psz;
509 cPass++;
510 }
511 else
512 rc = E_FAIL;
513 break;
514 }
515
516 case 'e': // sataideemulation
517 {
518 if ((GetState.uIndex < 1) && (GetState.uIndex > 4))
519 return errorSyntax(USAGE_STORAGECONTROLLER,
520 "Missing or Invalid SATA boot slot number in '%s'",
521 GetState.pDef->pszLong);
522
523 if ((ValueUnion.u32 < 1) && (ValueUnion.u32 > 30))
524 return errorSyntax(USAGE_STORAGECONTROLLER,
525 "Missing or Invalid SATA port number in '%s'",
526 GetState.pDef->pszLong);
527
528 satabootdev = GetState.uIndex;
529 sataidedev = ValueUnion.u32;
530 break;
531 }
532
533 case 'c': // sataportcount
534 {
535 sataportcount = ValueUnion.u32;
536 break;
537 }
538
539 case 'r': // remove controller
540 {
541 fRemoveCtl = true;
542 break;
543 }
544
545 default:
546 {
547 errorGetOpt(USAGE_STORAGECONTROLLER, c, &ValueUnion);
548 rc = E_FAIL;
549 break;
550 }
551 }
552 }
553
554 if (FAILED(rc))
555 return 1;
556
557 /* try to find the given machine */
558 if (!Guid(machineuuid).isEmpty())
559 {
560 CHECK_ERROR_RET (a->virtualBox, GetMachine (machineuuid, machine.asOutParam()), 1);
561 }
562 else
563 {
564 CHECK_ERROR_RET (a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()), 1);
565 machine->COMGETTER(Id)(machineuuid.asOutParam());
566 }
567
568 /* open a session for the VM */
569 CHECK_ERROR_RET (a->virtualBox, OpenSession (a->session, machineuuid), 1);
570
571 /* get the mutable session machine */
572 a->session->COMGETTER(Machine)(machine.asOutParam());
573
574 if (!pszCtl)
575 {
576 errorSyntax(USAGE_STORAGECONTROLLER, "Storage Controller Name not specified\n");
577 return 1;
578 }
579
580 if (cPass != 0 && cPass != 3)
581 {
582 errorSyntax(USAGE_STORAGECONTROLLER,
583 "All three options (--passthrough, --port, --device)\n"
584 "need to be specified for dvd passthrough to be applied\n");
585 return 1;
586 }
587
588 if (fRemoveCtl)
589 {
590 com::SafeIfaceArray<IMediumAttachment> mediumAttachments;
591
592 CHECK_ERROR (machine,
593 GetMediumAttachmentsOfController(Bstr(pszCtl),
594 ComSafeArrayAsOutParam(mediumAttachments)));
595 for (size_t i = 0; i < mediumAttachments.size(); ++ i)
596 {
597 ComPtr<IMediumAttachment> mediumAttach = mediumAttachments[i];
598 LONG cPort = 0;
599 LONG cDevice = 0;
600
601 CHECK_ERROR (mediumAttach, COMGETTER(Port)(&cPort));
602 CHECK_ERROR (mediumAttach, COMGETTER(Device)(&cDevice));
603 CHECK_ERROR (machine, DetachDevice(Bstr(pszCtl), cPort, cDevice));
604 }
605
606 if (SUCCEEDED(rc))
607 CHECK_ERROR (machine, RemoveStorageController(Bstr(pszCtl)));
608 else
609 errorArgument("Can't detach the devices connected to '%s' Controller\n"
610 "and thus its removal failed.", pszCtl);
611 }
612 else
613 {
614 if (pszBusType)
615 {
616 ComPtr<IStorageController> ctl;
617
618 if (!RTStrICmp(pszBusType, "ide"))
619 {
620 CHECK_ERROR (machine, AddStorageController(Bstr(pszCtl), StorageBus_IDE, ctl.asOutParam()));
621 }
622 else if (!RTStrICmp(pszBusType, "sata"))
623 {
624 CHECK_ERROR (machine, AddStorageController(Bstr(pszCtl), StorageBus_SATA, ctl.asOutParam()));
625 }
626 else if (!RTStrICmp(pszBusType, "scsi"))
627 {
628 CHECK_ERROR (machine, AddStorageController(Bstr(pszCtl), StorageBus_SCSI, ctl.asOutParam()));
629 }
630 else if (!RTStrICmp(pszBusType, "floppy"))
631 {
632 CHECK_ERROR (machine, AddStorageController(Bstr(pszCtl), StorageBus_Floppy, ctl.asOutParam()));
633 }
634 else
635 {
636 errorArgument("Invalid --add argument '%s'", pszBusType);
637 rc = E_FAIL;
638 }
639 }
640
641 if ( pszCtlType
642 && SUCCEEDED(rc))
643 {
644 ComPtr<IStorageController> ctl;
645
646 CHECK_ERROR (machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
647
648 if (SUCCEEDED(rc))
649 {
650 if (!RTStrICmp(pszCtlType, "lsilogic"))
651 {
652 CHECK_ERROR (ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogic));
653 }
654 else if (!RTStrICmp(pszCtlType, "buslogic"))
655 {
656 CHECK_ERROR (ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic));
657 }
658 else if (!RTStrICmp(pszCtlType, "intelahci"))
659 {
660 CHECK_ERROR (ctl, COMSETTER(ControllerType)(StorageControllerType_IntelAhci));
661 }
662 else if (!RTStrICmp(pszCtlType, "piix3"))
663 {
664 CHECK_ERROR (ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX3));
665 }
666 else if (!RTStrICmp(pszCtlType, "piix4"))
667 {
668 CHECK_ERROR (ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX4));
669 }
670 else if (!RTStrICmp(pszCtlType, "ich6"))
671 {
672 CHECK_ERROR (ctl, COMSETTER(ControllerType)(StorageControllerType_ICH6));
673 }
674 else if (!RTStrICmp(pszCtlType, "i82078"))
675 {
676 CHECK_ERROR (ctl, COMSETTER(ControllerType)(StorageControllerType_I82078));
677 }
678 else
679 {
680 errorArgument("Invalid --type argument '%s'", pszCtlType);
681 rc = E_FAIL;
682 }
683 }
684 else
685 {
686 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
687 rc = E_FAIL;
688 }
689 }
690
691 if ( (cPass == 3)
692 && SUCCEEDED(rc))
693 {
694 ComPtr<IMediumAttachment> mattach;
695
696 CHECK_ERROR (machine, GetMediumAttachment(Bstr(pszCtl), port, device, mattach.asOutParam()));
697
698 if (SUCCEEDED(rc))
699 {
700 if (!RTStrICmp(pszPassThrough, "on"))
701 {
702 CHECK_ERROR (mattach, COMSETTER(Passthrough)(true));
703 }
704 else if (!RTStrICmp(pszPassThrough, "off"))
705 {
706 CHECK_ERROR (mattach, COMSETTER(Passthrough)(false));
707 }
708 else
709 {
710 errorArgument("Invalid --passthrough argument '%s'", pszPassThrough);
711 rc = E_FAIL;
712 }
713 }
714 else
715 {
716 errorArgument("Couldn't find the controller attachment for the controller '%s'\n", pszCtl);
717 rc = E_FAIL;
718 }
719 }
720
721 if ( (sataportcount != ~0U)
722 && SUCCEEDED(rc))
723 {
724 ComPtr<IStorageController> ctl;
725
726 CHECK_ERROR (machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
727
728 if (SUCCEEDED(rc))
729 {
730 CHECK_ERROR (ctl, COMSETTER(PortCount)(sataportcount));
731 }
732 else
733 {
734 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
735 rc = E_FAIL;
736 }
737 }
738
739 if ( (sataidedev != ~0U)
740 && (satabootdev != ~0U)
741 && SUCCEEDED(rc))
742 {
743 ComPtr<IStorageController> ctl;
744
745 CHECK_ERROR (machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
746
747 if (SUCCEEDED(rc))
748 {
749 CHECK_ERROR (ctl, SetIDEEmulationPort(satabootdev, sataidedev));
750 }
751 else
752 {
753 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
754 rc = E_FAIL;
755 }
756 }
757 }
758
759 /* commit changes */
760 if (SUCCEEDED(rc))
761 CHECK_ERROR (machine, SaveSettings());
762
763 /* it's important to always close sessions */
764 a->session->Close();
765
766 return SUCCEEDED(rc) ? 0 : 1;
767}
768
769#endif /* !VBOX_ONLY_DOCS */
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