VirtualBox

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

Last change on this file since 24175 was 24026, checked in by vboxsync, 16 years ago

VBoxManageStorageController.cpp: Don't use doxygen comments (/ */) for normal code comments.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 29.2 KB
Line 
1/* $Id: VBoxManageStorageController.cpp 24026 2009-10-23 12:16:55Z 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_aStorageAttachOptions[] =
50{
51 { "--storagectl", 's', RTGETOPT_REQ_STRING },
52 { "--port", 'p', RTGETOPT_REQ_UINT32 },
53 { "--device", 'd', RTGETOPT_REQ_UINT32 },
54 { "--medium", 'm', RTGETOPT_REQ_STRING },
55 { "--type", 't', RTGETOPT_REQ_STRING },
56 { "--passthrough", 'h', RTGETOPT_REQ_STRING },
57};
58
59int handleStorageAttach(HandlerArg *a)
60{
61 int c;
62 HRESULT rc = S_OK;
63 ULONG port = ~0U;
64 ULONG device = ~0U;
65 bool fRunTime = false;
66 const char *pszCtl = NULL;
67 const char *pszType = NULL;
68 const char *pszMedium = NULL;
69 const char *pszPassThrough = NULL;
70 Bstr machineuuid (a->argv[0]);
71 RTGETOPTUNION ValueUnion;
72 RTGETOPTSTATE GetState;
73 ComPtr<IMachine> machine;
74 ComPtr<IStorageController> storageCtl;
75
76 if (a->argc < 9)
77 return errorSyntax(USAGE_STORAGEATTACH, "Too few parameters");
78 else if (a->argc > 13)
79 return errorSyntax(USAGE_STORAGEATTACH, "Too many parameters");
80
81 RTGetOptInit(&GetState, a->argc, a->argv, g_aStorageAttachOptions,
82 RT_ELEMENTS(g_aStorageAttachOptions), 1, 0 /* fFlags */);
83
84 while ( SUCCEEDED(rc)
85 && (c = RTGetOpt(&GetState, &ValueUnion)))
86 {
87 switch (c)
88 {
89 case 's': // storage controller name
90 {
91 if (ValueUnion.psz)
92 pszCtl = ValueUnion.psz;
93 else
94 rc = E_FAIL;
95 break;
96 }
97
98 case 'p': // port
99 {
100 port = ValueUnion.u32;
101 break;
102 }
103
104 case 'd': // device
105 {
106 device = ValueUnion.u32;
107 break;
108 }
109
110 case 'm': // medium <none|emptydrive|uuid|filename|host:<drive>>
111 {
112 if (ValueUnion.psz)
113 pszMedium = ValueUnion.psz;
114 else
115 rc = E_FAIL;
116 break;
117 }
118
119 case 't': // type <dvddrive|hdd|fdd>
120 {
121 if (ValueUnion.psz)
122 pszType = ValueUnion.psz;
123 else
124 rc = E_FAIL;
125 break;
126 }
127
128 case 'h': // passthrough <on|off>
129 {
130 if (ValueUnion.psz)
131 pszPassThrough = ValueUnion.psz;
132 else
133 rc = E_FAIL;
134 break;
135 }
136
137 default:
138 {
139 errorGetOpt(USAGE_STORAGEATTACH, c, &ValueUnion);
140 rc = E_FAIL;
141 break;
142 }
143 }
144 }
145
146 if ( FAILED(rc)
147 || !pszCtl
148 || port == ~0U
149 || device == ~0U)
150 {
151 errorGetOpt(USAGE_STORAGEATTACH, c, &ValueUnion);
152 return 1;
153 }
154
155 /* try to find the given machine */
156 if (!Guid(machineuuid).isEmpty())
157 {
158 CHECK_ERROR_RET(a->virtualBox, GetMachine(machineuuid, machine.asOutParam()), 1);
159 }
160 else
161 {
162 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()), 1);
163 machine->COMGETTER(Id)(machineuuid.asOutParam());
164 }
165
166 /* open a session for the VM */
167 rc = a->virtualBox->OpenSession(a->session, machineuuid);
168 if (FAILED(rc))
169 {
170 /* try to open an existing session for the VM */
171 CHECK_ERROR_RET(a->virtualBox, OpenExistingSession(a->session, machineuuid), 1);
172 fRunTime = true;
173 }
174
175 if ( fRunTime
176 && ( !RTStrICmp(pszMedium, "none")
177 || !RTStrICmp(pszType, "hdd")))
178 {
179 errorArgument("DVD/HardDisk Drives can't be changed while the VM is still running\n");
180 goto leave;
181 }
182
183 if (fRunTime && pszPassThrough)
184 {
185 errorArgument("Drive passthrough state can't be changed while the VM is still running\n");
186 goto leave;
187 }
188
189 /* get the mutable session machine */
190 a->session->COMGETTER(Machine)(machine.asOutParam());
191
192 /* check if the storage controller is present */
193 rc = machine->GetStorageControllerByName(Bstr(pszCtl), storageCtl.asOutParam());
194 if (FAILED(rc))
195 {
196 errorSyntax(USAGE_STORAGEATTACH, "Couldn't find the controller with the name: '%s'\n", pszCtl);
197 goto leave;
198 }
199
200 if (!RTStrICmp(pszMedium, "none"))
201 {
202 CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl), port, device));
203 }
204 else if (!RTStrICmp(pszMedium, "emptydrive"))
205 {
206 if (fRunTime)
207 {
208 ComPtr<IMediumAttachment> mediumAttachment;
209 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachment.asOutParam());
210 if (SUCCEEDED(rc))
211 {
212 DeviceType_T deviceType;
213 mediumAttachment->COMGETTER(Type)(&deviceType);
214
215 if ( (deviceType == DeviceType_DVD)
216 || (deviceType == DeviceType_Floppy))
217 {
218 /* just unmount the floppy/dvd */
219 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl), port, device, Bstr("")));
220 }
221 else
222 {
223 errorArgument("No DVD/Floppy Drive attached to the controller '%s'"
224 "at the port: %u, device: %u", pszCtl, port, device);
225 goto leave;
226 }
227 }
228 else
229 {
230 errorArgument("No DVD/Floppy Drive attached to the controller '%s'"
231 "at the port: %u, device: %u", pszCtl, port, device);
232 goto leave;
233 }
234
235 }
236 else
237 {
238 StorageBus_T storageBus = StorageBus_Null;
239 DeviceType_T deviceType = DeviceType_Null;
240
241 CHECK_ERROR(storageCtl, COMGETTER(Bus)(&storageBus));
242
243 if (storageBus == StorageBus_Floppy)
244 deviceType = DeviceType_Floppy;
245 else
246 deviceType = DeviceType_DVD;
247
248 /* attach a empty floppy/dvd drive after removing previous attachment */
249 machine->DetachDevice(Bstr(pszCtl), port, device);
250 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, deviceType, Bstr("")));
251 }
252 }
253 else
254 {
255 {
256 /*
257 * try to determine the type of the drive from the
258 * storage controller chipset, the attachment and
259 * the medium being attached
260 */
261 StorageControllerType_T ctlType = StorageControllerType_Null;
262 CHECK_ERROR(storageCtl, COMGETTER(ControllerType)(&ctlType));
263 if (ctlType == StorageControllerType_I82078)
264 {
265 /*
266 * floppy controller found so lets assume the medium
267 * given by the user is also a floppy image or floppy
268 * host drive
269 */
270 pszType = "fdd";
271 }
272 else
273 {
274 /*
275 * for SATA/SCSI/IDE it is hard to tell if it is a harddisk or
276 * a dvd being attached so lets check if the medium attachment
277 * and the medium, both are of same type. if yes then we are
278 * sure of its type and don't need the user to enter it manually
279 * else ask the user for the type.
280 */
281 ComPtr<IMediumAttachment> mediumAttachement;
282 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachement.asOutParam());
283 if (SUCCEEDED(rc))
284 {
285 DeviceType_T deviceType;
286 mediumAttachement->COMGETTER(Type)(&deviceType);
287
288 if (deviceType == DeviceType_DVD)
289 {
290 Bstr uuid(pszMedium);
291 ComPtr<IMedium> dvdMedium;
292 /* first assume it's a UUID */
293 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
294 if (FAILED(rc) || !dvdMedium)
295 {
296 /* must be a filename, check if it's in the collection */
297 a->virtualBox->FindDVDImage(Bstr(pszMedium), dvdMedium.asOutParam());
298 }
299 if (dvdMedium)
300 {
301 /*
302 * ok so the medium and attachment both are DVD's so it is
303 * safe to assume that we are dealing with a DVD here
304 */
305 pszType = "dvddrive";
306 }
307 }
308 else if (deviceType == DeviceType_HardDisk)
309 {
310 Bstr uuid(pszMedium);
311 ComPtr<IMedium> hardDisk;
312 /* first assume it's a UUID */
313 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
314 if (FAILED(rc) || !hardDisk)
315 {
316 /* must be a filename, check if it's in the collection */
317 a->virtualBox->FindHardDisk(Bstr(pszMedium), hardDisk.asOutParam());
318 }
319 if (hardDisk)
320 {
321 /*
322 * ok so the medium and attachment both are hdd's so it is
323 * safe to assume that we are dealing with a hdd here
324 */
325 pszType = "hdd";
326 }
327 }
328 }
329 }
330 /* for all other cases lets ask the user what type of drive it is */
331 }
332
333 if (!pszType)
334 {
335 errorSyntax(USAGE_STORAGEATTACH, "Argument --type not specified\n");
336 goto leave;
337 }
338
339 if (!RTStrICmp(pszType, "dvddrive"))
340 {
341 Bstr uuid;
342 ComPtr<IMedium> dvdMedium;
343
344 if (!fRunTime)
345 {
346 ComPtr<IMediumAttachment> mediumAttachement;
347
348 /* check if there is a dvd drive at the given location, if not attach one */
349 rc = machine->GetMediumAttachment(Bstr(pszCtl), port, device, mediumAttachement.asOutParam());
350 if (SUCCEEDED(rc))
351 {
352 DeviceType_T deviceType;
353 mediumAttachement->COMGETTER(Type)(&deviceType);
354
355 if (deviceType != DeviceType_DVD)
356 {
357 machine->DetachDevice(Bstr(pszCtl), port, device);
358 rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, Bstr(""));
359 }
360 }
361 else
362 {
363 rc = machine->AttachDevice(Bstr(pszCtl), port, device, DeviceType_DVD, Bstr(""));
364 }
365 }
366
367 /* Attach/Detach the dvd medium now */
368 do
369 {
370 /* host drive? */
371 if (!RTStrNICmp(pszMedium, "host:", 5))
372 {
373 ComPtr<IHost> host;
374 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
375 rc = host->FindHostDVDDrive(Bstr(pszMedium + 5), dvdMedium.asOutParam());
376 if (!dvdMedium)
377 {
378 /* 2nd try: try with the real name, important on Linux+libhal */
379 char szPathReal[RTPATH_MAX];
380 if (RT_FAILURE(RTPathReal(pszMedium + 5, szPathReal, sizeof(szPathReal))))
381 {
382 errorArgument("Invalid host DVD drive name \"%s\"", pszMedium + 5);
383 rc = E_FAIL;
384 break;
385 }
386 rc = host->FindHostDVDDrive(Bstr(szPathReal), dvdMedium.asOutParam());
387 if (!dvdMedium)
388 {
389 errorArgument("Invalid host DVD drive name \"%s\"", pszMedium + 5);
390 rc = E_FAIL;
391 break;
392 }
393 }
394 }
395 else
396 {
397 /* first assume it's a UUID */
398 uuid = pszMedium;
399 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
400 if (FAILED(rc) || !dvdMedium)
401 {
402 /* must be a filename, check if it's in the collection */
403 rc = a->virtualBox->FindDVDImage(Bstr(pszMedium), dvdMedium.asOutParam());
404 /* not registered, do that on the fly */
405 if (!dvdMedium)
406 {
407 Bstr emptyUUID;
408 CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(pszMedium),
409 emptyUUID, dvdMedium.asOutParam()));
410 }
411 }
412 if (!dvdMedium)
413 {
414 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
415 rc = E_FAIL;
416 break;
417 }
418 }
419 } while (0);
420
421 if (dvdMedium)
422 {
423 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
424 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl), port, device, uuid));
425 }
426 }
427 else if ( !RTStrICmp(pszType, "hdd")
428 && !fRunTime)
429 {
430 ComPtr<IMediumAttachment> mediumAttachement;
431
432 /* if there is anything attached at the given location, remove it */
433 machine->DetachDevice(Bstr(pszCtl), port, device);
434
435 /* first guess is that it's a UUID */
436 Bstr uuid(pszMedium);
437 ComPtr<IMedium> hardDisk;
438 rc = a->virtualBox->GetHardDisk(uuid, hardDisk.asOutParam());
439
440 /* not successful? Then it must be a filename */
441 if (!hardDisk)
442 {
443 rc = a->virtualBox->FindHardDisk(Bstr(pszMedium), hardDisk.asOutParam());
444 if (FAILED(rc))
445 {
446 /* open the new hard disk object */
447 CHECK_ERROR(a->virtualBox,
448 OpenHardDisk(Bstr(pszMedium),
449 AccessMode_ReadWrite, false, Bstr(""),
450 false, Bstr(""), hardDisk.asOutParam()));
451 }
452 }
453
454 if (hardDisk)
455 {
456 hardDisk->COMGETTER(Id)(uuid.asOutParam());
457 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_HardDisk, uuid));
458 }
459 else
460 {
461 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
462 rc = E_FAIL;
463 }
464 }
465 else if (!RTStrICmp(pszType, "fdd"))
466 {
467 Bstr uuid;
468 ComPtr<IMedium> floppyMedium;
469 ComPtr<IMediumAttachment> floppyAttachment;
470 machine->GetMediumAttachment(Bstr(pszCtl), port, device, floppyAttachment.asOutParam());
471
472 if ( !fRunTime
473 && !floppyAttachment)
474 CHECK_ERROR(machine, AttachDevice(Bstr(pszCtl), port, device, DeviceType_Floppy, Bstr("")));
475
476 /* host drive? */
477 if (!RTStrNICmp(pszMedium, "host:", 5))
478 {
479 ComPtr<IHost> host;
480
481 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
482 rc = host->FindHostFloppyDrive(Bstr(pszMedium + 5), floppyMedium.asOutParam());
483 if (!floppyMedium)
484 {
485 errorArgument("Invalid host floppy drive name \"%s\"", pszMedium + 5);
486 rc = E_FAIL;
487 }
488 }
489 else
490 {
491 /* first assume it's a UUID */
492 uuid = pszMedium;
493 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
494 if (FAILED(rc) || !floppyMedium)
495 {
496 /* must be a filename, check if it's in the collection */
497 rc = a->virtualBox->FindFloppyImage(Bstr(pszMedium), floppyMedium.asOutParam());
498 /* not registered, do that on the fly */
499 if (!floppyMedium)
500 {
501 Bstr emptyUUID;
502 CHECK_ERROR(a->virtualBox,
503 OpenFloppyImage(Bstr(pszMedium),
504 emptyUUID,
505 floppyMedium.asOutParam()));
506 }
507 }
508
509 if (!floppyMedium)
510 {
511 errorArgument("Invalid UUID or filename \"%s\"", pszMedium);
512 rc = E_FAIL;
513 }
514 }
515
516 if (floppyMedium)
517 {
518 floppyMedium->COMGETTER(Id)(uuid.asOutParam());
519 CHECK_ERROR(machine, MountMedium(Bstr(pszCtl), port, device, uuid));
520 }
521 }
522 else
523 {
524 errorArgument("Invalid --type argument '%s'", pszType);
525 rc = E_FAIL;
526 }
527 }
528
529 if ( pszPassThrough
530 && (SUCCEEDED(rc)))
531 {
532 ComPtr<IMediumAttachment> mattach;
533
534 CHECK_ERROR(machine, GetMediumAttachment(Bstr(pszCtl), port, device, mattach.asOutParam()));
535
536 if (SUCCEEDED(rc))
537 {
538 if (!RTStrICmp(pszPassThrough, "on"))
539 {
540 CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl), port, device, TRUE));
541 }
542 else if (!RTStrICmp(pszPassThrough, "off"))
543 {
544 CHECK_ERROR(machine, PassthroughDevice(Bstr(pszCtl), port, device, FALSE));
545 }
546 else
547 {
548 errorArgument("Invalid --passthrough argument '%s'", pszPassThrough);
549 rc = E_FAIL;
550 }
551 }
552 else
553 {
554 errorArgument("Couldn't find the controller attachment for the controller '%s'\n", pszCtl);
555 rc = E_FAIL;
556 }
557 }
558
559 /* commit changes */
560 if (SUCCEEDED(rc))
561 CHECK_ERROR(machine, SaveSettings());
562
563leave:
564 /* it's important to always close sessions */
565 a->session->Close();
566
567 return SUCCEEDED(rc) ? 0 : 1;
568}
569
570
571static const RTGETOPTDEF g_aStorageControllerOptions[] =
572{
573 { "--name", 'n', RTGETOPT_REQ_STRING },
574 { "--add", 'a', RTGETOPT_REQ_STRING },
575 { "--controller", 'c', RTGETOPT_REQ_STRING },
576 { "--sataideemulation", 'e', RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_INDEX },
577 { "--sataportcount", 'p', RTGETOPT_REQ_UINT32 },
578 { "--remove", 'r', RTGETOPT_REQ_NOTHING },
579};
580
581int handleStorageController(HandlerArg *a)
582{
583 int c;
584 HRESULT rc = S_OK;
585 const char *pszCtl = NULL;
586 const char *pszBusType = NULL;
587 const char *pszCtlType = NULL;
588 ULONG satabootdev = ~0U;
589 ULONG sataidedev = ~0U;
590 ULONG sataportcount = ~0U;
591 bool fRemoveCtl = false;
592 Bstr machineuuid (a->argv[0]);
593 ComPtr<IMachine> machine;
594 RTGETOPTUNION ValueUnion;
595 RTGETOPTSTATE GetState;
596
597 if (a->argc < 4)
598 return errorSyntax(USAGE_STORAGECONTROLLER, "Too few parameters");
599
600 RTGetOptInit (&GetState, a->argc, a->argv, g_aStorageControllerOptions,
601 RT_ELEMENTS(g_aStorageControllerOptions), 1, 0 /* fFlags */);
602
603 while ( SUCCEEDED(rc)
604 && (c = RTGetOpt(&GetState, &ValueUnion)))
605 {
606 switch (c)
607 {
608 case 'n': // controller name
609 {
610 if (ValueUnion.psz)
611 pszCtl = ValueUnion.psz;
612 else
613 rc = E_FAIL;
614 break;
615 }
616
617 case 'a': // controller bus type <ide/sata/scsi/floppy>
618 {
619 if (ValueUnion.psz)
620 pszBusType = ValueUnion.psz;
621 else
622 rc = E_FAIL;
623 break;
624 }
625
626 case 'c': // controller <lsilogic/buslogic/intelahci/piix3/piix4/ich6/i82078>
627 {
628 if (ValueUnion.psz)
629 pszCtlType = ValueUnion.psz;
630 else
631 rc = E_FAIL;
632 break;
633 }
634
635 case 'e': // sataideemulation
636 {
637 if ((GetState.uIndex < 1) && (GetState.uIndex > 4))
638 return errorSyntax(USAGE_STORAGECONTROLLER,
639 "Missing or Invalid SATA boot slot number in '%s'",
640 GetState.pDef->pszLong);
641
642 if ((ValueUnion.u32 < 1) && (ValueUnion.u32 > 30))
643 return errorSyntax(USAGE_STORAGECONTROLLER,
644 "Missing or Invalid SATA port number in '%s'",
645 GetState.pDef->pszLong);
646
647 satabootdev = GetState.uIndex;
648 sataidedev = ValueUnion.u32;
649 break;
650 }
651
652 case 'p': // sataportcount
653 {
654 sataportcount = ValueUnion.u32;
655 break;
656 }
657
658 case 'r': // remove controller
659 {
660 fRemoveCtl = true;
661 break;
662 }
663
664 default:
665 {
666 errorGetOpt(USAGE_STORAGECONTROLLER, c, &ValueUnion);
667 rc = E_FAIL;
668 break;
669 }
670 }
671 }
672
673 if (FAILED(rc))
674 return 1;
675
676 /* try to find the given machine */
677 if (!Guid(machineuuid).isEmpty())
678 {
679 CHECK_ERROR_RET(a->virtualBox, GetMachine (machineuuid, machine.asOutParam()), 1);
680 }
681 else
682 {
683 CHECK_ERROR_RET(a->virtualBox, FindMachine(Bstr(a->argv[0]), machine.asOutParam()), 1);
684 machine->COMGETTER(Id)(machineuuid.asOutParam());
685 }
686
687 /* open a session for the VM */
688 CHECK_ERROR_RET(a->virtualBox, OpenSession (a->session, machineuuid), 1);
689
690 /* get the mutable session machine */
691 a->session->COMGETTER(Machine)(machine.asOutParam());
692
693 if (!pszCtl)
694 {
695 /* it's important to always close sessions */
696 a->session->Close();
697 errorSyntax(USAGE_STORAGECONTROLLER, "Storage Controller Name not specified\n");
698 return 1;
699 }
700
701 if (fRemoveCtl)
702 {
703 com::SafeIfaceArray<IMediumAttachment> mediumAttachments;
704
705 CHECK_ERROR(machine,
706 GetMediumAttachmentsOfController(Bstr(pszCtl),
707 ComSafeArrayAsOutParam(mediumAttachments)));
708 for (size_t i = 0; i < mediumAttachments.size(); ++ i)
709 {
710 ComPtr<IMediumAttachment> mediumAttach = mediumAttachments[i];
711 LONG port = 0;
712 LONG device = 0;
713
714 CHECK_ERROR(mediumAttach, COMGETTER(Port)(&port));
715 CHECK_ERROR(mediumAttach, COMGETTER(Device)(&device));
716 CHECK_ERROR(machine, DetachDevice(Bstr(pszCtl), port, device));
717 }
718
719 if (SUCCEEDED(rc))
720 CHECK_ERROR(machine, RemoveStorageController(Bstr(pszCtl)));
721 else
722 errorArgument("Can't detach the devices connected to '%s' Controller\n"
723 "and thus its removal failed.", pszCtl);
724 }
725 else
726 {
727 if (pszBusType)
728 {
729 ComPtr<IStorageController> ctl;
730
731 if (!RTStrICmp(pszBusType, "ide"))
732 {
733 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_IDE, ctl.asOutParam()));
734 }
735 else if (!RTStrICmp(pszBusType, "sata"))
736 {
737 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_SATA, ctl.asOutParam()));
738 }
739 else if (!RTStrICmp(pszBusType, "scsi"))
740 {
741 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_SCSI, ctl.asOutParam()));
742 }
743 else if (!RTStrICmp(pszBusType, "floppy"))
744 {
745 CHECK_ERROR(machine, AddStorageController(Bstr(pszCtl), StorageBus_Floppy, ctl.asOutParam()));
746 }
747 else
748 {
749 errorArgument("Invalid --add argument '%s'", pszBusType);
750 rc = E_FAIL;
751 }
752 }
753
754 if ( pszCtlType
755 && SUCCEEDED(rc))
756 {
757 ComPtr<IStorageController> ctl;
758
759 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
760
761 if (SUCCEEDED(rc))
762 {
763 if (!RTStrICmp(pszCtlType, "lsilogic"))
764 {
765 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_LsiLogic));
766 }
767 else if (!RTStrICmp(pszCtlType, "buslogic"))
768 {
769 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_BusLogic));
770 }
771 else if (!RTStrICmp(pszCtlType, "intelahci"))
772 {
773 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_IntelAhci));
774 }
775 else if (!RTStrICmp(pszCtlType, "piix3"))
776 {
777 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX3));
778 }
779 else if (!RTStrICmp(pszCtlType, "piix4"))
780 {
781 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_PIIX4));
782 }
783 else if (!RTStrICmp(pszCtlType, "ich6"))
784 {
785 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_ICH6));
786 }
787 else if (!RTStrICmp(pszCtlType, "i82078"))
788 {
789 CHECK_ERROR(ctl, COMSETTER(ControllerType)(StorageControllerType_I82078));
790 }
791 else
792 {
793 errorArgument("Invalid --type argument '%s'", pszCtlType);
794 rc = E_FAIL;
795 }
796 }
797 else
798 {
799 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
800 rc = E_FAIL;
801 }
802 }
803
804 if ( (sataportcount != ~0U)
805 && SUCCEEDED(rc))
806 {
807 ComPtr<IStorageController> ctl;
808
809 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
810
811 if (SUCCEEDED(rc))
812 {
813 CHECK_ERROR(ctl, COMSETTER(PortCount)(sataportcount));
814 }
815 else
816 {
817 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
818 rc = E_FAIL;
819 }
820 }
821
822 if ( (sataidedev != ~0U)
823 && (satabootdev != ~0U)
824 && SUCCEEDED(rc))
825 {
826 ComPtr<IStorageController> ctl;
827
828 CHECK_ERROR(machine, GetStorageControllerByName(Bstr(pszCtl), ctl.asOutParam()));
829
830 if (SUCCEEDED(rc))
831 {
832 CHECK_ERROR(ctl, SetIDEEmulationPort(satabootdev, sataidedev));
833 }
834 else
835 {
836 errorArgument("Couldn't find the controller with the name: '%s'\n", pszCtl);
837 rc = E_FAIL;
838 }
839 }
840 }
841
842 /* commit changes */
843 if (SUCCEEDED(rc))
844 CHECK_ERROR(machine, SaveSettings());
845
846 /* it's important to always close sessions */
847 a->session->Close();
848
849 return SUCCEEDED(rc) ? 0 : 1;
850}
851
852#endif /* !VBOX_ONLY_DOCS */
853
Note: See TracBrowser for help on using the repository browser.

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