VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/guestctrl/UIGuestControlInterface.cpp@ 102493

Last change on this file since 102493 was 100245, checked in by vboxsync, 15 months ago

FE/Qt: Checking appropriate GA facility first while seaching for guest control functionality.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.0 KB
Line 
1/* $Id: UIGuestControlInterface.cpp 100245 2023-06-22 10:46:35Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIGuestControlInterface class implementation.
4 */
5
6/*
7 * Copyright (C) 2016-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* GUI includes: */
29#include "UIErrorString.h"
30#include "UIGuestControlInterface.h"
31#include "UICommon.h"
32
33/* COM includes: */
34#include "CFsObjInfo.h"
35#include "CGuestDirectory.h"
36#include "CGuestProcess.h"
37#include "CGuestSession.h"
38#include "CGuestFsObjInfo.h"
39
40/* Misc. includes: */
41#include <iprt/err.h>
42#include <iprt/getopt.h>
43
44
45#define GCTLCMD_COMMON_OPT_USER 999 /**< The --username option number. */
46#define GCTLCMD_COMMON_OPT_PASSWORD 998 /**< The --password option number. */
47#define GCTLCMD_COMMON_OPT_PASSWORD_FILE 997 /**< The --password-file option number. */
48#define GCTLCMD_COMMON_OPT_DOMAIN 996 /**< The --domain option number. */
49#define GCTLCMD_COMMON_OPT_SESSION_NAME 995 /**< The --sessionname option number. */
50#define GCTLCMD_COMMON_OPT_SESSION_ID 994 /**< The --sessionid option number. */
51
52#define RETURN_ERROR(strError) \
53 do { \
54 m_strStatus.append(strError); \
55 return false; \
56 } while (0)
57
58#define RETURN_MESSAGE(strMessage) \
59 do { \
60 m_strStatus.append(strMessage); \
61 return true; \
62 } while (0)
63
64#define GCTLCMD_COMMON_OPTION_DEFS() \
65 { "--username", GCTLCMD_COMMON_OPT_USER, RTGETOPT_REQ_STRING }, \
66 { "--passwordfile", GCTLCMD_COMMON_OPT_PASSWORD_FILE, RTGETOPT_REQ_STRING }, \
67 { "--password", GCTLCMD_COMMON_OPT_PASSWORD, RTGETOPT_REQ_STRING }, \
68 { "--domain", GCTLCMD_COMMON_OPT_DOMAIN, RTGETOPT_REQ_STRING }, \
69 { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, \
70 { "--verbose", 'v', RTGETOPT_REQ_NOTHING },
71
72#define HANDLE_COMMON_OPTION_DEFS() \
73 case GCTLCMD_COMMON_OPT_USER: \
74 commandData.m_strUserName = ValueUnion.psz; \
75 break; \
76 case GCTLCMD_COMMON_OPT_PASSWORD: \
77 commandData.m_strPassword = ValueUnion.psz; \
78 break;
79
80/* static */ QString UIGuestControlInterface::getFsObjTypeString(KFsObjType type)
81{
82 QString strType;
83 switch(type)
84 {
85 case KFsObjType_Unknown:
86 strType = "Unknown";
87 break;
88 case KFsObjType_Fifo:
89 strType = "Fifo";
90 break;
91 case KFsObjType_DevChar:
92 strType = "DevChar";
93 break;
94 case KFsObjType_Directory:
95 strType = "Directory";
96 break;
97 case KFsObjType_DevBlock:
98 strType = "DevBlock";
99 break;
100 case KFsObjType_File:
101 strType = "File";
102 break;
103 case KFsObjType_Symlink:
104 strType = "Symlink";
105 break;
106 case KFsObjType_Socket:
107 strType = "Socket";
108 break;
109 case KFsObjType_WhiteOut:
110 strType = "WhiteOut";
111 break;
112 default:
113 strType = "Unknown";
114 break;
115 }
116 return strType;
117};
118
119QString generateErrorString(int getOptErrorCode, const RTGETOPTUNION &/*valueUnion*/)
120{
121 QString errorString;
122 // if (valueUnion.pDef)
123 // {
124 // if (valueUnion.pDef->pszLong)
125 // {
126 // errorString = QString(valueUnion.pDef->pszLong);
127 // }
128 // }
129
130 switch (getOptErrorCode)
131 {
132 case VERR_GETOPT_UNKNOWN_OPTION:
133 errorString = errorString.append("RTGetOpt: Command line option not recognized.");
134 break;
135 case VERR_GETOPT_REQUIRED_ARGUMENT_MISSING:
136 errorString = errorString.append("RTGetOpt: Command line option needs argument.");
137 break;
138 case VERR_GETOPT_INVALID_ARGUMENT_FORMAT:
139 errorString = errorString.append("RTGetOpt: Command line option has argument with bad format.");
140 break;
141 case VINF_GETOPT_NOT_OPTION:
142 errorString = errorString.append("RTGetOpt: Not an option.");
143 break;
144 case VERR_GETOPT_INDEX_MISSING:
145 errorString = errorString.append("RTGetOpt: Command line option needs an index.");
146 break;
147 default:
148 break;
149 }
150 return errorString;
151}
152
153/** Common option definitions: */
154class CommandData
155{
156public:
157 CommandData()
158 : m_bSessionIdGiven(false)
159 , m_bSessionNameGiven(false)
160 , m_bCreateParentDirectories(false){}
161 QString m_strUserName;
162 QString m_strPassword;
163 QString m_strExePath;
164 QString m_strSessionName;
165 QString m_strPath;
166 ULONG m_uSessionId;
167 QString m_strDomain;
168 bool m_bSessionIdGiven;
169 bool m_bSessionNameGiven;
170 /* Create the whole path during mkdir */
171 bool m_bCreateParentDirectories;
172 QVector<QString> m_arguments;
173 QVector<QString> m_environmentChanges;
174};
175
176UIGuestControlInterface::UIGuestControlInterface(QObject* parent, const CGuest &comGuest)
177 :QObject(parent)
178 , m_comGuest(comGuest)
179 , m_strHelp("[common-options]\t[--username <name>] [--domain <domain>]\n"
180 "\t\t[--passwordfile <file> | --password <password>]\n"
181 "start\t\t[common-options]\n"
182 "\t\t[--exe <path to executable>] [--timeout <msec>]\n"
183 "\t\t[--sessionid <id> | [sessionname <name>]]\n"
184 "\t\t[-E|--putenv <NAME>[=<VALUE>]] [--unquoted-args]\n"
185 "\t\t[--ignore-orphaned-processes] [--profile]\n"
186 "\t\t-- <program/arg0> [argument1] ... [argumentN]]\n"
187 "createsession\t\t[common-options] [--sessionname <name>]\n"
188 "mkdir\t\t[common-options]\n"
189 "\t\t[-P|--parents] [<guest directory>\n"
190 "\t\t[--sessionid <id> | --sessionname <name>]\n"
191 "stat|ls\t\t[common-options]\n"
192 "\t\t[--sessionid <id> | --sessionname <name>]\n"
193 "list\n"
194 )
195{
196 prepareSubCommandHandlers();
197}
198
199bool UIGuestControlInterface::handleMkdir(int argc , char** argv)
200{
201
202 CommandData commandData;
203
204 static const RTGETOPTDEF s_aOptions[] =
205 {
206 GCTLCMD_COMMON_OPTION_DEFS()
207 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING },
208 { "--sessionid", GCTLCMD_COMMON_OPT_SESSION_ID, RTGETOPT_REQ_UINT32 },
209 { "--parents", 'P', RTGETOPT_REQ_NOTHING }
210 };
211
212 int ch;
213 bool pathFound = false;
214 RTGETOPTUNION ValueUnion;
215 RTGETOPTSTATE GetState;
216 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* ignore 0th element (command) */, 0);
217 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
218 {
219 switch (ch)
220 {
221 HANDLE_COMMON_OPTION_DEFS()
222 case GCTLCMD_COMMON_OPT_SESSION_NAME:
223 commandData.m_bSessionNameGiven = true;
224 commandData.m_strSessionName = ValueUnion.psz;
225 break;
226 case GCTLCMD_COMMON_OPT_SESSION_ID:
227 commandData.m_bSessionIdGiven = true;
228 commandData.m_uSessionId = ValueUnion.i32;
229 break;
230 case 'P':
231 commandData.m_bCreateParentDirectories = true;
232 break;
233 case VINF_GETOPT_NOT_OPTION:
234 if (!pathFound)
235 {
236 commandData.m_strPath = ValueUnion.psz;
237 pathFound = true;
238 }
239 /* Allow only a single NOT_OPTION */
240 else
241 RETURN_ERROR(generateErrorString(ch, ValueUnion));
242
243 break;
244 default:
245 RETURN_ERROR(generateErrorString(ch, ValueUnion));
246 }
247 }
248 if (commandData.m_strPath.isEmpty())
249 RETURN_ERROR(QString(m_strHelp).append("Syntax error! No path is given\n"));
250
251 CGuestSession guestSession;
252 if (!findOrCreateSession(commandData, guestSession) || !guestSession.isOk())
253 return false;
254
255
256 //const QString &strErr = comProgressInstall.GetErrorInfo().GetText();
257 QVector<KDirectoryCreateFlag> creationFlags;
258 if (commandData.m_bCreateParentDirectories)
259 creationFlags.push_back(KDirectoryCreateFlag_None);
260 else
261 creationFlags.push_back(KDirectoryCreateFlag_Parents);
262
263 guestSession.DirectoryCreate(commandData.m_strPath, 0 /*ULONG aMode*/, creationFlags);
264
265 //startProcess(commandData, guestSession);
266 return true;
267}
268
269bool UIGuestControlInterface::handleStat(int argc, char** argv)
270{
271 CommandData commandData;
272
273 static const RTGETOPTDEF s_aOptions[] =
274 {
275 GCTLCMD_COMMON_OPTION_DEFS()
276 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING },
277 { "--sessionid", GCTLCMD_COMMON_OPT_SESSION_ID, RTGETOPT_REQ_UINT32 }
278 };
279
280 int ch;
281 bool pathFound = false;
282 RTGETOPTUNION ValueUnion;
283 RTGETOPTSTATE GetState;
284 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* ignore 0th element (command) */, 0);
285 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
286 {
287 switch (ch)
288 {
289 HANDLE_COMMON_OPTION_DEFS()
290 case GCTLCMD_COMMON_OPT_SESSION_NAME:
291 commandData.m_bSessionNameGiven = true;
292 commandData.m_strSessionName = ValueUnion.psz;
293 break;
294 case GCTLCMD_COMMON_OPT_SESSION_ID:
295 commandData.m_bSessionIdGiven = true;
296 commandData.m_uSessionId = ValueUnion.i32;
297 break;
298 case 'P':
299 commandData.m_bCreateParentDirectories = true;
300 break;
301 case VINF_GETOPT_NOT_OPTION:
302 if (!pathFound)
303 {
304 commandData.m_strPath = ValueUnion.psz;
305 pathFound = true;
306 }
307 /* Allow only a single NOT_OPTION */
308 else
309 RETURN_ERROR(generateErrorString(ch, ValueUnion));
310
311 break;
312 default:
313 RETURN_ERROR(generateErrorString(ch, ValueUnion));
314 }
315 }
316 if (commandData.m_strPath.isEmpty())
317 RETURN_ERROR(QString(m_strHelp).append("Syntax error! No path is given\n"));
318
319 CGuestSession guestSession;
320 if (!findOrCreateSession(commandData, guestSession) || !guestSession.isOk())
321 return false;
322 if (guestSession.GetStatus() != KGuestSessionStatus_Started)
323 RETURN_ERROR("The guest session is not valid");
324
325 bool isADirectory =
326 guestSession.DirectoryExists(commandData.m_strPath, false /*BOOL aFollowSymlinks*/);
327
328 bool isAFile = false;
329 if (!isADirectory)
330 isAFile = guestSession.FileExists(commandData.m_strPath, false /*BOOL aFollowSymlinks*/);
331
332 if (!isADirectory && !isAFile)
333 RETURN_ERROR("Specified object does not exist");
334
335 CGuestFsObjInfo fsObjectInfo = guestSession.FsObjQueryInfo(commandData.m_strPath, false /*BOOL aFollowSymlinks*/);
336 if (!fsObjectInfo.isOk())
337 RETURN_ERROR("Cannot get object info");
338 QString strObjectInfo = getFsObjInfoString<CGuestFsObjInfo>(fsObjectInfo);
339
340 /* In case it is a directory get a list of its content: */
341 if (isADirectory)
342 {
343 QVector<KDirectoryOpenFlag> aFlags;
344 aFlags.push_back(KDirectoryOpenFlag_None);
345 CGuestDirectory directory = guestSession.DirectoryOpen(commandData.m_strPath, /*aFilter*/ "", aFlags);
346 if (directory.isOk())
347 {
348 CFsObjInfo directoryInfo = directory.Read();
349 while (directoryInfo.isOk())
350 {
351 strObjectInfo.append("\n");
352 strObjectInfo.append(getFsObjInfoString<CFsObjInfo>(directoryInfo));
353 directoryInfo = directory.Read();
354 }
355 }
356 }
357 RETURN_MESSAGE(strObjectInfo);
358}
359
360bool UIGuestControlInterface::handleList(int, char**)
361{
362 if (!m_comGuest.isOk())
363 RETURN_ERROR("The guest session is not valid");
364
365 QString strSessionInfo;
366 QVector<CGuestSession> sessions = m_comGuest.GetSessions();
367 if (sessions.isEmpty())
368 {
369 strSessionInfo.append("No guest sessions");
370 RETURN_MESSAGE(strSessionInfo);
371 }
372 strSessionInfo += QString("Listing %1 guest sessions in total:\n").arg(QString::number(sessions.size()));
373 //strSessionInfo += QString("\t%1\t%2\n").arg("Session Name").arg("Session Id");
374
375 for (int i = 0; i < sessions.size(); ++i)
376 {
377 strSessionInfo += QString("\tName: %1\t\tID: %2\n").arg(sessions[i].GetName()).arg(QString::number(sessions[i].GetId()));
378 QVector<CGuestProcess> processes = sessions[i].GetProcesses();
379 strSessionInfo += QString("\t%1 guest prcesses for this session:\n").arg(QString::number(processes.size()));
380
381 for (int j = 0; j < processes.size(); ++j)
382 {
383 strSessionInfo += QString("\t\tName: %1\t\tID: %2\n").arg(processes[j].GetName()).arg(QString::number(processes[j].GetPID()));
384
385 }
386 }
387 RETURN_MESSAGE(strSessionInfo);
388}
389
390bool UIGuestControlInterface::handleStart(int argc, char** argv)
391{
392 enum kGstCtrlRunOpt
393 {
394 kGstCtrlRunOpt_IgnoreOrphanedProcesses = 1000,
395 kGstCtrlRunOpt_NoProfile, /** @todo Deprecated and will be removed soon; use kGstCtrlRunOpt_Profile instead, if needed. */
396 kGstCtrlRunOpt_Profile,
397 kGstCtrlRunOpt_Dos2Unix,
398 kGstCtrlRunOpt_Unix2Dos,
399 kGstCtrlRunOpt_WaitForStdOut,
400 kGstCtrlRunOpt_NoWaitForStdOut,
401 kGstCtrlRunOpt_WaitForStdErr,
402 kGstCtrlRunOpt_NoWaitForStdErr
403 };
404
405 CommandData commandData;
406
407 static const RTGETOPTDEF s_aOptions[] =
408 {
409 GCTLCMD_COMMON_OPTION_DEFS()
410 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING },
411 { "--sessionid", GCTLCMD_COMMON_OPT_SESSION_ID, RTGETOPT_REQ_UINT32 },
412 { "--putenv", 'E', RTGETOPT_REQ_STRING },
413 { "--exe", 'e', RTGETOPT_REQ_STRING },
414 { "--timeout", 't', RTGETOPT_REQ_UINT32 },
415 { "--unquoted-args", 'u', RTGETOPT_REQ_NOTHING },
416 { "--ignore-orphaned-processes", kGstCtrlRunOpt_IgnoreOrphanedProcesses, RTGETOPT_REQ_NOTHING },
417 { "--no-profile", kGstCtrlRunOpt_NoProfile, RTGETOPT_REQ_NOTHING }, /** @todo Deprecated. */
418 { "--profile", kGstCtrlRunOpt_Profile, RTGETOPT_REQ_NOTHING }
419 };
420
421 int ch;
422 RTGETOPTUNION ValueUnion;
423 RTGETOPTSTATE GetState;
424 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1 /* ignore 0th element (command) */, 0);
425 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
426 {
427 switch (ch)
428 {
429 HANDLE_COMMON_OPTION_DEFS()
430 case GCTLCMD_COMMON_OPT_SESSION_NAME:
431 commandData.m_bSessionNameGiven = true;
432 commandData.m_strSessionName = ValueUnion.psz;
433 break;
434 case GCTLCMD_COMMON_OPT_SESSION_ID:
435 commandData.m_bSessionIdGiven = true;
436 commandData.m_uSessionId = ValueUnion.i32;
437 break;
438 case 'e':
439 commandData.m_strExePath = ValueUnion.psz;
440 break;
441 default:
442 RETURN_ERROR(generateErrorString(ch, ValueUnion));
443 }
444 }
445 if (commandData.m_strExePath.isEmpty())
446 RETURN_ERROR(QString(m_strHelp).append("Syntax error! No executable is given\n"));
447
448 CGuestSession guestSession;
449 if (!findOrCreateSession(commandData, guestSession) || !guestSession.isOk())
450 return false;
451 startProcess(commandData, guestSession);
452 return true;
453}
454
455bool UIGuestControlInterface::findOrCreateSession(const CommandData &commandData, CGuestSession &outGuestSession)
456{
457 if (commandData.m_bSessionNameGiven && commandData.m_strSessionName.isEmpty())
458 RETURN_ERROR(QString(m_strHelp).append("'Session Name' is not name valid\n"));
459
460 /* Check if sessionname and sessionid are both supplied */
461 if (commandData.m_bSessionIdGiven && commandData.m_bSessionNameGiven)
462 RETURN_ERROR(QString(m_strHelp).append("Both 'Session Name' and 'Session Id' are supplied\n"));
463
464 /* If sessionid is given then look for the session. if not found return without starting the process: */
465 else if (commandData.m_bSessionIdGiven && !commandData.m_bSessionNameGiven)
466 {
467 if (!findSession(commandData.m_uSessionId, outGuestSession))
468 {
469 RETURN_ERROR(QString(m_strHelp).append("No session with id %1 found.\n").arg(commandData.m_uSessionId));
470 }
471 else
472 return true;
473 }
474 /* If sessionname is given then look for the session. if not try to create a session with the provided name: */
475 else if (!commandData.m_bSessionIdGiven && commandData.m_bSessionNameGiven)
476 {
477 if (!findSession(commandData.m_strSessionName, outGuestSession))
478 {
479 if (!createSession(commandData, outGuestSession))
480 return false;
481 else
482 return true;
483 }
484 else
485 return true;
486 }
487 /* search within the existing CGuestSessions and return a valid one if found: */
488 if (findAValidGuestSession(outGuestSession))
489 return true;
490 /* if neither sessionname and session id is given then create a new session */
491 if (!createSession(commandData, outGuestSession))
492 return false;
493 return true;
494}
495
496bool UIGuestControlInterface::findAValidGuestSession(CGuestSession &outGuestSession)
497{
498 if (!m_comGuest.isOk())
499 return false;
500
501 QVector<CGuestSession> sessions = m_comGuest.GetSessions();
502 for (int i = 0; i < sessions.size(); ++i)
503 {
504 if (sessions[i].isOk() && sessions[i].GetStatus() == KGuestSessionStatus_Started)
505 {
506 outGuestSession = sessions[i];
507 return true;
508 }
509 }
510 return false;
511}
512
513bool UIGuestControlInterface::handleHelp(int, char**)
514{
515 emit sigOutputString(m_strHelp);
516 return true;
517}
518
519bool UIGuestControlInterface::handleCreateSession(int argc, char** argv)
520{
521 CommandData commandData;
522
523 static const RTGETOPTDEF s_aOptions[] =
524 {
525 GCTLCMD_COMMON_OPTION_DEFS()
526 { "--sessionname", GCTLCMD_COMMON_OPT_SESSION_NAME, RTGETOPT_REQ_STRING }
527 };
528
529 int ch;
530 RTGETOPTUNION ValueUnion;
531 RTGETOPTSTATE GetState;
532 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
533 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
534 {
535 switch (ch)
536 {
537 HANDLE_COMMON_OPTION_DEFS()
538 case GCTLCMD_COMMON_OPT_SESSION_NAME:
539 commandData.m_strSessionName = ValueUnion.psz;
540 if (commandData.m_strSessionName.isEmpty())
541 {
542 RETURN_ERROR(QString("'Session Name' is not name valid\n").append(m_strHelp));
543 }
544 break;
545 default:
546 break;
547 }
548 }
549 CGuestSession guestSession;
550 if (!createSession(commandData, guestSession))
551 return false;
552 return true;
553}
554
555bool UIGuestControlInterface::startProcess(const CommandData &commandData, CGuestSession &guestSession)
556{
557 QVector<KProcessCreateFlag> createFlags;
558 createFlags.push_back(KProcessCreateFlag_WaitForProcessStartOnly);
559 CGuestProcess process = guestSession.ProcessCreate(commandData.m_strExePath,
560 commandData.m_arguments,
561 "", /* Working directory. */
562 commandData.m_environmentChanges,
563 createFlags,
564 0);
565 if (!process.isOk())
566 return false;
567 return true;
568}
569
570UIGuestControlInterface::~UIGuestControlInterface()
571{
572}
573
574void UIGuestControlInterface::prepareSubCommandHandlers()
575{
576 m_subCommandHandlers.insert("createsession" , &UIGuestControlInterface::handleCreateSession);
577 m_subCommandHandlers.insert("start", &UIGuestControlInterface::handleStart);
578 m_subCommandHandlers.insert("help" , &UIGuestControlInterface::handleHelp);
579 m_subCommandHandlers.insert("mkdir" , &UIGuestControlInterface::handleMkdir);
580 m_subCommandHandlers.insert("stat" , &UIGuestControlInterface::handleStat);
581 m_subCommandHandlers.insert("ls" , &UIGuestControlInterface::handleStat);
582 m_subCommandHandlers.insert("list" , &UIGuestControlInterface::handleList);
583}
584
585void UIGuestControlInterface::putCommand(const QString &strCommand)
586{
587 if (!isGuestAdditionsAvailable(m_comGuest, "6.1"))
588 {
589 emit sigOutputString("No guest addtions detected. Guest control requires guest additions");
590 return;
591 }
592
593 char **argv;
594 int argc;
595 QByteArray array = strCommand.toLocal8Bit();
596 RTGetOptArgvFromString(&argv, &argc, array.data(), RTGETOPTARGV_CNV_QUOTE_BOURNE_SH, 0);
597 m_strStatus.clear();
598 static const RTGETOPTDEF s_aOptions[] =
599 {
600 GCTLCMD_COMMON_OPTION_DEFS()
601 };
602
603 int ch;
604 RTGETOPTUNION ValueUnion;
605 RTGETOPTSTATE GetState;
606 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 0, 0);
607 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
608 {
609 switch (ch)
610 {
611 case VINF_GETOPT_NOT_OPTION:
612 {
613 /* Try to map ValueUnion.psz to a sub command handler: */
614 QString strNoOption(ValueUnion.psz);
615 if (!strNoOption.isNull())
616 {
617 QMap<QString, HandleFuncPtr>::iterator iterator =
618 m_subCommandHandlers.find(strNoOption);
619 if (iterator != m_subCommandHandlers.end())
620 {
621 (this->*(iterator.value()))(argc, argv);
622 RTGetOptArgvFree(argv);
623 if (!m_strStatus.isEmpty())
624 emit sigOutputString(m_strStatus);
625 return;
626 }
627 else
628 {
629 emit sigOutputString(QString(m_strHelp).append("\nSyntax Error. Unknown Command '%1'").arg(ValueUnion.psz));
630 RTGetOptArgvFree(argv);
631 return;
632 }
633 }
634 break;
635 }
636 default:
637 break;
638 }
639 }
640 if (!m_strStatus.isEmpty())
641 emit sigOutputString(m_strStatus);
642
643 RTGetOptArgvFree(argv);
644}
645
646bool UIGuestControlInterface::findSession(ULONG sessionId, CGuestSession& outSession)
647{
648 if (!m_comGuest.isOk())
649 return false;
650 QVector<CGuestSession> sessionVector = m_comGuest.GetSessions();
651 if (sessionVector.isEmpty())
652 return false;
653 for (int i = 0; i < sessionVector.size(); ++i)
654 {
655 if (sessionVector.at(i).isOk() && sessionId == sessionVector.at(i).GetId())
656 {
657 outSession = sessionVector.at(i);
658 return true;
659 }
660 }
661 return false;
662}
663
664bool UIGuestControlInterface::findSession(const QString& strSessionName, CGuestSession& outSession)
665{
666 if (!m_comGuest.isOk())
667 return false;
668 QVector<CGuestSession> sessionVector = m_comGuest.FindSession(strSessionName);
669 if (sessionVector.isEmpty())
670 return false;
671 /* Return the first session with @a sessionName */
672 outSession = sessionVector.at(0);
673 return false;
674}
675
676bool UIGuestControlInterface::createSession(const CommandData &commandData, CGuestSession& outSession)
677{
678 if (!m_comGuest.isOk())
679 return false;
680 if (commandData.m_strUserName.isEmpty())
681 RETURN_ERROR("No user name has been given");
682 CGuestSession guestSession = m_comGuest.CreateSession(commandData.m_strUserName,
683 commandData.m_strPassword,
684 commandData.m_strDomain,
685 commandData.m_strSessionName);
686
687 if (!guestSession.isOk())
688 return false;
689
690 /* Wait session to start: */
691 const ULONG waitTimeout = 2000;
692 KGuestSessionWaitResult waitResult = guestSession.WaitFor(KGuestSessionWaitForFlag_Start, waitTimeout);
693 if (waitResult != KGuestSessionWaitResult_Start)
694 return false;
695
696 outSession = guestSession;
697 return true;
698}
699
700/* static */
701bool UIGuestControlInterface::isGuestAdditionsAvailable(const CGuest &guest, const char *pszMinimumVersion)
702{
703 CGuest guestNonConst = const_cast<CGuest&>(guest);
704
705 if (guestNonConst.isNull() || !pszMinimumVersion)
706 return false;
707
708 /* Guest control stuff is in userland: */
709 if (!guestNonConst.GetAdditionsStatus(KAdditionsRunLevelType_Userland))
710 return false;
711
712 if (!guestNonConst.isOk())
713 return false;
714
715 /* Check the related GA facility: */
716 LONG64 iLastUpdatedIgnored;
717 if (guestNonConst.GetFacilityStatus(KAdditionsFacilityType_VBoxService, iLastUpdatedIgnored) != KAdditionsFacilityStatus_Active)
718 return false;
719
720 if (!guestNonConst.isOk())
721 return false;
722
723 QString strGAVersion = guestNonConst.GetAdditionsVersion();
724 if (guestNonConst.isOk())
725 return (RTStrVersionCompare(strGAVersion.toUtf8().constData(), pszMinimumVersion) >= 0);
726
727 return false;
728}
729
730template<typename T>
731QString UIGuestControlInterface::getFsObjInfoString(const T &fsObjectInfo) const
732{
733 QString strObjectInfo;
734 if (!fsObjectInfo.isOk())
735 return strObjectInfo;
736
737 strObjectInfo.append(getFsObjTypeString(fsObjectInfo.GetType()).append("\t"));
738 strObjectInfo.append(fsObjectInfo.GetName().append("\t"));
739 strObjectInfo.append(QString::number(fsObjectInfo.GetObjectSize()).append("\t"));
740
741 /* Currently I dont know a way to convert these into a meaningful date/time: */
742 // strObjectInfo.append("BirthTime", QString::number(fsObjectInfo.GetBirthTime()));
743 // strObjectInfo.append("ChangeTime", QString::number(fsObjectInfo.GetChangeTime()));
744
745 return strObjectInfo;
746}
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