VirtualBox

Changeset 55591 in vbox for trunk/src


Ignore:
Timestamp:
May 2, 2015 1:57:14 AM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
99964
Message:

Main: Renamed IGuestSession::environment to IGuestSession::environmentChanges, IGuestSession::environmentSet to IGuestSession::environmentScheduleSet, IGuestSession::environmentUnset to IGuestSession::environmentScheduleUnset. Introduced read only IGuestSession::environmentBase attribute and associated IGuestSession::environmentGetBaseVariable and IGuestSession::environmentDoesBaseVariableExist for future exploitations. Changed IGuestProcess::environment back to it's originally documented behavior, though that means it will fail with VBOX_E_NOT_SUPPORTED until the session base environment is implemented.

Location:
trunk/src/VBox
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r55590 r55591  
    51585158        <link to="IConsole::powerUp"/>.
    51595159
     5160<!-- TODO/r=bird: What about making @a environment into a smart array?  Guess
     5161this predates our safe array support by a year or so... Dmitry wrote the text here, right?
     5162Just rename it to @a environmentChanges and shorten the documentation to say the string
     5163are applied onto the server environment putenv style, i.e. "VAR=VALUE" for setting/replacing
     5164and "VAR" for unsetting. -->
    51605165        The @a environment argument is a string containing definitions of
    51615166        environment variables in the following format:
     
    1024210247    </const>
    1024310248    <const name="ExpandArguments"           value="64">
    10244       <desc>Expands environment variables in process arguments.</desc>
     10249      <desc>Expands environment variables in process arguments.
     10250        <note>
     10251          This is not yet implemented and is currently silently ignored.
     10252          We will document the protocolVersion number for this feature once it
     10253          appears, so don't use it till then.
     10254        </note>
     10255      </desc>
    1024510256    </const>
    1024610257    <const name="UnquotedArguments"         value="128">
     
    1078310794  <interface
    1078410795    name="IGuestSession" extends="$unknown"
    10785     uuid="e1fa83fe-437d-3e3a-9278-4297f1ca95dd"
     10796    uuid="bb890975-4903-38f8-4bc2-f39341f95533"
    1078610797    wsmap="managed"
    1078710798    >
     
    1079510806<!-- r=bird: Is the root session part of the maximum of 32?? Not really clear. -->
    1079610807      This root session is controlling all other guest sessions and also is
    10797       responsible for actions which require system level privileges.  Each
    10798       guest session keeps track of its started guest processes, opened guest
    10799       files or guest directories.  To work on guest files or directories a
    10800       guest session offers methods to open or create such objects (see
    10801       <link to="IGuestSession::fileOpen"/> or
    10802       <link to="IGuestSession::directoryOpen"/> for example).
     10808      responsible for actions which require system level privileges.
     10809
     10810      Each guest session keeps track of the guest directories and files that
     10811      it opened as well as guest processes it has created.  To work on guest
     10812      files or directories a guest session offers methods to open or create
     10813      such objects (see <link to="IGuestSession::fileOpen"/> or
     10814      <link to="IGuestSession::directoryOpen"/> for instance).  Similarly,
     10815      there a methods for creating guest processes.
     10816
     10817      There can be up to 2048 objects (guest processes, files and directories)
     10818      a time per guest session.  Exceeding the limit will result in an error.
     10819<!-- @todo r=bird: Add specific VBOX_E_XXX error for this and document it here! -->
    1080310820
    1080410821      When done with either of these objects, including the guest session itself,
    1080510822      use the appropriate close() method to let the object do its cleanup work.
    1080610823
    10807       A set of environment variables changes is associated with each session.
    10808       These are applied to the standard environment of the impersonated guest
    10809       user when creating a new guest process.  For additional flexibility the
    10810       <link to="IGuestSession::processCreate"/> and
    10811       <link to="IGuestSession::processCreateEx"/> methods allows you to specify
    10812       individual environment changes for each process you create.
     10824      Closing a session via <link to="IGuestSession::close" /> will try to close
     10825      all the mentioned objects above unless these objects are still used by
     10826      a client.
     10827
     10828      A set of environment variables changes is associated with each session
     10829      (<link to="IGuestSession::environmentChanges"/>).  These are applied to
     10830      the base environment of the impersonated guest user when creating a new
     10831      guest process.  For additional flexibility the <link to="IGuestSession::processCreate"/>
     10832      and <link to="IGuestSession::processCreateEx"/> methods allows you to
     10833      specify individual environment changes for each process you create.
     10834      With newer guest addition versions, the base environment is also made
     10835      available via <link to="IGuestSession::environmentBase"/>.  (One reason
     10836      for why we record changes to a base environment instead of working
     10837      directly on an environment block is that we need to be compatible
     10838      with older guest additions.  Another reason is that this way it is always
     10839      possible to undo all the changes you've scheduled.)
    1081310840    </desc>
    1081410841
     
    1084510872      <desc>Returns the current session status.</desc>
    1084610873    </attribute>
    10847     <attribute name="environment" type="wstring" safearray="yes">
    10848       <!-- r=bird: Would probably be a great idea to rename this attribute as
    10849                    it is misleading and will cause worse confusion if we ever
    10850                    expose the default environment for session (which arguably
    10851                    would be useful in many ways).   -->
    10852       <desc>
    10853         The set of environment changes.  They are in putenv format, i.e.
    10854         "NAME=VALUE" for setting and "NAME" for unsetting.
     10874    <attribute name="environmentChanges" type="wstring" safearray="yes">
     10875      <desc>
     10876        The set of scheduled environment changes to the base environment of the
     10877        session.  They are in putenv format, i.e. "VAR=VALUE" for setting and
     10878        "VAR" for unsetting.  One entry per variable (change).  The changes are
     10879        applied when creating new guest processes.
     10880
     10881        This is writable, so to undo all the scheduled changes, assign it an
     10882        empty array.
     10883      </desc>
     10884    </attribute>
     10885    <attribute name="environmentBase" type="wstring" safearray="yes" readonly="yes">
     10886      <desc>
     10887        The base environment of the session.  They are on the "VAR=VALUE" form,
     10888        one array entry per variable.
     10889        <!-- @todo/TODO/FIXME: This doesn't end up in the PDF.
     10890        <result name="VBOX_E_NOT_SUPPORTED">If the guest additions does not
     10891          support the session base environment feature.  Support for this was
     10892          introduced with protocol version XXX.</result>
     10893        <result name="VBOX_E_INVALID_OBJECT_STATE">If the guest additions has
     10894          yet to report the session base environment.</result> -->
     10895
     10896        Access fails with VBOX_E_NOT_SUPPORTED if the guest additions does not
     10897        support the session base environment feature.  Support for this was
     10898        introduced with protocol version XXXX.
     10899
     10900        Access fails with VBOX_E_INVALID_OBJECT_STATE if the guest additions
     10901        has yet to report the session base environment.
    1085510902      </desc>
    1085610903    </attribute>
     
    1111011157    </method>
    1111111158
    11112     <method name="environmentSet">
     11159    <method name="environmentScheduleSet">
    1111311160      <desc>
    1111411161        Schedules setting an environment variable when creating the next guest
    11115         process.  This affects the <link to="IGuestSession::environment"/> attribute.
     11162        process.  This affects the <link to="IGuestSession::environmentChanges"/>
     11163        attribute.
    1111611164      </desc>
    1111711165      <param name="name" type="wstring" dir="in">
     
    1112411172    </method>
    1112511173
    11126     <method name="environmentUnset">
     11174    <method name="environmentScheduleUnset">
    1112711175      <desc>
    1112811176        Schedules unsetting (removing) an environment variable when creating
    11129         the next guest process.  This affects the <link to="IGuestSession::environment"/>
    11130         attribute.
     11177        the next guest process.  This affects the
     11178        <link to="IGuestSession::environmentChanges"/> attribute.
    1113111179      </desc>
    1113211180      <param name="name" type="wstring" dir="in">
    1113311181        <desc>Name of the environment variable to unset.  This cannot be empty
    1113411182          nor can it contain any equal signs.</desc>
     11183      </param>
     11184    </method>
     11185
     11186    <method name="environmentGetBaseVariable">
     11187      <desc>
     11188        Gets an environment variable from the session's base environment
     11189        (<link to="IGuestSession::environmentBase"/>).
     11190
     11191        <result name="VBOX_E_NOT_SUPPORTED">If the guest additions does not
     11192          support the session base environment feature.  Support for this was
     11193          introduced with protocol version XXXX.</result>
     11194        <result name="VBOX_E_INVALID_OBJECT_STATE">If the guest additions has
     11195          yet to report the session base environment.</result>
     11196      </desc>
     11197      <param name="name" type="wstring" dir="in">
     11198        <desc>Name of the environment variable to   get.This cannot be empty
     11199          nor can it contain any equal signs.</desc>
     11200      </param>
     11201      <param name="value" type="wstring" dir="return">
     11202        <desc>
     11203          The value of the variable.  Empty if not found.  To deal with
     11204          variables that may have empty values, use
     11205          <link to="IGuestSession::environmentDoesBaseVariableExist"/>.
     11206        </desc>
     11207      </param>
     11208    </method>
     11209
     11210    <method name="environmentDoesBaseVariableExist">
     11211      <desc>
     11212        Checks if the given environment variable exists in the session's base
     11213        environment (<link to="IGuestSession::environmentBase"/>).
     11214
     11215        <result name="VBOX_E_NOT_SUPPORTED">If the guest additions does not
     11216          support the session base environment feature.  Support for this was
     11217          introduced with protocol version XXXX.</result>
     11218        <result name="VBOX_E_INVALID_OBJECT_STATE">If the guest additions has
     11219          yet to report the session base environment.</result>
     11220      </desc>
     11221      <param name="name" type="wstring" dir="in">
     11222        <desc>Name of the environment variable to look for.  This cannot be
     11223          empty nor can it contain any equal signs.</desc>
     11224      </param>
     11225      <param name="exists" type="boolean" dir="return">
     11226        <desc>TRUE if the variable exists, FALSE if not.</desc>
    1113511227      </param>
    1113611228    </method>
     
    1143211524        </desc>
    1143311525      </param>
    11434       <param name="environment" type="wstring" dir="in" safearray="yes">
     11526      <param name="environmentChanges" type="wstring" dir="in" safearray="yes">
    1143511527        <desc>
    1143611528          Set of environment changes to complement
    11437           <link to="IGuestSession::environment"/>.  Takes precedence over
    11438           the session ones.  The changes are in putenv format, i.e.
    11439           "NAME=VALUE" for setting and "NAME" for unsetting.
    11440 
    11441           The changes are applied to the standard environment of the
    11442           impersonated guest user when creating the process.
     11529          <link to="IGuestSession::environmentChanges"/>.  Takes precedence
     11530          over the session ones.  The changes are in putenv format, i.e.
     11531          "VAR=VALUE" for setting and "VAR" for unsetting.
     11532
     11533          The changes are applied to the base environment of the impersonated
     11534          guest user (<link to="IGuestSession::environmentBase"/>) when
     11535          creating the process.  (This is done on the guest side of things in
     11536          order to be compatible with older guest additions.  That is one of
     11537          the motivations for not passing in the whole environment here.)
    1144311538        </desc>
    1144411539      </param>
     
    1148811583        </desc>
    1148911584      </param>
    11490       <param name="environment" type="wstring" dir="in" safearray="yes">
     11585      <param name="environmentChanges" type="wstring" dir="in" safearray="yes">
    1149111586        <desc>
    1149211587          Set of environment changes to complement
    11493           <link to="IGuestSession::environment"/>.  Takes precedence over
    11494           the session ones.  The changes are in putenv format, i.e.
    11495           "NAME=VALUE" for setting and "NAME" for unsetting.
    11496 
    11497           The changes are applied to the standard environment of the
    11498           impersonated guest user when creating the process.
     11588          <link to="IGuestSession::environmentChanges"/>.  Takes precedence
     11589          over the session ones.  The changes are in putenv format, i.e.
     11590          "VAR=VALUE" for setting and "VAR" for unsetting.
     11591
     11592          The changes are applied to the base environment of the impersonated
     11593          guest user (<link to="IGuestSession::environmentBase"/>) when
     11594          creating the process.  (This is done on the guest side of things in
     11595          order to be compatible with older guest additions.  That is one of
     11596          the motivations for not passing in the whole environment here.)
    1149911597        </desc>
    1150011598      </param>
     
    1168811786  <interface
    1168911787    name="IProcess" extends="$unknown"
    11690     uuid="5a4fe06d-8cb1-40ff-ac9e-9676e32f706e"
     11788    uuid="064cf1ca-4c0f-50b5-8f8e-e8b4bfa76c33"
    1169111789    wsmap="managed"
    1169211790    >
     
    1170111799    </attribute>
    1170211800    <attribute name="environment" type="wstring" readonly="yes" safearray="yes">
    11703       <!-- r=bird: Would probably be a great idea to rename this attribute as
    11704                    it is misleading and will cause worse confusion if we ever
    11705                    expose the initial environment for processes.  -->
    11706       <desc>
    11707         The set of environment changes appled to the default environment when
    11708         starting the process.  The format is putenv style, i.e. "NAME=VALUE"
    11709         for variables that should be set and "NAME" for values that should be
    11710         unset (removed).  See also <link to="IGuestSession::environment"/>.
     11801      <desc>
     11802        The initial process environment.  Not yet implemented.
    1171111803      </desc>
    1171211804    </attribute>
     
    1188311975  <interface
    1188411976    name="IGuestProcess" extends="IProcess"
    11885     uuid="dfa39a36-5d43-4840-a025-67ea956b3111"
     11977    uuid="1f3c2d60-4c09-d824-4ca1-579a2bda858f"
    1188611978    wsmap="managed"
    1188711979    >
     
    1249112583        the session object via <link to="IGuest::createSession"/>. Anonymous
    1249212584        sessions, that is, sessions without specifying a valid
    12493         user account in the guest are not allowed due to security reasons.
    12494 
    12495         There can be a maximum of 32 sessions at once per VM. Each session keeps
    12496         track of its started guest processes, opened guest files or guest directories.
    12497         To work on guest files or directories a guest session offers methods to open
    12498         or create such objects (see <link to="IGuestSession::fileOpen"/> or
    12499         <link to="IGuestSession::directoryOpen"/> for example).
    12500 
    12501         There can be up to 2048 objects (guest processes, files or directories)
    12502         a time per guest session. Exceeding the limit will result in an appropriate
    12503         error message.
    12504 
    12505         When done with either of these objects, including the guest session itself,
    12506         use the appropriate close() method to let the object do its cleanup work.
    12507 
    12508         Every guest session has its own environment variable block which gets
    12509         automatically applied when starting a new guest process via
    12510         <link to="IGuestSession::processCreate"/> or <link to="IGuestSession::processCreateEx"/>.
    12511         To override (or unset) certain environment variables already set by the
    12512         guest session, one can specify a per-process environment block when using
    12513         one of the both above mentioned process creation calls.
    12514 
    12515         Closing a session via <link to="IGuestSession::close" /> will try to close
    12516         all the mentioned objects above unless these objects are still used by
    12517         a client.
     12585        user account in the guest are not allowed reasons of security.
     12586
     12587        There can be a maximum of 32 sessions at once per VM.  An error will
     12588        be returned if this has been reached. <!-- This should actually read:
     12589        VBOX_E_IPRT_ERROR will be return if this limit has been reached.
     12590        However, keep in mind that VBOX_E_IPRT_ERROR can be returned for about
     12591        88 unrelated reasons, so you don't know what happend unless you parse
     12592        the error text. (bird) -->
     12593<!-- @todo r=bird: Seriously, add an dedicated VBOX_E_MAX_GUEST_SESSIONS status
     12594for this condition.  Do the same for all other maximums and things that could be
     12595useful to the API client. -->
     12596
     12597        For more information please consult <link to="IGuestSession"/>
    1251812598      </desc>
    1251912599      <param name="user" type="wstring" dir="in">
  • trunk/src/VBox/Main/include/GuestCtrlImplPrivate.h

    r55588 r55591  
    2626#include <iprt/env.h>
    2727#include <iprt/semaphore.h>
     28#include <iprt/cpp/utils.h>
    2829
    2930#include <VBox/com/com.h>
     
    7879    GuestEnvironmentBase(void)
    7980        : m_hEnv(NIL_RTENV)
     81        , m_cRefs(1)
    8082    { }
    8183
     
    8587    virtual ~GuestEnvironmentBase(void)
    8688    {
     89        Assert(m_cRefs <= 1);
    8790        int rc = RTEnvDestroy(m_hEnv); AssertRC(rc);
    8891        m_hEnv = NIL_RTENV;
     
    9093
    9194    /**
    92      * Initialize this as a normal environment block.
    93      * @returns IPRT status code.
    94      */
    95     int initNormal(void)
    96     {
    97         AssertReturn(m_hEnv == NIL_RTENV, VERR_WRONG_ORDER);
    98         return RTEnvCreate(&m_hEnv);
     95     * Retains a reference to this object.
     96     * @returns New reference count.
     97     * @remarks Sharing an object is currently only safe if no changes are made to
     98     *          it because RTENV does not yet implement any locking.  For the only
     99     *          purpose we need this, implementing IGuestProcess::environment by
     100     *          using IGuestSession::environmentBase, that's fine as the session
     101     *          base environment is immutable.
     102     */
     103    uint32_t retain(void)
     104    {
     105        uint32_t cRefs = ASMAtomicIncU32(&m_cRefs);
     106        Assert(cRefs > 1); Assert(cRefs < _1M);
     107        return cRefs;
     108
     109    }
     110    /** Useful shortcut. */
     111    uint32_t retainConst(void) const { return unconst(this)->retain(); }
     112
     113    /**
     114     * Releases a reference to this object, deleting the object when reaching zero.
     115     * @returns New reference count.
     116     */
     117    uint32_t release(void)
     118    {
     119        uint32_t cRefs = ASMAtomicDecU32(&m_cRefs);
     120        Assert(cRefs < _1M);
     121        if (cRefs == 0)
     122            delete this;
     123        return cRefs;
     124    }
     125
     126    /** Useful shortcut. */
     127    uint32_t releaseConst(void) const { return unconst(this)->retain(); }
     128
     129    /**
     130     * Checks if the environment has been successfully initialized or not.
     131     *
     132     * @returns @c true if initialized, @c false if not.
     133     */
     134    bool isInitialized(void) const
     135    {
     136        return m_hEnv != NIL_RTENV;
    99137    }
    100138
     
    167205        return VINF_SUCCESS;
    168206    }
     207
     208    /**
     209     * Applies the changes from another environment to this.
     210     *
     211     * @returns IPRT status code.
     212     * @param   rChanges        Reference to an environment which variables will be
     213     *                          imported and, if it's a change record, schedule
     214     *                          variable unsets will be applied.
     215     * @sa      RTEnvApplyChanges
     216     */
     217    int applyChanges(const GuestEnvironmentBase &rChanges)
     218    {
     219        return RTEnvApplyChanges(m_hEnv, rChanges.m_hEnv);
     220    }
     221
    169222
    170223    /**
     
    219272
    220273    /**
     274     * Checks if the given variable exists.
     275     *
     276     * @returns @c true if it exists, @c false if not or if it's an scheduled unset
     277     *          in a environment change record.
     278     * @param   rName               The variable name.
     279     * @sa      RTEnvExistEx
     280     */
     281    bool doesVariableExist(const com::Utf8Str &rName) const
     282    {
     283        return RTEnvExistEx(m_hEnv, rName.c_str());
     284    }
     285
     286    /**
    221287     * Set an environment variable.
    222288     *
     
    243309    }
    244310
    245 #if 0
    246 private:
    247     /* No copy operator. */
    248     GuestEnvironmentBase(const GuestEnvironmentBase &) { throw E_FAIL; }
    249 #else
     311protected:
    250312    /**
    251313     * Copy constructor.
     
    259321            throw (Global::vboxStatusCodeToCOM(rc));
    260322    }
    261 #endif
    262 
    263 protected:
     323
    264324    /**
    265325     * Common clone/copy method with type conversion abilities.
     
    304364
    305365    /** The environment change record. */
    306     RTENV       m_hEnv;
    307 };
    308 
    309 
    310 #if 0 /* Not currently used. */
     366    RTENV               m_hEnv;
     367    /** Reference counter. */
     368    uint32_t volatile   m_cRefs;
     369};
     370
     371
    311372/**
    312373 * Wrapper around the RTEnv API for a normal environment.
     
    364425    }
    365426};
    366 #endif /* unused */
    367427
    368428
     
    548608    ProcessArguments            mArguments;
    549609    /** The process environment change record.  */
    550     GuestEnvironmentChanges     mEnvironment;
     610    GuestEnvironmentChanges     mEnvironmentChanges;
    551611    /** Process creation flags. */
    552612    uint32_t                    mFlags;
     
    9801040protected:
    9811041
    982     /**
    983      * Commom parameters for all derived objects, when then have
    984      * an own mData structure to keep their specific data around.
    985      */
    986 
     1042    /** @name Common parameters for all derived objects.  They have their own
     1043     * mData structure to keep their specific data around.
     1044     * @{ */
    9871045    /** Pointer to parent session. Per definition
    9881046     *  this objects *always* lives shorter than the
    989      *  parent. */
     1047     *  parent.
     1048     * @todo r=bird: When wanting to use mSession in the
     1049     * IGuestProcess::getEnvironment() implementation I wanted to access
     1050     * GuestSession::mData::mpBaseEnvironment.  Seeing the comment in
     1051     * GuestProcess::terminate() saying:
     1052     *      "Now only API clients still can hold references to it."
     1053     * and recalling seeing similar things in VirtualBox.xidl or some such place,
     1054     * I'm wondering how this "per definition" behavior is enforced.  Is there any
     1055     * GuestProcess:uninit() call or similar magic that invalidates objects that
     1056     * GuestSession loses track of in place like GuestProcess::terminate() that I've
     1057     * failed to spot?
     1058     *
     1059     * Please enlighten me.
     1060     */
    9901061    GuestSession            *mSession;
    9911062    /** The object ID -- must be unique for each guest
     
    9961067     *  for guest files this is the internal file ID. */
    9971068    uint32_t                 mObjectID;
    998 };
    999 #endif // ____H_GUESTIMPLPRIVATE
    1000 
     1069    /** @} */
     1070};
     1071#endif // !____H_GUESTIMPLPRIVATE
     1072
  • trunk/src/VBox/Main/include/GuestProcessImpl.h

    r51321 r55591  
    2222#include "GuestProcessWrap.h"
    2323
     24#include <iprt/cpp/utils.h>
     25
    2426class Console;
    2527class GuestSession;
     
    3739    DECLARE_EMPTY_CTOR_DTOR(GuestProcess)
    3840
    39     int     init(Console *aConsole, GuestSession *aSession, ULONG aProcessID, const GuestProcessStartupInfo &aProcInfo);
     41    int     init(Console *aConsole, GuestSession *aSession, ULONG aProcessID,
     42                 const GuestProcessStartupInfo &aProcInfo, const GuestEnvironment *pBaseEnv);
    4043    void    uninit(void);
    4144    HRESULT FinalConstruct(void);
     
    137140        /** The process startup information. */
    138141        GuestProcessStartupInfo  mProcess;
     142        /** Reference to the immutable session base environment. NULL if the
     143         * environment feature isn't supported.
     144         * @remarks If there is proof that the uninit order of GuestSession and
     145         *          this class is what GuestObjectBase claims, then this isn't
     146         *          strictly necessary. */
     147        GuestEnvironment const  *mpSessionBaseEnv;
    139148        /** Exit code if process has been terminated. */
    140149        LONG                     mExitCode;
     
    146155         *  returned from the guest side. */
    147156        int                      mLastError;
     157
     158        Data(void) : mpSessionBaseEnv(NULL)
     159        { }
     160        ~Data(void)
     161        {
     162            if (mpSessionBaseEnv)
     163            {
     164                mpSessionBaseEnv->releaseConst();
     165                mpSessionBaseEnv = NULL;
     166            }
     167        }
    148168    } mData;
    149169};
  • trunk/src/VBox/Main/include/GuestSessionImpl.h

    r55590 r55591  
    268268    HRESULT getProtocolVersion(ULONG *aProtocolVersion);
    269269    HRESULT getStatus(GuestSessionStatus_T *aStatus);
    270     HRESULT getEnvironment(std::vector<com::Utf8Str> &aEnvironment);
    271     HRESULT setEnvironment(const std::vector<com::Utf8Str> &aEnvironment);
     270    HRESULT getEnvironmentChanges(std::vector<com::Utf8Str> &aEnvironmentChanges);
     271    HRESULT setEnvironmentChanges(const std::vector<com::Utf8Str> &aEnvironmentChanges);
     272    HRESULT getEnvironmentBase(std::vector<com::Utf8Str> &aEnvironmentBase);
    272273    HRESULT getProcesses(std::vector<ComPtr<IGuestProcess> > &aProcesses);
    273274    HRESULT getDirectories(std::vector<ComPtr<IGuestDirectory> > &aDirectories);
     
    312313    HRESULT directorySetACL(const com::Utf8Str &aPath,
    313314                             const com::Utf8Str &aAcl);
    314     HRESULT environmentSet(const com::Utf8Str &aName,
    315                            const com::Utf8Str &aValue);
    316     HRESULT environmentUnset(const com::Utf8Str &aName);
     315    HRESULT environmentScheduleSet(const com::Utf8Str &aName,
     316                                   const com::Utf8Str &aValue);
     317    HRESULT environmentScheduleUnset(const com::Utf8Str &aName);
     318    HRESULT environmentGetBaseVariable(const com::Utf8Str &aName,
     319                                       com::Utf8Str &aValue);
     320    HRESULT environmentDoesBaseVariableExist(const com::Utf8Str &aName,
     321                                             BOOL *aExists);
    317322    HRESULT fileCreateTemp(const com::Utf8Str &aTemplateName,
    318323                           ULONG aMode,
     
    469474        /** The set of environment changes for the session for use when
    470475         *  creating new guest processes. */
    471         GuestEnvironmentChanges     mEnvironment;
     476        GuestEnvironmentChanges     mEnvironmentChanges;
     477        /** Pointer to the immutable base environment for the session.
     478         * @note This is not allocated until the guest reports it to the host. It is
     479         *       also shared with child processes. */
     480        GuestEnvironment const     *mpBaseEnvironment;
    472481        /** Directory objects bound to this session. */
    473482        SessionDirectories          mDirectories;
     
    488497         *  returned from the guest side. */
    489498        int                         mRC;
     499
     500        Data(void)
     501            : mpBaseEnvironment(NULL)
     502        { }
     503        Data(const Data &rThat)
     504            : mCredentials(rThat.mCredentials)
     505            , mSession(rThat.mSession)
     506            , mStatus(rThat.mStatus)
     507            , mEnvironmentChanges(rThat.mEnvironmentChanges)
     508            , mpBaseEnvironment(NULL)
     509            , mDirectories(rThat.mDirectories)
     510            , mFiles(rThat.mFiles)
     511            , mProcesses(rThat.mProcesses)
     512            , mProtocolVersion(rThat.mProtocolVersion)
     513            , mTimeout(rThat.mTimeout)
     514            , mNumObjects(rThat.mNumObjects)
     515            , mRC(rThat.mRC)
     516        { }
    490517    } mData;
    491518};
  • trunk/src/VBox/Main/src-client/GuestProcessImpl.cpp

    r55588 r55591  
    162162/////////////////////////////////////////////////////////////////////////////
    163163
    164 int GuestProcess::init(Console *aConsole, GuestSession *aSession,
    165                        ULONG aProcessID, const GuestProcessStartupInfo &aProcInfo)
    166 {
    167     LogFlowThisFunc(("aConsole=%p, aSession=%p, aProcessID=%RU32\n",
    168                      aConsole, aSession, aProcessID));
     164int GuestProcess::init(Console *aConsole, GuestSession *aSession, ULONG aProcessID,
     165                       const GuestProcessStartupInfo &aProcInfo, const GuestEnvironment *pBaseEnv)
     166{
     167    LogFlowThisFunc(("aConsole=%p, aSession=%p, aProcessID=%RU32 pBaseEnv=%p\n",
     168                     aConsole, aSession, aProcessID, pBaseEnv));
    169169
    170170    AssertPtrReturn(aConsole, VERR_INVALID_POINTER);
     
    237237    {
    238238        mData.mProcess = aProcInfo;
     239        mData.mpSessionBaseEnv = pBaseEnv;
     240        if (pBaseEnv)
     241            pBaseEnv->retainConst();
    239242        mData.mExitCode = 0;
    240243        mData.mPID = 0;
     
    274277     *       case of failure. */
    275278
     279    if (mData.mpSessionBaseEnv)
     280    {
     281        mData.mpSessionBaseEnv->releaseConst();
     282        mData.mpSessionBaseEnv = NULL;
     283    }
     284
    276285    baseUninit();
    277286
     
    298307HRESULT GuestProcess::getEnvironment(std::vector<com::Utf8Str> &aEnvironment)
    299308{
    300 #ifndef VBOX_WITH_GUEST_CONTROL
     309#ifndef VBOX_WTIH_GUEST_CONTROL
    301310    ReturnComNotImplemented();
    302311#else
    303     LogFlowThisFuncEnter();
    304 
    305     AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    306     mData.mProcess.mEnvironment.queryPutEnvArray(&aEnvironment);
    307     return S_OK;
    308 #endif /* VBOX_WITH_GUEST_CONTROL */
     312    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);  /* (Paranoia since both environment objects are immutable.) */
     313    HRESULT hrc;
     314    if (mData.mpSessionBaseEnv)
     315    {
     316        int vrc;
     317        if (mData.mProcess.mEnvironmentChanges.count() == 0)
     318            vrc = mData.mpSessionBaseEnv->queryPutEnvArray(&aEnvironment);
     319        else
     320        {
     321            GuestEnvironment TmpEnv;
     322            vrc = TmpEnv.copy(*mData.mpSessionBaseEnv);
     323            if (RT_SUCCESS(vrc))
     324            {
     325                vrc = TmpEnv.applyChanges(mData.mProcess.mEnvironmentChanges);
     326                if (RT_SUCCESS(rc))
     327                    vrc = TmpEnv.queryPutEnvArray(&aEnvironment);
     328            }
     329        }
     330        hrc = Global::vboxStatusCodeToCOM(vrc);
     331    }
     332    else
     333        hrc = setError(VBOX_E_NOT_SUPPORTED, tr("The base environment feature is not supported by the guest additions"));
     334    LogFlowThisFuncLeave();
     335    return hrc;
     336#endif
    309337}
    310338
     
    10571085    char   *pszzEnvBlock;
    10581086    if (RT_SUCCESS(vrc))
    1059         vrc = mData.mProcess.mEnvironment.queryUtf8Block(&pszzEnvBlock, &cbEnvBlock);
     1087        vrc = mData.mProcess.mEnvironmentChanges.queryUtf8Block(&pszzEnvBlock, &cbEnvBlock);
    10601088
    10611089    if (RT_SUCCESS(vrc))
     
    10691097        paParms[i++].setUInt32((uint32_t)mData.mProcess.mArguments.size());
    10701098        paParms[i++].setPointer(pszArgs, (uint32_t)cbArgs);
    1071         paParms[i++].setUInt32(mData.mProcess.mEnvironment.count());
     1099        paParms[i++].setUInt32(mData.mProcess.mEnvironmentChanges.count());
    10721100        paParms[i++].setUInt32((uint32_t)cbEnvBlock);
    10731101        paParms[i++].setPointer(pszzEnvBlock, (uint32_t)cbEnvBlock);
     
    11091137        }
    11101138
    1111         mData.mProcess.mEnvironment.freeUtf8Block(pszzEnvBlock);
     1139        mData.mProcess.mEnvironmentChanges.freeUtf8Block(pszzEnvBlock);
    11121140    }
    11131141
  • trunk/src/VBox/Main/src-client/GuestSessionImpl.cpp

    r55590 r55591  
    205205    mData.mStatus = GuestSessionStatus_Undefined;
    206206    mData.mNumObjects = 0;
    207     int rc = mData.mEnvironment.initNormal();
     207    mData.mpBaseEnvironment = NULL;
     208    int rc = mData.mEnvironmentChanges.initChangeRecord();
    208209    if (RT_SUCCESS(rc))
    209210    {
     
    320321    mData.mProcesses.clear();
    321322
    322     mData.mEnvironment.reset();
     323    mData.mEnvironmentChanges.reset();
     324
     325    if (mData.mpBaseEnvironment)
     326    {
     327        GuestEnvironment *pBaseEnv = unconst(mData.mpBaseEnvironment);
     328        mData.mpBaseEnvironment = NULL;
     329        pBaseEnv->release();
     330    }
    323331
    324332    AssertMsg(mData.mNumObjects == 0,
     
    462470}
    463471
    464 HRESULT GuestSession::getEnvironment(std::vector<com::Utf8Str> &aEnvironment)
     472HRESULT GuestSession::getEnvironmentChanges(std::vector<com::Utf8Str> &aEnvironmentChanges)
    465473{
    466474#ifndef VBOX_WITH_GUEST_CONTROL
     
    471479    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
    472480
    473     int vrc = mData.mEnvironment.queryPutEnvArray(&aEnvironment);
     481    int vrc = mData.mEnvironmentChanges.queryPutEnvArray(&aEnvironmentChanges);
    474482
    475483    LogFlowFuncLeaveRC(vrc);
     
    478486}
    479487
    480 HRESULT GuestSession::setEnvironment(const std::vector<com::Utf8Str> &aEnvironment)
     488HRESULT GuestSession::setEnvironmentChanges(const std::vector<com::Utf8Str> &aEnvironmentChanges)
    481489{
    482490#ifndef VBOX_WITH_GUEST_CONTROL
     
    487495    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    488496
    489     mData.mEnvironment.reset();
    490     int vrc = mData.mEnvironment.applyPutEnvArray(aEnvironment);
     497    mData.mEnvironmentChanges.reset();
     498    int vrc = mData.mEnvironmentChanges.applyPutEnvArray(aEnvironmentChanges);
    491499
    492500    LogFlowFuncLeaveRC(vrc);
    493501    return Global::vboxStatusCodeToCOM(vrc);
     502#endif /* VBOX_WITH_GUEST_CONTROL */
     503}
     504
     505HRESULT GuestSession::getEnvironmentBase(std::vector<com::Utf8Str> &aEnvironmentBase)
     506{
     507#ifndef VBOX_WITH_GUEST_CONTROL
     508    ReturnComNotImplemented();
     509#else
     510    LogFlowThisFuncEnter();
     511
     512    AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     513    HRESULT hrc;
     514    if (mData.mpBaseEnvironment)
     515    {
     516        int vrc = mData.mpBaseEnvironment->queryPutEnvArray(&aEnvironmentBase);
     517        hrc = Global::vboxStatusCodeToCOM(vrc);
     518    }
     519    else if (mData.mProtocolVersion < 99999)
     520        hrc = setError(VBOX_E_NOT_SUPPORTED, tr("The base environment feature is not supported by the guest additions"));
     521    else
     522        hrc = setError(VBOX_E_INVALID_OBJECT_STATE, tr("The base environment has not yet been reported by the guest"));
     523
     524    LogFlowFuncLeave();
     525    return hrc;
    494526#endif /* VBOX_WITH_GUEST_CONTROL */
    495527}
     
    19171949
    19181950    rc = pProcess->init(mParent->i_getConsole() /* Console */, this /* Session */,
    1919                         uNewProcessID, procInfo);
     1951                        uNewProcessID, procInfo, mData.mpBaseEnvironment);
    19201952    if (RT_FAILURE(rc))
    19211953        return rc;
     
    29042936}
    29052937
    2906 HRESULT GuestSession::environmentSet(const com::Utf8Str &aName, const com::Utf8Str &aValue)
     2938HRESULT GuestSession::environmentScheduleSet(const com::Utf8Str &aName, const com::Utf8Str &aValue)
    29072939{
    29082940#ifndef VBOX_WITH_GUEST_CONTROL
     
    29172949        {
    29182950            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2919             int vrc = mData.mEnvironment.setVariable(aName, aValue);
     2951            int vrc = mData.mEnvironmentChanges.setVariable(aName, aValue);
    29202952            if (RT_SUCCESS(vrc))
    29212953                hrc = S_OK;
     
    29342966}
    29352967
    2936 HRESULT GuestSession::environmentUnset(const com::Utf8Str &aName)
     2968HRESULT GuestSession::environmentScheduleUnset(const com::Utf8Str &aName)
    29372969{
    29382970#ifndef VBOX_WITH_GUEST_CONTROL
     
    29462978        {
    29472979            AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);
    2948             int vrc = mData.mEnvironment.unsetVariable(aName);
     2980            int vrc = mData.mEnvironmentChanges.unsetVariable(aName);
    29492981            if (RT_SUCCESS(vrc))
    29502982                hrc = S_OK;
    29512983            else
    29522984                hrc = setErrorVrc(vrc);
     2985        }
     2986        else
     2987            hrc = setError(E_INVALIDARG, tr("The equal char is not allowed in environment variable names"));
     2988    }
     2989    else
     2990        hrc = setError(E_INVALIDARG, tr("No variable name specified"));
     2991
     2992    LogFlowThisFuncLeave();
     2993    return hrc;
     2994#endif /* VBOX_WITH_GUEST_CONTROL */
     2995}
     2996
     2997HRESULT GuestSession::environmentGetBaseVariable(const com::Utf8Str &aName, com::Utf8Str &aValue)
     2998{
     2999#ifndef VBOX_WITH_GUEST_CONTROL
     3000    ReturnComNotImplemented();
     3001#else
     3002    LogFlowThisFuncEnter();
     3003    HRESULT hrc;
     3004    if (RT_LIKELY(aName.isNotEmpty()))
     3005    {
     3006        if (RT_LIKELY(strchr(aName.c_str(), '=') == NULL))
     3007        {
     3008            AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     3009            if (mData.mpBaseEnvironment)
     3010            {
     3011                int vrc = mData.mpBaseEnvironment->getVariable(aName, &aValue);
     3012                if (RT_SUCCESS(vrc))
     3013                    hrc = S_OK;
     3014                else
     3015                    hrc = setErrorVrc(vrc);
     3016            }
     3017            else if (mData.mProtocolVersion < 99999)
     3018                hrc = setError(VBOX_E_NOT_SUPPORTED, tr("The base environment feature is not supported by the guest additions"));
     3019            else
     3020                hrc = setError(VBOX_E_INVALID_OBJECT_STATE, tr("The base environment has not yet been reported by the guest"));
     3021        }
     3022        else
     3023            hrc = setError(E_INVALIDARG, tr("The equal char is not allowed in environment variable names"));
     3024    }
     3025    else
     3026        hrc = setError(E_INVALIDARG, tr("No variable name specified"));
     3027
     3028    LogFlowThisFuncLeave();
     3029    return hrc;
     3030#endif /* VBOX_WITH_GUEST_CONTROL */
     3031}
     3032
     3033HRESULT GuestSession::environmentDoesBaseVariableExist(const com::Utf8Str &aName, BOOL *aExists)
     3034{
     3035#ifndef VBOX_WITH_GUEST_CONTROL
     3036    ReturnComNotImplemented();
     3037#else
     3038    LogFlowThisFuncEnter();
     3039    *aExists = FALSE;
     3040    HRESULT hrc;
     3041    if (RT_LIKELY(aName.isNotEmpty()))
     3042    {
     3043        if (RT_LIKELY(strchr(aName.c_str(), '=') == NULL))
     3044        {
     3045            AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);
     3046            if (mData.mpBaseEnvironment)
     3047            {
     3048                hrc = S_OK;
     3049                *aExists = mData.mpBaseEnvironment->doesVariableExist(aName);
     3050            }
     3051            else if (mData.mProtocolVersion < 99999)
     3052                hrc = setError(VBOX_E_NOT_SUPPORTED, tr("The base environment feature is not supported by the guest additions"));
     3053            else
     3054                hrc = setError(VBOX_E_INVALID_OBJECT_STATE, tr("The base environment has not yet been reported by the guest"));
    29533055        }
    29543056        else
     
    33453447       the caller, giving priority to the latter.  The changes are putenv style
    33463448       and will be applied to the standard environment for the guest user. */
    3347     int vrc = procInfo.mEnvironment.copy(mData.mEnvironment);
     3449    int vrc = procInfo.mEnvironmentChanges.copy(mData.mEnvironmentChanges);
    33483450    if (RT_SUCCESS(vrc))
    3349         vrc = procInfo.mEnvironment.applyPutEnvArray(aEnvironment);
     3451        vrc = procInfo.mEnvironmentChanges.applyPutEnvArray(aEnvironment);
    33503452    if (RT_SUCCESS(vrc))
    33513453    {
  • trunk/src/VBox/ValidationKit/tests/additions/tdAddGuestCtrl.py

    r55590 r55591  
    10701070    def testGuestCtrlSessionEnvironment(self, oSession, oTxsSession, oTestVm): # pylint: disable=R0914
    10711071        """
    1072         Tests the guest session environment.
     1072        Tests the guest session environment changes.
    10731073        """
    10741074
     
    11121112        ];
    11131113
     1114        # The IGuestSession::environment attribute changed late in 5.0 development.
     1115        sEnvironmentChangesAttr = 'environmentChanges' if self.oTstDrv.fpApiVer >= 5.0 else 'environment';
     1116
    11141117        # Parameters.
    11151118        fRc = True;
     
    11271130                break;
    11281131            # Make sure environment is empty.
    1129             curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, 'environment');
     1132            curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, sEnvironmentChangesAttr);
    11301133            reporter.log2('Test #%d: Environment initially has %d elements' % (i, len(curEnv)));
    11311134            if len(curEnv) != 0:
     
    11451148                                  % (i, strKey, strValue, len(aElems)));
    11461149                    try:
    1147                         curGuestSession.environmentSet(strKey, strValue); # No return (e.g. boolean) value available thru wrapper.
     1150                        if self.oTstDrv.fpApiVer >= 5.0:
     1151                            curGuestSession.environmentScheduleSet(strKey, strValue);
     1152                        else:
     1153                            curGuestSession.environmentSet(strKey, strValue);
    11481154                    except:
    11491155                        # Setting environment variables might fail (e.g. if empty name specified). Check.
    11501156                        reporter.logXcpt('Test #%d failed: Setting environment variable failed:' % (i,));
    1151                         curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, 'environment');
     1157                        curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, sEnvironmentChangesAttr);
    11521158                        if len(curEnv) is not curRes.cNumVars:
    11531159                            reporter.error('Test #%d failed: Session environment has %d vars, expected %d' \
     
    11581164                            reporter.log('Test #%d: API reported an error (single), good' % (i,));
    11591165                    ## @todo environmentGet() has been removed in 5.0 because it's not up to the task of returning all the
    1160                     ## putenv strings forms and gives the impression that the envrionment is something it isn't. This test
     1166                    ## putenv strings forms and gives the impression that the environment is something it isn't. This test
    11611167                    ## should be rewritten using the attribute.  What's more, there should be an Unset test here, shouldn't
    11621168                    ## there?
     
    11971203                    except:
    11981204                        # Setting environment variables might fail (e.g. if empty name specified). Check.
    1199                         curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, 'environment');
     1205                        curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, sEnvironmentChangesAttr);
    12001206                        if len(curEnv) is not curRes.cNumVars:
    12011207                            reporter.error('Test #%d failed: Session environment has %d vars, expected %d (array)' \
     
    12071213                ## @todo Get current system environment and add it to curRes.cNumVars before comparing!
    12081214                reporter.log('Test #%d: Environment size' % (i,));
    1209                 curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, 'environment');
     1215                curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, sEnvironmentChangesAttr);
    12101216                reporter.log2('Test #%d: Environment (%d) -> %s' % (i, len(curEnv), curEnv));
    12111217                if len(curEnv) != curRes.cNumVars:
     
    12151221                    break;
    12161222
    1217                 self.oTstDrv.oVBoxMgr.setArray(curGuestSession, 'environment', []);
    1218                 curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, 'environment');
     1223                self.oTstDrv.oVBoxMgr.setArray(curGuestSession, sEnvironmentChangesAttr, []);
     1224                curEnv = self.oTstDrv.oVBoxMgr.getArray(curGuestSession, sEnvironmentChangesAttr);
    12191225                if len(curEnv) is not 0:
    12201226                    reporter.error('Test #%d failed: Session environment has %d vars, expected 0');
Note: See TracChangeset for help on using the changeset viewer.

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