VirtualBox

Changeset 57906 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Sep 25, 2015 8:43:36 PM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
102878
Message:

RTProc/win,RTErr: Avoid doing LogonUserW when we don't need to get the profile environment as this may require the TCB privilege. On W2K CreateProcessWithLogonW doesn't plant standard handles in the child process, so try our best to do it ourselves. (This may be applicable to later windows versions too, but behavior must've been change in W10 or earlier.) Introduced specific error codes for the missing process rights to prevent wasting time.

Location:
trunk/src/VBox/Runtime
Files:
3 edited

Legend:

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

    r57845 r57906  
    3232#include <iprt/asm.h> /* hack */
    3333
     34#include <iprt/nt/nt-and-windows.h>
    3435#include <Userenv.h>
    35 #include <Windows.h>
    3636#include <tlhelp32.h>
    3737#include <process.h>
     
    136136*********************************************************************************************************************************/
    137137static int rtProcWinFindExe(uint32_t fFlags, RTENV hEnv, const char *pszExec, PRTUTF16 *ppwszExec);
     138static int rtProcWinCreateEnvBlockAndFindExe(uint32_t fFlags, RTENV hEnv, const char *pszExec,
     139                                             PRTUTF16 *ppwszzBlock, PRTUTF16 *ppwszExec);
    138140
    139141
     
    369371    switch (dwError)
    370372    {
    371         case ERROR_NOACCESS:
    372         case ERROR_PRIVILEGE_NOT_HELD:
     373        case ERROR_NOACCESS: /** @todo r=bird: this is a bogus transation.  Used a couple of places in main. */
    373374            rc = VERR_PERMISSION_DENIED;
    374             break;
    375 
    376         case ERROR_PASSWORD_EXPIRED:
    377         case ERROR_ACCOUNT_RESTRICTION: /* See: http://support.microsoft.com/kb/303846/ */
    378         case ERROR_PASSWORD_RESTRICTION:
    379         case ERROR_ACCOUNT_DISABLED:    /* See: http://support.microsoft.com/kb/263936 */
    380             rc = VERR_ACCOUNT_RESTRICTED;
    381             break;
    382 
    383         case ERROR_FILE_CORRUPT:
    384             rc = VERR_BAD_EXE_FORMAT;
    385             break;
    386 
    387         case ERROR_BAD_DEVICE: /* Can happen when opening funny things like "CON". */
    388             rc = VERR_INVALID_NAME;
    389375            break;
    390376
     
    660646     * for NULL domain names when running on NT4 here, pass an empty string if so.
    661647     * However, passing FQDNs should work!
    662      */
     648     *
     649     * The SE_TCB_NAME (Policy: Act as part of the operating system) right
     650     * is required on older windows versions (NT4, W2K, possibly XP).
     651     */
     652    PCRTUTF16 pwszDomainToUse = g_enmWinVer < kRTWinOSType_2K ? L"" /* NT4 and older */ : NULL /* Windows 2000 and up */;
    663653    BOOL fRc = LogonUserW(pwszUser,
    664                           g_enmWinVer < kRTWinOSType_2K ? L"" /* NT4 and older */ : NULL /* Windows 2000 and up */,
     654                          pwszDomainToUse,
    665655                          pwszPassword,
    666656                          LOGON32_LOGON_INTERACTIVE,
     
    671661
    672662    DWORD dwErr = GetLastError();
    673     int rc = rtProcWinMapErrorCodes(dwErr);
     663    int rc = dwErr == ERROR_PRIVILEGE_NOT_HELD ? VERR_PROC_TCB_PRIV_NOT_HELD : rtProcWinMapErrorCodes(dwErr);
    674664    if (rc == VERR_UNRESOLVED_ERROR)
    675665        LogRelFunc(("dwErr=%u (%#x), rc=%Rrc\n", dwErr, dwErr, rc));
     
    751741
    752742    return rc;
     743}
     744
     745
     746/**
     747 * Figures which privilege we're missing for success application of
     748 * CreateProcessAsUserW.
     749 *
     750 * @returns IPRT error status.
     751 */
     752static int rtProcWinFigureWhichPrivilegeNotHeld2(void)
     753{
     754    HANDLE hToken;
     755    if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
     756    {
     757        static struct
     758        {
     759            const char *pszName;
     760            int         rc;
     761        } const s_aPrivileges[] =
     762        {
     763            { SE_TCB_NAME,                      VERR_PROC_TCB_PRIV_NOT_HELD },
     764            { SE_ASSIGNPRIMARYTOKEN_NAME,       VERR_PROC_APT_PRIV_NOT_HELD },
     765            { SE_INCREASE_QUOTA_NAME,           VERR_PROC_IQ_PRIV_NOT_HELD  },
     766        };
     767        for (uint32_t i = 0; i < RT_ELEMENTS(s_aPrivileges); i++)
     768        {
     769            union
     770            {
     771                TOKEN_PRIVILEGES TokPriv;
     772                char abAlloced[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)];
     773            } uNew, uOld;
     774            uNew.TokPriv.PrivilegeCount = 1;
     775            uNew.TokPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
     776            AssertStmt(LookupPrivilegeValue(NULL, s_aPrivileges[i].pszName, &uNew.TokPriv.Privileges[0].Luid), continue);
     777            uOld = uNew;
     778            SetLastError(NO_ERROR);
     779            DWORD cbActual = RT_OFFSETOF(TOKEN_PRIVILEGES, Privileges[1]);
     780            AdjustTokenPrivileges(hToken, FALSE /*fDisableAllPrivileges*/, &uNew.TokPriv, cbActual, &uOld.TokPriv, &cbActual);
     781            if (GetLastError() != NO_ERROR)
     782            {
     783                CloseHandle(hToken);
     784                return s_aPrivileges[i].rc;
     785            }
     786            if (uOld.TokPriv.Privileges[0].Attributes == 0)
     787                AdjustTokenPrivileges(hToken, FALSE /*fDisableAllPrivileges*/, &uOld.TokPriv, 0, NULL, NULL);
     788        }
     789        AssertFailed();
     790        CloseHandle(hToken);
     791    }
     792    else
     793        AssertFailed();
     794    return VERR_PRIVILEGE_NOT_HELD;
    753795}
    754796
     
    782824     * The following rights are needed in order to use LogonUserW and
    783825     * CreateProcessAsUserW, so the local policy has to be modified to:
    784      *  - SE_TCB_NAME = Act as part of the operating system
    785      *  - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a token object
    786      *  - SE_INCREASE_QUOTA_NAME
     826     *  - SE_TCB_NAME                = Act as part of the operating system
     827     *  - SE_ASSIGNPRIMARYTOKEN_NAME = Create/replace a (process) token object
     828     *  - SE_INCREASE_QUOTA_NAME     = Increase quotas
    787829     *
    788830     * We may fail here with ERROR_PRIVILEGE_NOT_HELD.
    789831     */
    790 /** @todo r=bird: Both methods starts with rtProcWinUserLogon, so we could probably do that once in the parent function, right... */
    791832    DWORD   dwErr       = NO_ERROR;
    792833    HANDLE  hTokenLogon = INVALID_HANDLE_VALUE;
     
    831872                    }
    832873                    else
    833                         dwErr = GetLastError() != NO_ERROR ? GetLastError() : ERROR_INTERNAL_ERROR;
     874                    {
     875                        dwErr = GetLastError();
     876                        rc = dwErr != NO_ERROR ? RTErrConvertFromWin32(dwErr) : VERR_INTERNAL_ERROR_3;
     877                    }
    834878                    RTMemFree(pwszDomain);
    835879                }
     
    844888        /* If we got an error due to account lookup/loading above, don't
    845889         * continue here. */
    846         if (dwErr == NO_ERROR)
     890        if (RT_SUCCESS(rc))
    847891        {
    848892            /*
     
    868912
    869913                    if (!g_pfnLoadUserProfileW(hTokenToUse, &ProfileInfo))
    870                         dwErr = GetLastError();
     914                        rc = RTErrConvertFromWin32(GetLastError());
    871915                }
    872                 if (dwErr == NO_ERROR)
     916                if (RT_SUCCESS(rc))
    873917                {
    874918                    /*
     
    906950                                                           pProcInfo);
    907951                                if (fRc)
    908                                     dwErr = NO_ERROR;
     952                                    rc = VINF_SUCCESS;
    909953                                else
    910                                     dwErr = GetLastError(); /* CreateProcessAsUserW() failed. */
     954                                {
     955                                    dwErr = GetLastError();
     956                                    if (dwErr == ERROR_PRIVILEGE_NOT_HELD)
     957                                        rc = rtProcWinFigureWhichPrivilegeNotHeld2();
     958                                    else
     959                                        rc = RTErrConvertFromWin32(dwErr);
     960                                }
    911961                            }
    912962                            RTEnvFreeUtf16Block(pwszzBlock);
     
    939989        CloseHandle(hTokenLogon);
    940990
    941         /*
    942          * Do error conversion.
    943          */
    944         if (   RT_SUCCESS(rc)
    945             && dwErr != NO_ERROR)
    946         {
    947             rc = rtProcWinMapErrorCodes(dwErr);
    948             if (rc == VERR_UNRESOLVED_ERROR)
    949                 LogRelFunc(("dwErr=%u (%#x), rc=%Rrc\n", dwErr, dwErr, rc));
    950         }
     991        if (rc == VERR_UNRESOLVED_ERROR)
     992            LogRelFunc(("dwErr=%u (%#x), rc=%Rrc\n", dwErr, dwErr, rc));
    951993    }
    952994    return rc;
     
    955997
    956998/**
     999 * Plants a standard handle into a child process on older windows versions.
     1000 *
     1001 * This is only needed when using CreateProcessWithLogonW on older windows
     1002 * versions.  It would appear that newer versions of windows does this for us.
     1003 *
     1004 * @param   hSrcHandle              The source handle.
     1005 * @param   hDstProcess             The child process handle.
     1006 * @param   offProcParamMember      The offset to RTL_USER_PROCESS_PARAMETERS.
     1007 * @param   ppvDstProcParamCache    Where where cached the address of
     1008 *                                  RTL_USER_PROCESS_PARAMETERS in the child.
     1009 */
     1010static void rtProcWinDupStdHandleIntoChild(HANDLE hSrcHandle, HANDLE hDstProcess, uint32_t offProcParamMember,
     1011                                           PVOID *ppvDstProcParamCache)
     1012{
     1013    if (hSrcHandle != NULL && hSrcHandle != INVALID_HANDLE_VALUE)
     1014    {
     1015        HANDLE hDstHandle;
     1016        if (DuplicateHandle(GetCurrentProcess(), hSrcHandle, hDstProcess, &hDstHandle,
     1017                            0 /*IgnoredDesiredAccess*/, FALSE /*fInherit*/, DUPLICATE_SAME_ACCESS))
     1018        {
     1019            if (hSrcHandle == hDstHandle)
     1020                return;
     1021
     1022            if (!*ppvDstProcParamCache)
     1023            {
     1024                PROCESS_BASIC_INFORMATION BasicInfo;
     1025                ULONG cbIgn;
     1026                NTSTATUS rcNt = NtQueryInformationProcess(hDstProcess, ProcessBasicInformation,
     1027                                                          &BasicInfo, sizeof(BasicInfo), &cbIgn);
     1028                if (NT_SUCCESS(rcNt))
     1029                {
     1030                    SIZE_T cbCopied = 0;
     1031                    if (!ReadProcessMemory(hDstProcess,
     1032                                           (char *)BasicInfo.PebBaseAddress + RT_OFFSETOF(PEB_COMMON, ProcessParameters),
     1033                                           ppvDstProcParamCache, sizeof(*ppvDstProcParamCache), &cbCopied))
     1034                    {
     1035                        AssertMsgFailed(("PebBaseAddress=%p %d\n", BasicInfo.PebBaseAddress, GetLastError()));
     1036                        *ppvDstProcParamCache = NULL;
     1037                    }
     1038                }
     1039                else
     1040                    AssertMsgFailed(("rcNt=%#x\n", rcNt));
     1041            }
     1042            if (*ppvDstProcParamCache)
     1043            {
     1044                if (WriteProcessMemory(hDstProcess, (char *)*ppvDstProcParamCache + offProcParamMember,
     1045                                       &hDstHandle, sizeof(hDstHandle), NULL))
     1046                    return;
     1047            }
     1048
     1049            /*
     1050             * Close the handle.
     1051             */
     1052            HANDLE hSrcHandle2;
     1053            if (DuplicateHandle(hDstProcess, hDstHandle, GetCurrentProcess(), &hSrcHandle2,
     1054                                0 /*IgnoredDesiredAccess*/, FALSE /*fInherit*/, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
     1055                CloseHandle(hSrcHandle2);
     1056            else
     1057                AssertMsgFailed(("hDstHandle=%p %u\n", hDstHandle, GetLastError()));
     1058        }
     1059        else
     1060            AssertMsg(GetLastError() == ERROR_INVALID_PARAMETER, ("%u\n", GetLastError()));
     1061    }
     1062}
     1063
     1064
     1065/**
    9571066 * Method \#1.
    9581067 *
    959  * This may fail on too old (NT4) platforms or if the calling process
    960  * is running on a SYSTEM account (like a service, ERROR_ACCESS_DENIED) on newer
    961  * platforms (however, this works on W2K!).
     1068 * This method requires Windows 2000 or later.  It may fail if the process is
     1069 * running under the SYSTEM account (like a service, ERROR_ACCESS_DENIED) on
     1070 * newer platforms (however, this works on W2K!).
    9621071 */
    9631072static int rtProcWinCreateAsUser1(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 *ppwszExec, PRTUTF16 pwszCmdLine,
     
    9661075                                  uint32_t fFlags, const char *pszExec)
    9671076{
     1077    /* The CreateProcessWithLogonW API was introduced with W2K and later.  It uses a service
     1078       for launching the process. */
    9681079    if (!g_pfnCreateProcessWithLogonW)
    9691080        return VERR_SYMBOL_NOT_FOUND;
    9701081
    971     RTENV  hEnvToUse = NIL_RTENV;
    972     HANDLE hToken;
    973     int rc = rtProcWinUserLogon(pwszUser, pwszPassword, NULL /* Domain */, &hToken);
     1082    /*
     1083     * Create the environment block and find the executable first.
     1084     *
     1085     * We try to skip this when RTPROC_FLAGS_PROFILE is set so we can sidestep
     1086     * potential missing TCB privilege issues when calling UserLogonW.  At least
     1087     * NT4 and W2K requires the trusted code base (TCB) privilege for logon use.
     1088     * Passing pwszzBlock=NULL and LOGON_WITH_PROFILE means the child process
     1089     * gets the environment specified by the user profile.
     1090     */
     1091    int      rc         = VINF_SUCCESS;
     1092    PRTUTF16 pwszzBlock = NULL;
     1093
     1094    /* Eliminating the path search flags simplifies things a little. */
     1095    if (   (fFlags & RTPROC_FLAGS_SEARCH_PATH)
     1096        && (RTPathHasPath(pszExec) || RTPathExists(pszExec)))
     1097        fFlags &= ~RTPROC_FLAGS_SEARCH_PATH;
     1098
     1099    /*
     1100     * No profile is simple, as is a user specified environment (no change record).
     1101     */
     1102    if (   !(fFlags & RTPROC_FLAGS_PROFILE)
     1103        || (   !(fFlags & RTPROC_FLAGS_ENV_CHANGE_RECORD)
     1104            && hEnv != RTENV_DEFAULT))
     1105        rc = rtProcWinCreateEnvBlockAndFindExe(fFlags, hEnv, pszExec, &pwszzBlock, ppwszExec);
     1106    /*
     1107     * Default profile environment without changes or path searching we leave
     1108     * to the service that implements the API.
     1109     */
     1110    else if (   hEnv == RTENV_DEFAULT
     1111             && !(fFlags & (RTPROC_FLAGS_ENV_CHANGE_RECORD | RTPROC_FLAGS_SEARCH_PATH)))
     1112        pwszzBlock = NULL;
     1113    /*
     1114     * Otherwise, we need to get the user profile environment.
     1115     */
     1116    else
     1117    {
     1118        RTENV  hEnvToUse = NIL_RTENV;
     1119        HANDLE hToken;
     1120        rc = rtProcWinUserLogon(pwszUser, pwszPassword, NULL /* Domain */, &hToken);
     1121        if (RT_SUCCESS(rc))
     1122        {
     1123    /** @todo r=bird: Why didn't we load the environment here?  The
     1124     *       CreateEnvironmentBlock docs indicate that USERPROFILE isn't set
     1125     *       unless we call LoadUserProfile first.  However, experiments here on W10
     1126     *       shows it isn't really needed though. Weird.
     1127     * Update: It works even on W2K. Possible only required for roaming profiles? */
     1128#if 0
     1129            if (fFlags & RTPROC_FLAGS_PROFILE)
     1130            {
     1131                PROFILEINFOW ProfileInfo;
     1132                RT_ZERO(ProfileInfo);
     1133                ProfileInfo.dwSize     = sizeof(ProfileInfo);
     1134                ProfileInfo.lpUserName = pwszUser;
     1135                ProfileInfo.dwFlags    = PI_NOUI; /* Prevents the display of profile error messages. */
     1136
     1137                if (g_pfnLoadUserProfileW(hToken, &ProfileInfo))
     1138                {
     1139                    rc = rtProcWinCreateEnvFromToken(hToken, hEnv, fFlags, &hEnvToUse);
     1140
     1141                    if (!g_pfnUnloadUserProfile(hToken, ProfileInfo.hProfile))
     1142                        AssertFailed();
     1143                }
     1144                else
     1145                    rc = RTErrConvertFromWin32(GetLastError());
     1146            }
     1147            else
     1148#endif
     1149                rc = rtProcWinCreateEnvFromToken(hToken, hEnv, fFlags, &hEnvToUse);
     1150            CloseHandle(hToken);
     1151
     1152            /*
     1153             * Query the environment block and find the executable file,
     1154             * Then destroy any temp env block.
     1155             */
     1156            if (RT_SUCCESS(rc))
     1157            {
     1158                rc = rtProcWinFindExe(fFlags, hEnv, pszExec, ppwszExec);
     1159                if (RT_SUCCESS(rc))
     1160                    rc = RTEnvQueryUtf16Block(hEnvToUse, &pwszzBlock);
     1161                if (hEnvToUse != hEnv)
     1162                    RTEnvDestroy(hEnvToUse);
     1163            }
     1164        }
     1165    }
    9741166    if (RT_SUCCESS(rc))
    9751167    {
    976 /** @todo r=bird: Why didn't we load the environment here?  The
    977  *       CreateEnvironmentBlock docs indicate that USERPROFILE isn't set
    978  *       unless we call LoadUserProfile first.  However, experiments here on W10
    979  *       shows it isn't really needed though. Weird. */
    980 #if 0
    981         if (fFlags & RTPROC_FLAGS_PROFILE)
    982         {
    983             PROFILEINFOW ProfileInfo;
    984             RT_ZERO(ProfileInfo);
    985             ProfileInfo.dwSize     = sizeof(ProfileInfo);
    986             ProfileInfo.lpUserName = pwszUser;
    987             ProfileInfo.dwFlags    = PI_NOUI; /* Prevents the display of profile error messages. */
    988 
    989             if (g_pfnLoadUserProfileW(hToken, &ProfileInfo))
    990             {
    991                 rc = rtProcWinCreateEnvFromToken(hToken, hEnv, fFlags, &hEnvToUse);
    992 
    993                 if (!g_pfnUnloadUserProfile(hToken, ProfileInfo.hProfile))
    994                     AssertFailed();
    995             }
     1168        Assert(!(dwCreationFlags & CREATE_SUSPENDED));
     1169        bool const fCreatedSuspended = g_enmWinVer < kRTWinOSType_XP;
     1170        BOOL fRc = g_pfnCreateProcessWithLogonW(pwszUser,
     1171                                                NULL,                       /* lpDomain*/
     1172                                                pwszPassword,
     1173                                                fFlags & RTPROC_FLAGS_PROFILE ? 1 /*LOGON_WITH_ PROFILE*/ : 0,
     1174                                                *ppwszExec,
     1175                                                pwszCmdLine,
     1176                                                dwCreationFlags | (fCreatedSuspended ? CREATE_SUSPENDED : 0),
     1177                                                pwszzBlock,
     1178                                                NULL,                       /* pCurrentDirectory */
     1179                                                pStartupInfo,
     1180                                                pProcInfo);
     1181        if (fRc)
     1182        {
     1183            if (!fCreatedSuspended)
     1184                rc = VINF_SUCCESS;
    9961185            else
    997                 rc = RTErrConvertFromWin32(GetLastError());
     1186            {
     1187                /* Duplicate standard handles into the child process, we ignore failures here as it's
     1188                   legal to have bad standard handle values and we cannot dup console I/O handles. */
     1189                PVOID pvDstProcParamCache = NULL;
     1190                rtProcWinDupStdHandleIntoChild(pStartupInfo->hStdInput, pProcInfo->hProcess,
     1191                                               RT_OFFSETOF(RTL_USER_PROCESS_PARAMETERS, StandardInput), &pvDstProcParamCache);
     1192                rtProcWinDupStdHandleIntoChild(pStartupInfo->hStdOutput, pProcInfo->hProcess,
     1193                                               RT_OFFSETOF(RTL_USER_PROCESS_PARAMETERS, StandardOutput), &pvDstProcParamCache);
     1194                rtProcWinDupStdHandleIntoChild(pStartupInfo->hStdError,  pProcInfo->hProcess,
     1195                                               RT_OFFSETOF(RTL_USER_PROCESS_PARAMETERS, StandardError), &pvDstProcParamCache);
     1196
     1197                if (ResumeThread(pProcInfo->hThread) == ~(DWORD)0)
     1198                    rc = RTErrConvertFromWin32(GetLastError());
     1199                if (RT_FAILURE(rc))
     1200                {
     1201                    TerminateProcess(pProcInfo->hProcess, 127);
     1202                    CloseHandle(pProcInfo->hThread);
     1203                    CloseHandle(pProcInfo->hProcess);
     1204                }
     1205            }
    9981206        }
    9991207        else
    1000 #endif
    1001             rc = rtProcWinCreateEnvFromToken(hToken, hEnv, fFlags, &hEnvToUse);
    1002         CloseHandle(hToken);
    1003     }
    1004     if (RT_SUCCESS(rc))
    1005     {
    1006         PRTUTF16 pwszzBlock;
    1007         rc = RTEnvQueryUtf16Block(hEnvToUse, &pwszzBlock);
    1008         if (RT_SUCCESS(rc))
    1009         {
    1010             rc = rtProcWinFindExe(fFlags, hEnv, pszExec, ppwszExec);
    1011             if (RT_SUCCESS(rc))
    1012             {
    1013                 BOOL fRc = g_pfnCreateProcessWithLogonW(pwszUser,
    1014                                                         NULL,                       /* lpDomain*/
    1015                                                         pwszPassword,
    1016                                                         fFlags & RTPROC_FLAGS_PROFILE ? 1 /*LOGON_WITH_PROFILE*/ : 0,
    1017                                                         *ppwszExec,
    1018                                                         pwszCmdLine,
    1019                                                         dwCreationFlags,
    1020                                                         pwszzBlock,
    1021                                                         NULL,                       /* pCurrentDirectory */
    1022                                                         pStartupInfo,
    1023                                                         pProcInfo);
    1024                 if (fRc)
    1025                     rc = VINF_SUCCESS;
    1026                 else
    1027                 {
    1028                     DWORD dwErr = GetLastError();
    1029                     rc = rtProcWinMapErrorCodes(dwErr);
    1030                     if (rc == VERR_UNRESOLVED_ERROR)
    1031                         LogRelFunc(("g_pfnCreateProcessWithLogonW (%p) failed: dwErr=%u (%#x), rc=%Rrc\n",
    1032                                     g_pfnCreateProcessWithLogonW, dwErr, dwErr, rc));
    1033                 }
    1034             }
     1208        {
     1209            DWORD dwErr = GetLastError();
     1210            rc = rtProcWinMapErrorCodes(dwErr);
     1211            if (rc == VERR_UNRESOLVED_ERROR)
     1212                LogRelFunc(("g_pfnCreateProcessWithLogonW (%p) failed: dwErr=%u (%#x), rc=%Rrc\n",
     1213                            g_pfnCreateProcessWithLogonW, dwErr, dwErr, rc));
     1214        }
     1215        if (pwszzBlock)
    10351216            RTEnvFreeUtf16Block(pwszzBlock);
    1036         }
    1037         if (hEnvToUse != hEnv)
    1038             RTEnvDestroy(hEnvToUse);
    10391217    }
    10401218    return rc;
     
    10491227    /*
    10501228     * If we run as a service CreateProcessWithLogon will fail, so don't even
    1051      * try it (because of Local System context).   This method may not work on
    1052      * older OSes, it will fail and we try the next alternative.
     1229     * try it (because of Local System context).  This method is very slow on W2K.
    10531230     */
    10541231    if (!(fFlags & RTPROC_FLAGS_SERVICE))
  • trunk/src/VBox/Runtime/testcase/tstRTProcCreateEx.cpp

    r57869 r57906  
    168168#if 1
    169169    /* For manual testing. */
    170     if (strcmp(argv[2],"noinherit-change-record") == 0)
     170    if (strcmp(argv[2],"noinherit") == 0)
     171    //if (strcmp(argv[2],"noinherit-change-record") == 0)
    171172    {
    172173        RTENV hEnv;
     
    230231    RTTESTI_CHECK_RC_RETV(RTEnvCreateChangeRecord(&hEnvChange), VINF_SUCCESS);
    231232    RTTESTI_CHECK_RC_RETV(RTEnvSetEx(hEnvChange, "testcase-child-6", "changed"), VINF_SUCCESS);
    232     RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, hEnvChange, RTPROC_FLAGS_ENV_CHANGE_RECORD,
     233    int rc;
     234    RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange, RTPROC_FLAGS_ENV_CHANGE_RECORD,
    233235                                         NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
    234     ProcStatus.enmReason = RTPROCEXITREASON_ABEND;
    235     ProcStatus.iStatus   = -1;
    236     RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
    237 
    238     if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
    239         RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
     236    if (RT_SUCCESS(rc))
     237    {
     238        ProcStatus.enmReason = RTPROCEXITREASON_ABEND;
     239        ProcStatus.iStatus   = -1;
     240        RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
     241
     242        if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
     243            RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
     244    }
    240245
    241246
    242247    /* Use profile environment this time. */
    243248    apszArgs[2] = "noinherit";
    244     RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, RTPROC_FLAGS_PROFILE,
     249    RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, RTPROC_FLAGS_PROFILE,
    245250                                         NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
    246     ProcStatus.enmReason = RTPROCEXITREASON_ABEND;
    247     ProcStatus.iStatus   = -1;
    248     RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
    249 
    250     if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
    251         RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
     251    if (RT_SUCCESS(rc))
     252    {
     253        ProcStatus.enmReason = RTPROCEXITREASON_ABEND;
     254        ProcStatus.iStatus   = -1;
     255        RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
     256
     257        if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
     258            RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
     259    }
    252260
    253261    /* Use profile environment this time. */
    254262    apszArgs[2] = "noinherit-change-record";
    255     RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, hEnvChange,
     263    RTTESTI_CHECK_RC(rc = RTProcCreateEx(g_szExecName, apszArgs, hEnvChange,
    256264                                         RTPROC_FLAGS_PROFILE | RTPROC_FLAGS_ENV_CHANGE_RECORD,
    257265                                         NULL, NULL, NULL, pszAsUser, pszPassword, &hProc), VINF_SUCCESS);
    258     ProcStatus.enmReason = RTPROCEXITREASON_ABEND;
    259     ProcStatus.iStatus   = -1;
    260     RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
    261 
    262     if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
    263         RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
     266    if (RT_SUCCESS(rc))
     267    {
     268        ProcStatus.enmReason = RTPROCEXITREASON_ABEND;
     269        ProcStatus.iStatus   = -1;
     270        RTTESTI_CHECK_RC(RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus), VINF_SUCCESS);
     271
     272        if (ProcStatus.enmReason != RTPROCEXITREASON_NORMAL || ProcStatus.iStatus != 0)
     273            RTTestIFailed("enmReason=%d iStatus=%d", ProcStatus.enmReason, ProcStatus.iStatus);
     274    }
    264275
    265276
     
    403414
    404415    /* Test for invalid logons. */
    405     RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    406                                          NULL, NULL, "non-existing-user", "wrong-password", &hProc), VERR_AUTHENTICATION_FAILURE);
     416    int rc = RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL, NULL, NULL,
     417                            "non-existing-user", "wrong-password", &hProc);
     418    if (rc != VERR_AUTHENTICATION_FAILURE && rc != VERR_PRIVILEGE_NOT_HELD && rc != VERR_PROC_TCB_PRIV_NOT_HELD)
     419        RTTestIFailed("rc=%Rrc");
     420
    407421    /* Test for invalid application. */
    408     RTTESTI_CHECK_RC_RETV(RTProcCreateEx("non-existing-app", apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
    409                                          NULL, NULL, NULL, NULL, &hProc), VERR_FILE_NOT_FOUND);
     422    RTTESTI_CHECK_RC(RTProcCreateEx("non-existing-app", apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
     423                                    NULL, NULL, NULL, NULL, &hProc), VERR_FILE_NOT_FOUND);
    410424    /* Test a (hopefully) valid user/password logon (given by parameters of this function). */
    411425    RTTESTI_CHECK_RC_RETV(RTProcCreateEx(g_szExecName, apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, NULL,
  • trunk/src/VBox/Runtime/win/RTErrConvertFromWin32.cpp

    r57358 r57906  
    148148
    149149        case ERROR_INVALID_NAME:
     150        case ERROR_BAD_DEVICE:
    150151        case ERROR_BAD_PATHNAME:            return VERR_INVALID_NAME;
    151152
     
    184185        case ERROR_INVALID_EXE_SIGNATURE:   return VERR_INVALID_EXE_SIGNATURE;
    185186        case ERROR_BAD_EXE_FORMAT:          return VERR_BAD_EXE_FORMAT;
     187        case ERROR_FILE_CORRUPT:            return VERR_BAD_EXE_FORMAT;
    186188        case ERROR_RESOURCE_DATA_NOT_FOUND: return VERR_NO_DATA; ///@todo fix ERROR_RESOURCE_DATA_NOT_FOUND translation
    187189        case ERROR_INVALID_ADDRESS:         return VERR_INVALID_POINTER; ///@todo fix ERROR_INVALID_ADDRESS translation - dbghelp returns it on some line number queries.
     
    192194
    193195        case ERROR_LOGON_FAILURE:           return VERR_AUTHENTICATION_FAILURE;
     196        case ERROR_PRIVILEGE_NOT_HELD:      return VERR_PRIVILEGE_NOT_HELD;
     197
     198        case ERROR_PASSWORD_EXPIRED:
     199        case ERROR_ACCOUNT_RESTRICTION:
     200        case ERROR_PASSWORD_RESTRICTION:
     201        case ERROR_ACCOUNT_DISABLED:        return VERR_ACCOUNT_RESTRICTED;
     202
    194203
    195204        /*
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