VirtualBox

source: vbox/trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp@ 29334

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

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 31.3 KB
Line 
1/* $Id: VBoxManageControlVM.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * VBoxManage - VirtualBox's command-line interface.
4 */
5
6/*
7 * Copyright (C) 2006-2009 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
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#include <VBox/com/com.h>
23#include <VBox/com/string.h>
24#include <VBox/com/Guid.h>
25#include <VBox/com/array.h>
26#include <VBox/com/ErrorInfo.h>
27#include <VBox/com/errorprint.h>
28#include <VBox/com/EventQueue.h>
29
30#include <VBox/com/VirtualBox.h>
31
32#include <iprt/ctype.h>
33#include <VBox/err.h>
34#include <iprt/getopt.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <iprt/uuid.h>
38#include <VBox/log.h>
39
40#include "VBoxManage.h"
41
42
43/**
44 * Parses a number.
45 *
46 * @returns Valid number on success.
47 * @returns 0 if invalid number. All necesary bitching has been done.
48 * @param psz Pointer to the nic number.
49 */
50static unsigned parseNum(const char *psz, unsigned cMaxNum, const char *name)
51{
52 uint32_t u32;
53 char *pszNext;
54 int rc = RTStrToUInt32Ex(psz, &pszNext, 10, &u32);
55 if ( RT_SUCCESS(rc)
56 && *pszNext == '\0'
57 && u32 >= 1
58 && u32 <= cMaxNum)
59 return (unsigned)u32;
60 errorArgument("Invalid %s number '%s'", name, psz);
61 return 0;
62}
63
64
65int handleControlVM(HandlerArg *a)
66{
67 using namespace com;
68 HRESULT rc;
69
70 if (a->argc < 2)
71 return errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
72
73 /* try to find the given machine */
74 ComPtr <IMachine> machine;
75 Bstr machineuuid (a->argv[0]);
76 if (!Guid(machineuuid).isEmpty())
77 {
78 CHECK_ERROR(a->virtualBox, GetMachine(machineuuid, machine.asOutParam()));
79 }
80 else
81 {
82 CHECK_ERROR(a->virtualBox, FindMachine(machineuuid, machine.asOutParam()));
83 if (SUCCEEDED (rc))
84 machine->COMGETTER(Id)(machineuuid.asOutParam());
85 }
86 if (FAILED (rc))
87 return 1;
88
89 /* open a session for the VM */
90 CHECK_ERROR_RET(a->virtualBox, OpenExistingSession(a->session, machineuuid), 1);
91
92 do
93 {
94 /* get the associated console */
95 ComPtr<IConsole> console;
96 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
97 /* ... and session machine */
98 ComPtr<IMachine> sessionMachine;
99 CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
100
101 /* which command? */
102 if (!strcmp(a->argv[1], "pause"))
103 {
104 CHECK_ERROR_BREAK(console, Pause());
105 }
106 else if (!strcmp(a->argv[1], "resume"))
107 {
108 CHECK_ERROR_BREAK(console, Resume());
109 }
110 else if (!strcmp(a->argv[1], "reset"))
111 {
112 CHECK_ERROR_BREAK(console, Reset());
113 }
114 else if (!strcmp(a->argv[1], "unplugcpu"))
115 {
116 if (a->argc <= 1 + 1)
117 {
118 errorArgument("Missing argument to '%s'. Expected CPU number.", a->argv[1]);
119 rc = E_FAIL;
120 break;
121 }
122
123 unsigned n = parseNum(a->argv[2], 32, "CPU");
124
125 CHECK_ERROR_BREAK(sessionMachine, HotUnplugCPU(n));
126 }
127 else if (!strcmp(a->argv[1], "plugcpu"))
128 {
129 if (a->argc <= 1 + 1)
130 {
131 errorArgument("Missing argument to '%s'. Expected CPU number.", a->argv[1]);
132 rc = E_FAIL;
133 break;
134 }
135
136 unsigned n = parseNum(a->argv[2], 32, "CPU");
137
138 CHECK_ERROR_BREAK(sessionMachine, HotPlugCPU(n));
139 }
140 else if (!strcmp(a->argv[1], "poweroff"))
141 {
142 ComPtr<IProgress> progress;
143 CHECK_ERROR_BREAK(console, PowerDown(progress.asOutParam()));
144
145 rc = showProgress(progress);
146 if (FAILED(rc))
147 {
148 com::ProgressErrorInfo info(progress);
149 if (info.isBasicAvailable())
150 {
151 RTPrintf("Error: failed to power off machine. Error message: %lS\n", info.getText().raw());
152 }
153 else
154 {
155 RTPrintf("Error: failed to power off machine. No error message available!\n");
156 }
157 }
158 }
159 else if (!strcmp(a->argv[1], "savestate"))
160 {
161 ComPtr<IProgress> progress;
162 CHECK_ERROR_BREAK(console, SaveState(progress.asOutParam()));
163
164 rc = showProgress(progress);
165 if (FAILED(rc))
166 {
167 com::ProgressErrorInfo info(progress);
168 if (info.isBasicAvailable())
169 {
170 RTPrintf("Error: failed to save machine state. Error message: %lS\n", info.getText().raw());
171 }
172 else
173 {
174 RTPrintf("Error: failed to save machine state. No error message available!\n");
175 }
176 }
177 }
178 else if (!strcmp(a->argv[1], "acpipowerbutton"))
179 {
180 CHECK_ERROR_BREAK(console, PowerButton());
181 }
182 else if (!strcmp(a->argv[1], "acpisleepbutton"))
183 {
184 CHECK_ERROR_BREAK(console, SleepButton());
185 }
186 else if (!strcmp(a->argv[1], "injectnmi"))
187 {
188 /* get the machine debugger. */
189 ComPtr <IMachineDebugger> debugger;
190 CHECK_ERROR_BREAK(console, COMGETTER(Debugger)(debugger.asOutParam()));
191 CHECK_ERROR_BREAK(debugger, InjectNMI());
192 }
193 else if (!strcmp(a->argv[1], "keyboardputscancode"))
194 {
195 ComPtr<IKeyboard> keyboard;
196 CHECK_ERROR_BREAK(console, COMGETTER(Keyboard)(keyboard.asOutParam()));
197
198 if (a->argc <= 1 + 1)
199 {
200 errorArgument("Missing argument to '%s'. Expected IBM PC AT set 2 keyboard scancode(s) as hex byte(s).", a->argv[1]);
201 rc = E_FAIL;
202 break;
203 }
204
205 /* Arbitrary restrict the length of a sequence of scancodes to 1024. */
206 LONG alScancodes[1024];
207 int cScancodes = 0;
208
209 /* Process the command line. */
210 int i;
211 for (i = 1 + 1; i < a->argc && cScancodes < (int)RT_ELEMENTS(alScancodes); i++, cScancodes++)
212 {
213 if ( RT_C_IS_XDIGIT (a->argv[i][0])
214 && RT_C_IS_XDIGIT (a->argv[i][1])
215 && a->argv[i][2] == 0)
216 {
217 uint8_t u8Scancode;
218 int irc = RTStrToUInt8Ex(a->argv[i], NULL, 16, &u8Scancode);
219 if (RT_FAILURE (irc))
220 {
221 RTPrintf("Error: converting '%s' returned %Rrc!\n", a->argv[i], rc);
222 rc = E_FAIL;
223 break;
224 }
225
226 alScancodes[cScancodes] = u8Scancode;
227 }
228 else
229 {
230 RTPrintf("Error: '%s' is not a hex byte!\n", a->argv[i]);
231 rc = E_FAIL;
232 break;
233 }
234 }
235
236 if (FAILED(rc))
237 break;
238
239 if ( cScancodes == RT_ELEMENTS(alScancodes)
240 && i < a->argc)
241 {
242 RTPrintf("Error: too many scancodes, maximum %d allowed!\n", RT_ELEMENTS(alScancodes));
243 rc = E_FAIL;
244 break;
245 }
246
247 /* Send scancodes to the VM.
248 * Note: 'PutScancodes' did not work here. Only the first scancode was transmitted.
249 */
250 for (i = 0; i < cScancodes; i++)
251 {
252 CHECK_ERROR_BREAK(keyboard, PutScancode(alScancodes[i]));
253 RTPrintf("Scancode[%d]: 0x%02X\n", i, alScancodes[i]);
254 }
255 }
256 else if (!strncmp(a->argv[1], "setlinkstate", 12))
257 {
258 /* Get the number of network adapters */
259 ULONG NetworkAdapterCount = 0;
260 ComPtr <ISystemProperties> info;
261 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
262 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
263
264 unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
265 if (!n)
266 {
267 rc = E_FAIL;
268 break;
269 }
270 if (a->argc <= 1 + 1)
271 {
272 errorArgument("Missing argument to '%s'", a->argv[1]);
273 rc = E_FAIL;
274 break;
275 }
276 /* get the corresponding network adapter */
277 ComPtr<INetworkAdapter> adapter;
278 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
279 if (adapter)
280 {
281 if (!strcmp(a->argv[2], "on"))
282 {
283 CHECK_ERROR_BREAK(adapter, COMSETTER(CableConnected)(TRUE));
284 }
285 else if (!strcmp(a->argv[2], "off"))
286 {
287 CHECK_ERROR_BREAK(adapter, COMSETTER(CableConnected)(FALSE));
288 }
289 else
290 {
291 errorArgument("Invalid link state '%s'", Utf8Str(a->argv[2]).raw());
292 rc = E_FAIL;
293 break;
294 }
295 }
296 }
297#ifdef VBOX_DYNAMIC_NET_ATTACH
298 /* here the order in which strncmp is called is important
299 * cause nictracefile can be very well compared with
300 * nictrace and nic and thus everything will always fail
301 * if the order is changed
302 */
303 else if (!strncmp(a->argv[1], "nictracefile", 12))
304 {
305 /* Get the number of network adapters */
306 ULONG NetworkAdapterCount = 0;
307 ComPtr <ISystemProperties> info;
308 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
309 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
310
311 unsigned n = parseNum(&a->argv[1][12], NetworkAdapterCount, "NIC");
312 if (!n)
313 {
314 rc = E_FAIL;
315 break;
316 }
317 if (a->argc <= 2)
318 {
319 errorArgument("Missing argument to '%s'", a->argv[1]);
320 rc = E_FAIL;
321 break;
322 }
323
324 /* get the corresponding network adapter */
325 ComPtr<INetworkAdapter> adapter;
326 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
327 if (adapter)
328 {
329 BOOL fEnabled;
330 adapter->COMGETTER(Enabled)(&fEnabled);
331 if (fEnabled)
332 {
333 if (a->argv[2])
334 {
335 CHECK_ERROR_RET(adapter, COMSETTER(TraceFile)(Bstr(a->argv[2])), 1);
336 }
337 else
338 {
339 errorArgument("Invalid filename or filename not specified for NIC %lu", n);
340 rc = E_FAIL;
341 break;
342 }
343 }
344 else
345 {
346 RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
347 }
348 }
349 }
350 else if (!strncmp(a->argv[1], "nictrace", 8))
351 {
352 /* Get the number of network adapters */
353 ULONG NetworkAdapterCount = 0;
354 ComPtr <ISystemProperties> info;
355 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
356 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
357
358 unsigned n = parseNum(&a->argv[1][8], NetworkAdapterCount, "NIC");
359 if (!n)
360 {
361 rc = E_FAIL;
362 break;
363 }
364 if (a->argc <= 2)
365 {
366 errorArgument("Missing argument to '%s'", a->argv[1]);
367 rc = E_FAIL;
368 break;
369 }
370
371 /* get the corresponding network adapter */
372 ComPtr<INetworkAdapter> adapter;
373 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
374 if (adapter)
375 {
376 BOOL fEnabled;
377 adapter->COMGETTER(Enabled)(&fEnabled);
378 if (fEnabled)
379 {
380 if (!strcmp(a->argv[2], "on"))
381 {
382 CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(TRUE), 1);
383 }
384 else if (!strcmp(a->argv[2], "off"))
385 {
386 CHECK_ERROR_RET(adapter, COMSETTER(TraceEnabled)(FALSE), 1);
387 }
388 else
389 {
390 errorArgument("Invalid nictrace%lu argument '%s'", n, Utf8Str(a->argv[2]).raw());
391 rc = E_FAIL;
392 break;
393 }
394 }
395 else
396 {
397 RTPrintf("The NIC %d is currently disabled and thus can't change its tracefile\n", n);
398 }
399 }
400 }
401 else if (!strncmp(a->argv[1], "nic", 3))
402 {
403 /* Get the number of network adapters */
404 ULONG NetworkAdapterCount = 0;
405 ComPtr <ISystemProperties> info;
406 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(SystemProperties)(info.asOutParam()));
407 CHECK_ERROR_BREAK(info, COMGETTER(NetworkAdapterCount)(&NetworkAdapterCount));
408
409 unsigned n = parseNum(&a->argv[1][3], NetworkAdapterCount, "NIC");
410 if (!n)
411 {
412 rc = E_FAIL;
413 break;
414 }
415 if (a->argc <= 2)
416 {
417 errorArgument("Missing argument to '%s'", a->argv[1]);
418 rc = E_FAIL;
419 break;
420 }
421
422 /* get the corresponding network adapter */
423 ComPtr<INetworkAdapter> adapter;
424 CHECK_ERROR_BREAK(sessionMachine, GetNetworkAdapter(n - 1, adapter.asOutParam()));
425 if (adapter)
426 {
427 BOOL fEnabled;
428 adapter->COMGETTER(Enabled)(&fEnabled);
429 if (fEnabled)
430 {
431 if (!strcmp(a->argv[2], "null"))
432 {
433 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
434 CHECK_ERROR_RET(adapter, Detach(), 1);
435 }
436 else if (!strcmp(a->argv[2], "nat"))
437 {
438 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
439 if (a->argc == 4)
440 CHECK_ERROR_RET(adapter, COMSETTER(NATNetwork)(Bstr(a->argv[3])), 1);
441 CHECK_ERROR_RET(adapter, AttachToNAT(), 1);
442 }
443 else if ( !strcmp(a->argv[2], "bridged")
444 || !strcmp(a->argv[2], "hostif")) /* backward compatibility */
445 {
446 if (a->argc <= 3)
447 {
448 errorArgument("Missing argument to '%s'", a->argv[2]);
449 rc = E_FAIL;
450 break;
451 }
452 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
453 CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
454 CHECK_ERROR_RET(adapter, AttachToBridgedInterface(), 1);
455 }
456 else if (!strcmp(a->argv[2], "intnet"))
457 {
458 if (a->argc <= 3)
459 {
460 errorArgument("Missing argument to '%s'", a->argv[2]);
461 rc = E_FAIL;
462 break;
463 }
464 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
465 CHECK_ERROR_RET(adapter, COMSETTER(InternalNetwork)(Bstr(a->argv[3])), 1);
466 CHECK_ERROR_RET(adapter, AttachToInternalNetwork(), 1);
467 }
468#if defined(VBOX_WITH_NETFLT)
469 else if (!strcmp(a->argv[2], "hostonly"))
470 {
471 if (a->argc <= 3)
472 {
473 errorArgument("Missing argument to '%s'", a->argv[2]);
474 rc = E_FAIL;
475 break;
476 }
477 CHECK_ERROR_RET(adapter, COMSETTER(Enabled)(TRUE), 1);
478 CHECK_ERROR_RET(adapter, COMSETTER(HostInterface)(Bstr(a->argv[3])), 1);
479 CHECK_ERROR_RET(adapter, AttachToHostOnlyInterface(), 1);
480 }
481#endif
482 else
483 {
484 errorArgument("Invalid type '%s' specfied for NIC %lu", Utf8Str(a->argv[2]).raw(), n);
485 rc = E_FAIL;
486 break;
487 }
488 }
489 else
490 {
491 RTPrintf("The NIC %d is currently disabled and thus can't change its attachment type\n", n);
492 }
493 }
494 }
495#endif /* VBOX_DYNAMIC_NET_ATTACH */
496#ifdef VBOX_WITH_VRDP
497 else if (!strcmp(a->argv[1], "vrdp"))
498 {
499 if (a->argc <= 1 + 1)
500 {
501 errorArgument("Missing argument to '%s'", a->argv[1]);
502 rc = E_FAIL;
503 break;
504 }
505 /* get the corresponding VRDP server */
506 ComPtr<IVRDPServer> vrdpServer;
507 sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
508 ASSERT(vrdpServer);
509 if (vrdpServer)
510 {
511 if (!strcmp(a->argv[2], "on"))
512 {
513 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Enabled)(TRUE));
514 }
515 else if (!strcmp(a->argv[2], "off"))
516 {
517 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Enabled)(FALSE));
518 }
519 else
520 {
521 errorArgument("Invalid vrdp server state '%s'", Utf8Str(a->argv[2]).raw());
522 rc = E_FAIL;
523 break;
524 }
525 }
526 }
527 else if (!strcmp(a->argv[1], "vrdpport"))
528 {
529 if (a->argc <= 1 + 1)
530 {
531 errorArgument("Missing argument to '%s'", a->argv[1]);
532 rc = E_FAIL;
533 break;
534 }
535 /* get the corresponding VRDP server */
536 ComPtr<IVRDPServer> vrdpServer;
537 sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
538 ASSERT(vrdpServer);
539 if (vrdpServer)
540 {
541 Bstr vrdpports;
542
543 if (!strcmp(a->argv[2], "default"))
544 vrdpports = "0";
545 else
546 vrdpports = a->argv [2];
547
548 CHECK_ERROR_BREAK(vrdpServer, COMSETTER(Ports)(vrdpports));
549 }
550 }
551#endif /* VBOX_WITH_VRDP */
552 else if ( !strcmp(a->argv[1], "usbattach")
553 || !strcmp(a->argv[1], "usbdetach"))
554 {
555 if (a->argc < 3)
556 {
557 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
558 rc = E_FAIL;
559 break;
560 }
561
562 bool attach = !strcmp(a->argv[1], "usbattach");
563
564 Bstr usbId = a->argv [2];
565 if (Guid(usbId).isEmpty())
566 {
567 // assume address
568 if (attach)
569 {
570 ComPtr <IHost> host;
571 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
572 SafeIfaceArray <IHostUSBDevice> coll;
573 CHECK_ERROR_BREAK(host, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
574 ComPtr <IHostUSBDevice> dev;
575 CHECK_ERROR_BREAK(host, FindUSBDeviceByAddress(Bstr(a->argv [2]), dev.asOutParam()));
576 CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
577 }
578 else
579 {
580 SafeIfaceArray <IUSBDevice> coll;
581 CHECK_ERROR_BREAK(console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
582 ComPtr <IUSBDevice> dev;
583 CHECK_ERROR_BREAK(console, FindUSBDeviceByAddress(Bstr(a->argv [2]),
584 dev.asOutParam()));
585 CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
586 }
587 }
588
589 if (attach)
590 CHECK_ERROR_BREAK(console, AttachUSBDevice(usbId));
591 else
592 {
593 ComPtr <IUSBDevice> dev;
594 CHECK_ERROR_BREAK(console, DetachUSBDevice(usbId, dev.asOutParam()));
595 }
596 }
597 else if (!strcmp(a->argv[1], "setvideomodehint"))
598 {
599 if (a->argc != 5 && a->argc != 6)
600 {
601 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
602 rc = E_FAIL;
603 break;
604 }
605 uint32_t xres = RTStrToUInt32(a->argv[2]);
606 uint32_t yres = RTStrToUInt32(a->argv[3]);
607 uint32_t bpp = RTStrToUInt32(a->argv[4]);
608 uint32_t displayIdx = 0;
609 if (a->argc == 6)
610 displayIdx = RTStrToUInt32(a->argv[5]);
611
612 ComPtr<IDisplay> display;
613 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
614 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
615 }
616 else if (!strcmp(a->argv[1], "setcredentials"))
617 {
618 bool fAllowLocalLogon = true;
619 if (a->argc == 7)
620 {
621 if ( strcmp(a->argv[5], "--allowlocallogon")
622 && strcmp(a->argv[5], "-allowlocallogon"))
623 {
624 errorArgument("Invalid parameter '%s'", a->argv[5]);
625 rc = E_FAIL;
626 break;
627 }
628 if (!strcmp(a->argv[6], "no"))
629 fAllowLocalLogon = false;
630 }
631 else if (a->argc != 5)
632 {
633 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
634 rc = E_FAIL;
635 break;
636 }
637
638 ComPtr<IGuest> guest;
639 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
640 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
641 }
642#if 0 /* TODO: review & remove */
643 else if (!strcmp(a->argv[1], "dvdattach"))
644 {
645 Bstr uuid;
646 if (a->argc != 3)
647 {
648 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
649 rc = E_FAIL;
650 break;
651 }
652
653 ComPtr<IMedium> dvdMedium;
654
655 /* unmount? */
656 if (!strcmp(a->argv[2], "none"))
657 {
658 /* nothing to do, NULL object will cause unmount */
659 }
660 /* host drive? */
661 else if (!strncmp(a->argv[2], "host:", 5))
662 {
663 ComPtr<IHost> host;
664 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
665
666 rc = host->FindHostDVDDrive(Bstr(a->argv[2] + 5), dvdMedium.asOutParam());
667 if (!dvdMedium)
668 {
669 errorArgument("Invalid host DVD drive name \"%s\"",
670 a->argv[2] + 5);
671 rc = E_FAIL;
672 break;
673 }
674 }
675 else
676 {
677 /* first assume it's a UUID */
678 uuid = a->argv[2];
679 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
680 if (FAILED(rc) || !dvdMedium)
681 {
682 /* must be a filename, check if it's in the collection */
683 rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdMedium.asOutParam());
684 /* not registered, do that on the fly */
685 if (!dvdMedium)
686 {
687 Bstr emptyUUID;
688 CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdMedium.asOutParam()));
689 }
690 }
691 if (!dvdMedium)
692 {
693 rc = E_FAIL;
694 break;
695 }
696 }
697
698 /** @todo generalize this, allow arbitrary number of DVD drives
699 * and as a consequence multiple attachments and different
700 * storage controllers. */
701 if (dvdMedium)
702 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
703 else
704 uuid = Guid().toString();
705 CHECK_ERROR(machine, MountMedium(Bstr("IDE Controller"), 1, 0, uuid, FALSE /* aForce */));
706 }
707 else if (!strcmp(a->argv[1], "floppyattach"))
708 {
709 Bstr uuid;
710 if (a->argc != 3)
711 {
712 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
713 rc = E_FAIL;
714 break;
715 }
716
717 ComPtr<IMedium> floppyMedium;
718
719 /* unmount? */
720 if (!strcmp(a->argv[2], "none"))
721 {
722 /* nothing to do, NULL object will cause unmount */
723 }
724 /* host drive? */
725 else if (!strncmp(a->argv[2], "host:", 5))
726 {
727 ComPtr<IHost> host;
728 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
729 host->FindHostFloppyDrive(Bstr(a->argv[2] + 5), floppyMedium.asOutParam());
730 if (!floppyMedium)
731 {
732 errorArgument("Invalid host floppy drive name \"%s\"",
733 a->argv[2] + 5);
734 rc = E_FAIL;
735 break;
736 }
737 }
738 else
739 {
740 /* first assume it's a UUID */
741 uuid = a->argv[2];
742 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
743 if (FAILED(rc) || !floppyMedium)
744 {
745 /* must be a filename, check if it's in the collection */
746 rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyMedium.asOutParam());
747 /* not registered, do that on the fly */
748 if (!floppyMedium)
749 {
750 Bstr emptyUUID;
751 CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyMedium.asOutParam()));
752 }
753 }
754 if (!floppyMedium)
755 {
756 rc = E_FAIL;
757 break;
758 }
759 }
760 floppyMedium->COMGETTER(Id)(uuid.asOutParam());
761 CHECK_ERROR(machine, MountMedium(Bstr("Floppy Controller"), 0, 0, uuid, FALSE /* aForce */));
762 }
763#endif /* obsolete dvdattach/floppyattach */
764 else if (!strcmp(a->argv[1], "guestmemoryballoon"))
765 {
766 if (a->argc != 3)
767 {
768 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
769 rc = E_FAIL;
770 break;
771 }
772 uint32_t uVal;
773 int vrc;
774 vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
775 if (vrc != VINF_SUCCESS)
776 {
777 errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
778 rc = E_FAIL;
779 break;
780 }
781 /* guest is running; update IGuest */
782 ComPtr <IGuest> guest;
783 rc = console->COMGETTER(Guest)(guest.asOutParam());
784 if (SUCCEEDED(rc))
785 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
786 }
787 else if (!strcmp(a->argv[1], "teleport"))
788 {
789 Bstr bstrHostname;
790 uint32_t uMaxDowntime = 250 /*ms*/;
791 uint32_t uPort = UINT32_MAX;
792 uint32_t cMsTimeout = 0;
793 Bstr bstrPassword("");
794 static const RTGETOPTDEF s_aTeleportOptions[] =
795 {
796 { "--host", 'h', RTGETOPT_REQ_STRING }, /** @todo RTGETOPT_FLAG_MANDATORY */
797 { "--hostname", 'h', RTGETOPT_REQ_STRING }, /** @todo remove this */
798 { "--maxdowntime", 'd', RTGETOPT_REQ_UINT32 },
799 { "--port", 'p', RTGETOPT_REQ_UINT32 }, /** @todo RTGETOPT_FLAG_MANDATORY */
800 { "--password", 'P', RTGETOPT_REQ_STRING },
801 { "--timeout", 't', RTGETOPT_REQ_UINT32 }
802 };
803 RTGETOPTSTATE GetOptState;
804 RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTeleportOptions, RT_ELEMENTS(s_aTeleportOptions), 2, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
805 int ch;
806 RTGETOPTUNION Value;
807 while ( SUCCEEDED(rc)
808 && (ch = RTGetOpt(&GetOptState, &Value)))
809 {
810 switch (ch)
811 {
812 case 'h': bstrHostname = Value.psz; break;
813 case 'd': uMaxDowntime = Value.u32; break;
814 case 'p': uPort = Value.u32; break;
815 case 'P': bstrPassword = Value.psz; break;
816 case 't': cMsTimeout = Value.u32; break;
817 default:
818 errorGetOpt(USAGE_CONTROLVM, ch, &Value);
819 rc = E_FAIL;
820 break;
821 }
822 }
823 if (FAILED(rc))
824 break;
825
826 ComPtr<IProgress> progress;
827 CHECK_ERROR_BREAK(console, Teleport(bstrHostname, uPort, bstrPassword, uMaxDowntime, progress.asOutParam()));
828
829 if (cMsTimeout)
830 {
831 rc = progress->COMSETTER(Timeout)(cMsTimeout);
832 if (FAILED(rc) && rc != VBOX_E_INVALID_OBJECT_STATE)
833 CHECK_ERROR_BREAK(progress, COMSETTER(Timeout)(cMsTimeout)); /* lazyness */
834 }
835
836 rc = showProgress(progress);
837 if (FAILED(rc))
838 {
839 com::ProgressErrorInfo info(progress);
840 if (info.isBasicAvailable())
841 RTPrintf("Error: teleportation failed. Error message: %lS\n", info.getText().raw());
842 else
843 RTPrintf("Error: teleportation failed. No error message available!\n");
844 }
845 }
846 else
847 {
848 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
849 rc = E_FAIL;
850 }
851 } while (0);
852
853 a->session->Close();
854
855 return SUCCEEDED(rc) ? 0 : 1;
856}
857
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