VirtualBox

Changeset 22744 in vbox


Ignore:
Timestamp:
Sep 3, 2009 1:09:02 PM (15 years ago)
Author:
vboxsync
Message:

VBoxService: Sigh. Cleaned up the code myself. It's current disabled as it has not been tested.

Location:
trunk/src/VBox/Additions/common/VBoxService
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxService/Makefile.kmk

    r22728 r22744  
    4040 VBoxService_DEFS        += VBOX_WITH_GUEST_PROPS VBOXSERVICE_VMINFO
    4141 if1of ($(KBUILD_TARGET), win)
    42   VBoxService_DEFS       += VBOX_WITH_HGCM VBOXSERVICE_VMEXEC
     42  VBoxService_DEFS       += VBOX_WITH_HGCM VBOXSERVICE_EXEC
    4343 endif
    4444endif
  • trunk/src/VBox/Additions/common/VBoxService/VBoxService.cpp

    r22530 r22744  
    8383#endif
    8484#ifdef VBOXSERVICE_VMINFO
    85     { &g_VMInfo, NIL_RTTHREAD, false, false, false, true },
    86 #endif
    87 #ifdef VBOXSERVICE_VMEXEC
    88     { &g_VMExec, NIL_RTTHREAD, false, false, false, true },
     85    { &g_VMInfo,    NIL_RTTHREAD, false, false, false, true },
     86#endif
     87#ifdef VBOXSERVICE_EXEC
     88    { &g_Exec,      NIL_RTTHREAD, false, false, false, true },
    8989#endif
    9090};
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceExec.cpp

    r22733 r22744  
    11/* $Id$ */
    22/** @file
    3  * VBoxServiceExec - In-VM Command Execution Service.
    4  */
    5 /** @todo r=bird: Why is this called VMExec while the filename is VBoxServiceExec.cpp? See VMInfo... */
    6 /** @todo r=bird: Use svn-ps.[sh|cmd] -a when adding new files, please. Then the EOLs and $Id$ won't be messed up all the time. */
     3 * VBoxServiceExec - Host-driven Command Execution.
     4 */
    75
    86/*
     
    2725*******************************************************************************/
    2826#include <iprt/assert.h>
     27#include <iprt/ctype.h>
    2928#include <iprt/env.h>
    3029#include <iprt/file.h>
    3130#include <iprt/mem.h>
     31#include <iprt/path.h>
     32#include <iprt/param.h>
    3233#include <iprt/process.h>
    3334#include <iprt/string.h>
     
    3839#include "VBoxServiceInternal.h"
    3940#include "VBoxServiceUtils.h"
    40 #ifdef VBOX_WITH_GUEST_PROPS
    41 # include <VBox/HostServices/GuestPropertySvc.h>
    42 #endif
    4341
    4442
     
    4745*******************************************************************************/
    4846/** The vminfo interval (millseconds). */
    49 uint32_t                g_VMExecInterval = 0;
     47static uint32_t         g_cMsExecInterval = 0;
    5048/** The semaphore we're blocking on. */
    51 static RTSEMEVENTMULTI  g_VMExecEvent = NIL_RTSEMEVENTMULTI;
     49static RTSEMEVENTMULTI  g_hExecEvent = NIL_RTSEMEVENTMULTI;
    5250/** The guest property service client ID. */
    53 static uint32_t         g_VMExecGuestPropSvcClientID = 0;
    54 /** The maximum of arguments a command can have. */
    55 #define EXEC_MAX_ARGS   32
     51static uint32_t         g_uExecGuestPropSvcClientID = 0;
     52
    5653
    5754/** @copydoc VBOXSERVICE::pfnPreInit */
     
    6865    if (ppszShort)
    6966        /* no short options */;
    70     else if (!strcmp(argv[*pi], "--vmexec-interval"))
    71         rc = VBoxServiceArgUInt32(argc, argv, "", pi, &g_VMExecInterval, 1, UINT32_MAX - 1);
     67    else if (!strcmp(argv[*pi], "--exec-interval"))
     68        rc = VBoxServiceArgUInt32(argc, argv, "", pi, &g_cMsExecInterval, 1, UINT32_MAX - 1);
    7269    return rc;
    7370}
     
    8178     * Then create the event sem to block on.
    8279     */
    83     if (!g_VMExecInterval)
    84         g_VMExecInterval = g_DefaultInterval * 1000;
    85     if (!g_VMExecInterval)
    86         g_VMExecInterval = 10 * 1000;
    87 
    88     int rc = RTSemEventMultiCreate(&g_VMExecEvent);
     80    if (!g_cMsExecInterval)
     81        g_cMsExecInterval = g_DefaultInterval * 1000;
     82    if (!g_cMsExecInterval)
     83        g_cMsExecInterval = 10 * 1000;
     84
     85    int rc = RTSemEventMultiCreate(&g_hExecEvent);
    8986    AssertRCReturn(rc, rc);
    9087
    91     rc = VbglR3GuestPropConnect(&g_VMExecGuestPropSvcClientID);
     88    rc = VbglR3GuestPropConnect(&g_uExecGuestPropSvcClientID);
    9289    if (RT_SUCCESS(rc))
    93         VBoxServiceVerbose(3, "Property Service Client ID: %#x\n", g_VMExecGuestPropSvcClientID);
     90        VBoxServiceVerbose(3, "Exec: Property Service Client ID: %#x\n", g_uExecGuestPropSvcClientID);
    9491    else
    9592    {
    96         VBoxServiceError("Failed to connect to the guest property service! Error: %Rrc\n", rc);
    97         RTSemEventMultiDestroy(g_VMExecEvent);
    98         g_VMExecEvent = NIL_RTSEMEVENTMULTI;
     93        VBoxServiceError("Exec: Failed to connect to the guest property service! Error: %Rrc\n", rc);
     94        RTSemEventMultiDestroy(g_hExecEvent);
     95        g_hExecEvent = NIL_RTSEMEVENTMULTI;
    9996    }
    10097
     
    106103 * Validates flags for executable guest properties.
    107104 *
    108  * @returns boolean.
    109  * @retval  true on success.
    110  * @retval  false if not valid.
     105 * @returns VBox status code. Success means they are valid.
    111106 *
    112107 * @param   pszFlags     Pointer to flags to be checked.
    113108 */
    114 bool VBoxServiceExecValidateFlags(char* pszFlags)
    115 {
    116     bool ret = false;
    117 
    118     if (   (NULL != RTStrStr(pszFlags, "TRANSIENT"))
    119         && (NULL != RTStrStr(pszFlags, "RDONLYGUEST")))
     109static int VBoxServiceExecValidateFlags(const char *pszFlags)
     110{
     111    if (!pszFlags)
     112        return VERR_ACCESS_DENIED;
     113    if (!RTStrStr(pszFlags, "TRANSIENT"))
     114        return VERR_ACCESS_DENIED;
     115    if (!RTStrStr(pszFlags, "RDONLYGUEST"))
     116        return VERR_ACCESS_DENIED;
     117    return VINF_SUCCESS;
     118}
     119
     120
     121/**
     122 * Reads a host transient property.
     123 *
     124 * This will validate the flags to make sure it is a transient property that can
     125 * only be change by the host.
     126 *
     127 * @returns VBox status code, fully bitched.
     128 * @param   pszPropName         The property name.
     129 * @param   ppszValue           Where to return the value.  This is always set
     130 *                              to NULL.  Free it using RTStrFree().
     131 * @param   puTimestamp         Where to return the timestamp.  This is only set
     132 *                              on success.  Optional.
     133 */
     134static int VBoxServiceExecReadHostProp(const char *pszPropName, char **ppszValue, uint64_t *puTimestamp)
     135{
     136    size_t  cbBuf = _1K;
     137    void   *pvBuf = NULL;
     138    int     rc;
     139
     140    *ppszValue = NULL;
     141
     142    for (unsigned cTries = 0; cTries < 10; cTries++)
    120143    {
    121         ret = true;
     144        /*
     145         * (Re-)Allocate the buffer and try read the property.
     146         */
     147        RTMemFree(pvBuf);
     148        pvBuf = RTMemAlloc(cbBuf);
     149        if (!pvBuf)
     150        {
     151            VBoxServiceError("Exec: Failed to allocate %zu bytes\n", cbBuf);
     152            rc = VERR_NO_MEMORY;
     153            break;
     154        }
     155        char    *pszValue;
     156        char    *pszFlags;
     157        uint64_t uTimestamp;
     158        rc = VbglR3GuestPropRead(g_uExecGuestPropSvcClientID, pszPropName,
     159                                 pvBuf, cbBuf,
     160                                 &pszValue, &uTimestamp, &pszFlags, NULL);
     161        if (RT_FAILURE(rc))
     162        {
     163            if (rc == VERR_BUFFER_OVERFLOW)
     164            {
     165                /* try again with a bigger buffer. */
     166                cbBuf *= 2;
     167                continue;
     168            }
     169            if (rc == VERR_NOT_FOUND)
     170                VBoxServiceVerbose(2, "Exec: %s not found\n", pszPropName);
     171            else
     172                VBoxServiceError("Exec: Failed to query \"%s\": %Rrc\n", pszPropName, rc);
     173            break;
     174        }
     175
     176        /*
     177         * Validate it and set return values on success.
     178         */
     179        rc = VBoxServiceExecValidateFlags(pszFlags);
     180        if (RT_FAILURE(rc))
     181        {
     182            static uint32_t s_cBitched = 0;
     183            if (++s_cBitched < 10)
     184                VBoxServiceError("Exec: Flag validation failed for \"%s\": %Rrc; flags=\"%s\"\n",
     185                                 pszPropName, rc, pszFlags);
     186            break;
     187        }
     188        VBoxServiceVerbose(2, "Exec: Read \"%s\" = \"%s\", timestamp %RU64n\n",
     189                           pszPropName, pszValue, uTimestamp);
     190        *ppszValue = RTStrDup(pszValue);
     191        if (!*ppszValue)
     192        {
     193            VBoxServiceError("Exec: RTStrDup failed for \"%s\"\n", pszValue);
     194            rc = VERR_NO_MEMORY;
     195            break;
     196        }
     197
     198        if (puTimestamp)
     199            *puTimestamp = uTimestamp;
     200        break; /* done */
    122201    }
    123     VBoxServiceVerbose(3, "Validating flags %s = %s\n",
    124                        ((pszFlags == NULL) || (RTStrICmp(pszFlags, "") == 0)) ? "<NULL>" : pszFlags,
    125                        ret ? "true" : "false");
    126     return ret;
     202
     203    RTMemFree(pvBuf);
     204    return rc;
     205}
     206
     207
     208/**
     209 * Frees an argument vector constructed by VBoxServiceExecCreateArgV.
     210 *
     211 * @param   papszArgs           The vector to free.
     212 */
     213static void VBoxServiceExecFreeArgV(char **papszArgs)
     214{
     215    for (size_t i = 0; papszArgs[i]; i++)
     216    {
     217        RTStrFree(papszArgs[i]);
     218        papszArgs[i] = NULL;
     219    }
     220    RTMemFree(papszArgs);
     221}
     222
     223
     224/**
     225 * Creates an argument vector out of an executable name and a string containing
     226 * the arguments separated by spaces.
     227 *
     228 * @returns VBox status code. Not bitched.
     229 * @param   pszExec             The executable name.
     230 * @param   pszArgs             The string containging the arguments.
     231 * @param   ppapszArgs          Where to return the argument vector.  Not set on
     232 *                              failure.  Use VBoxServiceExecFreeArgV to free.
     233 *
     234 * @todo    Quoted strings. Do it unix (bourne shell) fashion.
     235 */
     236static int VBoxServiceExecCreateArgV(const char *pszExec, const char *pszArgs, char ***ppapszArgs)
     237{
     238    size_t  cAlloc   = 1;
     239    size_t  cUsed    = 1;
     240    char **papszArgs = (char **)RTMemAlloc(sizeof(char *) * (cAlloc + 1));
     241    if (!papszArgs)
     242        return VERR_NO_MEMORY;
     243
     244    /*
     245     * Start by adding the executable name first.
     246     * Note! We keep the papszArgs fully terminated at all times to keep cleanup simple.
     247     */
     248    int     rc   = VERR_NO_MEMORY;
     249    papszArgs[1] = NULL;
     250    papszArgs[0] = RTStrDup(pszExec);
     251    if (papszArgs[0])
     252    {
     253        /*
     254         * Parse the argument string and add any arguments found in it.
     255         */
     256        for (;;)
     257        {
     258            /* skip leading spaces */
     259            char ch;
     260            while ((ch = *pszArgs) && RT_C_IS_SPACE(ch))
     261                pszArgs++;
     262            if (!*pszArgs)
     263            {
     264                *ppapszArgs = papszArgs;
     265                return VINF_SUCCESS;
     266            }
     267
     268            /* find the of the current word. Quoting is ignored atm. */
     269            char const *pszEnd = pszArgs + 1;
     270            while ((ch = *pszEnd) && !RT_C_IS_SPACE(ch))
     271                pszEnd++;
     272
     273            /* resize the vector. */
     274            if (cUsed == cAlloc)
     275            {
     276                cAlloc += 10;
     277                void *pvNew = RTMemRealloc(papszArgs, sizeof(char *) * (cAlloc + 1));
     278                if (!pvNew)
     279                    break;
     280                papszArgs = (char **)pvNew;
     281                for (size_t i = cUsed; i <= cAlloc; i++)
     282                    papszArgs[i] = NULL;
     283            }
     284
     285            /* add it */
     286            papszArgs[cUsed++] = RTStrDupN(pszArgs, (uintptr_t)pszEnd - (uintptr_t)pszArgs);
     287            if (!papszArgs[cUsed++])
     288                break;
     289
     290            /* advance */
     291            pszArgs = pszEnd;
     292        }
     293    }
     294
     295    VBoxServiceExecFreeArgV(papszArgs);
     296    return rc;
    127297}
    128298
     
    131301DECLCALLBACK(int) VBoxServiceExecWorker(bool volatile *pfShutdown)
    132302{
    133     using namespace guestProp;
    134     int rc = VINF_SUCCESS;
     303    int rcRet = VINF_SUCCESS;
    135304
    136305    /*
     
    139308     */
    140309    RTThreadUserSignal(RTThreadSelf());
    141     Assert(g_VMExecGuestPropSvcClientID > 0);
     310    Assert(g_uExecGuestPropSvcClientID > 0);
    142311
    143312    /*
    144313     * Execution loop.
     314     *
     315     * The thread at the moment does nothing but checking for one specific guest property
     316     * for triggering a hard coded sysprep command with parameters given by the host. This
     317     * feature was required by the VDI guys.
     318     *
     319     * Later this thread could become a general host->guest executor.. there are some
     320     * sketches for this in the code.
    145321     */
    146322#ifdef FULL_FEATURED_EXEC
    147323    uint64_t    u64TimestampPrev = UINT64_MAX;
    148324#endif
    149     bool        fSysprepDone     = false;
     325    bool        fSysprepDone = false;
     326    bool        fBitchedAboutMissingSysPrepCmd = false;
    150327    for (;;)
    151328    {
    152         /*
    153          * The thread at the moment does nothing but checking for one specific guest property
    154          * for triggering a hard coded sysprep command with parameters given by the host. This
    155          * feature was required by the VDI guys.
    156          *
    157          * Later this thread could become a general host->guest executor (remote shell?).
    158          */
     329#if 0 /** @todo r=bird: This code needs reviewing and testing before it can be enabled. */
    159330        if (!fSysprepDone)
    160331        {
    161             uint32_t cbBuf = MAX_VALUE_LEN + MAX_FLAGS_LEN + 1024;
    162 
    163             /* Get arguments. */
    164             /** @todo r=bird: How exactly does this work wrt. enabled/disabled?  In
    165              *        ConsoleImpl2.cpp it's now always set to "", which means it will
    166              *        always be executed. So, if someone adds a bogus
    167              *        c:\\sysprep\\sysprep.exe to their system and install the latest
    168              *        additions this will be executed everytime the system starts now - if
    169              *        I understand the code correctly. Is this intentional? */
    170             void* pvSysprepCmd = RTMemAllocZ(cbBuf);
    171             char* pszSysprepCmdValue = NULL;
    172             uint64_t u64SysprepCmdTimestamp = 0;
    173             char* pszSysprepCmdFlags = NULL;
     332            /*
     333             * Get the sysprep command and arguments.
     334             *
     335             * The sysprep executable location is either retrieved from the host
     336             * or is in a hard coded location depending on the Windows version.
     337             */
     338            char *pszSysprepExec = NULL;
    174339#ifdef SYSPREP_WITH_CMD
    175             /* Get sysprep properties. */
     340            int rc = VBoxServiceExecReadHostProp("/VirtualBox/HostGuest/SysprepExec", &pszSysprepExec, NULL);
     341            if (RT_SUCCESS(rc) && !*pszSysprepExec)
     342                rc = VERR_NOT_FOUND;
     343#else
     344            /* Predefined sys. */
     345            int  rc = VINF_SUCCESS;
     346            char szSysprepCmd[RTPATH_MAX] = "C:\\sysprep\\sysprep.exe";
     347            OSVERSIONINFOEX OSInfoEx;
     348            RT_ZERO(OSInfoEx);
     349            OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
     350            if (    GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
     351                &&  OSInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT
     352                &&  OSInfoEx.dwMajorVersion >= 6 /* Vista */)
     353            {
     354                rc = RTEnvGetEx(RTENV_DEFAULT, "windir", szSysPrepCmd, sizeof(szSysPrepCmd), NULL);
     355                if (RT_SUCCESS(rc))
     356                    rc = RTPathAppend(szSysPrepCmd, sizeof(szSysPrepCmd), "system32\\sysprep\\sysprep.exe");
     357            }
     358            pszSysprepExec = szSysprepCmd;
     359#endif
    176360            if (RT_SUCCESS(rc))
    177361            {
    178                 rc = VbglR3GuestPropRead(g_VMExecGuestPropSvcClientID, "/VirtualBox/HostGuest/SysprepCmd",
    179                                          pvSysprepCmd, cbBuf,
    180                                          &pszSysprepCmdValue, &u64SysprepCmdTimestamp, &pszSysprepCmdFlags, NULL);
    181                 if (RT_FAILURE(rc))
    182                 {
    183                     if (rc == VERR_NOT_FOUND)
    184                         VBoxServiceVerbose(2, "Sysprep cmd guest property not found\n");
    185                     else
    186                         VBoxServiceError("Sysprep cmd guest property: Error = %Rrc\n", rc);
    187                 }
    188                 else
    189                 {
    190                     VBoxServiceExecValidateFlags(pszSysprepCmdFlags) ? rc = rc : rc = VERR_ACCESS_DENIED;
    191                     if (RT_SUCCESS(rc))
    192                     {
    193                         if (RTStrNLen(pszSysprepCmdValue, _MAX_PATH) <= 0)
    194                             rc = VERR_NOT_FOUND;
    195                     }
    196                     VBoxServiceVerbose(2, "Sysprep cmd guest property: %Rrc\n", rc);
    197                 }
    198             }
    199 #else
    200             /* Choose sysprep image based on OS version. */
    201             char szSysprepCmd[_MAX_PATH] = "c:\\sysprep\\sysprep.exe";
    202             OSVERSIONINFOEX OSInfoEx;
    203             memset(&OSInfoEx, '\0', sizeof(OSInfoEx));
    204             OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    205             if (GetVersionEx((LPOSVERSIONINFO) &OSInfoEx))
    206             {
    207                 if (OSInfoEx.dwMajorVersion >= 6) /* Use built-in sysprep on Vista or later. */
    208                     RTStrPrintf(szSysprepCmd, sizeof(szSysprepCmd), "%s\\system32\\sysprep\\sysprep.exe", RTEnvGet("windir"));
    209             }
    210             pszSysprepCmdValue = szSysprepCmd;
    211 #endif
    212             void* pvSysprepArgs = RTMemAllocZ(cbBuf);
    213             char* pszSysprepArgsValue = NULL;
    214             uint64_t u64SysprepArgsTimestamp = 0;
    215             char* pszSysprepArgsFlags = NULL;
    216 
    217             if (RT_SUCCESS(rc))
    218             {
    219                 pvSysprepArgs = RTMemAllocZ(cbBuf);
    220                 char szVal[] = "/VirtualBox/HostGuest/SysprepArgs";
    221                 char *pTmp = NULL;
    222                 rc = RTStrCurrentCPToUtf8(&pTmp, szVal);
    223                 rc = VbglR3GuestPropRead(g_VMExecGuestPropSvcClientID, pTmp,
    224                                          pvSysprepArgs, cbBuf,
    225                                          &pszSysprepArgsValue, &u64SysprepArgsTimestamp, &pszSysprepArgsFlags, NULL);
    226                 RTStrFree(pTmp);
    227                 if (RT_FAILURE(rc))
    228                 {
    229                     if (rc == VERR_NOT_FOUND)
    230                         VBoxServiceVerbose(2, "Sysprep argument guest property not found\n");
    231                     else
    232                         VBoxServiceError("Sysprep argument guest property: Error = %Rrc\n", rc);
    233                 }
    234                 else
    235                 {
    236                     VBoxServiceExecValidateFlags(pszSysprepArgsFlags) ? rc = rc : rc = VERR_ACCESS_DENIED;
    237                     if (RT_SUCCESS(rc))
    238                     {
    239                         if (RTStrNLen(pszSysprepArgsValue, EXEC_MAX_ARGS) <= 0)
    240                             rc = VERR_NOT_FOUND;
    241                     }
    242                     VBoxServiceVerbose(2, "Sysprep argument guest property: %Rrc\n", rc);
    243                 }
    244             }
    245 
    246             if (   RT_SUCCESS(rc)
    247                 && !RTFileExists(pszSysprepCmdValue))
    248             {
    249                 VBoxServiceError("Sysprep executable not found! Search path=%s\n", pszSysprepCmdValue);
    250                 rc = VERR_FILE_NOT_FOUND;
    251             }
    252 
    253             if (RT_SUCCESS(rc))
    254             {
    255                 RTPROCESS pid;
    256 
    257                 /* Construct arguments list. */
    258                 /** @todo would be handy to have such a function in IPRT. */
    259                 int16_t index = 0;
    260                 char* pszArg = pszSysprepArgsValue;
    261 
    262                 const char* pArgs[EXEC_MAX_ARGS]; /* Do we have a #define in IPRT for max args? */
    263 
    264                 VBoxServiceVerbose(3, "Sysprep argument value: %s\n", pszSysprepArgsValue);
    265                 pArgs[index++] = pszSysprepCmdValue; /* Store image name as first argument. */
    266                 while (   (pszArg != NULL)
    267                        && (*pszArg != NULL))
    268                 {
    269                     char* pCurArg = (char*)RTMemAllocZ(_MAX_PATH);
    270                     int arg = 0;
    271                     while (   (*pszArg != ' ')
    272                            && (*pszArg != NULL))
    273                     {
    274                         pCurArg[arg++] = *pszArg;
    275                         pszArg++;
    276                     }
    277                     pszArg++; /* Skip leading space. */
    278                     VBoxServiceVerbose(3, "Sysprep argument %d = %s\n", index, pCurArg);
    279                     pArgs[index++] = pCurArg;
    280                 }
    281                 pArgs[index] = NULL;
    282 
    283                 /* Execute ... */
    284                 VBoxServiceVerbose(3, "Executing sysprep ...\n");
    285                 rc = RTProcCreate(pszSysprepCmdValue, pArgs, RTENV_DEFAULT, 0, &pid);
     362                char *pszSysprepArgs;
     363                rc = VBoxServiceExecReadHostProp("/VirtualBox/HostGuest/SysprepArgs", &pszSysprepArgs, NULL);
     364                if (RT_SUCCESS(rc) && !*pszSysprepArgs)
     365                    rc = VERR_NOT_FOUND;
    286366                if (RT_SUCCESS(rc))
    287367                {
    288                     RTPROCSTATUS Status;
    289                     rc = RTProcWait(pid, RTPROCWAIT_FLAGS_BLOCK, &Status);
    290 
    291                     VBoxServiceVerbose(3, "Sysprep returned: %d\n", Status.iStatus);
    292                     if (RT_SUCCESS(rc))
     368                    if (RTFileExists(pszSysprepExec))
    293369                    {
    294                         if (    Status.iStatus == 0
    295                             &&  Status.enmReason == RTPROCEXITREASON_NORMAL)
     370                        char **papszArgs;
     371                        rc = VBoxServiceExecCreateArgV(pszSysprepExec, pszSysprepArgs, &papszArgs);
     372                        if (RT_SUCCESS(rc))
    296373                        {
    297                             fSysprepDone = true; /* We're done, no need to repeat the sysprep exec. */
     374                            /*
     375                             * Execute it synchronously and store the result.
     376                             *
     377                             * Note that RTProcWait should never fail here and
     378                             * that (the host is screwed if it does though).
     379                             */
     380                            VBoxServiceVerbose(3, "Exec: Executing sysprep ...\n");
     381                            for (size_t i = 0; papszArgs[i]; i++)
     382                                VBoxServiceVerbose(3, "Exec: sysprep argv[%u]: \"%s\"\n", i, papszArgs[i]);
     383
     384                            RTPROCESS pid;
     385                            rc = RTProcCreate(pszSysprepExec, papszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &pid);
     386                            if (RT_SUCCESS(rc))
     387                            {
     388                                RTPROCSTATUS Status;
     389                                rc = RTProcWait(pid, RTPROCWAIT_FLAGS_BLOCK, &Status);
     390                                if (RT_SUCCESS(rc))
     391                                {
     392                                    VBoxServiceVerbose(1, "Sysprep returned: %d (reason %d)\n",
     393                                                       Status.iStatus, Status.enmReason);
     394/** @todo r=bird: Figure out whether you should try re-execute sysprep if it
     395 *        fails or not. This is not mentioned in the defect.  */
     396                                    fSysprepDone = true; /* paranoia */
     397
     398                                    /*
     399                                     * Store the result in Set return value so the host knows what happend.
     400                                     */
     401                                    rc = VbglR3GuestPropWriteValueF(g_uExecGuestPropSvcClientID,
     402                                                                    "/VirtualBox/HostGuest/SysprepRet",
     403                                                                    "%d", Status.iStatus);
     404                                    if (RT_FAILURE(rc))
     405                                        VBoxServiceError("Exec: Failed to write SysprepRet: rc=%Rrc\n", rc);
     406                                }
     407                                else
     408                                    VBoxServiceError("Exec: RTProcWait failed for sysprep: %Rrc\n", rc);
     409                            }
     410                            VBoxServiceExecFreeArgV(papszArgs);
    298411                        }
     412                        else
     413                            VBoxServiceError("Exec: VBoxServiceExecCreateArgV: %Rrc\n", rc);
    299414                    }
    300 
    301                     /* Set return value so the host knows what happend. */
    302                     rc = VboxServiceWritePropInt(g_VMExecGuestPropSvcClientID, "HostGuest/SysprepRet", Status.iStatus);
    303                     if (RT_FAILURE(rc))
    304                         VBoxServiceError("Failed to write SysprepRet: rc=%Rrc\n", rc);
     415                    else
     416                    {
     417                        if (!fBitchedAboutMissingSysPrepCmd)
     418                        {
     419                            VBoxServiceError("Exec: Sysprep executable not found! Search path=%s\n", pszSysprepExec);
     420                            fBitchedAboutMissingSysPrepCmd = true;
     421                        }
     422                        rc = VERR_FILE_NOT_FOUND;
     423                    }
     424                    RTStrFree(pszSysprepArgs);
    305425                }
    306 
    307                 /* Destroy argument list (all but the first and last arg, it's just a pointer). */
    308                 for (int i=1; i<index-1; i++)
    309                     RTMemFree((void*)pArgs[i]);
     426#ifndef SYSPREP_WITH_CMD
     427                RTStrFree(pszSysprepExec);
     428#endif
    310429            }
    311         }
     430
     431            /*
     432             * Only continue polling if the guest property value is empty/missing
     433             * or if the sysprep command is missing.
     434             */
     435            if (    rc != VERR_NOT_FOUND
     436                &&  rc != VERR_FILE_NOT_FOUND)
     437            {
     438                VBoxServiceVerbose(1, "Exec: Stopping sysprep processing (rc=%Rrc)\n", rc);
     439                rc = VbglR3GuestPropWriteValueF(g_uExecGuestPropSvcClientID, "/VirtualBox/HostGuest/SysprepVBoxRC", "%d", rc);
     440                if (RT_FAILURE(rc))
     441                    VBoxServiceError("Exec: Failed to write SysprepVBoxRC: rc=%Rrc\n", rc);
     442                fSysprepDone = true;
     443            }
     444        }
     445#endif /* temporarily disabled. */
    312446
    313447#ifdef FULL_FEATURED_EXEC
     
    333467        Wait for changes to the command value. If that fails for some reason other than timeout / interrupt, fall back on the semaphore.
    334468#else
    335         int rc2 = RTSemEventMultiWait(g_VMExecEvent, g_VMExecInterval);
     469        int rc2 = RTSemEventMultiWait(g_hExecEvent, g_cMsExecInterval);
    336470#endif
    337471        if (*pfShutdown)
     
    339473        if (rc2 != VERR_TIMEOUT && RT_FAILURE(rc2))
    340474        {
    341             VBoxServiceError("RTSemEventMultiWait failed; rc2=%Rrc\n", rc2);
    342             rc = rc2;
     475            VBoxServiceError("Exec: Service terminating - RTSemEventMultiWait: %Rrc\n", rc2);
     476            rcRet = rc2;
    343477            break;
    344478        }
    345479    }
    346480
    347     RTSemEventMultiDestroy(g_VMExecEvent);
    348     g_VMExecEvent = NIL_RTSEMEVENTMULTI;
    349     return rc;
     481    RTSemEventMultiDestroy(g_hExecEvent);
     482    g_hExecEvent = NIL_RTSEMEVENTMULTI;
     483    return rcRet;
    350484}
    351485
     
    356490    /** @todo Later, figure what to do if we're in RTProcWait(). it's a very
    357491     *        annoying call since doesn't support timeouts in the posix world. */
    358     RTSemEventMultiSignal(g_VMExecEvent);
     492    RTSemEventMultiSignal(g_hExecEvent);
    359493#ifdef FULL_FEATURED_EXEC
    360494    Interrupts waits.
     
    367501{
    368502    /* Nothing here yet. */
    369     VbglR3GuestPropDisconnect(g_VMExecGuestPropSvcClientID);
    370     g_VMExecGuestPropSvcClientID = 0;
    371 
    372     RTSemEventMultiDestroy(g_VMExecEvent);
    373     g_VMExecEvent = NIL_RTSEMEVENTMULTI;
     503    VbglR3GuestPropDisconnect(g_uExecGuestPropSvcClientID);
     504    g_uExecGuestPropSvcClientID = 0;
     505
     506    RTSemEventMultiDestroy(g_hExecEvent);
     507    g_hExecEvent = NIL_RTSEMEVENTMULTI;
    374508}
    375509
     
    378512 * The 'vminfo' service description.
    379513 */
    380 VBOXSERVICE g_VMExec =
     514VBOXSERVICE g_Exec =
    381515{
    382516    /* pszName. */
    383     "vmexec",
     517    "exec",
    384518    /* pszDescription. */
    385     "Virtual Machine Remote Execution",
     519    "Host-driven Command Execution",
    386520    /* pszUsage. */
    387     "[--vmexec-interval <ms>]"
     521    "[--exec-interval <ms>]"
    388522    ,
    389523    /* pszOptions. */
    390     "    --vmexec-interval   Specifies the interval at which to check for new\n"
     524    "    --exec-interval     Specifies the interval at which to check for new\n"
    391525    "                        remote execution commands. The default is 10000 ms.\n"
    392526    ,
  • trunk/src/VBox/Additions/common/VBoxService/VBoxServiceInternal.h

    r22728 r22744  
    135135extern VBOXSERVICE g_Control;
    136136extern VBOXSERVICE g_VMInfo;
    137 extern VBOXSERVICE g_VMExec;
     137extern VBOXSERVICE g_Exec;
    138138
    139139#ifdef RT_OS_WINDOWS
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette