diff options
Diffstat (limited to 'src/VBox/Runtime/r3/win')
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; |