summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/r3/win/process-win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Runtime/r3/win/process-win.cpp')
-rw-r--r--src/VBox/Runtime/r3/win/process-win.cpp283
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);
/*