VirtualBox

Changeset 27513 in vbox for trunk/src/VBox/Runtime/r3/win


Ignore:
Timestamp:
Mar 19, 2010 2:19:41 AM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
59016
Message:

process-win.cpp: code review / cleanup.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/process-win.cpp

    r27512 r27513  
    8484} PROCESSINFOCLASS;
    8585
    86 typedef WINADVAPI BOOL WINAPI CREATEPROCESSWITHLOGON(LPCWSTR,
    87                                                      LPCWSTR,
    88                                                      LPCWSTR,
    89                                                      DWORD,
    90                                                      LPCWSTR,
    91                                                      LPWSTR,
    92                                                      DWORD,
    93                                                      LPVOID,
    94                                                      LPCWSTR,
    95                                                      LPSTARTUPINFOW,
    96                                                      LPPROCESS_INFORMATION);
    97 typedef CREATEPROCESSWITHLOGON *PCREATEPROCESSWITHLOGON;
    98 
    9986extern "C" LONG WINAPI
    10087NtQueryInformationProcess(
     
    10592    OUT PULONG ReturnLength OPTIONAL);
    10693
     94typedef WINADVAPI BOOL WINAPI FNCREATEPROCESSWITHLOGON(LPCWSTR,
     95                                                       LPCWSTR,
     96                                                       LPCWSTR,
     97                                                       DWORD,
     98                                                       LPCWSTR,
     99                                                       LPWSTR,
     100                                                       DWORD,
     101                                                       LPVOID,
     102                                                       LPCWSTR,
     103                                                       LPSTARTUPINFOW,
     104                                                       LPPROCESS_INFORMATION);
     105typedef FNCREATEPROCESSWITHLOGON *PFNCREATEPROCESSWITHLOGON;
     106
     107
     108#if 0  /** @todo Andy, could you enable and test this, please?  It should work, but I don't have a full windows install to test it on. */
     109RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess)
     110{
     111    return RTProcCreateEx(pszExec, papszArgs, Env, fFlags,
     112                          NULL, NULL, NULL,  /* standard handles */
     113                          NULL /*pszAsUser*/, NULL /* pszPassword*/,
     114                          pProcess);
     115}
     116#else
    107117/** @todo r=michael This function currently does not work correctly if the arguments
    108118                    contain spaces. */
     
    181191    return rc;
    182192}
    183 
     193#endif
     194
     195
     196static int rtProcCreateAsUserHlp(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszExec, PRTUTF16 pwszCmdLine,
     197                                 PRTUTF16 pwszzBlock, STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo)
     198{
     199    /*
     200     * The following rights are needed in order to use LogonUserW and
     201     * CreateProcessAsUserW, so the local policy has to be modified to:
     202     *  - SE_TCB_NAME = Act as part of the operating system
     203     *  - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object
     204     *  - SE_INCREASE_QUOTA_NAME
     205     *
     206     * We may fail here with ERROR_PRIVILEGE_NOT_HELD.
     207     */
     208    int    rc;
     209    DWORD  dwErr  = NO_ERROR;
     210    HANDLE hToken = INVALID_HANDLE_VALUE;
     211    BOOL   fRc    = LogonUserW(pwszUser,
     212                               NULL,      /* lpDomain */
     213                               pwszPassword,
     214                               LOGON32_LOGON_INTERACTIVE,
     215                               LOGON32_PROVIDER_DEFAULT,
     216                               &hToken);
     217    if (fRc)
     218    {
     219        fRc = CreateProcessAsUserW(hToken,
     220                                   pwszExec,
     221                                   pwszCmdLine,
     222                                   NULL,         /* pProcessAttributes */
     223                                   NULL,         /* pThreadAttributes */
     224                                   TRUE,         /* fInheritHandles */
     225                                   CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
     226                                   pwszzBlock,
     227                                   NULL,         /* pCurrentDirectory */
     228                                   pStartupInfo,
     229                                   pProcInfo);
     230        if (!fRc)
     231            dwErr = GetLastError();
     232        CloseHandle(hToken);
     233    }
     234    else
     235        dwErr = GetLastError();
     236
     237#ifndef IPRT_TARGET_NT4 /* We could dispense with the tediuos dynamic loading here if we wanted. */
     238    /*
     239     * If we don't hold enough priviledges to spawn a new process with
     240     * different credentials we have to use CreateProcessWithLogonW here.  This
     241     * API is W2K+ and uses a system service for spawning the process.
     242     */
     243    /** @todo Use fFlags to either use this feature or just fail. */
     244    if (dwErr == ERROR_PRIVILEGE_NOT_HELD)
     245    {
     246        RTLDRMOD hAdvAPI32;
     247        rc = RTLdrLoad("Advapi32.dll", &hAdvAPI32);
     248        if (RT_SUCCESS(rc))
     249        {
     250            /* This may fail on too old (NT4) platforms. */
     251            PFNCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW;
     252            rc = RTLdrGetSymbol(hAdvAPI32, "CreateProcessWithLogonW", (void**)&pfnCreateProcessWithLogonW);
     253            if (RT_SUCCESS(rc))
     254            {
     255                fRc = pfnCreateProcessWithLogonW(pwszUser,
     256                                                 NULL,                       /* lpDomain*/
     257                                                 pwszPassword,
     258                                                 1 /*LOGON_WITH_PROFILE*/,   /* dwLogonFlags */
     259                                                 pwszExec,
     260                                                 pwszCmdLine,
     261                                                 CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
     262                                                 pwszzBlock,
     263                                                 NULL,                       /* pCurrentDirectory */
     264                                                 pStartupInfo,
     265                                                 pProcInfo);
     266                if (fRc)
     267                    dwErr = NO_ERROR;
     268                else
     269                    dwErr = GetLastError();
     270            }
     271            RTLdrClose(hAdvAPI32);
     272        }
     273    }
     274#endif
     275
     276    if (dwErr != NO_ERROR)
     277        rc = RTErrConvertFromWin32(dwErr);
     278    else
     279        rc = VINF_SUCCESS;
     280    return rc;
     281}
    184282
    185283RTR3DECL(int)   RTProcCreateEx(const char *pszExec, const char * const *papszArgs, RTENV hEnv, uint32_t fFlags,
     
    299397                PROCESS_INFORMATION ProcInfo;
    300398                RT_ZERO(ProcInfo);
    301                 BOOL fRc;
    302399                if (pszAsUser == NULL)
    303                     fRc = CreateProcessW(pwszExec,
    304                                          pwszCmdLine,
    305                                          NULL,         /* pProcessAttributes */
    306                                          NULL,         /* pThreadAttributes */
    307                                          TRUE,         /* fInheritHandles */
    308                                          CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
    309                                          pwszzBlock,
    310                                          NULL,          /* pCurrentDirectory */
    311                                          &StartupInfo,
    312                                          &ProcInfo);
     400                {
     401                    if (CreateProcessW(pwszExec,
     402                                       pwszCmdLine,
     403                                       NULL,         /* pProcessAttributes */
     404                                       NULL,         /* pThreadAttributes */
     405                                       TRUE,         /* fInheritHandles */
     406                                       CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
     407                                       pwszzBlock,
     408                                       NULL,          /* pCurrentDirectory */
     409                                       &StartupInfo,
     410                                       &ProcInfo))
     411                        rc = VINF_SUCCESS;
     412                    else
     413                        rc = RTErrConvertFromWin32(GetLastError());
     414                }
    313415                else
    314416                {
    315                     HANDLE hToken = INVALID_HANDLE_VALUE;
     417                    /*
     418                     * Convert the additional parameters and use a helper
     419                     * function to do the actual work.
     420                     */
    316421                    PRTUTF16 pwszUser;
    317 
    318422                    rc = RTStrToUtf16(pszAsUser, &pwszUser);
    319423                    if (RT_SUCCESS(rc))
    320424                    {
    321425                        PRTUTF16 pwszPassword;
    322                         rc = RTStrToUtf16(pszPassword, &pwszPassword);
     426                        rc = RTStrToUtf16(pszPassword ? pszPassword : "", &pwszPassword);
    323427                        if (RT_SUCCESS(rc))
    324428                        {
    325                             /*
    326                              * User needs to be specified in UPN format because we
    327                              * don't fill a domain name.
    328                              */
    329 
    330                             /*
    331                              * The following rights are needed in order to use
    332                              * LogonUserW and CreateProcessAsUserW,
    333                              * so the local policy has to be modified to:
    334                              * - SE_TCB_NAME = Act as part of the operating system
    335                              * - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object
    336                              * - SE_INCREASE_QUOTA_NAME
    337                              */
    338                             fRc = LogonUserW(pwszUser,
    339                                              NULL,      /* lpDomain */
    340                                              pszPassword ? pwszPassword : L"",
    341                                              LOGON32_LOGON_INTERACTIVE,
    342                                              LOGON32_PROVIDER_DEFAULT,
    343                                              &hToken);
    344                             /** @todo Add SecureZeroMemory() here for wiping the password? */
    345                             if (fRc)
    346                             {
    347                                 fRc = CreateProcessAsUserW(hToken,
    348                                                            pwszExec,
    349                                                            pwszCmdLine,
    350                                                            NULL,         /* pProcessAttributes */
    351                                                            NULL,         /* pThreadAttributes */
    352                                                            TRUE,         /* fInheritHandles */
    353                                                            CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
    354                                                            pwszzBlock,
    355                                                            NULL,         /* pCurrentDirectory */
    356                                                            &StartupInfo,
    357                                                            &ProcInfo);
    358                                 CloseHandle(hToken);
    359                             }
    360 
    361                             /* If call above failed (ERROR_PRIVILEGE_NOT_HELD or else, might happen on W2K),
    362                              * try a newer method. */
    363                             if (!fRc)
    364                             {
    365                                 DWORD dwErr = GetLastError();
    366 
    367                                 /*
    368                                  * If we don't hold enough priviledges to spawn a new
    369                                  * process with different credentials we have to use
    370                                  * CreateProcessWithLogonW here.
    371                                  *
    372                                  * Note that NT4 does *not* support this API, thus we have
    373                                  * to load it dynamically (W2K+) to not blow up things.
    374                                  *
    375                                  * @todo Use fFlags to either use this feature or just fail.
    376                                  */
    377                                 if (ERROR_PRIVILEGE_NOT_HELD == dwErr)
    378                                 {
    379                                     RTLDRMOD modAdvAPI32;
    380                                     rc = RTLdrLoad("Advapi32.dll", &modAdvAPI32);
    381                                     PCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW;
    382                                     if (RT_SUCCESS(rc))
    383                                     {
    384                                         /* This may fail on too old (NT4) platforms. */
    385                                         rc = RTLdrGetSymbol(modAdvAPI32, "CreateProcessWithLogonW", (void**)&pfnCreateProcessWithLogonW);
    386                                         if (RT_SUCCESS(rc))
    387                                         {
    388                                             fRc = pfnCreateProcessWithLogonW(pwszUser,
    389                                                                              NULL,                       /* lpDomain*/
    390                                                                              pwszPassword,
    391                                                                              1 /*LOGON_WITH_PROFILE*/,   /* dwLogonFlags */
    392                                                                              pwszExec,
    393                                                                              pwszCmdLine,
    394                                                                              CREATE_UNICODE_ENVIRONMENT, /* dwCreationFlags */
    395                                                                              pwszzBlock,
    396                                                                              NULL,                       /* pCurrentDirectory */
    397                                                                              &StartupInfo,
    398                                                                              &ProcInfo);
    399                                         }
    400                                         RTLdrClose(modAdvAPI32);
    401                                     }
    402                                 }
    403                             }
     429                            rc = rtProcCreateAsUserHlp(pwszUser, pwszPassword,
     430                                                       pwszExec, pwszCmdLine, pwszzBlock,
     431                                                       &StartupInfo, &ProcInfo);
     432
    404433                            RTUtf16Free(pwszPassword);
    405434                        }
     
    407436                    }
    408437                }
    409 
    410                 if (fRc)
     438                if (RT_SUCCESS(rc))
    411439                {
    412440                    CloseHandle(ProcInfo.hThread);
     
    420448                    rc = VINF_SUCCESS;
    421449                }
    422                 else
    423                     rc = RTErrConvertFromWin32(GetLastError());
    424450                RTUtf16Free(pwszExec);
    425451            }
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