summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/r3/win
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Runtime/r3/win')
-rw-r--r--src/VBox/Runtime/r3/win/RTHandleGetStandard-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp10
-rw-r--r--src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp228
-rw-r--r--src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp12
-rw-r--r--src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def22
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-openssl.def12
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-win32.def2
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-win64.def2
-rw-r--r--src/VBox/Runtime/r3/win/alloc-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/allocex-win.cpp120
-rw-r--r--src/VBox/Runtime/r3/win/dir-win.cpp342
-rw-r--r--src/VBox/Runtime/r3/win/direnum-win.cpp389
-rw-r--r--src/VBox/Runtime/r3/win/dllmain-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/env-win.cpp268
-rw-r--r--src/VBox/Runtime/r3/win/fileaio-win.cpp14
-rw-r--r--src/VBox/Runtime/r3/win/fs-win.cpp5
-rw-r--r--src/VBox/Runtime/r3/win/init-win.cpp273
-rw-r--r--src/VBox/Runtime/r3/win/internal-r3-win.h72
-rw-r--r--src/VBox/Runtime/r3/win/ldrNative-win.cpp54
-rw-r--r--src/VBox/Runtime/r3/win/localipc-win.cpp782
-rw-r--r--src/VBox/Runtime/r3/win/mp-win.cpp69
-rw-r--r--src/VBox/Runtime/r3/win/ntdll-mini-implib.c111
-rw-r--r--src/VBox/Runtime/r3/win/ntdll-mini-implib.def9
-rw-r--r--src/VBox/Runtime/r3/win/path-win.cpp4
-rw-r--r--src/VBox/Runtime/r3/win/pipe-win.cpp22
-rw-r--r--src/VBox/Runtime/r3/win/poll-win.cpp586
-rw-r--r--src/VBox/Runtime/r3/win/process-win.cpp283
-rw-r--r--src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/sched-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/semmutex-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/symlink-win.cpp15
-rw-r--r--src/VBox/Runtime/r3/win/thread-win.cpp10
-rw-r--r--src/VBox/Runtime/r3/win/time-win.cpp25
-rw-r--r--src/VBox/Runtime/r3/win/timer-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/tls-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/utf16locale-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/uuid-win.cpp2
39 files changed, 2307 insertions, 1458 deletions
diff --git a/src/VBox/Runtime/r3/win/RTHandleGetStandard-win.cpp b/src/VBox/Runtime/r3/win/RTHandleGetStandard-win.cpp
index 683d6ee4..8c3d86b5 100644
--- a/src/VBox/Runtime/r3/win/RTHandleGetStandard-win.cpp
+++ b/src/VBox/Runtime/r3/win/RTHandleGetStandard-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp b/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp
index 2f3c16c0..69d028a0 100644
--- a/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp
+++ b/src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp b/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp
index 57831910..8621a36b 100644
--- a/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp
+++ b/src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -165,8 +165,11 @@ RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t c
/*
* Before we do anything with COM, we have to initialize it.
*/
+ bool fUninit = true;
HRESULT hrc = rtSystemDmiWinInitialize();
- if (FAILED(hrc))
+ if (hrc == RPC_E_CHANGED_MODE)
+ fUninit = false; /* don't fail if already initialized */
+ else if (FAILED(hrc))
return VERR_NOT_SUPPORTED;
int rc = VERR_NOT_SUPPORTED;
@@ -246,7 +249,8 @@ RTDECL(int) RTSystemQueryDmiString(RTSYSDMISTR enmString, char *pszBuf, size_t c
}
else
hrc = E_OUTOFMEMORY;
- rtSystemDmiWinTerminate();
+ if (fUninit)
+ rtSystemDmiWinTerminate();
if (FAILED(hrc) && rc == VERR_NOT_SUPPORTED)
rc = VERR_NOT_SUPPORTED;
return rc;
diff --git a/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp b/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp
index 50dee1aa..28c34625 100644
--- a/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp
+++ b/src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -27,9 +27,11 @@
/*******************************************************************************
* Header Files *
*******************************************************************************/
+#include "internal/iprt.h"
#include <Windows.h>
#include <WinUser.h>
+#include "internal-r3-win.h"
#include <iprt/system.h>
#include <iprt/assert.h>
#include <iprt/string.h>
@@ -39,35 +41,6 @@
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
-/**
- * Windows OS type as determined by rtSystemWinOSType().
- */
-typedef enum RTWINOSTYPE
-{
- kRTWinOSType_UNKNOWN = 0,
- kRTWinOSType_9XFIRST = 1,
- kRTWinOSType_95 = kRTWinOSType_9XFIRST,
- kRTWinOSType_95SP1,
- kRTWinOSType_95OSR2,
- kRTWinOSType_98,
- kRTWinOSType_98SP1,
- kRTWinOSType_98SE,
- kRTWinOSType_ME,
- kRTWinOSType_9XLAST = 99,
- kRTWinOSType_NTFIRST = 100,
- kRTWinOSType_NT31 = kRTWinOSType_NTFIRST,
- kRTWinOSType_NT351,
- kRTWinOSType_NT4,
- kRTWinOSType_2K,
- kRTWinOSType_XP,
- kRTWinOSType_2003,
- kRTWinOSType_VISTA,
- kRTWinOSType_2008,
- kRTWinOSType_7,
- kRTWinOSType_8,
- kRTWinOSType_NT_UNKNOWN = 199,
- kRTWinOSType_NT_LAST = kRTWinOSType_UNKNOWN
-} RTWINOSTYPE;
/**
* These are the PRODUCT_* defines found in the Vista Platform SDK and returned
@@ -111,112 +84,6 @@ typedef enum RTWINPRODTYPE
/**
- * Translates OSVERSIONINOFEX into a Windows OS type.
- *
- * @returns The Windows OS type.
- * @param pOSInfoEx The OS info returned by Windows.
- *
- * @remarks This table has been assembled from Usenet postings, personal
- * observations, and reading other people's code. Please feel
- * free to add to it or correct it.
- * <pre>
- dwPlatFormID dwMajorVersion dwMinorVersion dwBuildNumber
-95 1 4 0 950
-95 SP1 1 4 0 >950 && <=1080
-95 OSR2 1 4 <10 >1080
-98 1 4 10 1998
-98 SP1 1 4 10 >1998 && <2183
-98 SE 1 4 10 >=2183
-ME 1 4 90 3000
-
-NT 3.51 2 3 51 1057
-NT 4 2 4 0 1381
-2000 2 5 0 2195
-XP 2 5 1 2600
-2003 2 5 2 3790
-Vista 2 6 0
-
-CE 1.0 3 1 0
-CE 2.0 3 2 0
-CE 2.1 3 2 1
-CE 3.0 3 3 0
-</pre>
- */
-static RTWINOSTYPE rtSystemWinOSType(OSVERSIONINFOEX const *pOSInfoEx)
-{
- RTWINOSTYPE enmVer = kRTWinOSType_UNKNOWN;
- BYTE const bProductType = pOSInfoEx->wProductType;
- DWORD const dwPlatformId = pOSInfoEx->dwPlatformId;
- DWORD const dwMinorVersion = pOSInfoEx->dwMinorVersion;
- DWORD const dwMajorVersion = pOSInfoEx->dwMajorVersion;
- DWORD const dwBuildNumber = pOSInfoEx->dwBuildNumber & 0xFFFF; /* Win 9x needs this. */
-
- if ( dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
- && dwMajorVersion == 4)
- {
- if ( dwMinorVersion < 10
- && dwBuildNumber == 950)
- enmVer = kRTWinOSType_95;
- else if ( dwMinorVersion < 10
- && dwBuildNumber > 950
- && dwBuildNumber <= 1080)
- enmVer = kRTWinOSType_95SP1;
- else if ( dwMinorVersion < 10
- && dwBuildNumber > 1080)
- enmVer = kRTWinOSType_95OSR2;
- else if ( dwMinorVersion == 10
- && dwBuildNumber == 1998)
- enmVer = kRTWinOSType_98;
- else if ( dwMinorVersion == 10
- && dwBuildNumber > 1998
- && dwBuildNumber < 2183)
- enmVer = kRTWinOSType_98SP1;
- else if ( dwMinorVersion == 10
- && dwBuildNumber >= 2183)
- enmVer = kRTWinOSType_98SE;
- else if (dwMinorVersion == 90)
- enmVer = kRTWinOSType_ME;
- }
- else if (dwPlatformId == VER_PLATFORM_WIN32_NT)
- {
- if ( dwMajorVersion == 3
- && dwMinorVersion == 51)
- enmVer = kRTWinOSType_NT351;
- else if ( dwMajorVersion == 4
- && dwMinorVersion == 0)
- enmVer = kRTWinOSType_NT4;
- else if ( dwMajorVersion == 5
- && dwMinorVersion == 0)
- enmVer = kRTWinOSType_2K;
- else if ( dwMajorVersion == 5
- && dwMinorVersion == 1)
- enmVer = kRTWinOSType_XP;
- else if ( dwMajorVersion == 5
- && dwMinorVersion == 2)
- enmVer = kRTWinOSType_2003;
- else if ( dwMajorVersion == 6
- && dwMinorVersion == 0)
- {
- if (bProductType != VER_NT_WORKSTATION)
- enmVer = kRTWinOSType_2008;
- else
- enmVer = kRTWinOSType_VISTA;
- }
- else if ( dwMajorVersion == 6
- && dwMinorVersion == 1)
- enmVer = kRTWinOSType_7;
- else if ( dwMajorVersion == 6
- && dwMinorVersion == 2)
- enmVer = kRTWinOSType_8;
- else
- enmVer = kRTWinOSType_NT_UNKNOWN;
- }
-
- return enmVer;
-}
-
-
-/**
* Wrapper around the GetProductInfo API.
*
* @returns The vista type.
@@ -224,7 +91,7 @@ static RTWINOSTYPE rtSystemWinOSType(OSVERSIONINFOEX const *pOSInfoEx)
static RTWINPRODTYPE rtSystemWinGetProductInfo(DWORD dwOSMajorVersion, DWORD dwOSMinorVersion, DWORD dwSpMajorVersion, DWORD dwSpMinorVersion)
{
BOOL (WINAPI *pfnGetProductInfo)(DWORD, DWORD, DWORD, DWORD, PDWORD);
- pfnGetProductInfo = (BOOL (WINAPI *)(DWORD, DWORD, DWORD, DWORD, PDWORD))GetProcAddress(GetModuleHandle("KERNEL32.DLL"), "GetProductInfo");
+ pfnGetProductInfo = (BOOL (WINAPI *)(DWORD, DWORD, DWORD, DWORD, PDWORD))GetProcAddress(GetModuleHandle("kernel32.dll"), "GetProductInfo");
if (pfnGetProductInfo)
{
DWORD dwProductType = kRTWinProdType_UNDEFINED;
@@ -291,48 +158,21 @@ static void rtSystemWinAppendProductType(char *pszTmp)
*/
static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchInfo)
{
- int rc;
-
/*
* Make sure it's terminated correctly in case of error.
*/
*pszInfo = '\0';
/*
- * Query the Windows version.
- *
- * ASSUMES OSVERSIONINFOEX starts with the exact same layout as OSVERSIONINFO (safe).
+ * Check that we got the windows version at init time.
*/
- OSVERSIONINFOEX OSInfoEx;
- memset(&OSInfoEx, '\0', sizeof(OSInfoEx));
- OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- if (!GetVersionEx((LPOSVERSIONINFO) &OSInfoEx))
- {
- DWORD err = GetLastError();
- rc = RTErrConvertFromWin32(err);
- AssertMsgFailedReturn(("err=%d\n", err), rc == VERR_BUFFER_OVERFLOW ? VERR_INTERNAL_ERROR : rc);
- }
-
- /* Get extended version info for 2000 and later. */
- if ( OSInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT
- && OSInfoEx.dwMajorVersion >= 5)
- {
- ZeroMemory(&OSInfoEx, sizeof(OSInfoEx));
- OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- if (!GetVersionEx((LPOSVERSIONINFO) &OSInfoEx))
- {
- DWORD err = GetLastError();
- rc = RTErrConvertFromWin32(err);
- AssertMsgFailedReturn(("err=%d\n", err), rc == VERR_BUFFER_OVERFLOW ? VERR_INTERNAL_ERROR : rc);
- }
- }
+ AssertReturn(g_WinOsInfoEx.dwOSVersionInfoSize, VERR_WRONG_ORDER);
/*
* Service the request.
*/
char szTmp[512];
szTmp[0] = '\0';
- rc = VINF_SUCCESS;
switch (enmInfo)
{
/*
@@ -340,8 +180,7 @@ static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t
*/
case RTSYSOSINFO_PRODUCT:
{
- RTWINOSTYPE enmVer = rtSystemWinOSType(&OSInfoEx);
- switch (enmVer)
+ switch (g_enmWinVer)
{
case kRTWinOSType_95: strcpy(szTmp, "Windows 95"); break;
case kRTWinOSType_95SP1: strcpy(szTmp, "Windows 95 (Service Pack 1)"); break;
@@ -355,10 +194,10 @@ static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t
case kRTWinOSType_2K: strcpy(szTmp, "Windows 2000"); break;
case kRTWinOSType_XP:
strcpy(szTmp, "Windows XP");
- if (OSInfoEx.wSuiteMask & VER_SUITE_PERSONAL)
+ if (g_WinOsInfoEx.wSuiteMask & VER_SUITE_PERSONAL)
strcat(szTmp, " Home");
- if ( OSInfoEx.wProductType == VER_NT_WORKSTATION
- && !(OSInfoEx.wSuiteMask & VER_SUITE_PERSONAL))
+ if ( g_WinOsInfoEx.wProductType == VER_NT_WORKSTATION
+ && !(g_WinOsInfoEx.wSuiteMask & VER_SUITE_PERSONAL))
strcat(szTmp, " Professional");
#if 0 /** @todo fixme */
if (GetSystemMetrics(SM_MEDIACENTER))
@@ -376,15 +215,18 @@ static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t
case kRTWinOSType_2008: strcpy(szTmp, "Windows 2008"); break;
case kRTWinOSType_7: strcpy(szTmp, "Windows 7"); break;
case kRTWinOSType_8: strcpy(szTmp, "Windows 8"); break;
+ case kRTWinOSType_81: strcpy(szTmp, "Windows 8.1"); break;
case kRTWinOSType_NT_UNKNOWN:
- RTStrPrintf(szTmp, sizeof(szTmp), "Unknown NT v%u.%u", OSInfoEx.dwMajorVersion, OSInfoEx.dwMinorVersion);
+ RTStrPrintf(szTmp, sizeof(szTmp), "Unknown NT v%u.%u",
+ g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion);
break;
default:
AssertFailed();
case kRTWinOSType_UNKNOWN:
- RTStrPrintf(szTmp, sizeof(szTmp), "Unknown %d v%u.%u", OSInfoEx.dwPlatformId, OSInfoEx.dwMajorVersion, OSInfoEx.dwMinorVersion);
+ RTStrPrintf(szTmp, sizeof(szTmp), "Unknown %d v%u.%u",
+ g_WinOsInfoEx.dwPlatformId, g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion);
break;
}
break;
@@ -395,8 +237,8 @@ static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t
*/
case RTSYSOSINFO_RELEASE:
{
- RTWINOSTYPE enmVer = rtSystemWinOSType(&OSInfoEx);
- RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u.%u", OSInfoEx.dwMajorVersion, OSInfoEx.dwMinorVersion, OSInfoEx.dwBuildNumber);
+ RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u.%u",
+ g_WinOsInfoEx.dwMajorVersion, g_WinOsInfoEx.dwMinorVersion, g_WinOsInfoEx.dwBuildNumber);
break;
}
@@ -406,24 +248,25 @@ static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t
*/
case RTSYSOSINFO_SERVICE_PACK:
{
- if (OSInfoEx.wServicePackMajor)
+ if (g_WinOsInfoEx.wServicePackMajor)
{
- if (OSInfoEx.wServicePackMinor)
- RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u", (unsigned)OSInfoEx.wServicePackMajor, (unsigned)OSInfoEx.wServicePackMinor);
+ if (g_WinOsInfoEx.wServicePackMinor)
+ RTStrPrintf(szTmp, sizeof(szTmp), "%u.%u",
+ (unsigned)g_WinOsInfoEx.wServicePackMajor, (unsigned)g_WinOsInfoEx.wServicePackMinor);
else
- RTStrPrintf(szTmp, sizeof(szTmp), "%u", (unsigned)OSInfoEx.wServicePackMajor);
+ RTStrPrintf(szTmp, sizeof(szTmp), "%u",
+ (unsigned)g_WinOsInfoEx.wServicePackMajor);
}
- else if (OSInfoEx.szCSDVersion[0])
+ else if (g_WinOsInfoEx.szCSDVersion[0])
{
/* just copy the entire string. */
- memcpy(szTmp, OSInfoEx.szCSDVersion, sizeof(OSInfoEx.szCSDVersion));
- szTmp[sizeof(OSInfoEx.szCSDVersion)] = '\0';
- AssertCompile(sizeof(szTmp) > sizeof(OSInfoEx.szCSDVersion));
+ memcpy(szTmp, g_WinOsInfoEx.szCSDVersion, sizeof(g_WinOsInfoEx.szCSDVersion));
+ szTmp[sizeof(g_WinOsInfoEx.szCSDVersion)] = '\0';
+ AssertCompile(sizeof(szTmp) > sizeof(g_WinOsInfoEx.szCSDVersion));
}
else
{
- RTWINOSTYPE enmVer = rtSystemWinOSType(&OSInfoEx);
- switch (enmVer)
+ switch (g_enmWinVer)
{
case kRTWinOSType_95SP1: strcpy(szTmp, "1"); break;
case kRTWinOSType_98SP1: strcpy(szTmp, "1"); break;
@@ -444,15 +287,13 @@ static int rtSystemWinQueryOSVersion(RTSYSOSINFO enmInfo, char *pszInfo, size_t
size_t cchTmp = strlen(szTmp);
Assert(cchTmp < sizeof(szTmp));
if (cchTmp < cchInfo)
- memcpy(pszInfo, szTmp, cchTmp + 1);
- else
{
- memcpy(pszInfo, szTmp, cchInfo - 1);
- pszInfo[cchInfo - 1] = '\0';
- if (RT_SUCCESS(rc))
- rc = VERR_BUFFER_OVERFLOW;
+ memcpy(pszInfo, szTmp, cchTmp + 1);
+ return VINF_SUCCESS;
}
- return VINF_SUCCESS;
+ memcpy(pszInfo, szTmp, cchInfo - 1);
+ pszInfo[cchInfo - 1] = '\0';
+ return VERR_BUFFER_OVERFLOW;
}
@@ -481,7 +322,8 @@ RTDECL(int) RTSystemQueryOSInfo(RTSYSOSINFO enmInfo, char *pszInfo, size_t cchIn
case RTSYSOSINFO_VERSION:
default:
*pszInfo = '\0';
- return VERR_NOT_SUPPORTED;
}
+
+ return VERR_NOT_SUPPORTED;
}
diff --git a/src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp b/src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp
index 62a25bc3..2ddb96c8 100644
--- a/src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp
+++ b/src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp
@@ -53,9 +53,9 @@ RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char
BOOL fForceAppsClosed = fFlags & RTSYSTEM_SHUTDOWN_FORCE ? TRUE : FALSE;
/*
- * Do the
+ * Do the
*/
- if (InitiateSystemShutdownW(NULL /*pwszMachineName = NULL = localhost*/,
+ if (InitiateSystemShutdownW(NULL /*pwszMachineName = NULL = localhost*/,
pwszLogMsg,
cSecsTimeout,
fForceAppsClosed,
@@ -70,7 +70,7 @@ RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char
if (dwErr == ERROR_ACCESS_DENIED)
{
HANDLE hToken = NULL;
- if (OpenThreadToken(GetCurrentThread(),
+ if (OpenThreadToken(GetCurrentThread(),
TOKEN_ADJUST_PRIVILEGES,
TRUE /*OpenAsSelf*/,
&hToken))
@@ -80,7 +80,7 @@ RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char
dwErr = GetLastError();
if (dwErr == ERROR_NO_TOKEN)
{
- if (OpenProcessToken(GetCurrentProcess(),
+ if (OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES,
&hToken))
dwErr = NO_ERROR;
@@ -91,7 +91,7 @@ RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char
if (dwErr == NO_ERROR)
{
- union
+ union
{
TOKEN_PRIVILEGES TokenPriv;
char ab[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)];
@@ -107,7 +107,7 @@ RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char
NULL,
NULL) )
{
- if (InitiateSystemShutdownW(NULL /*pwszMachineName = NULL = localhost*/,
+ if (InitiateSystemShutdownW(NULL /*pwszMachineName = NULL = localhost*/,
pwszLogMsg,
cSecsTimeout,
fForceAppsClosed,
diff --git a/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp b/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp
index 8083f98d..7792b794 100644
--- a/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp
+++ b/src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def b/src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def
index fc314a4d..e1ac857f 100644
--- a/src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def
+++ b/src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def
@@ -32,8 +32,8 @@
;
; OpenSSL symbols
;
- _CONF_get_section
- _CONF_get_string
+;; _CONF_get_section
+;; _CONF_get_string
a2d_ASN1_OBJECT
a2i_ASN1_INTEGER
a2i_ASN1_STRING
@@ -442,10 +442,10 @@
CRYPTO_dbg_free
CRYPTO_dbg_get_options
CRYPTO_dbg_malloc
- CRYPTO_dbg_pop_info
- CRYPTO_dbg_push_info
+;; CRYPTO_dbg_pop_info
+;; CRYPTO_dbg_push_info
CRYPTO_dbg_realloc
- CRYPTO_dbg_remove_all_info
+;; CRYPTO_dbg_remove_all_info
CRYPTO_dbg_set_options
CRYPTO_destroy_dynlockid
CRYPTO_dup_ex_data
@@ -474,7 +474,7 @@
CRYPTO_is_mem_check_on
CRYPTO_lock
CRYPTO_malloc
- CRYPTO_malloc_debug_init
+;; CRYPTO_malloc_debug_init
CRYPTO_malloc_locked
CRYPTO_mem_ctrl
CRYPTO_mem_leaks
@@ -502,7 +502,7 @@
CRYPTO_set_mem_debug_options
CRYPTO_set_mem_ex_functions
CRYPTO_set_mem_functions
- CRYPTO_set_mem_info_functions
+;; CRYPTO_set_mem_info_functions
CRYPTO_strdup
CRYPTO_thread_id
d2i_ACCESS_DESCRIPTION
@@ -1123,8 +1123,8 @@
NOTICEREF_new
o2i_ECPublicKey
OBJ_add_object
- OBJ_bsearch
- OBJ_bsearch_ex
+;; OBJ_bsearch
+;; OBJ_bsearch_ex
OBJ_cleanup
OBJ_cmp
OBJ_create
@@ -1283,7 +1283,7 @@
RSA_size
RSA_up_ref
RSA_verify
- RSAPrivateKey_asn1_meth
+;; RSAPrivateKey_asn1_meth
RSAPrivateKey_dup
RSAPublicKey_dup
s2i_ASN1_INTEGER
@@ -1428,7 +1428,7 @@
X509_ALGOR_set0
X509_alias_get0
X509_alias_set1
- X509_asn1_meth
+;; X509_asn1_meth
X509_ATTRIBUTE_count
X509_ATTRIBUTE_create
X509_ATTRIBUTE_create_by_NID
diff --git a/src/VBox/Runtime/r3/win/VBoxRT-openssl.def b/src/VBox/Runtime/r3/win/VBoxRT-openssl.def
index 01e269b5..f872e71c 100644
--- a/src/VBox/Runtime/r3/win/VBoxRT-openssl.def
+++ b/src/VBox/Runtime/r3/win/VBoxRT-openssl.def
@@ -9,7 +9,7 @@
;
;
-; Copyright (C) 2009-2012 Oracle Corporation
+; Copyright (C) 2009-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;
@@ -476,11 +476,6 @@
c2i_ASN1_OBJECT
CERTIFICATEPOLICIES_free
CERTIFICATEPOLICIES_new
- COMP_compress_block
- COMP_CTX_free
- COMP_CTX_new
- COMP_expand_block
- COMP_zlib
CONF_dump_bio
CONF_dump_fp
CONF_free
@@ -961,7 +956,6 @@
ERR_get_state
ERR_get_string_table
ERR_lib_error_string
- ERR_load_ERR_strings
ERR_load_strings
ERR_peek_error
ERR_peek_error_line
@@ -1690,7 +1684,6 @@
SSLeay
SSLeay_version
string_to_hex
- stub_VBOX_BIO_printf
SXNET_add_id_asc
SXNET_add_id_INTEGER
SXNET_add_id_ulong
@@ -2234,7 +2227,8 @@
ssl_cert_inst
ssl_cert_new
ssl_cert_type
- ssl_check_clienthello_tlsext
+ ssl_check_clienthello_tlsext_early
+ ssl_check_clienthello_tlsext_late
SSL_check_private_key
ssl_check_serverhello_tlsext
SSL_CIPHER_description
diff --git a/src/VBox/Runtime/r3/win/VBoxRT-win32.def b/src/VBox/Runtime/r3/win/VBoxRT-win32.def
index 8764142a..e36769fd 100644
--- a/src/VBox/Runtime/r3/win/VBoxRT-win32.def
+++ b/src/VBox/Runtime/r3/win/VBoxRT-win32.def
@@ -4,7 +4,7 @@
;
;
-; Copyright (C) 2006-2007 Oracle Corporation
+; Copyright (C) 2006-2012 Oracle Corporation
;
; This file is part of VirtualBox Open Source Edition (OSE), as
; available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/VBoxRT-win64.def b/src/VBox/Runtime/r3/win/VBoxRT-win64.def
index 4a1eb1de..434c7be3 100644
--- a/src/VBox/Runtime/r3/win/VBoxRT-win64.def
+++ b/src/VBox/Runtime/r3/win/VBoxRT-win64.def
@@ -4,7 +4,7 @@
;
;
-; Copyright (C) 2006-2007 Oracle Corporation
+; Copyright (C) 2006-2012 Oracle Corporation
;
; This file is part of VirtualBox Open Source Edition (OSE), as
; available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/alloc-win.cpp b/src/VBox/Runtime/r3/win/alloc-win.cpp
index 7e052673..25879154 100644
--- a/src/VBox/Runtime/r3/win/alloc-win.cpp
+++ b/src/VBox/Runtime/r3/win/alloc-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/allocex-win.cpp b/src/VBox/Runtime/r3/win/allocex-win.cpp
new file mode 100644
index 00000000..30de9aa7
--- /dev/null
+++ b/src/VBox/Runtime/r3/win/allocex-win.cpp
@@ -0,0 +1,120 @@
+/* $Id: allocex-win.cpp $ */
+/** @file
+ * IPRT - Memory Allocation, Extended Alloc Workers, Windows.
+ */
+
+/*
+ * 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;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#define RTMEM_NO_WRAP_TO_EF_APIS
+#include <iprt/mem.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/param.h>
+#include "../allocex.h"
+
+#include <Windows.h>
+
+
+static int rtMemAllocExInRange(size_t cbAlloc, uint32_t fFlags, void **ppv, uintptr_t uAddr, uintptr_t uAddrLast)
+{
+ /*
+ * Try with every possible address hint since the possible range is very limited.
+ */
+ DWORD fPageProt = (fFlags & RTMEMALLOCEX_FLAGS_EXEC ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
+ while (uAddr <= uAddrLast)
+ {
+ MEMORY_BASIC_INFORMATION MemInfo;
+ SIZE_T cbRange = VirtualQuery((void *)uAddr, &MemInfo, sizeof(MemInfo));
+ AssertReturn(cbRange == sizeof(MemInfo), VERR_NOT_SUPPORTED);
+ Assert(MemInfo.RegionSize > 0);
+
+ if ( MemInfo.State == MEM_FREE
+ && MemInfo.RegionSize >= cbAlloc)
+ {
+ void *pv = VirtualAlloc((void *)uAddr, cbAlloc, MEM_RESERVE | MEM_COMMIT, fPageProt);
+ if ((uintptr_t)pv == uAddr)
+ {
+ *ppv = pv;
+ return VINF_SUCCESS;
+ }
+ AssertStmt(!pv, VirtualFree(pv, cbAlloc, MEM_RELEASE));
+ }
+
+ /* skip ahead */
+ uintptr_t uAddrNext = (uintptr_t)MemInfo.BaseAddress + MemInfo.RegionSize;
+ if (uAddrNext <= uAddr)
+ break;
+ uAddr += uAddrNext;
+ }
+
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtMemAllocEx16BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv)
+{
+ cbAlloc = RT_ALIGN_Z(cbAlloc, PAGE_SIZE);
+ AssertReturn(cbAlloc <= _64K - PAGE_SIZE, VERR_NO_MEMORY);
+
+ /* Seems this doesn't work on W7/64... */
+ return rtMemAllocExInRange(cbAlloc, fFlags, ppv, PAGE_SIZE, _64K - cbAlloc);
+}
+
+
+DECLHIDDEN(int) rtMemAllocEx32BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv)
+{
+ cbAlloc = RT_ALIGN_Z(cbAlloc, PAGE_SIZE);
+ AssertReturn(cbAlloc <= _2G+_1G, VERR_NO_MEMORY);
+
+ /*
+ * Just try first.
+ */
+ DWORD fPageProt = (fFlags & RTMEMALLOCEX_FLAGS_EXEC ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE);
+ void *pv = VirtualAlloc(NULL, cbAlloc, MEM_RESERVE | MEM_COMMIT, fPageProt);
+ if (!pv)
+ return VERR_NO_MEMORY;
+ if ((uintptr_t)pv + cbAlloc - 1 < _4G)
+ {
+ *ppv = pv;
+ return VINF_SUCCESS;
+ }
+ VirtualFree(pv, cbAlloc, MEM_RELEASE);
+
+ /*
+ * No luck, do address scan based allocation.
+ */
+ return rtMemAllocExInRange(cbAlloc, fFlags, ppv, _64K, _4G - cbAlloc);
+}
+
+
+DECLHIDDEN(void) rtMemFreeExYyBitReach(void *pv, size_t cb, uint32_t fFlags)
+{
+ BOOL fRc = VirtualFree(pv, cb, MEM_RELEASE);
+ Assert(fRc);
+}
+
diff --git a/src/VBox/Runtime/r3/win/dir-win.cpp b/src/VBox/Runtime/r3/win/dir-win.cpp
index 2494b8b4..5c57315f 100644
--- a/src/VBox/Runtime/r3/win/dir-win.cpp
+++ b/src/VBox/Runtime/r3/win/dir-win.cpp
@@ -1,10 +1,10 @@
/* $Id: dir-win.cpp $ */
/** @file
- * IPRT - Directory, win32.
+ * IPRT - Directory, Windows.
*/
/*
- * Copyright (C) 2006-2007 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;
@@ -30,20 +30,17 @@
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_DIR
#include <Windows.h>
-#include <io.h>
#include <iprt/dir.h>
#include <iprt/path.h>
-#include <iprt/alloc.h>
+#include <iprt/mem.h>
#include <iprt/string.h>
#include <iprt/assert.h>
-#include <iprt/param.h>
#include <iprt/err.h>
#include <iprt/file.h>
#include <iprt/log.h>
#include "internal/fs.h"
#include "internal/path.h"
-#include "internal/dir.h"
@@ -129,339 +126,6 @@ RTDECL(int) RTDirFlush(const char *pszPath)
}
-int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
-{
- /*
- * Setup the search expression.
- *
- * pszPathBuf is pointing to the return 4K return buffer for the RTPathReal()
- * call in rtDirOpenCommon(), so all we gota do is check that we don't overflow
- * it when adding the wildcard expression.
- */
- size_t cchExpr;
- const char *pszExpr;
- if (pDir->enmFilter == RTDIRFILTER_WINNT)
- {
- pszExpr = pDir->pszFilter;
- cchExpr = pDir->cchFilter + 1;
- }
- else
- {
- pszExpr = "*";
- cchExpr = sizeof("*");
- }
- if (pDir->cchPath + cchExpr > RTPATH_MAX)
- return VERR_FILENAME_TOO_LONG;
- memcpy(pszPathBuf + pDir->cchPath, pszExpr, cchExpr);
-
-
- /*
- * Attempt opening the search.
- */
- int rc = VINF_SUCCESS;
- PRTUTF16 pwszName;
- rc = RTStrToUtf16(pszPathBuf, &pwszName);
- if (RT_SUCCESS(rc))
- {
- pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
- if (pDir->hDir != INVALID_HANDLE_VALUE)
- pDir->fDataUnread = true;
- /* theoretical case of an empty directory. */
- else if (GetLastError() == ERROR_NO_MORE_FILES)
- pDir->fDataUnread = false;
- else
- rc = RTErrConvertFromWin32(GetLastError());
- RTUtf16Free(pwszName);
- }
-
- return rc;
-}
-
-
-RTDECL(int) RTDirClose(PRTDIR pDir)
-{
- /*
- * Validate input.
- */
- if (!pDir)
- return VERR_INVALID_PARAMETER;
- if (pDir->u32Magic != RTDIR_MAGIC)
- {
- AssertMsgFailed(("Invalid pDir=%p\n", pDir));
- return VERR_INVALID_PARAMETER;
- }
-
- /*
- * Close the handle.
- */
- pDir->u32Magic++;
- if (pDir->hDir != INVALID_HANDLE_VALUE)
- {
- BOOL fRc = FindClose(pDir->hDir);
- Assert(fRc);
- pDir->hDir = INVALID_HANDLE_VALUE;
- }
- RTStrFree(pDir->pszName);
- pDir->pszName = NULL;
- RTMemFree(pDir);
-
- return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
-{
- /*
- * Validate input.
- */
- if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
- {
- AssertMsgFailed(("Invalid pDir=%p\n", pDir));
- return VERR_INVALID_PARAMETER;
- }
- if (!pDirEntry)
- {
- AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
- return VERR_INVALID_PARAMETER;
- }
- size_t cbDirEntry = sizeof(*pDirEntry);
- if (pcbDirEntry)
- {
- cbDirEntry = *pcbDirEntry;
- if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2]))
- {
- AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])));
- return VERR_INVALID_PARAMETER;
- }
- }
-
- /*
- * Fetch data?
- */
- if (!pDir->fDataUnread)
- {
- RTStrFree(pDir->pszName);
- pDir->pszName = NULL;
-
- BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
- if (!fRc)
- {
- int iErr = GetLastError();
- if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
- return VERR_NO_MORE_FILES;
- return RTErrConvertFromWin32(iErr);
- }
- }
-
- /*
- * Convert the filename to UTF-8.
- */
- if (!pDir->pszName)
- {
- int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
- if (RT_FAILURE(rc))
- {
- pDir->pszName = NULL;
- return rc;
- }
- pDir->cchName = strlen(pDir->pszName);
- }
-
- /*
- * Check if we've got enough space to return the data.
- */
- const char *pszName = pDir->pszName;
- const size_t cchName = pDir->cchName;
- const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName;
- if (pcbDirEntry)
- *pcbDirEntry = cbRequired;
- if (cbRequired > cbDirEntry)
- return VERR_BUFFER_OVERFLOW;
-
- /*
- * Setup the returned data.
- */
- pDir->fDataUnread = false;
- pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */
- pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
- ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE;
- pDirEntry->cbName = (uint16_t)cchName;
- Assert(pDirEntry->cbName == cchName);
- memcpy(pDirEntry->szName, pszName, cchName + 1);
-
- return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
-{
- /** @todo Symlinks: Find[First|Next]FileW will return info about
- the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
- /*
- * Validate input.
- */
- if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
- {
- AssertMsgFailed(("Invalid pDir=%p\n", pDir));
- return VERR_INVALID_PARAMETER;
- }
- if (!pDirEntry)
- {
- AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
- return VERR_INVALID_PARAMETER;
- }
- if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
- || enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
- {
- AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
- return VERR_INVALID_PARAMETER;
- }
- AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
- size_t cbDirEntry = sizeof(*pDirEntry);
- if (pcbDirEntry)
- {
- cbDirEntry = *pcbDirEntry;
- if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2]))
- {
- AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])));
- return VERR_INVALID_PARAMETER;
- }
- }
-
- /*
- * Fetch data?
- */
- if (!pDir->fDataUnread)
- {
- RTStrFree(pDir->pszName);
- pDir->pszName = NULL;
-
- BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
- if (!fRc)
- {
- int iErr = GetLastError();
- if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
- return VERR_NO_MORE_FILES;
- return RTErrConvertFromWin32(iErr);
- }
- }
-
- /*
- * Convert the filename to UTF-8.
- */
- if (!pDir->pszName)
- {
- int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
- if (RT_FAILURE(rc))
- {
- pDir->pszName = NULL;
- return rc;
- }
- pDir->cchName = strlen(pDir->pszName);
- }
-
- /*
- * Check if we've got enough space to return the data.
- */
- const char *pszName = pDir->pszName;
- const size_t cchName = pDir->cchName;
- const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName;
- if (pcbDirEntry)
- *pcbDirEntry = cbRequired;
- if (cbRequired > cbDirEntry)
- return VERR_BUFFER_OVERFLOW;
-
- /*
- * Setup the returned data.
- */
- pDir->fDataUnread = false;
- pDirEntry->cbName = (uint16_t)cchName;
- Assert(pDirEntry->cbName == cchName);
- memcpy(pDirEntry->szName, pszName, cchName + 1);
- if (pDir->Data.cAlternateFileName[0])
- {
- /* copy and calc length */
- PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName;
- PRTUTF16 pwszDst = pDirEntry->wszShortName;
- uint32_t off = 0;
- while (pwszSrc[off] && off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U)
- {
- pwszDst[off] = pwszSrc[off];
- off++;
- }
- pDirEntry->cwcShortName = (uint16_t)off;
-
- /* zero the rest */
- do
- pwszDst[off++] = '\0';
- while (off < RT_ELEMENTS(pDirEntry->wszShortName));
- }
- else
- {
- memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
- pDirEntry->cwcShortName = 0;
- }
-
- pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32)
- | (uint64_t)pDir->Data.nFileSizeLow;
- pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject;
-
- Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime));
- RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime);
- RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime);
- RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime);
- pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime;
-
- pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
- pszName, cchName);
-
- /*
- * Requested attributes (we cannot provide anything actually).
- */
- switch (enmAdditionalAttribs)
- {
- case RTFSOBJATTRADD_EASIZE:
- pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
- pDirEntry->Info.Attr.u.EASize.cb = 0;
- break;
-
- case RTFSOBJATTRADD_UNIX:
- pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
- pDirEntry->Info.Attr.u.Unix.uid = ~0U;
- pDirEntry->Info.Attr.u.Unix.gid = ~0U;
- pDirEntry->Info.Attr.u.Unix.cHardlinks = 1;
- pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */
- pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */
- pDirEntry->Info.Attr.u.Unix.fFlags = 0;
- pDirEntry->Info.Attr.u.Unix.GenerationId = 0;
- pDirEntry->Info.Attr.u.Unix.Device = 0;
- break;
-
- case RTFSOBJATTRADD_NOTHING:
- pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
- break;
-
- case RTFSOBJATTRADD_UNIX_OWNER:
- pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER;
- pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U;
- pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */
- break;
-
- case RTFSOBJATTRADD_UNIX_GROUP:
- pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP;
- pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U;
- pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0';
- break;
-
- default:
- AssertMsgFailed(("Impossible!\n"));
- return VERR_INTERNAL_ERROR;
- }
-
- return VINF_SUCCESS;
-}
-
-
RTDECL(int) RTDirRename(const char *pszSrc, const char *pszDst, unsigned fRename)
{
/*
diff --git a/src/VBox/Runtime/r3/win/direnum-win.cpp b/src/VBox/Runtime/r3/win/direnum-win.cpp
new file mode 100644
index 00000000..acc98de3
--- /dev/null
+++ b/src/VBox/Runtime/r3/win/direnum-win.cpp
@@ -0,0 +1,389 @@
+/* $Id: direnum-win.cpp $ */
+/** @file
+ * IPRT - Directory Enumeration, Windows.
+ */
+
+/*
+ * 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;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#define LOG_GROUP RTLOGGROUP_DIR
+#include <Windows.h>
+
+#include <iprt/dir.h>
+#include <iprt/path.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/file.h>
+#include <iprt/log.h>
+#include "internal/fs.h"
+#include "internal/dir.h"
+
+
+size_t rtDirNativeGetStructSize(const char *pszPath)
+{
+ NOREF(pszPath);
+ return sizeof(RTDIR);
+}
+
+
+int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
+{
+ /*
+ * Setup the search expression.
+ *
+ * pszPathBuf is pointing to the return 4K return buffer for the RTPathReal()
+ * call in rtDirOpenCommon(), so all we gota do is check that we don't overflow
+ * it when adding the wildcard expression.
+ */
+ size_t cbExpr;
+ const char *pszExpr;
+ if (pDir->enmFilter == RTDIRFILTER_WINNT)
+ {
+ pszExpr = pDir->pszFilter;
+ cbExpr = pDir->cchFilter + 1;
+ }
+ else
+ {
+ pszExpr = "*";
+ cbExpr = sizeof("*");
+ }
+ if (pDir->cchPath + cbExpr > RTPATH_MAX)
+ return VERR_FILENAME_TOO_LONG;
+ memcpy(pszPathBuf + pDir->cchPath, pszExpr, cbExpr);
+
+
+ /*
+ * Attempt opening the search.
+ */
+ int rc = VINF_SUCCESS;
+ PRTUTF16 pwszName;
+ rc = RTStrToUtf16(pszPathBuf, &pwszName);
+ if (RT_SUCCESS(rc))
+ {
+ pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
+ if (pDir->hDir != INVALID_HANDLE_VALUE)
+ pDir->fDataUnread = true;
+ else
+ {
+ DWORD dwErr = GetLastError();
+ /* Theoretical case of an empty directory or more normal case of no matches. */
+ if ( dwErr == ERROR_FILE_NOT_FOUND
+ || dwErr == ERROR_NO_MORE_FILES /* ???*/)
+ pDir->fDataUnread = false;
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+ RTUtf16Free(pwszName);
+ }
+
+ return rc;
+}
+
+
+RTDECL(int) RTDirClose(PRTDIR pDir)
+{
+ /*
+ * Validate input.
+ */
+ if (!pDir)
+ return VERR_INVALID_PARAMETER;
+ if (pDir->u32Magic != RTDIR_MAGIC)
+ {
+ AssertMsgFailed(("Invalid pDir=%p\n", pDir));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ /*
+ * Close the handle.
+ */
+ pDir->u32Magic++;
+ if (pDir->hDir != INVALID_HANDLE_VALUE)
+ {
+ BOOL fRc = FindClose(pDir->hDir);
+ Assert(fRc);
+ pDir->hDir = INVALID_HANDLE_VALUE;
+ }
+ RTStrFree(pDir->pszName);
+ pDir->pszName = NULL;
+ RTMemFree(pDir);
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
+{
+ /*
+ * Validate input.
+ */
+ if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
+ {
+ AssertMsgFailed(("Invalid pDir=%p\n", pDir));
+ return VERR_INVALID_PARAMETER;
+ }
+ if (!pDirEntry)
+ {
+ AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
+ return VERR_INVALID_PARAMETER;
+ }
+ size_t cbDirEntry = sizeof(*pDirEntry);
+ if (pcbDirEntry)
+ {
+ cbDirEntry = *pcbDirEntry;
+ if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2]))
+ {
+ AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])));
+ return VERR_INVALID_PARAMETER;
+ }
+ }
+
+ /*
+ * Fetch data?
+ */
+ if (!pDir->fDataUnread)
+ {
+ RTStrFree(pDir->pszName);
+ pDir->pszName = NULL;
+
+ BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
+ if (!fRc)
+ {
+ int iErr = GetLastError();
+ if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
+ return VERR_NO_MORE_FILES;
+ return RTErrConvertFromWin32(iErr);
+ }
+ }
+
+ /*
+ * Convert the filename to UTF-8.
+ */
+ if (!pDir->pszName)
+ {
+ int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
+ if (RT_FAILURE(rc))
+ {
+ pDir->pszName = NULL;
+ return rc;
+ }
+ pDir->cchName = strlen(pDir->pszName);
+ }
+
+ /*
+ * Check if we've got enough space to return the data.
+ */
+ const char *pszName = pDir->pszName;
+ const size_t cchName = pDir->cchName;
+ const size_t cbRequired = RT_OFFSETOF(RTDIRENTRY, szName[1]) + cchName;
+ if (pcbDirEntry)
+ *pcbDirEntry = cbRequired;
+ if (cbRequired > cbDirEntry)
+ return VERR_BUFFER_OVERFLOW;
+
+ /*
+ * Setup the returned data.
+ */
+ pDir->fDataUnread = false;
+ pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */
+ pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
+ ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE;
+ pDirEntry->cbName = (uint16_t)cchName;
+ Assert(pDirEntry->cbName == cchName);
+ memcpy(pDirEntry->szName, pszName, cchName + 1);
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
+{
+ /** @todo Symlinks: Find[First|Next]FileW will return info about
+ the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
+ /*
+ * Validate input.
+ */
+ if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
+ {
+ AssertMsgFailed(("Invalid pDir=%p\n", pDir));
+ return VERR_INVALID_PARAMETER;
+ }
+ if (!pDirEntry)
+ {
+ AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
+ return VERR_INVALID_PARAMETER;
+ }
+ if ( enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
+ || enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
+ {
+ AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
+ return VERR_INVALID_PARAMETER;
+ }
+ AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
+ size_t cbDirEntry = sizeof(*pDirEntry);
+ if (pcbDirEntry)
+ {
+ cbDirEntry = *pcbDirEntry;
+ if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2]))
+ {
+ AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])));
+ return VERR_INVALID_PARAMETER;
+ }
+ }
+
+ /*
+ * Fetch data?
+ */
+ if (!pDir->fDataUnread)
+ {
+ RTStrFree(pDir->pszName);
+ pDir->pszName = NULL;
+
+ BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
+ if (!fRc)
+ {
+ int iErr = GetLastError();
+ if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
+ return VERR_NO_MORE_FILES;
+ return RTErrConvertFromWin32(iErr);
+ }
+ }
+
+ /*
+ * Convert the filename to UTF-8.
+ */
+ if (!pDir->pszName)
+ {
+ int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
+ if (RT_FAILURE(rc))
+ {
+ pDir->pszName = NULL;
+ return rc;
+ }
+ pDir->cchName = strlen(pDir->pszName);
+ }
+
+ /*
+ * Check if we've got enough space to return the data.
+ */
+ const char *pszName = pDir->pszName;
+ const size_t cchName = pDir->cchName;
+ const size_t cbRequired = RT_OFFSETOF(RTDIRENTRYEX, szName[1]) + cchName;
+ if (pcbDirEntry)
+ *pcbDirEntry = cbRequired;
+ if (cbRequired > cbDirEntry)
+ return VERR_BUFFER_OVERFLOW;
+
+ /*
+ * Setup the returned data.
+ */
+ pDir->fDataUnread = false;
+ pDirEntry->cbName = (uint16_t)cchName;
+ Assert(pDirEntry->cbName == cchName);
+ memcpy(pDirEntry->szName, pszName, cchName + 1);
+ if (pDir->Data.cAlternateFileName[0])
+ {
+ /* copy and calc length */
+ PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName;
+ PRTUTF16 pwszDst = pDirEntry->wszShortName;
+ uint32_t off = 0;
+ while (pwszSrc[off] && off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U)
+ {
+ pwszDst[off] = pwszSrc[off];
+ off++;
+ }
+ pDirEntry->cwcShortName = (uint16_t)off;
+
+ /* zero the rest */
+ do
+ pwszDst[off++] = '\0';
+ while (off < RT_ELEMENTS(pDirEntry->wszShortName));
+ }
+ else
+ {
+ memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
+ pDirEntry->cwcShortName = 0;
+ }
+
+ pDirEntry->Info.cbObject = ((uint64_t)pDir->Data.nFileSizeHigh << 32)
+ | (uint64_t)pDir->Data.nFileSizeLow;
+ pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject;
+
+ Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime));
+ RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, *(uint64_t *)&pDir->Data.ftCreationTime);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, *(uint64_t *)&pDir->Data.ftLastAccessTime);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, *(uint64_t *)&pDir->Data.ftLastWriteTime);
+ pDirEntry->Info.ChangeTime = pDirEntry->Info.ModificationTime;
+
+ pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
+ pszName, cchName);
+
+ /*
+ * Requested attributes (we cannot provide anything actually).
+ */
+ switch (enmAdditionalAttribs)
+ {
+ case RTFSOBJATTRADD_EASIZE:
+ pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
+ pDirEntry->Info.Attr.u.EASize.cb = 0;
+ break;
+
+ case RTFSOBJATTRADD_UNIX:
+ pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX;
+ pDirEntry->Info.Attr.u.Unix.uid = ~0U;
+ pDirEntry->Info.Attr.u.Unix.gid = ~0U;
+ pDirEntry->Info.Attr.u.Unix.cHardlinks = 1;
+ pDirEntry->Info.Attr.u.Unix.INodeIdDevice = 0; /** @todo Use the volume serial number (see GetFileInformationByHandle). */
+ pDirEntry->Info.Attr.u.Unix.INodeId = 0; /** @todo Use the fileid (see GetFileInformationByHandle). */
+ pDirEntry->Info.Attr.u.Unix.fFlags = 0;
+ pDirEntry->Info.Attr.u.Unix.GenerationId = 0;
+ pDirEntry->Info.Attr.u.Unix.Device = 0;
+ break;
+
+ case RTFSOBJATTRADD_NOTHING:
+ pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_NOTHING;
+ break;
+
+ case RTFSOBJATTRADD_UNIX_OWNER:
+ pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_OWNER;
+ pDirEntry->Info.Attr.u.UnixOwner.uid = ~0U;
+ pDirEntry->Info.Attr.u.UnixOwner.szName[0] = '\0'; /** @todo return something sensible here. */
+ break;
+
+ case RTFSOBJATTRADD_UNIX_GROUP:
+ pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_UNIX_GROUP;
+ pDirEntry->Info.Attr.u.UnixGroup.gid = ~0U;
+ pDirEntry->Info.Attr.u.UnixGroup.szName[0] = '\0';
+ break;
+
+ default:
+ AssertMsgFailed(("Impossible!\n"));
+ return VERR_INTERNAL_ERROR;
+ }
+
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Runtime/r3/win/dllmain-win.cpp b/src/VBox/Runtime/r3/win/dllmain-win.cpp
index 1646b39e..6efb702a 100644
--- a/src/VBox/Runtime/r3/win/dllmain-win.cpp
+++ b/src/VBox/Runtime/r3/win/dllmain-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/env-win.cpp b/src/VBox/Runtime/r3/win/env-win.cpp
new file mode 100644
index 00000000..030c6cd7
--- /dev/null
+++ b/src/VBox/Runtime/r3/win/env-win.cpp
@@ -0,0 +1,268 @@
+/* $Id: env-win.cpp $ */
+/** @file
+ * IPRT - Environment, Posix.
+ */
+
+/*
+ * Copyright (C) 2006-2014 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <iprt/env.h>
+
+#include <iprt/alloca.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/mem.h>
+
+#include <stdlib.h>
+#include <errno.h>
+
+
+RTDECL(bool) RTEnvExistsBad(const char *pszVar)
+{
+ return RTEnvGetBad(pszVar) != NULL;
+}
+
+
+RTDECL(bool) RTEnvExist(const char *pszVar)
+{
+ return RTEnvExistsBad(pszVar);
+}
+
+
+RTDECL(bool) RTEnvExistsUtf8(const char *pszVar)
+{
+ PRTUTF16 pwszVar;
+ int rc = RTStrToUtf16(pszVar, &pwszVar);
+ AssertRCReturn(rc, false);
+ bool fRet = _wgetenv(pwszVar) != NULL;
+ RTUtf16Free(pwszVar);
+ return fRet;
+}
+
+
+RTDECL(const char *) RTEnvGetBad(const char *pszVar)
+{
+ return getenv(pszVar);
+}
+
+
+RTDECL(const char *) RTEnvGet(const char *pszVar)
+{
+ return RTEnvGetBad(pszVar);
+}
+
+RTDECL(int) RTEnvGetUtf8(const char *pszVar, char *pszValue, size_t cbValue, size_t *pcchActual)
+{
+ AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(pszValue, VERR_INVALID_POINTER);
+ AssertReturn(pszValue || !cbValue, VERR_INVALID_PARAMETER);
+ AssertPtrNullReturn(pcchActual, VERR_INVALID_POINTER);
+ AssertReturn(pcchActual || (pszValue && cbValue), VERR_INVALID_PARAMETER);
+
+ if (pcchActual)
+ *pcchActual = 0;
+
+ PRTUTF16 pwszVar;
+ int rc = RTStrToUtf16(pszVar, &pwszVar);
+ AssertRCReturn(rc, false);
+
+ /** @todo Consider _wgetenv_s or GetEnvironmentVariableW here to avoid the
+ * potential race with a concurrent _wputenv/_putenv. */
+ PCRTUTF16 pwszValue = _wgetenv(pwszVar);
+ RTUtf16Free(pwszVar);
+ if (pwszValue)
+ {
+ if (cbValue)
+ rc = RTUtf16ToUtf8Ex(pwszValue, RTSTR_MAX, &pszValue, cbValue, pcchActual);
+ else
+ rc = RTUtf16CalcUtf8LenEx(pwszValue, RTSTR_MAX, pcchActual);
+ }
+ else
+ rc = VERR_ENV_VAR_NOT_FOUND;
+ return rc;
+}
+
+
+RTDECL(int) RTEnvPutBad(const char *pszVarEqualValue)
+{
+ /** @todo putenv is a source memory leaks. deal with this on a per system basis. */
+ if (!putenv((char *)pszVarEqualValue))
+ return 0;
+ return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
+{
+ return RTEnvPutBad(pszVarEqualValue);
+}
+
+
+RTDECL(int) RTEnvPutUtf8(const char *pszVarEqualValue)
+{
+ PRTUTF16 pwszVarEqualValue;
+ int rc = RTStrToUtf16(pszVarEqualValue, &pwszVarEqualValue);
+ if (RT_SUCCESS(rc))
+ {
+ if (!_wputenv(pwszVarEqualValue))
+ rc = VINF_SUCCESS;
+ else
+ rc = RTErrConvertFromErrno(errno);
+ RTUtf16Free(pwszVarEqualValue);
+ }
+ return rc;
+}
+
+
+
+RTDECL(int) RTEnvSetBad(const char *pszVar, const char *pszValue)
+{
+ /* make a local copy and feed it to putenv. */
+ const size_t cchVar = strlen(pszVar);
+ const size_t cchValue = strlen(pszValue);
+ char *pszTmp = (char *)alloca(cchVar + cchValue + 2 + !*pszValue);
+ memcpy(pszTmp, pszVar, cchVar);
+ pszTmp[cchVar] = '=';
+ if (*pszValue)
+ memcpy(pszTmp + cchVar + 1, pszValue, cchValue + 1);
+ else
+ {
+ pszTmp[cchVar + 1] = ' '; /* wrong, but putenv will remove it otherwise. */
+ pszTmp[cchVar + 2] = '\0';
+ }
+
+ if (!putenv(pszTmp))
+ return 0;
+ return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
+{
+ return RTEnvSetBad(pszVar, pszValue);
+}
+
+RTDECL(int) RTEnvSetUtf8(const char *pszVar, const char *pszValue)
+{
+ size_t cwcVar;
+ int rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcVar);
+ if (RT_SUCCESS(rc))
+ {
+ size_t cwcValue;
+ rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcValue);
+ if (RT_SUCCESS(rc))
+ {
+ PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAlloc((cwcVar + 1 + cwcValue + 1) * sizeof(RTUTF16));
+ if (pwszTmp)
+ {
+ rc = RTStrToUtf16Ex(pszVar, RTSTR_MAX, &pwszTmp, cwcVar + 1, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ PRTUTF16 pwszTmpValue = &pwszTmp[cwcVar];
+ *pwszTmpValue++ = '=';
+ rc = RTStrToUtf16Ex(pszValue, RTSTR_MAX, &pwszTmpValue, cwcValue + 1, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ if (!_wputenv(pwszTmp))
+ rc = VINF_SUCCESS;
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+ }
+ RTMemTmpFree(pwszTmp);
+ }
+ else
+ rc = VERR_NO_TMP_MEMORY;
+ }
+ }
+ return rc;
+}
+
+
+RTDECL(int) RTEnvUnsetBad(const char *pszVar)
+{
+ AssertReturn(!strchr(pszVar, '='), VERR_INVALID_PARAMETER);
+
+ /*
+ * Check that it exists first.
+ */
+ if (!RTEnvExist(pszVar))
+ return VINF_ENV_VAR_NOT_FOUND;
+
+ /*
+ * Ok, try remove it.
+ */
+#ifdef RT_OS_WINDOWS
+ /* Use putenv(var=) since Windows does not have unsetenv(). */
+ size_t cchVar = strlen(pszVar);
+ char *pszBuf = (char *)alloca(cchVar + 2);
+ memcpy(pszBuf, pszVar, cchVar);
+ pszBuf[cchVar] = '=';
+ pszBuf[cchVar + 1] = '\0';
+
+ if (!putenv(pszBuf))
+ return VINF_SUCCESS;
+
+#else
+ /* This is the preferred function as putenv() like used above does neither work on Solaris nor on Darwin. */
+ if (!unsetenv((char*)pszVar))
+ return VINF_SUCCESS;
+#endif
+
+ return RTErrConvertFromErrno(errno);
+}
+
+
+RTDECL(int) RTEnvUnset(const char *pszVar)
+{
+ return RTEnvUnsetBad(pszVar);
+}
+
+
+RTDECL(int) RTEnvUnsetUtf8(const char *pszVar)
+{
+ size_t cwcVar;
+ int rc = RTStrCalcUtf16LenEx(pszVar, RTSTR_MAX, &cwcVar);
+ if (RT_SUCCESS(rc))
+ {
+ PRTUTF16 pwszTmp = (PRTUTF16)RTMemTmpAlloc((cwcVar + 1 + 1) * sizeof(RTUTF16));
+ if (pwszTmp)
+ {
+ rc = RTStrToUtf16Ex(pszVar, RTSTR_MAX, &pwszTmp, cwcVar + 1, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ pwszTmp[cwcVar] = '=';
+ pwszTmp[cwcVar + 1] = '\0';
+ if (!_wputenv(pwszTmp))
+ rc = VINF_SUCCESS;
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+ RTMemTmpFree(pwszTmp);
+ }
+ }
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/win/fileaio-win.cpp b/src/VBox/Runtime/r3/win/fileaio-win.cpp
index 95e20e12..73c99a7e 100644
--- a/src/VBox/Runtime/r3/win/fileaio-win.cpp
+++ b/src/VBox/Runtime/r3/win/fileaio-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 Oracle Corporation
+ * Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -72,6 +72,8 @@ typedef struct RTFILEAIOCTXINTERNAL
volatile bool fWokenUp;
/** Flag whether the thread is currently waiting. */
volatile bool fWaiting;
+ /** Flags given during creation. */
+ uint32_t fFlags;
/** Magic value (RTFILEAIOCTX_MAGIC). */
uint32_t u32Magic;
} RTFILEAIOCTXINTERNAL;
@@ -266,10 +268,12 @@ RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
return rc;
}
-RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
+RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax,
+ uint32_t fFlags)
{
PRTFILEAIOCTXINTERNAL pCtxInt;
AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER);
+ AssertReturn(!(fFlags & ~RTFILEAIOCTX_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
pCtxInt = (PRTFILEAIOCTXINTERNAL)RTMemAllocZ(sizeof(RTFILEAIOCTXINTERNAL));
if (RT_UNLIKELY(!pCtxInt))
@@ -285,7 +289,8 @@ RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
return VERR_NO_MEMORY;
}
- pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
+ pCtxInt->fFlags = fFlags;
+ pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
*phAioCtx = (RTFILEAIOCTX)pCtxInt;
@@ -398,7 +403,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL
/*
* Can't wait if there are no requests around.
*/
- if (RT_UNLIKELY(ASMAtomicUoReadS32(&pCtxInt->cRequests) == 0))
+ if ( RT_UNLIKELY(ASMAtomicUoReadS32(&pCtxInt->cRequests) == 0)
+ && !(pCtxInt->fFlags & RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS))
return VERR_FILE_AIO_NO_REQUEST;
/* Wait for at least one. */
diff --git a/src/VBox/Runtime/r3/win/fs-win.cpp b/src/VBox/Runtime/r3/win/fs-win.cpp
index c0fa65c3..586444e4 100644
--- a/src/VBox/Runtime/r3/win/fs-win.cpp
+++ b/src/VBox/Runtime/r3/win/fs-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -319,6 +319,9 @@ RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProper
pProperties->fReadOnly = !!(dwFlags & FILE_READ_ONLY_VOLUME);
pProperties->fSupportsUnicode = !!(dwFlags & FILE_UNICODE_ON_DISK);
pProperties->fCaseSensitive = false; /* win32 is case preserving only */
+ /** @todo r=bird: What about FILE_CASE_SENSITIVE_SEARCH ? Is this set for NTFS
+ * as well perchance? If so, better mention it instead of just setting
+ * fCaseSensitive to false. */
pProperties->fRemote = false; /* no idea yet */
}
else
diff --git a/src/VBox/Runtime/r3/win/init-win.cpp b/src/VBox/Runtime/r3/win/init-win.cpp
new file mode 100644
index 00000000..e40adf6a
--- /dev/null
+++ b/src/VBox/Runtime/r3/win/init-win.cpp
@@ -0,0 +1,273 @@
+/* $Id: init-win.cpp $ */
+/** @file
+ * IPRT - Init Ring-3, Windows Specific Code.
+ */
+
+/*
+ * 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;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#define LOG_GROUP RTLOGGROUP_DEFAULT
+#include <Windows.h>
+#ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
+# define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x200
+# define LOAD_LIBRARY_SEARCH_SYSTEM32 0x800
+#endif
+
+#include "internal-r3-win.h"
+#include <iprt/initterm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+#include "../init.h"
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+/** Windows DLL loader protection level. */
+DECLHIDDEN(RTR3WINLDRPROT) g_enmWinLdrProt = RTR3WINLDRPROT_NONE;
+/** Our simplified windows version. */
+DECLHIDDEN(RTWINOSTYPE) g_enmWinVer = kRTWinOSType_UNKNOWN;
+/** Extended windows version information. */
+DECLHIDDEN(OSVERSIONINFOEX) g_WinOsInfoEx;
+/** The native kernel32.dll handle. */
+DECLHIDDEN(HMODULE) g_hModKernel32 = NULL;
+/** The native ntdll.dll handle. */
+DECLHIDDEN(HMODULE) g_hModNtDll = NULL;
+
+
+
+/**
+ * Translates OSVERSIONINOFEX into a Windows OS type.
+ *
+ * @returns The Windows OS type.
+ * @param pOSInfoEx The OS info returned by Windows.
+ *
+ * @remarks This table has been assembled from Usenet postings, personal
+ * observations, and reading other people's code. Please feel
+ * free to add to it or correct it.
+ * <pre>
+ dwPlatFormID dwMajorVersion dwMinorVersion dwBuildNumber
+95 1 4 0 950
+95 SP1 1 4 0 >950 && <=1080
+95 OSR2 1 4 <10 >1080
+98 1 4 10 1998
+98 SP1 1 4 10 >1998 && <2183
+98 SE 1 4 10 >=2183
+ME 1 4 90 3000
+
+NT 3.51 2 3 51 1057
+NT 4 2 4 0 1381
+2000 2 5 0 2195
+XP 2 5 1 2600
+2003 2 5 2 3790
+Vista 2 6 0
+
+CE 1.0 3 1 0
+CE 2.0 3 2 0
+CE 2.1 3 2 1
+CE 3.0 3 3 0
+</pre>
+ */
+static RTWINOSTYPE rtR3InitWinSimplifiedVersion(OSVERSIONINFOEX const *pOSInfoEx)
+{
+ RTWINOSTYPE enmVer = kRTWinOSType_UNKNOWN;
+ BYTE const bProductType = pOSInfoEx->wProductType;
+ DWORD const dwPlatformId = pOSInfoEx->dwPlatformId;
+ DWORD const dwMinorVersion = pOSInfoEx->dwMinorVersion;
+ DWORD const dwMajorVersion = pOSInfoEx->dwMajorVersion;
+ DWORD const dwBuildNumber = pOSInfoEx->dwBuildNumber & 0xFFFF; /* Win 9x needs this. */
+
+ if ( dwPlatformId == VER_PLATFORM_WIN32_WINDOWS
+ && dwMajorVersion == 4)
+ {
+ if ( dwMinorVersion < 10
+ && dwBuildNumber == 950)
+ enmVer = kRTWinOSType_95;
+ else if ( dwMinorVersion < 10
+ && dwBuildNumber > 950
+ && dwBuildNumber <= 1080)
+ enmVer = kRTWinOSType_95SP1;
+ else if ( dwMinorVersion < 10
+ && dwBuildNumber > 1080)
+ enmVer = kRTWinOSType_95OSR2;
+ else if ( dwMinorVersion == 10
+ && dwBuildNumber == 1998)
+ enmVer = kRTWinOSType_98;
+ else if ( dwMinorVersion == 10
+ && dwBuildNumber > 1998
+ && dwBuildNumber < 2183)
+ enmVer = kRTWinOSType_98SP1;
+ else if ( dwMinorVersion == 10
+ && dwBuildNumber >= 2183)
+ enmVer = kRTWinOSType_98SE;
+ else if (dwMinorVersion == 90)
+ enmVer = kRTWinOSType_ME;
+ }
+ else if (dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ if ( dwMajorVersion == 3
+ && dwMinorVersion == 51)
+ enmVer = kRTWinOSType_NT351;
+ else if ( dwMajorVersion == 4
+ && dwMinorVersion == 0)
+ enmVer = kRTWinOSType_NT4;
+ else if ( dwMajorVersion == 5
+ && dwMinorVersion == 0)
+ enmVer = kRTWinOSType_2K;
+ else if ( dwMajorVersion == 5
+ && dwMinorVersion == 1)
+ enmVer = kRTWinOSType_XP;
+ else if ( dwMajorVersion == 5
+ && dwMinorVersion == 2)
+ enmVer = kRTWinOSType_2003;
+ else if ( dwMajorVersion == 6
+ && dwMinorVersion == 0)
+ {
+ if (bProductType != VER_NT_WORKSTATION)
+ enmVer = kRTWinOSType_2008;
+ else
+ enmVer = kRTWinOSType_VISTA;
+ }
+ else if ( dwMajorVersion == 6
+ && dwMinorVersion == 1)
+ enmVer = kRTWinOSType_7;
+ else if ( dwMajorVersion == 6
+ && dwMinorVersion == 2)
+ enmVer = kRTWinOSType_8;
+ else if ( dwMajorVersion == 6
+ && dwMinorVersion == 3)
+ enmVer = kRTWinOSType_81;
+ else
+ enmVer = kRTWinOSType_NT_UNKNOWN;
+ }
+
+ return enmVer;
+}
+
+
+DECLHIDDEN(int) rtR3InitNativeObtrusiveWorker(void)
+{
+ /*
+ * Disable error popups.
+ */
+ UINT fOldErrMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
+ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX | fOldErrMode);
+
+ /*
+ * Query the Windows version.
+ * ASSUMES OSVERSIONINFOEX starts with the exact same layout as OSVERSIONINFO (safe).
+ */
+ AssertCompileMembersSameSizeAndOffset(OSVERSIONINFOEX, szCSDVersion, OSVERSIONINFO, szCSDVersion);
+ AssertCompileMemberOffset(OSVERSIONINFOEX, wServicePackMajor, sizeof(OSVERSIONINFO));
+ RT_ZERO(g_WinOsInfoEx);
+ g_WinOsInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if (!GetVersionExA((POSVERSIONINFOA)&g_WinOsInfoEx))
+ {
+ /* Fallback, just get the basic info. */
+ RT_ZERO(g_WinOsInfoEx);
+ g_WinOsInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (GetVersionExA((POSVERSIONINFOA)&g_WinOsInfoEx))
+ Assert(g_WinOsInfoEx.dwPlatformId != VER_PLATFORM_WIN32_NT || g_WinOsInfoEx.dwMajorVersion < 5);
+ else
+ {
+ AssertBreakpoint();
+ RT_ZERO(g_WinOsInfoEx);
+ }
+ }
+ if (g_WinOsInfoEx.dwOSVersionInfoSize)
+ g_enmWinVer = rtR3InitWinSimplifiedVersion(&g_WinOsInfoEx);
+
+ /*
+ * Restrict DLL searching for the process on windows versions which allow
+ * us to do so.
+ * - The first trick works on XP SP1+ and disables the searching of the
+ * current directory.
+ * - The second trick is W7 w/ KB2533623 and W8+, it restrict the DLL
+ * searching to the application directory and the System32 directory.
+ */
+ int rc = VINF_SUCCESS;
+
+ typedef BOOL (WINAPI *PFNSETDLLDIRECTORY)(LPCWSTR);
+ PFNSETDLLDIRECTORY pfnSetDllDir = (PFNSETDLLDIRECTORY)GetProcAddress(g_hModKernel32, "SetDllDirectoryW");
+ if (pfnSetDllDir)
+ {
+ if (pfnSetDllDir(L""))
+ g_enmWinLdrProt = RTR3WINLDRPROT_NO_CWD;
+ else
+ rc = VERR_INTERNAL_ERROR_3;
+ }
+
+ /** @bugref 6861: Observed GUI issues on Vista (32-bit and 64-bit). */
+ if (g_enmWinVer > kRTWinOSType_VISTA)
+ {
+ typedef BOOL(WINAPI *PFNSETDEFAULTDLLDIRECTORIES)(DWORD);
+ PFNSETDEFAULTDLLDIRECTORIES pfnSetDefDllDirs;
+ pfnSetDefDllDirs = (PFNSETDEFAULTDLLDIRECTORIES)GetProcAddress(g_hModKernel32, "SetDefaultDllDirectories");
+ if (pfnSetDefDllDirs)
+ {
+ if (pfnSetDefDllDirs(LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32))
+ g_enmWinLdrProt = RTR3WINLDRPROT_SAFE;
+ else if (RT_SUCCESS(rc))
+ rc = VERR_INTERNAL_ERROR_4;
+ }
+ }
+
+ return rc;
+}
+
+
+DECLHIDDEN(int) rtR3InitNativeFirst(uint32_t fFlags)
+{
+ /*
+ * Make sure we've got the handles of the two main Windows NT dlls.
+ */
+ g_hModKernel32 = GetModuleHandleW(L"kernel32.dll");
+ if (g_hModKernel32 == NULL)
+ return VERR_INTERNAL_ERROR_2;
+ g_hModNtDll = GetModuleHandleW(L"ntdll.dll");
+ if (g_hModNtDll == NULL)
+ return VERR_INTERNAL_ERROR_2;
+
+ int rc = VINF_SUCCESS;
+ if (!(fFlags & RTR3INIT_FLAGS_UNOBTRUSIVE))
+ rc = rtR3InitNativeObtrusiveWorker();
+
+ return rc;
+}
+
+
+DECLHIDDEN(void) rtR3InitNativeObtrusive(void)
+{
+ rtR3InitNativeObtrusiveWorker();
+}
+
+
+DECLHIDDEN(int) rtR3InitNativeFinal(uint32_t fFlags)
+{
+ /* Nothing to do here. */
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Runtime/r3/win/internal-r3-win.h b/src/VBox/Runtime/r3/win/internal-r3-win.h
new file mode 100644
index 00000000..efec00a1
--- /dev/null
+++ b/src/VBox/Runtime/r3/win/internal-r3-win.h
@@ -0,0 +1,72 @@
+
+#ifndef ___internal_r3_win_h
+#define ___internal_r3_win_h
+
+#include "internal/iprt.h"
+#include <iprt/types.h>
+
+
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
+/**
+ * Windows OS type as determined by rtSystemWinOSType().
+ *
+ * @note ASSUMPTIONS are made regarding ordering. Win 9x should come first, then
+ * NT. The Win9x and NT versions should internally be ordered in ascending
+ * version/code-base order.
+ */
+typedef enum RTWINOSTYPE
+{
+ kRTWinOSType_UNKNOWN = 0,
+ kRTWinOSType_9XFIRST = 1,
+ kRTWinOSType_95 = kRTWinOSType_9XFIRST,
+ kRTWinOSType_95SP1,
+ kRTWinOSType_95OSR2,
+ kRTWinOSType_98,
+ kRTWinOSType_98SP1,
+ kRTWinOSType_98SE,
+ kRTWinOSType_ME,
+ kRTWinOSType_9XLAST = 99,
+ kRTWinOSType_NTFIRST = 100,
+ kRTWinOSType_NT31 = kRTWinOSType_NTFIRST,
+ kRTWinOSType_NT351,
+ kRTWinOSType_NT4,
+ kRTWinOSType_2K,
+ kRTWinOSType_XP,
+ kRTWinOSType_2003,
+ kRTWinOSType_VISTA,
+ kRTWinOSType_2008,
+ kRTWinOSType_7,
+ kRTWinOSType_8,
+ kRTWinOSType_81,
+ kRTWinOSType_NT_UNKNOWN = 199,
+ kRTWinOSType_NT_LAST = kRTWinOSType_UNKNOWN
+} RTWINOSTYPE;
+
+/**
+ * Windows loader protection level.
+ */
+typedef enum RTR3WINLDRPROT
+{
+ RTR3WINLDRPROT_INVALID = 0,
+ RTR3WINLDRPROT_NONE,
+ RTR3WINLDRPROT_NO_CWD,
+ RTR3WINLDRPROT_SAFE
+} RTR3WINLDRPROT;
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+extern DECLHIDDEN(RTR3WINLDRPROT) g_enmWinLdrProt;
+extern DECLHIDDEN(RTWINOSTYPE) g_enmWinVer;
+#ifdef _WINDEF_
+extern DECLHIDDEN(HMODULE) g_hModKernel32;
+extern DECLHIDDEN(HMODULE) g_hModNtDll;
+extern DECLHIDDEN(OSVERSIONINFOEX) g_WinOsInfoEx;
+#endif
+
+
+#endif
+
diff --git a/src/VBox/Runtime/r3/win/ldrNative-win.cpp b/src/VBox/Runtime/r3/win/ldrNative-win.cpp
index 54016958..8b26ab2c 100644
--- a/src/VBox/Runtime/r3/win/ldrNative-win.cpp
+++ b/src/VBox/Runtime/r3/win/ldrNative-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 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;
@@ -31,10 +31,17 @@
#include <Windows.h>
#include <iprt/ldr.h>
+#include "internal/iprt.h"
+
+#include <iprt/alloca.h>
#include <iprt/assert.h>
-#include <iprt/path.h>
#include <iprt/err.h>
-#include <iprt/alloca.h>
+#include <iprt/file.h>
+#include <iprt/log.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+
+#include <iprt/once.h>
#include <iprt/string.h>
#include "internal/ldr.h"
@@ -42,7 +49,10 @@
int rtldrNativeLoad(const char *pszFilename, uintptr_t *phHandle, uint32_t fFlags, PRTERRINFO pErrInfo)
{
Assert(sizeof(*phHandle) >= sizeof(HMODULE));
- AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER);
+ AssertReturn(fFlags == 0 || fFlags == RTLDRLOAD_FLAGS_NO_UNLOAD, VERR_INVALID_PARAMETER);
+ AssertLogRelMsgReturn(RTPathStartsWithRoot(pszFilename), /* Relative names will still be applied to the search path. */
+ ("pszFilename='%s'\n", pszFilename),
+ VERR_INTERNAL_ERROR_2);
/*
* Do we need to add an extension?
@@ -72,7 +82,7 @@ int rtldrNativeLoad(const char *pszFilename, uintptr_t *phHandle, uint32_t fFlag
* Try figure why it failed to load.
*/
DWORD dwErr = GetLastError();
- int rc = RTErrConvertFromWin32(dwErr);
+ int rc = RTErrConvertFromWin32(dwErr);
return RTErrInfoSetF(pErrInfo, rc, "GetLastError=%u", dwErr);
}
@@ -94,7 +104,8 @@ DECLCALLBACK(int) rtldrNativeGetSymbol(PRTLDRMODINTERNAL pMod, const char *pszSy
DECLCALLBACK(int) rtldrNativeClose(PRTLDRMODINTERNAL pMod)
{
PRTLDRMODNATIVE pModNative = (PRTLDRMODNATIVE)pMod;
- if (FreeLibrary((HMODULE)pModNative->hNative))
+ if ( (pModNative->fFlags & RTLDRLOAD_FLAGS_NO_UNLOAD)
+ || FreeLibrary((HMODULE)pModNative->hNative))
{
pModNative->hNative = (uintptr_t)INVALID_HANDLE_VALUE;
return VINF_SUCCESS;
@@ -102,3 +113,34 @@ DECLCALLBACK(int) rtldrNativeClose(PRTLDRMODINTERNAL pMod)
return RTErrConvertFromWin32(GetLastError());
}
+
+int rtldrNativeLoadSystem(const char *pszFilename, const char *pszExt, uint32_t fFlags, PRTLDRMOD phLdrMod)
+{
+ /*
+ * We only try the System32 directory.
+ */
+ WCHAR wszSysDir[MAX_PATH];
+ UINT cwcSysDir = GetSystemDirectoryW(wszSysDir, MAX_PATH);
+ if (cwcSysDir >= MAX_PATH)
+ return VERR_FILENAME_TOO_LONG;
+
+ char szPath[RTPATH_MAX];
+ char *pszPath = szPath;
+ int rc = RTUtf16ToUtf8Ex(wszSysDir, RTSTR_MAX, &pszPath, sizeof(szPath), NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTPathAppend(szPath, sizeof(szPath), pszFilename);
+ if (pszExt && RT_SUCCESS(rc))
+ rc = RTStrCat(szPath, sizeof(szPath), pszExt);
+ if (RT_SUCCESS(rc))
+ {
+ if (RTFileExists(szPath))
+ rc = RTLdrLoadEx(szPath, phLdrMod, fFlags, NULL);
+ else
+ rc = VERR_MODULE_NOT_FOUND;
+ }
+ }
+
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/win/localipc-win.cpp b/src/VBox/Runtime/r3/win/localipc-win.cpp
index 15ff6f8b..a25b9cac 100644
--- a/src/VBox/Runtime/r3/win/localipc-win.cpp
+++ b/src/VBox/Runtime/r3/win/localipc-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-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;
@@ -41,15 +41,17 @@
#include <Windows.h>
#include <sddl.h>
-#include <iprt/localipc.h>
-#include <iprt/thread.h>
-#include <iprt/critsect.h>
#include <iprt/alloc.h>
+#include <iprt/asm.h>
#include <iprt/assert.h>
-#include <iprt/param.h>
+#include <iprt/critsect.h>
#include <iprt/err.h>
+#include <iprt/ldr.h>
+#include <iprt/localipc.h>
+#include <iprt/param.h>
#include <iprt/string.h>
-#include <iprt/asm.h>
+#include <iprt/thread.h>
+#include <iprt/time.h>
#include "internal/magics.h"
@@ -66,7 +68,9 @@
*
* Note! FILE_GENERIC_WRITE (SDDL_FILE_WRITE) is evil here because it includes
* the FILE_CREATE_PIPE_INSTANCE(=FILE_APPEND_DATA) flag. Thus the hardcoded
- * value 0x0012019b in the 2nd ACE. It expands to:
+ * value 0x0012019b in the client ACE. The server-side still needs
+ * setting FILE_CREATE_PIPE_INSTANCE although.
+ * It expands to:
* 0x00000001 - FILE_READ_DATA
* 0x00000008 - FILE_READ_EA
* 0x00000080 - FILE_READ_ATTRIBUTES
@@ -75,11 +79,12 @@
* 0x00000002 - FILE_WRITE_DATA
* 0x00000010 - FILE_WRITE_EA
* 0x00000100 - FILE_WRITE_ATTRIBUTES
- * 0x0012019b
- * or FILE_GENERIC_READ | (FILE_GENERIC_WRITE & ~FILE_CREATE_PIPE_INSTANCE)
+ * = 0x0012019b (client)
+ * + (only for server):
+ * 0x00000004 - FILE_CREATE_PIPE_INSTANCE
+ * = 0x0012019f
*
- * @todo Double check this!
- * @todo Drop the EA rights too? Since they doesn't mean anything to PIPS according to the docs.
+ * @todo Triple check this!
* @todo EVERYONE -> AUTHENTICATED USERS or something more appropriate?
* @todo Have trouble allowing the owner FILE_CREATE_PIPE_INSTANCE access, so for now I'm hacking
* it just to get progress - the service runs as local system.
@@ -88,12 +93,19 @@
* is to go the annoying route of OpenProcessToken, QueryTokenInformation,
* ConvertSidToStringSid and then use the result... Suggestions are very welcome
*/
-#define RTLOCALIPC_WIN_SDDL \
- SDDL_DACL SDDL_DELIMINATOR \
+#define RTLOCALIPC_WIN_SDDL_BASE \
+ SDDL_DACL SDDL_DELIMINATOR \
SDDL_ACE_BEGIN SDDL_ACCESS_DENIED ";;" SDDL_GENERIC_ALL ";;;" SDDL_NETWORK SDDL_ACE_END \
- SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED ";;" "0x0012019b" ";;;" SDDL_EVERYONE SDDL_ACE_END \
SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED ";;" SDDL_FILE_ALL ";;;" SDDL_LOCAL_SYSTEM SDDL_ACE_END
+#define RTLOCALIPC_WIN_SDDL_SERVER \
+ RTLOCALIPC_WIN_SDDL_BASE \
+ SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED ";;" "0x0012019f" ";;;" SDDL_EVERYONE SDDL_ACE_END
+
+#define RTLOCALIPC_WIN_SDDL_CLIENT \
+ RTLOCALIPC_WIN_SDDL_BASE \
+ SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED ";;" "0x0012019b" ";;;" SDDL_EVERYONE SDDL_ACE_END
+
// SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED ";;" SDDL_GENERIC_ALL ";;;" SDDL_PERSONAL_SELF SDDL_ACE_END \
// SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED ";CIOI;" SDDL_GENERIC_ALL ";;;" SDDL_CREATOR_OWNER SDDL_ACE_END
// SDDL_ACE_BEGIN SDDL_ACCESS_ALLOWED ";;" "0x0012019b" ";;;" SDDL_EVERYONE SDDL_ACE_END
@@ -138,24 +150,41 @@ typedef RTLOCALIPCSERVERINT *PRTLOCALIPCSERVERINT;
typedef struct RTLOCALIPCSESSIONINT
{
/** The magic (RTLOCALIPCSESSION_MAGIC). */
- uint32_t u32Magic;
+ uint32_t u32Magic;
/** Critical section protecting the structure. */
- RTCRITSECT CritSect;
+ RTCRITSECT CritSect;
/** The number of references to the instance.
* @remarks The reference counting isn't race proof. */
- uint32_t volatile cRefs;
+ uint32_t volatile cRefs;
+ /** Set if there is already pending I/O. */
+ bool fIOPending;
+ /** Set if the zero byte read that the poll code using is pending. */
+ bool fZeroByteRead;
/** Indicates that there is a pending cancel request. */
- bool volatile fCancelled;
+ bool volatile fCancelled;
/** The name pipe handle. */
- HANDLE hNmPipe;
+ HANDLE hNmPipe;
/** The handle to the event object we're using for overlapped I/O. */
- HANDLE hEvent;
+ HANDLE hEvent;
/** The overlapped I/O structure. */
- OVERLAPPED OverlappedIO;
+ OVERLAPPED OverlappedIO;
+ /** Bounce buffer for writes. */
+ uint8_t *pbBounceBuf;
+ /** Amount of used buffer space. */
+ size_t cbBounceBufUsed;
+ /** Amount of allocated buffer space. */
+ size_t cbBounceBufAlloc;
+ /** Buffer for the zero byte read.
+ * Used in RTLocalIpcSessionWaitForData(). */
+ uint8_t abBuf[8];
} RTLOCALIPCSESSIONINT;
/** Pointer to a local IPC session instance (Windows). */
typedef RTLOCALIPCSESSIONINT *PRTLOCALIPCSESSIONINT;
+typedef BOOL WINAPI FNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR(LPCTSTR, DWORD, PSECURITY_DESCRIPTOR, PULONG);
+typedef FNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR
+ *PFNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR; /* No, nobody fell on the keyboard, really! */
+
/*******************************************************************************
* Internal Functions *
@@ -164,52 +193,124 @@ static int rtLocalIpcWinCreateSession(PRTLOCALIPCSESSION phClientSession, HANDLE
/**
+ * Builds and allocates the security descriptor required for securing the local pipe.
+ *
+ * @return IPRT status code.
+ * @param ppDesc Where to store the allocated security descriptor on success.
+ * Must be free'd using LocalFree().
+ */
+static int rtLocalIpcServerWinAllocSecurityDescriptior(PSECURITY_DESCRIPTOR *ppDesc, bool fServer)
+{
+ /** @todo Stuff this into RTInitOnce? Later. */
+ PFNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR
+ pfnConvertStringSecurityDescriptorToSecurityDescriptor = NULL;
+
+ RTLDRMOD hAdvApi32 = NIL_RTLDRMOD;
+ int rc = RTLdrLoadSystem("Advapi32.dll", true /*fNoUnload*/, &hAdvApi32);
+ if (RT_SUCCESS(rc))
+ rc = RTLdrGetSymbol(hAdvApi32, "ConvertStringSecurityDescriptorToSecurityDescriptorW",
+ (void**)&pfnConvertStringSecurityDescriptorToSecurityDescriptor);
+
+ PSECURITY_DESCRIPTOR pSecDesc = NULL;
+ if (RT_SUCCESS(rc))
+ {
+ AssertPtr(pfnConvertStringSecurityDescriptorToSecurityDescriptor);
+
+ /*
+ * We'll create a security descriptor from a SDDL that denies
+ * access to network clients (this is local IPC after all), it
+ * makes some further restrictions to prevent non-authenticated
+ * users from screwing around.
+ */
+ PRTUTF16 pwszSDDL;
+ rc = RTStrToUtf16(fServer
+ ? RTLOCALIPC_WIN_SDDL_SERVER : RTLOCALIPC_WIN_SDDL_CLIENT, &pwszSDDL);
+ if (RT_SUCCESS(rc))
+ {
+ if (!pfnConvertStringSecurityDescriptorToSecurityDescriptor((LPCTSTR)pwszSDDL,
+ SDDL_REVISION_1,
+ &pSecDesc,
+ NULL))
+ {
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+
+ RTUtf16Free(pwszSDDL);
+ }
+ }
+ else
+ {
+ /* Windows OSes < W2K SP2 not supported for now, bail out. */
+ /** @todo Implement me! */
+ rc = VERR_NOT_SUPPORTED;
+ }
+
+ if (hAdvApi32 != NIL_RTLDRMOD)
+ RTLdrClose(hAdvApi32);
+
+ if (RT_SUCCESS(rc))
+ {
+ AssertPtr(pSecDesc);
+ *ppDesc = pSecDesc;
+ }
+
+ return rc;
+}
+
+/**
* Creates a named pipe instance.
*
* This is used by both RTLocalIpcServerCreate and RTLocalIpcServerListen.
*
- * @returns Windows error code, that is NO_ERROR and *phNmPipe on success and some ERROR_* on failure.
- *
+ * @return IPRT status code.
* @param phNmPipe Where to store the named pipe handle on success. This
* will be set to INVALID_HANDLE_VALUE on failure.
* @param pszFullPipeName The full named pipe name.
* @param fFirst Set on the first call (from RTLocalIpcServerCreate), otherwise clear.
* Governs the FILE_FLAG_FIRST_PIPE_INSTANCE flag.
*/
-static DWORD rtLocalIpcServerWinCreatePipeInstance(PHANDLE phNmPipe, const char *pszFullPipeName, bool fFirst)
+static int rtLocalIpcServerWinCreatePipeInstance(PHANDLE phNmPipe, const char *pszFullPipeName, bool fFirst)
{
*phNmPipe = INVALID_HANDLE_VALUE;
- /*
- * We'll create a security descriptor from a SDDL that denies
- * access to network clients (this is local IPC after all), it
- * makes some further restrictions to prevent non-authenticated
- * users from screwing around.
- */
- DWORD err;
- PSECURITY_DESCRIPTOR pSecDesc = NULL;
-#if 0 /** @todo dynamically resolve this as it is the only thing that prevents
- * loading IPRT on NT4. */
- if (ConvertStringSecurityDescriptorToSecurityDescriptor(RTLOCALIPC_WIN_SDDL,
- SDDL_REVISION_1,
- &pSecDesc,
- NULL))
-#else
- AssertFatalFailed();
- SetLastError(-1);
- if (0)
-#endif
+ PSECURITY_DESCRIPTOR pSecDesc;
+ int rc = rtLocalIpcServerWinAllocSecurityDescriptior(&pSecDesc, fFirst /* Server? */);
+ if (RT_SUCCESS(rc))
{
SECURITY_ATTRIBUTES SecAttrs;
- SecAttrs.nLength = sizeof(SecAttrs);
+ SecAttrs.nLength = sizeof(SECURITY_ATTRIBUTES);
SecAttrs.lpSecurityDescriptor = pSecDesc;
SecAttrs.bInheritHandle = FALSE;
DWORD fOpenMode = PIPE_ACCESS_DUPLEX
| PIPE_WAIT
| FILE_FLAG_OVERLAPPED;
- if (fFirst)
- fOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE; /* Note! Requires W2K SP2+. */
+
+ bool fSupportsFirstInstance = false;
+
+ OSVERSIONINFOEX OSInfoEx;
+ RT_ZERO(OSInfoEx);
+ OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ if ( GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
+ && OSInfoEx.dwPlatformId == VER_PLATFORM_WIN32_NT)
+ {
+ if ( /* Vista+. */
+ OSInfoEx.dwMajorVersion >= 6
+ /* Windows XP+. */
+ || ( OSInfoEx.dwMajorVersion == 5
+ && OSInfoEx.dwMinorVersion > 0)
+ /* Windows 2000. */
+ || ( OSInfoEx.dwMajorVersion == 5
+ && OSInfoEx.dwMinorVersion == 0
+ && OSInfoEx.wServicePackMajor >= 2))
+ {
+ /* Requires at least W2K (5.0) SP2+. This is non-fatal. */
+ fSupportsFirstInstance = true;
+ }
+ }
+
+ if (fFirst && fSupportsFirstInstance)
+ fOpenMode |= FILE_FLAG_FIRST_PIPE_INSTANCE;
HANDLE hNmPipe = CreateNamedPipe(pszFullPipeName, /* lpName */
fOpenMode, /* dwOpenMode */
@@ -219,19 +320,16 @@ static DWORD rtLocalIpcServerWinCreatePipeInstance(PHANDLE phNmPipe, const char
PAGE_SIZE, /* nInBufferSize (ditto) */
30*1000, /* nDefaultTimeOut = 30 sec */
&SecAttrs); /* lpSecurityAttributes */
- err = GetLastError();
LocalFree(pSecDesc);
if (hNmPipe != INVALID_HANDLE_VALUE)
{
*phNmPipe = hNmPipe;
- return NO_ERROR;
}
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
}
- else
- err = GetLastError();
- AssertReturn(err != NO_ERROR, ERROR_GEN_FAILURE);
- return err;
+ return rc;
}
@@ -244,8 +342,7 @@ RTDECL(int) RTLocalIpcServerCreate(PRTLOCALIPCSERVER phServer, const char *pszNa
AssertPtrReturn(pszName, VERR_INVALID_POINTER);
AssertReturn(*pszName, VERR_INVALID_PARAMETER);
AssertReturn(!(fFlags & ~(RTLOCALIPC_FLAGS_VALID_MASK)), VERR_INVALID_PARAMETER);
-
- AssertReturn(fFlags & RTLOCALIPC_FLAGS_MULTI_SESSION, VERR_NOT_IMPLEMENTED); /** @todo implement !RTLOCALIPC_FLAGS_MULTI_SESSION */
+ AssertReturn((fFlags & RTLOCALIPC_FLAGS_MULTI_SESSION), VERR_INVALID_PARAMETER); /** @todo Implement !RTLOCALIPC_FLAGS_MULTI_SESSION */
/*
* Allocate and initialize the instance data.
@@ -263,24 +360,30 @@ RTDECL(int) RTLocalIpcServerCreate(PRTLOCALIPCSERVER phServer, const char *pszNa
int rc = RTCritSectInit(&pThis->CritSect);
if (RT_SUCCESS(rc))
{
- DWORD err = NO_ERROR;
- pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL /*lpName*/);
+ pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/,
+ FALSE /*bInitialState*/, NULL /*lpName*/);
if (pThis->hEvent != NULL)
{
- memset(&pThis->OverlappedIO, 0, sizeof(pThis->OverlappedIO));
+ RT_ZERO(pThis->OverlappedIO);
pThis->OverlappedIO.Internal = STATUS_PENDING;
pThis->OverlappedIO.hEvent = pThis->hEvent;
- err = rtLocalIpcServerWinCreatePipeInstance(&pThis->hNmPipe, pThis->szName, true /* fFirst */);
- if (err == NO_ERROR)
+ rc = rtLocalIpcServerWinCreatePipeInstance(&pThis->hNmPipe,
+ pThis->szName, true /* fFirst */);
+ if (RT_SUCCESS(rc))
{
*phServer = pThis;
return VINF_SUCCESS;
}
+
+ BOOL fRc = CloseHandle(pThis->hEvent);
+ AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc);
}
else
- err = GetLastError();
- rc = RTErrConvertFromWin32(err);
+ rc = RTErrConvertFromWin32(GetLastError());
+
+ int rc2 = RTCritSectDelete(&pThis->CritSect);
+ AssertRC(rc2);
}
RTMemFree(pThis);
return rc;
@@ -327,9 +430,10 @@ RTDECL(int) RTLocalIpcServerDestroy(RTLOCALIPCSERVER hServer)
RTCritSectEnter(&pThis->CritSect);
ASMAtomicUoWriteU32(&pThis->u32Magic, ~RTLOCALIPCSERVER_MAGIC);
ASMAtomicUoWriteBool(&pThis->fCancelled, true);
+ Assert(pThis->cRefs);
pThis->cRefs--;
- if (pThis->cRefs > 0)
+ if (pThis->cRefs)
{
BOOL fRc = SetEvent(pThis->hEvent);
AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc);
@@ -371,23 +475,23 @@ RTDECL(int) RTLocalIpcServerListen(RTLOCALIPCSERVER hServer, PRTLOCALIPCSESSION
/*
* Try connect a client. We need to use overlapped I/O here because
- * of the cancellation a by RTLocalIpcServerCancel and RTLocalIpcServerDestroy.
+ * of the cancellation done by RTLocalIpcServerCancel and RTLocalIpcServerDestroy.
*/
SetLastError(NO_ERROR);
BOOL fRc = ConnectNamedPipe(pThis->hNmPipe, &pThis->OverlappedIO);
- DWORD err = fRc ? NO_ERROR : GetLastError();
+ DWORD dwErr = fRc ? NO_ERROR : GetLastError();
if ( !fRc
- && err == ERROR_IO_PENDING)
+ && dwErr == ERROR_IO_PENDING)
{
WaitForSingleObject(pThis->hEvent, INFINITE);
DWORD dwIgnored;
fRc = GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, &dwIgnored, FALSE /* bWait*/);
- err = fRc ? NO_ERROR : GetLastError();
+ dwErr = fRc ? NO_ERROR : GetLastError();
}
RTCritSectEnter(&pThis->CritSect);
- if ( !pThis->fCancelled
- && pThis->u32Magic == RTLOCALIPCSERVER_MAGIC)
+ if ( !pThis->fCancelled /* Event signalled but not cancelled? */
+ && pThis->u32Magic == RTLOCALIPCSERVER_MAGIC)
{
/*
* Still alive, some error or an actual client.
@@ -396,12 +500,12 @@ RTDECL(int) RTLocalIpcServerListen(RTLOCALIPCSERVER hServer, PRTLOCALIPCSESSION
* replaces the current one for the server. The current pipe instance
* will be assigned to the client session.
*/
- if ( fRc
- || err == ERROR_PIPE_CONNECTED)
+ if ( fRc
+ || dwErr == ERROR_PIPE_CONNECTED)
{
HANDLE hNmPipe;
- DWORD err = rtLocalIpcServerWinCreatePipeInstance(&hNmPipe, pThis->szName, false /* fFirst */);
- if (err == NO_ERROR)
+ rc = rtLocalIpcServerWinCreatePipeInstance(&hNmPipe, pThis->szName, false /* fFirst */);
+ if (RT_SUCCESS(rc))
{
HANDLE hNmPipeSession = pThis->hNmPipe; /* consumed */
pThis->hNmPipe = hNmPipe;
@@ -413,13 +517,12 @@ RTDECL(int) RTLocalIpcServerListen(RTLOCALIPCSERVER hServer, PRTLOCALIPCSESSION
* We failed to create a new instance for the server, disconnect
* the client and fail. Don't try service the client here.
*/
- rc = RTErrConvertFromWin32(err);
fRc = DisconnectNamedPipe(pThis->hNmPipe);
AssertMsg(fRc, ("%d\n", GetLastError()));
}
}
else
- rc = RTErrConvertFromWin32(err);
+ rc = RTErrConvertFromWin32(dwErr);
}
else
{
@@ -430,9 +533,9 @@ RTDECL(int) RTLocalIpcServerListen(RTLOCALIPCSERVER hServer, PRTLOCALIPCSESSION
* in the this thread) or disconnect the client.
*/
if ( fRc
- || err == ERROR_PIPE_CONNECTED)
+ || dwErr == ERROR_PIPE_CONNECTED)
fRc = DisconnectNamedPipe(pThis->hNmPipe);
- else if (err == ERROR_IO_PENDING)
+ else if (dwErr == ERROR_IO_PENDING)
fRc = CancelIo(pThis->hNmPipe);
else
fRc = TRUE;
@@ -464,15 +567,17 @@ RTDECL(int) RTLocalIpcServerCancel(RTLOCALIPCSERVER hServer)
* Enter the critical section, then set the cancellation flag
* and signal the event (to wake up anyone in/at WaitForSingleObject).
*/
- RTCritSectEnter(&pThis->CritSect);
-
- ASMAtomicUoWriteBool(&pThis->fCancelled, true);
- BOOL fRc = SetEvent(pThis->hEvent);
- AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc);
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ ASMAtomicUoWriteBool(&pThis->fCancelled, true);
+ BOOL fRc = SetEvent(pThis->hEvent);
+ AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc);
- RTCritSectLeave(&pThis->CritSect);
+ rc = RTCritSectLeave(&pThis->CritSect);
+ }
- return VINF_SUCCESS;
+ return rc;
}
@@ -487,6 +592,9 @@ RTDECL(int) RTLocalIpcServerCancel(RTLOCALIPCSERVER hServer)
*/
static int rtLocalIpcWinCreateSession(PRTLOCALIPCSESSION phClientSession, HANDLE hNmPipeSession)
{
+ AssertPtrReturn(phClientSession, VERR_INVALID_POINTER);
+ AssertReturn(hNmPipeSession != INVALID_HANDLE_VALUE, VERR_INVALID_HANDLE);
+
int rc;
/*
@@ -498,15 +606,18 @@ static int rtLocalIpcWinCreateSession(PRTLOCALIPCSESSION phClientSession, HANDLE
pThis->u32Magic = RTLOCALIPCSESSION_MAGIC;
pThis->cRefs = 1; /* our ref */
pThis->fCancelled = false;
+ pThis->fIOPending = false;
+ pThis->fZeroByteRead = false;
pThis->hNmPipe = hNmPipeSession;
rc = RTCritSectInit(&pThis->CritSect);
if (RT_SUCCESS(rc))
{
- pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/, FALSE /*bInitialState*/, NULL /*lpName*/);
+ pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/,
+ FALSE /*bInitialState*/, NULL /*lpName*/);
if (pThis->hEvent != NULL)
{
- memset(&pThis->OverlappedIO, 0, sizeof(pThis->OverlappedIO));
+ RT_ZERO(pThis->OverlappedIO);
pThis->OverlappedIO.Internal = STATUS_PENDING;
pThis->OverlappedIO.hEvent = pThis->hEvent;
@@ -528,10 +639,88 @@ static int rtLocalIpcWinCreateSession(PRTLOCALIPCSESSION phClientSession, HANDLE
return rc;
}
-
RTDECL(int) RTLocalIpcSessionConnect(PRTLOCALIPCSESSION phSession, const char *pszName, uint32_t fFlags)
{
- return VINF_SUCCESS;
+ AssertPtrReturn(phSession, VERR_INVALID_POINTER);
+ AssertPtrReturn(pszName, VERR_INVALID_POINTER);
+ AssertReturn(*pszName, VERR_INVALID_PARAMETER);
+ AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* Flags currently unused, must be 0. */
+
+ PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)RTMemAlloc(sizeof(*pThis));
+ if (!pThis)
+ return VERR_NO_MEMORY;
+
+ pThis->u32Magic = RTLOCALIPCSESSION_MAGIC;
+ pThis->cRefs = 1; /* The one we return. */
+ pThis->fIOPending = false;
+ pThis->fZeroByteRead = false;
+ pThis->fCancelled = false;
+ pThis->pbBounceBuf = NULL;
+ pThis->cbBounceBufAlloc = 0;
+ pThis->cbBounceBufUsed = 0;
+
+ int rc = RTCritSectInit(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/,
+ FALSE /*bInitialState*/, NULL /*lpName*/);
+ if (pThis->hEvent != NULL)
+ {
+ RT_ZERO(pThis->OverlappedIO);
+ pThis->OverlappedIO.Internal = STATUS_PENDING;
+ pThis->OverlappedIO.hEvent = pThis->hEvent;
+
+ PSECURITY_DESCRIPTOR pSecDesc;
+ rc = rtLocalIpcServerWinAllocSecurityDescriptior(&pSecDesc, false /* Client */);
+ if (RT_SUCCESS(rc))
+ {
+ char *pszPipe;
+ if (RTStrAPrintf(&pszPipe, "%s%s", RTLOCALIPC_WIN_PREFIX, pszName))
+ {
+ SECURITY_ATTRIBUTES SecAttrs;
+ SecAttrs.nLength = sizeof(SECURITY_ATTRIBUTES);
+ SecAttrs.lpSecurityDescriptor = pSecDesc;
+ SecAttrs.bInheritHandle = FALSE;
+
+ HANDLE hPipe = CreateFile(pszPipe, /* pipe name */
+ GENERIC_READ /* read and write access */
+ | GENERIC_WRITE,
+ 0, /* no sharing */
+ &SecAttrs, /* lpSecurityAttributes */
+ OPEN_EXISTING, /* opens existing pipe */
+ FILE_FLAG_OVERLAPPED, /* default attributes */
+ NULL); /* no template file */
+ RTStrFree(pszPipe);
+
+ if (hPipe != INVALID_HANDLE_VALUE)
+ {
+ LocalFree(pSecDesc);
+
+ pThis->hNmPipe = hPipe;
+ *phSession = pThis;
+ return VINF_SUCCESS;
+ }
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ LocalFree(pSecDesc);
+ }
+
+ BOOL fRc = CloseHandle(pThis->hEvent);
+ AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc);
+ }
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+
+ int rc2 = RTCritSectDelete(&pThis->CritSect);
+ AssertRC(rc2);
+ }
+
+ RTMemFree(pThis);
+ return rc;
}
@@ -564,9 +753,9 @@ RTDECL(int) RTLocalIpcSessionClose(RTLOCALIPCSESSION hSession)
*/
if (hSession == NIL_RTLOCALIPCSESSION)
return VINF_SUCCESS;
- PRTLOCALIPCSESSIONINT pThis = (RTLOCALIPCSESSION)hSession;
+ PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)hSession;
AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic != RTLOCALIPCSESSION_MAGIC, VERR_INVALID_MAGIC);
+ AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_MAGIC);
/*
* Cancel any thread currently busy using the session,
@@ -593,32 +782,437 @@ RTDECL(int) RTLocalIpcSessionClose(RTLOCALIPCSESSION hSession)
RTDECL(int) RTLocalIpcSessionRead(RTLOCALIPCSESSION hSession, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
{
- return VINF_SUCCESS;
+ PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)hSession;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE);
+ AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
+ /* pcbRead is optional. */
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ /* No concurrent readers, sorry. */
+ if (pThis->cRefs == 1)
+ {
+ pThis->cRefs++;
+
+ /*
+ * If pcbRead is non-NULL this indicates the maximum number of bytes to read.
+ * If pcbRead is NULL then this is the exact number of bytes to read.
+ */
+ size_t cbToRead = pcbRead ? *pcbRead : cbBuffer;
+ size_t cbTotalRead = 0;
+ while (cbToRead > 0)
+ {
+ /*
+ * Kick of a an overlapped read. It should return immediately if
+ * there is bytes in the buffer. If not, we'll cancel it and see
+ * what we get back.
+ */
+ rc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(rc == TRUE);
+ DWORD cbRead = 0;
+ pThis->fIOPending = true;
+ RTCritSectLeave(&pThis->CritSect);
+
+ if (ReadFile(pThis->hNmPipe, pvBuffer,
+ cbToRead <= ~(DWORD)0 ? (DWORD)cbToRead : ~(DWORD)0,
+ &cbRead, &pThis->OverlappedIO))
+ rc = VINF_SUCCESS;
+ else if (GetLastError() == ERROR_IO_PENDING)
+ {
+ WaitForSingleObject(pThis->OverlappedIO.hEvent, INFINITE);
+ if (GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO,
+ &cbRead, TRUE /*fWait*/))
+ rc = VINF_SUCCESS;
+ else
+ {
+ DWORD dwErr = GetLastError();
+ AssertMsgFailed(("err=%ld\n", dwErr));
+ rc = RTErrConvertFromWin32(dwErr);
+ }
+ }
+ else
+ {
+ DWORD dwErr = GetLastError();
+ AssertMsgFailed(("err2=%ld\n", dwErr));
+ rc = RTErrConvertFromWin32(dwErr);
+ }
+
+ RTCritSectEnter(&pThis->CritSect);
+ pThis->fIOPending = false;
+ if (RT_FAILURE(rc))
+ break;
+
+ /* Advance. */
+ cbToRead -= cbRead;
+ cbTotalRead += cbRead;
+ pvBuffer = (uint8_t *)pvBuffer + cbRead;
+ }
+
+ if (pcbRead)
+ {
+ *pcbRead = cbTotalRead;
+ if ( RT_FAILURE(rc)
+ && cbTotalRead
+ && rc != VERR_INVALID_POINTER)
+ rc = VINF_SUCCESS;
+ }
+
+ pThis->cRefs--;
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+
+ return rc;
+}
+
+
+/**
+ * Common worker for handling I/O completion.
+ *
+ * This is used by RTLocalIpcSessionClose and RTLocalIpcSessionWrite.
+ *
+ * @returns IPRT status code.
+ * @param pThis The pipe instance handle.
+ */
+static int rtLocalIpcSessionWriteCheckCompletion(PRTLOCALIPCSESSIONINT pThis)
+{
+ int rc;
+ DWORD dwRc = WaitForSingleObject(pThis->OverlappedIO.hEvent, 0);
+ if (dwRc == WAIT_OBJECT_0)
+ {
+ DWORD cbWritten = 0;
+ if (GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, &cbWritten, TRUE))
+ {
+ for (;;)
+ {
+ if (cbWritten >= pThis->cbBounceBufUsed)
+ {
+ pThis->fIOPending = false;
+ rc = VINF_SUCCESS;
+ break;
+ }
+
+ /* resubmit the remainder of the buffer - can this actually happen? */
+ memmove(&pThis->pbBounceBuf[0], &pThis->pbBounceBuf[cbWritten], pThis->cbBounceBufUsed - cbWritten);
+ rc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(rc == TRUE);
+ if (!WriteFile(pThis->hNmPipe, pThis->pbBounceBuf, (DWORD)pThis->cbBounceBufUsed,
+ &cbWritten, &pThis->OverlappedIO))
+ {
+ DWORD dwErr = GetLastError();
+ if (dwErr == ERROR_IO_PENDING)
+ rc = VINF_TRY_AGAIN;
+ else
+ {
+ pThis->fIOPending = false;
+ if (dwErr == ERROR_NO_DATA)
+ rc = VERR_BROKEN_PIPE;
+ else
+ rc = RTErrConvertFromWin32(dwErr);
+ }
+ break;
+ }
+ Assert(cbWritten > 0);
+ }
+ }
+ else
+ {
+ pThis->fIOPending = false;
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+ }
+ else if (dwRc == WAIT_TIMEOUT)
+ rc = VINF_TRY_AGAIN;
+ else
+ {
+ pThis->fIOPending = false;
+ if (dwRc == WAIT_ABANDONED)
+ rc = VERR_INVALID_HANDLE;
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+ return rc;
}
RTDECL(int) RTLocalIpcSessionWrite(RTLOCALIPCSESSION hSession, const void *pvBuffer, size_t cbBuffer)
{
- return VINF_SUCCESS;
+ PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)hSession;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE);
+ AssertPtrReturn(pvBuffer, VERR_INVALID_POINTER);
+ AssertReturn(cbBuffer, VERR_INVALID_PARAMETER);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ /* No concurrent writers, sorry. */
+ if (pThis->cRefs == 1)
+ {
+ pThis->cRefs++;
+
+ /*
+ * If I/O is pending, wait for it to complete.
+ */
+ if (pThis->fIOPending)
+ {
+ rc = rtLocalIpcSessionWriteCheckCompletion(pThis);
+ while (rc == VINF_TRY_AGAIN)
+ {
+ Assert(pThis->fIOPending);
+ HANDLE hEvent = pThis->OverlappedIO.hEvent;
+ RTCritSectLeave(&pThis->CritSect);
+ WaitForSingleObject(pThis->OverlappedIO.hEvent, INFINITE);
+ RTCritSectEnter(&pThis->CritSect);
+ }
+ }
+ if (RT_SUCCESS(rc))
+ {
+ Assert(!pThis->fIOPending);
+
+ /*
+ * Try write everything.
+ * No bounce buffering, cUsers protects us.
+ */
+ size_t cbTotalWritten = 0;
+ while (cbBuffer > 0)
+ {
+ BOOL fRc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(fRc == TRUE);
+ pThis->fIOPending = true;
+ RTCritSectLeave(&pThis->CritSect);
+
+ DWORD cbWritten = 0;
+ fRc = WriteFile(pThis->hNmPipe, pvBuffer,
+ cbBuffer <= ~(DWORD)0 ? (DWORD)cbBuffer : ~(DWORD)0,
+ &cbWritten, &pThis->OverlappedIO);
+ if (fRc)
+ {
+ rc = VINF_SUCCESS;
+ }
+ else
+ {
+ DWORD dwErr = GetLastError();
+ if (dwErr == ERROR_IO_PENDING)
+ {
+ DWORD dwRc = WaitForSingleObject(pThis->OverlappedIO.hEvent, INFINITE);
+ if (dwRc == WAIT_OBJECT_0)
+ {
+ if (GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, &cbWritten, TRUE /*fWait*/))
+ rc = VINF_SUCCESS;
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+ else if (dwRc == WAIT_TIMEOUT)
+ rc = VERR_TIMEOUT;
+ else if (dwRc == WAIT_ABANDONED)
+ rc = VERR_INVALID_HANDLE;
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+ else if (dwErr == ERROR_NO_DATA)
+ rc = VERR_BROKEN_PIPE;
+ else
+ rc = RTErrConvertFromWin32(dwErr);
+ }
+
+ RTCritSectEnter(&pThis->CritSect);
+ pThis->fIOPending = false;
+ if (RT_FAILURE(rc))
+ break;
+
+ /* Advance. */
+ pvBuffer = (char const *)pvBuffer + cbWritten;
+ cbTotalWritten += cbWritten;
+ cbBuffer -= cbWritten;
+ }
+ }
+
+ pThis->cRefs--;
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+
+ return rc;
}
RTDECL(int) RTLocalIpcSessionFlush(RTLOCALIPCSESSION hSession)
{
+ /* No flushing on Windows needed since RTLocalIpcSessionWrite will block until
+ * all data was written (or an error occurred). */
+ /** @todo Implement this as soon as we want an explicit asynchronous version of
+ * RTLocalIpcSessionWrite on Windows. */
return VINF_SUCCESS;
}
RTDECL(int) RTLocalIpcSessionWaitForData(RTLOCALIPCSESSION hSession, uint32_t cMillies)
{
- RTThreadSleep(1000);
- return VINF_SUCCESS;
+ PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)hSession;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE);
+
+ uint64_t const StartMsTS = RTTimeMilliTS();
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_FAILURE(rc))
+ return rc;
+ for (unsigned iLoop = 0;; iLoop++)
+ {
+ HANDLE hWait = INVALID_HANDLE_VALUE;
+
+ if (pThis->fIOPending)
+ hWait = pThis->OverlappedIO.hEvent;
+ else
+ {
+ /* Peek at the pipe buffer and see how many bytes it contains. */
+ DWORD cbAvailable;
+ BOOL fRc = PeekNamedPipe(pThis->hNmPipe, NULL, 0, NULL, &cbAvailable, NULL);
+ if ( fRc
+ && cbAvailable)
+ {
+ rc = VINF_SUCCESS;
+ break;
+ }
+ else if (!fRc)
+ {
+ rc = RTErrConvertFromWin32(GetLastError());
+ break;
+ }
+
+ /* Start a zero byte read operation that we can wait on. */
+ if (cMillies == 0)
+ {
+ rc = VERR_TIMEOUT;
+ break;
+ }
+ AssertBreakStmt(pThis->cRefs == 1, rc = VERR_WRONG_ORDER);
+ fRc = ResetEvent(pThis->OverlappedIO.hEvent); Assert(fRc == TRUE);
+ DWORD cbRead = 0;
+ if (ReadFile(pThis->hNmPipe, pThis->abBuf, 0, &cbRead, &pThis->OverlappedIO))
+ {
+ rc = VINF_SUCCESS;
+ if (iLoop > 10)
+ RTThreadYield();
+ }
+ else if (GetLastError() == ERROR_IO_PENDING)
+ {
+ pThis->cRefs++;
+ pThis->fIOPending = true;
+ pThis->fZeroByteRead = true;
+ hWait = pThis->OverlappedIO.hEvent;
+ }
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+ }
+
+ if (RT_FAILURE(rc))
+ break;
+
+ /*
+ * Check for timeout.
+ */
+ DWORD cMsMaxWait = INFINITE;
+ if ( cMillies != RT_INDEFINITE_WAIT
+ && ( hWait != INVALID_HANDLE_VALUE
+ || iLoop > 10)
+ )
+ {
+ uint64_t cElapsed = RTTimeMilliTS() - StartMsTS;
+ if (cElapsed >= cMillies)
+ {
+ rc = VERR_TIMEOUT;
+ break;
+ }
+ cMsMaxWait = cMillies - (uint32_t)cElapsed;
+ }
+
+ /*
+ * Wait.
+ */
+ if (hWait != INVALID_HANDLE_VALUE)
+ {
+ RTCritSectLeave(&pThis->CritSect);
+
+ DWORD dwRc = WaitForSingleObject(hWait, cMsMaxWait);
+ if (dwRc == WAIT_OBJECT_0)
+ rc = VINF_SUCCESS;
+ else if (dwRc == WAIT_TIMEOUT)
+ rc = VERR_TIMEOUT;
+ else if (dwRc == WAIT_ABANDONED)
+ rc = VERR_INVALID_HANDLE;
+ else
+ rc = RTErrConvertFromWin32(GetLastError());
+
+ if ( RT_FAILURE(rc)
+ && pThis->u32Magic != RTLOCALIPCSESSION_MAGIC)
+ return rc;
+
+ int rc2 = RTCritSectEnter(&pThis->CritSect);
+ AssertRC(rc2);
+ if (pThis->fZeroByteRead)
+ {
+ Assert(pThis->cRefs);
+ pThis->cRefs--;
+ pThis->fIOPending = false;
+
+ if (rc != VINF_SUCCESS)
+ {
+ BOOL fRc = CancelIo(pThis->hNmPipe);
+ Assert(fRc == TRUE);
+ }
+
+ DWORD cbRead = 0;
+ BOOL fRc = GetOverlappedResult(pThis->hNmPipe, &pThis->OverlappedIO, &cbRead, TRUE /*fWait*/);
+ if ( !fRc
+ && RT_SUCCESS(rc))
+ {
+ DWORD dwRc = GetLastError();
+ if (dwRc == ERROR_OPERATION_ABORTED)
+ rc = VERR_CANCELLED;
+ else
+ rc = RTErrConvertFromWin32(dwRc);
+ }
+ }
+
+ if (RT_FAILURE(rc))
+ break;
+ }
+ }
+
+ int rc2 = RTCritSectLeave(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ rc = rc2;
+
+ return rc;
}
RTDECL(int) RTLocalIpcSessionCancel(RTLOCALIPCSESSION hSession)
{
- return VINF_SUCCESS;
+ PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)hSession;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTLOCALIPCSESSION_MAGIC, VERR_INVALID_HANDLE);
+
+ /*
+ * Enter the critical section, then set the cancellation flag
+ * and signal the event (to wake up anyone in/at WaitForSingleObject).
+ */
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ ASMAtomicUoWriteBool(&pThis->fCancelled, true);
+ BOOL fRc = SetEvent(pThis->hEvent);
+ AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc);
+
+ RTCritSectLeave(&pThis->CritSect);
+ }
+
+ return rc;
}
diff --git a/src/VBox/Runtime/r3/win/mp-win.cpp b/src/VBox/Runtime/r3/win/mp-win.cpp
index fed1152b..dce41d19 100644
--- a/src/VBox/Runtime/r3/win/mp-win.cpp
+++ b/src/VBox/Runtime/r3/win/mp-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -30,9 +30,14 @@
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_SYSTEM
#include <Windows.h>
+
#include <iprt/mp.h>
-#include <iprt/cpuset.h>
+#include "internal/iprt.h"
+
#include <iprt/assert.h>
+#include <iprt/cpuset.h>
+#include <iprt/ldr.h>
+#include <iprt/mem.h>
AssertCompile(MAXIMUM_PROCESSORS <= RTCPUSET_MAX_CPUS);
@@ -91,6 +96,59 @@ RTDECL(RTCPUID) RTMpGetCount(void)
}
+RTDECL(RTCPUID) RTMpGetCoreCount(void)
+{
+ /*
+ * Resolve the API dynamically (one try) as it requires XP w/ sp3 or later.
+ */
+ typedef BOOL (WINAPI *PFNGETLOGICALPROCINFO)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
+ static PFNGETLOGICALPROCINFO s_pfnGetLogicalProcInfo = (PFNGETLOGICALPROCINFO)~(uintptr_t)0;
+ if (s_pfnGetLogicalProcInfo == (PFNGETLOGICALPROCINFO)~(uintptr_t)0)
+ s_pfnGetLogicalProcInfo = (PFNGETLOGICALPROCINFO)RTLdrGetSystemSymbol("kernel32.dll", "GetLogicalProcessorInformation");
+
+ if (s_pfnGetLogicalProcInfo)
+ {
+ /*
+ * Query the information. This unfortunately requires a buffer, so we
+ * start with a guess and let windows advice us if it's too small.
+ */
+ DWORD cbSysProcInfo = _4K;
+ PSYSTEM_LOGICAL_PROCESSOR_INFORMATION paSysInfo = NULL;
+ BOOL fRc = FALSE;
+ do
+ {
+ cbSysProcInfo = RT_ALIGN_32(cbSysProcInfo, 256);
+ void *pv = RTMemRealloc(paSysInfo, cbSysProcInfo);
+ if (!pv)
+ break;
+ paSysInfo = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)pv;
+ fRc = s_pfnGetLogicalProcInfo(paSysInfo, &cbSysProcInfo);
+ } while (!fRc && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
+ if (fRc)
+ {
+ /*
+ * Parse the result.
+ */
+ uint32_t cCores = 0;
+ uint32_t i = cbSysProcInfo / sizeof(paSysInfo[0]);
+ while (i-- > 0)
+ if (paSysInfo[i].Relationship == RelationProcessorCore)
+ cCores++;
+
+ RTMemFree(paSysInfo);
+ Assert(cCores > 0);
+ return cCores;
+ }
+
+ RTMemFree(paSysInfo);
+ }
+
+ /* If we don't have the necessary API or if it failed, return the same
+ value as the generic implementation. */
+ return RTMpGetCount();
+}
+
+
RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
{
SYSTEM_INFO SysInfo;
@@ -107,3 +165,10 @@ RTDECL(RTCPUID) RTMpGetOnlineCount(void)
return RTCpuSetCount(&Set);
}
+
+RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void)
+{
+ /** @todo this isn't entirely correct. */
+ return RTMpGetCoreCount();
+}
+
diff --git a/src/VBox/Runtime/r3/win/ntdll-mini-implib.c b/src/VBox/Runtime/r3/win/ntdll-mini-implib.c
index 74094221..a3eeef7b 100644
--- a/src/VBox/Runtime/r3/win/ntdll-mini-implib.c
+++ b/src/VBox/Runtime/r3/win/ntdll-mini-implib.c
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-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;
@@ -34,13 +34,23 @@ typedef LONG NTSTATUS;
typedef PVOID PIO_STATUS_BLOCK;
typedef INT FILE_INFORMATION_CLASS;
typedef INT FS_INFORMATION_CLASS;
+typedef INT MEMORY_INFORMATION_CLASS;
+typedef INT PROCESSINFOCLASS;
+typedef PVOID POBJECT_ATTRIBUTES;
+typedef PVOID PIO_APC_ROUTINE;
+typedef PVOID PUNICODE_STRING;
+/* Error/status conversion: */
+
NTSYSAPI ULONG NTAPI RtlNtStatusToDosError(IN NTSTATUS Status)
{
return 1;
}
+
+/* Queries: */
+
NTSYSAPI LONG NTAPI NtQueryTimerResolution(OUT PULONG MaximumResolution,
OUT PULONG MinimumResolution,
OUT PULONG CurrentResolution)
@@ -48,15 +58,72 @@ NTSYSAPI LONG NTAPI NtQueryTimerResolution(OUT PULONG MaximumResolution,
return -1;
}
-NTSYSAPI NTSTATUS WINAPI NtQueryInformationFile(HANDLE h,
- PIO_STATUS_BLOCK b,
- PVOID c,
- LONG d,
- FILE_INFORMATION_CLASS e)
+NTSYSAPI LONG NTAPI NtQueryDirectoryFile(IN HANDLE FileHandle,
+ IN HANDLE Event OPTIONAL,
+ IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
+ IN PVOID ApcContext OPTIONAL,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID FileInformation,
+ IN ULONG Length,
+ IN FILE_INFORMATION_CLASS FileInformationClass,
+ IN BOOLEAN ReturnSingleEntry,
+ IN PUNICODE_STRING FileName OPTIONAL,
+ IN BOOLEAN RestartScan)
+{
+ return -1;
+}
+
+NTSYSAPI LONG NTAPI NtQueryDirectoryObject(IN HANDLE ObjectHandle,
+ OUT PVOID Buffer,
+ IN ULONG Length,
+ IN BOOLEAN ReturnSingleEntry,
+ IN BOOLEAN RestartScan,
+ IN OUT PULONG Context,
+ OUT PULONG ReturneLength)
+{
+ return -1;
+}
+
+NTSYSAPI NTSTATUS WINAPI NtQueryInformationFile(IN HANDLE h,
+ OUT PIO_STATUS_BLOCK b,
+ OUT PVOID pvBuf,
+ IN LONG cbBuf,
+ IN FILE_INFORMATION_CLASS e)
+{
+ return -1;
+}
+
+NTSYSAPI NTSTATUS NTAPI NtQueryInformationProcess(IN HANDLE hProcess,
+ IN PROCESSINFOCLASS enmProcInfo,
+ OUT PVOID pvBuf,
+ IN SIZE_T cbBuf,
+ OUT PSIZE_T pcbReturned OPTIONAL)
+{
+ return -1;
+}
+
+NTSYSAPI NTSTATUS NTAPI NtQueryVolumeInformationFile(IN HANDLE hFile,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ OUT PVOID pvBuf,
+ IN ULONG cbBuf,
+ IN FS_INFORMATION_CLASS FsInformationClass)
+{
+ return -1;
+}
+
+NTSYSAPI NTSTATUS NTAPI NtQueryVirtualMemory(IN HANDLE hProcess,
+ IN LPCVOID pvWhere,
+ IN MEMORY_INFORMATION_CLASS MemoryInfo,
+ OUT PVOID pvBuf,
+ IN SIZE_T cbBuf,
+ OUT PSIZE_T pcbReturned OPTIONAL)
{
return -1;
}
+
+/* Setters: */
+
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID FileInformation,
@@ -73,11 +140,33 @@ NTSYSAPI LONG NTAPI NtSetTimerResolution(IN ULONG DesiredResolution,
return -1;
}
-NTSYSAPI NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE h,
- PIO_STATUS_BLOCK IoStatusBlock,
- PVOID pvBuf,
- ULONG cbBuf,
- FS_INFORMATION_CLASS FsInformationClass)
+
+
+/* Handles: */
+
+NTSYSAPI NTSTATUS NTAPI NtCreateFile(OUT PHANDLE FileHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes,
+ OUT PIO_STATUS_BLOCK IoStatusBlock,
+ IN PLARGE_INTEGER AllocationSize OPTIONAL,
+ IN ULONG FileAttributes,
+ IN ULONG ShareAccess,
+ IN ULONG CreateDisposition,
+ IN ULONG CreateOptions,
+ IN PVOID EaBuffer,
+ IN ULONG EaLength)
+{
+ return -1;
+}
+
+NTSYSAPI NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE ObjectHandle,
+ IN ACCESS_MASK DesiredAccess,
+ IN POBJECT_ATTRIBUTES ObjectAttributes)
+{
+ return -1;
+}
+
+NTSYSAPI NTSTATUS NTAPI NtClose(IN HANDLE Handle)
{
return -1;
}
diff --git a/src/VBox/Runtime/r3/win/ntdll-mini-implib.def b/src/VBox/Runtime/r3/win/ntdll-mini-implib.def
index a0d39ee4..64bc9328 100644
--- a/src/VBox/Runtime/r3/win/ntdll-mini-implib.def
+++ b/src/VBox/Runtime/r3/win/ntdll-mini-implib.def
@@ -4,7 +4,7 @@
;
;
-; Copyright (C) 2010 Oracle Corporation
+; Copyright (C) 2010-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;
@@ -28,8 +28,13 @@ LIBRARY ntdll.dll
EXPORTS
RtlNtStatusToDosError
NtQueryTimerResolution
+ NtQueryDirectoryFile
NtQueryInformationFile
+ NtQueryInformationProcess
NtSetInformationFile
NtSetTimerResolution
NtQueryVolumeInformationFile
-
+ NtQueryVirtualMemory
+ NtCreateFile
+ NtClose
+ NtOpenDirectoryObject
diff --git a/src/VBox/Runtime/r3/win/path-win.cpp b/src/VBox/Runtime/r3/win/path-win.cpp
index aacf7d5f..0245b778 100644
--- a/src/VBox/Runtime/r3/win/path-win.cpp
+++ b/src/VBox/Runtime/r3/win/path-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -195,7 +195,7 @@ RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath)
AssertReturn(cchPath, VERR_INVALID_PARAMETER);
RTLDRMOD hShell32;
- int rc = RTLdrLoad("Shell32.dll", &hShell32);
+ int rc = RTLdrLoadSystem("Shell32.dll", true /*fNoUnload*/, &hShell32);
if (RT_SUCCESS(rc))
{
PFNSHGETFOLDERPATHW pfnSHGetFolderPathW;
diff --git a/src/VBox/Runtime/r3/win/pipe-win.cpp b/src/VBox/Runtime/r3/win/pipe-win.cpp
index 5abe809e..11f8b432 100644
--- a/src/VBox/Runtime/r3/win/pipe-win.cpp
+++ b/src/VBox/Runtime/r3/win/pipe-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-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;
@@ -724,7 +724,7 @@ RTDECL(int) RTPipeWrite(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_
int rc = RTCritSectEnter(&pThis->CritSect);
if (RT_SUCCESS(rc))
{
- /* No concurrent readers, sorry. */
+ /* No concurrent writers, sorry. */
if (pThis->cUsers == 0)
{
pThis->cUsers++;
@@ -839,7 +839,7 @@ RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrit
int rc = RTCritSectEnter(&pThis->CritSect);
if (RT_SUCCESS(rc))
{
- /* No concurrent readers, sorry. */
+ /* No concurrent writers, sorry. */
if (pThis->cUsers == 0)
{
pThis->cUsers++;
@@ -1170,28 +1170,19 @@ RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable)
}
-/**
- * Internal RTPollSetAdd helper that returns the handle that should be added to
- * the pollset.
- *
- * @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
- * @param hPipe The pipe handle.
- * @param fEvents The events we're polling for.
- * @param ph where to put the primary handle.
- */
-int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PHANDLE ph)
+int rtPipePollGetHandle(RTPIPE hPipe, uint32_t fEvents, PRTHCINTPTR phNative)
{
RTPIPEINTERNAL *pThis = hPipe;
AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
- AssertReturn(!(fEvents & RTPOLL_EVT_READ) || pThis->fRead, VERR_INVALID_PARAMETER);
+ AssertReturn(!(fEvents & RTPOLL_EVT_READ) || pThis->fRead, VERR_INVALID_PARAMETER);
AssertReturn(!(fEvents & RTPOLL_EVT_WRITE) || !pThis->fRead, VERR_INVALID_PARAMETER);
/* Later: Try register an event handle with the pipe like on OS/2, there is
a file control for doing this obviously intended for the OS/2 subsys.
The question is whether this still exists on Vista and W7. */
- *ph = pThis->Overlapped.hEvent;
+ *phNative = (RTHCINTPTR)pThis->Overlapped.hEvent;
return VINF_SUCCESS;
}
@@ -1397,6 +1388,7 @@ uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents, bool fFinalEntry, bool f
/* update counters. */
pThis->cUsers--;
+ /** @todo This isn't sane, or is it? See OS/2 impl. */
if (!pThis->cUsers)
pThis->hPollSet = NIL_RTPOLLSET;
diff --git a/src/VBox/Runtime/r3/win/poll-win.cpp b/src/VBox/Runtime/r3/win/poll-win.cpp
deleted file mode 100644
index 0f3b187f..00000000
--- a/src/VBox/Runtime/r3/win/poll-win.cpp
+++ /dev/null
@@ -1,586 +0,0 @@
-/* $Id: poll-win.cpp $ */
-/** @file
- * IPRT - Polling I/O Handles, Windows Implementation.
- *
- * @todo merge poll-win.cpp and poll-posix.cpp, there is lots of common code.
- */
-
-/*
- * Copyright (C) 2010 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- *
- * The contents of this file may alternatively be used under the terms
- * of the Common Development and Distribution License Version 1.0
- * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
- * VirtualBox OSE distribution, in which case the provisions of the
- * CDDL are applicable instead of those of the GPL.
- *
- * You may elect to license modified versions of this file under the
- * terms and conditions of either the GPL or the CDDL or both.
- */
-
-
-/*******************************************************************************
-* Header Files *
-*******************************************************************************/
-#include <Windows.h>
-
-#include <iprt/poll.h>
-#include "internal/iprt.h"
-
-#include <iprt/asm.h>
-#include <iprt/assert.h>
-#include <iprt/err.h>
-#include <iprt/mem.h>
-#include <iprt/pipe.h>
-#include <iprt/string.h>
-#include <iprt/thread.h>
-#include <iprt/time.h>
-
-#include "internal/pipe.h"
-#define IPRT_INTERNAL_SOCKET_POLLING_ONLY
-#include "internal/socket.h"
-#include "internal/magics.h"
-
-
-/*******************************************************************************
-* Structures and Typedefs *
-*******************************************************************************/
-/**
- * Handle entry in a poll set.
- */
-typedef struct RTPOLLSETHNDENT
-{
- /** The handle type. */
- RTHANDLETYPE enmType;
- /** The handle ID. */
- uint32_t id;
- /** The events we're waiting for here. */
- uint32_t fEvents;
- /** Set if this is the final entry for this handle.
- * If the handle is entered more than once, this will be clear for all but
- * the last entry. */
- bool fFinalEntry;
- /** The handle union. */
- RTHANDLEUNION u;
-} RTPOLLSETHNDENT;
-/** Pointer to a handle entry. */
-typedef RTPOLLSETHNDENT *PRTPOLLSETHNDENT;
-
-
-/**
- * Poll set data, Windows.
- */
-typedef struct RTPOLLSETINTERNAL
-{
- /** The magic value (RTPOLLSET_MAGIC). */
- uint32_t u32Magic;
- /** Set when someone is polling or making changes. */
- bool volatile fBusy;
-
- /** The number of valid handles in the set. */
- uint32_t cHandles;
- /** The native handles. */
- HANDLE ahNative[MAXIMUM_WAIT_OBJECTS];
- /** Array of handles and IDs. */
- RTPOLLSETHNDENT aHandles[MAXIMUM_WAIT_OBJECTS];
-} RTPOLLSETINTERNAL;
-
-
-/**
- * Common worker for RTPoll and RTPollNoResume
- */
-static int rtPollNoResumeWorker(RTPOLLSETINTERNAL *pThis, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
-{
- int rc;
-
- if (RT_UNLIKELY(pThis->cHandles == 0 && cMillies == RT_INDEFINITE_WAIT))
- return VERR_DEADLOCK;
-
- /*
- * Check for special case, RTThreadSleep...
- */
- uint32_t const cHandles = pThis->cHandles;
- if (cHandles == 0)
- {
- rc = RTThreadSleep(cMillies);
- if (RT_SUCCESS(rc))
- rc = VERR_TIMEOUT;
- return rc;
- }
-
- /*
- * Check + prepare the handles before waiting.
- */
- uint32_t fEvents = 0;
- bool const fNoWait = cMillies == 0;
- uint32_t i;
- for (i = 0; i < cHandles; i++)
- {
- switch (pThis->aHandles[i].enmType)
- {
- case RTHANDLETYPE_PIPE:
- fEvents = rtPipePollStart(pThis->aHandles[i].u.hPipe, pThis, pThis->aHandles[i].fEvents,
- pThis->aHandles[i].fFinalEntry, fNoWait);
- break;
-
- case RTHANDLETYPE_SOCKET:
- fEvents = rtSocketPollStart(pThis->aHandles[i].u.hSocket, pThis, pThis->aHandles[i].fEvents,
- pThis->aHandles[i].fFinalEntry, fNoWait);
- break;
-
- default:
- AssertFailed();
- fEvents = UINT32_MAX;
- break;
- }
- if (fEvents)
- break;
- }
- if ( fEvents
- || fNoWait)
- {
-
- if (pid)
- *pid = pThis->aHandles[i].id;
- if (pfEvents)
- *pfEvents = fEvents;
- rc = !fEvents
- ? VERR_TIMEOUT
- : fEvents != UINT32_MAX
- ? VINF_SUCCESS
- : VERR_INTERNAL_ERROR_4;
-
- /* clean up */
- if (!fNoWait)
- while (i-- > 0)
- {
- switch (pThis->aHandles[i].enmType)
- {
- case RTHANDLETYPE_PIPE:
- rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,
- pThis->aHandles[i].fFinalEntry, false);
- break;
-
- case RTHANDLETYPE_SOCKET:
- rtSocketPollDone(pThis->aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,
- pThis->aHandles[i].fFinalEntry, false);
- break;
-
- default:
- AssertFailed();
- break;
- }
- }
-
- return rc;
- }
-
- /*
- * Wait.
- */
- DWORD dwRc = WaitForMultipleObjectsEx(cHandles, &pThis->ahNative[0],
- FALSE /*fWaitAll */,
- cMillies == RT_INDEFINITE_WAIT ? INFINITE : cMillies,
- TRUE /*fAlertable*/);
- if ( dwRc >= WAIT_OBJECT_0
- && dwRc < WAIT_OBJECT_0 + cHandles)
- rc = VERR_INTERRUPTED;
- else if (dwRc == WAIT_TIMEOUT)
- rc = VERR_TIMEOUT;
- else if (dwRc == WAIT_IO_COMPLETION)
- rc = VERR_INTERRUPTED;
- else if (dwRc == WAIT_FAILED)
- rc = RTErrConvertFromWin32(GetLastError());
- else
- {
- AssertMsgFailed(("%u (%#x)\n", dwRc, dwRc));
- rc = VERR_INTERNAL_ERROR_5;
- }
-
- /*
- * Get event (if pending) and do wait cleanup.
- */
- bool fHarvestEvents = true;
- for (i = 0; i < cHandles; i++)
- {
- fEvents = 0;
- switch (pThis->aHandles[i].enmType)
- {
- case RTHANDLETYPE_PIPE:
- fEvents = rtPipePollDone(pThis->aHandles[i].u.hPipe, pThis->aHandles[i].fEvents,
- pThis->aHandles[i].fFinalEntry, fHarvestEvents);
- break;
-
- case RTHANDLETYPE_SOCKET:
- fEvents = rtSocketPollDone(pThis->aHandles[i].u.hSocket, pThis->aHandles[i].fEvents,
- pThis->aHandles[i].fFinalEntry, fHarvestEvents);
- break;
-
- default:
- AssertFailed();
- break;
- }
- if ( fEvents
- && fHarvestEvents)
- {
- Assert(fEvents != UINT32_MAX);
- fHarvestEvents = false;
- if (pfEvents)
- *pfEvents = fEvents;
- if (pid)
- *pid = pThis->aHandles[i].id;
- rc = VINF_SUCCESS;
- }
- }
-
- return rc;
-}
-
-
-RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
-{
- RTPOLLSETINTERNAL *pThis = hPollSet;
- AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
- AssertPtrNull(pfEvents);
- AssertPtrNull(pid);
-
- /*
- * Set the busy flag and do the job.
- */
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
-
- int rc;
- if (cMillies == RT_INDEFINITE_WAIT || cMillies == 0)
- {
- do rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
- while (rc == VERR_INTERRUPTED);
- }
- else
- {
- uint64_t MsStart = RTTimeMilliTS();
- rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
- while (RT_UNLIKELY(rc == VERR_INTERRUPTED))
- {
- if (RTTimeMilliTS() - MsStart >= cMillies)
- {
- rc = VERR_TIMEOUT;
- break;
- }
- rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
- }
- }
-
- ASMAtomicWriteBool(&pThis->fBusy, false);
-
- return rc;
-}
-
-
-RTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
-{
- RTPOLLSETINTERNAL *pThis = hPollSet;
- AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
- AssertPtrNull(pfEvents);
- AssertPtrNull(pid);
-
- /*
- * Set the busy flag and do the job.
- */
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
-
- int rc = rtPollNoResumeWorker(pThis, cMillies, pfEvents, pid);
-
- ASMAtomicWriteBool(&pThis->fBusy, false);
-
- return rc;
-}
-
-
-RTDECL(int) RTPollSetCreate(PRTPOLLSET phPollSet)
-{
- AssertPtrReturn(phPollSet, VERR_INVALID_POINTER);
- RTPOLLSETINTERNAL *pThis = (RTPOLLSETINTERNAL *)RTMemAllocZ(sizeof(RTPOLLSETINTERNAL));
- if (!pThis)
- return VERR_NO_MEMORY;
-
- pThis->u32Magic = RTPOLLSET_MAGIC;
- pThis->fBusy = false;
- pThis->cHandles = 0;
- for (size_t i = 0; i < RT_ELEMENTS(pThis->ahNative); i++)
- pThis->ahNative[i] = INVALID_HANDLE_VALUE;
-
- *phPollSet = pThis;
- return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTPollSetDestroy(RTPOLLSET hPollSet)
-{
- RTPOLLSETINTERNAL *pThis = hPollSet;
- if (pThis == NIL_RTPOLLSET)
- return VINF_SUCCESS;
- AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
-
- ASMAtomicWriteU32(&pThis->u32Magic, ~RTPOLLSET_MAGIC);
- RTMemFree(pThis);
-
- return VINF_SUCCESS;
-}
-
-
-RTDECL(int) RTPollSetAdd(RTPOLLSET hPollSet, PCRTHANDLE pHandle, uint32_t fEvents, uint32_t id)
-{
- /*
- * Validate the input (tedious).
- */
- RTPOLLSETINTERNAL *pThis = hPollSet;
- AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
- AssertReturn(!(fEvents & ~RTPOLL_EVT_VALID_MASK), VERR_INVALID_PARAMETER);
- AssertReturn(fEvents, VERR_INVALID_PARAMETER);
- AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
-
- if (!pHandle)
- return VINF_SUCCESS;
- AssertPtrReturn(pHandle, VERR_INVALID_POINTER);
- AssertReturn(pHandle->enmType > RTHANDLETYPE_INVALID && pHandle->enmType < RTHANDLETYPE_END, VERR_INVALID_PARAMETER);
-
- /*
- * Set the busy flag and do the job.
- */
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
-
- int rc = VINF_SUCCESS;
- HANDLE hNative = INVALID_HANDLE_VALUE;
- RTHANDLEUNION uh;
- uh.uInt = 0;
- switch (pHandle->enmType)
- {
- case RTHANDLETYPE_PIPE:
- uh.hPipe = pHandle->u.hPipe;
- if (uh.hPipe != NIL_RTPIPE)
- rc = rtPipePollGetHandle(uh.hPipe, fEvents, &hNative);
- break;
-
- case RTHANDLETYPE_SOCKET:
- uh.hSocket = pHandle->u.hSocket;
- if (uh.hSocket != NIL_RTSOCKET)
- rc = rtSocketPollGetHandle(uh.hSocket, fEvents, &hNative);
- break;
-
- case RTHANDLETYPE_FILE:
- AssertMsgFailed(("Files are always ready for reading/writing and thus not pollable. Use native APIs for special devices.\n"));
- rc = VERR_POLL_HANDLE_NOT_POLLABLE;
- break;
-
- case RTHANDLETYPE_THREAD:
- AssertMsgFailed(("Thread handles are currently not pollable\n"));
- rc = VERR_POLL_HANDLE_NOT_POLLABLE;
- break;
-
- default:
- AssertMsgFailed(("\n"));
- rc = VERR_POLL_HANDLE_NOT_POLLABLE;
- break;
- }
- if ( RT_SUCCESS(rc)
- && hNative != INVALID_HANDLE_VALUE)
- {
- uint32_t const i = pThis->cHandles;
-
- /* Check that the handle ID doesn't exist already. */
- uint32_t iPrev = UINT32_MAX;
- uint32_t j = i;
- while (j-- > 0)
- {
- if (pThis->aHandles[j].id == id)
- {
- rc = VERR_POLL_HANDLE_ID_EXISTS;
- break;
- }
- if ( pThis->aHandles[j].enmType == pHandle->enmType
- && pThis->aHandles[j].u.uInt == uh.uInt)
- iPrev = j;
- }
-
- /* Check that we won't overflow the poll set now. */
- if ( RT_SUCCESS(rc)
- && i + 1 > RT_ELEMENTS(pThis->ahNative))
- rc = VERR_POLL_SET_IS_FULL;
- if (RT_SUCCESS(rc))
- {
- /* Add the handles to the two parallel arrays. */
- pThis->ahNative[i] = hNative;
- pThis->aHandles[i].enmType = pHandle->enmType;
- pThis->aHandles[i].u = uh;
- pThis->aHandles[i].id = id;
- pThis->aHandles[i].fEvents = fEvents;
- pThis->aHandles[i].fFinalEntry = true;
- pThis->cHandles = i + 1;
-
- if (iPrev != UINT32_MAX)
- {
- Assert(pThis->aHandles[i].fFinalEntry);
- pThis->aHandles[i].fFinalEntry = false;
- }
-
- rc = VINF_SUCCESS;
- }
- }
-
- ASMAtomicWriteBool(&pThis->fBusy, false);
- return rc;
-}
-
-
-RTDECL(int) RTPollSetRemove(RTPOLLSET hPollSet, uint32_t id)
-{
- /*
- * Validate the input.
- */
- RTPOLLSETINTERNAL *pThis = hPollSet;
- AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
- AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
-
- /*
- * Set the busy flag and do the job.
- */
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
-
- int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
- uint32_t i = pThis->cHandles;
- while (i-- > 0)
- if (pThis->aHandles[i].id == id)
- {
- /* Save some details for the duplicate searching. */
- bool fFinalEntry = pThis->aHandles[i].fFinalEntry;
- RTHANDLETYPE enmType = pThis->aHandles[i].enmType;
- RTHANDLEUNION uh = pThis->aHandles[i].u;
-
- /* Remove the entry. */
- pThis->cHandles--;
- size_t const cToMove = pThis->cHandles - i;
- if (cToMove)
- {
- memmove(&pThis->aHandles[i], &pThis->aHandles[i + 1], cToMove * sizeof(pThis->aHandles[i]));
- memmove(&pThis->ahNative[i], &pThis->ahNative[i + 1], cToMove * sizeof(pThis->ahNative[i]));
- }
-
- /* Check for duplicate and set the fFinalEntry flag. */
- if (fFinalEntry)
- while (i-- > 0)
- if ( pThis->aHandles[i].u.uInt == uh.uInt
- && pThis->aHandles[i].enmType == enmType)
- {
- Assert(!pThis->aHandles[i].fFinalEntry);
- pThis->aHandles[i].fFinalEntry = true;
- break;
- }
-
- rc = VINF_SUCCESS;
- break;
- }
-
- ASMAtomicWriteBool(&pThis->fBusy, false);
- return rc;
-}
-
-
-RTDECL(int) RTPollSetQueryHandle(RTPOLLSET hPollSet, uint32_t id, PRTHANDLE pHandle)
-{
- /*
- * Validate the input.
- */
- RTPOLLSETINTERNAL *pThis = hPollSet;
- AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
- AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
- AssertPtrNullReturn(pHandle, VERR_INVALID_POINTER);
-
- /*
- * Set the busy flag and do the job.
- */
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
-
- int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
- uint32_t i = pThis->cHandles;
- while (i-- > 0)
- if (pThis->aHandles[i].id == id)
- {
- if (pHandle)
- {
- pHandle->enmType = pThis->aHandles[i].enmType;
- pHandle->u = pThis->aHandles[i].u;
- }
- rc = VINF_SUCCESS;
- break;
- }
-
- ASMAtomicWriteBool(&pThis->fBusy, false);
- return rc;
-}
-
-
-RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
-{
- /*
- * Validate the input.
- */
- RTPOLLSETINTERNAL *pThis = hPollSet;
- AssertPtrReturn(pThis, UINT32_MAX);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, UINT32_MAX);
-
- /*
- * Set the busy flag and do the job.
- */
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), UINT32_MAX);
- uint32_t cHandles = pThis->cHandles;
- ASMAtomicWriteBool(&pThis->fBusy, false);
-
- return cHandles;
-}
-
-RTDECL(int) RTPollSetEventsChange(RTPOLLSET hPollSet, uint32_t id, uint32_t fEvents)
-{
- /*
- * Validate the input.
- */
- RTPOLLSETINTERNAL *pThis = hPollSet;
- AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
- AssertReturn(pThis->u32Magic == RTPOLLSET_MAGIC, VERR_INVALID_HANDLE);
- AssertReturn(id != UINT32_MAX, VERR_INVALID_PARAMETER);
- AssertReturn(!(fEvents & ~RTPOLL_EVT_VALID_MASK), VERR_INVALID_PARAMETER);
- AssertReturn(fEvents, VERR_INVALID_PARAMETER);
-
- /*
- * Set the busy flag and do the job.
- */
- AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
-
- int rc = VERR_POLL_HANDLE_ID_NOT_FOUND;
- uint32_t i = pThis->cHandles;
- while (i-- > 0)
- if (pThis->aHandles[i].id == id)
- {
- pThis->aHandles[i].fEvents = fEvents;
- rc = VINF_SUCCESS;
- break;
- }
-
- ASMAtomicWriteBool(&pThis->fBusy, false);
- return rc;
-}
-
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);
/*
diff --git a/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp b/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp
index 3b056cde..ab7ff7fc 100644
--- a/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp
+++ b/src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2008 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/sched-win.cpp b/src/VBox/Runtime/r3/win/sched-win.cpp
index 935bd651..54b8154b 100644
--- a/src/VBox/Runtime/r3/win/sched-win.cpp
+++ b/src/VBox/Runtime/r3/win/sched-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/semmutex-win.cpp b/src/VBox/Runtime/r3/win/semmutex-win.cpp
index 7cdab20b..e3ec555e 100644
--- a/src/VBox/Runtime/r3/win/semmutex-win.cpp
+++ b/src/VBox/Runtime/r3/win/semmutex-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/symlink-win.cpp b/src/VBox/Runtime/r3/win/symlink-win.cpp
index 30332539..52f5c410 100644
--- a/src/VBox/Runtime/r3/win/symlink-win.cpp
+++ b/src/VBox/Runtime/r3/win/symlink-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 2010-2011 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -29,8 +29,10 @@
* Header Files *
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_SYMLINK
+#include <Windows.h>
#include <iprt/symlink.h>
+#include "internal-r3-win.h"
#include <iprt/assert.h>
#include <iprt/err.h>
@@ -40,7 +42,6 @@
#include <iprt/string.h>
#include "internal/path.h"
-#include <Windows.h>
/*******************************************************************************
@@ -133,13 +134,9 @@ RTDECL(int) RTSymlinkCreate(const char *pszSymlink, const char *pszTarget, RTSYM
static bool s_fTried = FALSE;
if (!s_fTried)
{
- HMODULE hmod = LoadLibrary("KERNEL32.DLL");
- if (hmod)
- {
- PFNCREATESYMBOLICLINKW pfn = (PFNCREATESYMBOLICLINKW)GetProcAddress(hmod, "CreateSymbolicLinkW");
- if (pfn)
- s_pfnCreateSymbolicLinkW = pfn;
- }
+ PFNCREATESYMBOLICLINKW pfn = (PFNCREATESYMBOLICLINKW)GetProcAddress(g_hModKernel32, "CreateSymbolicLinkW");
+ if (pfn)
+ s_pfnCreateSymbolicLinkW = pfn;
s_fTried = true;
}
if (!s_pfnCreateSymbolicLinkW)
diff --git a/src/VBox/Runtime/r3/win/thread-win.cpp b/src/VBox/Runtime/r3/win/thread-win.cpp
index 788a616a..dab8cb70 100644
--- a/src/VBox/Runtime/r3/win/thread-win.cpp
+++ b/src/VBox/Runtime/r3/win/thread-win.cpp
@@ -68,6 +68,12 @@ DECLHIDDEN(int) rtThreadNativeInit(void)
}
+DECLHIDDEN(void) rtThreadNativeReInitObtrusive(void)
+{
+ /* nothing to do here. */
+}
+
+
DECLHIDDEN(void) rtThreadNativeDetach(void)
{
/*
@@ -167,7 +173,7 @@ static void rtThreadNativeUninitComAndOle(void)
AssertMsgFailed(("cComInits=%u (%#x) cOleInits=%u (%#x) - dangling COM/OLE inits!\n",
cComInits, cComInits, cOleInits, cOleInits));
- HMODULE hOle32 = GetModuleHandle("OLE32");
+ HMODULE hOle32 = GetModuleHandle("ole32.dll");
AssertReturnVoid(hOle32 != NULL);
typedef void (WINAPI *PFNOLEUNINITIALIZE)(void);
@@ -251,7 +257,7 @@ static int rtThreadGetCurrentProcessorNumber(void)
static DWORD (WINAPI *pfnGetCurrentProcessorNumber)(void) = NULL;
if (!fInitialized)
{
- HMODULE hmodKernel32 = GetModuleHandle("KERNEL32.DLL");
+ HMODULE hmodKernel32 = GetModuleHandle("kernel32.dll");
if (hmodKernel32)
pfnGetCurrentProcessorNumber = (DWORD (WINAPI*)(void))GetProcAddress(hmodKernel32, "GetCurrentProcessorNumber");
fInitialized = true;
diff --git a/src/VBox/Runtime/r3/win/time-win.cpp b/src/VBox/Runtime/r3/win/time-win.cpp
index bd4e768a..44dea140 100644
--- a/src/VBox/Runtime/r3/win/time-win.cpp
+++ b/src/VBox/Runtime/r3/win/time-win.cpp
@@ -39,13 +39,17 @@
#include <iprt/err.h>
#include "internal/time.h"
-#define USE_TICK_COUNT
+/*
+ * Note! The selected time source be the exact same one as we use in kernel land!
+ */
+//#define USE_TICK_COUNT
//#define USE_PERFORMANCE_COUNTER
-#if 0//defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
-# define USE_INTERRUPT_TIME
-#else
//# define USE_FILE_TIME
-#endif
+//#if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
+# define USE_INTERRUPT_TIME
+//#else
+//# define USE_TICK_COUNT
+//#endif
#ifdef USE_INTERRUPT_TIME
@@ -104,6 +108,7 @@ DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
return u64 * 100;
#elif defined USE_INTERRUPT_TIME
+# if 0 /* ASSUME 0x7ffe0000 is set in stone */
/*
* This is exactly what we want, but we have to obtain it by non-official
* means.
@@ -114,16 +119,18 @@ DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
/** @todo find official way of getting this or some more clever
* detection algorithm if necessary. The com debugger class
* exports this too, windbg knows it too... */
- s_pUserSharedData = (MY_ KUSER_SHARED_DATA *)(uintptr_t)0x7ffe0000;
+ s_pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
}
+# endif
+ PMY_KUSER_SHARED_DATA pUserSharedData = (PMY_KUSER_SHARED_DATA)(uintptr_t)0x7ffe0000;
/* use interrupt time */
LARGE_INTEGER Time;
do
{
- Time.HighPart = s_pUserSharedData->InterruptTime.High1Time;
- Time.LowPart = s_pUserSharedData->InterruptTime.LowPart;
- } while (s_pUserSharedData->InterruptTime.High2Time != Time.HighPart);
+ Time.HighPart = pUserSharedData->InterruptTime.High1Time;
+ Time.LowPart = pUserSharedData->InterruptTime.LowPart;
+ } while (pUserSharedData->InterruptTime.High2Time != Time.HighPart);
return (uint64_t)Time.QuadPart * 100;
diff --git a/src/VBox/Runtime/r3/win/timer-win.cpp b/src/VBox/Runtime/r3/win/timer-win.cpp
index 08ed4ec1..a23aa17a 100644
--- a/src/VBox/Runtime/r3/win/timer-win.cpp
+++ b/src/VBox/Runtime/r3/win/timer-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/tls-win.cpp b/src/VBox/Runtime/r3/win/tls-win.cpp
index 2bc332b7..51e0b23b 100644
--- a/src/VBox/Runtime/r3/win/tls-win.cpp
+++ b/src/VBox/Runtime/r3/win/tls-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/utf16locale-win.cpp b/src/VBox/Runtime/r3/win/utf16locale-win.cpp
index 40d99bb2..ccb51ade 100644
--- a/src/VBox/Runtime/r3/win/utf16locale-win.cpp
+++ b/src/VBox/Runtime/r3/win/utf16locale-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/Runtime/r3/win/uuid-win.cpp b/src/VBox/Runtime/r3/win/uuid-win.cpp
index 0d91df79..ef1a42bc 100644
--- a/src/VBox/Runtime/r3/win/uuid-win.cpp
+++ b/src/VBox/Runtime/r3/win/uuid-win.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;