VirtualBox

Changeset 32653 in vbox


Ignore:
Timestamp:
Sep 21, 2010 7:45:00 AM (14 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
66063
Message:

IPRT/process-win: Added extended user profile invocation (environment variables, registry hives etc).

Location:
trunk/src/VBox
Files:
3 edited

Legend:

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

    r32635 r32653  
    121121        crypt
    122122endif
     123VBoxService_LIBS.win     += \
     124        $(PATH_SDK_$(VBOX_WINDDK)_LIB)/Userenv.lib
    123125ifdef VBOX_WITH_GUEST_PROPS
    124126 VBoxService_LIBS.win    += \
  • trunk/src/VBox/Runtime/Makefile.kmk

    r32648 r32653  
    10801080endif
    10811081VBoxRT_LIBS.win                = \
     1082        $(PATH_SDK_$(VBOX_WINDDK)_LIB)/Userenv.lib \
    10821083        $(PATH_SDK_$(VBOX_WINDDK)_LIB)/vccomsup.lib \
    10831084        $(PATH_SDK_$(VBOX_WINDDK)_LIB)/wbemuuid.lib
  • trunk/src/VBox/Runtime/r3/win/process-win.cpp

    r32292 r32653  
    3636#include <process.h>
    3737#include <errno.h>
     38#include <Strsafe.h>
    3839
    3940#include <iprt/process.h>
     
    480481
    481482
     483/**
     484 * Logs on a specified user and returns its primary token.
     485 *
     486 * @return  int
     487 *
     488 * @param   pwszUser            User name.
     489 * @param   pwszPassword        Password.
     490 * @param   pwszDomain          Domain (not used at the moment).
     491 * @param   phToken             Pointer to store the logon token.
     492 */
     493static int rtProcUserLogon(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain, HANDLE *phToken)
     494{
     495    int rc = VINF_SUCCESS;
     496    /** @todo Add domain support! */
     497    BOOL fRc = LogonUserW(pwszUser,
     498                          /*
     499                           * Because we have to deal with http://support.microsoft.com/kb/245683
     500                           * for NULL domain names when running on NT4 here, pass an empty string if so.
     501                           * However, passing FQDNs should work!
     502                           */
     503                          ((DWORD)(LOBYTE(LOWORD(GetVersion()))) < 5)  /* < Windows 2000. */
     504                          ? L""   /* NT4 and older. */
     505                          : NULL, /* Windows 2000 and up. */
     506                          pwszPassword,
     507                          LOGON32_LOGON_INTERACTIVE,
     508                          LOGON32_PROVIDER_DEFAULT,
     509                          phToken);
     510    if (!fRc)
     511        rc = RTErrConvertFromWin32(GetLastError());
     512    return rc;
     513}
     514
     515
     516/**
     517 * Logs off a user, specified by the given tokken.
     518 *
     519 * @param   hToken      The token (=user) to log off.
     520 */
     521static void rtProcUserLogoff(HANDLE hToken)
     522{
     523    CloseHandle(hToken);
     524}
     525
     526
     527/**
     528 * Creates an environment block out of a handed in Unicode and RTENV block.
     529 * The RTENV block can overwrite entries already present in the Unicode block.
     530 *
     531 * @return  IPRT status code.
     532 *
     533 * @param   pvBlock         Unicode block (array) of environment entries; name=value
     534 * @param   hEnv            Handle of an existing RTENV block to use.
     535 * @param   ppwszBlock      Pointer to the final output.
     536 */
     537static int rtProcEnvironmentCreateInternal(VOID *pvBlock, RTENV hEnv, PRTUTF16 *ppwszBlock)
     538{
     539    int rc = VINF_SUCCESS;
     540    RTENV hEnvTemp;
     541    rc = RTEnvClone(&hEnvTemp, hEnv);
     542    if (RT_SUCCESS(rc))
     543    {
     544        PRTUTF16 pBlock = (PRTUTF16)pvBlock;
     545        while (   pBlock
     546               && pBlock != '\0'
     547               && RT_SUCCESS(rc))
     548        {
     549            char *pszEntry;
     550            rc = RTUtf16ToUtf8(pBlock, &pszEntry);
     551            if (RT_SUCCESS(rc))
     552            {
     553                /* Don't overwrite values which we already have set to a custom value
     554                 * specified in hEnv ... */
     555                if (!RTEnvExistEx(hEnv, pszEntry))
     556                    rc = RTEnvPutEx(hEnvTemp, pszEntry);
     557                RTStrFree(pszEntry);
     558            }
     559
     560            size_t l;
     561            /* 32k should be the maximum the environment block can have on Windows. */
     562            if (FAILED(StringCbLengthW((LPCWSTR)pBlock, _32K * sizeof(RTUTF16), &l)))
     563                break;
     564            pBlock += l / sizeof(RTUTF16);
     565            if (pBlock[1] == '\0') /* Did we reach the double zero termination (\0\0)? */
     566                break;
     567            pBlock++; /* Skip zero termination of current string and advance to next string ... */
     568        }
     569
     570        if (RT_SUCCESS(rc))
     571            rc = RTEnvQueryUtf16Block(hEnvTemp, ppwszBlock);
     572        RTEnvDestroy(hEnvTemp);
     573    }
     574    return rc;
     575}
     576
     577
     578/**
     579 * Builds up the environment block for a specified user (identified by a token),
     580 * whereas hEnv is an additional set of environment variables which overwrite existing
     581 * values of the user profile.  ppwszBlock needs to be destroyed after usage
     582 * calling rtProcEnvironmentDestroy().
     583 *
     584 * @return  IPRT status code.
     585 *
     586 * @param   hToken          Token of the user to use.
     587 * @param   hEnv            Own environment block to extend/overwrite the profile's data with.
     588 * @param   ppwszBlock      Pointer to a pointer of the final UTF16 environment block.
     589 */
     590static int rtProcEnvironmentCreateFromToken(HANDLE hToken, RTENV hEnv, PRTUTF16 *ppwszBlock)
     591{
     592    int rc = VINF_SUCCESS;
     593    LPVOID pEnvBlockProfile = NULL;
     594    if (CreateEnvironmentBlock(&pEnvBlockProfile, hToken, FALSE /* Don't inherit from parent. */))
     595    {
     596        rc = rtProcEnvironmentCreateInternal(pEnvBlockProfile, hEnv, ppwszBlock);
     597        DestroyEnvironmentBlock(pEnvBlockProfile);
     598    }
     599    else
     600        rc = RTErrConvertFromWin32(GetLastError());
     601    return rc;
     602}
     603
     604
     605/**
     606 * Builds up the environment block for a specified user (identified by user name, password
     607 * and domain), whereas hEnv is an additional set of environment variables which overwrite
     608 * existing values of the user profile.  ppwszBlock needs to be destroyed after usage
     609 * calling rtProcEnvironmentDestroy().
     610 *
     611 * @return  IPRT status code.
     612 *
     613 * @param   pwszUser        User name.
     614 * @param   pwszPassword    Password.
     615 * @param   pwszDomain      Domain.
     616 * @param   hEnv            Own environment block to extend/overwrite the profile's data with.
     617 * @param   ppwszBlock      Pointer to a pointer of the final UTF16 environment block.
     618 */
     619static int rtProcEnvironmentCreateFromAccount(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain,
     620                                              RTENV hEnv, PRTUTF16 *ppwszBlock)
     621{
     622    HANDLE hToken;
     623    int rc = rtProcUserLogon(pwszUser, pwszPassword, pwszDomain, &hToken);
     624    if (RT_SUCCESS(rc))
     625    {
     626        rc = rtProcEnvironmentCreateFromToken(hToken, hEnv, ppwszBlock);
     627        rtProcUserLogoff(hToken);
     628    }
     629    return rc;
     630}
     631
     632
     633/**
     634 * Destroys an environment block formerly created by rtProcEnvironmentCreateInternal(),
     635 * rtProcEnvironmentCreateFromToken() or rtProcEnvironmentCreateFromAccount().
     636 *
     637 * @param   ppwszBlock      Environment block to destroy.
     638 */
     639static void rtProcEnvironmentDestroy(PRTUTF16 ppwszBlock)
     640{
     641    RTEnvFreeUtf16Block(ppwszBlock);
     642}
     643
     644
    482645static int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine,
    483                                  PRTUTF16 pwszzBlock, DWORD dwCreationFlags,
     646                                 RTENV hEnv, DWORD dwCreationFlags,
    484647                                 STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo, uint32_t fFlags)
    485648{
     
    507670            if (RT_SUCCESS(rc))
    508671            {
    509                 fRc = pfnCreateProcessWithLogonW(pwszUser,
    510                                                  NULL,                       /* lpDomain*/
    511                                                  pwszPassword,
    512                                                  1 /*LOGON_WITH_PROFILE*/,   /* dwLogonFlags */
    513                                                  pwszExec,
    514                                                  pwszCmdLine,
    515                                                  dwCreationFlags,
    516                                                  pwszzBlock,
    517                                                  NULL,                       /* pCurrentDirectory */
    518                                                  pStartupInfo,
    519                                                  pProcInfo);
    520                 if (!fRc)
    521                     dwErr = GetLastError();
     672                PRTUTF16 pwszzBlock;
     673                rc = rtProcEnvironmentCreateFromAccount(pwszUser, pwszPassword, NULL /* Domain */,
     674                                                        hEnv, &pwszzBlock);
     675                if (RT_SUCCESS(rc))
     676                {
     677                    fRc = pfnCreateProcessWithLogonW(pwszUser,
     678                                                     NULL,                       /* lpDomain*/
     679                                                     pwszPassword,
     680                                                     1 /*LOGON_WITH_PROFILE*/,   /* dwLogonFlags */
     681                                                     pwszExec,
     682                                                     pwszCmdLine,
     683                                                     dwCreationFlags,
     684                                                     pwszzBlock,
     685                                                     NULL,                       /* pCurrentDirectory */
     686                                                     pStartupInfo,
     687                                                     pProcInfo);
     688                    if (!fRc)
     689                        dwErr = GetLastError();
     690                    rtProcEnvironmentDestroy(pwszzBlock);
     691                }
    522692            }
    523693            RTLdrClose(hAdvAPI32);
     
    560730        PHANDLE phToken = NULL;
    561731        HANDLE hTokenLogon = INVALID_HANDLE_VALUE;
    562         fRc = LogonUserW(pwszUser,
    563                          /*
    564                           * Because we have to deal with http://support.microsoft.com/kb/245683
    565                           * for NULL domain names when running on NT4 here, pass an empty string if so.
    566                           * However, passing FQDNs should work!
    567                           */
    568                          ((DWORD)(LOBYTE(LOWORD(GetVersion()))) < 5)  /* < Windows 2000. */
    569                          ? L""   /* NT4 and older. */
    570                          : NULL, /* Windows 2000 and up. */
    571                          pwszPassword,
    572                          LOGON32_LOGON_INTERACTIVE,
    573                          LOGON32_PROVIDER_DEFAULT,
    574                          &hTokenLogon);
    575 
    576         bool fFound = false;
    577         HANDLE hTokenUserDesktop = INVALID_HANDLE_VALUE;
    578         if (fRc)
    579         {
     732        rc = rtProcUserLogon(pwszUser, pwszPassword, NULL /* Domain */, &hTokenLogon);
     733        if (RT_SUCCESS(rc))
     734        {
     735            bool fFound = false;
     736            HANDLE hTokenUserDesktop = INVALID_HANDLE_VALUE;
     737
    580738            if (fFlags & RTPROC_FLAGS_SERVICE)
    581739            {
     
    649807            phToken = fFound ? &hTokenUserDesktop : &hTokenLogon;
    650808
    651             /*
    652              * Useful KB articles:
    653              *      http://support.microsoft.com/kb/165194/
    654              *      http://support.microsoft.com/kb/184802/
    655              *      http://support.microsoft.com/kb/327618/
    656              */
    657             fRc = CreateProcessAsUserW(*phToken,
    658                                        pwszExec,
    659                                        pwszCmdLine,
    660                                        NULL,         /* pProcessAttributes */
    661                                        NULL,         /* pThreadAttributes */
    662                                        TRUE,         /* fInheritHandles */
    663                                        dwCreationFlags,
    664                                        pwszzBlock,
    665                                        NULL,         /* pCurrentDirectory */
    666                                        pStartupInfo,
    667                                        pProcInfo);
    668             if (fRc)
    669                 dwErr = NO_ERROR;
     809            PROFILEINFOW profileInfo;
     810            ZeroMemory(&profileInfo, sizeof(profileInfo));
     811            profileInfo.dwSize = sizeof(profileInfo);
     812            profileInfo.lpUserName = pwszUser;
     813            profileInfo.dwFlags = PI_NOUI; /* Prevents the display of profile error messages. */
     814            if (LoadUserProfileW(*phToken, &profileInfo))
     815            {
     816                PRTUTF16 pwszzBlock;
     817                rc = rtProcEnvironmentCreateFromToken(*phToken, hEnv, &pwszzBlock);
     818                if (RT_SUCCESS(rc))
     819                {
     820                    /*
     821                     * Useful KB articles:
     822                     *      http://support.microsoft.com/kb/165194/
     823                     *      http://support.microsoft.com/kb/184802/
     824                     *      http://support.microsoft.com/kb/327618/
     825                     */
     826                    fRc = CreateProcessAsUserW(*phToken,
     827                                               pwszExec,
     828                                               pwszCmdLine,
     829                                               NULL,         /* pProcessAttributes */
     830                                               NULL,         /* pThreadAttributes */
     831                                               TRUE,         /* fInheritHandles */
     832                                               dwCreationFlags,
     833                                               pwszzBlock,
     834                                               NULL,         /* pCurrentDirectory */
     835                                               pStartupInfo,
     836                                               pProcInfo);
     837                    if (fRc)
     838                        dwErr = NO_ERROR;
     839                    else
     840                        dwErr = GetLastError(); /* CreateProcessAsUserW() failed. */
     841                    rtProcEnvironmentDestroy(pwszzBlock);
     842                }
     843                else
     844                    dwErr = rc;
     845                UnloadUserProfile(*phToken, profileInfo.hProfile);
     846            }
    670847            else
    671                 dwErr = GetLastError(); /* CreateProcessAsUserW() failed. */
    672 
     848                dwErr = GetLastError(); /* LoadUserProfileW() failed. */
    673849            if (hTokenUserDesktop != INVALID_HANDLE_VALUE)
    674850                CloseHandle(hTokenUserDesktop);
    675             CloseHandle(hTokenLogon);
     851            rtProcUserLogoff(hTokenLogon);
    676852        }
    677853        else
    678             dwErr = GetLastError(); /* LogonUserW() failed. */
     854            dwErr = rc; /* rtProcUserLogon() failed. */
    679855    }
    680856
     
    8741050                        {
    8751051                            rc = rtProcCreateAsUserHlp(pwszUser, pwszPassword,
    876                                                        pwszExec, pwszCmdLine, pwszzBlock, dwCreationFlags,
     1052                                                       pwszExec, pwszCmdLine, hEnv, dwCreationFlags,
    8771053                                                       &StartupInfo, &ProcInfo, fFlags);
    8781054
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