VirtualBox

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

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

Implemented VBoxManage controlvm vrdpvideochannelquality

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 32.0 KB
Line 
1/* $Id: VBoxManageControlVM.cpp 29364 2010-05-11 15:13:50Z 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 else if (!strcmp(a->argv[1], "vrdpvideochannelquality"))
552 {
553 if (a->argc <= 1 + 1)
554 {
555 errorArgument("Missing argument to '%s'", a->argv[1]);
556 rc = E_FAIL;
557 break;
558 }
559 /* get the corresponding VRDP server */
560 ComPtr<IVRDPServer> vrdpServer;
561 sessionMachine->COMGETTER(VRDPServer)(vrdpServer.asOutParam());
562 ASSERT(vrdpServer);
563 if (vrdpServer)
564 {
565 unsigned n = parseNum(a->argv[2], 100, "VRDP video channel quality in percent");
566
567 CHECK_ERROR(vrdpServer, COMSETTER(VideoChannelQuality)(n));
568 }
569 }
570#endif /* VBOX_WITH_VRDP */
571 else if ( !strcmp(a->argv[1], "usbattach")
572 || !strcmp(a->argv[1], "usbdetach"))
573 {
574 if (a->argc < 3)
575 {
576 errorSyntax(USAGE_CONTROLVM, "Not enough parameters");
577 rc = E_FAIL;
578 break;
579 }
580
581 bool attach = !strcmp(a->argv[1], "usbattach");
582
583 Bstr usbId = a->argv [2];
584 if (Guid(usbId).isEmpty())
585 {
586 // assume address
587 if (attach)
588 {
589 ComPtr <IHost> host;
590 CHECK_ERROR_BREAK(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
591 SafeIfaceArray <IHostUSBDevice> coll;
592 CHECK_ERROR_BREAK(host, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
593 ComPtr <IHostUSBDevice> dev;
594 CHECK_ERROR_BREAK(host, FindUSBDeviceByAddress(Bstr(a->argv [2]), dev.asOutParam()));
595 CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
596 }
597 else
598 {
599 SafeIfaceArray <IUSBDevice> coll;
600 CHECK_ERROR_BREAK(console, COMGETTER(USBDevices)(ComSafeArrayAsOutParam(coll)));
601 ComPtr <IUSBDevice> dev;
602 CHECK_ERROR_BREAK(console, FindUSBDeviceByAddress(Bstr(a->argv [2]),
603 dev.asOutParam()));
604 CHECK_ERROR_BREAK(dev, COMGETTER(Id)(usbId.asOutParam()));
605 }
606 }
607
608 if (attach)
609 CHECK_ERROR_BREAK(console, AttachUSBDevice(usbId));
610 else
611 {
612 ComPtr <IUSBDevice> dev;
613 CHECK_ERROR_BREAK(console, DetachUSBDevice(usbId, dev.asOutParam()));
614 }
615 }
616 else if (!strcmp(a->argv[1], "setvideomodehint"))
617 {
618 if (a->argc != 5 && a->argc != 6)
619 {
620 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
621 rc = E_FAIL;
622 break;
623 }
624 uint32_t xres = RTStrToUInt32(a->argv[2]);
625 uint32_t yres = RTStrToUInt32(a->argv[3]);
626 uint32_t bpp = RTStrToUInt32(a->argv[4]);
627 uint32_t displayIdx = 0;
628 if (a->argc == 6)
629 displayIdx = RTStrToUInt32(a->argv[5]);
630
631 ComPtr<IDisplay> display;
632 CHECK_ERROR_BREAK(console, COMGETTER(Display)(display.asOutParam()));
633 CHECK_ERROR_BREAK(display, SetVideoModeHint(xres, yres, bpp, displayIdx));
634 }
635 else if (!strcmp(a->argv[1], "setcredentials"))
636 {
637 bool fAllowLocalLogon = true;
638 if (a->argc == 7)
639 {
640 if ( strcmp(a->argv[5], "--allowlocallogon")
641 && strcmp(a->argv[5], "-allowlocallogon"))
642 {
643 errorArgument("Invalid parameter '%s'", a->argv[5]);
644 rc = E_FAIL;
645 break;
646 }
647 if (!strcmp(a->argv[6], "no"))
648 fAllowLocalLogon = false;
649 }
650 else if (a->argc != 5)
651 {
652 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
653 rc = E_FAIL;
654 break;
655 }
656
657 ComPtr<IGuest> guest;
658 CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
659 CHECK_ERROR_BREAK(guest, SetCredentials(Bstr(a->argv[2]), Bstr(a->argv[3]), Bstr(a->argv[4]), fAllowLocalLogon));
660 }
661#if 0 /* TODO: review & remove */
662 else if (!strcmp(a->argv[1], "dvdattach"))
663 {
664 Bstr uuid;
665 if (a->argc != 3)
666 {
667 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
668 rc = E_FAIL;
669 break;
670 }
671
672 ComPtr<IMedium> dvdMedium;
673
674 /* unmount? */
675 if (!strcmp(a->argv[2], "none"))
676 {
677 /* nothing to do, NULL object will cause unmount */
678 }
679 /* host drive? */
680 else if (!strncmp(a->argv[2], "host:", 5))
681 {
682 ComPtr<IHost> host;
683 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
684
685 rc = host->FindHostDVDDrive(Bstr(a->argv[2] + 5), dvdMedium.asOutParam());
686 if (!dvdMedium)
687 {
688 errorArgument("Invalid host DVD drive name \"%s\"",
689 a->argv[2] + 5);
690 rc = E_FAIL;
691 break;
692 }
693 }
694 else
695 {
696 /* first assume it's a UUID */
697 uuid = a->argv[2];
698 rc = a->virtualBox->GetDVDImage(uuid, dvdMedium.asOutParam());
699 if (FAILED(rc) || !dvdMedium)
700 {
701 /* must be a filename, check if it's in the collection */
702 rc = a->virtualBox->FindDVDImage(Bstr(a->argv[2]), dvdMedium.asOutParam());
703 /* not registered, do that on the fly */
704 if (!dvdMedium)
705 {
706 Bstr emptyUUID;
707 CHECK_ERROR(a->virtualBox, OpenDVDImage(Bstr(a->argv[2]), emptyUUID, dvdMedium.asOutParam()));
708 }
709 }
710 if (!dvdMedium)
711 {
712 rc = E_FAIL;
713 break;
714 }
715 }
716
717 /** @todo generalize this, allow arbitrary number of DVD drives
718 * and as a consequence multiple attachments and different
719 * storage controllers. */
720 if (dvdMedium)
721 dvdMedium->COMGETTER(Id)(uuid.asOutParam());
722 else
723 uuid = Guid().toString();
724 CHECK_ERROR(machine, MountMedium(Bstr("IDE Controller"), 1, 0, uuid, FALSE /* aForce */));
725 }
726 else if (!strcmp(a->argv[1], "floppyattach"))
727 {
728 Bstr uuid;
729 if (a->argc != 3)
730 {
731 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
732 rc = E_FAIL;
733 break;
734 }
735
736 ComPtr<IMedium> floppyMedium;
737
738 /* unmount? */
739 if (!strcmp(a->argv[2], "none"))
740 {
741 /* nothing to do, NULL object will cause unmount */
742 }
743 /* host drive? */
744 else if (!strncmp(a->argv[2], "host:", 5))
745 {
746 ComPtr<IHost> host;
747 CHECK_ERROR(a->virtualBox, COMGETTER(Host)(host.asOutParam()));
748 host->FindHostFloppyDrive(Bstr(a->argv[2] + 5), floppyMedium.asOutParam());
749 if (!floppyMedium)
750 {
751 errorArgument("Invalid host floppy drive name \"%s\"",
752 a->argv[2] + 5);
753 rc = E_FAIL;
754 break;
755 }
756 }
757 else
758 {
759 /* first assume it's a UUID */
760 uuid = a->argv[2];
761 rc = a->virtualBox->GetFloppyImage(uuid, floppyMedium.asOutParam());
762 if (FAILED(rc) || !floppyMedium)
763 {
764 /* must be a filename, check if it's in the collection */
765 rc = a->virtualBox->FindFloppyImage(Bstr(a->argv[2]), floppyMedium.asOutParam());
766 /* not registered, do that on the fly */
767 if (!floppyMedium)
768 {
769 Bstr emptyUUID;
770 CHECK_ERROR(a->virtualBox, OpenFloppyImage(Bstr(a->argv[2]), emptyUUID, floppyMedium.asOutParam()));
771 }
772 }
773 if (!floppyMedium)
774 {
775 rc = E_FAIL;
776 break;
777 }
778 }
779 floppyMedium->COMGETTER(Id)(uuid.asOutParam());
780 CHECK_ERROR(machine, MountMedium(Bstr("Floppy Controller"), 0, 0, uuid, FALSE /* aForce */));
781 }
782#endif /* obsolete dvdattach/floppyattach */
783 else if (!strcmp(a->argv[1], "guestmemoryballoon"))
784 {
785 if (a->argc != 3)
786 {
787 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters");
788 rc = E_FAIL;
789 break;
790 }
791 uint32_t uVal;
792 int vrc;
793 vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal);
794 if (vrc != VINF_SUCCESS)
795 {
796 errorArgument("Error parsing guest memory balloon size '%s'", a->argv[2]);
797 rc = E_FAIL;
798 break;
799 }
800 /* guest is running; update IGuest */
801 ComPtr <IGuest> guest;
802 rc = console->COMGETTER(Guest)(guest.asOutParam());
803 if (SUCCEEDED(rc))
804 CHECK_ERROR(guest, COMSETTER(MemoryBalloonSize)(uVal));
805 }
806 else if (!strcmp(a->argv[1], "teleport"))
807 {
808 Bstr bstrHostname;
809 uint32_t uMaxDowntime = 250 /*ms*/;
810 uint32_t uPort = UINT32_MAX;
811 uint32_t cMsTimeout = 0;
812 Bstr bstrPassword("");
813 static const RTGETOPTDEF s_aTeleportOptions[] =
814 {
815 { "--host", 'h', RTGETOPT_REQ_STRING }, /** @todo RTGETOPT_FLAG_MANDATORY */
816 { "--hostname", 'h', RTGETOPT_REQ_STRING }, /** @todo remove this */
817 { "--maxdowntime", 'd', RTGETOPT_REQ_UINT32 },
818 { "--port", 'p', RTGETOPT_REQ_UINT32 }, /** @todo RTGETOPT_FLAG_MANDATORY */
819 { "--password", 'P', RTGETOPT_REQ_STRING },
820 { "--timeout", 't', RTGETOPT_REQ_UINT32 }
821 };
822 RTGETOPTSTATE GetOptState;
823 RTGetOptInit(&GetOptState, a->argc, a->argv, s_aTeleportOptions, RT_ELEMENTS(s_aTeleportOptions), 2, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
824 int ch;
825 RTGETOPTUNION Value;
826 while ( SUCCEEDED(rc)
827 && (ch = RTGetOpt(&GetOptState, &Value)))
828 {
829 switch (ch)
830 {
831 case 'h': bstrHostname = Value.psz; break;
832 case 'd': uMaxDowntime = Value.u32; break;
833 case 'p': uPort = Value.u32; break;
834 case 'P': bstrPassword = Value.psz; break;
835 case 't': cMsTimeout = Value.u32; break;
836 default:
837 errorGetOpt(USAGE_CONTROLVM, ch, &Value);
838 rc = E_FAIL;
839 break;
840 }
841 }
842 if (FAILED(rc))
843 break;
844
845 ComPtr<IProgress> progress;
846 CHECK_ERROR_BREAK(console, Teleport(bstrHostname, uPort, bstrPassword, uMaxDowntime, progress.asOutParam()));
847
848 if (cMsTimeout)
849 {
850 rc = progress->COMSETTER(Timeout)(cMsTimeout);
851 if (FAILED(rc) && rc != VBOX_E_INVALID_OBJECT_STATE)
852 CHECK_ERROR_BREAK(progress, COMSETTER(Timeout)(cMsTimeout)); /* lazyness */
853 }
854
855 rc = showProgress(progress);
856 if (FAILED(rc))
857 {
858 com::ProgressErrorInfo info(progress);
859 if (info.isBasicAvailable())
860 RTPrintf("Error: teleportation failed. Error message: %lS\n", info.getText().raw());
861 else
862 RTPrintf("Error: teleportation failed. No error message available!\n");
863 }
864 }
865 else
866 {
867 errorSyntax(USAGE_CONTROLVM, "Invalid parameter '%s'", Utf8Str(a->argv[1]).raw());
868 rc = E_FAIL;
869 }
870 } while (0);
871
872 a->session->Close();
873
874 return SUCCEEDED(rc) ? 0 : 1;
875}
876
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