VirtualBox

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

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

com/string: Remove bool conversion operator and other convenience error operators. They are hiding programming errors (like incorrect empty string checks, and in one case a free of the wrong pointer).

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