VirtualBox

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

Last change on this file since 33281 was 32885, checked in by vboxsync, 14 years ago

Renaming cpu priority to cpu execution cap

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