diff options
Diffstat (limited to 'src/VBox/Runtime/r3/win/process-win.cpp')
-rw-r--r-- | src/VBox/Runtime/r3/win/process-win.cpp | 283 |
1 files changed, 143 insertions, 140 deletions
diff --git a/src/VBox/Runtime/r3/win/process-win.cpp b/src/VBox/Runtime/r3/win/process-win.cpp index 47f6d9eb..41a8cbf8 100644 --- a/src/VBox/Runtime/r3/win/process-win.cpp +++ b/src/VBox/Runtime/r3/win/process-win.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2006-2012 Oracle Corporation + * Copyright (C) 2006-2013 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -40,7 +40,7 @@ #include <Lmcons.h> #include <iprt/process.h> -#include "internal/iprt.h" +#include "internal-r3-win.h" #include <iprt/assert.h> #include <iprt/critsect.h> @@ -50,6 +50,7 @@ #include <iprt/getopt.h> #include <iprt/initterm.h> #include <iprt/ldr.h> +#include <iprt/log.h> #include <iprt/mem.h> #include <iprt/once.h> #include <iprt/path.h> @@ -58,6 +59,7 @@ #include <iprt/socket.h> + /******************************************************************************* * Structures and Typedefs * *******************************************************************************/ @@ -157,12 +159,11 @@ static DECLCALLBACK(void) rtProcWinTerm(RTTERMREASON enmReason, int32_t iStatus, * Initialize the globals. * * @returns IPRT status code. - * @param pvUser1 Ignored. - * @param pvUser2 Ignored. + * @param pvUser Ignored. */ -static DECLCALLBACK(int32_t) rtProcWinInitOnce(void *pvUser1, void *pvUser2) +static DECLCALLBACK(int32_t) rtProcWinInitOnce(void *pvUser) { - NOREF(pvUser1); NOREF(pvUser2); + NOREF(pvUser); g_cProcesses = 0; g_cProcessesAlloc = 0; @@ -294,7 +295,8 @@ static int rtProcWinMapErrorCodes(DWORD dwError) case ERROR_PASSWORD_EXPIRED: case ERROR_ACCOUNT_RESTRICTION: /* See: http://support.microsoft.com/kb/303846/ */ case ERROR_PASSWORD_RESTRICTION: - rc = VERR_AUTHENTICATION_FAILURE; + case ERROR_ACCOUNT_DISABLED: /* See: http://support.microsoft.com/kb/263936 */ + rc = VERR_ACCOUNT_RESTRICTED; break; case ERROR_FILE_CORRUPT: @@ -420,77 +422,73 @@ static bool rtProcWinFindTokenByProcessAndPsApi(const char * const *papszNames, /* * Load PSAPI.DLL and resolve the two symbols we need. */ - RTLDRMOD hPsApi; - int rc = RTLdrLoad("PSAPI.dll", &hPsApi); - if (RT_FAILURE_NP(rc)) + PFNGETMODULEBASENAME pfnGetModuleBaseName = (PFNGETMODULEBASENAME)RTLdrGetSystemSymbol("psapi.dll", "GetModuleBaseName"); + if (!pfnGetModuleBaseName) return false; - PFNGETMODULEBASENAME pfnGetModuleBaseName; - PFNENUMPROCESSES pfnEnumProcesses; - rc = RTLdrGetSymbol(hPsApi, "EnumProcesses", (void**)&pfnEnumProcesses); - if (RT_SUCCESS(rc)) - rc = RTLdrGetSymbol(hPsApi, "GetModuleBaseName", (void**)&pfnGetModuleBaseName); + PFNENUMPROCESSES pfnEnumProcesses = (PFNENUMPROCESSES)RTLdrGetSystemSymbol("psapi.dll", "EnumProcesses"); + if (!pfnEnumProcesses) + return false; + + /* + * Get a list of PID. We retry if it looks like there are more PIDs + * to be returned than what we supplied buffer space for. + */ + int rc = VINF_SUCCESS; + DWORD cbPidsAllocated = 4096; + DWORD cbPidsReturned = 0; + DWORD *paPids; + for (;;) + { + paPids = (DWORD *)RTMemTmpAlloc(cbPidsAllocated); + AssertBreakStmt(paPids, rc = VERR_NO_TMP_MEMORY); + if (!pfnEnumProcesses(paPids, cbPidsAllocated, &cbPidsReturned)) + { + rc = RTErrConvertFromWin32(GetLastError()); + AssertMsgFailedBreak(("%Rrc\n", rc)); + } + if ( cbPidsReturned < cbPidsAllocated + || cbPidsAllocated >= _512K) + break; + RTMemTmpFree(paPids); + cbPidsAllocated *= 2; + } if (RT_SUCCESS(rc)) { /* - * Get a list of PID. We retry if it looks like there are more PIDs - * to be returned than what we supplied buffer space for. + * Search for the process. + * + * We ASSUME that the caller won't be specifying any names longer + * than RTPATH_MAX. */ - DWORD cbPidsAllocated = 4096; - DWORD cbPidsReturned = 0; - DWORD *paPids; - for (;;) - { - paPids = (DWORD *)RTMemTmpAlloc(cbPidsAllocated); - AssertBreakStmt(paPids, rc = VERR_NO_TMP_MEMORY); - if (!pfnEnumProcesses(paPids, cbPidsAllocated, &cbPidsReturned)) - { - rc = RTErrConvertFromWin32(GetLastError()); - AssertMsgFailedBreak(("%Rrc\n", rc)); - } - if ( cbPidsReturned < cbPidsAllocated - || cbPidsAllocated >= _512K) - break; - RTMemTmpFree(paPids); - cbPidsAllocated *= 2; - } - if (RT_SUCCESS(rc)) + DWORD cbProcName = RTPATH_MAX; + char *pszProcName = (char *)RTMemTmpAlloc(RTPATH_MAX); + if (pszProcName) { - /* - * Search for the process. - * - * We ASSUME that the caller won't be specifying any names longer - * than RTPATH_MAX. - */ - DWORD cbProcName = RTPATH_MAX; - char *pszProcName = (char *)RTMemTmpAlloc(RTPATH_MAX); - if (pszProcName) + for (size_t i = 0; papszNames[i] && !fFound; i++) { - for (size_t i = 0; papszNames[i] && !fFound; i++) + const DWORD cPids = cbPidsReturned / sizeof(DWORD); + for (DWORD iPid = 0; iPid < cPids && !fFound; iPid++) { - const DWORD cPids = cbPidsReturned / sizeof(DWORD); - for (DWORD iPid = 0; iPid < cPids && !fFound; iPid++) + HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, paPids[iPid]); + if (hProc) { - HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, paPids[iPid]); - if (hProc) - { - *pszProcName = '\0'; - DWORD cbRet = pfnGetModuleBaseName(hProc, 0 /*hModule = exe */, pszProcName, cbProcName); - if ( cbRet > 0 - && _stricmp(pszProcName, papszNames[i]) == 0 - && RT_SUCCESS(rtProcWinGetProcessTokenHandle(paPids[iPid], pSid, phToken))) - fFound = true; - CloseHandle(hProc); - } + *pszProcName = '\0'; + DWORD cbRet = pfnGetModuleBaseName(hProc, 0 /*hModule = exe */, pszProcName, cbProcName); + if ( cbRet > 0 + && _stricmp(pszProcName, papszNames[i]) == 0 + && RT_SUCCESS(rtProcWinGetProcessTokenHandle(paPids[iPid], pSid, phToken))) + fFound = true; + CloseHandle(hProc); } } - RTMemTmpFree(pszProcName); } - else - rc = VERR_NO_TMP_MEMORY; + RTMemTmpFree(pszProcName); } - RTMemTmpFree(paPids); + else + rc = VERR_NO_TMP_MEMORY; } - RTLdrClose(hPsApi); + RTMemTmpFree(paPids); + return fFound; } @@ -517,59 +515,48 @@ static bool rtProcWinFindTokenByProcess(const char * const *papszNames, PSID pSi * On modern systems (W2K+) try the Toolhelp32 API first; this is more stable * and reliable. Fallback to EnumProcess on NT4. */ - RTLDRMOD hKernel32; - int rc = RTLdrLoad("Kernel32.dll", &hKernel32); - if (RT_SUCCESS(rc)) + PFNCREATETOOLHELP32SNAPSHOT pfnCreateToolhelp32Snapshot; + pfnCreateToolhelp32Snapshot = (PFNCREATETOOLHELP32SNAPSHOT)GetProcAddress(g_hModKernel32, "CreateToolhelp32Snapshot"); + PFNPROCESS32FIRST pfnProcess32First = (PFNPROCESS32FIRST)GetProcAddress(g_hModKernel32, "Process32First"); + PFNPROCESS32NEXT pfnProcess32Next = (PFNPROCESS32NEXT )GetProcAddress(g_hModKernel32, "Process32Next"); + bool fFallback = true; + if (pfnProcess32Next && pfnProcess32First && pfnCreateToolhelp32Snapshot) { - PFNCREATETOOLHELP32SNAPSHOT pfnCreateToolhelp32Snapshot; - PFNPROCESS32FIRST pfnProcess32First; - PFNPROCESS32NEXT pfnProcess32Next; - rc = RTLdrGetSymbol(hKernel32, "CreateToolhelp32Snapshot", (void **)&pfnCreateToolhelp32Snapshot); - if (RT_SUCCESS(rc)) - rc = RTLdrGetSymbol(hKernel32, "Process32First", (void**)&pfnProcess32First); - if (RT_SUCCESS(rc)) - rc = RTLdrGetSymbol(hKernel32, "Process32Next", (void**)&pfnProcess32Next); - - if (RT_SUCCESS(rc)) + HANDLE hSnap = pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnap != INVALID_HANDLE_VALUE) { - HANDLE hSnap = pfnCreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (hSnap != INVALID_HANDLE_VALUE) + fFallback = false; + for (size_t i = 0; papszNames[i] && !fFound; i++) { - for (size_t i = 0; papszNames[i] && !fFound; i++) + PROCESSENTRY32 procEntry; + procEntry.dwSize = sizeof(PROCESSENTRY32); + if (pfnProcess32First(hSnap, &procEntry)) { - PROCESSENTRY32 procEntry; - procEntry.dwSize = sizeof(PROCESSENTRY32); - if (pfnProcess32First(hSnap, &procEntry)) + do { - do + if ( _stricmp(procEntry.szExeFile, papszNames[i]) == 0 + && RT_SUCCESS(rtProcWinGetProcessTokenHandle(procEntry.th32ProcessID, pSid, phToken))) { - if ( _stricmp(procEntry.szExeFile, papszNames[i]) == 0 - && RT_SUCCESS(rtProcWinGetProcessTokenHandle(procEntry.th32ProcessID, pSid, phToken))) - { - fFound = true; - break; - } - } while (pfnProcess32Next(hSnap, &procEntry)); - } + fFound = true; + break; + } + } while (pfnProcess32Next(hSnap, &procEntry)); + } #ifdef RT_STRICT - else - { - DWORD dwErr = GetLastError(); - AssertMsgFailed(("dwErr=%u (%x)\n", dwErr, dwErr)); - } -#endif + else + { + DWORD dwErr = GetLastError(); + AssertMsgFailed(("dwErr=%u (%x)\n", dwErr, dwErr)); } - CloseHandle(hSnap); +#endif } - else /* hSnap == INVALID_HANDLE_VALUE */ - rc = RTErrConvertFromWin32(GetLastError()); + CloseHandle(hSnap); } - RTLdrClose(hKernel32); } /* If we couldn't take a process snapshot for some reason or another, fall back on the NT4 compatible API. */ - if (RT_FAILURE(rc)) + if (fFallback) return rtProcWinFindTokenByProcessAndPsApi(papszNames, pSid, phToken); return fFound; } @@ -602,7 +589,13 @@ static int rtProcWinUserLogon(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 LOGON32_PROVIDER_DEFAULT, phToken); if (!fRc) - return rtProcWinMapErrorCodes(GetLastError()); + { + DWORD dwErr = GetLastError(); + int rc = rtProcWinMapErrorCodes(dwErr); + if (rc == VERR_UNRESOLVED_ERROR) + LogRelFunc(("dwErr=%u (%#x), rc=%Rrc\n", dwErr, dwErr, rc)); + return rc; + } return VINF_SUCCESS; } @@ -651,8 +644,10 @@ static int rtProcWinEnvironmentCreateInternal(VOID *pvBlock, RTENV hEnv, PRTUTF1 RTStrFree(pszEntry); } } + else + break; pwch += RTUtf16Len(pwch) + 1; - if (*pwch) + if (!*pwch) break; } @@ -680,8 +675,11 @@ static int rtProcWinEnvironmentCreateInternal(VOID *pvBlock, RTENV hEnv, PRTUTF1 */ static int rtProcWinCreateEnvFromToken(HANDLE hToken, RTENV hEnv, PRTUTF16 *ppwszBlock) { + Assert(hToken); + Assert(hEnv != NIL_RTENV); + RTLDRMOD hUserenv; - int rc = RTLdrLoad("Userenv.dll", &hUserenv); + int rc = RTLdrLoadSystem("Userenv.dll", true /*fNoUnload*/, &hUserenv); if (RT_SUCCESS(rc)) { PFNCREATEENVIRONMENTBLOCK pfnCreateEnvironmentBlock; @@ -729,7 +727,7 @@ static int rtProcWinCreateEnvFromToken(HANDLE hToken, RTENV hEnv, PRTUTF16 *ppws * @param ppwszBlock Pointer to a pointer of the final UTF16 environment block. */ static int rtProcWinCreateEnvFromAccount(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTUTF16 pwszDomain, - RTENV hEnv, PRTUTF16 *ppwszBlock) + RTENV hEnv, PRTUTF16 *ppwszBlock) { HANDLE hToken; int rc = rtProcWinUserLogon(pwszUser, pwszPassword, pwszDomain, &hToken); @@ -873,7 +871,7 @@ static int rtProcWinCreateAsUser2(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTU */ phToken = fFound ? &hTokenUserDesktop : &hTokenLogon; RTLDRMOD hUserenv; - int rc = RTLdrLoad("Userenv.dll", &hUserenv); + rc = RTLdrLoadSystem("Userenv.dll", true /*fNoUnload*/, &hUserenv); if (RT_SUCCESS(rc)) { PFNLOADUSERPROFILEW pfnLoadUserProfileW; @@ -915,7 +913,9 @@ static int rtProcWinCreateAsUser2(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTU NULL, /* pThreadAttributes */ TRUE, /* fInheritHandles */ dwCreationFlags, - pwszzBlock, + /** @todo Warn about exceeding 8192 bytes + * on XP and up. */ + pwszzBlock, /* lpEnvironment */ NULL, /* pCurrentDirectory */ pStartupInfo, pProcInfo); @@ -951,7 +951,11 @@ static int rtProcWinCreateAsUser2(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTU if ( RT_SUCCESS(rc) && dwErr != NO_ERROR) + { rc = rtProcWinMapErrorCodes(dwErr); + if (rc == VERR_UNRESOLVED_ERROR) + LogRelFunc(("dwErr=%u (%#x), rc=%Rrc\n", dwErr, dwErr, rc)); + } return rc; } @@ -967,36 +971,36 @@ static int rtProcWinCreateAsUser1(PRTUTF16 pwszUser, PRTUTF16 pwszPassword, PRTU RTENV hEnv, DWORD dwCreationFlags, STARTUPINFOW *pStartupInfo, PROCESS_INFORMATION *pProcInfo, uint32_t fFlags) { - RTLDRMOD hAdvAPI32; - int rc = RTLdrLoad("Advapi32.dll", &hAdvAPI32); + PFNCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW; + pfnCreateProcessWithLogonW = (PFNCREATEPROCESSWITHLOGON)RTLdrGetSystemSymbol("Advapi32.dll", "CreateProcessWithLogonW"); + if (!pfnCreateProcessWithLogonW) + return VERR_SYMBOL_NOT_FOUND; + + PRTUTF16 pwszzBlock; + int rc = rtProcWinCreateEnvFromAccount(pwszUser, pwszPassword, NULL /* Domain */, + hEnv, &pwszzBlock); if (RT_SUCCESS(rc)) { - PFNCREATEPROCESSWITHLOGON pfnCreateProcessWithLogonW; - rc = RTLdrGetSymbol(hAdvAPI32, "CreateProcessWithLogonW", (void **)&pfnCreateProcessWithLogonW); - if (RT_SUCCESS(rc)) + BOOL fRc = pfnCreateProcessWithLogonW(pwszUser, + NULL, /* lpDomain*/ + pwszPassword, + 1 /*LOGON_WITH_PROFILE*/, /* dwLogonFlags */ + pwszExec, + pwszCmdLine, + dwCreationFlags, + pwszzBlock, + NULL, /* pCurrentDirectory */ + pStartupInfo, + pProcInfo); + if (!fRc) { - PRTUTF16 pwszzBlock; - rc = rtProcWinCreateEnvFromAccount(pwszUser, pwszPassword, NULL /* Domain */, - hEnv, &pwszzBlock); - if (RT_SUCCESS(rc)) - { - BOOL fRc = pfnCreateProcessWithLogonW(pwszUser, - NULL, /* lpDomain*/ - pwszPassword, - 1 /*LOGON_WITH_PROFILE*/, /* dwLogonFlags */ - pwszExec, - pwszCmdLine, - dwCreationFlags, - pwszzBlock, - NULL, /* pCurrentDirectory */ - pStartupInfo, - pProcInfo); - if (!fRc) - rc = rtProcWinMapErrorCodes(GetLastError()); - rtProcWinDestroyEnv(pwszzBlock); - } + DWORD dwErr = GetLastError(); + rc = rtProcWinMapErrorCodes(dwErr); + if (rc == VERR_UNRESOLVED_ERROR) + LogRelFunc(("pfnCreateProcessWithLogonW (%p) failed: dwErr=%u (%#x), rc=%Rrc\n", + pfnCreateProcessWithLogonW, dwErr, dwErr, rc)); } - RTLdrClose(hAdvAPI32); + rtProcWinDestroyEnv(pwszzBlock); } return rc; } @@ -1060,12 +1064,11 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg AssertReturn(!pszAsUser || *pszAsUser, VERR_INVALID_PARAMETER); AssertReturn(!pszPassword || pszAsUser, VERR_INVALID_PARAMETER); AssertPtrNullReturn(pszPassword, VERR_INVALID_POINTER); - /** @todo search the PATH (add flag for this). */ /* * Initialize the globals. */ - int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL); + int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL); AssertRCReturn(rc, rc); /* @@ -1197,7 +1200,7 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg */ PROCESS_INFORMATION ProcInfo; RT_ZERO(ProcInfo); - DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT; + DWORD dwCreationFlags = CREATE_UNICODE_ENVIRONMENT; if (fFlags & RTPROC_FLAGS_DETACHED) dwCreationFlags |= DETACHED_PROCESS; if (fFlags & RTPROC_FLAGS_NO_WINDOW) @@ -1288,7 +1291,7 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg RTR3DECL(int) RTProcWait(RTPROCESS Process, unsigned fFlags, PRTPROCSTATUS pProcStatus) { AssertReturn(!(fFlags & ~(RTPROCWAIT_FLAGS_BLOCK | RTPROCWAIT_FLAGS_NOBLOCK)), VERR_INVALID_PARAMETER); - int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL); + int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL); AssertRCReturn(rc, rc); /* @@ -1384,7 +1387,7 @@ RTR3DECL(int) RTProcTerminate(RTPROCESS Process) if (Process == NIL_RTPROCESS) return VINF_SUCCESS; - int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL, NULL); + int rc = RTOnce(&g_rtProcWinInitOnce, rtProcWinInitOnce, NULL); AssertRCReturn(rc, rc); /* |