summaryrefslogtreecommitdiff
path: root/src/VBox/Runtime/r3
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Runtime/r3')
-rw-r--r--src/VBox/Runtime/r3/alloc-ef-cpp.cpp2
-rw-r--r--src/VBox/Runtime/r3/alloc-ef.cpp2
-rw-r--r--src/VBox/Runtime/r3/alloc.cpp6
-rw-r--r--src/VBox/Runtime/r3/allocex.cpp126
-rw-r--r--src/VBox/Runtime/r3/allocex.h84
-rw-r--r--src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp65
-rw-r--r--src/VBox/Runtime/r3/darwin/mp-darwin.cpp83
-rw-r--r--src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp13
-rw-r--r--src/VBox/Runtime/r3/darwin/sched-darwin.cpp2
-rw-r--r--src/VBox/Runtime/r3/darwin/time-darwin.cpp2
-rw-r--r--src/VBox/Runtime/r3/dir.cpp106
-rw-r--r--src/VBox/Runtime/r3/dir2.cpp2
-rw-r--r--src/VBox/Runtime/r3/fileio.cpp88
-rw-r--r--src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp12
-rw-r--r--src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp2
-rw-r--r--src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp2
-rw-r--r--src/VBox/Runtime/r3/fs.cpp3
-rw-r--r--src/VBox/Runtime/r3/generic/allocex-r3-generic.cpp (renamed from src/VBox/Runtime/r3/os2/poll-os2.cpp)52
-rw-r--r--src/VBox/Runtime/r3/generic/semspinmutex-r3-generic.cpp2
-rw-r--r--src/VBox/Runtime/r3/haiku/rtProcInitExePath-haiku.cpp60
-rw-r--r--src/VBox/Runtime/r3/haiku/time-haiku.cpp84
-rw-r--r--src/VBox/Runtime/r3/init.cpp157
-rw-r--r--src/VBox/Runtime/r3/init.h38
-rw-r--r--src/VBox/Runtime/r3/isofs.cpp2
-rw-r--r--src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp2
-rw-r--r--src/VBox/Runtime/r3/linux/RTSystemShutdown-linux.cpp13
-rw-r--r--src/VBox/Runtime/r3/linux/fileaio-linux.cpp12
-rw-r--r--src/VBox/Runtime/r3/linux/mp-linux.cpp70
-rw-r--r--src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp2
-rw-r--r--src/VBox/Runtime/r3/linux/sched-linux.cpp2
-rw-r--r--src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp2
-rw-r--r--src/VBox/Runtime/r3/linux/semmutex-linux.cpp2
-rw-r--r--src/VBox/Runtime/r3/linux/sysfs.cpp166
-rw-r--r--src/VBox/Runtime/r3/linux/systemmem-linux.cpp42
-rw-r--r--src/VBox/Runtime/r3/linux/time-linux.cpp2
-rw-r--r--src/VBox/Runtime/r3/nt/Makefile.kup0
-rw-r--r--src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp697
-rw-r--r--src/VBox/Runtime/r3/nt/fs-nt.cpp284
-rw-r--r--src/VBox/Runtime/r3/nt/internal-r3-nt.h140
-rw-r--r--src/VBox/Runtime/r3/nt/pathint-nt.cpp356
-rw-r--r--src/VBox/Runtime/r3/os2/filelock-os2.cpp2
-rw-r--r--src/VBox/Runtime/r3/os2/mp-os2.cpp2
-rw-r--r--src/VBox/Runtime/r3/os2/pipe-os2.cpp956
-rw-r--r--src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp2
-rw-r--r--src/VBox/Runtime/r3/os2/sched-os2.cpp2
-rw-r--r--src/VBox/Runtime/r3/os2/sems-os2.cpp2
-rw-r--r--src/VBox/Runtime/r3/os2/systemmem-os2.cpp70
-rw-r--r--src/VBox/Runtime/r3/os2/thread-os2.cpp25
-rw-r--r--src/VBox/Runtime/r3/path.cpp2
-rw-r--r--src/VBox/Runtime/r3/poll.cpp1109
-rw-r--r--src/VBox/Runtime/r3/posix/RTFileQueryFsSizes-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/RTHandleGetStandard-posix.cpp3
-rw-r--r--src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/RTPathUserHome-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/RTTimeNow-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/allocex-r3-posix.cpp109
-rw-r--r--src/VBox/Runtime/r3/posix/dir-posix.cpp31
-rw-r--r--src/VBox/Runtime/r3/posix/env-posix.cpp41
-rw-r--r--src/VBox/Runtime/r3/posix/fileaio-posix.cpp10
-rw-r--r--src/VBox/Runtime/r3/posix/fileio-posix.cpp16
-rw-r--r--src/VBox/Runtime/r3/posix/fileio2-posix.cpp36
-rw-r--r--src/VBox/Runtime/r3/posix/filelock-posix.cpp3
-rw-r--r--src/VBox/Runtime/r3/posix/fs-posix.cpp4
-rw-r--r--src/VBox/Runtime/r3/posix/fs2-posix.cpp5
-rw-r--r--src/VBox/Runtime/r3/posix/ldrNative-posix.cpp12
-rw-r--r--src/VBox/Runtime/r3/posix/path-posix.cpp7
-rw-r--r--src/VBox/Runtime/r3/posix/path2-posix.cpp4
-rw-r--r--src/VBox/Runtime/r3/posix/pathhost-posix.cpp14
-rw-r--r--src/VBox/Runtime/r3/posix/pipe-posix.cpp19
-rw-r--r--src/VBox/Runtime/r3/posix/poll-posix.cpp519
-rw-r--r--src/VBox/Runtime/r3/posix/process-creation-posix.cpp71
-rw-r--r--src/VBox/Runtime/r3/posix/process-posix.cpp3
-rw-r--r--src/VBox/Runtime/r3/posix/rand-posix.cpp8
-rw-r--r--src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp19
-rw-r--r--src/VBox/Runtime/r3/posix/sched-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/semevent-posix.cpp6
-rw-r--r--src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp4
-rw-r--r--src/VBox/Runtime/r3/posix/semmutex-posix.cpp59
-rw-r--r--src/VBox/Runtime/r3/posix/semrw-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/symlink-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/thread-posix.cpp148
-rw-r--r--src/VBox/Runtime/r3/posix/thread2-posix.cpp8
-rw-r--r--src/VBox/Runtime/r3/posix/time-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/timelocal-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/timer-posix.cpp20
-rw-r--r--src/VBox/Runtime/r3/posix/tls-posix.cpp2
-rw-r--r--src/VBox/Runtime/r3/posix/utf8-posix.cpp26
-rw-r--r--src/VBox/Runtime/r3/process.cpp2
-rw-r--r--src/VBox/Runtime/r3/socket.cpp119
-rw-r--r--src/VBox/Runtime/r3/solaris/Makefile.kup0
-rw-r--r--src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp102
-rw-r--r--src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp56
-rw-r--r--src/VBox/Runtime/r3/solaris/coredumper-solaris.h2
-rw-r--r--src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp14
-rw-r--r--src/VBox/Runtime/r3/solaris/mp-solaris.cpp182
-rw-r--r--src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp2
-rw-r--r--src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp172
-rw-r--r--src/VBox/Runtime/r3/stream.cpp3
-rw-r--r--src/VBox/Runtime/r3/tcp.cpp48
-rw-r--r--src/VBox/Runtime/r3/test.cpp350
-rw-r--r--src/VBox/Runtime/r3/testi.cpp2
-rw-r--r--src/VBox/Runtime/r3/udp.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/RTHandleGetStandard-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/RTLogWriteDebugger-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/RTSystemQueryDmiString-win.cpp10
-rw-r--r--src/VBox/Runtime/r3/win/RTSystemQueryOSInfo-win.cpp228
-rw-r--r--src/VBox/Runtime/r3/win/RTSystemShutdown-win.cpp12
-rw-r--r--src/VBox/Runtime/r3/win/RTUuidCreate-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-openssl-ose.def22
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-openssl.def12
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-win32.def2
-rw-r--r--src/VBox/Runtime/r3/win/VBoxRT-win64.def2
-rw-r--r--src/VBox/Runtime/r3/win/alloc-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/allocex-win.cpp120
-rw-r--r--src/VBox/Runtime/r3/win/dir-win.cpp342
-rw-r--r--src/VBox/Runtime/r3/win/direnum-win.cpp389
-rw-r--r--src/VBox/Runtime/r3/win/dllmain-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/env-win.cpp268
-rw-r--r--src/VBox/Runtime/r3/win/fileaio-win.cpp14
-rw-r--r--src/VBox/Runtime/r3/win/fs-win.cpp5
-rw-r--r--src/VBox/Runtime/r3/win/init-win.cpp273
-rw-r--r--src/VBox/Runtime/r3/win/internal-r3-win.h72
-rw-r--r--src/VBox/Runtime/r3/win/ldrNative-win.cpp54
-rw-r--r--src/VBox/Runtime/r3/win/localipc-win.cpp782
-rw-r--r--src/VBox/Runtime/r3/win/mp-win.cpp69
-rw-r--r--src/VBox/Runtime/r3/win/ntdll-mini-implib.c111
-rw-r--r--src/VBox/Runtime/r3/win/ntdll-mini-implib.def9
-rw-r--r--src/VBox/Runtime/r3/win/path-win.cpp4
-rw-r--r--src/VBox/Runtime/r3/win/pipe-win.cpp22
-rw-r--r--src/VBox/Runtime/r3/win/poll-win.cpp586
-rw-r--r--src/VBox/Runtime/r3/win/process-win.cpp283
-rw-r--r--src/VBox/Runtime/r3/win/rtProcInitExePath-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/sched-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/semmutex-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/symlink-win.cpp15
-rw-r--r--src/VBox/Runtime/r3/win/thread-win.cpp10
-rw-r--r--src/VBox/Runtime/r3/win/time-win.cpp25
-rw-r--r--src/VBox/Runtime/r3/win/timer-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/tls-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/utf16locale-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/win/uuid-win.cpp2
-rw-r--r--src/VBox/Runtime/r3/xml.cpp975
143 files changed, 8953 insertions, 3029 deletions
diff --git a/src/VBox/Runtime/r3/alloc-ef-cpp.cpp b/src/VBox/Runtime/r3/alloc-ef-cpp.cpp
index 7aa12880..eb8614e3 100644
--- a/src/VBox/Runtime/r3/alloc-ef-cpp.cpp
+++ b/src/VBox/Runtime/r3/alloc-ef-cpp.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;
diff --git a/src/VBox/Runtime/r3/alloc-ef.cpp b/src/VBox/Runtime/r3/alloc-ef.cpp
index 16892e29..570800be 100644
--- a/src/VBox/Runtime/r3/alloc-ef.cpp
+++ b/src/VBox/Runtime/r3/alloc-ef.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;
diff --git a/src/VBox/Runtime/r3/alloc.cpp b/src/VBox/Runtime/r3/alloc.cpp
index 94889c10..98892aaa 100644
--- a/src/VBox/Runtime/r3/alloc.cpp
+++ b/src/VBox/Runtime/r3/alloc.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;
@@ -39,6 +39,10 @@
# undef RTMEMALLOC_USE_TRACKER
#endif
+#if defined(RTMEMALLOC_USE_TRACKER) && defined(RTALLOC_USE_EFENCE)
+# error "Cannot define both RTMEMALLOC_USE_TRACKER and RTALLOC_USE_EFENCE!"
+#endif
+
/*******************************************************************************
* Header Files *
diff --git a/src/VBox/Runtime/r3/allocex.cpp b/src/VBox/Runtime/r3/allocex.cpp
new file mode 100644
index 00000000..c1bd6a40
--- /dev/null
+++ b/src/VBox/Runtime/r3/allocex.cpp
@@ -0,0 +1,126 @@
+/* $Id: allocex.cpp $ */
+/** @file
+ * IPRT - Memory Allocation, Extended Alloc and Free Functions for Ring-3, posix.
+ */
+
+/*
+ * 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 "internal/magics.h"
+#include "allocex.h"
+
+
+RTDECL(int) RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) RT_NO_THROW
+{
+ /*
+ * Validate and adjust input.
+ */
+ AssertMsgReturn(!(fFlags & ~RTMEMALLOCEX_FLAGS_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
+ AssertReturn(cb > 0, VERR_INVALID_PARAMETER);
+ AssertReturn(RT_IS_POWER_OF_TWO(cbAlignment), VERR_INVALID_PARAMETER);
+ AssertMsgReturn(cbAlignment <= sizeof(void *), ("%zu (%#x)\n", cbAlignment, cbAlignment), VERR_UNSUPPORTED_ALIGNMENT);
+
+ if (fFlags & RTMEMALLOCEX_FLAGS_ANY_CTX)
+ return VERR_NOT_SUPPORTED;
+
+ /*
+ * Align the request.
+ */
+ size_t cbAligned = cb;
+ if (cbAlignment)
+ cbAligned = RT_ALIGN_Z(cb, cbAlignment);
+ else
+ cbAligned = RT_ALIGN_Z(cb, sizeof(uint64_t));
+ AssertMsgReturn(cbAligned >= cb && cbAligned <= ~(size_t)0, ("cbAligned=%#zx cb=%#zx", cbAligned, cb),
+ VERR_INVALID_PARAMETER);
+
+ /*
+ * Allocate the requested memory.
+ */
+ void *pv;
+ if (fFlags & (RTMEMALLOCEX_FLAGS_16BIT_REACH | RTMEMALLOCEX_FLAGS_32BIT_REACH))
+ {
+ int rc;
+ if (fFlags & RTMEMALLOCEX_FLAGS_16BIT_REACH)
+ rc = rtMemAllocEx16BitReach(cbAligned + sizeof(RTMEMHDRR3), fFlags, &pv);
+ else
+ rc = rtMemAllocEx32BitReach(cbAligned + sizeof(RTMEMHDRR3), fFlags, &pv);
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+ else if (fFlags & RTMEMALLOCEX_FLAGS_EXEC)
+ {
+ pv = RTMemExecAlloc(cbAligned + sizeof(RTMEMHDRR3));
+ if ((fFlags & RTMEMALLOCEX_FLAGS_ZEROED) && pv)
+ RT_BZERO(pv, cbAligned + sizeof(RTMEMHDRR3));
+ }
+ else if (fFlags & RTMEMALLOCEX_FLAGS_ZEROED)
+ pv = RTMemAllocZ(cbAligned + sizeof(RTMEMHDRR3));
+ else
+ pv = RTMemAlloc(cbAligned + sizeof(RTMEMHDRR3));
+ if (!pv)
+ return VERR_NO_MEMORY;
+
+ /*
+ * Fill in the header and return.
+ */
+ PRTMEMHDRR3 pHdr = (PRTMEMHDRR3)pv;
+ pHdr->u32Magic = RTMEMHDR_MAGIC;
+ pHdr->fFlags = fFlags;
+ pHdr->cb = (uint32_t)cbAligned;
+ pHdr->cbReq = (uint32_t)cb;
+
+ *ppv = pHdr + 1;
+ return VINF_SUCCESS;
+}
+RT_EXPORT_SYMBOL(RTMemAllocExTag);
+
+
+RTDECL(void) RTMemFreeEx(void *pv, size_t cb) RT_NO_THROW
+{
+ if (!pv)
+ return;
+ AssertPtr(pv);
+
+ PRTMEMHDRR3 pHdr = (PRTMEMHDRR3)pv - 1;
+ AssertMsg(pHdr->u32Magic == RTMEMHDR_MAGIC, ("pHdr->u32Magic=%RX32 pv=%p cb=%#x\n", pHdr->u32Magic, pv, cb));
+ pHdr->u32Magic = RTMEMHDR_MAGIC_DEAD;
+ Assert(pHdr->cbReq == cb);
+
+ if (pHdr->fFlags & (RTMEMALLOCEX_FLAGS_16BIT_REACH | RTMEMALLOCEX_FLAGS_32BIT_REACH))
+ rtMemFreeExYyBitReach(pHdr, pHdr->cb + sizeof(*pHdr), pHdr->fFlags);
+ else if (pHdr->fFlags & RTMEMALLOCEX_FLAGS_EXEC)
+ RTMemExecFree(pHdr, pHdr->cb + sizeof(*pHdr));
+ else
+ RTMemFree(pHdr);
+}
+RT_EXPORT_SYMBOL(RTMemFreeEx);
+
diff --git a/src/VBox/Runtime/r3/allocex.h b/src/VBox/Runtime/r3/allocex.h
new file mode 100644
index 00000000..2724335c
--- /dev/null
+++ b/src/VBox/Runtime/r3/allocex.h
@@ -0,0 +1,84 @@
+/* $Id: allocex.h $ */
+/** @file
+ * IPRT - Memory Allocation, Extended Alloc and Free Functions for Ring-3.
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef ___r3_allocex_h
+#define ___r3_allocex_h
+
+#include <iprt/types.h>
+
+/**
+ * Heading for extended memory allocations in ring-3.
+ */
+typedef struct RTMEMHDRR3
+{
+ /** Magic (RTMEMHDR_MAGIC). */
+ uint32_t u32Magic;
+ /** Block flags (RTMEMALLOCEX_FLAGS_*). */
+ uint32_t fFlags;
+ /** The actual size of the block, header not included. */
+ uint32_t cb;
+ /** The requested allocation size. */
+ uint32_t cbReq;
+} RTMEMHDRR3;
+/** Pointer to a ring-3 extended memory header. */
+typedef RTMEMHDRR3 *PRTMEMHDRR3;
+
+
+/**
+ * Allocate memory in below 64KB.
+ *
+ * @returns IPRT status code.
+ * @param cbAlloc Number of bytes to allocate (including the
+ * header if the caller needs one).
+ * @param fFlags Allocation flags.
+ * @param ppv Where to return the pointer to the memory.
+ */
+DECLHIDDEN(int) rtMemAllocEx16BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv);
+
+/**
+ * Allocate memory in below 4GB.
+ *
+ * @returns IPRT status code.
+ * @param cbAlloc Number of bytes to allocate (including the
+ * header if the caller needs one).
+ * @param fFlags Allocation flags.
+ * @param ppv Where to return the pointer to the memory.
+ */
+DECLHIDDEN(int) rtMemAllocEx32BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv);
+
+
+/**
+ * Frees memory allocated by rtMemAllocEx16BitReach and rtMemAllocEx32BitReach.
+ *
+ * @param pv Start of allocation.
+ * @param cb Allocation size.
+ * @param fFlags Allocation flags.
+ */
+DECLHIDDEN(void) rtMemFreeExYyBitReach(void *pv, size_t cb, uint32_t fFlags);
+
+#endif
+
diff --git a/src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp b/src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp
index 2b033b2f..aae99908 100644
--- a/src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp
+++ b/src/VBox/Runtime/r3/darwin/RTPathUserDocuments-darwin.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2011 Oracle Corporation
+ * Copyright (C) 2011-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,10 +28,18 @@
* Header Files *
*******************************************************************************/
#include <iprt/path.h>
-#include <iprt/err.h>
+#include "internal/iprt.h"
+
#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <iprt/err.h>
+
+#include <NSSystemDirectories.h>
+#include <sys/syslimits.h>
+#ifdef IPRT_USE_CORE_SERVICE_FOR_USER_DOCUMENTS
+# include <CoreServices/CoreServices.h>
+#endif
-#include <CoreServices/CoreServices.h>
RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath)
{
@@ -41,15 +49,50 @@ RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath)
AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
AssertReturn(cchPath, VERR_INVALID_PARAMETER);
- FSRef ref;
- OSErr err = FSFindFolder(kOnAppropriateDisk, kDocumentsFolderType, false /* createFolder */, &ref);
- if (err != noErr)
- return VERR_PATH_NOT_FOUND;
+ /*
+ * Try NSSystemDirectories first since that works for directories that doesn't exist.
+ */
+ int rc = VERR_PATH_NOT_FOUND;
+ NSSearchPathEnumerationState EnmState = NSStartSearchPathEnumeration(NSDocumentDirectory, NSUserDomainMask);
+ if (EnmState != 0)
+ {
+ char szTmp[PATH_MAX];
+ szTmp[0] = szTmp[PATH_MAX - 1] = '\0';
+ EnmState = NSGetNextSearchPathEnumeration(EnmState, szTmp);
+ if (EnmState != 0)
+ {
+ size_t cchTmp = strlen(szTmp);
+ if (cchTmp >= cchPath)
+ return VERR_BUFFER_OVERFLOW;
- err = FSRefMakePath(&ref, (UInt8*)pszPath, cchPath);
- if (err != noErr)
- return VERR_PATH_NOT_FOUND;
+ if (szTmp[0] == '~' && szTmp[1] == '/')
+ {
+ /* Expand tilde. */
+ rc = RTPathUserHome(pszPath, cchPath - cchTmp + 2);
+ if (RT_FAILURE(rc))
+ return rc;
+ rc = RTPathAppend(pszPath, cchPath, &szTmp[2]);
+ }
+ else
+ rc = RTStrCopy(pszPath, cchPath, szTmp);
+ return rc;
+ }
+ }
- return VINF_SUCCESS;
+#ifdef IPRT_USE_CORE_SERVICE_FOR_USER_DOCUMENTS
+ /*
+ * Fall back on FSFindFolder in case the above should fail...
+ */
+ FSRef ref;
+ OSErr err = FSFindFolder(kOnAppropriateDisk, kDocumentsFolderType, false /* createFolder */, &ref);
+ if (err == noErr)
+ {
+ err = FSRefMakePath(&ref, (UInt8*)pszPath, cchPath);
+ if (err == noErr)
+ return VINF_SUCCESS;
+ }
+#endif
+ Assert(RT_FAILURE_NP(rc));
+ return rc;
}
diff --git a/src/VBox/Runtime/r3/darwin/mp-darwin.cpp b/src/VBox/Runtime/r3/darwin/mp-darwin.cpp
index 9942686a..bfdeb0d4 100644
--- a/src/VBox/Runtime/r3/darwin/mp-darwin.cpp
+++ b/src/VBox/Runtime/r3/darwin/mp-darwin.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2008 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;
@@ -46,18 +46,63 @@
/**
- * Internal worker that determines the max possible CPU count.
+ * Internal worker that determines the max possible logical CPU count (hyperthreads).
*
* @returns Max cpus.
*/
-static RTCPUID rtMpDarwinMaxCpus(void)
+static RTCPUID rtMpDarwinMaxLogicalCpus(void)
{
- int aiMib[2];
- aiMib[0] = CTL_HW;
- aiMib[1] = HW_NCPU;
int cCpus = -1;
size_t cb = sizeof(cCpus);
- int rc = sysctl(aiMib, RT_ELEMENTS(aiMib), &cCpus, &cb, NULL, 0);
+ int rc = sysctlbyname("hw.logicalcpu_max", &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 1;
+}
+
+/**
+ * Internal worker that determines the max possible physical core count.
+ *
+ * @returns Max cpus.
+ */
+static RTCPUID rtMpDarwinMaxPhysicalCpus(void)
+{
+ int cCpus = -1;
+ size_t cb = sizeof(cCpus);
+ int rc = sysctlbyname("hw.physicalcpu_max", &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 1;
+}
+
+/**
+ * Internal worker that determines the current number of logical CPUs (hyperthreads).
+ *
+ * @returns Max cpus.
+ */
+static RTCPUID rtMpDarwinOnlineLogicalCpus(void)
+{
+ int cCpus = -1;
+ size_t cb = sizeof(cCpus);
+ int rc = sysctlbyname("hw.logicalcpu", &cCpus, &cb, NULL, 0);
+ if (rc != -1 && cCpus >= 1)
+ return cCpus;
+ AssertFailed();
+ return 1;
+}
+
+/**
+ * Internal worker that determines the current number of physical CPUs.
+ *
+ * @returns Max cpus.
+ */
+static RTCPUID rtMpDarwinOnlinePhysicalCpus(void)
+{
+ int cCpus = -1;
+ size_t cb = sizeof(cCpus);
+ int rc = sysctlbyname("hw.physicalcpu", &cCpus, &cb, NULL, 0);
if (rc != -1 && cCpus >= 1)
return cCpus;
AssertFailed();
@@ -69,19 +114,19 @@ static RTCPUID rtMpDarwinMaxCpus(void)
RTDECL(int) RTMpCpuIdToSetIndex(RTCPUID idCpu)
{
- return idCpu < RTCPUSET_MAX_CPUS && idCpu < rtMpDarwinMaxCpus() ? idCpu : -1;
+ return idCpu < RTCPUSET_MAX_CPUS && idCpu < rtMpDarwinMaxLogicalCpus() ? idCpu : -1;
}
RTDECL(RTCPUID) RTMpCpuIdFromSetIndex(int iCpu)
{
- return (unsigned)iCpu < rtMpDarwinMaxCpus() ? iCpu : NIL_RTCPUID;
+ return (unsigned)iCpu < rtMpDarwinMaxLogicalCpus() ? iCpu : NIL_RTCPUID;
}
RTDECL(RTCPUID) RTMpGetMaxCpuId(void)
{
- return rtMpDarwinMaxCpus() - 1;
+ return rtMpDarwinMaxLogicalCpus() - 1;
}
@@ -97,7 +142,7 @@ RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
kern_return_t krc = host_processor_info(mach_host_self(),
PROCESSOR_BASIC_INFO, &nCpus, (processor_info_array_t*)&pinfo, &count);
AssertReturn (krc == KERN_SUCCESS, true);
- bool isOnline = idCpu < nCpus ? pinfo[idCpu].running : true;
+ bool isOnline = idCpu < nCpus ? pinfo[idCpu].running : false;
vm_deallocate(mach_task_self(), (vm_address_t)pinfo, count * sizeof(*pinfo));
return isOnline;
#endif
@@ -107,19 +152,19 @@ RTDECL(bool) RTMpIsCpuOnline(RTCPUID idCpu)
RTDECL(bool) RTMpIsCpuPossible(RTCPUID idCpu)
{
return idCpu != NIL_RTCPUID
- && idCpu < rtMpDarwinMaxCpus();
+ && idCpu < rtMpDarwinMaxLogicalCpus();
}
RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
{
#if 0
- RTCPUID cCpus = rtMpDarwinMaxCpus();
+ RTCPUID cCpus = rtMpDarwinMaxLogicalCpus();
return RTCpuSetFromU64(RT_BIT_64(cCpus) - 1);
#else
RTCpuSetEmpty(pSet);
- RTCPUID cMax = rtMpDarwinMaxCpus();
+ RTCPUID cMax = rtMpDarwinMaxLogicalCpus();
for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
if (RTMpIsCpuPossible(idCpu))
RTCpuSetAdd(pSet, idCpu);
@@ -130,7 +175,13 @@ RTDECL(PRTCPUSET) RTMpGetSet(PRTCPUSET pSet)
RTDECL(RTCPUID) RTMpGetCount(void)
{
- return rtMpDarwinMaxCpus();
+ return rtMpDarwinMaxLogicalCpus();
+}
+
+
+RTDECL(RTCPUID) RTMpGetCoreCount(void)
+{
+ return rtMpDarwinMaxPhysicalCpus();
}
@@ -140,7 +191,7 @@ RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
return RTMpGetSet(pSet);
#else
RTCpuSetEmpty(pSet);
- RTCPUID cMax = rtMpDarwinMaxCpus();
+ RTCPUID cMax = rtMpDarwinMaxLogicalCpus();
for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
if (RTMpIsCpuOnline(idCpu))
RTCpuSetAdd(pSet, idCpu);
diff --git a/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp
index 103e70b4..922bd41e 100644
--- a/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.cpp
+++ b/src/VBox/Runtime/r3/darwin/rtProcInitExePath-darwin.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;
@@ -32,6 +32,9 @@
# include <mach-o/dyld.h>
#endif
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
#include <iprt/string.h>
#include <iprt/assert.h>
#include <iprt/err.h>
@@ -48,7 +51,13 @@ DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
const char *pszImageName = _dyld_get_image_name(0);
AssertReturn(pszImageName, VERR_INTERNAL_ERROR);
- int rc = rtPathFromNativeCopy(pszPath, cchPath, pszImageName, NULL);
+ char szTmpPath[PATH_MAX + 1];
+ const char *psz = realpath(pszImageName, szTmpPath);
+ int rc;
+ if (psz)
+ rc = rtPathFromNativeCopy(pszPath, cchPath, szTmpPath, NULL);
+ else
+ rc = RTErrConvertFromErrno(errno);
AssertMsgRCReturn(rc, ("rc=%Rrc pszLink=\"%s\"\nhex: %.*Rhxs\n", rc, pszPath, strlen(pszImageName), pszPath), rc);
return VINF_SUCCESS;
diff --git a/src/VBox/Runtime/r3/darwin/sched-darwin.cpp b/src/VBox/Runtime/r3/darwin/sched-darwin.cpp
index ad47cdbb..3879db8c 100644
--- a/src/VBox/Runtime/r3/darwin/sched-darwin.cpp
+++ b/src/VBox/Runtime/r3/darwin/sched-darwin.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 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/darwin/time-darwin.cpp b/src/VBox/Runtime/r3/darwin/time-darwin.cpp
index 38878c63..a737d01b 100644
--- a/src/VBox/Runtime/r3/darwin/time-darwin.cpp
+++ b/src/VBox/Runtime/r3/darwin/time-darwin.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/dir.cpp b/src/VBox/Runtime/r3/dir.cpp
index 16f2577e..1cfa50d7 100644
--- a/src/VBox/Runtime/r3/dir.cpp
+++ b/src/VBox/Runtime/r3/dir.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;
@@ -29,14 +29,6 @@
* Header Files *
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_DIR
-#ifdef RT_OS_WINDOWS /* PORTME: Assumes everyone else is using dir-posix.cpp */
-# include <Windows.h>
-#else
-# include <dirent.h>
-# include <unistd.h>
-# include <limits.h>
-#endif
-
#include <iprt/dir.h>
#include "internal/iprt.h"
@@ -49,6 +41,7 @@
#include <iprt/path.h>
#include <iprt/string.h>
#include <iprt/uni.h>
+#define RTDIR_AGNOSTIC
#include "internal/dir.h"
#include "internal/path.h"
@@ -533,7 +526,7 @@ static int rtDirOpenCommon(PRTDIR *ppDir, const char *pszPath, const char *pszFi
if (!pszFilter)
{
cbFilter = cucFilter0 = 0;
- rc = RTPathReal(pszPath, szRealPath, sizeof(szRealPath) - 1);
+ rc = RTPathAbs(pszPath, szRealPath, sizeof(szRealPath) - 1);
}
else
{
@@ -547,7 +540,7 @@ static int rtDirOpenCommon(PRTDIR *ppDir, const char *pszPath, const char *pszFi
if (!pszTmp)
return VERR_NO_MEMORY;
pszTmp[pszFilter - pszPath] = '\0';
- rc = RTPathReal(pszTmp, szRealPath, sizeof(szRealPath) - 1);
+ rc = RTPathAbs(pszTmp, szRealPath, sizeof(szRealPath) - 1);
RTStrFree(pszTmp);
}
else
@@ -570,34 +563,19 @@ static int rtDirOpenCommon(PRTDIR *ppDir, const char *pszPath, const char *pszFi
* The posix definition of Data.d_name allows it to be < NAME_MAX + 1,
* thus the horrible ugliness here. Solaris uses d_name[1] for instance.
*/
-#ifndef RT_OS_WINDOWS
- long cbNameMax = pathconf(szRealPath, _PC_NAME_MAX);
-# ifdef NAME_MAX
- if (cbNameMax < NAME_MAX) /* This is plain paranoia, but it doesn't hurt. */
- cbNameMax = NAME_MAX;
-# endif
-# ifdef _XOPEN_NAME_MAX
- if (cbNameMax < _XOPEN_NAME_MAX) /* Ditto. */
- cbNameMax = _XOPEN_NAME_MAX;
-# endif
- size_t cbDir = RT_OFFSETOF(RTDIR, Data.d_name[cbNameMax + 1]);
- if (cbDir < sizeof(RTDIR)) /* Ditto. */
- cbDir = sizeof(RTDIR);
- cbDir = RT_ALIGN_Z(cbDir, 8);
-#else
- size_t cbDir = sizeof(RTDIR);
-#endif
+ size_t cbDir = rtDirNativeGetStructSize(szRealPath);
size_t const cbAllocated = cbDir
+ cucFilter0 * sizeof(RTUNICP)
+ cbFilter
+ cchRealPath + 1 + 4;
- PRTDIR pDir = (PRTDIR)RTMemAlloc(cbAllocated);
+ PRTDIR pDir = (PRTDIR)RTMemAllocZ(cbAllocated);
if (!pDir)
return VERR_NO_MEMORY;
uint8_t *pb = (uint8_t *)pDir + cbDir;
/* initialize it */
pDir->u32Magic = RTDIR_MAGIC;
+ pDir->cbSelf = cbDir;
if (cbFilter)
{
pDir->puszFilter = (PRTUNICP)pb;
@@ -638,9 +616,6 @@ static int rtDirOpenCommon(PRTDIR *ppDir, const char *pszPath, const char *pszFi
pDir->fDataUnread = false;
pDir->pszName = NULL;
pDir->cchName = 0;
-#ifndef RT_OS_WINDOWS
- pDir->cbMaxName = cbDir - RT_OFFSETOF(RTDIR, Data.d_name);
-#endif
/*
* Hand it over to the native part.
@@ -730,3 +705,70 @@ RTDECL(int) RTDirFlushParent(const char *pszChild)
return rc;
}
+
+RTDECL(int) RTDirQueryUnknownTypeEx(const char *pszComposedName, bool fFollowSymlinks,
+ RTDIRENTRYTYPE *penmType, PRTFSOBJINFO pObjInfo)
+{
+ int rc = RTPathQueryInfoEx(pszComposedName, pObjInfo, RTFSOBJATTRADD_NOTHING,
+ fFollowSymlinks ? RTPATH_F_FOLLOW_LINK : RTPATH_F_ON_LINK);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ if (RTFS_IS_DIRECTORY(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_DIRECTORY;
+ else if (RTFS_IS_FILE(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_FILE;
+ else if (RTFS_IS_SYMLINK(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_SYMLINK;
+ else if (RTFS_IS_FIFO(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_FIFO;
+ else if (RTFS_IS_DEV_CHAR(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_DEV_CHAR;
+ else if (RTFS_IS_DEV_BLOCK(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_DEV_BLOCK;
+ else if (RTFS_IS_SOCKET(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_SOCKET;
+ else if (RTFS_IS_WHITEOUT(pObjInfo->Attr.fMode))
+ *penmType = RTDIRENTRYTYPE_WHITEOUT;
+ else
+ *penmType = RTDIRENTRYTYPE_UNKNOWN;
+
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTDirQueryUnknownType(const char *pszComposedName, bool fFollowSymlinks, RTDIRENTRYTYPE *penmType)
+{
+ if ( *penmType != RTDIRENTRYTYPE_UNKNOWN
+ && ( !fFollowSymlinks
+ || *penmType != RTDIRENTRYTYPE_SYMLINK))
+ return VINF_SUCCESS;
+
+ RTFSOBJINFO ObjInfo;
+ return RTDirQueryUnknownTypeEx(pszComposedName, fFollowSymlinks, penmType, &ObjInfo);
+}
+
+
+RTDECL(bool) RTDirEntryIsStdDotLink(PRTDIRENTRY pDirEntry)
+{
+ if (pDirEntry->szName[0] != '.')
+ return false;
+ if (pDirEntry->cbName == 1)
+ return true;
+ if (pDirEntry->cbName != 2)
+ return false;
+ return pDirEntry->szName[1] == '.';
+}
+
+
+RTDECL(bool) RTDirEntryExIsStdDotLink(PCRTDIRENTRYEX pDirEntryEx)
+{
+ if (pDirEntryEx->szName[0] != '.')
+ return false;
+ if (pDirEntryEx->cbName == 1)
+ return true;
+ if (pDirEntryEx->cbName != 2)
+ return false;
+ return pDirEntryEx->szName[1] == '.';
+}
+
diff --git a/src/VBox/Runtime/r3/dir2.cpp b/src/VBox/Runtime/r3/dir2.cpp
index bec029de..f01f42c1 100644
--- a/src/VBox/Runtime/r3/dir2.cpp
+++ b/src/VBox/Runtime/r3/dir2.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;
diff --git a/src/VBox/Runtime/r3/fileio.cpp b/src/VBox/Runtime/r3/fileio.cpp
index 5b4e8873..fd1a2898 100644
--- a/src/VBox/Runtime/r3/fileio.cpp
+++ b/src/VBox/Runtime/r3/fileio.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;
@@ -208,6 +208,49 @@ RTR3DECL(int) RTFileReadAt(RTFILE File, RTFOFF off, void *pvBuf, size_t cbToRea
/**
+ * Read bytes from a file at a given offset into a S/G buffer.
+ * This function may modify the file position.
+ *
+ * @returns iprt status code.
+ * @param hFile Handle to the file.
+ * @param off Where to read.
+ * @param pSgBuf Pointer to the S/G buffer to read into.
+ * @param cbToRead How much to read.
+ * @param pcbRead How much we actually read.
+ * If NULL an error will be returned for a partial read.
+ */
+RTR3DECL(int) RTFileSgReadAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToRead, size_t *pcbRead)
+{
+ int rc = VINF_SUCCESS;
+ size_t cbRead = 0;
+
+ while (cbToRead)
+ {
+ size_t cbThisRead = 0;
+ size_t cbBuf = cbToRead;
+ void *pvBuf = RTSgBufGetNextSegment(pSgBuf, &cbBuf);
+
+ rc = RTFileReadAt(hFile, off, pvBuf, cbBuf, pcbRead ? &cbThisRead : NULL);
+ if (RT_SUCCESS(rc))
+ cbRead += cbThisRead;
+
+ if ( RT_FAILURE(rc)
+ || ( cbThisRead < cbBuf
+ && pcbRead))
+ break;
+
+ cbToRead -= cbBuf;
+ off += cbBuf;
+ }
+
+ if (pcbRead)
+ *pcbRead = cbRead;
+
+ return rc;
+}
+
+
+/**
* Write bytes to a file at a given offset.
* This function may modify the file position.
*
@@ -229,6 +272,49 @@ RTR3DECL(int) RTFileWriteAt(RTFILE File, RTFOFF off, const void *pvBuf, size_t
/**
+ * Write bytes from a S/G buffer to a file at a given offset.
+ * This function may modify the file position.
+ *
+ * @returns iprt status code.
+ * @param hFile Handle to the file.
+ * @param off Where to write.
+ * @param pSgBuf What to write.
+ * @param cbToWrite How much to write.
+ * @param pcbWritten How much we actually wrote.
+ * If NULL an error will be returned for a partial write.
+ */
+RTR3DECL(int) RTFileSgWriteAt(RTFILE hFile, RTFOFF off, PRTSGBUF pSgBuf, size_t cbToWrite, size_t *pcbWritten)
+{
+ int rc = VINF_SUCCESS;
+ size_t cbWritten = 0;
+
+ while (cbToWrite)
+ {
+ size_t cbThisWritten = 0;
+ size_t cbBuf = cbToWrite;
+ void *pvBuf = RTSgBufGetNextSegment(pSgBuf, &cbBuf);
+
+ rc = RTFileWriteAt(hFile, off, pvBuf, cbBuf, pcbWritten ? &cbThisWritten : NULL);
+ if (RT_SUCCESS(rc))
+ cbWritten += cbThisWritten;
+
+ if ( RT_FAILURE(rc)
+ || ( cbThisWritten < cbBuf
+ && pcbWritten))
+ break;
+
+ cbToWrite -= cbBuf;
+ off += cbBuf;
+ }
+
+ if (pcbWritten)
+ *pcbWritten = cbWritten;
+
+ return rc;
+}
+
+
+/**
* Gets the current file position.
*
* @returns File offset.
diff --git a/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp b/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp
index 1d47c759..b5ddfcca 100644
--- a/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.cpp
+++ b/src/VBox/Runtime/r3/freebsd/fileaio-freebsd.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;
@@ -66,6 +66,8 @@ typedef struct RTFILEAIOCTXINTERNAL
volatile bool fWokenUp;
/** Flag whether the thread is currently waiting in the syscall. */
volatile bool fWaiting;
+ /** Flags given during creation. */
+ uint32_t fFlags;
/** Magic value (RTFILEAIOCTX_MAGIC). */
uint32_t u32Magic;
} RTFILEAIOCTXINTERNAL;
@@ -299,11 +301,13 @@ RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
return pReqInt->Rc;
}
-RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
+RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax,
+ uint32_t fFlags)
{
int rc = VINF_SUCCESS;
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))
@@ -313,6 +317,7 @@ RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
pCtxInt->iKQueue = kqueue();
if (RT_LIKELY(pCtxInt->iKQueue > 0))
{
+ pCtxInt->fFlags = fFlags;
pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
*phAioCtx = (RTFILEAIOCTX)pCtxInt;
}
@@ -498,7 +503,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL
AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER);
AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE);
- if (RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0))
+ if ( RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0)
+ && !(pCtxInt->fFlags & RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS))
return VERR_FILE_AIO_NO_REQUEST;
/*
diff --git a/src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp b/src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp
index 8296025b..8475dd04 100644
--- a/src/VBox/Runtime/r3/freebsd/mp-freebsd.cpp
+++ b/src/VBox/Runtime/r3/freebsd/mp-freebsd.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;
diff --git a/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp b/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp
index 55112775..216c1004 100644
--- a/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.cpp
+++ b/src/VBox/Runtime/r3/freebsd/rtProcInitExePath-freebsd.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/fs.cpp b/src/VBox/Runtime/r3/fs.cpp
index dac1a5cc..b79e43d2 100644
--- a/src/VBox/Runtime/r3/fs.cpp
+++ b/src/VBox/Runtime/r3/fs.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;
@@ -205,6 +205,7 @@ RTDECL(const char *) RTFsTypeName(RTFSTYPE enmType)
case RTFSTYPE_SYSFS: return "sysfs";
case RTFSTYPE_PROC: return "proc";
case RTFSTYPE_OCFS2: return "ocfs2";
+ case RTFSTYPE_BTRFS: return "btrfs";
case RTFSTYPE_NTFS: return "ntfs";
case RTFSTYPE_FAT: return "fat";
diff --git a/src/VBox/Runtime/r3/os2/poll-os2.cpp b/src/VBox/Runtime/r3/generic/allocex-r3-generic.cpp
index 890cdc8c..dd1dea61 100644
--- a/src/VBox/Runtime/r3/os2/poll-os2.cpp
+++ b/src/VBox/Runtime/r3/generic/allocex-r3-generic.cpp
@@ -1,10 +1,10 @@
-/* $Id: poll-os2.cpp $ */
+/* $Id: allocex-r3-generic.cpp $ */
/** @file
- * IPRT - Polling I/O Handles, OS/2 Implementation.
+ * IPRT - Memory Allocation, Extended Alloc Workers, generic.
*/
/*
- * Copyright (C) 2010 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;
@@ -28,58 +28,30 @@
/*******************************************************************************
* Header Files *
*******************************************************************************/
-#include <iprt/poll.h>
+#define RTMEM_NO_WRAP_TO_EF_APIS
+#include <iprt/mem.h>
#include "internal/iprt.h"
#include <iprt/assert.h>
#include <iprt/err.h>
-#include "internal/magics.h"
+#include "../allocex.h"
-RTDECL(int) RTPoll(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
-{
- return VERR_NOT_IMPLEMENTED;
-}
-
-
-RTDECL(int) RTPollNoResume(RTPOLLSET hPollSet, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
-{
- return VERR_NOT_IMPLEMENTED;
-}
-
-
-RTDECL(int) RTPollSetCreate(PRTPOLLSET hPollSet)
-{
- return VERR_NOT_IMPLEMENTED;
-}
-
-
-RTDECL(int) RTPollSetDestroy(RTPOLLSET hPollSet)
-{
- return VERR_NOT_IMPLEMENTED;
-}
-
-
-RTDECL(int) RTPollSetAdd(RTPOLLSET hPollSet, PCRTHANDLE pHandle, uint32_t fEvents, uint32_t id)
-{
- return VERR_NOT_IMPLEMENTED;
-}
-
-RTDECL(int) RTPollSetRemove(RTPOLLSET hPollSet, uint32_t id)
+DECLHIDDEN(int) rtMemAllocEx16BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv)
{
- return VERR_NOT_IMPLEMENTED;
+ return VERR_NOT_SUPPORTED;
}
-RTDECL(int) RTPollSetQueryHandle(RTPOLLSET hPollSet, uint32_t id, PRTHANDLE pHandle)
+DECLHIDDEN(int) rtMemAllocEx32BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv)
{
- return VERR_NOT_IMPLEMENTED;
+ return VERR_NOT_SUPPORTED;
}
-RTDECL(uint32_t) RTPollSetGetCount(RTPOLLSET hPollSet)
+DECLHIDDEN(void) rtMemFreeExYyBitReach(void *pv, size_t cb, uint32_t fFlags)
{
- return UINT32_MAX;
+ AssertFailed();
}
diff --git a/src/VBox/Runtime/r3/generic/semspinmutex-r3-generic.cpp b/src/VBox/Runtime/r3/generic/semspinmutex-r3-generic.cpp
index 1c0e4603..e6edca4f 100644
--- a/src/VBox/Runtime/r3/generic/semspinmutex-r3-generic.cpp
+++ b/src/VBox/Runtime/r3/generic/semspinmutex-r3-generic.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/haiku/rtProcInitExePath-haiku.cpp b/src/VBox/Runtime/r3/haiku/rtProcInitExePath-haiku.cpp
new file mode 100644
index 00000000..7a41e9f1
--- /dev/null
+++ b/src/VBox/Runtime/r3/haiku/rtProcInitExePath-haiku.cpp
@@ -0,0 +1,60 @@
+/* $Id: rtProcInitExePath-haiku.cpp $ */
+/** @file
+ * IPRT - rtProcInitName, Haiku.
+ */
+
+/*
+ * Copyright (C) 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;
+ * 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_PROCESS
+#ifdef RT_OS_HAIKU
+# include <image.h>
+#endif
+
+#include <iprt/string.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/path.h>
+#include "internal/process.h"
+#include "internal/path.h"
+
+
+DECLHIDDEN(int) rtProcInitExePath(char *pszPath, size_t cchPath)
+{
+ image_info ImageInfo;
+ int32 Cookie = 0;
+ status_t status;
+
+ /*
+ * Query the image name from the OS, convert and return it.
+ */
+ status = get_next_image_info(0, &Cookie, &ImageInfo);
+ AssertReturn((status == B_OK), VERR_INTERNAL_ERROR);
+
+ int rc = rtPathFromNativeCopy(pszPath, MIN(cchPath, MAXPATHLEN), ImageInfo.name, NULL);
+ AssertMsgRCReturn(rc, ("rc=%Rrc pszLink=\"%s\"\nhex: %.*Rhxs\n", rc, pszPath, MIN(cchPath, MAXPATHLEN), pszPath), rc);
+
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Runtime/r3/haiku/time-haiku.cpp b/src/VBox/Runtime/r3/haiku/time-haiku.cpp
new file mode 100644
index 00000000..269b4b2c
--- /dev/null
+++ b/src/VBox/Runtime/r3/haiku/time-haiku.cpp
@@ -0,0 +1,84 @@
+/* $Id: time-haiku.cpp $ */
+/** @file
+ * IPRT - Time, Haiku.
+ */
+
+/*
+ * Copyright (C) 2012-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_TIME
+#define RTTIME_INCL_TIMEVAL
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <OS.h>
+
+#include <iprt/time.h>
+#include <iprt/err.h>
+#include "internal/time.h"
+
+
+DECLINLINE(uint64_t) rtTimeGetSystemNanoTS(void)
+{
+ return (uint64_t)system_time() * 1000;
+}
+
+
+/**
+ * Gets the current nanosecond timestamp.
+ *
+ * This differs from RTTimeNanoTS in that it will use system APIs and not do any
+ * resolution or performance optimizations.
+ *
+ * @returns nanosecond timestamp.
+ */
+RTDECL(uint64_t) RTTimeSystemNanoTS(void)
+{
+ return rtTimeGetSystemNanoTS();
+}
+
+
+/**
+ * Gets the current millisecond timestamp.
+ *
+ * This differs from RTTimeNanoTS in that it will use system APIs and not do any
+ * resolution or performance optimizations.
+ *
+ * @returns millisecond timestamp.
+ */
+RTDECL(uint64_t) RTTimeSystemMilliTS(void)
+{
+ return rtTimeGetSystemNanoTS() / 1000000;
+}
+
+
+RTDECL(int) RTTimeSet(PCRTTIMESPEC pTime)
+{
+ struct timeval tv;
+ RTTimeSpecGetTimeval(pTime, &tv);
+ set_real_time_clock(tv.tv_sec);
+ return VINF_SUCCESS;
+}
diff --git a/src/VBox/Runtime/r3/init.cpp b/src/VBox/Runtime/r3/init.cpp
index 8c3699d1..1f680bf2 100644
--- a/src/VBox/Runtime/r3/init.cpp
+++ b/src/VBox/Runtime/r3/init.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 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;
@@ -66,11 +66,11 @@
#endif
#include <stdlib.h>
+#include "init.h"
#include "internal/alignmentchecks.h"
#include "internal/path.h"
#include "internal/process.h"
#include "internal/thread.h"
-#include "internal/thread.h"
#include "internal/time.h"
@@ -92,6 +92,9 @@ DECLHIDDEN(size_t) g_cchrtProcDir;
/** The offset of the process name into g_szrtProcExePath. */
DECLHIDDEN(size_t) g_offrtProcName;
+/** The IPRT init flags. */
+static uint32_t g_fInitFlags;
+
/** The argument count of the program. */
static int g_crtArgs = -1;
/** The arguments of the program (UTF-8). This is "leaked". */
@@ -139,6 +142,15 @@ RTDATADECL(bool) g_fRTAlignmentChecks = false;
#endif
+#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_HAIKU) \
+ || defined(RT_OS_LINUX) || defined(RT_OS_OS2) || defined(RT_OS_SOLARIS) /** @todo add host init hooks everywhere. */
+/* Stubs */
+DECLHIDDEN(int) rtR3InitNativeFirst(uint32_t fFlags) { return VINF_SUCCESS; }
+DECLHIDDEN(int) rtR3InitNativeFinal(uint32_t fFlags) { return VINF_SUCCESS; }
+DECLHIDDEN(void) rtR3InitNativeObtrusive(void) { }
+#endif
+
+
/**
* atexit callback.
*
@@ -228,7 +240,7 @@ static int rtR3InitProgramPath(const char *pszProgramPath)
* Parse the name.
*/
ssize_t offName;
- g_cchrtProcExePath = RTPathParse(g_szrtProcExePath, &g_cchrtProcDir, &offName, NULL);
+ g_cchrtProcExePath = RTPathParseSimple(g_szrtProcExePath, &g_cchrtProcDir, &offName, NULL);
g_offrtProcName = offName;
return VINF_SUCCESS;
}
@@ -265,31 +277,74 @@ static int rtR3InitArgv(uint32_t fFlags, int cArgs, char ***ppapszArgs)
return VINF_SUCCESS;
}
- /*
- * Convert the arguments.
- */
- char **papszArgs = (char **)RTMemAllocZ((cArgs + 1) * sizeof(char *));
- if (!papszArgs)
- return VERR_NO_MEMORY;
-
- for (int i = 0; i < cArgs; i++)
+ if (!(fFlags & RTR3INIT_FLAGS_UTF8_ARGV))
{
- int rc = RTStrCurrentCPToUtf8(&papszArgs[i], papszOrgArgs[i]);
- if (RT_FAILURE(rc))
+ /*
+ * Convert the arguments.
+ */
+ char **papszArgs = (char **)RTMemAllocZ((cArgs + 1) * sizeof(char *));
+ if (!papszArgs)
+ return VERR_NO_MEMORY;
+
+#ifdef RT_OS_WINDOWS
+ /* HACK ALERT! Try convert from unicode versions if possible.
+ Unfortunately for us, __wargv is only initialized if we have a
+ unicode main function. So, we have to use CommandLineToArgvW to get
+ something similar. It should do the same conversion... :-) */
+ int cArgsW = -1;
+ PWSTR *papwszArgs = NULL;
+ if ( papszOrgArgs == __argv
+ && cArgs == __argc
+ && (papwszArgs = CommandLineToArgvW(GetCommandLineW(), &cArgsW)) != NULL )
{
- while (i--)
- RTStrFree(papszArgs[i]);
- RTMemFree(papszArgs);
- return rc;
+ AssertMsg(cArgsW == cArgs, ("%d vs %d\n", cArgsW, cArgs));
+ for (int i = 0; i < cArgs; i++)
+ {
+ int rc = RTUtf16ToUtf8(papwszArgs[i], &papszArgs[i]);
+ if (RT_FAILURE(rc))
+ {
+ while (i--)
+ RTStrFree(papszArgs[i]);
+ RTMemFree(papszArgs);
+ LocalFree(papwszArgs);
+ return rc;
+ }
+ }
+ LocalFree(papwszArgs);
+ }
+ else
+#endif
+ {
+ for (int i = 0; i < cArgs; i++)
+ {
+ int rc = RTStrCurrentCPToUtf8(&papszArgs[i], papszOrgArgs[i]);
+ if (RT_FAILURE(rc))
+ {
+ while (i--)
+ RTStrFree(papszArgs[i]);
+ RTMemFree(papszArgs);
+ return rc;
+ }
+ }
}
- }
- papszArgs[cArgs] = NULL;
- g_papszrtOrgArgs = papszOrgArgs;
- g_papszrtArgs = papszArgs;
- g_crtArgs = cArgs;
+ papszArgs[cArgs] = NULL;
- *ppapszArgs = papszArgs;
+ g_papszrtOrgArgs = papszOrgArgs;
+ g_papszrtArgs = papszArgs;
+ g_crtArgs = cArgs;
+
+ *ppapszArgs = papszArgs;
+ }
+ else
+ {
+ /*
+ * The arguments are already UTF-8, no conversion needed.
+ */
+ g_papszrtOrgArgs = papszOrgArgs;
+ g_papszrtArgs = papszOrgArgs;
+ g_crtArgs = cArgs;
+ }
}
return VINF_SUCCESS;
@@ -316,6 +371,19 @@ static void rtR3SigChildHandler(int iSignal)
static int rtR3InitBody(uint32_t fFlags, int cArgs, char ***papszArgs, const char *pszProgramPath)
{
/*
+ * Early native initialization.
+ */
+ int rc = rtR3InitNativeFirst(fFlags);
+ AssertMsgRCReturn(rc, ("rtR3InitNativeFirst failed with %Rrc\n", rc), rc);
+
+ /*
+ * Disable error popups.
+ */
+#if defined(RT_OS_OS2) /** @todo move to private code. */
+ DosError(FERR_DISABLEHARDERR);
+#endif
+
+ /*
* Init C runtime locale before we do anything that may end up converting
* paths or we'll end up using the "C" locale for path conversion.
*/
@@ -331,14 +399,9 @@ static int rtR3InitBody(uint32_t fFlags, int cArgs, char ***papszArgs, const cha
#endif
/*
- * Disable error popups.
+ * Save the init flags.
*/
-#ifdef RT_OS_WINDOWS
- UINT fOldErrMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
- SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX | fOldErrMode);
-#elif defined(RT_OS_OS2)
- DosError(FERR_DISABLEHARDERR);
-#endif
+ g_fInitFlags |= fFlags;
#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
# ifdef VBOX
@@ -363,7 +426,7 @@ static int rtR3InitBody(uint32_t fFlags, int cArgs, char ***papszArgs, const cha
* This must be done before everything else or else we'll call into threading
* without having initialized TLS entries and suchlike.
*/
- int rc = rtThreadInit();
+ rc = rtThreadInit();
AssertMsgRCReturn(rc, ("Failed to initialize threads, rc=%Rrc!\n", rc), rc);
#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
@@ -465,6 +528,12 @@ static int rtR3InitBody(uint32_t fFlags, int cArgs, char ***papszArgs, const cha
IPRT_ALIGNMENT_CHECKS_ENABLE();
#endif
+ /*
+ * Final native initialization.
+ */
+ rc = rtR3InitNativeFinal(fFlags);
+ AssertMsgRCReturn(rc, ("rtR3InitNativeFinal failed with %Rrc\n", rc), rc);
+
return VINF_SUCCESS;
}
@@ -483,7 +552,10 @@ static int rtR3InitBody(uint32_t fFlags, int cArgs, char ***papszArgs, const cha
static int rtR3Init(uint32_t fFlags, int cArgs, char ***papszArgs, const char *pszProgramPath)
{
/* no entry log flow, because prefixes and thread may freak out. */
- Assert(!(fFlags & ~(RTR3INIT_FLAGS_DLL | RTR3INIT_FLAGS_SUPLIB)));
+ Assert(!(fFlags & ~( RTR3INIT_FLAGS_DLL
+ | RTR3INIT_FLAGS_SUPLIB
+ | RTR3INIT_FLAGS_UNOBTRUSIVE
+ | RTR3INIT_FLAGS_UTF8_ARGV)));
Assert(!(fFlags & RTR3INIT_FLAGS_DLL) || cArgs == 0);
/*
@@ -499,12 +571,23 @@ static int rtR3Init(uint32_t fFlags, int cArgs, char ***papszArgs, const char *p
Assert(!g_fInitializing);
#if !defined(IN_GUEST) && !defined(RT_NO_GIP)
if (fFlags & RTR3INIT_FLAGS_SUPLIB)
+ {
SUPR3Init(NULL);
+ g_fInitFlags |= RTR3INIT_FLAGS_SUPLIB;
+ }
#endif
- if (!pszProgramPath)
- return VINF_SUCCESS;
- int rc = rtR3InitProgramPath(pszProgramPath);
+ if ( !(fFlags & RTR3INIT_FLAGS_UNOBTRUSIVE)
+ && (g_fInitFlags & RTR3INIT_FLAGS_UNOBTRUSIVE))
+ {
+ g_fInitFlags &= ~RTR3INIT_FLAGS_UNOBTRUSIVE;
+ rtR3InitNativeObtrusive();
+ rtThreadReInitObtrusive();
+ }
+
+ int rc = VINF_SUCCESS;
+ if (pszProgramPath)
+ rc = rtR3InitProgramPath(pszProgramPath);
if (RT_SUCCESS(rc))
rc = rtR3InitArgv(fFlags, cArgs, papszArgs);
return rc;
@@ -557,6 +640,10 @@ RTR3DECL(int) RTR3InitEx(uint32_t iVersion, uint32_t fFlags, int cArgs, char ***
return rtR3Init(fFlags, cArgs, papszArgs, pszProgramPath);
}
+RTR3DECL(bool) RTR3InitIsUnobtrusive(void)
+{
+ return RT_BOOL(g_fInitFlags & RTR3INIT_FLAGS_UNOBTRUSIVE);
+}
#if 0 /** @todo implement RTR3Term. */
RTR3DECL(void) RTR3Term(void)
diff --git a/src/VBox/Runtime/r3/init.h b/src/VBox/Runtime/r3/init.h
new file mode 100644
index 00000000..fae5c41f
--- /dev/null
+++ b/src/VBox/Runtime/r3/init.h
@@ -0,0 +1,38 @@
+/* $Id: init.h $ */
+/** @file
+ * IPRT - Ring-3 initialization.
+ */
+
+/*
+ * 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.
+ */
+
+
+#ifndef ___r3_init_h
+#define ___r3_init_h
+
+#include <iprt/types.h>
+
+DECLHIDDEN(int) rtR3InitNativeFirst(uint32_t fFlags);
+DECLHIDDEN(int) rtR3InitNativeFinal(uint32_t fFlags);
+DECLHIDDEN(void) rtR3InitNativeObtrusive(void);
+
+#endif
+
diff --git a/src/VBox/Runtime/r3/isofs.cpp b/src/VBox/Runtime/r3/isofs.cpp
index 05f5da9d..16d0334f 100644
--- a/src/VBox/Runtime/r3/isofs.cpp
+++ b/src/VBox/Runtime/r3/isofs.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/linux/RTProcIsRunningByName-linux.cpp b/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp
index 5582cef9..64edf958 100644
--- a/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/RTProcIsRunningByName-linux.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-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/linux/RTSystemShutdown-linux.cpp b/src/VBox/Runtime/r3/linux/RTSystemShutdown-linux.cpp
index a1da642c..e58365ac 100644
--- a/src/VBox/Runtime/r3/linux/RTSystemShutdown-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/RTSystemShutdown-linux.cpp
@@ -47,20 +47,24 @@ RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char
* Assemble the argument vector.
*/
int iArg = 0;
- const char *apszArgs[5];
+ const char *apszArgs[6];
+
+ RT_BZERO(apszArgs, sizeof(apszArgs));
apszArgs[iArg++] = "/sbin/shutdown";
switch (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK)
{
case RTSYSTEM_SHUTDOWN_HALT:
- apszArgs[iArg++] = "--halt";
+ apszArgs[iArg++] = "-h";
+ apszArgs[iArg++] = "-H";
break;
case RTSYSTEM_SHUTDOWN_REBOOT:
- apszArgs[iArg++] = "--reboot";
+ apszArgs[iArg++] = "-r";
break;
case RTSYSTEM_SHUTDOWN_POWER_OFF:
case RTSYSTEM_SHUTDOWN_POWER_OFF_HALT:
- apszArgs[iArg++] = "--poweroff";
+ apszArgs[iArg++] = "-h";
+ apszArgs[iArg++] = "-P";
break;
}
@@ -95,4 +99,3 @@ RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char
}
RT_EXPORT_SYMBOL(RTSystemShutdown);
-
diff --git a/src/VBox/Runtime/r3/linux/fileaio-linux.cpp b/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
index 51215de6..2cc8feb1 100644
--- a/src/VBox/Runtime/r3/linux/fileaio-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/fileaio-linux.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;
@@ -183,6 +183,8 @@ typedef struct RTFILEAIOCTXINTERNAL
volatile bool fWokenUp;
/** Flag whether the thread is currently waiting in the syscall. */
volatile bool fWaiting;
+ /** Flags given during creation. */
+ uint32_t fFlags;
/** Magic value (RTFILEAIOCTX_MAGIC). */
uint32_t u32Magic;
} RTFILEAIOCTXINTERNAL;
@@ -472,10 +474,12 @@ RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
}
-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);
/* The kernel interface needs a maximum. */
if (cAioReqsMax == RTFILEAIO_UNLIMITED_REQS)
@@ -493,6 +497,7 @@ RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
pCtxInt->fWaiting = false;
pCtxInt->hThreadWait = NIL_RTTHREAD;
pCtxInt->cRequestsMax = cAioReqsMax;
+ pCtxInt->fFlags = fFlags;
pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
*phAioCtx = (RTFILEAIOCTX)pCtxInt;
}
@@ -658,7 +663,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL
/*
* Can't wait if there are not 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;
/*
diff --git a/src/VBox/Runtime/r3/linux/mp-linux.cpp b/src/VBox/Runtime/r3/linux/mp-linux.cpp
index 54304aba..210f75a7 100644
--- a/src/VBox/Runtime/r3/linux/mp-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/mp-linux.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;
@@ -33,6 +33,9 @@
#include <errno.h>
#include <iprt/mp.h>
+#include "internal/iprt.h"
+
+#include <iprt/alloca.h>
#include <iprt/cpuset.h>
#include <iprt/assert.h>
#include <iprt/string.h>
@@ -82,7 +85,7 @@ static uint32_t rtMpLinuxGetFrequency(RTCPUID idCpu)
while (fgets(sz, sizeof(sz), pFile))
{
char *psz;
- if ( !strncmp(sz, "processor", 9)
+ if ( !strncmp(sz, RT_STR_TUPLE("processor"))
&& (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':')
&& (psz = strchr(sz, ':')))
{
@@ -93,7 +96,7 @@ static uint32_t rtMpLinuxGetFrequency(RTCPUID idCpu)
idCpuFound = iCpu;
}
else if ( idCpu == idCpuFound
- && !strncmp(sz, "cpu MHz", 7)
+ && !strncmp(sz, RT_STR_TUPLE("cpu MHz"))
&& (sz[10] == ' ' || sz[10] == '\t' || sz[10] == ':')
&& (psz = strchr(sz, ':')))
{
@@ -177,6 +180,36 @@ RTDECL(RTCPUID) RTMpGetCount(void)
}
+RTDECL(RTCPUID) RTMpGetCoreCount(void)
+{
+ RTCPUID cMax = rtMpLinuxMaxCpus();
+ uint32_t *paidCores = (uint32_t *)alloca(sizeof(paidCores[0]) * (cMax + 1));
+ uint32_t *paidPckgs = (uint32_t *)alloca(sizeof(paidPckgs[0]) * (cMax + 1));
+ uint32_t cCores = 0;
+ for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
+ {
+ if (RTMpIsCpuPossible(idCpu))
+ {
+ uint32_t idCore = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/core_id", (int)idCpu);
+ uint32_t idPckg = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/physical_package_id", (int)idCpu);
+ uint32_t i;
+ for (i = 0; i < cCores; i++)
+ if ( paidCores[i] == idCore
+ && paidPckgs[i] == idPckg)
+ break;
+ if (i >= cCores)
+ {
+ paidCores[cCores] = idCore;
+ paidPckgs[cCores] = idPckg;
+ cCores++;
+ }
+ }
+ }
+ Assert(cCores > 0);
+ return cCores;
+}
+
+
RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
{
RTCpuSetEmpty(pSet);
@@ -196,6 +229,37 @@ RTDECL(RTCPUID) RTMpGetOnlineCount(void)
}
+RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void)
+{
+ RTCPUID cMax = rtMpLinuxMaxCpus();
+ uint32_t *paidCores = (uint32_t *)alloca(sizeof(paidCores[0]) * (cMax + 1));
+ uint32_t *paidPckgs = (uint32_t *)alloca(sizeof(paidPckgs[0]) * (cMax + 1));
+ uint32_t cCores = 0;
+ for (RTCPUID idCpu = 0; idCpu < cMax; idCpu++)
+ {
+ if (RTMpIsCpuOnline(idCpu))
+ {
+ uint32_t idCore = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/core_id", (int)idCpu);
+ uint32_t idPckg = (uint32_t)RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/topology/physical_package_id", (int)idCpu);
+ uint32_t i;
+ for (i = 0; i < cCores; i++)
+ if ( paidCores[i] == idCore
+ && paidPckgs[i] == idPckg)
+ break;
+ if (i >= cCores)
+ {
+ paidCores[cCores] = idCore;
+ paidPckgs[cCores] = idPckg;
+ cCores++;
+ }
+ }
+ }
+ Assert(cCores > 0);
+ return cCores;
+}
+
+
+
RTDECL(uint32_t) RTMpGetCurFrequency(RTCPUID idCpu)
{
int64_t kHz = RTLinuxSysFsReadIntFile(0, "devices/system/cpu/cpu%d/cpufreq/cpuinfo_cur_freq", (int)idCpu);
diff --git a/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp b/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp
index 3ab0860b..cb43d9d0 100644
--- a/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/rtProcInitExePath-linux.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/linux/sched-linux.cpp b/src/VBox/Runtime/r3/linux/sched-linux.cpp
index 3972a6af..1e85af5b 100644
--- a/src/VBox/Runtime/r3/linux/sched-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/sched-linux.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/linux/semeventmulti-linux.cpp b/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
index 01094187..b623c846 100644
--- a/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/semeventmulti-linux.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/linux/semmutex-linux.cpp b/src/VBox/Runtime/r3/linux/semmutex-linux.cpp
index 1be76f4e..60abc1ed 100644
--- a/src/VBox/Runtime/r3/linux/semmutex-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/semmutex-linux.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/linux/sysfs.cpp b/src/VBox/Runtime/r3/linux/sysfs.cpp
index aa1060ac..15309330 100644
--- a/src/VBox/Runtime/r3/linux/sysfs.cpp
+++ b/src/VBox/Runtime/r3/linux/sysfs.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;
@@ -53,8 +53,7 @@
* Constructs the path of a sysfs file from the format parameters passed,
* prepending a prefix if the path is relative.
*
- * @returns The number of characters returned, or -1 and errno set to ERANGE on
- * failure.
+ * @returns The number of characters returned, or an iprt error code on failure.
*
* @param pszPrefix The prefix to prepend if the path is relative. Must end
* in '/'.
@@ -70,8 +69,8 @@ static ssize_t rtLinuxConstructPathV(char *pszBuf, size_t cchBuf,
const char *pszFormat, va_list va)
{
size_t cchPrefix = strlen(pszPrefix);
- AssertReturnStmt(pszPrefix[cchPrefix - 1] == '/', errno = ERANGE, -1);
- AssertReturnStmt(cchBuf > cchPrefix + 1, errno = ERANGE, -1);
+ AssertReturn(pszPrefix[cchPrefix - 1] == '/', VERR_INVALID_PARAMETER);
+ AssertReturn(cchBuf > cchPrefix + 1, VERR_INVALID_PARAMETER);
/** @todo While RTStrPrintfV prevents overflows, it doesn't make it easy to
* check for truncations. RTPath should provide some formatters and
@@ -80,7 +79,7 @@ static ssize_t rtLinuxConstructPathV(char *pszBuf, size_t cchBuf,
size_t cch = RTStrPrintfV(pszBuf, cchBuf, pszFormat, va);
if (*pszBuf != '/')
{
- AssertReturnStmt(cchBuf >= cch + cchPrefix + 1, errno = ERANGE, -1);
+ AssertReturn(cchBuf >= cch + cchPrefix + 1, VERR_BUFFER_OVERFLOW);
memmove(pszBuf + cchPrefix, pszBuf, cch + 1);
memcpy(pszBuf, pszPrefix, cchPrefix);
cch += cchPrefix;
@@ -93,8 +92,8 @@ static ssize_t rtLinuxConstructPathV(char *pszBuf, size_t cchBuf,
* Constructs the path of a sysfs file from the format parameters passed,
* prepending a prefix if the path is relative.
*
- * @returns The number of characters returned, or -1 and errno set to ERANGE on
- * failure.
+ * @returns The number of characters returned, or an iprt error code on failure.
+ * @note Unused.
*
* @param pszPrefix The prefix to prepend if the path is relative. Must end
* in '/'.
@@ -131,7 +130,11 @@ static ssize_t rtLinuxConstructPath(char *pszBuf, size_t cchBuf,
*/
static ssize_t rtLinuxSysFsConstructPath(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va)
{
- return rtLinuxConstructPathV(pszBuf, cchBuf, "/sys/", pszFormat, va);
+ ssize_t rc = rtLinuxConstructPathV(pszBuf, cchBuf, "/sys/", pszFormat, va);
+ if (rc >= 0)
+ return rc;
+ errno = ERANGE;
+ return -1;
}
@@ -409,125 +412,118 @@ RTDECL(ssize_t) RTLinuxSysFsGetLinkDest(char *pszBuf, size_t cchBuf, const char
}
-static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const char *pszBasePath,
- char *pszBuf, size_t cchBuf)
+/** Search for a device node with the number @a DevNum and the type (character
+ * or block) @a fMode below the path @a pszPath. @a pszPath MUST point to a
+ * buffer of size at least RTPATH_MAX which will be modified during the function
+ * execution. On successful return it will contain the path to the device node
+ * found. */
+/** @note This function previously used a local stack buffer of size RTPATH_MAX
+ * to construct the path passed to the next recursive call, which used up 4K
+ * of stack space per iteration and caused a stack overflow on a path with
+ * too many components. */
+static int rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode,
+ char *pszPath)
{
+ int rc;
+ PRTDIR pDir;
+ size_t const cchPath = strlen(pszPath);
+
/*
* Check assumptions made by the code below.
*/
- size_t const cchBasePath = strlen(pszBasePath);
- AssertReturnStmt(cchBasePath < RTPATH_MAX - 10U, errno = ENAMETOOLONG, -1);
-
- ssize_t rcRet;
- PRTDIR pDir;
- int rc = RTDirOpen(&pDir, pszBasePath);
+ AssertReturn(cchPath < RTPATH_MAX - 10U, VERR_BUFFER_OVERFLOW);
+ rc = RTDirOpen(&pDir, pszPath);
if (RT_SUCCESS(rc))
{
- char szPath[RTPATH_MAX]; /** @todo 4K per recursion - can easily be optimized away by passing it along pszBasePath
- and only remember the length. */
- memcpy(szPath, pszBasePath, cchBasePath + 1);
-
for (;;)
{
RTDIRENTRYEX Entry;
- rc = RTDirReadEx(pDir, &Entry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
+ rc = RTDirReadEx(pDir, &Entry, NULL, RTFSOBJATTRADD_UNIX,
+ RTPATH_F_ON_LINK);
if (RT_FAILURE(rc))
- {
- errno = rc == VERR_NO_MORE_FILES
- ? ENOENT
- : rc == VERR_BUFFER_OVERFLOW
- ? EOVERFLOW
- : EIO;
- rcRet = -1;
break;
- }
if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode))
continue;
-
+ pszPath[cchPath] = '\0';
+ rc = RTPathAppend(pszPath, RTPATH_MAX, Entry.szName);
+ if (RT_FAILURE(rc))
+ break;
/* Do the matching. */
if ( Entry.Info.Attr.u.Unix.Device == DevNum
&& (Entry.Info.Attr.fMode & RTFS_TYPE_MASK) == fMode)
- {
- rcRet = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s", Entry.szName);
break;
- }
-
/* Recurse into subdirectories. */
if (!RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode))
continue;
if (Entry.szName[0] == '.')
continue;
-
- szPath[cchBasePath] = '\0';
- rc = RTPathAppend(szPath, sizeof(szPath) - 1, Entry.szName); /* -1: for slash */
- if (RT_FAILURE(rc))
- {
- errno = ENAMETOOLONG;
- rcRet = -1;
- break;
- }
- strcat(&szPath[cchBasePath], "/");
- rcRet = rtLinuxFindDevicePathRecursive(DevNum, fMode, szPath, pszBuf, cchBuf);
- if (rcRet >= 0 || errno != ENOENT)
+ rc = rtLinuxFindDevicePathRecursive(DevNum, fMode, pszPath);
+ if (RT_SUCCESS(rc) || rc != VERR_NO_MORE_FILES)
break;
}
RTDirClose(pDir);
}
- else
- {
- rcRet = -1;
- errno = RTErrConvertToErrno(rc);
- }
- return rcRet;
+ return rc;
}
-RTDECL(ssize_t) RTLinuxFindDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf,
- const char *pszSuggestion, va_list va)
+RTDECL(ssize_t) RTLinuxFindDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf,
+ size_t cchBuf, const char *pszSuggestion,
+ va_list va)
{
- AssertReturnStmt(cchBuf >= 2, errno = EINVAL, -1);
- AssertReturnStmt( fMode == RTFS_TYPE_DEV_CHAR
- || fMode == RTFS_TYPE_DEV_BLOCK,
- errno = EINVAL, -1);
+ char szFilename[RTPATH_MAX];
+ int rc = VINF_TRY_AGAIN;
+ AssertReturn(cchBuf >= 2, VERR_INVALID_PARAMETER);
+ AssertReturn( fMode == RTFS_TYPE_DEV_CHAR
+ || fMode == RTFS_TYPE_DEV_BLOCK,
+ VERR_INVALID_PARAMETER);
if (pszSuggestion)
{
/*
* Construct the filename and read the link.
*/
- char szFilename[RTPATH_MAX];
- int rc = rtLinuxConstructPathV(szFilename, sizeof(szFilename), "/dev/", pszSuggestion, va);
- if (rc == -1)
- return -1;
-
- /*
- * Check whether the caller's suggestion was right.
- */
- RTFSOBJINFO Info;
- rc = RTPathQueryInfo(szFilename, &Info, RTFSOBJATTRADD_UNIX);
- if ( RT_SUCCESS(rc)
- && Info.Attr.u.Unix.Device == DevNum
- && (Info.Attr.fMode & RTFS_TYPE_MASK) == fMode)
+ rc = rtLinuxConstructPathV(szFilename, sizeof(szFilename), "/dev/",
+ pszSuggestion, va);
+ if (rc > 0)
{
- size_t cchPath = strlen(szFilename);
- if (cchPath >= cchBuf)
- {
- errno = EOVERFLOW;
- return -1;
- }
- memcpy(pszBuf, szFilename, cchPath + 1);
- return cchPath;
+ /*
+ * Check whether the caller's suggestion was right.
+ */
+ RTFSOBJINFO Info;
+ rc = RTPathQueryInfo(szFilename, &Info, RTFSOBJATTRADD_UNIX);
+ if ( rc == VERR_PATH_NOT_FOUND
+ || rc == VERR_FILE_NOT_FOUND
+ || ( RT_SUCCESS(rc)
+ && ( Info.Attr.u.Unix.Device != DevNum
+ || (Info.Attr.fMode & RTFS_TYPE_MASK) != fMode)))
+ /* The suggestion was wrong, fall back on the brute force attack. */
+ rc = VINF_TRY_AGAIN;
}
-
- /* The suggestion was wrong, fall back on the brute force attack. */
}
- return rtLinuxFindDevicePathRecursive(DevNum, fMode, "/dev/", pszBuf, cchBuf);
+ if (rc == VINF_TRY_AGAIN)
+ {
+ RTStrCopy(szFilename, sizeof(szFilename), "/dev/");
+ rc = rtLinuxFindDevicePathRecursive(DevNum, fMode, szFilename);
+ }
+ if (RT_SUCCESS(rc))
+ {
+ size_t cchPath = strlen(szFilename);
+ if (cchPath >= cchBuf)
+ return VERR_BUFFER_OVERFLOW;
+ memcpy(pszBuf, szFilename, cchPath + 1);
+ return cchPath;
+ }
+ return rc;
}
-RTDECL(ssize_t) RTLinuxFindDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf,
- const char *pszSuggestion, ...)
+/** @todo Do we really need to return the string length? If the caller is
+ * interested (the current ones aren't) they can check themselves. */
+RTDECL(ssize_t) RTLinuxFindDevicePath(dev_t DevNum, RTFMODE fMode, char *pszBuf,
+ size_t cchBuf, const char *pszSuggestion,
+ ...)
{
va_list va;
va_start(va, pszSuggestion);
diff --git a/src/VBox/Runtime/r3/linux/systemmem-linux.cpp b/src/VBox/Runtime/r3/linux/systemmem-linux.cpp
index f3234403..23fe70b8 100644
--- a/src/VBox/Runtime/r3/linux/systemmem-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/systemmem-linux.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2012 Oracle Corporation
+ * Copyright (C) 2012-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;
@@ -33,7 +33,9 @@
#include <iprt/err.h>
#include <iprt/assert.h>
+#include <iprt/string.h>
+#include <stdio.h>
#include <errno.h>
/* Satisfy compiller warning */
@@ -50,7 +52,7 @@ RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb)
int rc = sysinfo(&info);
if (rc == 0)
{
- *pcb = (uint64_t)(info.totalram * (unsigned long)info.mem_unit);
+ *pcb = (uint64_t)info.totalram * info.mem_unit;
return VINF_SUCCESS;
}
return RTErrConvertFromErrno(errno);
@@ -61,11 +63,45 @@ RTDECL(int) RTSystemQueryAvailableRam(uint64_t *pcb)
{
AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+ FILE *pFile = fopen("/proc/meminfo", "r");
+ if (pFile)
+ {
+ int rc = VERR_NOT_FOUND;
+ uint64_t cbTotal = 0;
+ uint64_t cbFree = 0;
+ uint64_t cbBuffers = 0;
+ uint64_t cbCached = 0;
+ char sz[256];
+ while (fgets(sz, sizeof(sz), pFile))
+ {
+ if (!strncmp(sz, RT_STR_TUPLE("MemTotal:")))
+ rc = RTStrToUInt64Ex(RTStrStripL(&sz[sizeof("MemTotal:")]), NULL, 0, &cbTotal);
+ else if (!strncmp(sz, RT_STR_TUPLE("MemFree:")))
+ rc = RTStrToUInt64Ex(RTStrStripL(&sz[sizeof("MemFree:")]), NULL, 0, &cbFree);
+ else if (!strncmp(sz, RT_STR_TUPLE("Buffers:")))
+ rc = RTStrToUInt64Ex(RTStrStripL(&sz[sizeof("Buffers:")]), NULL, 0, &cbBuffers);
+ else if (!strncmp(sz, RT_STR_TUPLE("Cached:")))
+ rc = RTStrToUInt64Ex(RTStrStripL(&sz[sizeof("Cached:")]), NULL, 0, &cbCached);
+ if (RT_FAILURE(rc))
+ break;
+ }
+ fclose(pFile);
+ if (RT_SUCCESS(rc))
+ {
+ *pcb = (cbFree + cbBuffers + cbCached) * _1K;
+ return VINF_SUCCESS;
+ }
+ }
+ /*
+ * Fallback (e.g. /proc not mapped) to sysinfo. Less accurat because there
+ * is no information about the cached memory. 'Cached:' from above is only
+ * accessible through proc :-(
+ */
struct sysinfo info;
int rc = sysinfo(&info);
if (rc == 0)
{
- *pcb = (uint64_t)(info.freeram * (unsigned long)info.mem_unit);
+ *pcb = ((uint64_t)info.freeram + info.bufferram) * info.mem_unit;
return VINF_SUCCESS;
}
return RTErrConvertFromErrno(errno);
diff --git a/src/VBox/Runtime/r3/linux/time-linux.cpp b/src/VBox/Runtime/r3/linux/time-linux.cpp
index a9de927e..ab9c0e5a 100644
--- a/src/VBox/Runtime/r3/linux/time-linux.cpp
+++ b/src/VBox/Runtime/r3/linux/time-linux.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/nt/Makefile.kup b/src/VBox/Runtime/r3/nt/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Runtime/r3/nt/Makefile.kup
diff --git a/src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp b/src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp
new file mode 100644
index 00000000..f93f6e4e
--- /dev/null
+++ b/src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp
@@ -0,0 +1,697 @@
+/* $Id: direnum-r3-nt.cpp $ */
+/** @file
+ * IPRT - Directory Enumeration, Native NT.
+ */
+
+/*
+ * 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 "internal-r3-nt.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"
+
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
+/** Whether to return a single record (TRUE) or multiple (FALSE)o. */
+#define RTDIR_NT_SINGLE_RECORD FALSE
+
+/** Go hard on record chaining (has slight performance impact). */
+#ifdef RT_STRICT
+# define RTDIR_NT_STRICT
+#endif
+
+
+/* ASSUMES FileID comes after ShortName and the structus are identical up to that point. */
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, NextEntryOffset, FILE_ID_BOTH_DIR_INFORMATION, NextEntryOffset);
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileIndex , FILE_ID_BOTH_DIR_INFORMATION, FileIndex );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, CreationTime , FILE_ID_BOTH_DIR_INFORMATION, CreationTime );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, LastAccessTime , FILE_ID_BOTH_DIR_INFORMATION, LastAccessTime );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, LastWriteTime , FILE_ID_BOTH_DIR_INFORMATION, LastWriteTime );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ChangeTime , FILE_ID_BOTH_DIR_INFORMATION, ChangeTime );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, EndOfFile , FILE_ID_BOTH_DIR_INFORMATION, EndOfFile );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, AllocationSize , FILE_ID_BOTH_DIR_INFORMATION, AllocationSize );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileAttributes , FILE_ID_BOTH_DIR_INFORMATION, FileAttributes );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileNameLength , FILE_ID_BOTH_DIR_INFORMATION, FileNameLength );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, EaSize , FILE_ID_BOTH_DIR_INFORMATION, EaSize );
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ShortNameLength, FILE_ID_BOTH_DIR_INFORMATION, ShortNameLength);
+AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ShortName , FILE_ID_BOTH_DIR_INFORMATION, ShortName );
+
+
+
+size_t rtDirNativeGetStructSize(const char *pszPath)
+{
+ NOREF(pszPath);
+ return sizeof(RTDIR);
+}
+
+
+int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
+{
+ /*
+ * Convert the filter to UTF-16.
+ */
+ int rc;
+ pDir->pNtFilterStr = NULL;
+ if ( pDir->cchFilter > 0
+ && pDir->enmFilter == RTDIRFILTER_WINNT)
+ {
+ PRTUTF16 pwszTmp;
+ rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp);
+ if (RT_FAILURE(rc))
+ return rc;
+ pDir->NtFilterStr.Buffer = pwszTmp;
+ pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16));
+ pDir->pNtFilterStr = &pDir->NtFilterStr;
+ }
+
+ /*
+ * Try open the directory
+ */
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ bool fObjDir;
+#endif
+ rc = rtNtPathOpenDir(pszPathBuf,
+ FILE_READ_DATA | SYNCHRONIZE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
+ OBJ_CASE_INSENSITIVE,
+ &pDir->hDir,
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ &fObjDir
+#else
+ NULL
+#endif
+ );
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Init data.
+ */
+ pDir->fDataUnread = false; /* spelling it out */
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ if (fObjDir)
+ pDir->enmInfoClass = FileMaximumInformation; /* object directory. */
+#endif
+ }
+ 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 = ~RTDIR_MAGIC;
+ if (pDir->hDir != MY_INVALID_HANDLE_VALUE)
+ {
+ int rc = rtNtPathClose(pDir->hDir);
+ AssertRC(rc);
+ pDir->hDir = MY_INVALID_HANDLE_VALUE;
+ }
+ RTStrFree(pDir->pszName);
+ pDir->pszName = NULL;
+ RTUtf16Free(pDir->NtFilterStr.Buffer);
+ pDir->NtFilterStr.Buffer = NULL;
+ RTMemFree(pDir->pabBuffer);
+ pDir->pabBuffer = NULL;
+ RTMemFree(pDir);
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Checks the validity of the current record.
+ *
+ * @returns IPRT status code
+ * @param pThis The directory instance data.
+ */
+static int rtDirNtCheckRecord(PRTDIR pThis)
+{
+#ifdef RTDIR_NT_STRICT
+# ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ if (pThis->enmInfoClass != FileMaximumInformation)
+# endif
+ {
+ uintptr_t uEndAddr;
+ if (pThis->enmInfoClass == FileIdBothDirectoryInformation)
+ uEndAddr = (uintptr_t)&pThis->uCurData.pBothId->FileName[0];
+ else
+ uEndAddr = (uintptr_t)&pThis->uCurData.pBoth->FileName[0];
+ AssertReturn(uEndAddr < (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE);
+
+ AssertReturn(pThis->uCurData.pBoth->FileNameLength < _64K, VERR_FILENAME_TOO_LONG);
+ AssertReturn((pThis->uCurData.pBoth->FileNameLength & 1) == 0, VERR_IO_GEN_FAILURE);
+
+ uEndAddr += pThis->uCurData.pBoth->FileNameLength;
+ AssertReturn(uEndAddr <= (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE);
+
+ AssertReturn((unsigned)pThis->uCurData.pBoth->ShortNameLength <= sizeof(pThis->uCurData.pBoth->ShortName),
+ VERR_IO_GEN_FAILURE);
+ }
+#endif
+
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Advances the buffer pointer.
+ *
+ * @param pThis The directory instance data.
+ */
+static int rtDirNtAdvanceBuffer(PRTDIR pThis)
+{
+ int rc;
+
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ if (pThis->enmInfoClass == FileMaximumInformation)
+ {
+ pThis->uCurData.pObjDir++;
+ pThis->fDataUnread = pThis->uCurData.pObjDir->Name.Length != 0;
+ return VINF_SUCCESS;
+ }
+#endif
+
+ pThis->fDataUnread = false;
+
+ uint32_t const offNext = pThis->uCurData.pBoth->NextEntryOffset;
+ if (offNext == 0)
+ return VINF_SUCCESS;
+
+#ifdef RTDIR_NT_STRICT
+ /* Make sure the next-record offset is beyond the current record. */
+ size_t cbRec;
+ if (pThis->enmInfoClass == FileIdBothDirectoryInformation)
+ cbRec = RT_UOFFSETOF(FILE_ID_BOTH_DIR_INFORMATION, FileName);
+ else
+ cbRec = RT_UOFFSETOF(FILE_BOTH_DIR_INFORMATION, FileName);
+ cbRec += pThis->uCurData.pBoth->FileNameLength;
+ AssertReturn(offNext >= cbRec, VERR_IO_GEN_FAILURE);
+#endif
+ pThis->uCurData.u += offNext;
+
+ rc = rtDirNtCheckRecord(pThis);
+ pThis->fDataUnread = RT_SUCCESS(rc);
+ return rc;
+}
+
+
+/**
+ * Fetches more data from the file system.
+ *
+ * @returns IPRT status code
+ * @param pThis The directory instance data.
+ */
+static int rtDirNtFetchMore(PRTDIR pThis)
+{
+ Assert(!pThis->fDataUnread);
+
+ /*
+ * Allocate the buffer the first time around.
+ * We do this in lazy fashion as some users of RTDirOpen will not actually
+ * list any files, just open it for various reasons.
+ */
+ bool fFirst = false;
+ if (!pThis->pabBuffer)
+ {
+ fFirst = false;
+ pThis->cbBufferAlloc = _256K;
+ pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc);
+ if (!pThis->pabBuffer)
+ {
+ do
+ {
+ pThis->cbBufferAlloc /= 4;
+ pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc);
+ } while (pThis->pabBuffer == NULL && pThis->cbBufferAlloc > _4K);
+ if (!pThis->pabBuffer)
+ return VERR_NO_MEMORY;
+ }
+ }
+
+ /*
+ * Read more.
+ */
+ NTSTATUS rcNt;
+ IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
+ if (pThis->enmInfoClass != (FILE_INFORMATION_CLASS)0)
+ {
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ if (pThis->enmInfoClass == FileMaximumInformation)
+ {
+ Ios.Information = 0;
+ Ios.Status = rcNt = NtQueryDirectoryObject(pThis->hDir,
+ pThis->pabBuffer,
+ pThis->cbBufferAlloc,
+ RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
+ FALSE /*RestartScan*/,
+ &pThis->uObjDirCtx,
+ (PULONG)&Ios.Information);
+ }
+ else
+#endif
+ rcNt = NtQueryDirectoryFile(pThis->hDir,
+ NULL /* Event */,
+ NULL /* ApcRoutine */,
+ NULL /* ApcContext */,
+ &Ios,
+ pThis->pabBuffer,
+ pThis->cbBufferAlloc,
+ pThis->enmInfoClass,
+ RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
+ pThis->pNtFilterStr,
+ FALSE /*RestartScan */);
+ }
+ else
+ {
+ /*
+ * The first time around we have figure which info class we can use.
+ * We prefer one which gives us file IDs, but we'll settle for less.
+ */
+ pThis->enmInfoClass = FileIdBothDirectoryInformation;
+ rcNt = NtQueryDirectoryFile(pThis->hDir,
+ NULL /* Event */,
+ NULL /* ApcRoutine */,
+ NULL /* ApcContext */,
+ &Ios,
+ pThis->pabBuffer,
+ pThis->cbBufferAlloc,
+ pThis->enmInfoClass,
+ RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
+ pThis->pNtFilterStr,
+ FALSE /*RestartScan */);
+ if (!NT_SUCCESS(rcNt))
+ {
+ pThis->enmInfoClass = FileBothDirectoryInformation;
+ rcNt = NtQueryDirectoryFile(pThis->hDir,
+ NULL /* Event */,
+ NULL /* ApcRoutine */,
+ NULL /* ApcContext */,
+ &Ios,
+ pThis->pabBuffer,
+ pThis->cbBufferAlloc,
+ pThis->enmInfoClass,
+ RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
+ pThis->pNtFilterStr,
+ FALSE /*RestartScan */);
+ }
+ }
+ if (!NT_SUCCESS(rcNt))
+ {
+ if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES)
+ return VERR_NO_MORE_FILES;
+ return RTErrConvertFromNtStatus(rcNt);
+ }
+ Assert(Ios.Information > sizeof(*pThis->uCurData.pBoth));
+
+ /*
+ * Set up the data members.
+ */
+ pThis->uCurData.u = (uintptr_t)pThis->pabBuffer;
+ pThis->cbBuffer = Ios.Information;
+
+ int rc = rtDirNtCheckRecord(pThis);
+ pThis->fDataUnread = RT_SUCCESS(rc);
+
+ return rc;
+}
+
+
+/**
+ * Converts the name from UTF-16 to UTF-8.
+ *
+ * Fortunately, the names are relative to the directory, so we won't have to do
+ * any sweaty path style coversion. :-)
+ *
+ * @returns IPRT status code
+ * @param pThis The directory instance data.
+ * @param cbName The file name length in bytes.
+ * @param pwsName The file name, not terminated.
+ */
+static int rtDirNtConvertName(PRTDIR pThis, uint32_t cbName, PCRTUTF16 pwsName)
+{
+ int rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName);
+ if (RT_SUCCESS(rc))
+ {
+ if (!pThis->cbNameAlloc)
+ pThis->cbNameAlloc = pThis->cchName + 1;
+ }
+ else if (rc == VERR_BUFFER_OVERFLOW)
+ {
+ RTStrFree(pThis->pszName);
+ pThis->pszName = NULL;
+ pThis->cbNameAlloc = 0;
+
+ rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName);
+ if (RT_SUCCESS(rc))
+ pThis->cbNameAlloc = pThis->cchName + 1;
+ }
+ Assert(RT_SUCCESS(rc) ? pThis->pszName != NULL : pThis->pszName == NULL);
+ return rc;
+}
+
+
+/**
+ * Converts the name of the current record.
+ *
+ * @returns IPRT status code.
+ * @param pThis The directory instance data.
+ */
+static int rtDirNtConvertCurName(PRTDIR pThis)
+{
+ switch (pThis->enmInfoClass)
+ {
+ case FileIdBothDirectoryInformation:
+ return rtDirNtConvertName(pThis, pThis->uCurData.pBothId->FileNameLength, pThis->uCurData.pBothId->FileName);
+ case FileBothDirectoryInformation:
+ return rtDirNtConvertName(pThis, pThis->uCurData.pBoth->FileNameLength, pThis->uCurData.pBoth->FileName);
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ case FileMaximumInformation:
+ return rtDirNtConvertName(pThis, pThis->uCurData.pObjDir->Name.Length, pThis->uCurData.pObjDir->Name.Buffer);
+#endif
+
+ default:
+ AssertFailedReturn(VERR_INTERNAL_ERROR_3);
+ }
+}
+
+
+RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
+{
+ int rc;
+
+ /*
+ * Validate input.
+ */
+ AssertPtrReturn(pDir, VERR_INVALID_POINTER);
+ AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
+ AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER);
+ size_t cbDirEntry = sizeof(*pDirEntry);
+ if (pcbDirEntry)
+ {
+ cbDirEntry = *pcbDirEntry;
+ AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRY, szName[2]),
+ ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])),
+ VERR_INVALID_PARAMETER);
+ }
+
+ /*
+ * Fetch data?
+ */
+ if (!pDir->fDataUnread)
+ {
+ rc = rtDirNtFetchMore(pDir);
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ /*
+ * Convert the filename to UTF-8.
+ */
+ rc = rtDirNtConvertCurName(pDir);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * 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.
+ */
+ pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName);
+ memcpy(pDirEntry->szName, pszName, cchName + 1);
+
+ pDirEntry->INodeId = pDir->enmInfoClass == FileIdBothDirectoryInformation
+ ? pDir->uCurData.pBothId->FileId.QuadPart : 0;
+
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ if (pDir->enmInfoClass != FileMaximumInformation)
+#endif
+ {
+ switch ( pDir->uCurData.pBoth->FileAttributes
+ & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY))
+ {
+ default:
+ AssertFailed();
+ case 0:
+ pDirEntry->enmType = RTDIRENTRYTYPE_FILE;
+ break;
+
+ case FILE_ATTRIBUTE_DIRECTORY:
+ pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY;
+ break;
+
+ case FILE_ATTRIBUTE_REPARSE_POINT:
+ case FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY:
+ pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK;
+ break;
+ }
+ }
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ else
+ {
+ pDirEntry->enmType = RTDIRENTRYTYPE_UNKNOWN;
+ if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
+ RT_STR_TUPLE("Directory")))
+ pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY;
+ else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
+ RT_STR_TUPLE("SymbolicLink")))
+ pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK;
+ }
+#endif
+
+ return rtDirNtAdvanceBuffer(pDir);
+}
+
+
+RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry,
+ RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
+{
+ int rc;
+
+ /*
+ * Validate input.
+ */
+ AssertPtrReturn(pDir, VERR_INVALID_POINTER);
+ AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
+ AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER);
+
+ AssertReturn(enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
+ 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;
+ AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRYEX, szName[2]),
+ ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])),
+ VERR_INVALID_PARAMETER);
+ }
+
+ /*
+ * Fetch data?
+ */
+ if (!pDir->fDataUnread)
+ {
+ rc = rtDirNtFetchMore(pDir);
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ /*
+ * Convert the filename to UTF-8.
+ */
+ rc = rtDirNtConvertCurName(pDir);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * 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.
+ */
+ PFILE_BOTH_DIR_INFORMATION pBoth = pDir->uCurData.pBoth;
+
+ pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName);
+ memcpy(pDirEntry->szName, pszName, cchName + 1);
+ memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ if (pDir->enmInfoClass != FileMaximumInformation)
+#endif
+ {
+ uint8_t cbShort = pBoth->ShortNameLength;
+ if (cbShort > 0)
+ {
+ AssertStmt(cbShort < sizeof(pDirEntry->wszShortName), cbShort = sizeof(pDirEntry->wszShortName) - 2);
+ memcpy(pDirEntry->wszShortName, pBoth->ShortName, cbShort);
+ pDirEntry->cwcShortName = cbShort / 2;
+ }
+ else
+ pDirEntry->cwcShortName = 0;
+
+ pDirEntry->Info.cbObject = pBoth->EndOfFile.QuadPart;
+ pDirEntry->Info.cbAllocated = pBoth->AllocationSize.QuadPart;
+
+ Assert(sizeof(uint64_t) == sizeof(pBoth->CreationTime));
+ RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, pBoth->CreationTime.QuadPart);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, pBoth->LastAccessTime.QuadPart);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, pBoth->LastWriteTime.QuadPart);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, pBoth->ChangeTime.QuadPart);
+
+ pDirEntry->Info.Attr.fMode = rtFsModeFromDos((pBoth->FileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
+ pszName, cchName);
+ }
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ else
+ {
+ pDirEntry->cwcShortName = 0;
+ pDirEntry->Info.cbObject = 0;
+ pDirEntry->Info.cbAllocated = 0;
+ RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime, 0);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime, 0);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime, 0);
+ RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime, 0);
+
+ if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
+ RT_STR_TUPLE("Directory")))
+ pDirEntry->Info.Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777;
+ else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
+ RT_STR_TUPLE("SymbolicLink")))
+ pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_REPARSE_POINT | RTFS_TYPE_SYMLINK | 0777;
+ else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
+ RT_STR_TUPLE("Device")))
+ pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_DEVICE | RTFS_TYPE_DEV_CHAR | 0666;
+ else
+ pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE | 0666;
+ }
+#endif
+
+ /*
+ * Requested attributes (we cannot provide anything actually).
+ */
+ switch (enmAdditionalAttribs)
+ {
+ case RTFSOBJATTRADD_EASIZE:
+ pDirEntry->Info.Attr.enmAdditional = RTFSOBJATTRADD_EASIZE;
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ if (pDir->enmInfoClass == FileMaximumInformation)
+ pDirEntry->Info.Attr.u.EASize.cb = 0;
+ else
+#endif
+ pDirEntry->Info.Attr.u.EASize.cb = pBoth->EaSize;
+ 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;
+ }
+
+ /*
+ * Follow links if requested.
+ */
+ if ( (fFlags & RTPATH_F_FOLLOW_LINK)
+ && RTFS_IS_SYMLINK(fFlags))
+ {
+ /** @todo Symlinks: Find[First|Next]FileW will return info about
+ the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
+ }
+
+ /*
+ * Finally advance the buffer.
+ */
+ return rtDirNtAdvanceBuffer(pDir);
+}
+
diff --git a/src/VBox/Runtime/r3/nt/fs-nt.cpp b/src/VBox/Runtime/r3/nt/fs-nt.cpp
new file mode 100644
index 00000000..314059de
--- /dev/null
+++ b/src/VBox/Runtime/r3/nt/fs-nt.cpp
@@ -0,0 +1,284 @@
+/* $Id: fs-nt.cpp $ */
+/** @file
+ * IPRT - File System, Native NT.
+ */
+
+/*
+ * 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_FS
+#include "internal-r3-nt.h"
+
+#include <iprt/fs.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/param.h>
+#include <iprt/err.h>
+#include <iprt/log.h>
+#include <iprt/assert.h>
+#include "internal/fs.h"
+
+
+
+
+RTR3DECL(int) RTFsQuerySizes(const char *pszFsPath, RTFOFF *pcbTotal, RTFOFF *pcbFree,
+ uint32_t *pcbBlock, uint32_t *pcbSector)
+{
+ AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
+
+ /*
+ * Open the file/dir/whatever.
+ */
+ HANDLE hFile;
+ int rc = rtNtPathOpen(pszFsPath,
+ GENERIC_READ,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN,
+ FILE_OPEN_FOR_BACKUP_INTENT,
+ OBJ_CASE_INSENSITIVE,
+ &hFile,
+ NULL);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Get the volume information.
+ */
+ FILE_FS_SIZE_INFORMATION FsSizeInfo;
+ IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
+ NTSTATUS rcNt = NtQueryVolumeInformationFile(hFile, &Ios, &FsSizeInfo, sizeof(FsSizeInfo), FileFsSizeInformation);
+ if (NT_SUCCESS(rcNt))
+ {
+ /*
+ * Calculate the return values.
+ */
+ if (pcbTotal)
+ {
+ *pcbTotal = FsSizeInfo.TotalAllocationUnits.QuadPart
+ * FsSizeInfo.SectorsPerAllocationUnit
+ * FsSizeInfo.BytesPerSector;
+ if ( *pcbTotal / FsSizeInfo.SectorsPerAllocationUnit / FsSizeInfo.BytesPerSector
+ != FsSizeInfo.TotalAllocationUnits.QuadPart)
+ *pcbTotal = UINT64_MAX;
+ }
+
+ if (pcbFree)
+ {
+ *pcbFree = FsSizeInfo.AvailableAllocationUnits.QuadPart
+ * FsSizeInfo.SectorsPerAllocationUnit
+ * FsSizeInfo.BytesPerSector;
+ if ( *pcbFree / FsSizeInfo.SectorsPerAllocationUnit / FsSizeInfo.BytesPerSector
+ != FsSizeInfo.AvailableAllocationUnits.QuadPart)
+ *pcbFree = UINT64_MAX;
+ }
+
+ if (pcbBlock)
+ {
+ *pcbBlock = FsSizeInfo.SectorsPerAllocationUnit * FsSizeInfo.BytesPerSector;
+ if (*pcbBlock / FsSizeInfo.BytesPerSector != FsSizeInfo.SectorsPerAllocationUnit)
+ rc = VERR_OUT_OF_RANGE;
+ }
+
+ if (pcbSector)
+ *pcbSector = FsSizeInfo.BytesPerSector;
+ }
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+
+ rtNtPathClose(hFile);
+ }
+ return rc;
+}
+
+
+RTR3DECL(int) RTFsQuerySerial(const char *pszFsPath, uint32_t *pu32Serial)
+{
+ /*
+ * Validate & get valid root path.
+ */
+ AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
+ AssertPtrReturn(pu32Serial, VERR_INVALID_POINTER);
+
+ /*
+ * Open the file/dir/whatever.
+ */
+ HANDLE hFile;
+ int rc = rtNtPathOpen(pszFsPath,
+ GENERIC_READ,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN,
+ FILE_OPEN_FOR_BACKUP_INTENT,
+ OBJ_CASE_INSENSITIVE,
+ &hFile,
+ NULL);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Get the volume information.
+ */
+ union
+ {
+ FILE_FS_VOLUME_INFORMATION FsVolInfo;
+ uint8_t abBuf[sizeof(FILE_FS_VOLUME_INFORMATION) + 4096];
+ } u;
+ IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
+ NTSTATUS rcNt = NtQueryVolumeInformationFile(hFile, &Ios, &u, sizeof(u), FileFsVolumeInformation);
+ if (NT_SUCCESS(rcNt))
+ *pu32Serial = u.FsVolInfo.VolumeSerialNumber;
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+
+ rtNtPathClose(hFile);
+ }
+ return rc;
+}
+
+
+RTR3DECL(int) RTFsQueryProperties(const char *pszFsPath, PRTFSPROPERTIES pProperties)
+{
+ /*
+ * Validate & get valid root path.
+ */
+ AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
+ AssertPtrReturn(pProperties, VERR_INVALID_POINTER);
+
+ /*
+ * Open the file/dir/whatever.
+ */
+ HANDLE hFile;
+ int rc = rtNtPathOpen(pszFsPath,
+ GENERIC_READ,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN,
+ FILE_OPEN_FOR_BACKUP_INTENT,
+ OBJ_CASE_INSENSITIVE,
+ &hFile,
+ NULL);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Get the volume information.
+ */
+ union
+ {
+ FILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
+ uint8_t abBuf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 4096];
+ } u;
+ IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
+ NTSTATUS rcNt = NtQueryVolumeInformationFile(hFile, &Ios, &u, sizeof(u), FileFsAttributeInformation);
+ if (NT_SUCCESS(rcNt))
+ {
+ FILE_FS_DEVICE_INFORMATION FsDevInfo;
+ rcNt = NtQueryVolumeInformationFile(hFile, &Ios, &FsDevInfo, sizeof(FsDevInfo), FileFsDeviceInformation);
+ if (NT_SUCCESS(rcNt))
+ {
+ /*
+ * Fill in the return structure.
+ */
+ memset(pProperties, 0, sizeof(*pProperties));
+ pProperties->cbMaxComponent = u.FsAttrInfo.MaximumComponentNameLength;
+ pProperties->fFileCompression = !!(u.FsAttrInfo.FileSystemAttributes & FILE_FILE_COMPRESSION);
+ pProperties->fCompressed = !!(u.FsAttrInfo.FileSystemAttributes & FILE_VOLUME_IS_COMPRESSED);
+ pProperties->fReadOnly = !!(u.FsAttrInfo.FileSystemAttributes & FILE_READ_ONLY_VOLUME);
+ pProperties->fSupportsUnicode = !!(u.FsAttrInfo.FileSystemAttributes & 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. */
+
+ /* figure the remote stuff */
+ pProperties->fRemote = RT_BOOL(FsDevInfo.Characteristics & FILE_REMOTE_DEVICE);
+ }
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+ }
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+
+ rtNtPathClose(hFile);
+ }
+ return rc;
+}
+
+
+
+RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
+{
+ /*
+ * Validate input.
+ */
+ *penmType = RTFSTYPE_UNKNOWN;
+ AssertPtrReturn(pszFsPath, VERR_INVALID_POINTER);
+ AssertReturn(*pszFsPath, VERR_INVALID_PARAMETER);
+
+ /*
+ * Open the file/dir/whatever.
+ */
+ HANDLE hFile;
+ int rc = rtNtPathOpen(pszFsPath,
+ GENERIC_READ,
+ FILE_ATTRIBUTE_NORMAL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ FILE_OPEN,
+ FILE_OPEN_FOR_BACKUP_INTENT,
+ OBJ_CASE_INSENSITIVE,
+ &hFile,
+ NULL);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Get the file system name.
+ */
+ union
+ {
+ FILE_FS_ATTRIBUTE_INFORMATION FsAttrInfo;
+ uint8_t abBuf[sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + 4096];
+ } u;
+ IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
+ NTSTATUS rcNt = NtQueryVolumeInformationFile(hFile, &Ios, &u, sizeof(u), FileFsAttributeInformation);
+ if (NT_SUCCESS(rcNt))
+ {
+#define IS_FS(a_szName) \
+ rtNtCompWideStrAndAscii(u.FsAttrInfo.FileSystemName, u.FsAttrInfo.FileSystemNameLength, RT_STR_TUPLE(a_szName))
+ if (IS_FS("NTFS"))
+ *penmType = RTFSTYPE_NTFS;
+ else if (IS_FS("FAT"))
+ *penmType = RTFSTYPE_FAT;
+ else if (IS_FS("FAT32"))
+ *penmType = RTFSTYPE_FAT;
+ else if (IS_FS("VBoxSharedFolderFS"))
+ *penmType = RTFSTYPE_VBOXSHF;
+#undef IS_FS
+ }
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+
+ rtNtPathClose(hFile);
+ }
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/nt/internal-r3-nt.h b/src/VBox/Runtime/r3/nt/internal-r3-nt.h
new file mode 100644
index 00000000..0a970965
--- /dev/null
+++ b/src/VBox/Runtime/r3/nt/internal-r3-nt.h
@@ -0,0 +1,140 @@
+/* $Id: internal-r3-nt.h $ */
+/** @file
+ * IPRT - Internal Header for the Native NT code.
+ */
+
+/*
+ * Copyright (C) 2010-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;
+ * 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.
+ */
+
+
+#ifndef ___internal_r3_nt_h___
+#define ___internal_r3_nt_h___
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <ntstatus.h>
+#ifdef IPRT_NT_USE_WINTERNL
+# define WIN32_NO_STATUS
+# include <windef.h>
+# include <winnt.h>
+# include <winternl.h>
+# define IPRT_NT_NEED_API_GROUP_1
+
+#elif defined(IPRT_NT_USE_WDM)
+# include <wdm.h>
+# define IPRT_NT_NEED_API_GROUP_1
+
+#else
+# include <ntifs.h>
+#endif
+#include "internal/iprt.h"
+
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
+/** Indicates that we're targetting native NT in the current source. */
+#define RT_USE_NATIVE_NT 1
+/** Initializes a IO_STATUS_BLOCK. */
+#define MY_IO_STATUS_BLOCK_INITIALIZER { STATUS_FAILED_DRIVER_ENTRY, ~(uintptr_t)42 }
+/** Similar to INVALID_HANDLE_VALUE in the Windows environment. */
+#define MY_INVALID_HANDLE_VALUE ( (HANDLE)~(uintptr_t)0 )
+
+#ifdef DEBUG_bird
+/** Enables the "\\!\" NT path pass thru as well as hacks for listing NT object
+ * directories. */
+# define IPRT_WITH_NT_PATH_PASSTHRU 1
+#endif
+
+
+/*******************************************************************************
+* Internal Functions *
+*******************************************************************************/
+int rtNtPathOpen(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
+ ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
+ PHANDLE phHandle, PULONG_PTR puDisposition);
+int rtNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions,
+ ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir);
+int rtNtPathClose(HANDLE hHandle);
+
+
+/**
+ * Internal helper for comparing a WCHAR string with a char string.
+ *
+ * @returns @c true if equal, @c false if not.
+ * @param pwsz1 The first string.
+ * @param cb1 The length of the first string, in bytes.
+ * @param psz2 The second string.
+ * @param cch2 The length of the second string.
+ */
+DECLINLINE(bool) rtNtCompWideStrAndAscii(WCHAR const *pwsz1, size_t cch1, const char *psz2, size_t cch2)
+{
+ if (cch1 != cch2 * 2)
+ return false;
+ while (cch2-- > 0)
+ {
+ unsigned ch1 = *pwsz1++;
+ unsigned ch2 = (unsigned char)*psz2++;
+ if (ch1 != ch2)
+ return false;
+ }
+ return true;
+}
+
+
+/*******************************************************************************
+* NT APIs *
+*******************************************************************************/
+
+RT_C_DECLS_BEGIN
+
+#ifdef IPRT_NT_NEED_API_GROUP_1
+
+typedef struct _FILE_FS_ATTRIBUTE_INFORMATION
+{
+ ULONG FileSystemAttributes;
+ LONG MaximumComponentNameLength;
+ ULONG FileSystemNameLength;
+ WCHAR FileSystemName[1];
+} FILE_FS_ATTRIBUTE_INFORMATION;
+typedef FILE_FS_ATTRIBUTE_INFORMATION *PFILE_FS_ATTRIBUTE_INFORMATION;
+extern "C" NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FS_INFORMATION_CLASS);
+
+#endif
+
+NTSTATUS NTAPI NtOpenDirectoryObject(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
+
+typedef struct _OBJECT_DIRECTORY_INFORMATION
+{
+ UNICODE_STRING Name;
+ UNICODE_STRING TypeName;
+} OBJECT_DIRECTORY_INFORMATION;
+typedef OBJECT_DIRECTORY_INFORMATION *POBJECT_DIRECTORY_INFORMATION;
+
+NTSTATUS NTAPI NtQueryDirectoryObject(HANDLE, PVOID, ULONG, BOOLEAN, BOOLEAN, PULONG, PULONG);
+
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/src/VBox/Runtime/r3/nt/pathint-nt.cpp b/src/VBox/Runtime/r3/nt/pathint-nt.cpp
new file mode 100644
index 00000000..a68f0597
--- /dev/null
+++ b/src/VBox/Runtime/r3/nt/pathint-nt.cpp
@@ -0,0 +1,356 @@
+/* $Id: pathint-nt.cpp $ */
+/** @file
+ * IPRT - Native NT, Internal Path stuff.
+ */
+
+/*
+ * 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_FS
+#include "internal-r3-nt.h"
+
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/err.h>
+#include <iprt/assert.h>
+
+
+
+/**
+ * Handles the pass thru case.
+ *
+ * @returns IPRT status code.
+ * @param pNtName Where to return the NT name.
+ * @param phRootDir Where to return the root handle, if applicable.
+ * @param pszPath The UTF-8 path.
+ */
+static int rtNtPathToNativePassThruWin(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
+{
+ PRTUTF16 pwszPath = NULL;
+ size_t cwcLen;
+ int rc = RTStrToUtf16Ex(pszPath + 1, RTSTR_MAX, &pwszPath, 0, &cwcLen);
+ if (RT_SUCCESS(rc))
+ {
+ if (cwcLen < _32K - 1)
+ {
+ pwszPath[0] = '\\';
+ pwszPath[1] = '.';
+ pwszPath[2] = '\\';
+
+ pNtName->Buffer = pwszPath;
+ pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2);
+ *phRootDir = NULL;
+ return VINF_SUCCESS;
+ }
+
+ RTUtf16Free(pwszPath);
+ rc = VERR_FILENAME_TOO_LONG;
+ }
+ return rc;
+}
+
+
+/**
+ * Converts the path to UTF-16 and sets all the return values.
+ *
+ * @returns IPRT status code.
+ * @param pNtName Where to return the NT name.
+ * @param phRootDir Where to return the root handle, if applicable.
+ * @param pszPath The UTF-8 path.
+ */
+static int rtNtPathToNativeToUtf16(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
+{
+ PRTUTF16 pwszPath = NULL;
+ size_t cwcLen;
+ int rc = RTStrToUtf16Ex(pszPath, RTSTR_MAX, &pwszPath, 0, &cwcLen);
+ if (RT_SUCCESS(rc))
+ {
+ if (cwcLen < _32K - 1)
+ {
+ pNtName->Buffer = pwszPath;
+ pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2);
+ *phRootDir = NULL;
+ return VINF_SUCCESS;
+ }
+
+ RTUtf16Free(pwszPath);
+ rc = VERR_FILENAME_TOO_LONG;
+ }
+ return rc;
+}
+
+
+/**
+ * Converts a path to NT format and encoding.
+ *
+ * @returns IPRT status code.
+ * @param pNtName Where to return the NT name.
+ * @param phRootDir Where to return the root handle, if applicable.
+ * @param pszPath The UTF-8 path.
+ */
+static int rtNtPathToNative(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
+{
+ static char const s_szPrefixUnc[] = "\\??\\UNC\\";
+ static char const s_szPrefix[] = "\\??\\";
+
+ /*
+ * Very simple conversion of a win32-like path into an NT path.
+ */
+ const char *pszPrefix = s_szPrefix;
+ size_t cchPrefix = sizeof(s_szPrefix) - 1;
+ size_t cchSkip = 0;
+
+ if ( RTPATH_IS_SLASH(pszPath[0])
+ && RTPATH_IS_SLASH(pszPath[1])
+ && !RTPATH_IS_SLASH(pszPath[2])
+ && pszPath[2])
+ {
+ if ( pszPath[2] == '?'
+ && RTPATH_IS_SLASH(pszPath[3]))
+ return rtNtPathToNativePassThruWin(pNtName, phRootDir, pszPath);
+
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ /* Special hack: The path starts with "\\\\!\\", we will skip past the bang and pass it thru. */
+ if ( pszPath[2] == '!'
+ && RTPATH_IS_SLASH(pszPath[3]))
+ return rtNtPathToNativeToUtf16(pNtName, phRootDir, pszPath + 3);
+#endif
+
+ if ( pszPath[2] == '.'
+ && RTPATH_IS_SLASH(pszPath[3]))
+ {
+ /*
+ * Device path.
+ * Note! I suspect \\.\stuff\..\otherstuff may be handled differently by windows.
+ */
+ cchSkip = 4;
+ }
+ else
+ {
+ /* UNC */
+ pszPrefix = s_szPrefixUnc;
+ cchPrefix = sizeof(s_szPrefixUnc) - 1;
+ cchSkip = 2;
+ }
+ }
+
+ /*
+ * Straighten out all .. and uncessary . references and convert slashes.
+ */
+ char szPath[RTPATH_MAX];
+ int rc = RTPathAbs(pszPath, &szPath[cchPrefix - cchSkip], sizeof(szPath) - (cchPrefix - cchSkip));
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Add prefix and convert it to UTF16.
+ */
+ memcpy(szPath, pszPrefix, cchPrefix);
+ return rtNtPathToNativeToUtf16(pNtName, phRootDir, szPath);
+}
+
+
+/**
+ * Frees the native path and root handle.
+ *
+ * @param pNtName The NT path after a successful rtNtPathToNative
+ * call.
+ * @param phRootDir The root handle variable after a
+ * rtNtPathToNative.
+ */
+void rtNtPathFreeNative(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir)
+{
+ RTUtf16Free(pNtName->Buffer);
+ pNtName->Buffer = NULL;
+}
+
+
+/**
+ * Wrapper around NtCreateFile.
+ *
+ * @returns IPRT status code.
+ * @param pszPath The UTF-8 path.
+ * @param fDesiredAccess See NtCreateFile.
+ * @param fFileAttribs See NtCreateFile.
+ * @param fShareAccess See NtCreateFile.
+ * @param fCreateDisposition See NtCreateFile.
+ * @param fCreateOptions See NtCreateFile.
+ * @param fObjAttribs The OBJECT_ATTRIBUTES::Attributes value, see
+ * NtCreateFile and InitializeObjectAttributes.
+ * @param phHandle Where to return the handle.
+ * @param puAction Where to return the action taken. Optional.
+ */
+int rtNtPathOpen(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
+ ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
+ PHANDLE phHandle, PULONG_PTR puAction)
+{
+ *phHandle = MY_INVALID_HANDLE_VALUE;
+
+ HANDLE hRootDir;
+ UNICODE_STRING NtName;
+ int rc = rtNtPathToNative(&NtName, &hRootDir, pszPath);
+ if (RT_SUCCESS(rc))
+ {
+ HANDLE hFile = MY_INVALID_HANDLE_VALUE;
+ IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
+ OBJECT_ATTRIBUTES ObjAttr;
+ InitializeObjectAttributes(&ObjAttr, &NtName, fObjAttribs, hRootDir, NULL);
+
+ NTSTATUS rcNt = NtCreateFile(&hFile,
+ fDesiredAccess,
+ &ObjAttr,
+ &Ios,
+ NULL /* AllocationSize*/,
+ fFileAttribs,
+ fShareAccess,
+ fCreateDisposition,
+ fCreateOptions,
+ NULL /*EaBuffer*/,
+ 0 /*EaLength*/);
+ if (NT_SUCCESS(rcNt))
+ {
+ if (puAction)
+ *puAction = Ios.Information;
+ *phHandle = hFile;
+ rc = VINF_SUCCESS;
+ }
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+ rtNtPathFreeNative(&NtName, &hRootDir);
+ }
+ return rc;
+}
+
+
+/**
+ * Wrapper around NtCreateFile.
+ *
+ * @returns IPRT status code.
+ * @param pszPath The UTF-8 path.
+ * @param fDesiredAccess See NtCreateFile.
+ * @param fFileAttribs See NtCreateFile.
+ * @param fShareAccess See NtCreateFile.
+ * @param fCreateDisposition See NtCreateFile.
+ * @param fCreateOptions See NtCreateFile.
+ * @param fObjAttribs The OBJECT_ATTRIBUTES::Attributes value, see
+ * NtCreateFile and InitializeObjectAttributes.
+ * @param phHandle Where to return the handle.
+ * @param pfObjDir If not NULL, the variable pointed to will be set
+ * to @c true if we opened an object directory and
+ * @c false if we opened an directory file (normal
+ * directory).
+ */
+int rtNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions,
+ ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir)
+{
+ *phHandle = MY_INVALID_HANDLE_VALUE;
+
+ HANDLE hRootDir;
+ UNICODE_STRING NtName;
+ int rc = rtNtPathToNative(&NtName, &hRootDir, pszPath);
+ if (RT_SUCCESS(rc))
+ {
+ HANDLE hFile = MY_INVALID_HANDLE_VALUE;
+ IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
+ OBJECT_ATTRIBUTES ObjAttr;
+ InitializeObjectAttributes(&ObjAttr, &NtName, fObjAttribs, hRootDir, NULL);
+
+ NTSTATUS rcNt = NtCreateFile(&hFile,
+ fDesiredAccess,
+ &ObjAttr,
+ &Ios,
+ NULL /* AllocationSize*/,
+ FILE_ATTRIBUTE_NORMAL,
+ fShareAccess,
+ FILE_OPEN,
+ fCreateOptions,
+ NULL /*EaBuffer*/,
+ 0 /*EaLength*/);
+ if (NT_SUCCESS(rcNt))
+ {
+ if (pfObjDir)
+ *pfObjDir = false;
+ *phHandle = hFile;
+ rc = VINF_SUCCESS;
+ }
+#ifdef IPRT_WITH_NT_PATH_PASSTHRU
+ else if ( pfObjDir
+ && (rcNt == STATUS_OBJECT_NAME_INVALID || rcNt == STATUS_OBJECT_TYPE_MISMATCH)
+ && RTPATH_IS_SLASH(pszPath[0])
+ && RTPATH_IS_SLASH(pszPath[1])
+ && pszPath[2] == '!'
+ && RTPATH_IS_SLASH(pszPath[3]))
+ {
+ /* Strip trailing slash. */
+ if ( NtName.Length > 2
+ && RTPATH_IS_SLASH(NtName.Buffer[(NtName.Length / 2) - 1]))
+ NtName.Length -= 2;
+
+ /* Rought conversion of the access flags. */
+ ULONG fObjDesiredAccess = 0;
+ if (fDesiredAccess & (GENERIC_ALL | STANDARD_RIGHTS_ALL))
+ fObjDesiredAccess = DIRECTORY_ALL_ACCESS;
+ else
+ {
+ if (fDesiredAccess & (FILE_GENERIC_WRITE | GENERIC_WRITE | STANDARD_RIGHTS_WRITE))
+ fObjDesiredAccess |= DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_OBJECT;
+ if ( (fDesiredAccess & (FILE_LIST_DIRECTORY | FILE_GENERIC_READ | GENERIC_READ | STANDARD_RIGHTS_READ))
+ || !fObjDesiredAccess)
+ fObjDesiredAccess |= DIRECTORY_QUERY | FILE_LIST_DIRECTORY;
+ }
+
+ rcNt = NtOpenDirectoryObject(&hFile, fObjDesiredAccess, &ObjAttr);
+ if (NT_SUCCESS(rcNt))
+ {
+ *pfObjDir = true;
+ *phHandle = hFile;
+ rc = VINF_SUCCESS;
+ }
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+ }
+#endif
+ else
+ rc = RTErrConvertFromNtStatus(rcNt);
+ rtNtPathFreeNative(&NtName, &hRootDir);
+ }
+ return rc;
+}
+
+
+/**
+ * Closes an handled open by rtNtPathOpen.
+ *
+ * @returns IPRT status code
+ * @param hHandle The handle value.
+ */
+int rtNtPathClose(HANDLE hHandle)
+{
+ NTSTATUS rcNt = NtClose(hHandle);
+ if (NT_SUCCESS(rcNt))
+ return VINF_SUCCESS;
+ return RTErrConvertFromNtStatus(rcNt);
+}
+
diff --git a/src/VBox/Runtime/r3/os2/filelock-os2.cpp b/src/VBox/Runtime/r3/os2/filelock-os2.cpp
index 8646ecba..21839947 100644
--- a/src/VBox/Runtime/r3/os2/filelock-os2.cpp
+++ b/src/VBox/Runtime/r3/os2/filelock-os2.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-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/os2/mp-os2.cpp b/src/VBox/Runtime/r3/os2/mp-os2.cpp
index 00260ca0..78e22a87 100644
--- a/src/VBox/Runtime/r3/os2/mp-os2.cpp
+++ b/src/VBox/Runtime/r3/os2/mp-os2.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/os2/pipe-os2.cpp b/src/VBox/Runtime/r3/os2/pipe-os2.cpp
index 729f09b3..e5832c4e 100644
--- a/src/VBox/Runtime/r3/os2/pipe-os2.cpp
+++ b/src/VBox/Runtime/r3/os2/pipe-os2.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;
@@ -28,75 +28,1005 @@
/*******************************************************************************
* Header Files *
*******************************************************************************/
+#define INCL_ERRORS
+#define INCL_DOSSEMAPHORES
+#include <os2.h>
+
#include <iprt/pipe.h>
#include "internal/iprt.h"
+#include <iprt/asm.h>
#include <iprt/assert.h>
+#include <iprt/critsect.h>
#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/poll.h>
+#include <iprt/process.h>
+#include <iprt/thread.h>
+#include <iprt/time.h>
+#include "internal/pipe.h"
+#include "internal/magics.h"
+
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
+/** The pipe buffer size we prefer. */
+#define RTPIPE_OS2_SIZE _32K
+
+
+/*******************************************************************************
+* Structures and Typedefs *
+*******************************************************************************/
+typedef struct RTPIPEINTERNAL
+{
+ /** Magic value (RTPIPE_MAGIC). */
+ uint32_t u32Magic;
+ /** The pipe handle. */
+ HPIPE hPipe;
+ /** Set if this is the read end, clear if it's the write end. */
+ bool fRead;
+ /** Whether the pipe is in blocking or non-blocking mode. */
+ bool fBlocking;
+ /** Set if the pipe is broken. */
+ bool fBrokenPipe;
+ /** Usage counter. */
+ uint32_t cUsers;
+
+ /** The event semaphore associated with the pipe. */
+ HEV hev;
+ /** The handle of the poll set currently polling on this pipe.
+ * We can only have one poller at the time (lazy bird). */
+ RTPOLLSET hPollSet;
+ /** Critical section protecting the above members.
+ * (Taking the lazy/simple approach.) */
+ RTCRITSECT CritSect;
+
+} RTPIPEINTERNAL;
+
+
+/**
+ * Ensures that the pipe has a semaphore associated with it.
+ *
+ * @returns VBox status code.
+ * @param pThis The pipe.
+ */
+static int rtPipeOs2EnsureSem(RTPIPEINTERNAL *pThis)
+{
+ if (pThis->hev != NULLHANDLE)
+ return VINF_SUCCESS;
+
+ HEV hev;
+ APIRET orc = DosCreateEventSem(NULL, &hev, DC_SEM_SHARED, FALSE);
+ if (orc == NO_ERROR)
+ {
+ orc = DosSetNPipeSem(pThis->hPipe, (HSEM)hev, 1);
+ if (orc == NO_ERROR)
+ {
+ pThis->hev = hev;
+ return VINF_SUCCESS;
+ }
+
+ DosCloseEventSem(hev);
+ }
+ return RTErrConvertFromOS2(orc);
+}
RTDECL(int) RTPipeCreate(PRTPIPE phPipeRead, PRTPIPE phPipeWrite, uint32_t fFlags)
{
- return VERR_NOT_IMPLEMENTED;
+ AssertPtrReturn(phPipeRead, VERR_INVALID_POINTER);
+ AssertPtrReturn(phPipeWrite, VERR_INVALID_POINTER);
+ AssertReturn(!(fFlags & ~RTPIPE_C_VALID_MASK), VERR_INVALID_PARAMETER);
+
+ /*
+ * Try create and connect a pipe pair.
+ */
+ APIRET orc;
+ HPIPE hPipeR;
+ HFILE hPipeW;
+ int rc;
+ for (;;)
+ {
+ static volatile uint32_t g_iNextPipe = 0;
+ char szName[128];
+ RTStrPrintf(szName, sizeof(szName), "\\pipe\\iprt-pipe-%u-%u", RTProcSelf(), ASMAtomicIncU32(&g_iNextPipe));
+
+ /*
+ * Create the read end of the pipe.
+ */
+ ULONG fPipeMode = 1 /*instance*/ | NP_TYPE_BYTE | NP_READMODE_BYTE | NP_NOWAIT;
+ ULONG fOpenMode = NP_ACCESS_DUPLEX | NP_WRITEBEHIND;
+ if (fFlags & RTPIPE_C_INHERIT_READ)
+ fOpenMode |= NP_INHERIT;
+ else
+ fOpenMode |= NP_NOINHERIT;
+ orc = DosCreateNPipe((PSZ)szName, &hPipeR, fOpenMode, fPipeMode, RTPIPE_OS2_SIZE, RTPIPE_OS2_SIZE, NP_DEFAULT_WAIT);
+ if (orc == NO_ERROR)
+ {
+ orc = DosConnectNPipe(hPipeR);
+ if (orc == ERROR_PIPE_NOT_CONNECTED || orc == NO_ERROR)
+ {
+ /*
+ * Connect to the pipe (the write end), attach sem below.
+ */
+ ULONG ulAction = 0;
+ ULONG fOpenW = OPEN_ACTION_FAIL_IF_NEW | OPEN_ACTION_OPEN_IF_EXISTS;
+ ULONG fModeW = OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_FAIL_ON_ERROR;
+ if (!(fFlags & RTPIPE_C_INHERIT_WRITE))
+ fModeW |= OPEN_FLAGS_NOINHERIT;
+ orc = DosOpen((PSZ)szName, &hPipeW, &ulAction, 0 /*cbFile*/, FILE_NORMAL,
+ fOpenW, fModeW, NULL /*peaop2*/);
+ if (orc == NO_ERROR)
+ break;
+ }
+ DosClose(hPipeR);
+ }
+ if ( orc != ERROR_PIPE_BUSY /* already exist - compatible */
+ && orc != ERROR_ACCESS_DENIED /* already exist - incompatible (?) */)
+ return RTErrConvertFromOS2(orc);
+ /* else: try again with a new name */
+ }
+
+ /*
+ * Create the two handles.
+ */
+ RTPIPEINTERNAL *pThisR = (RTPIPEINTERNAL *)RTMemAllocZ(sizeof(RTPIPEINTERNAL));
+ if (pThisR)
+ {
+ RTPIPEINTERNAL *pThisW = (RTPIPEINTERNAL *)RTMemAllocZ(sizeof(RTPIPEINTERNAL));
+ if (pThisW)
+ {
+ /* Crit sects. */
+ rc = RTCritSectInit(&pThisR->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTCritSectInit(&pThisW->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ /* Initialize the structures. */
+ pThisR->u32Magic = RTPIPE_MAGIC;
+ pThisW->u32Magic = RTPIPE_MAGIC;
+ pThisR->hPipe = hPipeR;
+ pThisW->hPipe = hPipeW;
+ pThisR->hev = NULLHANDLE;
+ pThisW->hev = NULLHANDLE;
+ pThisR->fRead = true;
+ pThisW->fRead = false;
+ pThisR->fBlocking = false;
+ pThisW->fBlocking = true;
+ //pThisR->fBrokenPipe = false;
+ //pThisW->fBrokenPipe = false;
+ //pThisR->cUsers = 0;
+ //pThisW->cUsers = 0;
+ pThisR->hPollSet = NIL_RTPOLLSET;
+ pThisW->hPollSet = NIL_RTPOLLSET;
+
+ *phPipeRead = pThisR;
+ *phPipeWrite = pThisW;
+ return VINF_SUCCESS;
+ }
+
+ RTCritSectDelete(&pThisR->CritSect);
+ }
+ RTMemFree(pThisW);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ RTMemFree(pThisR);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ /* Don't call DosDisConnectNPipe! */
+ DosClose(hPipeW);
+ DosClose(hPipeR);
+ return rc;
}
RTDECL(int) RTPipeClose(RTPIPE hPipe)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ if (pThis == NIL_RTPIPE)
+ return VINF_SUCCESS;
+ AssertPtrReturn(pThis, VERR_INVALID_PARAMETER);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+
+ /*
+ * Do the cleanup.
+ */
+ AssertReturn(ASMAtomicCmpXchgU32(&pThis->u32Magic, ~RTPIPE_MAGIC, RTPIPE_MAGIC), VERR_INVALID_HANDLE);
+ RTCritSectEnter(&pThis->CritSect);
+ Assert(pThis->cUsers == 0);
+
+ /* Don't call DosDisConnectNPipe! */
+ DosClose(pThis->hPipe);
+ pThis->hPipe = (HPIPE)-1;
+
+ if (pThis->hev != NULLHANDLE)
+ {
+ DosCloseEventSem(pThis->hev);
+ pThis->hev = NULLHANDLE;
+ }
+
+ RTCritSectLeave(&pThis->CritSect);
+ RTCritSectDelete(&pThis->CritSect);
+
+ RTMemFree(pThis);
+
+ return VINF_SUCCESS;
}
RTDECL(int) RTPipeFromNative(PRTPIPE phPipe, RTHCINTPTR hNativePipe, uint32_t fFlags)
{
- return VERR_NOT_IMPLEMENTED;
-}
+ AssertPtrReturn(phPipe, VERR_INVALID_POINTER);
+ AssertReturn(!(fFlags & ~RTPIPE_N_VALID_MASK), VERR_INVALID_PARAMETER);
+ AssertReturn(!!(fFlags & RTPIPE_N_READ) != !!(fFlags & RTPIPE_N_WRITE), VERR_INVALID_PARAMETER);
+
+ /*
+ * Get and validate the pipe handle info.
+ */
+ HPIPE hNative = (HPIPE)hNativePipe;
+ ULONG ulType = 0;
+ ULONG ulAttr = 0;
+ APIRET orc = DosQueryHType(hNative, &ulType, &ulAttr);
+ AssertMsgReturn(orc == NO_ERROR, ("%d\n", orc), RTErrConvertFromOS2(orc));
+ AssertReturn((ulType & 0x7) == HANDTYPE_PIPE, VERR_INVALID_HANDLE);
+#if 0
+ union
+ {
+ PIPEINFO PipeInfo;
+ uint8_t abPadding[sizeof(PIPEINFO) + 127];
+ } Buf;
+ orc = DosQueryNPipeInfo(hNative, 1, &Buf, sizeof(Buf));
+ if (orc != NO_ERROR)
+ {
+ /* Sorry, anonymous pips are not supported. */
+ AssertMsgFailed(("%d\n", orc));
+ return VERR_INVALID_HANDLE;
+ }
+ AssertReturn(Buf.PipeInfo.cbMaxInst == 1, VERR_INVALID_HANDLE);
+#endif
+
+ ULONG fPipeState = 0;
+ orc = DosQueryNPHState(hNative, &fPipeState);
+ if (orc != NO_ERROR)
+ {
+ /* Sorry, anonymous pips are not supported. */
+ AssertMsgFailed(("%d\n", orc));
+ return VERR_INVALID_HANDLE;
+ }
+ AssertReturn(!(fPipeState & NP_TYPE_MESSAGE), VERR_INVALID_HANDLE);
+ AssertReturn(!(fPipeState & NP_READMODE_MESSAGE), VERR_INVALID_HANDLE);
+ AssertReturn((fPipeState & 0xff) == 1, VERR_INVALID_HANDLE);
+
+ ULONG fFileState = 0;
+ orc = DosQueryFHState(hNative, &fFileState);
+ AssertMsgReturn(orc == NO_ERROR, ("%d\n", orc), VERR_INVALID_HANDLE);
+ AssertMsgReturn( (fFileState & 0x3) == (fFlags & RTPIPE_N_READ ? OPEN_ACCESS_READONLY : OPEN_ACCESS_WRITEONLY)
+ || (fFileState & 0x3) == OPEN_ACCESS_READWRITE
+ , ("%#x\n", fFileState), VERR_INVALID_HANDLE);
+
+ /*
+ * Looks kind of OK. Fix the inherit flag.
+ */
+ orc = DosSetFHState(hNative, (fFileState & (OPEN_FLAGS_WRITE_THROUGH | OPEN_FLAGS_FAIL_ON_ERROR | OPEN_FLAGS_NO_CACHE))
+ | (fFlags & RTPIPE_N_INHERIT ? 0 : OPEN_FLAGS_NOINHERIT));
+ AssertMsgReturn(orc == NO_ERROR, ("%d\n", orc), RTErrConvertFromOS2(orc));
+
+
+ /*
+ * Create a handle so we can try rtPipeQueryInfo on it
+ * and see if we need to duplicate it to make that call work.
+ */
+ RTPIPEINTERNAL *pThis = (RTPIPEINTERNAL *)RTMemAllocZ(sizeof(RTPIPEINTERNAL));
+ if (!pThis)
+ return VERR_NO_MEMORY;
+ int rc = RTCritSectInit(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ pThis->u32Magic = RTPIPE_MAGIC;
+ pThis->hPipe = hNative;
+ pThis->hev = NULLHANDLE;
+ pThis->fRead = !!(fFlags & RTPIPE_N_READ);
+ pThis->fBlocking = !(fPipeState & NP_NOWAIT);
+ //pThis->fBrokenPipe = false;
+ //pThis->cUsers = 0;
+ pThis->hPollSet = NIL_RTPOLLSET;
+
+ *phPipe = pThis;
+ return VINF_SUCCESS;
+
+ //RTCritSectDelete(&pThis->CritSect);
+ }
+ RTMemFree(pThis);
+ return rc;
+}
RTDECL(RTHCINTPTR) RTPipeToNative(RTPIPE hPipe)
{
- return -1;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, -1);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, -1);
+
+ return (RTHCINTPTR)pThis->hPipe;
+}
+
+/**
+ * Prepare blocking mode.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_WRONG_ORDER if simultaneous non-blocking and blocking access is
+ * attempted.
+ *
+ * @param pThis The pipe handle.
+ *
+ * @remarks Caller owns the critical section.
+ */
+static int rtPipeTryBlocking(RTPIPEINTERNAL *pThis)
+{
+ if (!pThis->fBlocking)
+ {
+ if (pThis->cUsers != 0)
+ return VERR_WRONG_ORDER;
+
+ APIRET orc = DosSetNPHState(pThis->hPipe, NP_WAIT | NP_READMODE_BYTE);
+ if (orc != NO_ERROR)
+ {
+ if (orc != ERROR_BROKEN_PIPE && orc != ERROR_PIPE_NOT_CONNECTED)
+ return RTErrConvertFromOS2(orc);
+ pThis->fBrokenPipe = true;
+ }
+ pThis->fBlocking = true;
+ }
+
+ pThis->cUsers++;
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Prepare non-blocking mode.
+ *
+ * @returns IPRT status code.
+ * @retval VERR_WRONG_ORDER if simultaneous non-blocking and blocking access is
+ * attempted.
+ *
+ * @param pThis The pipe handle.
+ */
+static int rtPipeTryNonBlocking(RTPIPEINTERNAL *pThis)
+{
+ if (pThis->fBlocking)
+ {
+ if (pThis->cUsers != 0)
+ return VERR_WRONG_ORDER;
+
+ APIRET orc = DosSetNPHState(pThis->hPipe, NP_NOWAIT | NP_READMODE_BYTE);
+ if (orc != NO_ERROR)
+ {
+ if (orc != ERROR_BROKEN_PIPE && orc != ERROR_PIPE_NOT_CONNECTED)
+ return RTErrConvertFromOS2(orc);
+ pThis->fBrokenPipe = true;
+ }
+ pThis->fBlocking = false;
+ }
+
+ pThis->cUsers++;
+ return VINF_SUCCESS;
+}
+
+
+/**
+ * Checks if the read pipe has been broken.
+ *
+ * @returns true if broken, false if no.
+ * @param pThis The pipe handle (read).
+ */
+static bool rtPipeOs2IsBroken(RTPIPEINTERNAL *pThis)
+{
+ Assert(pThis->fRead);
+
+#if 0
+ /*
+ * Query it via the semaphore. Not sure how fast this is...
+ */
+ PIPESEMSTATE aStates[3]; RT_ZERO(aStates);
+ APIRET orc = DosQueryNPipeSemState(pThis->hev, &aStates[0], sizeof(aStates));
+ if (orc == NO_ERROR)
+ {
+ if (aStates[0].fStatus == NPSS_CLOSE)
+ return true;
+ if (aStates[0].fStatus == NPSS_RDATA)
+ return false;
+ }
+ AssertMsgFailed(("%d / %d\n", orc, aStates[0].fStatus));
+
+ /*
+ * Fall back / alternative method.
+ */
+#endif
+ ULONG cbActual = 0;
+ ULONG ulState = 0;
+ AVAILDATA Avail = { 0, 0 };
+ APIRET orc = DosPeekNPipe(pThis->hPipe, NULL, 0, &cbActual, &Avail, &ulState);
+ if (orc != NO_ERROR)
+ {
+ if (orc != ERROR_PIPE_BUSY)
+ AssertMsgFailed(("%d\n", orc));
+ return false;
+ }
+
+ return ulState != NP_STATE_CONNECTED;
}
RTDECL(int) RTPipeRead(RTPIPE hPipe, void *pvBuf, size_t cbToRead, size_t *pcbRead)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->fRead, VERR_ACCESS_DENIED);
+ AssertPtr(pcbRead);
+ AssertPtr(pvBuf);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = rtPipeTryNonBlocking(pThis);
+ if (RT_SUCCESS(rc))
+ {
+ RTCritSectLeave(&pThis->CritSect);
+
+ ULONG cbActual = 0;
+ APIRET orc = DosRead(pThis->hPipe, pvBuf, cbToRead, &cbActual);
+ if (orc == NO_ERROR)
+ {
+ if (cbActual || !cbToRead || !rtPipeOs2IsBroken(pThis))
+ *pcbRead = cbActual;
+ else
+ rc = VERR_BROKEN_PIPE;
+ }
+ else if (orc == ERROR_NO_DATA)
+ {
+ *pcbRead = 0;
+ rc = VINF_TRY_AGAIN;
+ }
+ else
+ rc = RTErrConvertFromOS2(orc);
+
+ RTCritSectEnter(&pThis->CritSect);
+ if (rc == VERR_BROKEN_PIPE)
+ pThis->fBrokenPipe = true;
+ pThis->cUsers--;
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+ return rc;
}
RTDECL(int) RTPipeReadBlocking(RTPIPE hPipe, void *pvBuf, size_t cbToRead, size_t *pcbRead)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->fRead, VERR_ACCESS_DENIED);
+ AssertPtr(pvBuf);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = rtPipeTryBlocking(pThis);
+ if (RT_SUCCESS(rc))
+ {
+ RTCritSectLeave(&pThis->CritSect);
+
+ size_t cbTotalRead = 0;
+ while (cbToRead > 0)
+ {
+ ULONG cbActual = 0;
+ APIRET orc = DosRead(pThis->hPipe, pvBuf, cbToRead, &cbActual);
+ if (orc != NO_ERROR)
+ {
+ rc = RTErrConvertFromOS2(orc);
+ break;
+ }
+ if (!cbActual && rtPipeOs2IsBroken(pThis))
+ {
+ rc = VERR_BROKEN_PIPE;
+ break;
+ }
+
+ /* advance */
+ pvBuf = (char *)pvBuf + cbActual;
+ cbTotalRead += cbActual;
+ cbToRead -= cbActual;
+ }
+
+ if (pcbRead)
+ {
+ *pcbRead = cbTotalRead;
+ if ( RT_FAILURE(rc)
+ && cbTotalRead)
+ rc = VINF_SUCCESS;
+ }
+
+ RTCritSectEnter(&pThis->CritSect);
+ if (rc == VERR_BROKEN_PIPE)
+ pThis->fBrokenPipe = true;
+ pThis->cUsers--;
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+ return rc;
+}
+
+
+/**
+ * Gets the available write buffer size of the pipe.
+ *
+ * @returns Number of bytes, 1 on failure.
+ * @param pThis The pipe handle.
+ */
+static ULONG rtPipeOs2GetSpace(RTPIPEINTERNAL *pThis)
+{
+ Assert(!pThis->fRead);
+
+#if 0 /* Not sure which is more efficient, neither are really optimal, I fear. */
+ /*
+ * Query via semaphore state.
+ * This will walk the list of active named pipes...
+ */
+ /** @todo Check how hev and hpipe are associated, if complicated, use the
+ * alternative method below. */
+ PIPESEMSTATE aStates[3]; RT_ZERO(aStates);
+ APIRET orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates));
+ if (orc == NO_ERROR)
+ {
+ if (aStates[0].fStatus == NPSS_WSPACE)
+ return aStates[0].usAvail;
+ if (aStates[1].fStatus == NPSS_WSPACE)
+ return aStates[1].usAvail;
+ return 0;
+ }
+ AssertMsgFailed(("%d / %d\n", orc, aStates[0].fStatus));
+
+#else
+ /*
+ * Query via the pipe info.
+ * This will have to lookup and store the pipe name.
+ */
+ union
+ {
+ PIPEINFO PipeInfo;
+ uint8_t abPadding[sizeof(PIPEINFO) + 127];
+ } Buf;
+ APIRET orc = DosQueryNPipeInfo(pThis->hPipe, 1, &Buf, sizeof(Buf));
+ if (orc == NO_ERROR)
+ return Buf.PipeInfo.cbOut;
+ AssertMsgFailed(("%d\n", orc));
+#endif
+
+ return 1;
}
RTDECL(int) RTPipeWrite(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+ AssertReturn(!pThis->fRead, VERR_ACCESS_DENIED);
+ AssertPtr(pcbWritten);
+ AssertPtr(pvBuf);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = rtPipeTryNonBlocking(pThis);
+ if (RT_SUCCESS(rc))
+ {
+ if (cbToWrite > 0)
+ {
+ ULONG cbActual = 0;
+ APIRET orc = DosWrite(pThis->hPipe, pvBuf, cbToWrite, &cbActual);
+ if (orc == NO_ERROR && cbActual == 0)
+ {
+ /* Retry with the request adjusted to the available buffer space. */
+ ULONG cbAvail = rtPipeOs2GetSpace(pThis);
+ orc = DosWrite(pThis->hPipe, pvBuf, RT_MIN(cbAvail, cbToWrite), &cbActual);
+ }
+
+ if (orc == NO_ERROR)
+ {
+ *pcbWritten = cbActual;
+ if (cbActual == 0)
+ rc = VINF_TRY_AGAIN;
+ }
+ else
+ {
+ rc = RTErrConvertFromOS2(orc);
+ if (rc == VERR_PIPE_NOT_CONNECTED)
+ rc = VERR_BROKEN_PIPE;
+ }
+ }
+ else
+ *pcbWritten = 0;
+
+ if (rc == VERR_BROKEN_PIPE)
+ pThis->fBrokenPipe = true;
+ pThis->cUsers--;
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+ return rc;
}
RTDECL(int) RTPipeWriteBlocking(RTPIPE hPipe, const void *pvBuf, size_t cbToWrite, size_t *pcbWritten)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+ AssertReturn(!pThis->fRead, VERR_ACCESS_DENIED);
+ AssertPtr(pvBuf);
+ AssertPtrNull(pcbWritten);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = rtPipeTryBlocking(pThis);
+ if (RT_SUCCESS(rc))
+ {
+ RTCritSectLeave(&pThis->CritSect);
+
+ size_t cbTotalWritten = 0;
+ while (cbToWrite > 0)
+ {
+ ULONG cbActual = 0;
+ APIRET orc = DosWrite(pThis->hPipe, pvBuf, cbToWrite, &cbActual);
+ if (orc != NO_ERROR)
+ {
+ rc = RTErrConvertFromOS2(orc);
+ if (rc == VERR_PIPE_NOT_CONNECTED)
+ rc = VERR_BROKEN_PIPE;
+ break;
+ }
+ pvBuf = (char const *)pvBuf + cbActual;
+ cbToWrite -= cbActual;
+ cbTotalWritten += cbActual;
+ }
+
+ if (pcbWritten)
+ {
+ *pcbWritten = cbTotalWritten;
+ if ( RT_FAILURE(rc)
+ && cbTotalWritten)
+ rc = VINF_SUCCESS;
+ }
+
+ RTCritSectEnter(&pThis->CritSect);
+ if (rc == VERR_BROKEN_PIPE)
+ pThis->fBrokenPipe = true;
+ pThis->cUsers--;
+ }
+ else
+ rc = VERR_WRONG_ORDER;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+ return rc;
}
RTDECL(int) RTPipeFlush(RTPIPE hPipe)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+ AssertReturn(!pThis->fRead, VERR_ACCESS_DENIED);
+
+ APIRET orc = DosResetBuffer(pThis->hPipe);
+ if (orc != NO_ERROR)
+ {
+ int rc = RTErrConvertFromOS2(orc);
+ if (rc == VERR_BROKEN_PIPE)
+ {
+ RTCritSectEnter(&pThis->CritSect);
+ pThis->fBrokenPipe = true;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+ return rc;
+ }
+ return VINF_SUCCESS;
}
RTDECL(int) RTPipeSelectOne(RTPIPE hPipe, RTMSINTERVAL cMillies)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+
+ uint64_t const StartMsTS = RTTimeMilliTS();
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ rc = rtPipeOs2EnsureSem(pThis);
+ if (RT_SUCCESS(rc) && cMillies > 0)
+ {
+ /* Stop polling attempts if we might block. */
+ if (pThis->hPollSet == NIL_RTPOLLSET)
+ pThis->hPollSet = (RTPOLLSET)(uintptr_t)0xbeef0042;
+ else
+ rc = VERR_WRONG_ORDER;
+ }
+ if (RT_SUCCESS(rc))
+ {
+ for (unsigned iLoop = 0;; iLoop++)
+ {
+ /*
+ * Check the handle state.
+ */
+ APIRET orc;
+ if (cMillies > 0)
+ {
+ ULONG ulIgnore;
+ orc = DosResetEventSem(pThis->hev, &ulIgnore);
+ AssertMsg(orc == NO_ERROR || orc == ERROR_ALREADY_RESET, ("%d\n", orc));
+ }
+
+ PIPESEMSTATE aStates[4]; RT_ZERO(aStates);
+ orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates));
+ if (orc != NO_ERROR)
+ {
+ rc = RTErrConvertFromOS2(orc);
+ break;
+ }
+ int i = 0;
+ if (pThis->fRead)
+ while (aStates[i].fStatus == NPSS_WSPACE)
+ i++;
+ else
+ while (aStates[i].fStatus == NPSS_RDATA)
+ i++;
+ if (aStates[i].fStatus == NPSS_CLOSE)
+ break;
+ Assert(aStates[i].fStatus == NPSS_WSPACE || aStates[i].fStatus == NPSS_RDATA || aStates[i].fStatus == NPSS_EOI);
+ if ( aStates[i].fStatus != NPSS_EOI
+ && aStates[i].usAvail > 0)
+ break;
+
+ /*
+ * Check for timeout.
+ */
+ ULONG cMsMaxWait = SEM_INDEFINITE_WAIT;
+ if (cMillies != RT_INDEFINITE_WAIT)
+ {
+ uint64_t cElapsed = RTTimeMilliTS() - StartMsTS;
+ if (cElapsed >= cMillies)
+ {
+ rc = VERR_TIMEOUT;
+ break;
+ }
+ cMsMaxWait = cMillies - (uint32_t)cElapsed;
+ }
+
+ /*
+ * Wait.
+ */
+ RTCritSectLeave(&pThis->CritSect);
+ orc = DosWaitEventSem(pThis->hev, cMsMaxWait);
+ RTCritSectEnter(&pThis->CritSect);
+ if (orc != NO_ERROR && orc != ERROR_TIMEOUT && orc != ERROR_SEM_TIMEOUT )
+ {
+ rc = RTErrConvertFromOS2(orc);
+ break;
+ }
+ }
+
+ if (rc == VERR_BROKEN_PIPE)
+ pThis->fBrokenPipe = true;
+ if (cMillies > 0)
+ pThis->hPollSet = NIL_RTPOLLSET;
+ }
+
+ RTCritSectLeave(&pThis->CritSect);
+ return rc;
}
RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable)
{
- return VERR_NOT_IMPLEMENTED;
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, VERR_INVALID_HANDLE);
+ AssertReturn(pThis->fRead, VERR_PIPE_NOT_READ);
+ AssertPtrReturn(pcbReadable, VERR_INVALID_POINTER);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ ULONG cbActual = 0;
+ ULONG ulState = 0;
+ AVAILDATA Avail = { 0, 0 };
+ APIRET orc = DosPeekNPipe(pThis->hPipe, NULL, 0, &cbActual, &Avail, &ulState);
+ if (orc == NO_ERROR)
+ {
+ if (Avail.cbpipe > 0 || ulState == NP_STATE_CONNECTED)
+ *pcbReadable = Avail.cbpipe;
+ else
+ rc = VERR_PIPE_NOT_CONNECTED; /*??*/
+ }
+ else
+ rc = RTErrConvertFromOS2(orc);
+
+ RTCritSectLeave(&pThis->CritSect);
+ return rc;
}
+
+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_WRITE) || !pThis->fRead, VERR_INVALID_PARAMETER);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = rtPipeOs2EnsureSem(pThis);
+ if (RT_SUCCESS(rc))
+ *phNative = (RTHCINTPTR)pThis->hev;
+ RTCritSectLeave(&pThis->CritSect);
+ }
+ return rc;
+}
+
+
+/**
+ * Checks for pending events.
+ *
+ * @returns Event mask or 0.
+ * @param pThis The pipe handle.
+ * @param fEvents The desired events.
+ * @param fResetEvtSem Whether to reset the event semaphore.
+ */
+static uint32_t rtPipePollCheck(RTPIPEINTERNAL *pThis, uint32_t fEvents, bool fResetEvtSem)
+{
+ /*
+ * Reset the event semaphore if we're gonna wait.
+ */
+ APIRET orc;
+ ULONG ulIgnore;
+ if (fResetEvtSem)
+ {
+ orc = DosResetEventSem(pThis->hev, &ulIgnore);
+ AssertMsg(orc == NO_ERROR || orc == ERROR_ALREADY_RESET, ("%d\n", orc));
+ }
+
+ /*
+ * Check for events.
+ */
+ uint32_t fRetEvents = 0;
+ if (pThis->fBrokenPipe)
+ fRetEvents |= RTPOLL_EVT_ERROR;
+ else if (pThis->fRead)
+ {
+ ULONG cbActual = 0;
+ ULONG ulState = 0;
+ AVAILDATA Avail = { 0, 0 };
+ orc = DosPeekNPipe(pThis->hPipe, NULL, 0, &cbActual, &Avail, &ulState);
+ if (orc != NO_ERROR)
+ {
+ fRetEvents |= RTPOLL_EVT_ERROR;
+ if (orc == ERROR_BROKEN_PIPE || orc == ERROR_PIPE_NOT_CONNECTED)
+ pThis->fBrokenPipe = true;
+ }
+ else if (Avail.cbpipe > 0)
+ fRetEvents |= RTPOLL_EVT_READ;
+ else if (ulState != NP_STATE_CONNECTED)
+ {
+ fRetEvents |= RTPOLL_EVT_ERROR;
+ pThis->fBrokenPipe = true;
+ }
+ }
+ else
+ {
+ PIPESEMSTATE aStates[4]; RT_ZERO(aStates);
+ orc = DosQueryNPipeSemState((HSEM)pThis->hev, &aStates[0], sizeof(aStates));
+ if (orc == NO_ERROR)
+ {
+ int i = 0;
+ while (aStates[i].fStatus == NPSS_RDATA)
+ i++;
+ if (aStates[i].fStatus == NPSS_CLOSE)
+ {
+ fRetEvents |= RTPOLL_EVT_ERROR;
+ pThis->fBrokenPipe = true;
+ }
+ else if ( aStates[i].fStatus == NPSS_WSPACE
+ && aStates[i].usAvail > 0)
+ fRetEvents |= RTPOLL_EVT_WRITE;
+ }
+ else
+ {
+ fRetEvents |= RTPOLL_EVT_ERROR;
+ if (orc == ERROR_BROKEN_PIPE || orc == ERROR_PIPE_NOT_CONNECTED)
+ pThis->fBrokenPipe = true;
+ }
+ }
+
+ return fRetEvents & (fEvents | RTPOLL_EVT_ERROR);
+}
+
+
+uint32_t rtPipePollStart(RTPIPE hPipe, RTPOLLSET hPollSet, uint32_t fEvents, bool fFinalEntry, bool fNoWait)
+{
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, UINT32_MAX);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, UINT32_MAX);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ AssertRCReturn(rc, UINT32_MAX);
+
+ /* Check that this is the only current use of this pipe. */
+ uint32_t fRetEvents;
+ if ( pThis->cUsers == 0
+ || pThis->hPollSet == NIL_RTPOLLSET)
+ {
+ fRetEvents = rtPipePollCheck(pThis, fEvents, fNoWait);
+ if (!fRetEvents && !fNoWait)
+ {
+ /* Mark the set busy while waiting. */
+ pThis->cUsers++;
+ pThis->hPollSet = hPollSet;
+ }
+ }
+ else
+ {
+ AssertFailed();
+ fRetEvents = UINT32_MAX;
+ }
+
+ RTCritSectLeave(&pThis->CritSect);
+ return fRetEvents;
+}
+
+
+uint32_t rtPipePollDone(RTPIPE hPipe, uint32_t fEvents, bool fFinalEntry, bool fHarvestEvents)
+{
+ RTPIPEINTERNAL *pThis = hPipe;
+ AssertPtrReturn(pThis, 0);
+ AssertReturn(pThis->u32Magic == RTPIPE_MAGIC, 0);
+
+ int rc = RTCritSectEnter(&pThis->CritSect);
+ AssertRCReturn(rc, 0);
+
+ Assert(pThis->cUsers > 0);
+
+ /* harvest events. */
+ uint32_t fRetEvents = rtPipePollCheck(pThis, fEvents, false);
+
+ /* update counters. */
+ pThis->cUsers--;
+ pThis->hPollSet = NIL_RTPOLLSET;
+
+ RTCritSectLeave(&pThis->CritSect);
+ return fRetEvents;
+}
diff --git a/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp b/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp
index 26ee5b49..3ee59bfc 100644
--- a/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.cpp
+++ b/src/VBox/Runtime/r3/os2/rtProcInitExePath-os2.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/os2/sched-os2.cpp b/src/VBox/Runtime/r3/os2/sched-os2.cpp
index 02a4bbd3..d6e5bce7 100644
--- a/src/VBox/Runtime/r3/os2/sched-os2.cpp
+++ b/src/VBox/Runtime/r3/os2/sched-os2.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/os2/sems-os2.cpp b/src/VBox/Runtime/r3/os2/sems-os2.cpp
index d19a3246..a7ca3097 100644
--- a/src/VBox/Runtime/r3/os2/sems-os2.cpp
+++ b/src/VBox/Runtime/r3/os2/sems-os2.cpp
@@ -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/os2/systemmem-os2.cpp b/src/VBox/Runtime/r3/os2/systemmem-os2.cpp
new file mode 100644
index 00000000..0f95ab24
--- /dev/null
+++ b/src/VBox/Runtime/r3/os2/systemmem-os2.cpp
@@ -0,0 +1,70 @@
+/* $Id: systemmem-os2.cpp $ */
+/** @file
+ * IPRT - RTSystemQueryTotalRam, OS/2 ring-3.
+ */
+
+/*
+ * 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;
+ * 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 INCL_DOSMISC
+#define INCL_ERRORS
+#include <os2.h>
+#undef RT_MAX
+
+#include <iprt/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+#include <iprt/string.h>
+
+
+RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ ULONG cbMem;
+ APIRET rc = DosQuerySysInfo(QSV_TOTPHYSMEM, QSV_TOTPHYSMEM, &cbMem, sizeof(cbMem));
+ if (rc != NO_ERROR)
+ return RTErrConvertFromOS2(rc);
+
+ *pcb = cbMem;
+ return VINF_SUCCESS;
+}
+
+
+RTDECL(int) RTSystemQueryAvailableRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ ULONG cbAvailMem;
+ APIRET rc = DosQuerySysInfo(QSV_TOTAVAILMEM, QSV_TOTAVAILMEM, &cbAvailMem, sizeof(cbAvailMem));
+ if (rc != NO_ERROR)
+ return RTErrConvertFromOS2(rc);
+
+ *pcb = cbAvailMem;
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Runtime/r3/os2/thread-os2.cpp b/src/VBox/Runtime/r3/os2/thread-os2.cpp
index e2efa01f..e6f20213 100644
--- a/src/VBox/Runtime/r3/os2/thread-os2.cpp
+++ b/src/VBox/Runtime/r3/os2/thread-os2.cpp
@@ -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;
@@ -78,7 +78,7 @@ DECLHIDDEN(int) rtThreadNativeInit(void)
}
-DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
+static void rtThreadOs2BlockSigAlarm(void)
{
/*
* Block SIGALRM - required for timer-posix.cpp.
@@ -89,6 +89,17 @@ DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
sigemptyset(&SigSet);
sigaddset(&SigSet, SIGALRM);
sigprocmask(SIG_BLOCK, &SigSet, NULL);
+}
+
+
+DECLHIDDEN(void) rtThreadNativeReInitObtrusive(void)
+{
+ rtThreadOs2BlockSigAlarm();
+}
+
+
+DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
+{
*g_ppCurThread = pThread;
return VINF_SUCCESS;
@@ -107,15 +118,7 @@ DECLHIDDEN(void) rtThreadNativeDestroy(PRTTHREADINT pThread)
*/
static void rtThreadNativeMain(void *pvArgs)
{
- /*
- * Block SIGALRM - required for timer-posix.cpp.
- * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
- * It will not help much if someone creates threads directly using pthread_create. :/
- */
- sigset_t SigSet;
- sigemptyset(&SigSet);
- sigaddset(&SigSet, SIGALRM);
- sigprocmask(SIG_BLOCK, &SigSet, NULL);
+ rtThreadOs2BlockSigAlarm();
/*
* Call common main.
diff --git a/src/VBox/Runtime/r3/path.cpp b/src/VBox/Runtime/r3/path.cpp
index 591f0556..e43f5d95 100644
--- a/src/VBox/Runtime/r3/path.cpp
+++ b/src/VBox/Runtime/r3/path.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/poll.cpp b/src/VBox/Runtime/r3/poll.cpp
new file mode 100644
index 00000000..ea71cb43
--- /dev/null
+++ b/src/VBox/Runtime/r3/poll.cpp
@@ -0,0 +1,1109 @@
+/* $Id: poll.cpp $ */
+/** @file
+ * IPRT - Polling I/O Handles, Windows+Posix Implementation.
+ */
+
+/*
+ * 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;
+ * 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/cdefs.h>
+#ifdef RT_OS_WINDOWS
+# include <Windows.h>
+
+#elif defined(RT_OS_OS2)
+# define INCL_BASE
+# include <os2.h>
+# include <limits.h>
+# include <sys/socket.h>
+
+#else
+# include <limits.h>
+# include <errno.h>
+# include <sys/poll.h>
+#endif
+
+#include <iprt/poll.h>
+#include "internal/iprt.h"
+
+#include <iprt/alloca.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/pipe.h>
+#include <iprt/socket.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"
+
+
+/*******************************************************************************
+* Defined Constants And Macros *
+*******************************************************************************/
+/** The maximum poll set size.
+ * @remarks To help portability, we set this to the Windows limit. We can lift
+ * this restriction later if it becomes necessary. */
+#define RTPOLL_SET_MAX 64
+
+
+
+/*******************************************************************************
+* 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.
+ */
+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 allocated handles. */
+ uint16_t cHandlesAllocated;
+ /** The number of valid handles in the set. */
+ uint16_t cHandles;
+
+#ifdef RT_OS_WINDOWS
+ /** Pointer to an array of native handles. */
+ HANDLE *pahNative;
+#elif defined(RT_OS_OS2)
+ /** The semaphore records. */
+ PSEMRECORD paSemRecs;
+ /** The multiple wait semaphore used for non-socket waits. */
+ HMUX hmux;
+ /** os2_select template. */
+ int *pafdSelect;
+ /** The number of sockets to monitor for read. */
+ uint16_t cReadSockets;
+ /** The number of sockets to monitor for write. */
+ uint16_t cWriteSockets;
+ /** The number of sockets to monitor for exceptions. */
+ uint16_t cXcptSockets;
+ /** The number of pipes. */
+ uint16_t cPipes;
+ /** Pointer to an array of native handles. */
+ PRTHCINTPTR pahNative;
+#else
+ /** Pointer to an array of pollfd structures. */
+ struct pollfd *paPollFds;
+#endif
+ /** Pointer to an array of handles and IDs. */
+ PRTPOLLSETHNDENT paHandles;
+} RTPOLLSETINTERNAL;
+
+
+
+/**
+ * Common worker for RTPoll and RTPollNoResume
+ */
+static int rtPollNoResumeWorker(RTPOLLSETINTERNAL *pThis, uint64_t MsStart, 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;
+ }
+
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+ /*
+ * 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->paHandles[i].enmType)
+ {
+ case RTHANDLETYPE_PIPE:
+ fEvents = rtPipePollStart(pThis->paHandles[i].u.hPipe, pThis, pThis->paHandles[i].fEvents,
+ pThis->paHandles[i].fFinalEntry, fNoWait);
+ break;
+
+ case RTHANDLETYPE_SOCKET:
+ fEvents = rtSocketPollStart(pThis->paHandles[i].u.hSocket, pThis, pThis->paHandles[i].fEvents,
+ pThis->paHandles[i].fFinalEntry, fNoWait);
+ break;
+
+ default:
+ AssertFailed();
+ fEvents = UINT32_MAX;
+ break;
+ }
+ if (fEvents)
+ break;
+ }
+ if ( fEvents
+ || fNoWait)
+ {
+
+ if (pid)
+ *pid = pThis->paHandles[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->paHandles[i].enmType)
+ {
+ case RTHANDLETYPE_PIPE:
+ rtPipePollDone(pThis->paHandles[i].u.hPipe, pThis->paHandles[i].fEvents,
+ pThis->paHandles[i].fFinalEntry, false);
+ break;
+
+ case RTHANDLETYPE_SOCKET:
+ rtSocketPollDone(pThis->paHandles[i].u.hSocket, pThis->paHandles[i].fEvents,
+ pThis->paHandles[i].fFinalEntry, false);
+ break;
+
+ default:
+ AssertFailed();
+ break;
+ }
+ }
+
+ return rc;
+ }
+
+
+ /*
+ * Wait.
+ */
+# ifdef RT_OS_WINDOWS
+ DWORD dwRc = WaitForMultipleObjectsEx(cHandles, pThis->pahNative,
+ 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;
+ }
+
+# else /* RT_OS_OS2 */
+ APIRET orc;
+ ULONG ulUser = 0;
+ uint16_t cSockets = pThis->cReadSockets + pThis->cWriteSockets + pThis->cXcptSockets;
+ if (cSockets == 0)
+ {
+ /* Only pipes. */
+ AssertReturn(pThis->cPipes > 0, VERR_INTERNAL_ERROR_2);
+ orc = DosWaitMuxWaitSem(pThis->hmux,
+ cMillies == RT_INDEFINITE_WAIT ? SEM_INDEFINITE_WAIT : RT_MIN(cMillies, SEM_INDEFINITE_WAIT - 1),
+ &ulUser);
+ rc = RTErrConvertFromOS2(orc);
+ }
+ else
+ {
+ int *pafdSelect = (int *)alloca(cSockets + 1);
+ if (pThis->cPipes == 0)
+ {
+ /* Only sockets. */
+ memcpy(pafdSelect, pThis->pafdSelect, sizeof(pThis->pafdSelect[0]) * (cSockets + 1));
+ rc = os2_select(pafdSelect, pThis->cReadSockets, pThis->cWriteSockets, pThis->cXcptSockets,
+ cMillies == RT_INDEFINITE_WAIT ? -1 : (long)RT_MIN(cMillies, LONG_MAX));
+ if (rc > 0)
+ rc = VINF_SUCCESS;
+ else if (rc == 0)
+ rc = VERR_TIMEOUT;
+ else
+ rc = RTErrConvertFromErrno(sock_errno());
+ }
+ else
+ {
+ /* Mix of both - taking the easy way out, not optimal, but whatever... */
+ do
+ {
+ orc = DosWaitMuxWaitSem(pThis->hmux, 8, &ulUser);
+ if (orc != ERROR_TIMEOUT && orc != ERROR_SEM_TIMEOUT)
+ {
+ rc = RTErrConvertFromOS2(orc);
+ break;
+ }
+
+ memcpy(pafdSelect, pThis->pafdSelect, sizeof(pThis->pafdSelect[0]) * (cSockets + 1));
+ rc = os2_select(pafdSelect, pThis->cReadSockets, pThis->cWriteSockets, pThis->cXcptSockets, 8);
+ if (rc != 0)
+ {
+ if (rc > 0)
+ rc = VINF_SUCCESS;
+ else
+ rc = RTErrConvertFromErrno(sock_errno());
+ break;
+ }
+ } while (cMillies == RT_INDEFINITE_WAIT || RTTimeMilliTS() - MsStart < cMillies);
+ }
+ }
+# endif /* RT_OS_OS2 */
+
+ /*
+ * Get event (if pending) and do wait cleanup.
+ */
+ bool fHarvestEvents = true;
+ for (i = 0; i < cHandles; i++)
+ {
+ fEvents = 0;
+ switch (pThis->paHandles[i].enmType)
+ {
+ case RTHANDLETYPE_PIPE:
+ fEvents = rtPipePollDone(pThis->paHandles[i].u.hPipe, pThis->paHandles[i].fEvents,
+ pThis->paHandles[i].fFinalEntry, fHarvestEvents);
+ break;
+
+ case RTHANDLETYPE_SOCKET:
+ fEvents = rtSocketPollDone(pThis->paHandles[i].u.hSocket, pThis->paHandles[i].fEvents,
+ pThis->paHandles[i].fFinalEntry, fHarvestEvents);
+ break;
+
+ default:
+ AssertFailed();
+ break;
+ }
+ if ( fEvents
+ && fHarvestEvents)
+ {
+ Assert(fEvents != UINT32_MAX);
+ fHarvestEvents = false;
+ if (pfEvents)
+ *pfEvents = fEvents;
+ if (pid)
+ *pid = pThis->paHandles[i].id;
+ rc = VINF_SUCCESS;
+ }
+ }
+
+#else /* POSIX */
+
+ /* clear the revents. */
+ uint32_t i = pThis->cHandles;
+ while (i-- > 0)
+ pThis->paPollFds[i].revents = 0;
+
+ rc = poll(&pThis->paPollFds[0], pThis->cHandles,
+ cMillies == RT_INDEFINITE_WAIT || cMillies >= INT_MAX
+ ? -1
+ : (int)cMillies);
+ if (rc == 0)
+ return VERR_TIMEOUT;
+ if (rc < 0)
+ return RTErrConvertFromErrno(errno);
+ for (i = 0; i < pThis->cHandles; i++)
+ if (pThis->paPollFds[i].revents)
+ {
+ if (pfEvents)
+ {
+ *pfEvents = 0;
+ if (pThis->paPollFds[i].revents & (POLLIN
+# ifdef POLLRDNORM
+ | POLLRDNORM /* just in case */
+# endif
+# ifdef POLLRDBAND
+ | POLLRDBAND /* ditto */
+# endif
+# ifdef POLLPRI
+ | POLLPRI /* ditto */
+# endif
+# ifdef POLLMSG
+ | POLLMSG /* ditto */
+# endif
+# ifdef POLLWRITE
+ | POLLWRITE /* ditto */
+# endif
+# ifdef POLLEXTEND
+ | POLLEXTEND /* ditto */
+# endif
+ )
+ )
+ *pfEvents |= RTPOLL_EVT_READ;
+
+ if (pThis->paPollFds[i].revents & (POLLOUT
+# ifdef POLLWRNORM
+ | POLLWRNORM /* just in case */
+# endif
+# ifdef POLLWRBAND
+ | POLLWRBAND /* ditto */
+# endif
+ )
+ )
+ *pfEvents |= RTPOLL_EVT_WRITE;
+
+ if (pThis->paPollFds[i].revents & (POLLERR | POLLHUP | POLLNVAL
+# ifdef POLLRDHUP
+ | POLLRDHUP
+# endif
+ )
+ )
+ *pfEvents |= RTPOLL_EVT_ERROR;
+ }
+ if (pid)
+ *pid = pThis->paHandles[i].id;
+ return VINF_SUCCESS;
+ }
+
+ AssertFailed();
+ RTThreadYield();
+ rc = VERR_INTERRUPTED;
+
+#endif /* POSIX */
+
+ 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, 0, cMillies, pfEvents, pid);
+ while (rc == VERR_INTERRUPTED);
+ }
+ else
+ {
+ uint64_t MsStart = RTTimeMilliTS();
+ rc = rtPollNoResumeWorker(pThis, MsStart, cMillies, pfEvents, pid);
+ while (RT_UNLIKELY(rc == VERR_INTERRUPTED))
+ {
+ if (RTTimeMilliTS() - MsStart >= cMillies)
+ {
+ rc = VERR_TIMEOUT;
+ break;
+ }
+ rc = rtPollNoResumeWorker(pThis, MsStart, 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;
+ if (cMillies == RT_INDEFINITE_WAIT || cMillies == 0)
+ rc = rtPollNoResumeWorker(pThis, 0, cMillies, pfEvents, pid);
+ else
+ rc = rtPollNoResumeWorker(pThis, RTTimeMilliTS(), cMillies, pfEvents, pid);
+
+ ASMAtomicWriteBool(&pThis->fBusy, false);
+
+ return rc;
+}
+
+
+RTDECL(int) RTPollSetCreate(PRTPOLLSET phPollSet)
+{
+ AssertPtrReturn(phPollSet, VERR_INVALID_POINTER);
+ RTPOLLSETINTERNAL *pThis = (RTPOLLSETINTERNAL *)RTMemAlloc(sizeof(RTPOLLSETINTERNAL));
+ if (!pThis)
+ return VERR_NO_MEMORY;
+
+ pThis->fBusy = false;
+ pThis->cHandles = 0;
+ pThis->cHandlesAllocated = 0;
+#ifdef RT_OS_WINDOWS
+ pThis->pahNative = NULL;
+#elif defined(RT_OS_OS2)
+ pThis->hmux = NULLHANDLE;
+ APIRET orc = DosCreateMuxWaitSem(NULL, &pThis->hmux, 0, NULL, DCMW_WAIT_ANY);
+ if (orc != NO_ERROR)
+ {
+ RTMemFree(pThis);
+ return RTErrConvertFromOS2(orc);
+ }
+ pThis->pafdSelect = NULL;
+ pThis->cReadSockets = 0;
+ pThis->cWriteSockets = 0;
+ pThis->cXcptSockets = 0;
+ pThis->cPipes = 0;
+ pThis->pahNative = NULL;
+#else
+ pThis->paPollFds = NULL;
+#endif
+ pThis->paHandles = NULL;
+ pThis->u32Magic = RTPOLLSET_MAGIC;
+
+ *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);
+#ifdef RT_OS_WINDOWS
+ RTMemFree(pThis->pahNative);
+ pThis->pahNative = NULL;
+#elif defined(RT_OS_OS2)
+ DosCloseMuxWaitSem(pThis->hmux);
+ pThis->hmux = NULLHANDLE;
+ RTMemFree(pThis->pafdSelect);
+ pThis->pafdSelect = NULL;
+ RTMemFree(pThis->pahNative);
+ pThis->pahNative = NULL;
+#else
+ RTMemFree(pThis->paPollFds);
+ pThis->paPollFds = NULL;
+#endif
+ RTMemFree(pThis->paHandles);
+ pThis->paHandles = NULL;
+ RTMemFree(pThis);
+
+ return VINF_SUCCESS;
+}
+
+#ifdef RT_OS_OS2
+
+/**
+ * Checks if @a fd is in the specific socket subset.
+ *
+ * @returns true / false.
+ * @param pThis The poll set instance.
+ * @param iStart The index to start at.
+ * @param cFds The number of sockets to check.
+ * @param fd The socket to look for.
+ */
+static bool rtPollSetOs2IsSocketInSet(RTPOLLSETINTERNAL *pThis, uint16_t iStart, uint16_t cFds, int fd)
+{
+ int const *pfd = pThis->pafdSelect + iStart;
+ while (cFds-- > 0)
+ {
+ if (*pfd == fd)
+ return true;
+ pfd++;
+ }
+ return false;
+}
+
+
+/**
+ * Removes a socket from a select template subset.
+ *
+ * @param pThis The poll set instance.
+ * @param iStart The index to start at.
+ * @param pcSubSet The subset counter to decrement.
+ * @param fd The socket to remove.
+ */
+static void rtPollSetOs2RemoveSocket(RTPOLLSETINTERNAL *pThis, uint16_t iStart, uint16_t *pcFds, int fd)
+{
+ uint16_t cFds = *pcFds;
+ while (cFds-- > 0)
+ {
+ if (pThis->pafdSelect[iStart] == fd)
+ break;
+ iStart++;
+ }
+ AssertReturnVoid(iStart != UINT16_MAX);
+
+ /* Note! We keep a -1 entry at the end of the set, thus the + 1. */
+ memmove(&pThis->pafdSelect[iStart],
+ &pThis->pafdSelect[iStart + 1],
+ pThis->cReadSockets + pThis->cWriteSockets + pThis->cXcptSockets + 1 - 1 - iStart);
+ *pcFds -= 1;
+
+ Assert(pThis->pafdSelect[pThis->cReadSockets + pThis->cWriteSockets + pThis->cXcptSockets] == -1);
+}
+
+
+/**
+ * Adds a socket to a select template subset.
+ *
+ * @param pThis The poll set instance.
+ * @param iInsert The insertion point.
+ * ASSUMED to be at the end of the subset.
+ * @param pcSubSet The subset counter to increment.
+ * @param fd The socket to add.
+ */
+static void rtPollSetOs2AddSocket(RTPOLLSETINTERNAL *pThis, uint16_t iInsert, uint16_t *pcFds, int fd)
+{
+ Assert(!rtPollSetOs2IsSocketInSet(pThis, iInsert - *pcFds, *pcFds, fd));
+
+ /* Note! We keep a -1 entry at the end of the set, thus the + 1. */
+ memmove(&pThis->pafdSelect[iInsert + 1],
+ &pThis->pafdSelect[iInsert],
+ pThis->cReadSockets + pThis->cWriteSockets + pThis->cXcptSockets + 1 - iInsert);
+ pThis->pafdSelect[iInsert] = fd;
+ *pcFds += 1;
+
+ Assert(pThis->pafdSelect[pThis->cReadSockets + pThis->cWriteSockets + pThis->cXcptSockets] == -1);
+}
+
+
+/**
+ * OS/2 specific RTPollSetAdd worker.
+ *
+ * @returns IPRT status code.
+ * @param pThis The poll set instance.
+ * @param i The index of the new handle (not committed).
+ * @param fEvents The events to poll for.
+ */
+static int rtPollSetOs2Add(RTPOLLSETINTERNAL *pThis, unsigned i, uint32_t fEvents)
+{
+ if (pThis->paHandles[i].enmType == RTHANDLETYPE_SOCKET)
+ {
+ int const fdSocket = pThis->pahNative[i];
+ if ( (fEvents & RTPOLL_EVT_READ)
+ && rtPollSetOs2IsSocketInSet(pThis, 0, pThis->cReadSockets, fdSocket))
+ rtPollSetOs2AddSocket(pThis, pThis->cReadSockets, &pThis->cReadSockets, fdSocket);
+
+ if ( (fEvents & RTPOLL_EVT_WRITE)
+ && rtPollSetOs2IsSocketInSet(pThis, pThis->cReadSockets, pThis->cWriteSockets, fdSocket))
+ rtPollSetOs2AddSocket(pThis, pThis->cReadSockets + pThis->cWriteSockets, &pThis->cWriteSockets, fdSocket);
+
+ if ( (fEvents & RTPOLL_EVT_ERROR)
+ && rtPollSetOs2IsSocketInSet(pThis, pThis->cReadSockets + pThis->cWriteSockets, pThis->cXcptSockets, fdSocket))
+ rtPollSetOs2AddSocket(pThis, pThis->cReadSockets + pThis->cWriteSockets + pThis->cXcptSockets,
+ &pThis->cXcptSockets, fdSocket);
+ }
+ else if (pThis->paHandles[i].enmType == RTHANDLETYPE_PIPE)
+ {
+ SEMRECORD Rec = { (HSEM)pThis->pahNative[i], pThis->paHandles[i].id };
+ APIRET orc = DosAddMuxWaitSem(pThis->hmux, &Rec);
+ if (orc != NO_ERROR && orc != ERROR_DUPLICATE_HANDLE)
+ return RTErrConvertFromOS2(orc);
+ pThis->cPipes++;
+ }
+ else
+ AssertFailedReturn(VERR_INTERNAL_ERROR_2);
+ return VINF_SUCCESS;
+}
+
+#endif /* RT_OS_OS2 */
+
+/**
+ * Grows the poll set.
+ *
+ * @returns VINF_SUCCESS or VERR_NO_MEMORY.
+ * @param pThis The poll set instance.
+ * @param cHandlesNew The new poll set size.
+ */
+static int rtPollSetGrow(RTPOLLSETINTERNAL *pThis, uint32_t cHandlesNew)
+{
+ Assert(cHandlesNew > pThis->cHandlesAllocated);
+
+ /* The common array. */
+ void *pvNew = RTMemRealloc(pThis->paHandles, cHandlesNew * sizeof(pThis->paHandles[0]));
+ if (!pvNew)
+ return VERR_NO_MEMORY;
+ pThis->paHandles = (PRTPOLLSETHNDENT)pvNew;
+
+
+ /* OS specific handles */
+#if defined(RT_OS_WINDOWS)
+ pvNew = RTMemRealloc(pThis->pahNative, cHandlesNew * sizeof(pThis->pahNative[0]));
+ if (!pvNew)
+ return VERR_NO_MEMORY;
+ pThis->pahNative = (HANDLE *)pvNew;
+
+#elif defined(RT_OS_OS2)
+ pvNew = RTMemRealloc(pThis->pahNative, cHandlesNew * sizeof(pThis->pahNative[0]));
+ if (!pvNew)
+ return VERR_NO_MEMORY;
+ pThis->pahNative = (PRTHCINTPTR)pvNew;
+
+ pvNew = RTMemRealloc(pThis->pafdSelect, (cHandlesNew * 3 + 1) * sizeof(pThis->pafdSelect[0]));
+ if (!pvNew)
+ return VERR_NO_MEMORY;
+ pThis->pafdSelect = (int *)pvNew;
+ if (pThis->cHandlesAllocated == 0)
+ pThis->pafdSelect[0] = -1;
+
+#else
+ pvNew = RTMemRealloc(pThis->paPollFds, cHandlesNew * sizeof(pThis->paPollFds[0]));
+ if (!pvNew)
+ return VERR_NO_MEMORY;
+ pThis->paPollFds = (struct pollfd *)pvNew;
+
+#endif
+
+ pThis->cHandlesAllocated = (uint16_t)cHandlesNew;
+ 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.
+ */
+
+ int rc = VINF_SUCCESS;
+ RTHCINTPTR hNative = -1;
+ RTHANDLEUNION uh;
+ uh.uInt = 0;
+ switch (pHandle->enmType)
+ {
+ case RTHANDLETYPE_PIPE:
+ uh.hPipe = pHandle->u.hPipe;
+ if (uh.hPipe == NIL_RTPIPE)
+ return VINF_SUCCESS;
+ rc = rtPipePollGetHandle(uh.hPipe, fEvents, &hNative);
+ break;
+
+ case RTHANDLETYPE_SOCKET:
+ uh.hSocket = pHandle->u.hSocket;
+ if (uh.hSocket == NIL_RTSOCKET)
+ return VINF_SUCCESS;
+ 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))
+ {
+ AssertReturn(ASMAtomicCmpXchgBool(&pThis->fBusy, true, false), VERR_CONCURRENT_ACCESS);
+
+ 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->paHandles[j].id == id)
+ {
+ rc = VERR_POLL_HANDLE_ID_EXISTS;
+ break;
+ }
+ if ( pThis->paHandles[j].enmType == pHandle->enmType
+ && pThis->paHandles[j].u.uInt == uh.uInt)
+ iPrev = j;
+ }
+
+ /* Check that we won't overflow the poll set now. */
+ if ( RT_SUCCESS(rc)
+ && i + 1 > RTPOLL_SET_MAX)
+ rc = VERR_POLL_SET_IS_FULL;
+
+ /* Grow the tables if necessary. */
+ if (RT_SUCCESS(rc) && i + 1 > pThis->cHandlesAllocated)
+ rc = rtPollSetGrow(pThis, pThis->cHandlesAllocated + 32);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Add the handles to the two parallel arrays.
+ */
+#ifdef RT_OS_WINDOWS
+ pThis->pahNative[i] = (HANDLE)hNative;
+#elif defined(RT_OS_OS2)
+ pThis->pahNative[i] = hNative;
+#else
+ pThis->paPollFds[i].fd = (int)hNative;
+ pThis->paPollFds[i].revents = 0;
+ pThis->paPollFds[i].events = 0;
+ if (fEvents & RTPOLL_EVT_READ)
+ pThis->paPollFds[i].events |= POLLIN;
+ if (fEvents & RTPOLL_EVT_WRITE)
+ pThis->paPollFds[i].events |= POLLOUT;
+ if (fEvents & RTPOLL_EVT_ERROR)
+ pThis->paPollFds[i].events |= POLLERR;
+#endif
+ pThis->paHandles[i].enmType = pHandle->enmType;
+ pThis->paHandles[i].u = uh;
+ pThis->paHandles[i].id = id;
+ pThis->paHandles[i].fEvents = fEvents;
+ pThis->paHandles[i].fFinalEntry = true;
+
+ if (iPrev != UINT32_MAX)
+ {
+ Assert(pThis->paHandles[i].fFinalEntry);
+ pThis->paHandles[i].fFinalEntry = false;
+ }
+
+ /*
+ * Validations and OS specific updates.
+ */
+#ifdef RT_OS_WINDOWS
+ /* none */
+#elif defined(RT_OS_OS2)
+ rc = rtPollSetOs2Add(pThis, i, fEvents);
+#else /* POSIX */
+ if (poll(&pThis->paPollFds[i], 1, 0) < 0)
+ {
+ rc = RTErrConvertFromErrno(errno);
+ pThis->paPollFds[i].fd = -1;
+ }
+#endif /* POSIX */
+
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Commit it to the set.
+ */
+ pThis->cHandles++; Assert(pThis->cHandles == i + 1);
+ 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->paHandles[i].id == id)
+ {
+ /* Save some details for the duplicate searching. */
+ bool const fFinalEntry = pThis->paHandles[i].fFinalEntry;
+ RTHANDLETYPE const enmType = pThis->paHandles[i].enmType;
+ RTHANDLEUNION const uh = pThis->paHandles[i].u;
+#ifdef RT_OS_OS2
+ uint32_t fRemovedEvents = pThis->paHandles[i].fEvents;
+ RTHCINTPTR const hNative = pThis->pahNative[i];
+#endif
+
+ /* Remove the entry. */
+ pThis->cHandles--;
+ size_t const cToMove = pThis->cHandles - i;
+ if (cToMove)
+ {
+ memmove(&pThis->paHandles[i], &pThis->paHandles[i + 1], cToMove * sizeof(pThis->paHandles[i]));
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+ memmove(&pThis->pahNative[i], &pThis->pahNative[i + 1], cToMove * sizeof(pThis->pahNative[i]));
+#else
+ memmove(&pThis->paPollFds[i], &pThis->paPollFds[i + 1], cToMove * sizeof(pThis->paPollFds[i]));
+#endif
+ }
+
+ /* Check for duplicate and set the fFinalEntry flag. */
+ if (fFinalEntry)
+ while (i-- > 0)
+ if ( pThis->paHandles[i].u.uInt == uh.uInt
+ && pThis->paHandles[i].enmType == enmType)
+ {
+ Assert(!pThis->paHandles[i].fFinalEntry);
+ pThis->paHandles[i].fFinalEntry = true;
+ break;
+ }
+
+#ifdef RT_OS_OS2
+ /*
+ * Update OS/2 wait structures.
+ */
+ uint32_t fNewEvents = 0;
+ i = pThis->cHandles;
+ while (i-- > 0)
+ if ( pThis->paHandles[i].u.uInt == uh.uInt
+ && pThis->paHandles[i].enmType == enmType)
+ fNewEvents |= pThis->paHandles[i].fEvents;
+ if (enmType == RTHANDLETYPE_PIPE)
+ {
+ pThis->cPipes--;
+ if (fNewEvents == 0)
+ {
+ APIRET orc = DosDeleteMuxWaitSem(pThis->hmux, (HSEM)hNative);
+ AssertMsg(orc == NO_ERROR, ("%d\n", orc));
+ }
+ }
+ else if ( fNewEvents != (fNewEvents | fRemovedEvents)
+ && enmType == RTHANDLETYPE_SOCKET)
+ {
+ fRemovedEvents = fNewEvents ^ (fNewEvents | fRemovedEvents);
+ if (fRemovedEvents & RTPOLL_EVT_ERROR)
+ rtPollSetOs2RemoveSocket(pThis, pThis->cReadSockets + pThis->cWriteSockets, &pThis->cXcptSockets, (int)hNative);
+ if (fRemovedEvents & RTPOLL_EVT_WRITE)
+ rtPollSetOs2RemoveSocket(pThis, pThis->cReadSockets, &pThis->cWriteSockets, (int)hNative);
+ if (fRemovedEvents & RTPOLL_EVT_READ)
+ rtPollSetOs2RemoveSocket(pThis, 0, &pThis->cReadSockets, (int)hNative);
+ }
+#endif /* RT_OS_OS2 */
+ 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->paHandles[i].id == id)
+ {
+ if (pHandle)
+ {
+ pHandle->enmType = pThis->paHandles[i].enmType;
+ pHandle->u = pThis->paHandles[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->paHandles[i].id == id)
+ {
+ if (pThis->paHandles[i].fEvents != fEvents)
+ {
+#if defined(RT_OS_WINDOWS)
+ /*nothing*/
+#elif defined(RT_OS_OS2)
+ if (pThis->paHandles[i].enmType == RTHANDLETYPE_SOCKET)
+ {
+ uint32_t fOldEvents = 0;
+ uint32_t j = pThis->cHandles;
+ while (j-- > 0)
+ if ( pThis->paHandles[j].enmType == RTHANDLETYPE_SOCKET
+ && pThis->paHandles[j].u.uInt == pThis->paHandles[i].u.uInt
+ && j != i)
+ fOldEvents |= pThis->paHandles[j].fEvents;
+ uint32_t fNewEvents = fOldEvents | fEvents;
+ fOldEvents |= pThis->paHandles[i].fEvents;
+ if (fOldEvents != fEvents)
+ {
+ int const fdSocket = pThis->pahNative[i];
+ uint32_t const fChangedEvents = fOldEvents ^ fNewEvents;
+
+ if ((fChangedEvents & RTPOLL_EVT_READ) && (fNewEvents & RTPOLL_EVT_READ))
+ rtPollSetOs2AddSocket(pThis, pThis->cReadSockets, &pThis->cReadSockets, fdSocket);
+ else if (fChangedEvents & RTPOLL_EVT_READ)
+ rtPollSetOs2RemoveSocket(pThis, 0, &pThis->cReadSockets, fdSocket);
+
+ if ((fChangedEvents & RTPOLL_EVT_WRITE) && (fNewEvents & RTPOLL_EVT_WRITE))
+ rtPollSetOs2AddSocket(pThis, pThis->cReadSockets + pThis->cWriteSockets,
+ &pThis->cWriteSockets, fdSocket);
+ else if (fChangedEvents & RTPOLL_EVT_WRITE)
+ rtPollSetOs2RemoveSocket(pThis, pThis->cReadSockets, &pThis->cWriteSockets, fdSocket);
+
+ if ((fChangedEvents & RTPOLL_EVT_ERROR) && (fNewEvents & RTPOLL_EVT_ERROR))
+ rtPollSetOs2AddSocket(pThis, pThis->cReadSockets + pThis->cWriteSockets + pThis->cXcptSockets,
+ &pThis->cXcptSockets, fdSocket);
+ else if (fChangedEvents & RTPOLL_EVT_ERROR)
+ rtPollSetOs2RemoveSocket(pThis, pThis->cReadSockets + pThis->cWriteSockets, &pThis->cXcptSockets,
+ fdSocket);
+ }
+ }
+#else
+ pThis->paPollFds[i].events = 0;
+ if (fEvents & RTPOLL_EVT_READ)
+ pThis->paPollFds[i].events |= POLLIN;
+ if (fEvents & RTPOLL_EVT_WRITE)
+ pThis->paPollFds[i].events |= POLLOUT;
+ if (fEvents & RTPOLL_EVT_ERROR)
+ pThis->paPollFds[i].events |= POLLERR;
+#endif
+ pThis->paHandles[i].fEvents = fEvents;
+ }
+ rc = VINF_SUCCESS;
+ break;
+ }
+
+ ASMAtomicWriteBool(&pThis->fBusy, false);
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/posix/RTFileQueryFsSizes-posix.cpp b/src/VBox/Runtime/r3/posix/RTFileQueryFsSizes-posix.cpp
index 1536d2cb..1e74477f 100644
--- a/src/VBox/Runtime/r3/posix/RTFileQueryFsSizes-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/RTFileQueryFsSizes-posix.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2009 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/posix/RTHandleGetStandard-posix.cpp b/src/VBox/Runtime/r3/posix/RTHandleGetStandard-posix.cpp
index aa12323b..ef5b4bc9 100644
--- a/src/VBox/Runtime/r3/posix/RTHandleGetStandard-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/RTHandleGetStandard-posix.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010 Oracle Corporation
+ * Copyright (C) 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;
@@ -32,7 +32,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
-#include <sys/fcntl.h>
#include <fcntl.h>
#ifdef _MSC_VER
# include <io.h>
diff --git a/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp b/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp
index 4e2e116d..12fff20f 100644
--- a/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/RTMpGetCount-posix.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/posix/RTPathUserHome-posix.cpp b/src/VBox/Runtime/r3/posix/RTPathUserHome-posix.cpp
index d39fd6c6..144f54a7 100644
--- a/src/VBox/Runtime/r3/posix/RTPathUserHome-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/RTPathUserHome-posix.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/posix/RTSystemQueryOSInfo-posix.cpp b/src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.cpp
index b37d921e..6fe59a63 100644
--- a/src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/RTSystemQueryOSInfo-posix.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/posix/RTTimeNow-posix.cpp b/src/VBox/Runtime/r3/posix/RTTimeNow-posix.cpp
index 96915fea..5f75e60e 100644
--- a/src/VBox/Runtime/r3/posix/RTTimeNow-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/RTTimeNow-posix.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/posix/allocex-r3-posix.cpp b/src/VBox/Runtime/r3/posix/allocex-r3-posix.cpp
new file mode 100644
index 00000000..2aca436c
--- /dev/null
+++ b/src/VBox/Runtime/r3/posix/allocex-r3-posix.cpp
@@ -0,0 +1,109 @@
+/* $Id: allocex-r3-posix.cpp $ */
+/** @file
+ * IPRT - Memory Allocation, Extended Alloc Workers, posix.
+ */
+
+/*
+ * 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/err.h>
+#include <iprt/string.h>
+#include "../allocex.h"
+
+#include <sys/mman.h>
+
+
+DECLHIDDEN(int) rtMemAllocEx16BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv)
+{
+ AssertReturn(cbAlloc < _64K, VERR_NO_MEMORY);
+
+ /*
+ * Try with every possible address hint since the possible range is very limited.
+ */
+ int fProt = PROT_READ | PROT_WRITE | (fFlags & RTMEMALLOCEX_FLAGS_EXEC ? PROT_EXEC : 0);
+ uintptr_t uAddr = 0x1000;
+ uintptr_t uAddrLast = _64K - uAddr - cbAlloc;
+ while (uAddr <= uAddrLast)
+ {
+ void *pv = mmap((void *)uAddr, cbAlloc, fProt, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (pv && (uintptr_t)pv <= uAddrLast)
+ {
+ *ppv = pv;
+ return VINF_SUCCESS;
+ }
+
+ if (pv)
+ {
+ munmap(pv, cbAlloc);
+ pv = NULL;
+ }
+ uAddr += _4K;
+ }
+
+ return VERR_NO_MEMORY;
+}
+
+
+DECLHIDDEN(int) rtMemAllocEx32BitReach(size_t cbAlloc, uint32_t fFlags, void **ppv)
+{
+ int fProt = PROT_READ | PROT_WRITE | (fFlags & RTMEMALLOCEX_FLAGS_EXEC ? PROT_EXEC : 0);
+#if ARCH_BITS == 32
+ void *pv = mmap(NULL, cbAlloc, fProt, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (pv)
+ {
+ *ppv = pv;
+ return VINF_SUCCESS;
+ }
+ return VERR_NO_MEMORY;
+
+#elif defined(RT_OS_LINUX)
+# ifdef MAP_32BIT
+ void *pv = mmap(NULL, cbAlloc, fProt, MAP_PRIVATE | MAP_ANONYMOUS | MAP_32BIT, -1, 0);
+ if (pv)
+ {
+ *ppv = pv;
+ return VINF_SUCCESS;
+ }
+# endif
+
+ /** @todo On linux, we need an accurate hint. Since I don't need this branch of
+ * the code right now, I won't bother starting to parse
+ * /proc/curproc/mmap right now... */
+#else
+#endif
+ return VERR_NOT_SUPPORTED;
+}
+
+
+DECLHIDDEN(void) rtMemFreeExYyBitReach(void *pv, size_t cb, uint32_t fFlags)
+{
+ munmap(pv, cb);
+}
+
diff --git a/src/VBox/Runtime/r3/posix/dir-posix.cpp b/src/VBox/Runtime/r3/posix/dir-posix.cpp
index d12cee31..db402d9e 100644
--- a/src/VBox/Runtime/r3/posix/dir-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/dir-posix.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;
@@ -33,7 +33,6 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/fcntl.h>
#include <fcntl.h>
#include <dirent.h>
#include <stdio.h>
@@ -53,7 +52,7 @@
#include "internal/fs.h"
#include "internal/path.h"
-#if !defined(RT_OS_SOLARIS)
+#if !defined(RT_OS_SOLARIS) && !defined(RT_OS_HAIKU)
# define HAVE_DIRENT_D_TYPE 1
#endif
@@ -193,6 +192,26 @@ RTDECL(int) RTDirFlush(const char *pszPath)
}
+size_t rtDirNativeGetStructSize(const char *pszPath)
+{
+ long cbNameMax = pathconf(pszPath, _PC_NAME_MAX);
+# ifdef NAME_MAX
+ if (cbNameMax < NAME_MAX) /* This is plain paranoia, but it doesn't hurt. */
+ cbNameMax = NAME_MAX;
+# endif
+# ifdef _XOPEN_NAME_MAX
+ if (cbNameMax < _XOPEN_NAME_MAX) /* Ditto. */
+ cbNameMax = _XOPEN_NAME_MAX;
+# endif
+ size_t cbDir = RT_OFFSETOF(RTDIR, Data.d_name[cbNameMax + 1]);
+ if (cbDir < sizeof(RTDIR)) /* Ditto. */
+ cbDir = sizeof(RTDIR);
+ cbDir = RT_ALIGN_Z(cbDir, 8);
+
+ return cbDir;
+}
+
+
int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
{
NOREF(pszPathBuf); /* only used on windows */
@@ -208,11 +227,9 @@ int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
if (pDir->pDir)
{
/*
- * Init data.
+ * Init data (allocated as all zeros).
*/
- pDir->fDataUnread = false;
- memset(&pDir->Data, 0, RT_OFFSETOF(RTDIR, Data.d_name)); /* not strictly necessary */
- memset(&pDir->Data.d_name[0], 0, pDir->cbMaxName);
+ pDir->fDataUnread = false; /* spelling it out */
}
else
rc = RTErrConvertFromErrno(errno);
diff --git a/src/VBox/Runtime/r3/posix/env-posix.cpp b/src/VBox/Runtime/r3/posix/env-posix.cpp
index 3134d764..cd4fdb16 100644
--- a/src/VBox/Runtime/r3/posix/env-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/env-posix.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * 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;
@@ -46,13 +46,19 @@
#include "internal/alignmentchecks.h"
+RTDECL(bool) RTEnvExistsBad(const char *pszVar)
+{
+ return RTEnvGetBad(pszVar) != NULL;
+}
+
+
RTDECL(bool) RTEnvExist(const char *pszVar)
{
- return RTEnvGet(pszVar) != NULL;
+ return RTEnvExistsBad(pszVar);
}
-RTDECL(const char *) RTEnvGet(const char *pszVar)
+RTDECL(const char *) RTEnvGetBad(const char *pszVar)
{
IPRT_ALIGNMENT_CHECKS_DISABLE(); /* glibc causes trouble */
const char *pszValue = getenv(pszVar);
@@ -61,7 +67,13 @@ RTDECL(const char *) RTEnvGet(const char *pszVar)
}
-RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
+RTDECL(const char *) RTEnvGet(const char *pszVar)
+{
+ return RTEnvGetBad(pszVar);
+}
+
+
+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))
@@ -69,7 +81,14 @@ RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
return RTErrConvertFromErrno(errno);
}
-RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
+
+RTDECL(int) RTEnvPut(const char *pszVarEqualValue)
+{
+ return RTEnvPutBad(pszVarEqualValue);
+}
+
+
+RTDECL(int) RTEnvSetBad(const char *pszVar, const char *pszValue)
{
#if defined(_MSC_VER)
/* make a local copy and feed it to putenv. */
@@ -98,7 +117,12 @@ RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
}
-RTDECL(int) RTEnvUnset(const char *pszVar)
+RTDECL(int) RTEnvSet(const char *pszVar, const char *pszValue)
+{
+ return RTEnvSetBad(pszVar, pszValue);
+}
+
+RTDECL(int) RTEnvUnsetBad(const char *pszVar)
{
AssertReturn(!strchr(pszVar, '='), VERR_INVALID_PARAMETER);
@@ -131,3 +155,8 @@ RTDECL(int) RTEnvUnset(const char *pszVar)
return RTErrConvertFromErrno(errno);
}
+RTDECL(int) RTEnvUnset(const char *pszVar)
+{
+ return RTEnvUnsetBad(pszVar);
+}
+
diff --git a/src/VBox/Runtime/r3/posix/fileaio-posix.cpp b/src/VBox/Runtime/r3/posix/fileaio-posix.cpp
index fe7b8d05..f14e800e 100644
--- a/src/VBox/Runtime/r3/posix/fileaio-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/fileaio-posix.cpp
@@ -122,6 +122,8 @@ typedef struct RTFILEAIOCTXINTERNAL
volatile bool fWokenUp;
/** Flag whether the thread is currently waiting in the syscall. */
volatile bool fWaiting;
+ /** Flags given during creation. */
+ uint32_t fFlags;
/** Magic value (RTFILEAIOCTX_MAGIC). */
uint32_t u32Magic;
/** Flag whether the thread was woken up due to a internal event. */
@@ -522,12 +524,14 @@ RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
}
-RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
+RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax,
+ uint32_t fFlags)
{
PRTFILEAIOCTXINTERNAL pCtxInt;
unsigned cReqsWaitMax;
AssertPtrReturn(phAioCtx, VERR_INVALID_POINTER);
+ AssertReturn(!(fFlags & ~RTFILEAIOCTX_FLAGS_VALID_MASK), VERR_INVALID_PARAMETER);
if (cAioReqsMax == RTFILEAIO_UNLIMITED_REQS)
return VERR_OUT_OF_RANGE;
@@ -550,6 +554,7 @@ RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
pCtxInt->cMaxRequests = cAioReqsMax;
pCtxInt->cReqsWaitMax = cReqsWaitMax;
+ pCtxInt->fFlags = fFlags;
*phAioCtx = (RTFILEAIOCTX)pCtxInt;
return VINF_SUCCESS;
@@ -871,7 +876,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL
int32_t cRequestsWaiting = ASMAtomicReadS32(&pCtxInt->cRequests);
- if (RT_UNLIKELY(cRequestsWaiting <= 0))
+ if ( RT_UNLIKELY(cRequestsWaiting <= 0)
+ && !(pCtxInt->fFlags & RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS))
return VERR_FILE_AIO_NO_REQUEST;
if (RT_UNLIKELY(cMinReqs > (uint32_t)cRequestsWaiting))
diff --git a/src/VBox/Runtime/r3/posix/fileio-posix.cpp b/src/VBox/Runtime/r3/posix/fileio-posix.cpp
index b77ff050..1af29184 100644
--- a/src/VBox/Runtime/r3/posix/fileio-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/fileio-posix.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 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;
@@ -34,7 +34,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
-#include <sys/fcntl.h>
#include <fcntl.h>
#ifdef _MSC_VER
# include <io.h>
@@ -712,6 +711,19 @@ RTR3DECL(int) RTFileSetMode(RTFILE hFile, RTFMODE fMode)
}
+RTDECL(int) RTFileSetOwner(RTFILE hFile, uint32_t uid, uint32_t gid)
+{
+ uid_t uidNative = uid != NIL_RTUID ? (uid_t)uid : (uid_t)-1;
+ AssertReturn(uid == uidNative, VERR_INVALID_PARAMETER);
+ gid_t gidNative = gid != NIL_RTGID ? (gid_t)gid : (gid_t)-1;
+ AssertReturn(gid == gidNative, VERR_INVALID_PARAMETER);
+
+ if (fchown(RTFileToNative(hFile), uidNative, gidNative))
+ return RTErrConvertFromErrno(errno);
+ return VINF_SUCCESS;
+}
+
+
RTR3DECL(int) RTFileRename(const char *pszSrc, const char *pszDst, unsigned fRename)
{
/*
diff --git a/src/VBox/Runtime/r3/posix/fileio2-posix.cpp b/src/VBox/Runtime/r3/posix/fileio2-posix.cpp
index 47c13697..33e10e35 100644
--- a/src/VBox/Runtime/r3/posix/fileio2-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/fileio2-posix.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;
@@ -46,16 +46,15 @@
#if defined(RT_OS_OS2) && (!defined(__INNOTEK_LIBC__) || __INNOTEK_LIBC__ < 0x006)
# include <io.h>
#endif
-#ifdef RT_OS_L4
-/* This is currently ifdef'ed out in the relevant L4 header file */
-/* Same as `utimes', but takes an open file descriptor instead of a name. */
-extern int futimes(int __fd, __const struct timeval __tvp[2]) __THROW;
-#endif
#ifdef RT_OS_SOLARIS
# define futimes(filedes, timeval) futimesat(filedes, NULL, timeval)
#endif
+#ifdef RT_OS_HAIKU
+# define USE_FUTIMENS
+#endif
+
#include <iprt/file.h>
#include <iprt/path.h>
#include <iprt/assert.h>
@@ -143,6 +142,30 @@ RTR3DECL(int) RTFileSetTimes(RTFILE hFile, PCRTTIMESPEC pAccessTime, PCRTTIMESPE
if (!pAccessTime && !pModificationTime)
return VINF_SUCCESS;
+#ifdef USE_FUTIMENS
+ struct timespec aTimespecs[2];
+ if (pAccessTime && pModificationTime)
+ {
+ memcpy(&aTimespecs[0], pAccessTime, sizeof(struct timespec));
+ memcpy(&aTimespecs[1], pModificationTime, sizeof(struct timespec));
+ }
+ else
+ {
+ RTFSOBJINFO ObjInfo;
+ int rc = RTFileQueryInfo(hFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
+ if (RT_FAILURE(rc))
+ return rc;
+ memcpy(&aTimespecs[0], pAccessTime ? pAccessTime : &ObjInfo.AccessTime, sizeof(struct timespec));
+ memcpy(&aTimespecs[1], pModificationTime ? pModificationTime : &ObjInfo.ModificationTime, sizeof(struct timespec));
+ }
+
+ if (futimens(RTFileToNative(hFile), aTimespecs))
+ {
+ int rc = RTErrConvertFromErrno(errno);
+ Log(("RTFileSetTimes(%RTfile,%p,%p,,): returns %Rrc\n", hFile, pAccessTime, pModificationTime, rc));
+ return rc;
+ }
+#else
/*
* Convert the input to timeval, getting the missing one if necessary,
* and call the API which does the change.
@@ -171,6 +194,7 @@ RTR3DECL(int) RTFileSetTimes(RTFILE hFile, PCRTTIMESPEC pAccessTime, PCRTTIMESPE
Log(("RTFileSetTimes(%RTfile,%p,%p,,): returns %Rrc\n", hFile, pAccessTime, pModificationTime, rc));
return rc;
}
+#endif
return VINF_SUCCESS;
}
diff --git a/src/VBox/Runtime/r3/posix/filelock-posix.cpp b/src/VBox/Runtime/r3/posix/filelock-posix.cpp
index 266297f2..67734d63 100644
--- a/src/VBox/Runtime/r3/posix/filelock-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/filelock-posix.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;
@@ -33,7 +33,6 @@
#include <errno.h>
#include <sys/types.h>
#include <sys/ioctl.h>
-#include <sys/fcntl.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
diff --git a/src/VBox/Runtime/r3/posix/fs-posix.cpp b/src/VBox/Runtime/r3/posix/fs-posix.cpp
index fdb991b1..d5e982e0 100644
--- a/src/VBox/Runtime/r3/posix/fs-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/fs-posix.cpp
@@ -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;
@@ -216,6 +216,8 @@ RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
*penmType = RTFSTYPE_JFS;
else if (!strcmp("xfs", mntEnt.mnt_type))
*penmType = RTFSTYPE_XFS;
+ else if (!strcmp("btrfs", mntEnt.mnt_type))
+ *penmType = RTFSTYPE_BTRFS;
else if ( !strcmp("vfat", mntEnt.mnt_type)
|| !strcmp("msdos", mntEnt.mnt_type))
*penmType = RTFSTYPE_FAT;
diff --git a/src/VBox/Runtime/r3/posix/fs2-posix.cpp b/src/VBox/Runtime/r3/posix/fs2-posix.cpp
index 38dafcf1..5eae05a1 100644
--- a/src/VBox/Runtime/r3/posix/fs2-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/fs2-posix.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;
@@ -33,6 +33,9 @@
#include <sys/param.h>
#ifndef DEV_BSIZE
# include <sys/stat.h>
+# if defined(RT_OS_HAIKU) && !defined(S_BLKSIZE)
+# define S_BLKSIZE 512
+# endif
# define DEV_BSIZE S_BLKSIZE /** @todo bird: add DEV_BSIZE to sys/param.h on OS/2. */
#endif
diff --git a/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp b/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp
index 61ce3578..4028eb5d 100644
--- a/src/VBox/Runtime/r3/posix/ldrNative-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/ldrNative-posix.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;
@@ -108,7 +108,8 @@ DECLCALLBACK(int) rtldrNativeGetSymbol(PRTLDRMODINTERNAL pMod, const char *pszSy
DECLCALLBACK(int) rtldrNativeClose(PRTLDRMODINTERNAL pMod)
{
PRTLDRMODNATIVE pModNative = (PRTLDRMODNATIVE)pMod;
- if (!dlclose((void *)pModNative->hNative))
+ if ( (pModNative->fFlags & RTLDRLOAD_FLAGS_NO_UNLOAD)
+ || !dlclose((void *)pModNative->hNative))
{
pModNative->hNative = (uintptr_t)0;
return VINF_SUCCESS;
@@ -117,3 +118,10 @@ DECLCALLBACK(int) rtldrNativeClose(PRTLDRMODINTERNAL pMod)
return VERR_GENERAL_FAILURE;
}
+
+int rtldrNativeLoadSystem(const char *pszFilename, const char *pszExt, uint32_t fFlags, PRTLDRMOD phLdrMod)
+{
+ /** @todo implement this in some sensible fashion. */
+ return VERR_NOT_SUPPORTED;
+}
+
diff --git a/src/VBox/Runtime/r3/posix/path-posix.cpp b/src/VBox/Runtime/r3/posix/path-posix.cpp
index 7ad6b028..2b7adf9f 100644
--- a/src/VBox/Runtime/r3/posix/path-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/path-posix.cpp
@@ -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;
@@ -49,11 +49,6 @@
#include "internal/process.h"
#include "internal/fs.h"
-#ifdef RT_OS_L4
-# include <l4/vboxserver/vboxserver.h>
-#endif
-
-
RTDECL(int) RTPathReal(const char *pszPath, char *pszRealPath, size_t cchRealPath)
diff --git a/src/VBox/Runtime/r3/posix/path2-posix.cpp b/src/VBox/Runtime/r3/posix/path2-posix.cpp
index abc2ce29..856424d7 100644
--- a/src/VBox/Runtime/r3/posix/path2-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/path2-posix.cpp
@@ -48,10 +48,6 @@
#include "internal/process.h"
#include "internal/fs.h"
-#ifdef RT_OS_L4
-# include <l4/vboxserver/vboxserver.h>
-#endif
-
RTR3DECL(int) RTPathQueryInfo(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs)
{
diff --git a/src/VBox/Runtime/r3/posix/pathhost-posix.cpp b/src/VBox/Runtime/r3/posix/pathhost-posix.cpp
index 5390fe57..6f75c27b 100644
--- a/src/VBox/Runtime/r3/posix/pathhost-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/pathhost-posix.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;
@@ -134,7 +134,7 @@ static bool rtPathConvInitIsUtf8(const char *pszCodeset)
* @param pvUser1 Unused.
* @param pvUser2 Unused.
*/
-static DECLCALLBACK(int32_t) rtPathConvInitOnce(void *pvUser1, void *pvUser2)
+static DECLCALLBACK(int32_t) rtPathConvInitOnce(void *pvUser)
{
/*
* Read the environment variable, no mercy on misconfigs here except that
@@ -172,7 +172,7 @@ static DECLCALLBACK(int32_t) rtPathConvInitOnce(void *pvUser1, void *pvUser2)
g_enmUtf8ToFsIdx = RTSTRICONV_UTF8_TO_LOCALE;
}
- NOREF(pvUser1); NOREF(pvUser2);
+ NOREF(pvUser);
return VINF_SUCCESS;
}
@@ -181,7 +181,7 @@ int rtPathToNative(char const **ppszNativePath, const char *pszPath, const char
{
*ppszNativePath = NULL;
- int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL, NULL);
+ int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL);
if (RT_SUCCESS(rc))
{
if (g_fPassthruUtf8 || !*pszPath)
@@ -208,7 +208,7 @@ int rtPathFromNative(const char **ppszPath, const char *pszNativePath, const cha
{
*ppszPath = NULL;
- int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL, NULL);
+ int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL);
if (RT_SUCCESS(rc))
{
if (g_fPassthruUtf8 || !*pszNativePath)
@@ -246,7 +246,7 @@ void rtPathFreeIprt(const char *pszPath, const char *pszNativePath)
int rtPathFromNativeCopy(char *pszPath, size_t cbPath, const char *pszNativePath, const char *pszBasePath)
{
- int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL, NULL);
+ int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL);
if (RT_SUCCESS(rc))
{
if (g_fPassthruUtf8 || !*pszNativePath)
@@ -266,7 +266,7 @@ int rtPathFromNativeCopy(char *pszPath, size_t cbPath, const char *pszNativePath
int rtPathFromNativeDup(char **ppszPath, const char *pszNativePath, const char *pszBasePath)
{
- int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL, NULL);
+ int rc = RTOnce(&g_OnceInitPathConv, rtPathConvInitOnce, NULL);
if (RT_SUCCESS(rc))
{
if (g_fPassthruUtf8 || !*pszNativePath)
diff --git a/src/VBox/Runtime/r3/posix/pipe-posix.cpp b/src/VBox/Runtime/r3/posix/pipe-posix.cpp
index 2e006cb3..9d950de9 100644
--- a/src/VBox/Runtime/r3/posix/pipe-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/pipe-posix.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;
@@ -35,6 +35,7 @@
#include <iprt/assert.h>
#include <iprt/err.h>
#include <iprt/mem.h>
+#include <iprt/poll.h>
#include <iprt/string.h>
#include <iprt/thread.h>
#include "internal/magics.h"
@@ -54,6 +55,8 @@
# include <sys/filio.h>
#endif
+#include "internal/pipe.h"
+
/*******************************************************************************
* Structures and Typedefs *
@@ -667,3 +670,17 @@ RTDECL(int) RTPipeQueryReadable(RTPIPE hPipe, size_t *pcbReadable)
return rc;
}
+
+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_WRITE) || !pThis->fRead, VERR_INVALID_PARAMETER);
+
+ *phNative = pThis->fd;
+ return VINF_SUCCESS;
+}
+
diff --git a/src/VBox/Runtime/r3/posix/poll-posix.cpp b/src/VBox/Runtime/r3/posix/poll-posix.cpp
deleted file mode 100644
index ff124968..00000000
--- a/src/VBox/Runtime/r3/posix/poll-posix.cpp
+++ /dev/null
@@ -1,519 +0,0 @@
-/* $Id: poll-posix.cpp $ */
-/** @file
- * IPRT - Polling I/O Handles, POSIX Implementation.
- */
-
-/*
- * 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 <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/socket.h>
-#include <iprt/string.h>
-#include <iprt/thread.h>
-#include <iprt/time.h>
-#include "internal/magics.h"
-
-#include <limits.h>
-#include <errno.h>
-#include <sys/poll.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 handle union. */
- RTHANDLEUNION u;
-} RTPOLLSETHNDENT;
-/** Pointer to a handle entry. */
-typedef RTPOLLSETHNDENT *PRTPOLLSETHNDENT;
-
-/**
- * Poll set data, POSIX.
- */
-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 number of allocated handles. */
- uint32_t cHandlesAllocated;
-
- /** Pointer to an array of pollfd structures. */
- struct pollfd *paPollFds;
- /** Pointer to an array of handles and IDs. */
- PRTPOLLSETHNDENT paHandles;
-} RTPOLLSETINTERNAL;
-
-
-/**
- * Common worker for RTPoll and RTPollNoResume
- */
-static int rtPollNoResumeWorker(RTPOLLSETINTERNAL *pThis, RTMSINTERVAL cMillies, uint32_t *pfEvents, uint32_t *pid)
-{
- if (RT_UNLIKELY(pThis->cHandles == 0 && cMillies == RT_INDEFINITE_WAIT))
- return VERR_DEADLOCK;
-
- /* clear the revents. */
- uint32_t i = pThis->cHandles;
- while (i-- > 0)
- pThis->paPollFds[i].revents = 0;
-
- int rc = poll(&pThis->paPollFds[0], pThis->cHandles,
- cMillies == RT_INDEFINITE_WAIT || cMillies >= INT_MAX
- ? -1
- : (int)cMillies);
- if (rc == 0)
- return VERR_TIMEOUT;
- if (rc < 0)
- return RTErrConvertFromErrno(errno);
-
- for (i = 0; i < pThis->cHandles; i++)
- if (pThis->paPollFds[i].revents)
- {
- if (pfEvents)
- {
- *pfEvents = 0;
- if (pThis->paPollFds[i].revents & (POLLIN
-#ifdef POLLRDNORM
- | POLLRDNORM /* just in case */
-#endif
-#ifdef POLLRDBAND
- | POLLRDBAND /* ditto */
-#endif
-#ifdef POLLPRI
- | POLLPRI /* ditto */
-#endif
-#ifdef POLLMSG
- | POLLMSG /* ditto */
-#endif
-#ifdef POLLWRITE
- | POLLWRITE /* ditto */
-#endif
-#ifdef POLLEXTEND
- | POLLEXTEND /* ditto */
-#endif
- )
- )
- *pfEvents |= RTPOLL_EVT_READ;
-
- if (pThis->paPollFds[i].revents & (POLLOUT
-#ifdef POLLWRNORM
- | POLLWRNORM /* just in case */
-#endif
-#ifdef POLLWRBAND
- | POLLWRBAND /* ditto */
-#endif
- )
- )
- *pfEvents |= RTPOLL_EVT_WRITE;
-
- if (pThis->paPollFds[i].revents & (POLLERR | POLLHUP | POLLNVAL
-#ifdef POLLRDHUP
- | POLLRDHUP
-#endif
- )
- )
- *pfEvents |= RTPOLL_EVT_ERROR;
- }
- if (pid)
- *pid = pThis->paHandles[i].id;
- return VINF_SUCCESS;
- }
-
- AssertFailed();
- RTThreadYield();
- return VERR_INTERRUPTED;
-}
-
-
-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 *)RTMemAlloc(sizeof(RTPOLLSETINTERNAL));
- if (!pThis)
- return VERR_NO_MEMORY;
-
- pThis->u32Magic = RTPOLLSET_MAGIC;
- pThis->fBusy = false;
- pThis->cHandles = 0;
- pThis->cHandlesAllocated = 0;
- pThis->paPollFds = NULL;
- pThis->paHandles = NULL;
-
- *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->paPollFds);
- pThis->paPollFds = NULL;
- RTMemFree(pThis->paHandles);
- pThis->paHandles = NULL;
- 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;
- int fd = -1;
- switch (pHandle->enmType)
- {
- case RTHANDLETYPE_PIPE:
- if (pHandle->u.hPipe != NIL_RTPIPE)
- fd = (int)RTPipeToNative(pHandle->u.hPipe);
- break;
-
- case RTHANDLETYPE_SOCKET:
- if (pHandle->u.hSocket != NIL_RTSOCKET)
- fd = (int)RTSocketToNative(pHandle->u.hSocket);
- 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 (fd != -1)
- {
- uint32_t const i = pThis->cHandles;
-
- /* Check that the handle ID doesn't exist already. */
- uint32_t j = i;
- while (j-- > 0)
- if (pThis->paHandles[j].id == id)
- {
- rc = VERR_POLL_HANDLE_ID_EXISTS;
- break;
- }
- if (RT_SUCCESS(rc))
- {
- /* Grow the tables if necessary. */
- if (i + 1 > pThis->cHandlesAllocated)
- {
- uint32_t const c = pThis->cHandlesAllocated + 32;
- void *pvNew;
- pvNew = RTMemRealloc(pThis->paHandles, c * sizeof(pThis->paHandles[0]));
- if (pvNew)
- {
- pThis->paHandles = (PRTPOLLSETHNDENT)pvNew;
- pvNew = RTMemRealloc(pThis->paPollFds, c * sizeof(pThis->paPollFds[0]));
- if (pvNew)
- pThis->paPollFds = (struct pollfd *)pvNew;
- else
- rc = VERR_NO_MEMORY;
- }
- else
- rc = VERR_NO_MEMORY;
- }
- if (RT_SUCCESS(rc))
- {
- /* Add it to the poll file descriptor array and call poll to
- validate the event flags. */
- pThis->paPollFds[i].fd = fd;
- pThis->paPollFds[i].revents = 0;
- pThis->paPollFds[i].events = 0;
- if (fEvents & RTPOLL_EVT_READ)
- pThis->paPollFds[i].events |= POLLIN;
- if (fEvents & RTPOLL_EVT_WRITE)
- pThis->paPollFds[i].events |= POLLOUT;
- if (fEvents & RTPOLL_EVT_ERROR)
- pThis->paPollFds[i].events |= POLLERR;
-
- if (poll(&pThis->paPollFds[i], 1, 0) >= 0)
- {
- /* Add the handle info and close the transaction. */
- pThis->paHandles[i].enmType = pHandle->enmType;
- pThis->paHandles[i].u = pHandle->u;
- pThis->paHandles[i].id = id;
-
- pThis->cHandles = i + 1;
- rc = VINF_SUCCESS;
- }
- else
- {
- rc = RTErrConvertFromErrno(errno);
- pThis->paPollFds[i].fd = -1;
- }
- }
- }
- }
-
- 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->paHandles[i].id == id)
- {
- pThis->cHandles--;
- size_t const cToMove = pThis->cHandles - i;
- if (cToMove)
- {
- memmove(&pThis->paHandles[i], &pThis->paHandles[i + 1], cToMove * sizeof(pThis->paHandles[i]));
- memmove(&pThis->paPollFds[i], &pThis->paPollFds[i + 1], cToMove * sizeof(pThis->paPollFds[i]));
- }
- 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->paHandles[i].id == id)
- {
- if (pHandle)
- {
- pHandle->enmType = pThis->paHandles[i].enmType;
- pHandle->u = pThis->paHandles[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->paHandles[i].id == id)
- {
- pThis->paPollFds[i].events = 0;
- if (fEvents & RTPOLL_EVT_READ)
- pThis->paPollFds[i].events |= POLLIN;
- if (fEvents & RTPOLL_EVT_WRITE)
- pThis->paPollFds[i].events |= POLLOUT;
- if (fEvents & RTPOLL_EVT_ERROR)
- pThis->paPollFds[i].events |= POLLERR;
- rc = VINF_SUCCESS;
- break;
- }
-
- ASMAtomicWriteBool(&pThis->fBusy, false);
- return rc;
-}
-
diff --git a/src/VBox/Runtime/r3/posix/process-creation-posix.cpp b/src/VBox/Runtime/r3/posix/process-creation-posix.cpp
index 2f8841c4..4fd2d0e2 100644
--- a/src/VBox/Runtime/r3/posix/process-creation-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/process-creation-posix.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2010 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;
@@ -29,6 +29,8 @@
* Header Files *
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_PROCESS
+#include <iprt/cdefs.h>
+
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
@@ -37,20 +39,28 @@
#include <sys/wait.h>
#include <fcntl.h>
#include <signal.h>
+#include <grp.h>
#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
# include <crypt.h>
# include <pwd.h>
# include <shadow.h>
#endif
+
#if defined(RT_OS_LINUX) || defined(RT_OS_OS2)
/* While Solaris has posix_spawn() of course we don't want to use it as
* we need to have the child in a different process contract, no matter
* whether it is started detached or not. */
# define HAVE_POSIX_SPAWN 1
#endif
+#if defined(RT_OS_DARWIN) && defined(MAC_OS_X_VERSION_MIN_REQUIRED)
+# if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
+# define HAVE_POSIX_SPAWN 1
+# endif
+#endif
#ifdef HAVE_POSIX_SPAWN
# include <spawn.h>
#endif
+
#ifdef RT_OS_DARWIN
# include <mach-o/dyld.h>
#endif
@@ -297,6 +307,10 @@ 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);
+#if defined(RT_OS_OS2)
+ if (fFlags & RTPROC_FLAGS_DETACHED)
+ return VERR_PROC_DETACH_NOT_SUPPORTED;
+#endif
/*
* Get the file descriptors for the handles we've been passed.
@@ -462,20 +476,30 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg
rc = posix_spawnattr_init(&Attr);
if (!rc)
{
-# ifndef RT_OS_OS2 /* We don't need this on OS/2 and I don't recall if it's actually implemented. */
- rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP);
+ /* Indicate that process group and signal mask are to be changed,
+ and that the child should use default signal actions. */
+ rc = posix_spawnattr_setflags(&Attr, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF);
Assert(rc == 0);
+
+ /* The child starts in its own process group. */
if (!rc)
{
rc = posix_spawnattr_setpgroup(&Attr, 0 /* pg == child pid */);
Assert(rc == 0);
}
-# endif
+
+ /* Unmask all signals. */
+ if (!rc)
+ {
+ sigset_t SigMask;
+ sigemptyset(&SigMask);
+ rc = posix_spawnattr_setsigmask(&Attr, &SigMask); Assert(rc == 0);
+ }
/* File changes. */
posix_spawn_file_actions_t FileActions;
posix_spawn_file_actions_t *pFileActions = NULL;
- if (aStdFds[0] != -1 || aStdFds[1] != -1 || aStdFds[2] != -1)
+ if ((aStdFds[0] != -1 || aStdFds[1] != -1 || aStdFds[2] != -1) && !rc)
{
rc = posix_spawn_file_actions_init(&FileActions);
if (!rc)
@@ -525,7 +549,7 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg
/* For a detached process this happens in the temp process, so
* it's not worth doing anything as this process must exit. */
if (fFlags & RTPROC_FLAGS_DETACHED)
- _Exit(0);
+ _Exit(0);
if (phProcess)
*phProcess = pid;
return VINF_SUCCESS;
@@ -540,15 +564,20 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg
#endif
{
#ifdef RT_OS_SOLARIS
- int templateFd = rtSolarisContractPreFork();
- if (templateFd == -1)
- return VERR_OPEN_FAILED;
+ int templateFd = -1;
+ if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
+ {
+ templateFd = rtSolarisContractPreFork();
+ if (templateFd == -1)
+ return VERR_OPEN_FAILED;
+ }
#endif /* RT_OS_SOLARIS */
pid = fork();
if (!pid)
{
#ifdef RT_OS_SOLARIS
- rtSolarisContractPostForkChild(templateFd);
+ if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
+ rtSolarisContractPostForkChild(templateFd);
#endif /* RT_OS_SOLARIS */
if (!(fFlags & RTPROC_FLAGS_DETACHED))
setpgid(0, 0); /* see comment above */
@@ -557,6 +586,17 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg
* Change group and user if requested.
*/
#if 1 /** @todo This needs more work, see suplib/hardening. */
+ if (pszAsUser)
+ {
+ int ret = initgroups(pszAsUser, gid);
+ if (ret)
+ {
+ if (fFlags & RTPROC_FLAGS_DETACHED)
+ _Exit(126);
+ else
+ exit(126);
+ }
+ }
if (gid != ~(gid_t)0)
{
if (setgid(gid))
@@ -581,6 +621,14 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg
#endif
/*
+ * Unset the signal mask.
+ */
+ sigset_t SigMask;
+ sigemptyset(&SigMask);
+ rc = sigprocmask(SIG_SETMASK, &SigMask, NULL);
+ Assert(rc == 0);
+
+ /*
* Apply changes to the standard file descriptor and stuff.
*/
for (int i = 0; i < 3; i++)
@@ -627,7 +675,8 @@ RTR3DECL(int) RTProcCreateEx(const char *pszExec, const char * const *papszArg
exit(127);
}
#ifdef RT_OS_SOLARIS
- rtSolarisContractPostForkParent(templateFd, pid);
+ if (!(fFlags & RTPROC_FLAGS_SAME_CONTRACT))
+ rtSolarisContractPostForkParent(templateFd, pid);
#endif /* RT_OS_SOLARIS */
if (pid > 0)
{
diff --git a/src/VBox/Runtime/r3/posix/process-posix.cpp b/src/VBox/Runtime/r3/posix/process-posix.cpp
index 7b823163..01631f6d 100644
--- a/src/VBox/Runtime/r3/posix/process-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/process-posix.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;
@@ -188,4 +188,3 @@ RTR3DECL(int) RTProcQueryUsername(RTPROCESS hProcess, char *pszUser, size_t cbUs
return rc;
}
-
diff --git a/src/VBox/Runtime/r3/posix/rand-posix.cpp b/src/VBox/Runtime/r3/posix/rand-posix.cpp
index f394d149..1d1725f1 100644
--- a/src/VBox/Runtime/r3/posix/rand-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/rand-posix.cpp
@@ -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;
@@ -32,7 +32,6 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
-#include <sys/fcntl.h>
#include <fcntl.h>
#ifdef _MSC_VER
# include <io.h>
@@ -57,7 +56,10 @@ static DECLCALLBACK(void) rtRandAdvPosixGetBytes(PRTRANDINT pThis, uint8_t *pb,
ssize_t cbRead = read(pThis->u.File.hFile, pb, cb);
if ((size_t)cbRead != cb)
{
- ssize_t cTries = RT_MIN(cb, 256);
+ /* S10 has been observed returning 1040 bytes at the time from /dev/urandom.
+ Which means we need to do than 256 rounds to reach 668171 bytes if
+ that's what demanded by the caller (like tstRTMemWipe.cpp). */
+ ssize_t cTries = RT_MAX(256, cb / 64);
do
{
if (cbRead > 0)
diff --git a/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp b/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp
index 73f925c2..c72cd22f 100644
--- a/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/rtmempage-exec-mmap-heap-posix.cpp
@@ -146,20 +146,20 @@ static RTHEAPPAGE g_MemExecPosixHeap;
#ifdef RT_OS_OS2
/*
- * A quick mmap/munmap mockup for avoid duplicating lots of good code.
+ * A quick mmap/munmap mockup for avoid duplicating lots of good code.
*/
# define INCL_BASE
# include <os2.h>
-# undef MAP_PRIVATE
+# undef MAP_PRIVATE
# define MAP_PRIVATE 0
-# undef MAP_ANONYMOUS
+# undef MAP_ANONYMOUS
# define MAP_ANONYMOUS 0
# undef MAP_FAILED
# define MAP_FAILED (void *)-1
# undef mmap
-# define mmap iprt_mmap
+# define mmap iprt_mmap
# undef munmap
-# define munmap iprt_munmap
+# define munmap iprt_munmap
static void *mmap(void *pvWhere, size_t cb, int fProt, int fFlags, int fd, off_t off)
{
@@ -605,12 +605,11 @@ int RTHeapPageFree(PRTHEAPPAGE pHeap, void *pv, size_t cPages)
* Initializes the heap.
*
* @returns IPRT status code
- * @param pvUser1 Unused.
- * @param pvUser2 Unused.
+ * @param pvUser Unused.
*/
-static DECLCALLBACK(int) rtMemPagePosixInitOnce(void *pvUser1, void *pvUser2)
+static DECLCALLBACK(int) rtMemPagePosixInitOnce(void *pvUser)
{
- NOREF(pvUser1); NOREF(pvUser2);
+ NOREF(pvUser);
int rc = RTHeapPageInit(&g_MemPagePosixHeap, false /*fExec*/);
if (RT_SUCCESS(rc))
{
@@ -663,7 +662,7 @@ static void *rtMemPagePosixAlloc(size_t cb, const char *pszTag, bool fZero, PRTH
}
else
{
- int rc = RTOnce(&g_MemPagePosixInitOnce, rtMemPagePosixInitOnce, NULL, NULL);
+ int rc = RTOnce(&g_MemPagePosixInitOnce, rtMemPagePosixInitOnce, NULL);
if (RT_SUCCESS(rc))
rc = RTHeapPageAlloc(pHeap, cb >> PAGE_SHIFT, pszTag, fZero, &pv);
if (RT_FAILURE(rc))
diff --git a/src/VBox/Runtime/r3/posix/sched-posix.cpp b/src/VBox/Runtime/r3/posix/sched-posix.cpp
index 6fbf2f9f..4fa2bb9a 100644
--- a/src/VBox/Runtime/r3/posix/sched-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/sched-posix.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/posix/semevent-posix.cpp b/src/VBox/Runtime/r3/posix/semevent-posix.cpp
index f2c40f3f..67d69cbb 100644
--- a/src/VBox/Runtime/r3/posix/semevent-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/semevent-posix.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;
@@ -48,7 +48,7 @@
# define pthread_yield() pthread_yield_np()
#endif
-#ifdef RT_OS_SOLARIS
+#if defined(RT_OS_SOLARIS) || defined(RT_OS_HAIKU)
# include <sched.h>
# define pthread_yield() sched_yield()
#endif
@@ -397,7 +397,7 @@ DECL_FORCE_INLINE(int) rtSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillie
* Get current time and calc end of wait time.
*/
struct timespec ts = {0,0};
-#ifdef RT_OS_DARWIN
+#if defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU)
struct timeval tv = {0,0};
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec;
diff --git a/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp b/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
index 8a1d066b..2875a9a0 100644
--- a/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
@@ -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;
@@ -481,7 +481,7 @@ static int rtSemEventMultiPosixWaitTimed(struct RTSEMEVENTMULTIINTERNAL *pThis,
struct timespec ts = {0,0};
if (!pThis->fMonotonicClock)
{
-#ifdef RT_OS_DARWIN
+#if defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU)
struct timeval tv = {0,0};
gettimeofday(&tv, NULL);
ts.tv_sec = tv.tv_sec;
diff --git a/src/VBox/Runtime/r3/posix/semmutex-posix.cpp b/src/VBox/Runtime/r3/posix/semmutex-posix.cpp
index e1e82558..89fa962c 100644
--- a/src/VBox/Runtime/r3/posix/semmutex-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/semmutex-posix.cpp
@@ -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;
@@ -65,6 +65,43 @@ struct RTSEMMUTEXINTERNAL
#endif
};
+#ifdef RT_OS_DARWIN
+/**
+ * This function emulate pthread_mutex_timedlock on Mac OS X
+ */
+static int DarwinPthreadMutexTimedlock(pthread_mutex_t * mutex, const struct timespec * pTsAbsTimeout)
+{
+ int rc = 0;
+ struct timeval tv;
+ timespec ts = {0, 0};
+ do
+ {
+ rc = pthread_mutex_trylock(mutex);
+ if (rc == EBUSY)
+ {
+ gettimeofday(&tv, NULL);
+
+ ts.tv_sec = pTsAbsTimeout->tv_sec - tv.tv_sec;
+ ts.tv_nsec = pTsAbsTimeout->tv_nsec - tv.tv_sec;
+
+ if (ts.tv_nsec < 0)
+ {
+ ts.tv_sec--;
+ ts.tv_nsec += 1000000000;
+ }
+
+ if ( ts.tv_sec > 0
+ && ts.tv_nsec > 0)
+ nanosleep(&ts, &ts);
+ }
+ else
+ break;
+ } while ( rc != 0
+ || ts.tv_sec > 0);
+ return rc;
+}
+#endif
+
#undef RTSemMutexCreate
RTDECL(int) RTSemMutexCreate(PRTSEMMUTEX phMutexSem)
@@ -241,15 +278,16 @@ DECL_FORCE_INLINE(int) rtSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMil
}
else
{
-#ifdef RT_OS_DARWIN
- AssertMsgFailed(("Not implemented on Darwin yet because of incomplete pthreads API."));
- return VERR_NOT_IMPLEMENTED;
-#else /* !RT_OS_DARWIN */
- /*
- * Get current time and calc end of wait time.
- */
struct timespec ts = {0,0};
+#if defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU)
+
+ struct timeval tv = {0,0};
+ gettimeofday(&tv, NULL);
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+#else
clock_gettime(CLOCK_REALTIME, &ts);
+#endif
if (cMillies != 0)
{
ts.tv_nsec += (cMillies % 1000) * 1000000;
@@ -262,14 +300,17 @@ DECL_FORCE_INLINE(int) rtSemMutexRequest(RTSEMMUTEX hMutexSem, RTMSINTERVAL cMil
}
/* take mutex */
+#ifndef RT_OS_DARWIN
int rc = pthread_mutex_timedlock(&pThis->Mutex, &ts);
+#else
+ int rc = DarwinPthreadMutexTimedlock(&pThis->Mutex, &ts);
+#endif
RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_MUTEX);
if (rc)
{
AssertMsg(rc == ETIMEDOUT, ("Failed to lock mutex sem %p, rc=%d.\n", hMutexSem, rc)); NOREF(rc);
return RTErrConvertFromErrno(rc);
}
-#endif /* !RT_OS_DARWIN */
}
/*
diff --git a/src/VBox/Runtime/r3/posix/semrw-posix.cpp b/src/VBox/Runtime/r3/posix/semrw-posix.cpp
index 81f71ef1..c6dfeb2f 100644
--- a/src/VBox/Runtime/r3/posix/semrw-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/semrw-posix.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/posix/symlink-posix.cpp b/src/VBox/Runtime/r3/posix/symlink-posix.cpp
index f2c05da2..b3e10877 100644
--- a/src/VBox/Runtime/r3/posix/symlink-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/symlink-posix.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/posix/thread-posix.cpp b/src/VBox/Runtime/r3/posix/thread-posix.cpp
index b212181a..66ccafb0 100644
--- a/src/VBox/Runtime/r3/posix/thread-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/thread-posix.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2011 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;
@@ -47,17 +47,22 @@
# include <mach/mach_init.h>
# include <mach/mach_host.h>
#endif
-#if defined(RT_OS_DARWIN) /*|| defined(RT_OS_FREEBSD) - later */ || defined(RT_OS_LINUX) \
+#if defined(RT_OS_DARWIN) /*|| defined(RT_OS_FREEBSD) - later */ \
+ || (defined(RT_OS_LINUX) && !defined(IN_RT_STATIC) /* static + dlsym = trouble */) \
|| defined(IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP)
# define IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP
# include <dlfcn.h>
#endif
+#if defined(RT_OS_HAIKU)
+# include <OS.h>
+#endif
#include <iprt/thread.h>
#include <iprt/log.h>
#include <iprt/assert.h>
#include <iprt/asm.h>
#include <iprt/err.h>
+#include <iprt/initterm.h>
#include <iprt/string.h>
#include "internal/thread.h"
@@ -115,20 +120,14 @@ static void rtThreadKeyDestruct(void *pvValue);
static void rtThreadPosixPokeSignal(int iSignal);
-DECLHIDDEN(int) rtThreadNativeInit(void)
-{
- /*
- * Allocate the TLS (key in posix terms) where we store the pointer to
- * a threads RTTHREADINT structure.
- */
- int rc = pthread_key_create(&g_SelfKey, rtThreadKeyDestruct);
- if (rc)
- return VERR_NO_TLS_FOR_SELF;
-
#ifdef RTTHREAD_POSIX_WITH_POKE
+/**
+ * Try register the dummy signal handler for RTThreadPoke.
+ */
+static void rtThreadPosixSelectPokeSignal(void)
+{
/*
- * Try register the dummy signal handler for RTThreadPoke.
- * Avoid SIGRTMIN thru SIGRTMIN+2 because of LinuxThreads.
+ * Note! Avoid SIGRTMIN thru SIGRTMIN+2 because of LinuxThreads.
*/
static const int s_aiSigCandidates[] =
{
@@ -144,34 +143,53 @@ DECLHIDDEN(int) rtThreadNativeInit(void)
};
g_iSigPokeThread = -1;
- for (unsigned iSig = 0; iSig < RT_ELEMENTS(s_aiSigCandidates); iSig++)
+ if (!RTR3InitIsUnobtrusive())
{
- struct sigaction SigActOld;
- if (!sigaction(s_aiSigCandidates[iSig], NULL, &SigActOld))
+ for (unsigned iSig = 0; iSig < RT_ELEMENTS(s_aiSigCandidates); iSig++)
{
- if ( SigActOld.sa_handler == SIG_DFL
- || SigActOld.sa_handler == rtThreadPosixPokeSignal)
+ struct sigaction SigActOld;
+ if (!sigaction(s_aiSigCandidates[iSig], NULL, &SigActOld))
{
- struct sigaction SigAct;
- RT_ZERO(SigAct);
- SigAct.sa_handler = rtThreadPosixPokeSignal;
- SigAct.sa_flags = 0;
- sigfillset(&SigAct.sa_mask);
-
- /* ASSUMES no sigaction race... (lazy bird) */
- if (!sigaction(s_aiSigCandidates[iSig], &SigAct, NULL))
+ if ( SigActOld.sa_handler == SIG_DFL
+ || SigActOld.sa_handler == rtThreadPosixPokeSignal)
{
- g_iSigPokeThread = s_aiSigCandidates[iSig];
- break;
+ struct sigaction SigAct;
+ RT_ZERO(SigAct);
+ SigAct.sa_handler = rtThreadPosixPokeSignal;
+ SigAct.sa_flags = 0;
+ sigfillset(&SigAct.sa_mask);
+
+ /* ASSUMES no sigaction race... (lazy bird) */
+ if (!sigaction(s_aiSigCandidates[iSig], &SigAct, NULL))
+ {
+ g_iSigPokeThread = s_aiSigCandidates[iSig];
+ break;
+ }
+ AssertMsgFailed(("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno));
}
- AssertMsgFailed(("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno));
}
+ else
+ AssertMsgFailed(("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno));
}
- else
- AssertMsgFailed(("rc=%Rrc errno=%d\n", RTErrConvertFromErrno(errno), errno));
}
+}
#endif /* RTTHREAD_POSIX_WITH_POKE */
+
+DECLHIDDEN(int) rtThreadNativeInit(void)
+{
+ /*
+ * Allocate the TLS (key in posix terms) where we store the pointer to
+ * a threads RTTHREADINT structure.
+ */
+ int rc = pthread_key_create(&g_SelfKey, rtThreadKeyDestruct);
+ if (rc)
+ return VERR_NO_TLS_FOR_SELF;
+
+#ifdef RTTHREAD_POSIX_WITH_POKE
+ rtThreadPosixSelectPokeSignal();
+#endif
+
#ifdef IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP
if (RT_SUCCESS(rc))
g_pfnThreadSetName = (PFNPTHREADSETNAME)(uintptr_t)dlsym(RTLD_DEFAULT, "pthread_setname_np");
@@ -179,6 +197,35 @@ DECLHIDDEN(int) rtThreadNativeInit(void)
return rc;
}
+static void rtThreadPosixBlockSignals(void)
+{
+ /*
+ * Block SIGALRM - required for timer-posix.cpp.
+ * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
+ * It will not help much if someone creates threads directly using pthread_create. :/
+ */
+ if (!RTR3InitIsUnobtrusive())
+ {
+ sigset_t SigSet;
+ sigemptyset(&SigSet);
+ sigaddset(&SigSet, SIGALRM);
+ sigprocmask(SIG_BLOCK, &SigSet, NULL);
+ }
+#ifdef RTTHREAD_POSIX_WITH_POKE
+ if (g_iSigPokeThread != -1)
+ siginterrupt(g_iSigPokeThread, 1);
+#endif
+}
+
+DECLHIDDEN(void) rtThreadNativeReInitObtrusive(void)
+{
+#ifdef RTTHREAD_POSIX_WITH_POKE
+ Assert(!RTR3InitIsUnobtrusive());
+ rtThreadPosixSelectPokeSignal();
+#endif
+ rtThreadPosixBlockSignals();
+}
+
/**
* Destructor called when a thread terminates.
@@ -221,19 +268,7 @@ static void rtThreadPosixPokeSignal(int iSignal)
*/
DECLHIDDEN(int) rtThreadNativeAdopt(PRTTHREADINT pThread)
{
- /*
- * Block SIGALRM - required for timer-posix.cpp.
- * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
- * It will not help much if someone creates threads directly using pthread_create. :/
- */
- sigset_t SigSet;
- sigemptyset(&SigSet);
- sigaddset(&SigSet, SIGALRM);
- sigprocmask(SIG_BLOCK, &SigSet, NULL);
-#ifdef RTTHREAD_POSIX_WITH_POKE
- if (g_iSigPokeThread != -1)
- siginterrupt(g_iSigPokeThread, 1);
-#endif
+ rtThreadPosixBlockSignals();
int rc = pthread_setspecific(g_SelfKey, pThread);
if (!rc)
@@ -266,19 +301,7 @@ static void *rtThreadNativeMain(void *pvArgs)
ASMMemoryFence();
#endif
- /*
- * Block SIGALRM - required for timer-posix.cpp.
- * This is done to limit harm done by OSes which doesn't do special SIGALRM scheduling.
- * It will not help much if someone creates threads directly using pthread_create. :/
- */
- sigset_t SigSet;
- sigemptyset(&SigSet);
- sigaddset(&SigSet, SIGALRM);
- sigprocmask(SIG_BLOCK, &SigSet, NULL);
-#ifdef RTTHREAD_POSIX_WITH_POKE
- if (g_iSigPokeThread != -1)
- siginterrupt(g_iSigPokeThread, 1);
-#endif
+ rtThreadPosixBlockSignals();
/*
* Set the TLS entry and, if possible, the thread name.
@@ -412,6 +435,15 @@ RTR3DECL(int) RTThreadGetExecutionTimeMilli(uint64_t *pKernelTime, uint64_t *pUs
*pUserTime = ThreadInfo.user_time.seconds * 1000 + ThreadInfo.user_time.microseconds / 1000;
return VINF_SUCCESS;
+#elif defined(RT_OS_HAIKU)
+ thread_info ThreadInfo;
+ status_t status = get_thread_info(find_thread(NULL), &ThreadInfo);
+ AssertReturn(status == B_OK, RTErrConvertFromErrno(status));
+
+ *pKernelTime = ThreadInfo.kernel_time / 1000;
+ *pUserTime = ThreadInfo.user_time / 1000;
+
+ return VINF_SUCCESS;
#else
return VERR_NOT_IMPLEMENTED;
#endif
diff --git a/src/VBox/Runtime/r3/posix/thread2-posix.cpp b/src/VBox/Runtime/r3/posix/thread2-posix.cpp
index b0402ed0..bd7e030e 100644
--- a/src/VBox/Runtime/r3/posix/thread2-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/thread2-posix.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;
@@ -62,7 +62,7 @@ RTDECL(int) RTThreadSleep(RTMSINTERVAL cMillies)
pthread_yield_np();
#elif defined(RT_OS_FREEBSD) /* void pthread_yield */
pthread_yield();
-#elif defined(RT_OS_SOLARIS)
+#elif defined(RT_OS_SOLARIS) || defined(RT_OS_HAIKU)
sched_yield();
#else
if (!pthread_yield())
@@ -101,7 +101,7 @@ RTDECL(int) RTThreadSleepNoLog(RTMSINTERVAL cMillies)
pthread_yield_np();
#elif defined(RT_OS_FREEBSD) /* void pthread_yield */
pthread_yield();
-#elif defined(RT_OS_SOLARIS)
+#elif defined(RT_OS_SOLARIS) || defined(RT_OS_HAIKU)
sched_yield();
#else
if (!pthread_yield())
@@ -130,7 +130,7 @@ RTDECL(bool) RTThreadYield(void)
#endif
#ifdef RT_OS_DARWIN
pthread_yield_np();
-#elif defined(RT_OS_SOLARIS)
+#elif defined(RT_OS_SOLARIS) || defined(RT_OS_HAIKU)
sched_yield();
#else
pthread_yield();
diff --git a/src/VBox/Runtime/r3/posix/time-posix.cpp b/src/VBox/Runtime/r3/posix/time-posix.cpp
index bdb3dcb7..6f313afd 100644
--- a/src/VBox/Runtime/r3/posix/time-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/time-posix.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/posix/timelocal-posix.cpp b/src/VBox/Runtime/r3/posix/timelocal-posix.cpp
index d65c0167..ce60f751 100644
--- a/src/VBox/Runtime/r3/posix/timelocal-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/timelocal-posix.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/posix/timer-posix.cpp b/src/VBox/Runtime/r3/posix/timer-posix.cpp
index f6e75492..043709a1 100644
--- a/src/VBox/Runtime/r3/posix/timer-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/timer-posix.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;
@@ -57,6 +57,7 @@
#include <iprt/string.h>
#include <iprt/once.h>
#include <iprt/err.h>
+#include <iprt/initterm.h>
#include <iprt/critsect.h>
#include "internal/magics.h"
@@ -152,14 +153,12 @@ typedef struct RTTIMER
* RTOnce callback that initializes the critical section.
*
* @returns RTCritSectInit return code.
- * @param pvUser1 NULL, ignored.
- * @param pvUser2 NULL, ignored.
+ * @param pvUser NULL, ignored.
*
*/
-static DECLCALLBACK(int) rtTimerOnce(void *pvUser1, void *pvUser2)
+static DECLCALLBACK(int) rtTimerOnce(void *pvUser)
{
- NOREF(pvUser1);
- NOREF(pvUser2);
+ NOREF(pvUser);
return RTCritSectInit(&g_TimerCritSect);
}
#endif
@@ -406,6 +405,13 @@ RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_
if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC)
return VERR_NOT_SUPPORTED;
+ /*
+ * We need the signal masks to be set correctly, which they won't be in
+ * unobtrusive mode.
+ */
+ if (RTR3InitIsUnobtrusive())
+ return VERR_NOT_SUPPORTED;
+
#ifndef IPRT_WITH_POSIX_TIMERS
/*
* Check if timer is busy.
@@ -539,7 +545,7 @@ RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_
/*
* Do the global init first.
*/
- int rc = RTOnce(&g_TimerOnce, rtTimerOnce, NULL, NULL);
+ int rc = RTOnce(&g_TimerOnce, rtTimerOnce, NULL);
if (RT_FAILURE(rc))
return rc;
diff --git a/src/VBox/Runtime/r3/posix/tls-posix.cpp b/src/VBox/Runtime/r3/posix/tls-posix.cpp
index c8005a59..c79e6e22 100644
--- a/src/VBox/Runtime/r3/posix/tls-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/tls-posix.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/posix/utf8-posix.cpp b/src/VBox/Runtime/r3/posix/utf8-posix.cpp
index 35ae6f3d..cb723eb7 100644
--- a/src/VBox/Runtime/r3/posix/utf8-posix.cpp
+++ b/src/VBox/Runtime/r3/posix/utf8-posix.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;
@@ -193,11 +193,13 @@ static int rtstrConvertCached(const void *pvInput, size_t cbInput, const char *p
size_t cbOutLeft = cbOutput2;
const void *pvInputLeft = pvInput;
void *pvOutputLeft = pvOutput;
-#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || (defined(RT_OS_DARWIN) && defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) /* there are different opinions about the constness of the input buffer. */
- if (iconv(hIconv, (char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft) != (size_t)-1)
+ size_t cchNonRev;
+#if defined(RT_OS_LINUX) || defined(RT_OS_HAIKU) || defined(RT_OS_SOLARIS) || (defined(RT_OS_DARWIN) && defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) /* there are different opinions about the constness of the input buffer. */
+ cchNonRev = iconv(hIconv, (char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft);
#else
- if (iconv(hIconv, (const char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft) != (size_t)-1)
+ cchNonRev = iconv(hIconv, (const char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft);
#endif
+ if (cchNonRev != (size_t)-1)
{
if (!cbInLeft)
{
@@ -209,7 +211,9 @@ static int rtstrConvertCached(const void *pvInput, size_t cbInput, const char *p
if (fUcs2Term)
((char *)pvOutputLeft)[1] = '\0';
*ppvOutput = pvOutput;
- return VINF_SUCCESS;
+ if (cchNonRev == 0)
+ return VINF_SUCCESS;
+ return VWRN_NO_TRANSLATION;
}
errno = E2BIG;
}
@@ -319,11 +323,13 @@ static int rtStrConvertUncached(const void *pvInput, size_t cbInput, const char
size_t cbOutLeft = cbOutput2;
const void *pvInputLeft = pvInput;
void *pvOutputLeft = pvOutput;
-#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || (defined(RT_OS_DARWIN) && defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) /* there are different opinions about the constness of the input buffer. */
- if (iconv(icHandle, (char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft) != (size_t)-1)
+ size_t cchNonRev;
+#if defined(RT_OS_LINUX) || defined(RT_OS_HAIKU) || defined(RT_OS_SOLARIS) || (defined(RT_OS_DARWIN) && defined(_DARWIN_FEATURE_UNIX_CONFORMANCE)) /* there are different opinions about the constness of the input buffer. */
+ cchNonRev = iconv(icHandle, (char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft);
#else
- if (iconv(icHandle, (const char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft) != (size_t)-1)
+ cchNonRev = iconv(icHandle, (const char **)&pvInputLeft, &cbInLeft, (char **)&pvOutputLeft, &cbOutLeft);
#endif
+ if (cchNonRev != (size_t)-1)
{
if (!cbInLeft)
{
@@ -336,7 +342,9 @@ static int rtStrConvertUncached(const void *pvInput, size_t cbInput, const char
if (fUcs2Term)
((char *)pvOutputLeft)[1] = '\0';
*ppvOutput = pvOutput;
- return VINF_SUCCESS;
+ if (cchNonRev == 0)
+ return VINF_SUCCESS;
+ return VWRN_NO_TRANSLATION;
}
errno = E2BIG;
}
diff --git a/src/VBox/Runtime/r3/process.cpp b/src/VBox/Runtime/r3/process.cpp
index 7be307f3..9f47814d 100644
--- a/src/VBox/Runtime/r3/process.cpp
+++ b/src/VBox/Runtime/r3/process.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/socket.cpp b/src/VBox/Runtime/r3/socket.cpp
index 42d42883..8678c37b 100644
--- a/src/VBox/Runtime/r3/socket.cpp
+++ b/src/VBox/Runtime/r3/socket.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;
@@ -33,6 +33,7 @@
# include <ws2tcpip.h>
#else /* !RT_OS_WINDOWS */
# include <errno.h>
+# include <sys/select.h>
# include <sys/stat.h>
# include <sys/socket.h>
# include <netinet/in.h>
@@ -110,6 +111,15 @@
/** How many pending connection. */
#define RTTCP_SERVER_BACKLOG 10
+/* Limit read and write sizes on Windows and OS/2. */
+#ifdef RT_OS_WINDOWS
+# define RTSOCKET_MAX_WRITE (INT_MAX / 2)
+# define RTSOCKET_MAX_READ (INT_MAX / 2)
+#elif defined(RT_OS_OS2)
+# define RTSOCKET_MAX_WRITE 0x10000
+# define RTSOCKET_MAX_READ 0x10000
+#endif
+
/*******************************************************************************
* Structures and Typedefs *
@@ -135,13 +145,15 @@ typedef struct RTSOCKETINT
/** Indicates whether the socket is operating in blocking or non-blocking mode
* currently. */
bool fBlocking;
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+ /** The pollset currently polling this socket. This is NIL if no one is
+ * polling. */
+ RTPOLLSET hPollSet;
+#endif
#ifdef RT_OS_WINDOWS
/** The event semaphore we've associated with the socket handle.
* This is WSA_INVALID_EVENT if not done. */
WSAEVENT hEvent;
- /** The pollset currently polling this socket. This is NIL if no one is
- * polling. */
- RTPOLLSET hPollSet;
/** The events we're polling for. */
uint32_t fPollEvts;
/** The events we're currently subscribing to with WSAEventSelect.
@@ -397,9 +409,11 @@ int rtSocketCreateForNative(RTSOCKETINT **ppSocket, RTSOCKETNATIVE hNative)
pThis->hNative = hNative;
pThis->fClosed = false;
pThis->fBlocking = true;
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
+ pThis->hPollSet = NIL_RTPOLLSET;
+#endif
#ifdef RT_OS_WINDOWS
pThis->hEvent = WSA_INVALID_EVENT;
- pThis->hPollSet = NIL_RTPOLLSET;
pThis->fPollEvts = 0;
pThis->fSubscribedEvts = 0;
#endif
@@ -853,8 +867,8 @@ RTDECL(int) RTSocketRead(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, size
for (;;)
{
rtSocketErrorReset();
-#ifdef RT_OS_WINDOWS
- int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
+#ifdef RTSOCKET_MAX_READ
+ int cbNow = cbToRead >= RTSOCKET_MAX_READ ? RTSOCKET_MAX_READ : (int)cbToRead;
#else
size_t cbNow = cbToRead;
#endif
@@ -920,8 +934,8 @@ RTDECL(int) RTSocketReadFrom(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer,
size_t cbToRead = cbBuffer;
rtSocketErrorReset();
RTSOCKADDRUNION u;
-#ifdef RT_OS_WINDOWS
- int cbNow = cbToRead >= INT_MAX/2 ? INT_MAX/2 : (int)cbToRead;
+#ifdef RTSOCKET_MAX_READ
+ int cbNow = cbToRead >= RTSOCKET_MAX_READ ? RTSOCKET_MAX_READ : (int)cbToRead;
int cbAddr = sizeof(u);
#else
size_t cbNow = cbToRead;
@@ -967,8 +981,8 @@ RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffe
/*
* Try write all at once.
*/
-#ifdef RT_OS_WINDOWS
- int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
+#ifdef RTSOCKET_MAX_WRITE
+ int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
#else
size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
#endif
@@ -994,8 +1008,8 @@ RTDECL(int) RTSocketWrite(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuffe
pvBuffer = (char const *)pvBuffer + cbWritten;
/* send */
-#ifdef RT_OS_WINDOWS
- cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
+#ifdef RTSOCKET_MAX_WRITE
+ cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
#else
cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
#endif
@@ -1056,7 +1070,7 @@ RTDECL(int) RTSocketWriteTo(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuf
* Must write all at once, otherwise it is a failure.
*/
#ifdef RT_OS_WINDOWS
- int cbNow = cbBuffer >= INT_MAX / 2 ? INT_MAX / 2 : (int)cbBuffer;
+ int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
#else
size_t cbNow = cbBuffer >= SSIZE_MAX ? SSIZE_MAX : cbBuffer;
#endif
@@ -1201,9 +1215,13 @@ RTDECL(int) RTSocketReadNB(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, si
return rc;
rtSocketErrorReset();
-#ifdef RT_OS_WINDOWS
- int cbNow = cbBuffer >= INT_MAX/2 ? INT_MAX/2 : (int)cbBuffer;
+#ifdef RTSOCKET_MAX_READ
+ int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
+#else
+ size_t cbNow = cbBuffer;
+#endif
+#ifdef RT_OS_WINDOWS
int cbRead = recv(pThis->hNative, (char *)pvBuffer, cbNow, MSG_NOSIGNAL);
if (cbRead >= 0)
{
@@ -1216,7 +1234,7 @@ RTDECL(int) RTSocketReadNB(RTSOCKET hSocket, void *pvBuffer, size_t cbBuffer, si
if (rc == VERR_TRY_AGAIN)
rc = VINF_TRY_AGAIN;
#else
- ssize_t cbRead = recv(pThis->hNative, pvBuffer, cbBuffer, MSG_NOSIGNAL);
+ ssize_t cbRead = recv(pThis->hNative, pvBuffer, cbNow, MSG_NOSIGNAL);
if (cbRead >= 0)
*pcbRead = cbRead;
else if (errno == EAGAIN)
@@ -1249,11 +1267,14 @@ RTDECL(int) RTSocketWriteNB(RTSOCKET hSocket, const void *pvBuffer, size_t cbBuf
return rc;
rtSocketErrorReset();
-#ifdef RT_OS_WINDOWS
- int cbNow = RT_MIN((int)cbBuffer, INT_MAX/2);
+#ifdef RTSOCKET_MAX_WRITE
+ int cbNow = cbBuffer >= RTSOCKET_MAX_WRITE ? RTSOCKET_MAX_WRITE : (int)cbBuffer;
+#else
+ size_t cbNow = cbBuffer;
+#endif
+#ifdef RT_OS_WINDOWS
int cbWritten = send(pThis->hNative, (const char *)pvBuffer, cbNow, MSG_NOSIGNAL);
-
if (cbWritten >= 0)
{
*pcbWritten = cbWritten;
@@ -1752,7 +1773,6 @@ int rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValu
return rc;
}
-#ifdef RT_OS_WINDOWS
/**
* Internal RTPollSetAdd helper that returns the handle that should be added to
@@ -1761,29 +1781,37 @@ int rtSocketSetOpt(RTSOCKET hSocket, int iLevel, int iOption, void const *pvValu
* @returns Valid handle on success, INVALID_HANDLE_VALUE on failure.
* @param hSocket The socket handle.
* @param fEvents The events we're polling for.
- * @param ph where to put the primary handle.
+ * @param phNative Where to put the primary handle.
*/
-int rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PHANDLE ph)
+int rtSocketPollGetHandle(RTSOCKET hSocket, uint32_t fEvents, PRTHCINTPTR phNative)
{
RTSOCKETINT *pThis = hSocket;
AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, VERR_INVALID_HANDLE);
+#ifdef RT_OS_WINDOWS
AssertReturn(rtSocketTryLock(pThis), VERR_CONCURRENT_ACCESS);
int rc = VINF_SUCCESS;
if (pThis->hEvent != WSA_INVALID_EVENT)
- *ph = pThis->hEvent;
+ *phNative = (RTHCINTPTR)pThis->hEvent;
else
{
- *ph = pThis->hEvent = WSACreateEvent();
+ pThis->hEvent = WSACreateEvent();
+ *phNative = (RTHCINTPTR)pThis->hEvent;
if (pThis->hEvent == WSA_INVALID_EVENT)
rc = rtSocketError();
}
rtSocketUnlock(pThis);
return rc;
+
+#else /* !RT_OS_WINDOWS */
+ *phNative = (RTHCUINTPTR)pThis->hNative;
+ return VINF_SUCCESS;
+#endif /* !RT_OS_WINDOWS */
}
+#ifdef RT_OS_WINDOWS
/**
* Undos the harm done by WSAEventSelect.
@@ -1853,6 +1881,10 @@ static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents)
return rc;
}
+#endif /* RT_OS_WINDOWS */
+
+
+#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
/**
* Checks for pending events.
@@ -1863,12 +1895,13 @@ static int rtSocketPollUpdateEvents(RTSOCKETINT *pThis, uint32_t fEvents)
*/
static uint32_t rtSocketPollCheck(RTSOCKETINT *pThis, uint32_t fEvents)
{
- int rc = VINF_SUCCESS;
- uint32_t fRetEvents = 0;
+ uint32_t fRetEvents = 0;
LogFlowFunc(("pThis=%#p fEvents=%#x\n", pThis, fEvents));
+# ifdef RT_OS_WINDOWS
/* Make sure WSAEnumNetworkEvents returns what we want. */
+ int rc = VINF_SUCCESS;
if ((pThis->fSubscribedEvts & fEvents) != fEvents)
rc = rtSocketPollUpdateEvents(pThis, pThis->fSubscribedEvts | fEvents);
@@ -1904,8 +1937,23 @@ static uint32_t rtSocketPollCheck(RTSOCKETINT *pThis, uint32_t fEvents)
/* Fall back on select if we hit an error above. */
if (RT_FAILURE(rc))
{
- /** @todo */
+
+ }
+
+#else /* RT_OS_OS2 */
+ int aFds[4] = { pThis->hNative, pThis->hNative, pThis->hNative, -1 };
+ int rc = os2_select(aFds, 1, 1, 1, 0);
+ if (rc > 0)
+ {
+ if (aFds[0] == pThis->hNative)
+ fRetEvents |= RTPOLL_EVT_READ;
+ if (aFds[1] == pThis->hNative)
+ fRetEvents |= RTPOLL_EVT_WRITE;
+ if (aFds[2] == pThis->hNative)
+ fRetEvents |= RTPOLL_EVT_ERROR;
+ fRetEvents &= fEvents;
}
+#endif /* RT_OS_OS2 */
LogFlowFunc(("fRetEvents=%#x\n", fRetEvents));
return fRetEvents;
@@ -1939,6 +1987,8 @@ uint32_t rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvent
RTSOCKETINT *pThis = hSocket;
AssertPtrReturn(pThis, UINT32_MAX);
AssertReturn(pThis->u32Magic == RTSOCKET_MAGIC, UINT32_MAX);
+ /** @todo This isn't quite sane. Replace by critsect and open up concurrent
+ * reads and writes! */
if (rtSocketTryLock(pThis))
pThis->hPollSet = hPollSet;
else
@@ -1948,6 +1998,7 @@ uint32_t rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvent
}
/* (rtSocketPollCheck will reset the event object). */
+# ifdef RT_OS_WINDOWS
uint32_t fRetEvents = pThis->fEventsSaved;
pThis->fEventsSaved = 0; /* Reset */
fRetEvents |= rtSocketPollCheck(pThis, fEvents);
@@ -1967,12 +2018,17 @@ uint32_t rtSocketPollStart(RTSOCKET hSocket, RTPOLLSET hPollSet, uint32_t fEvent
}
}
}
+# else
+ uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
+# endif
if (fRetEvents || fNoWait)
{
if (pThis->cUsers == 1)
{
+# ifdef RT_OS_WINDOWS
rtSocketPollClearEventAndRestoreBlocking(pThis);
+# endif
pThis->hPollSet = NIL_RTPOLLSET;
}
ASMAtomicDecU32(&pThis->cUsers);
@@ -2008,6 +2064,7 @@ uint32_t rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry,
/* Harvest events and clear the event mask for the next round of polling. */
uint32_t fRetEvents = rtSocketPollCheck(pThis, fEvents);
+# ifdef RT_OS_WINDOWS
pThis->fPollEvts = 0;
/*
@@ -2021,15 +2078,19 @@ uint32_t rtSocketPollDone(RTSOCKET hSocket, uint32_t fEvents, bool fFinalEntry,
pThis->fEventsSaved = fRetEvents;
fRetEvents = 0;
}
+# endif
/* Make the socket blocking again and unlock the handle. */
if (pThis->cUsers == 1)
{
+# ifdef RT_OS_WINDOWS
rtSocketPollClearEventAndRestoreBlocking(pThis);
+# endif
pThis->hPollSet = NIL_RTPOLLSET;
}
ASMAtomicDecU32(&pThis->cUsers);
return fRetEvents;
}
-#endif /* RT_OS_WINDOWS */
+#endif /* RT_OS_WINDOWS || RT_OS_OS2 */
+
diff --git a/src/VBox/Runtime/r3/solaris/Makefile.kup b/src/VBox/Runtime/r3/solaris/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Runtime/r3/solaris/Makefile.kup
diff --git a/src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp b/src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp
new file mode 100644
index 00000000..44906788
--- /dev/null
+++ b/src/VBox/Runtime/r3/solaris/RTSystemShutdown-solaris.cpp
@@ -0,0 +1,102 @@
+/* $Id: RTSystemShutdown-solaris.cpp $ */
+/** @file
+ * IPRT - RTSystemShutdown, linux implementation.
+ */
+
+/*
+ * Copyright (C) 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;
+ * 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/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/assert.h>
+#include <iprt/env.h>
+#include <iprt/err.h>
+#include <iprt/process.h>
+#include <iprt/string.h>
+
+
+RTDECL(int) RTSystemShutdown(RTMSINTERVAL cMsDelay, uint32_t fFlags, const char *pszLogMsg)
+{
+ AssertPtrReturn(pszLogMsg, VERR_INVALID_POINTER);
+ AssertReturn(!(fFlags & ~RTSYSTEM_SHUTDOWN_VALID_MASK), VERR_INVALID_PARAMETER);
+
+ /*
+ * Assemble the argument vector.
+ */
+ int iArg = 0;
+ const char *apszArgs[8];
+
+ RT_BZERO(apszArgs, sizeof(apszArgs));
+
+ apszArgs[iArg++] = "/usr/sbin/shutdown";
+ apszArgs[iArg++] = "-y"; /* Pre-answer confirmation question. */
+ apszArgs[iArg++] = "-i"; /* Change to the following state. */
+ switch (fFlags & RTSYSTEM_SHUTDOWN_ACTION_MASK)
+ {
+ case RTSYSTEM_SHUTDOWN_HALT:
+ apszArgs[iArg++] = "0";
+ break;
+ case RTSYSTEM_SHUTDOWN_REBOOT:
+ apszArgs[iArg++] = "6";
+ break;
+ case RTSYSTEM_SHUTDOWN_POWER_OFF:
+ case RTSYSTEM_SHUTDOWN_POWER_OFF_HALT:
+ apszArgs[iArg++] = "5";
+ break;
+ }
+
+ apszArgs[iArg++] = "-g"; /* Grace period. */
+
+ char szWhen[80];
+ if (cMsDelay < 500)
+ strcpy(szWhen, "0");
+ else
+ RTStrPrintf(szWhen, sizeof(szWhen), "%u", (unsigned)((cMsDelay + 499) / 1000));
+ apszArgs[iArg++] = szWhen;
+
+ apszArgs[iArg++] = pszLogMsg;
+
+
+ /*
+ * Start the shutdown process and wait for it to complete.
+ */
+ RTPROCESS hProc;
+ int rc = RTProcCreate(apszArgs[0], apszArgs, RTENV_DEFAULT, 0 /*fFlags*/, &hProc);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ RTPROCSTATUS ProcStatus;
+ rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &ProcStatus);
+ if (RT_SUCCESS(rc))
+ {
+ if ( ProcStatus.enmReason != RTPROCEXITREASON_NORMAL
+ || ProcStatus.iStatus != 0)
+ rc = VERR_SYS_SHUTDOWN_FAILED;
+ }
+
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp b/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
index 39726eda..66ef5286 100644
--- a/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/coredumper-solaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010-2011 Oracle Corporation
+ * Copyright (C) 2010-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;
@@ -162,7 +162,7 @@ static int ReadFileNoIntr(int fd, void *pv, size_t cbToRead)
*
* @param fd Handle to the file to write to.
* @param pv Pointer to what to write.
- * @param cbToWrite Size of data to write.
+ * @param cbToWrite Size of data to write.
*
* @return IPRT status code.
*/
@@ -191,9 +191,9 @@ static int WriteFileNoIntr(int fd, const void *pv, size_t cbToWrite)
* Read from a given offset in the process' address space.
*
* @param pSolProc Pointer to the solaris process.
- * @param pv Where to read the data into.
- * @param cb Size of the read buffer.
- * @param off Offset to read from.
+ * @param off The offset to read from.
+ * @param pvBuf Where to read the data into.
+ * @param cbToRead Number of bytes to read.
*
* @return VINF_SUCCESS, if all the given bytes was read in, otherwise VERR_READ_ERROR.
*/
@@ -1263,51 +1263,8 @@ static int rtCoreDumperResumeThreads(PRTSOLCORE pSolCore)
{
AssertReturn(pSolCore, VERR_INVALID_POINTER);
-#if 1
uint64_t cThreads;
return rtCoreDumperForEachThread(pSolCore, &cThreads, resumeThread);
-#else
- PRTSOLCOREPROCESS pSolProc = &pSolCore->SolProc;
-
- char szCurThread[128];
- char szPath[PATH_MAX];
- PRTDIR pDir = NULL;
-
- RTStrPrintf(szPath, sizeof(szPath), "/proc/%d/lwp", (int)pSolProc->Process);
- RTStrPrintf(szCurThread, sizeof(szCurThread), "%d", (int)pSolProc->hCurThread);
-
- int32_t cRunningThreads = 0;
- int rc = RTDirOpen(&pDir, szPath);
- if (RT_SUCCESS(rc))
- {
- /*
- * Loop through all our threads & resume them.
- */
- RTDIRENTRY DirEntry;
- while (RT_SUCCESS(RTDirRead(pDir, &DirEntry, NULL)))
- {
- if ( !strcmp(DirEntry.szName, ".")
- || !strcmp(DirEntry.szName, ".."))
- continue;
-
- if ( !strcmp(DirEntry.szName, szCurThread))
- continue;
-
- int32_t ThreadId = RTStrToInt32(DirEntry.szName);
- _lwp_continue((lwpid_t)ThreadId);
- ++cRunningThreads;
- }
-
- CORELOG((CORELOG_NAME "ResumeAllThreads: resumed %d threads\n", cRunningThreads));
- RTDirClose(pDir);
- }
- else
- {
- CORELOGRELSYS((CORELOG_NAME "ResumeAllThreads: Failed to open %s\n", szPath));
- rc = VERR_READ_ERROR;
- }
- return rc;
-#endif
}
@@ -2116,8 +2073,7 @@ static int rtCoreDumperDestroyCore(PRTSOLCORE pSolCore)
/**
- * Takes a core dump. This function has no other parameters than the context
- * because it can be called from signal handlers.
+ * Takes a core dump.
*
* @param pContext The context of the caller.
* @param pszOutputFile Path of the core file. If NULL is passed, the
diff --git a/src/VBox/Runtime/r3/solaris/coredumper-solaris.h b/src/VBox/Runtime/r3/solaris/coredumper-solaris.h
index 127fd9be..662effc6 100644
--- a/src/VBox/Runtime/r3/solaris/coredumper-solaris.h
+++ b/src/VBox/Runtime/r3/solaris/coredumper-solaris.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2010-2011 Oracle Corporation
+ * Copyright (C) 2010-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/solaris/fileaio-solaris.cpp b/src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp
index 2b6d60b8..2f218305 100644
--- a/src/VBox/Runtime/r3/solaris/fileaio-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/fileaio-solaris.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;
@@ -55,6 +55,8 @@ typedef struct RTFILEAIOCTXINTERNAL
int iPort;
/** Current number of requests active on this context. */
volatile int32_t cRequests;
+ /** Flags given during creation. */
+ uint32_t fFlags;
/** Magic value (RTFILEAIOCTX_MAGIC). */
uint32_t u32Magic;
} RTFILEAIOCTXINTERNAL;
@@ -270,11 +272,13 @@ RTDECL(int) RTFileAioReqGetRC(RTFILEAIOREQ hReq, size_t *pcbTransfered)
return RTErrConvertFromErrno(rcSol);
}
-RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
+RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax,
+ uint32_t fFlags)
{
int rc = VINF_SUCCESS;
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))
@@ -284,7 +288,8 @@ RTDECL(int) RTFileAioCtxCreate(PRTFILEAIOCTX phAioCtx, uint32_t cAioReqsMax)
pCtxInt->iPort = port_create();
if (RT_LIKELY(pCtxInt->iPort > 0))
{
- pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
+ pCtxInt->fFlags = fFlags;
+ pCtxInt->u32Magic = RTFILEAIOCTX_MAGIC;
*phAioCtx = (RTFILEAIOCTX)pCtxInt;
}
else
@@ -448,7 +453,8 @@ RTDECL(int) RTFileAioCtxWait(RTFILEAIOCTX hAioCtx, size_t cMinReqs, RTMSINTERVAL
AssertReturn(cReqs != 0, VERR_INVALID_PARAMETER);
AssertReturn(cReqs >= cMinReqs, VERR_OUT_OF_RANGE);
- if (RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0))
+ if ( RT_UNLIKELY(ASMAtomicReadS32(&pCtxInt->cRequests) == 0)
+ && !(pCtxInt->fFlags & RTFILEAIOCTX_FLAGS_WAIT_WITHOUT_PENDING_REQUESTS))
return VERR_FILE_AIO_NO_REQUEST;
/*
diff --git a/src/VBox/Runtime/r3/solaris/mp-solaris.cpp b/src/VBox/Runtime/r3/solaris/mp-solaris.cpp
index 0f2c6fdf..d21bbb42 100644
--- a/src/VBox/Runtime/r3/solaris/mp-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/mp-solaris.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-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;
@@ -57,19 +57,77 @@ static kstat_ctl_t *g_pKsCtl;
static kstat_t **g_papCpuInfo;
/** The number of entries in g_papCpuInfo */
static RTCPUID g_capCpuInfo;
+/** Array of core ids. */
+static uint64_t *g_pu64CoreIds;
+/** Number of entries in g_pu64CoreIds. */
+static size_t g_cu64CoreIds;
+/** Number of cores in the system. */
+static size_t g_cCores;
+
+
+/**
+ * Helper for getting the core ID for a given CPU/strand/hyperthread.
+ *
+ * @returns The core ID.
+ * @param idCpu The CPU ID instance.
+ */
+static inline uint64_t rtMpSolarisGetCoreId(RTCPUID idCpu)
+{
+ kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char *)"core_id");
+ Assert(pStat->data_type == KSTAT_DATA_LONG);
+ Assert(pStat->value.l >= 0);
+ AssertCompile(sizeof(uint64_t) >= sizeof(long)); /* Paranoia. */
+ return (uint64_t)pStat->value.l;
+}
+
+
+/**
+ * Populates 'g_pu64CoreIds' array with unique core identifiers in the system.
+ *
+ * @returns VBox status code.
+ */
+static int rtMpSolarisGetCoreIds(void)
+{
+ for (RTCPUID idCpu = 0; idCpu < g_capCpuInfo; idCpu++)
+ {
+ if (kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0) != -1)
+ {
+ /* Strands/Hyperthreads share the same core ID. */
+ uint64_t u64CoreId = rtMpSolarisGetCoreId(idCpu);
+ bool fAddedCore = false;
+ for (RTCPUID i = 0; i < g_cCores; i++)
+ {
+ if (g_pu64CoreIds[i] == u64CoreId)
+ {
+ fAddedCore = true;
+ break;
+ }
+ }
+
+ if (!fAddedCore)
+ {
+ g_pu64CoreIds[g_cCores] = u64CoreId;
+ ++g_cCores;
+ }
+ }
+ else
+ return VERR_INTERNAL_ERROR_2;
+ }
+
+ return VINF_SUCCESS;
+}
/**
* Run once function that initializes the kstats we need here.
*
* @returns IPRT status code.
- * @param pvUser1 Unused.
- * @param pvUser2 Unused.
+ * @param pvUser Unused.
*/
-static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
+static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser)
{
int rc = VINF_SUCCESS;
- NOREF(pvUser1); NOREF(pvUser2);
+ NOREF(pvUser);
/*
* Open kstat and find the cpu_info entries for each of the CPUs.
@@ -81,25 +139,40 @@ static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
g_papCpuInfo = (kstat_t **)RTMemAllocZ(g_capCpuInfo * sizeof(kstat_t *));
if (g_papCpuInfo)
{
- rc = RTCritSectInit(&g_MpSolarisCritSect);
- if (RT_SUCCESS(rc))
+ g_cu64CoreIds = g_capCpuInfo;
+ g_pu64CoreIds = (uint64_t *)RTMemAllocZ(g_cu64CoreIds * sizeof(uint64_t));
+ if (g_pu64CoreIds)
{
- RTCPUID i = 0;
- for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
+ rc = RTCritSectInit(&g_MpSolarisCritSect);
+ if (RT_SUCCESS(rc))
{
- if (!strcmp(pKsp->ks_module, "cpu_info"))
+ RTCPUID i = 0;
+ for (kstat_t *pKsp = g_pKsCtl->kc_chain; pKsp != NULL; pKsp = pKsp->ks_next)
{
- AssertBreak(i < g_capCpuInfo);
- g_papCpuInfo[i++] = pKsp;
- /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
+ if (!RTStrCmp(pKsp->ks_module, "cpu_info"))
+ {
+ AssertBreak(i < g_capCpuInfo);
+ g_papCpuInfo[i++] = pKsp;
+ /** @todo ks_instance == cpu_id (/usr/src/uts/common/os/cpu.c)? Check this and fix it ASAP. */
+ }
}
+
+ rc = rtMpSolarisGetCoreIds();
+ if (RT_SUCCESS(rc))
+ return VINF_SUCCESS;
+ else
+ Log(("rtMpSolarisGetCoreIds failed. rc=%Rrc\n", rc));
}
- return VINF_SUCCESS;
+ RTMemFree(g_pu64CoreIds);
+ g_pu64CoreIds = NULL;
}
+ else
+ rc = VERR_NO_MEMORY;
/* bail out, we failed. */
RTMemFree(g_papCpuInfo);
+ g_papCpuInfo = NULL;
}
else
rc = VERR_NO_MEMORY;
@@ -119,6 +192,21 @@ static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
/**
+ * RTOnceEx() cleanup function.
+ *
+ * @param pvUser Unused.
+ * @param fLazyCleanUpOk Whether lazy cleanup is okay or not.
+ */
+static DECLCALLBACK(void) rtMpSolarisCleanUp(void *pvUser, bool fLazyCleanUpOk)
+{
+ if (g_pKsCtl)
+ kstat_close(g_pKsCtl);
+ RTMemFree(g_pu64CoreIds);
+ RTMemFree(g_papCpuInfo);
+}
+
+
+/**
* Worker for RTMpGetCurFrequency and RTMpGetMaxFrequency.
*
* @returns The desired frequency on success, 0 on failure.
@@ -126,10 +214,10 @@ static DECLCALLBACK(int) rtMpSolarisOnce(void *pvUser1, void *pvUser2)
* @param idCpu The CPU ID.
* @param pszStatName The cpu_info stat name.
*/
-static uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, char *pszStatName)
+static uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, const char *pszStatName)
{
uint64_t u64 = 0;
- int rc = RTOnce(&g_MpSolarisOnce, rtMpSolarisOnce, NULL, NULL);
+ int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
if (RT_SUCCESS(rc))
{
if ( idCpu < g_capCpuInfo
@@ -141,7 +229,8 @@ static uint64_t rtMpSolarisGetFrequency(RTCPUID idCpu, char *pszStatName)
{
if (kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0) != -1)
{
- kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], pszStatName);
+ /* Solaris really need to fix their APIs. Explicitly cast for now. */
+ kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char*)pszStatName);
if (pStat)
{
Assert(pStat->data_type == KSTAT_DATA_UINT64 || pStat->data_type == KSTAT_DATA_LONG);
@@ -280,7 +369,7 @@ RTDECL(PRTCPUSET) RTMpGetOnlineSet(PRTCPUSET pSet)
RTDECL(PRTCPUSET) RTMpGetPresentSet(PRTCPUSET pSet)
{
#ifdef RT_STRICT
- long cCpusPresent = 0;
+ RTCPUID cCpusPresent = 0;
#endif
RTCpuSetEmpty(pSet);
RTCPUID cCpus = RTMpGetCount();
@@ -305,3 +394,60 @@ RTDECL(RTCPUID) RTMpGetPresentCount(void)
return sysconf(_SC_NPROCESSORS_CONF);
}
+
+RTDECL(RTCPUID) RTMpGetPresentCoreCount(void)
+{
+ return RTMpGetCoreCount();
+}
+
+
+RTDECL(RTCPUID) RTMpGetCoreCount(void)
+{
+ int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
+ if (RT_SUCCESS(rc))
+ return g_cCores;
+
+ return 0;
+}
+
+
+RTDECL(RTCPUID) RTMpGetOnlineCoreCount(void)
+{
+ RTCPUID uOnlineCores = 0;
+ int rc = RTOnceEx(&g_MpSolarisOnce, rtMpSolarisOnce, rtMpSolarisCleanUp, NULL /* pvUser */);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTCritSectEnter(&g_MpSolarisCritSect);
+ AssertRC(rc);
+
+ /*
+ * For each core in the system, count how many are currently online.
+ */
+ for (RTCPUID j = 0; j < g_cCores; j++)
+ {
+ uint64_t u64CoreId = g_pu64CoreIds[j];
+ for (RTCPUID idCpu = 0; idCpu < g_capCpuInfo; idCpu++)
+ {
+ rc = kstat_read(g_pKsCtl, g_papCpuInfo[idCpu], 0);
+ AssertReturn(rc != -1, 0 /* rc */);
+ uint64_t u64ThreadCoreId = rtMpSolarisGetCoreId(idCpu);
+ if (u64ThreadCoreId == u64CoreId)
+ {
+ kstat_named_t *pStat = (kstat_named_t *)kstat_data_lookup(g_papCpuInfo[idCpu], (char *)"state");
+ Assert(pStat->data_type == KSTAT_DATA_CHAR);
+ if( !RTStrNCmp(pStat->value.c, PS_ONLINE, sizeof(PS_ONLINE) - 1)
+ || !RTStrNCmp(pStat->value.c, PS_NOINTR, sizeof(PS_NOINTR) - 1))
+ {
+ uOnlineCores++;
+ break; /* Move to the next core. We have at least 1 hyperthread online in the current core. */
+ }
+ }
+ }
+ }
+
+ RTCritSectLeave(&g_MpSolarisCritSect);
+ }
+
+ return uOnlineCores;
+}
+
diff --git a/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp b/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp
index 40baf8c2..ffaad258 100644
--- a/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.cpp
+++ b/src/VBox/Runtime/r3/solaris/rtProcInitExePath-solaris.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/solaris/systemmem-solaris.cpp b/src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp
new file mode 100644
index 00000000..e5efe631
--- /dev/null
+++ b/src/VBox/Runtime/r3/solaris/systemmem-solaris.cpp
@@ -0,0 +1,172 @@
+/* $Id: systemmem-solaris.cpp $ */
+/** @file
+ * IPRT - RTSystemQueryTotalRam, Solaris ring-3.
+ */
+
+/*
+ * Copyright (C) 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;
+ * 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/system.h>
+#include "internal/iprt.h"
+
+#include <iprt/err.h>
+#include <iprt/assert.h>
+#include <iprt/critsect.h>
+#include <iprt/once.h>
+#include <iprt/param.h>
+
+#include <errno.h>
+#include <kstat.h>
+
+
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
+/** Initialize globals once. */
+static RTONCE g_rtSysMemSolInitOnce = RTONCE_INITIALIZER;
+/** Critical section serializing access to g_pKStatCtl and the other handles. */
+static RTCRITSECT g_rtSysMemSolCritSect;
+/** The kstate control handle. */
+static kstat_ctl_t *g_pKStatCtl = NULL;
+/** The unix.system_pages handle. */
+static kstat_t *g_pUnixSysPages = NULL;
+/** The zfs.archstats handle. */
+static kstat_t *g_pZfsArcStats = NULL;
+
+
+/** @callback_method_impl{FNRTONCE} */
+static DECLCALLBACK(int) rtSysMemSolInit(void *pvUser)
+{
+ int rc = RTCritSectInit(&g_rtSysMemSolCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ g_pKStatCtl = kstat_open();
+ if (g_pKStatCtl)
+ {
+ g_pUnixSysPages = kstat_lookup(g_pKStatCtl, (char *)"unix", 0, (char *)"system_pages");
+ if (g_pUnixSysPages)
+ {
+ g_pZfsArcStats = kstat_lookup(g_pKStatCtl, (char *)"zfs", 0, (char *)"arcstats"); /* allow NULL */
+ return VINF_SUCCESS;
+ }
+
+ rc = RTErrConvertFromErrno(errno);
+ kstat_close(g_pKStatCtl);
+ g_pKStatCtl = NULL;
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+ return rc;
+}
+
+
+/** @callback_method_impl{FNRTONCECLEANUP} */
+static DECLCALLBACK(void) rtSysMemSolCleanUp(void *pvUser, bool fLazyCleanUpOk)
+{
+ RTCritSectDelete(&g_rtSysMemSolCritSect);
+
+ kstat_close(g_pKStatCtl);
+ g_pKStatCtl = NULL;
+ g_pUnixSysPages = NULL;
+ g_pZfsArcStats = NULL;
+
+ NOREF(pvUser); NOREF(fLazyCleanUpOk);
+}
+
+
+
+RTDECL(int) RTSystemQueryTotalRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ int rc = RTOnceEx(&g_rtSysMemSolInitOnce, rtSysMemSolInit, rtSysMemSolCleanUp, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTCritSectEnter(&g_rtSysMemSolCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ if (kstat_read(g_pKStatCtl, g_pUnixSysPages, NULL) != -1)
+ {
+ kstat_named_t *pData = (kstat_named_t *)kstat_data_lookup(g_pUnixSysPages, (char *)"physmem");
+ if (pData)
+ *pcb = (uint64_t)pData->value.ul * PAGE_SIZE;
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ RTCritSectLeave(&g_rtSysMemSolCritSect);
+ }
+ }
+ return rc;
+}
+
+
+RTDECL(int) RTSystemQueryAvailableRam(uint64_t *pcb)
+{
+ AssertPtrReturn(pcb, VERR_INVALID_POINTER);
+
+ int rc = RTOnceEx(&g_rtSysMemSolInitOnce, rtSysMemSolInit, rtSysMemSolCleanUp, NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTCritSectEnter(&g_rtSysMemSolCritSect);
+ if (RT_SUCCESS(rc))
+ {
+ if (kstat_read(g_pKStatCtl, g_pUnixSysPages, NULL) != -1)
+ {
+ kstat_named_t *pData = (kstat_named_t *)kstat_data_lookup(g_pUnixSysPages, (char *)"freemem");
+ if (pData)
+ {
+ *pcb = (uint64_t)pData->value.ul * PAGE_SIZE;
+
+ /*
+ * Adjust for ZFS greedyness if possible.
+ * (c_min is the target minimum size of the cache, it is not
+ * an absolute minimum.)
+ */
+ if ( g_pZfsArcStats
+ && kstat_read(g_pKStatCtl, g_pZfsArcStats, NULL) != -1)
+ {
+ kstat_named_t *pCurSize = (kstat_named_t *)kstat_data_lookup(g_pZfsArcStats, (char *)"size");
+ kstat_named_t *pMinSize = (kstat_named_t *)kstat_data_lookup(g_pZfsArcStats, (char *)"c_min");
+ if ( pCurSize
+ && pMinSize
+ && pCurSize->value.ul > pMinSize->value.ul)
+ {
+ *pcb += pCurSize->value.ul - pMinSize->value.ul;
+ }
+ }
+ }
+ else
+ rc = RTErrConvertFromErrno(errno);
+ }
+
+ RTCritSectLeave(&g_rtSysMemSolCritSect);
+ }
+ }
+ return rc;
+}
+
diff --git a/src/VBox/Runtime/r3/stream.cpp b/src/VBox/Runtime/r3/stream.cpp
index e220e5c7..d8b90ccb 100644
--- a/src/VBox/Runtime/r3/stream.cpp
+++ b/src/VBox/Runtime/r3/stream.cpp
@@ -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;
@@ -311,6 +311,7 @@ RTR3DECL(int) RTStrmOpen(const char *pszFilename, const char *pszMode, PRTSTREAM
pStream->i32Error = VINF_SUCCESS;
pStream->fCurrentCodeSet = false;
pStream->fBinary = fBinary;
+ pStream->fRecheckMode = false;
#ifndef HAVE_FWRITE_UNLOCKED
pStream->pCritSect = NULL;
#endif /* HAVE_FWRITE_UNLOCKED */
diff --git a/src/VBox/Runtime/r3/tcp.cpp b/src/VBox/Runtime/r3/tcp.cpp
index 151dee86..7c6b2ef4 100644
--- a/src/VBox/Runtime/r3/tcp.cpp
+++ b/src/VBox/Runtime/r3/tcp.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;
@@ -805,11 +805,19 @@ RTR3DECL(int) RTTcpServerDestroy(PRTTCPSERVER pServer)
RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
{
+ return RTTcpClientConnectEx(pszAddress, uPort, pSock, NULL);
+}
+
+
+RTR3DECL(int) RTTcpClientConnectEx(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock,
+ PRTTCPCLIENTCONNECTCANCEL volatile *ppCancelCookie)
+{
/*
* Validate input.
*/
AssertReturn(uPort > 0, VERR_INVALID_PARAMETER);
AssertPtrReturn(pszAddress, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(ppCancelCookie, VERR_INVALID_POINTER);
/*
* Resolve the address.
@@ -828,7 +836,25 @@ RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCK
{
RTSocketSetInheritance(Sock, false /*fInheritable*/);
- rc = rtSocketConnect(Sock, &Addr);
+ if (!ppCancelCookie)
+ rc = rtSocketConnect(Sock, &Addr);
+ else
+ {
+ RTSocketRetain(Sock);
+ if (ASMAtomicCmpXchgPtr(ppCancelCookie, (PRTTCPCLIENTCONNECTCANCEL)Sock, NULL))
+ {
+ rc = rtSocketConnect(Sock, &Addr);
+ if (ASMAtomicCmpXchgPtr(ppCancelCookie, NULL, (PRTTCPCLIENTCONNECTCANCEL)Sock))
+ RTSocketRelease(Sock);
+ else
+ rc = VERR_CANCELLED;
+ }
+ else
+ {
+ RTSocketRelease(Sock);
+ rc = VERR_CANCELLED;
+ }
+ }
if (RT_SUCCESS(rc))
{
*pSock = Sock;
@@ -837,10 +863,28 @@ RTR3DECL(int) RTTcpClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCK
rtTcpClose(Sock, "RTTcpClientConnect", false /*fTryGracefulShutdown*/);
}
+ if (ppCancelCookie)
+ *ppCancelCookie = NULL;
return rc;
}
+RTR3DECL(int) RTTcpClientCancelConnect(PRTTCPCLIENTCONNECTCANCEL volatile *ppCancelCookie)
+{
+ AssertPtrReturn(ppCancelCookie, VERR_INVALID_POINTER);
+
+ AssertCompile(NIL_RTSOCKET == NULL);
+ RTSOCKET hSock = (RTSOCKET)ASMAtomicXchgPtr((void * volatile *)ppCancelCookie, (void *)(uintptr_t)0xdead9999);
+ if (hSock != NIL_RTSOCKET)
+ {
+ int rc = rtTcpClose(hSock, "RTTcpClientCancelConnect", false /*fTryGracefulShutdown*/);
+ AssertRCReturn(rc, rc);
+ }
+
+ return VINF_SUCCESS;
+}
+
+
RTR3DECL(int) RTTcpClientClose(RTSOCKET Sock)
{
return rtTcpClose(Sock, "RTTcpClientClose", true /*fTryGracefulShutdown*/);
diff --git a/src/VBox/Runtime/r3/test.cpp b/src/VBox/Runtime/r3/test.cpp
index 6c9abcc3..5688dc6c 100644
--- a/src/VBox/Runtime/r3/test.cpp
+++ b/src/VBox/Runtime/r3/test.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 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;
@@ -91,6 +91,8 @@ typedef struct RTTESTINT
uint32_t cbGuard;
/** The verbosity level. */
RTTESTLVL enmMaxLevel;
+ /** The creation flags. */
+ uint32_t fFlags;
/** Critical section serializing output. */
@@ -111,6 +113,8 @@ typedef struct RTTESTINT
const char *pszSubTest;
/** The length of the sub-test name. */
size_t cchSubTest;
+ /** Whether the current subtest should figure as 'SKIPPED'. */
+ bool fSubTestSkipped;
/** Whether we've reported the sub-test result or not. */
bool fSubTestReported;
/** The start error count of the current subtest. */
@@ -123,6 +127,10 @@ typedef struct RTTESTINT
/** Set if XML output is enabled. */
bool fXmlEnabled;
+ /** Set if we omit the top level test in the XML report. */
+ bool fXmlOmitTopTest;
+ /** Set if we've reported the top test (for RTTEST_C_XML_DELAY_TOP_TEST). */
+ bool fXmlTopTestDone;
enum {
kXmlPos_ValueStart,
kXmlPos_Value,
@@ -185,8 +193,6 @@ static void rtTestXmlElemV(PRTTESTINT pTest, const char *pszTag, const char *psz
static void rtTestXmlElem(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...);
static void rtTestXmlElemStartV(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, va_list va);
static void rtTestXmlElemStart(PRTTESTINT pTest, const char *pszTag, const char *pszAttrFmt, ...);
-static void rtTestXmlElemValueV(PRTTESTINT pTest, const char *pszFormat, va_list va);
-static void rtTestXmlElemValue(PRTTESTINT pTest, const char *pszFormat, ...);
static void rtTestXmlElemEnd(PRTTESTINT pTest, const char *pszTag);
static void rtTestXmlEnd(PRTTESTINT pTest);
@@ -205,31 +211,28 @@ static RTTLS g_iTestTls = NIL_RTTLS;
* Init TLS index once.
*
* @returns IPRT status code.
- * @param pvUser1 Ignored.
- * @param pvUser2 Ignored.
+ * @param pvUser Ignored.
*/
-static DECLCALLBACK(int32_t) rtTestInitOnce(void *pvUser1, void *pvUser2)
+static DECLCALLBACK(int32_t) rtTestInitOnce(void *pvUser)
{
- NOREF(pvUser1);
- NOREF(pvUser2);
+ NOREF(pvUser);
return RTTlsAllocEx(&g_iTestTls, NULL);
}
-
-/**
- * Creates a test instance.
- *
- * @returns IPRT status code.
- * @param pszTest The test name.
- * @param phTest Where to store the test instance handle.
- */
-RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
+RTR3DECL(int) RTTestCreateEx(const char *pszTest, uint32_t fFlags, RTTESTLVL enmMaxLevel,
+ RTHCINTPTR iNativeTestPipe, const char *pszXmlFile, PRTTEST phTest)
{
+ AssertReturn(!(fFlags & ~RTTEST_C_VALID_MASK), VERR_INVALID_PARAMETER);
+ AssertPtrNull(phTest);
+ AssertPtrNull(pszXmlFile);
+ /* RTTESTLVL_INVALID is valid! */
+ AssertReturn(enmMaxLevel >= RTTESTLVL_INVALID && enmMaxLevel < RTTESTLVL_END, VERR_INVALID_PARAMETER);
+
/*
* Global init.
*/
- int rc = RTOnce(&g_TestInitOnce, rtTestInitOnce, NULL, NULL);
+ int rc = RTOnce(&g_TestInitOnce, rtTestInitOnce, NULL);
if (RT_FAILURE(rc))
return rc;
@@ -243,7 +246,8 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
pTest->pszTest = RTStrDup(pszTest);
pTest->cchTest = strlen(pszTest);
pTest->cbGuard = PAGE_SIZE * 7;
- pTest->enmMaxLevel = RTTESTLVL_SUB_TEST;
+ pTest->enmMaxLevel = enmMaxLevel == RTTESTLVL_INVALID ? RTTESTLVL_INFO : enmMaxLevel;
+ pTest->fFlags = fFlags;
pTest->pOutStrm = g_pStdOut;
pTest->fNewLine = true;
@@ -252,12 +256,14 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
pTest->pszSubTest = NULL;
pTest->cchSubTest = 0;
+ pTest->fSubTestSkipped = false;
pTest->fSubTestReported = true;
pTest->cSubTestAtErrors = 0;
pTest->cSubTests = 0;
pTest->cSubTestsFailed = 0;
pTest->fXmlEnabled = false;
+ pTest->fXmlTopTestDone = false;
pTest->eXmlState = RTTESTINT::kXmlPos_ElementEnd;
pTest->hXmlPipe = NIL_RTPIPE;
pTest->hXmlFile = NIL_RTFILE;
@@ -273,82 +279,109 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
* Associate it with our TLS entry unless there is already
* an instance there.
*/
- if (!RTTlsGet(g_iTestTls))
+ if ( !(fFlags & RTTEST_C_NO_TLS)
+ && !RTTlsGet(g_iTestTls))
rc = RTTlsSet(g_iTestTls, pTest);
if (RT_SUCCESS(rc))
{
/*
- * Pick up overrides from the environment.
+ * Output level override?
*/
char szEnvVal[RTPATH_MAX];
- rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_MAX_LEVEL", szEnvVal, sizeof(szEnvVal), NULL);
- if (RT_SUCCESS(rc))
+ if ((fFlags & RTTEST_C_USE_ENV) && enmMaxLevel == RTTESTLVL_INVALID)
{
- char *pszMaxLevel = RTStrStrip(szEnvVal);
- if (!strcmp(pszMaxLevel, "all"))
- pTest->enmMaxLevel = RTTESTLVL_DEBUG;
- if (!strcmp(pszMaxLevel, "quiet"))
- pTest->enmMaxLevel = RTTESTLVL_FAILURE;
- else if (!strcmp(pszMaxLevel, "debug"))
- pTest->enmMaxLevel = RTTESTLVL_DEBUG;
- else if (!strcmp(pszMaxLevel, "info"))
- pTest->enmMaxLevel = RTTESTLVL_INFO;
- else if (!strcmp(pszMaxLevel, "sub_test"))
- pTest->enmMaxLevel = RTTESTLVL_SUB_TEST;
- else if (!strcmp(pszMaxLevel, "failure"))
- pTest->enmMaxLevel = RTTESTLVL_FAILURE;
+ rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_MAX_LEVEL", szEnvVal, sizeof(szEnvVal), NULL);
+ if (RT_SUCCESS(rc))
+ {
+ char *pszMaxLevel = RTStrStrip(szEnvVal);
+ if (!strcmp(pszMaxLevel, "all"))
+ pTest->enmMaxLevel = RTTESTLVL_DEBUG;
+ if (!strcmp(pszMaxLevel, "quiet"))
+ pTest->enmMaxLevel = RTTESTLVL_FAILURE;
+ else if (!strcmp(pszMaxLevel, "debug"))
+ pTest->enmMaxLevel = RTTESTLVL_DEBUG;
+ else if (!strcmp(pszMaxLevel, "info"))
+ pTest->enmMaxLevel = RTTESTLVL_INFO;
+ else if (!strcmp(pszMaxLevel, "sub_test"))
+ pTest->enmMaxLevel = RTTESTLVL_SUB_TEST;
+ else if (!strcmp(pszMaxLevel, "failure"))
+ pTest->enmMaxLevel = RTTESTLVL_FAILURE;
+ }
+ else if (rc != VERR_ENV_VAR_NOT_FOUND)
+ RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_MAX_LEVEL) -> %Rrc\n", pszTest, rc);
}
/*
* Any test driver we are connected or should connect to?
*/
- rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_PIPE", szEnvVal, sizeof(szEnvVal), NULL);
- if (RT_SUCCESS(rc))
+ if ((fFlags & RTTEST_C_USE_ENV) && iNativeTestPipe == -1)
{
- RTHCINTPTR hNative = -1;
+ rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_PIPE", szEnvVal, sizeof(szEnvVal), NULL);
+ if (RT_SUCCESS(rc))
+ {
#if ARCH_BITS == 64
- rc = RTStrToInt64Full(szEnvVal, 0, &hNative);
+ rc = RTStrToInt64Full(szEnvVal, 0, &iNativeTestPipe);
#else
- rc = RTStrToInt32Full(szEnvVal, 0, &hNative);
+ rc = RTStrToInt32Full(szEnvVal, 0, &iNativeTestPipe);
#endif
- if (RT_SUCCESS(rc))
- {
- rc = RTPipeFromNative(&pTest->hXmlPipe, hNative, RTPIPE_N_WRITE);
- if (RT_SUCCESS(rc))
- pTest->fXmlEnabled = true;
- else
+ if (RT_FAILURE(rc))
{
- RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTPipeFromNative(,\"%s\",WRITE) -> %Rrc\n", pszTest, szEnvVal, rc);
- pTest->hXmlPipe = NIL_RTPIPE;
+ RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTStrToInt32Full(\"%s\") -> %Rrc\n",
+ pszTest, szEnvVal, rc);
+ iNativeTestPipe = -1;
}
}
+ else if (rc != VERR_ENV_VAR_NOT_FOUND)
+ RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_PIPE) -> %Rrc\n", pszTest, rc);
+ }
+ if (iNativeTestPipe != -1)
+ {
+ rc = RTPipeFromNative(&pTest->hXmlPipe, iNativeTestPipe, RTPIPE_N_WRITE);
+ if (RT_SUCCESS(rc))
+ pTest->fXmlEnabled = true;
else
- RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTStrToInt32Full(\"%s\") -> %Rrc\n", pszTest, szEnvVal, rc);
+ {
+ RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTPipeFromNative(,%p,WRITE) -> %Rrc\n",
+ pszTest, iNativeTestPipe, rc);
+ pTest->hXmlPipe = NIL_RTPIPE;
+ }
}
- else if (rc != VERR_ENV_VAR_NOT_FOUND)
- RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_PIPE) -> %Rrc\n", pszTest, rc);
/*
* Any test file we should write the test report to?
*/
- rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_FILE", szEnvVal, sizeof(szEnvVal), NULL);
- if (RT_SUCCESS(rc))
+ if ((fFlags & RTTEST_C_USE_ENV) && pszXmlFile == NULL)
{
- rc = RTFileOpen(&pTest->hXmlFile, szEnvVal, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE_REPLACE);
+ rc = RTEnvGetEx(RTENV_DEFAULT, "IPRT_TEST_FILE", szEnvVal, sizeof(szEnvVal), NULL);
+ if (RT_SUCCESS(rc))
+ pszXmlFile = szEnvVal;
+ else if (rc != VERR_ENV_VAR_NOT_FOUND)
+ RTStrmPrintf(g_pStdErr, "%s: test pipe error: RTEnvGetEx(IPRT_TEST_MAX_LEVEL) -> %Rrc\n", pszTest, rc);
+ }
+ if (pszXmlFile && *pszXmlFile)
+ {
+ rc = RTFileOpen(&pTest->hXmlFile, pszXmlFile,
+ RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_TRUNCATE);
if (RT_SUCCESS(rc))
pTest->fXmlEnabled = true;
else
{
- RTStrmPrintf(g_pStdErr, "%s: test file error: RTFileOpen(,\"%s\",) -> %Rrc\n", pszTest, szEnvVal, rc);
+ RTStrmPrintf(g_pStdErr, "%s: test file error: RTFileOpen(,\"%s\",) -> %Rrc\n", pszTest, pszXmlFile, rc);
pTest->hXmlFile = NIL_RTFILE;
}
}
else if (rc != VERR_ENV_VAR_NOT_FOUND)
RTStrmPrintf(g_pStdErr, "%s: test file error: RTEnvGetEx(IPRT_TEST_FILE) -> %Rrc\n", pszTest, rc);
+ /*
+ * What do we report in the XML stream/file.?
+ */
+ pTest->fXmlOmitTopTest = (fFlags & RTTEST_C_XML_OMIT_TOP_TEST)
+ || ( (fFlags & RTTEST_C_USE_ENV)
+ && RTEnvExistEx(RTENV_DEFAULT, "IPRT_TEST_OMIT_TOP_TEST"));
/*
- * Tell the test driver that we're up.
+ * Tell the test driver that we're up to.
*/
rtTestXmlStart(pTest, pszTest);
@@ -368,6 +401,12 @@ RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
}
+RTR3DECL(int) RTTestCreate(const char *pszTest, PRTTEST phTest)
+{
+ return RTTestCreateEx(pszTest, RTTEST_C_USE_ENV, RTTESTLVL_INVALID, -1 /*iNativeTestPipe*/, NULL /*pszXmlFile*/, phTest);
+}
+
+
RTR3DECL(RTEXITCODE) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest)
{
int rc = RTR3InitExeNoArguments(0);
@@ -376,6 +415,30 @@ RTR3DECL(RTEXITCODE) RTTestInitAndCreate(const char *pszTest, PRTTEST phTest)
RTStrmPrintf(g_pStdErr, "%s: fatal error: RTR3InitExeNoArguments failed with rc=%Rrc\n", pszTest, rc);
return RTEXITCODE_INIT;
}
+
+ rc = RTTestCreate(pszTest, phTest);
+ if (RT_FAILURE(rc))
+ {
+ RTStrmPrintf(g_pStdErr, "%s: fatal error: RTTestCreate failed with rc=%Rrc\n", pszTest, rc);
+ return RTEXITCODE_INIT;
+ }
+ return RTEXITCODE_SUCCESS;
+}
+
+
+RTR3DECL(RTEXITCODE) RTTestInitExAndCreate(int cArgs, char ***papszArgs, uint32_t fRtInit, const char *pszTest, PRTTEST phTest)
+{
+ int rc;
+ if (cArgs <= 0 && papszArgs == NULL)
+ rc = RTR3InitExeNoArguments(fRtInit);
+ else
+ rc = RTR3InitExe(cArgs, papszArgs, fRtInit);
+ if (RT_FAILURE(rc))
+ {
+ RTStrmPrintf(g_pStdErr, "%s: fatal error: RTR3InitExe(,,%#x) failed with rc=%Rrc\n", pszTest, fRtInit, rc);
+ return RTEXITCODE_INIT;
+ }
+
rc = RTTestCreate(pszTest, phTest);
if (RT_FAILURE(rc))
{
@@ -454,6 +517,34 @@ RTR3DECL(int) RTTestSetDefault(RTTEST hNewDefaultTest, PRTTEST phOldTest)
}
+RTR3DECL(int) RTTestChangeName(RTTEST hTest, const char *pszName)
+{
+ PRTTESTINT pTest = hTest;
+ RTTEST_GET_VALID_RETURN(pTest);
+ AssertPtrReturn(pszName, VERR_INVALID_POINTER);
+ AssertReturn(*pszName, VERR_INVALID_PARAMETER);
+
+ size_t cchName = strlen(pszName);
+ AssertReturn(cchName < 128, VERR_INVALID_PARAMETER);
+ char *pszDupName = RTStrDup(pszName);
+ if (!pszDupName)
+ return VERR_NO_STR_MEMORY;
+
+ RTCritSectEnter(&pTest->Lock);
+ RTCritSectEnter(&pTest->OutputLock);
+
+ char *pszOldName = (char *)pTest->pszTest;
+ pTest->pszTest = pszDupName;
+ pTest->cchTest = cchName;
+
+ RTCritSectLeave(&pTest->OutputLock);
+ RTCritSectLeave(&pTest->Lock);
+
+ RTStrFree(pszOldName);
+ return VINF_SUCCESS;
+}
+
+
/**
* Allocate a block of guarded memory.
*
@@ -683,7 +774,9 @@ static void rtTestXmlStart(PRTTESTINT pTest, const char *pszTest)
{
rtTestXmlOutput(pTest, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
pTest->eXmlState = RTTESTINT::kXmlPos_ElementEnd;
- rtTestXmlElemStart(pTest, "Test", "name=%RMas", pszTest);
+ pTest->fXmlTopTestDone = !(pTest->fFlags & RTTEST_C_XML_DELAY_TOP_TEST) || pTest->fXmlOmitTopTest;
+ if (pTest->fXmlTopTestDone && !pTest->fXmlOmitTopTest)
+ rtTestXmlElemStart(pTest, "Test", "name=%RMas", pszTest);
}
}
@@ -795,43 +888,6 @@ static void rtTestXmlElemStart(PRTTESTINT pTest, const char *pszTag, const char
/**
- * Writes an element value, or a part of one, taking care of all the escaping.
- *
- * The caller must own the instance lock.
- *
- * @param pTest The test instance.
- * @param pszFormat The value format string.
- * @param va The format arguments.
- */
-static void rtTestXmlElemValueV(PRTTESTINT pTest, const char *pszFormat, va_list va)
-{
- if (pTest->fXmlEnabled)
- {
- char *pszValue;
- RTStrAPrintfV(&pszValue, pszFormat, va);
- if (pszValue)
- {
- rtTestXmlOutput(pTest, "%RMes", pszValue);
- RTStrFree(pszValue);
- }
- pTest->eXmlState = RTTESTINT::kXmlPos_Value;
- }
-}
-
-
-/**
- * Wrapper around rtTestXmlElemValueV.
- */
-static void rtTestXmlElemValue(PRTTESTINT pTest, const char *pszFormat, ...)
-{
- va_list va;
- va_start(va, pszFormat);
- rtTestXmlElemValueV(pTest, pszFormat, va);
- va_end(va);
-}
-
-
-/**
* Ends the current element.
*
* The caller must own the instance lock.
@@ -879,7 +935,7 @@ static void rtTestXmlEnd(PRTTESTINT pTest)
* final timestamp and some certainty that the XML is valid.
*/
size_t i = pTest->cXmlElements;
- AssertReturnVoid(i > 0);
+ AssertReturnVoid(i > 0 || pTest->fXmlOmitTopTest || !pTest->fXmlTopTestDone);
while (i-- > 1)
{
const char *pszTag = pTest->apszXmlElements[pTest->cXmlElements];
@@ -891,9 +947,13 @@ static void rtTestXmlEnd(PRTTESTINT pTest)
rtTestXmlOutput(pTest, "</%s>\n", pszTag);
pTest->eXmlState = RTTESTINT::kXmlPos_ElementEnd;
}
- rtTestXmlElem(pTest, "End", "SubTests=\"%u\" SubTestsFailed=\"%u\" errors=\"%u\"",
- pTest->cSubTests, pTest->cSubTestsFailed, pTest->cErrors);
- rtTestXmlOutput(pTest, "</Test>\n");
+
+ if (!pTest->fXmlOmitTopTest && pTest->fXmlTopTestDone)
+ {
+ rtTestXmlElem(pTest, "End", "SubTests=\"%u\" SubTestsFailed=\"%u\" errors=\"%u\"",
+ pTest->cSubTests, pTest->cSubTestsFailed, pTest->cErrors);
+ rtTestXmlOutput(pTest, "</Test>\n");
+ }
/*
* Close the XML outputs.
@@ -1130,15 +1190,24 @@ static int rtTestSubTestReport(PRTTESTINT pTest)
uint32_t cErrors = ASMAtomicUoReadU32(&pTest->cErrors) - pTest->cSubTestAtErrors;
if (!cErrors)
{
- rtTestXmlElem(pTest, "Passed", NULL);
- rtTestXmlElemEnd(pTest, "SubTest");
- cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: PASSED\n", pTest->pszSubTest);
+ if (!pTest->fSubTestSkipped)
+ {
+ rtTestXmlElem(pTest, "Passed", NULL);
+ rtTestXmlElemEnd(pTest, "Test");
+ cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: PASSED\n", pTest->pszSubTest);
+ }
+ else
+ {
+ rtTestXmlElem(pTest, "Skipped", NULL);
+ rtTestXmlElemEnd(pTest, "Test");
+ cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: SKIPPED\n", pTest->pszSubTest);
+ }
}
else
{
pTest->cSubTestsFailed++;
rtTestXmlElem(pTest, "Failed", "errors=\"%u\"", cErrors);
- rtTestXmlElemEnd(pTest, "SubTest");
+ rtTestXmlElemEnd(pTest, "Test");
cch += RTTestPrintfNl(pTest, RTTESTLVL_SUB_TEST, "%-50s: FAILED (%u errors)\n",
pTest->pszSubTest, cErrors);
}
@@ -1267,13 +1336,20 @@ RTR3DECL(int) RTTestSub(RTTEST hTest, const char *pszSubTest)
pTest->cSubTestAtErrors = ASMAtomicUoReadU32(&pTest->cErrors);
pTest->pszSubTest = RTStrDup(pszSubTest);
pTest->cchSubTest = strlen(pszSubTest);
+ pTest->fSubTestSkipped = false;
pTest->fSubTestReported = false;
int cch = 0;
if (pTest->enmMaxLevel >= RTTESTLVL_DEBUG)
cch = RTTestPrintfNl(hTest, RTTESTLVL_DEBUG, "debug: Starting sub-test '%s'\n", pszSubTest);
- rtTestXmlElemStart(pTest, "SubTest", "name=%RMas", pszSubTest);
+ if (!pTest->fXmlTopTestDone)
+ {
+ pTest->fXmlTopTestDone = true;
+ rtTestXmlElemStart(pTest, "Test", "name=%RMas", pTest->pszTest);
+ }
+
+ rtTestXmlElemStart(pTest, "Test", "name=%RMas", pszSubTest);
RTCritSectLeave(&pTest->Lock);
@@ -1337,7 +1413,7 @@ RTR3DECL(int) RTTestSubV(RTTEST hTest, const char *pszSubTestFmt, va_list va)
RTR3DECL(int) RTTestSubDone(RTTEST hTest)
{
PRTTESTINT pTest = hTest;
- RTTEST_GET_VALID_RETURN_RC(pTest, -1);
+ RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE);
RTCritSectEnter(&pTest->Lock);
int cch = rtTestSubCleanup(pTest);
@@ -1361,7 +1437,8 @@ RTR3DECL(int) RTTestSubDone(RTTEST hTest)
RTR3DECL(int) RTTestPassedV(RTTEST hTest, const char *pszFormat, va_list va)
{
PRTTESTINT pTest = hTest;
- RTTEST_GET_VALID_RETURN_RC(pTest, -1);
+ AssertPtr(pszFormat);
+ RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE);
int cch = 0;
if (pTest->enmMaxLevel >= RTTESTLVL_INFO)
@@ -1404,6 +1481,44 @@ RTR3DECL(int) RTTestPassed(RTTEST hTest, const char *pszFormat, ...)
}
+RTR3DECL(int) RTTestSkippedV(RTTEST hTest, const char *pszFormat, va_list va)
+{
+ PRTTESTINT pTest = hTest;
+ AssertPtrNull(pszFormat);
+ RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE);
+
+ pTest->fSubTestSkipped = true;
+
+ int cch = 0;
+ if (pszFormat && *pszFormat && pTest->enmMaxLevel >= RTTESTLVL_INFO)
+ {
+ va_list va2;
+ va_copy(va2, va);
+
+ RTCritSectEnter(&pTest->OutputLock);
+ cch += rtTestPrintf(pTest, "%N\n", pszFormat, &va2);
+ RTCritSectLeave(&pTest->OutputLock);
+
+ va_end(va2);
+ }
+
+ return cch;
+}
+
+
+RTR3DECL(int) RTTestSkipped(RTTEST hTest, const char *pszFormat, ...)
+{
+ va_list va;
+
+ va_start(va, pszFormat);
+ int cch = RTTestSkippedV(hTest, pszFormat, va);
+ va_end(va);
+
+ return cch;
+}
+
+
+
/**
* Gets the unit name.
*
@@ -1438,6 +1553,13 @@ static const char *rtTestUnitName(RTTESTUNIT enmUnit)
case RTTESTUNIT_NS_PER_OCCURRENCE: return "ns/occurrences";
case RTTESTUNIT_NS_PER_PACKET: return "ns/packet";
case RTTESTUNIT_NS_PER_ROUND_TRIP: return "ns/roundtrips";
+ case RTTESTUNIT_INSTRS: return "ins";
+ case RTTESTUNIT_INSTRS_PER_SEC: return "ins/sec";
+ case RTTESTUNIT_NONE: return "";
+ case RTTESTUNIT_PP1K: return "pp1k";
+ case RTTESTUNIT_PP10K: return "pp10k";
+ case RTTESTUNIT_PPM: return "ppm";
+ case RTTESTUNIT_PPB: return "ppb";
/* No default so gcc helps us keep this up to date. */
case RTTESTUNIT_INVALID:
@@ -1457,9 +1579,7 @@ RTR3DECL(int) RTTestValue(RTTEST hTest, const char *pszName, uint64_t u64Value,
const char *pszUnit = rtTestUnitName(enmUnit);
RTCritSectEnter(&pTest->Lock);
- rtTestXmlElemStart(pTest, "Value", "name=%RMas unit=%RMas", pszName, pszUnit);
- rtTestXmlElemValue(pTest, "%llu", u64Value);
- rtTestXmlElemEnd(pTest, "Value");
+ rtTestXmlElem(pTest, "Value", "name=%RMas unit=%RMas value=\"%llu\"", pszName, pszUnit, u64Value);
RTCritSectLeave(&pTest->Lock);
RTCritSectEnter(&pTest->OutputLock);
@@ -1510,6 +1630,7 @@ RTR3DECL(int) RTTestErrorInc(RTTEST hTest)
}
+
/**
* Get the current error count.
*
@@ -1526,6 +1647,15 @@ RTR3DECL(uint32_t) RTTestErrorCount(RTTEST hTest)
}
+RTR3DECL(uint32_t) RTTestSubErrorCount(RTTEST hTest)
+{
+ PRTTESTINT pTest = hTest;
+ RTTEST_GET_VALID_RETURN_RC(pTest, UINT32_MAX);
+
+ return ASMAtomicReadU32(&pTest->cErrors) - pTest->cSubTestAtErrors;
+}
+
+
/**
* Increments the error counter and prints a failure message.
*
@@ -1538,7 +1668,7 @@ RTR3DECL(uint32_t) RTTestErrorCount(RTTEST hTest)
RTR3DECL(int) RTTestFailedV(RTTEST hTest, const char *pszFormat, va_list va)
{
PRTTESTINT pTest = hTest;
- RTTEST_GET_VALID_RETURN_RC(pTest, -1);
+ RTTEST_GET_VALID_RETURN_RC(pTest, VERR_INVALID_HANDLE);
RTTestErrorInc(pTest);
diff --git a/src/VBox/Runtime/r3/testi.cpp b/src/VBox/Runtime/r3/testi.cpp
index e143e3c1..b0c78828 100644
--- a/src/VBox/Runtime/r3/testi.cpp
+++ b/src/VBox/Runtime/r3/testi.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-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/udp.cpp b/src/VBox/Runtime/r3/udp.cpp
index a5a2cc22..5e46b959 100644
--- a/src/VBox/Runtime/r3/udp.cpp
+++ b/src/VBox/Runtime/r3/udp.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;
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;
diff --git a/src/VBox/Runtime/r3/xml.cpp b/src/VBox/Runtime/r3/xml.cpp
index a753f34c..708e41fb 100644
--- a/src/VBox/Runtime/r3/xml.cpp
+++ b/src/VBox/Runtime/r3/xml.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2007-2011 Oracle Corporation
+ * Copyright (C) 2007-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;
@@ -24,6 +24,10 @@
* terms and conditions of either the GPL or the CDDL or both.
*/
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
#include <iprt/dir.h>
#include <iprt/file.h>
#include <iprt/err.h>
@@ -42,14 +46,11 @@
#include <libxml/xmlschemas.h>
#include <map>
-#include <boost/shared_ptr.hpp>
-////////////////////////////////////////////////////////////////////////////////
-//
-// globals
-//
-////////////////////////////////////////////////////////////////////////////////
+/*******************************************************************************
+* Global Variables *
+*******************************************************************************/
/**
* Global module initialization structure. This is to wrap non-reentrant bits
* of libxml, among other things.
@@ -58,8 +59,7 @@
* module initialization and cleanup. There must be only one global variable of
* this structure.
*/
-static
-class Global
+static class Global
{
public:
@@ -93,8 +93,7 @@ public:
RTCLockMtx lock;
}
sxml; /* XXX naming this xml will break with gcc-3.3 */
-}
-gGlobal;
+} gGlobal;
@@ -131,8 +130,7 @@ XmlError::XmlError(xmlErrorPtr aErr)
* Composes a single message for the given error. The caller must free the
* returned string using RTStrFree() when no more necessary.
*/
-// static
-char *XmlError::Format(xmlErrorPtr aErr)
+/* static */ char *XmlError::Format(xmlErrorPtr aErr)
{
const char *msg = aErr->message ? aErr->message : "<none>";
size_t msgLen = strlen(msg);
@@ -156,7 +154,7 @@ EIPRTFailure::EIPRTFailure(int aRC, const char *pcszContext, ...)
va_start(args, pcszContext);
RTStrAPrintfV(&pszContext2, pcszContext, args);
char *newMsg;
- RTStrAPrintf(&newMsg, "%s: %d (%s)", pszContext2, aRC, RTErrGetShort(aRC));
+ RTStrAPrintf(&newMsg, "%s: %d(%s)", pszContext2, aRC, RTErrGetShort(aRC));
setWhat(newMsg);
RTStrFree(newMsg);
RTStrFree(pszContext2);
@@ -241,7 +239,7 @@ File::~File()
delete m;
}
-const char* File::uri() const
+const char *File::uri() const
{
return m->strFileName.c_str();
}
@@ -291,19 +289,17 @@ int File::read(char *aBuf, int aLen)
int File::write(const char *aBuf, int aLen)
{
size_t len = aLen;
- int vrc = RTFileWrite (m->handle, aBuf, len, &len);
- if (RT_SUCCESS (vrc))
+ int vrc = RTFileWrite(m->handle, aBuf, len, &len);
+ if (RT_SUCCESS(vrc))
return (int)len;
throw EIPRTFailure(vrc, "Runtime error writing to file '%s'", m->strFileName.c_str());
-
- return -1 /* failure */;
}
void File::truncate()
{
- int vrc = RTFileSetSize (m->handle, pos());
- if (RT_SUCCESS (vrc))
+ int vrc = RTFileSetSize(m->handle, pos());
+ if (RT_SUCCESS(vrc))
return;
throw EIPRTFailure(vrc, "Runtime error truncating file '%s'", m->strFileName.c_str());
@@ -318,7 +314,7 @@ void File::truncate()
struct MemoryBuf::Data
{
Data()
- : buf (NULL), len (0), uri (NULL), pos (0) {}
+ : buf(NULL), len(0), uri(NULL), pos(0) {}
const char *buf;
size_t len;
@@ -327,20 +323,20 @@ struct MemoryBuf::Data
size_t pos;
};
-MemoryBuf::MemoryBuf (const char *aBuf, size_t aLen, const char *aURI /* = NULL */)
- : m (new Data())
+MemoryBuf::MemoryBuf(const char *aBuf, size_t aLen, const char *aURI /* = NULL */)
+ : m(new Data())
{
if (aBuf == NULL)
- throw EInvalidArg (RT_SRC_POS);
+ throw EInvalidArg(RT_SRC_POS);
m->buf = aBuf;
m->len = aLen;
- m->uri = RTStrDup (aURI);
+ m->uri = RTStrDup(aURI);
}
MemoryBuf::~MemoryBuf()
{
- RTStrFree (m->uri);
+ RTStrFree(m->uri);
}
const char *MemoryBuf::uri() const
@@ -353,9 +349,9 @@ uint64_t MemoryBuf::pos() const
return m->pos;
}
-void MemoryBuf::setPos (uint64_t aPos)
+void MemoryBuf::setPos(uint64_t aPos)
{
- size_t off = (size_t) aPos;
+ size_t off = (size_t)aPos;
if ((uint64_t) off != aPos)
throw EInvalidArg();
@@ -365,13 +361,13 @@ void MemoryBuf::setPos (uint64_t aPos)
m->pos = off;
}
-int MemoryBuf::read (char *aBuf, int aLen)
+int MemoryBuf::read(char *aBuf, int aLen)
{
if (m->pos >= m->len)
return 0 /* nothing to read */;
size_t len = m->pos + aLen < m->len ? aLen : m->len - m->pos;
- memcpy (aBuf, m->buf + m->pos, len);
+ memcpy(aBuf, m->buf + m->pos, len);
m->pos += len;
return (int)len;
@@ -422,90 +418,43 @@ xmlParserInput* GlobalLock::callDefaultLoader(const char *aURI,
return gGlobal.sxml.defaultEntityLoader(aURI, aID, aCtxt);
}
+
+
////////////////////////////////////////////////////////////////////////////////
//
// Node class
//
////////////////////////////////////////////////////////////////////////////////
-struct Node::Data
-{
- struct compare_const_char
- {
- bool operator()(const char* s1, const char* s2) const
- {
- return strcmp(s1, s2) < 0;
- }
- };
-
- // attributes, if this is an element; can be empty
- typedef std::map<const char*, boost::shared_ptr<AttributeNode>, compare_const_char > AttributesMap;
- AttributesMap attribs;
-
- // child elements, if this is an element; can be empty
- typedef std::list< boost::shared_ptr<Node> > InternalNodesList;
- InternalNodesList children;
-};
-
Node::Node(EnumType type,
Node *pParent,
- xmlNode *plibNode,
- xmlAttr *plibAttr)
- : m_Type(type),
- m_pParent(pParent),
- m_plibNode(plibNode),
- m_plibAttr(plibAttr),
- m_pcszNamespacePrefix(NULL),
- m_pcszNamespaceHref(NULL),
- m_pcszName(NULL),
- m(new Data)
+ PRTLISTANCHOR pListAnchor,
+ xmlNode *pLibNode,
+ xmlAttr *pLibAttr)
+ : m_Type(type)
+ , m_pParent(pParent)
+ , m_pLibNode(pLibNode)
+ , m_pLibAttr(pLibAttr)
+ , m_pcszNamespacePrefix(NULL)
+ , m_pcszNamespaceHref(NULL)
+ , m_pcszName(NULL)
+ , m_pParentListAnchor(pListAnchor)
{
+ RTListInit(&m_listEntry);
}
Node::~Node()
{
- delete m;
}
/**
- * Private implementation.
- * @param elmRoot
+ * Returns the name of the node, which is either the element name or
+ * the attribute name. For other node types it probably returns NULL.
+ * @return
*/
-void Node::buildChildren(const ElementNode &elmRoot) // private
+const char *Node::getName() const
{
- // go thru this element's attributes
- xmlAttr *plibAttr = m_plibNode->properties;
- while (plibAttr)
- {
- const char *pcszKey;
- boost::shared_ptr<AttributeNode> pNew(new AttributeNode(elmRoot, this, plibAttr, &pcszKey));
- // store
- m->attribs[pcszKey] = pNew;
-
- plibAttr = plibAttr->next;
- }
-
- // go thru this element's child elements
- xmlNodePtr plibNode = m_plibNode->children;
- while (plibNode)
- {
- boost::shared_ptr<Node> pNew;
-
- if (plibNode->type == XML_ELEMENT_NODE)
- pNew = boost::shared_ptr<Node>(new ElementNode(&elmRoot, this, plibNode));
- else if (plibNode->type == XML_TEXT_NODE)
- pNew = boost::shared_ptr<Node>(new ContentNode(this, plibNode));
- if (pNew)
- {
- // store
- m->children.push_back(pNew);
-
- // recurse for this child element to get its own children
- pNew->buildChildren(elmRoot);
- }
-
- plibNode = plibNode->next;
- }
+ return m_pcszName;
}
/**
@@ -513,9 +462,19 @@ void Node::buildChildren(const ElementNode &elmRoot) // private
* the attribute name. For other node types it probably returns NULL.
* @return
*/
-const char* Node::getName() const
+const char *Node::getPrefix() const
{
- return m_pcszName;
+ return m_pcszNamespacePrefix;
+}
+
+/**
+ * Returns the XML namespace URI, which is the attribute name. For other node types it probably
+ * returns NULL.
+ * @return
+ */
+const char *Node::getNamespaceURI() const
+{
+ return m_pcszNamespaceHref;
}
/**
@@ -524,7 +483,7 @@ const char* Node::getName() const
* @param pcsz
* @return
*/
-bool Node::nameEquals(const char *pcszNamespace, const char *pcsz) const
+bool Node::nameEqualsNS(const char *pcszNamespace, const char *pcsz) const
{
if (m_pcszName == pcsz)
return true;
@@ -546,24 +505,52 @@ bool Node::nameEquals(const char *pcszNamespace, const char *pcsz) const
}
/**
+ * Variant of nameEquals that checks the namespace as well.
+ *
+ * @returns true if equal, false if not.
+ * @param pcsz The element name.
+ * @param cchMax The maximum number of character from @a pcsz to
+ * match.
+ * @param pcszNamespace The name space prefix or NULL (default).
+ */
+bool Node::nameEqualsN(const char *pcsz, size_t cchMax, const char *pcszNamespace /* = NULL*/) const
+{
+ /* Match the name. */
+ if (!m_pcszName)
+ return false;
+ if (!pcsz || cchMax == 0)
+ return false;
+ if (strncmp(m_pcszName, pcsz, cchMax))
+ return false;
+ if (strlen(m_pcszName) > cchMax)
+ return false;
+
+ /* Match name space. */
+ if (!pcszNamespace)
+ return true; /* NULL, anything goes. */
+ if (!m_pcszNamespacePrefix)
+ return false; /* Element has no namespace. */
+ return !strcmp(m_pcszNamespacePrefix, pcszNamespace);
+}
+
+/**
* Returns the value of a node. If this node is an attribute, returns
* the attribute value; if this node is an element, then this returns
* the element text content.
* @return
*/
-const char* Node::getValue() const
+const char *Node::getValue() const
{
- if ( (m_plibAttr)
- && (m_plibAttr->children)
- )
+ if ( m_pLibAttr
+ && m_pLibAttr->children
+ )
// libxml hides attribute values in another node created as a
// single child of the attribute node, and it's in the content field
- return (const char*)m_plibAttr->children->content;
+ return (const char *)m_pLibAttr->children->content;
- if ( (m_plibNode)
- && (m_plibNode->children)
- )
- return (const char*)m_plibNode->children->content;
+ if ( m_pLibNode
+ && m_pLibNode->children)
+ return (const char *)m_pLibNode->children->content;
return NULL;
}
@@ -643,39 +630,132 @@ bool Node::copyValue(uint64_t &i) const
*/
int Node::getLineNumber() const
{
- if (m_plibAttr)
- return m_pParent->m_plibNode->line;
+ if (m_pLibAttr)
+ return m_pParent->m_pLibNode->line;
- return m_plibNode->line;
+ return m_pLibNode->line;
}
/**
* Private element constructor.
- * @param pelmRoot
- * @param pParent
- * @param plibNode
+ *
+ * @param pElmRoot Pointer to the root element.
+ * @param pParent Pointer to the parent element (always an ElementNode,
+ * despite the type). NULL for the root node.
+ * @param pListAnchor Pointer to the m_children member of the parent. NULL
+ * for the root node.
+ * @param pLibNode Pointer to the libxml2 node structure.
*/
-ElementNode::ElementNode(const ElementNode *pelmRoot,
+ElementNode::ElementNode(const ElementNode *pElmRoot,
Node *pParent,
- xmlNode *plibNode)
+ PRTLISTANCHOR pListAnchor,
+ xmlNode *pLibNode)
: Node(IsElement,
pParent,
- plibNode,
+ pListAnchor,
+ pLibNode,
NULL)
{
- if (!(m_pelmRoot = pelmRoot))
- // NULL passed, then this is the root element
- m_pelmRoot = this;
+ m_pElmRoot = pElmRoot ? pElmRoot : this; // If NULL is passed, then this is the root element.
+ m_pcszName = (const char *)pLibNode->name;
- m_pcszName = (const char*)plibNode->name;
+ if (pLibNode->ns)
+ {
+ m_pcszNamespacePrefix = (const char *)m_pLibNode->ns->prefix;
+ m_pcszNamespaceHref = (const char *)m_pLibNode->ns->href;
+ }
- if (plibNode->ns)
+ RTListInit(&m_children);
+ RTListInit(&m_attributes);
+}
+
+ElementNode::~ElementNode()
+{
+ Node *pCur, *pNext;
+ RTListForEachSafeCpp(&m_children, pCur, pNext, Node, m_listEntry)
{
- m_pcszNamespacePrefix = (const char*)m_plibNode->ns->prefix;
- m_pcszNamespaceHref = (const char*)m_plibNode->ns->href;
+ delete pCur;
}
+ RTListInit(&m_children);
+
+ RTListForEachSafeCpp(&m_attributes, pCur, pNext, Node, m_listEntry)
+ {
+ delete pCur;
+ }
+ RTListInit(&m_attributes);
}
+
+/**
+ * Gets the next tree element in a full tree enumeration.
+ *
+ * @returns Pointer to the next element in the tree, NULL if we're done.
+ * @param pElmRoot The root of the tree we're enumerating. NULL if
+ * it's the entire tree.
+ */
+ElementNode const *ElementNode::getNextTreeElement(ElementNode const *pElmRoot /*= NULL */) const
+{
+ /*
+ * Consider children first.
+ */
+ ElementNode const *pChild = getFirstChildElement();
+ if (pChild)
+ return pChild;
+
+ /*
+ * Then siblings, aunts and uncles.
+ */
+ ElementNode const *pCur = this;
+ do
+ {
+ ElementNode const *pSibling = pCur->getNextSibilingElement();
+ if (pSibling != NULL)
+ return pSibling;
+
+ pCur = static_cast<const xml::ElementNode *>(pCur->m_pParent);
+ Assert(pCur || pCur == pElmRoot);
+ } while (pCur != pElmRoot);
+
+ return NULL;
+}
+
+
+/**
+ * Private implementation.
+ *
+ * @param pElmRoot The root element.
+ */
+/*static*/ void ElementNode::buildChildren(ElementNode *pElmRoot) // protected
+{
+ for (ElementNode *pCur = pElmRoot; pCur; pCur = pCur->getNextTreeElement(pElmRoot))
+ {
+ /*
+ * Go thru this element's attributes creating AttributeNodes for them.
+ */
+ for (xmlAttr *pLibAttr = pCur->m_pLibNode->properties; pLibAttr; pLibAttr = pLibAttr->next)
+ {
+ AttributeNode *pNew = new AttributeNode(pElmRoot, pCur, &pCur->m_attributes, pLibAttr);
+ RTListAppend(&pCur->m_attributes, &pNew->m_listEntry);
+ }
+
+ /*
+ * Go thru this element's child elements (element and text nodes).
+ */
+ for (xmlNodePtr pLibNode = pCur->m_pLibNode->children; pLibNode; pLibNode = pLibNode->next)
+ {
+ Node *pNew;
+ if (pLibNode->type == XML_ELEMENT_NODE)
+ pNew = new ElementNode(pElmRoot, pCur, &pCur->m_children, pLibNode);
+ else if (pLibNode->type == XML_TEXT_NODE)
+ pNew = new ContentNode(pCur, &pCur->m_children, pLibNode);
+ else
+ continue;
+ RTListAppend(&pCur->m_children, &pNew->m_listEntry);
+ }
+ }
+}
+
+
/**
* Builds a list of direct child elements of the current element that
* match the given string; if pcszMatch is NULL, all direct child
@@ -689,18 +769,16 @@ int ElementNode::getChildElements(ElementNodesList &children,
const
{
int i = 0;
- for (Data::InternalNodesList::iterator it = m->children.begin();
- it != m->children.end();
- ++it)
+ Node *p;
+ RTListForEachCpp(&m_children, p, Node, m_listEntry)
{
// export this child node if ...
- Node *p = it->get();
if (p->isElement())
- if ( (!pcszMatch) // the caller wants all nodes or
- || (!strcmp(pcszMatch, p->getName())) // the element name matches
+ if ( !pcszMatch // ... the caller wants all nodes or ...
+ || !strcmp(pcszMatch, p->getName()) // ... the element name matches.
)
{
- children.push_back(static_cast<ElementNode*>(p));
+ children.push_back(static_cast<ElementNode *>(p));
++i;
}
}
@@ -714,25 +792,18 @@ int ElementNode::getChildElements(ElementNodesList &children,
* @param pcszMatch Element name to match.
* @return
*/
-const ElementNode* ElementNode::findChildElement(const char *pcszNamespace,
- const char *pcszMatch)
- const
+const ElementNode *ElementNode::findChildElementNS(const char *pcszNamespace, const char *pcszMatch) const
{
- Data::InternalNodesList::const_iterator
- it,
- last = m->children.end();
- for (it = m->children.begin();
- it != last;
- ++it)
+ Node *p;
+ RTListForEachCpp(&m_children, p, Node, m_listEntry)
{
- if ((**it).isElement())
+ if (p->isElement())
{
- ElementNode *pelm = static_cast<ElementNode*>((*it).get());
- if (pelm->nameEquals(pcszNamespace, pcszMatch))
+ ElementNode *pelm = static_cast<ElementNode*>(p);
+ if (pelm->nameEqualsNS(pcszNamespace, pcszMatch))
return pelm;
}
}
-
return NULL;
}
@@ -741,58 +812,154 @@ const ElementNode* ElementNode::findChildElement(const char *pcszNamespace,
* @param pcszId identifier to look for.
* @return child element or NULL if not found.
*/
-const ElementNode* ElementNode::findChildElementFromId(const char *pcszId) const
-{
- Data::InternalNodesList::const_iterator
- it,
- last = m->children.end();
- for (it = m->children.begin();
- it != last;
- ++it)
+const ElementNode *ElementNode::findChildElementFromId(const char *pcszId) const
+{
+ const Node *p;
+ RTListForEachCpp(&m_children, p, Node, m_listEntry)
{
- if ((**it).isElement())
+ if (p->isElement())
{
- ElementNode *pelm = static_cast<ElementNode*>((*it).get());
- const AttributeNode *pAttr;
- if ( ((pAttr = pelm->findAttribute("id")))
- && (!strcmp(pAttr->getValue(), pcszId))
- )
- return pelm;
+ const ElementNode *pElm = static_cast<const ElementNode *>(p);
+ const AttributeNode *pAttr = pElm->findAttribute("id");
+ if (pAttr && !strcmp(pAttr->getValue(), pcszId))
+ return pElm;
}
}
+ return NULL;
+}
+
+const ElementNode *ElementNode::findChildElementP(const char *pcszPath, const char *pcszNamespace /*= NULL*/) const
+{
+ size_t cchThis = strchr(pcszPath, '/') - pcszPath;
+ if (cchThis == (size_t)((const char *)0 - pcszPath))
+ return findChildElementNS(pcszNamespace, pcszPath);
+
+ /** @todo Can be done without recursion as we have both sibling lists and parent
+ * pointers in this variant. */
+ const Node *p;
+ RTListForEachCpp(&m_children, p, Node, m_listEntry)
+ {
+ if (p->isElement())
+ {
+ const ElementNode *pElm = static_cast<const ElementNode *>(p);
+ if (pElm->nameEqualsN(pcszPath, cchThis, pcszNamespace))
+ {
+ pElm = findChildElementP(pcszPath + cchThis, pcszNamespace);
+ if (pElm)
+ return pElm;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+const ElementNode *ElementNode::getFirstChildElement() const
+{
+ const Node *p;
+ RTListForEachCpp(&m_children, p, Node, m_listEntry)
+ {
+ if (p->isElement())
+ return static_cast<const ElementNode *>(p);
+ }
+ return NULL;
+}
+
+const ElementNode *ElementNode::getLastChildElement() const
+{
+ const Node *p;
+ RTListForEachReverseCpp(&m_children, p, Node, m_listEntry)
+ {
+ if (p->isElement())
+ return static_cast<const ElementNode *>(p);
+ }
return NULL;
}
+const ElementNode *ElementNode::getPrevSibilingElement() const
+{
+ if (!m_pParent)
+ return NULL;
+ const Node *pSibling = this;
+ for (;;)
+ {
+ pSibling = RTListGetPrevCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
+ if (!pSibling)
+ return NULL;
+ if (pSibling->isElement())
+ return static_cast<const ElementNode *>(pSibling);
+ }
+}
+
+const ElementNode *ElementNode::getNextSibilingElement() const
+{
+ if (!m_pParent)
+ return NULL;
+ const Node *pSibling = this;
+ for (;;)
+ {
+ pSibling = RTListGetNextCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
+ if (!pSibling)
+ return NULL;
+ if (pSibling->isElement())
+ return static_cast<const ElementNode *>(pSibling);
+ }
+}
+
+const ElementNode *ElementNode::findPrevSibilingElement(const char *pcszMatch, const char *pcszNamespace /*= NULL*/) const
+{
+ if (!m_pParent)
+ return NULL;
+ const Node *pSibling = this;
+ for (;;)
+ {
+ pSibling = RTListGetPrevCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
+ if (!pSibling)
+ return NULL;
+ if (pSibling->isElement())
+ {
+ const ElementNode *pElem = static_cast<const ElementNode *>(pSibling);
+ if (pElem->nameEqualsNS(pcszNamespace, pcszMatch))
+ return pElem;
+ }
+ }
+}
+
+const ElementNode *ElementNode::findNextSibilingElement(const char *pcszMatch, const char *pcszNamespace /*= NULL*/) const
+{
+ if (!m_pParent)
+ return NULL;
+ const Node *pSibling = this;
+ for (;;)
+ {
+ pSibling = RTListGetNextCpp(m_pParentListAnchor, pSibling, const Node, m_listEntry);
+ if (!pSibling)
+ return NULL;
+ if (pSibling->isElement())
+ {
+ const ElementNode *pElem = static_cast<const ElementNode *>(pSibling);
+ if (pElem->nameEqualsNS(pcszNamespace, pcszMatch))
+ return pElem;
+ }
+ }
+}
+
+
/**
* Looks up the given attribute node in this element's attribute map.
*
- * With respect to namespaces, the internal attributes map stores namespace
- * prefixes with attribute names only if the attribute uses a non-default
- * namespace. As a result, the following rules apply:
- *
- * -- To find attributes from a non-default namespace, pcszMatch must not
- * be prefixed with a namespace.
- *
- * -- To find attributes from the default namespace (or if the document does
- * not use namespaces), pcszMatch must be prefixed with the namespace
- * prefix and a colon.
- *
- * For example, if the document uses the "vbox:" namespace by default, you
- * must omit "vbox:" from pcszMatch to find such attributes, whether they
- * are specifed in the xml or not.
- *
- * @param pcszMatch
- * @return
+ * @param pcszMatch The name of the attribute to find.
+ * @param pcszNamespace The attribute name space prefix or NULL.
*/
-const AttributeNode* ElementNode::findAttribute(const char *pcszMatch) const
+const AttributeNode *ElementNode::findAttribute(const char *pcszMatch, const char *pcszNamespace /*= NULL*/) const
{
- Data::AttributesMap::const_iterator it;
-
- it = m->attribs.find(pcszMatch);
- if (it != m->attribs.end())
- return it->second.get();
-
+ AttributeNode *p;
+ RTListForEachCpp(&m_attributes, p, AttributeNode, m_listEntry)
+ {
+ if (p->nameEqualsNS(pcszNamespace, pcszMatch))
+ return p;
+ }
return NULL;
}
@@ -800,19 +967,19 @@ const AttributeNode* ElementNode::findAttribute(const char *pcszMatch) const
* Convenience method which attempts to find the attribute with the given
* name and returns its value as a string.
*
- * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
- * @param ppcsz out: attribute value
- * @return TRUE if attribute was found and str was thus updated.
+ * @param pcszMatch Name of attribute to find.
+ * @param ppcsz Where to return the attribute.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
*/
-bool ElementNode::getAttributeValue(const char *pcszMatch, const char *&ppcsz) const
+bool ElementNode::getAttributeValue(const char *pcszMatch, const char **ppcsz, const char *pcszNamespace /*= NULL*/) const
{
- const Node* pAttr;
- if ((pAttr = findAttribute(pcszMatch)))
+ const AttributeNode *pAttr = findAttribute(pcszMatch, pcszNamespace);
+ if (pAttr)
{
- ppcsz = pAttr->getValue();
+ *ppcsz = pAttr->getValue();
return true;
}
-
return false;
}
@@ -820,16 +987,20 @@ bool ElementNode::getAttributeValue(const char *pcszMatch, const char *&ppcsz) c
* Convenience method which attempts to find the attribute with the given
* name and returns its value as a string.
*
- * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
- * @param str out: attribute value; overwritten only if attribute was found
- * @return TRUE if attribute was found and str was thus updated.
+ * @param pcszMatch Name of attribute to find.
+ * @param pStr Pointer to the string object that should receive the
+ * attribute value.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
+ *
+ * @throws Whatever the string class may throw on assignment.
*/
-bool ElementNode::getAttributeValue(const char *pcszMatch, RTCString &str) const
+bool ElementNode::getAttributeValue(const char *pcszMatch, RTCString *pStr, const char *pcszNamespace /*= NULL*/) const
{
- const Node* pAttr;
- if ((pAttr = findAttribute(pcszMatch)))
+ const AttributeNode *pAttr = findAttribute(pcszMatch, pcszNamespace);
+ if (pAttr)
{
- str = pAttr->getValue();
+ *pStr = pAttr->getValue();
return true;
}
@@ -839,15 +1010,18 @@ bool ElementNode::getAttributeValue(const char *pcszMatch, RTCString &str) const
/**
* Like getAttributeValue (ministring variant), but makes sure that all backslashes
* are converted to forward slashes.
- * @param pcszMatch
- * @param str
- * @return
+ *
+ * @param pcszMatch Name of attribute to find.
+ * @param pStr Pointer to the string object that should
+ * receive the attribute path value.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
*/
-bool ElementNode::getAttributeValuePath(const char *pcszMatch, RTCString &str) const
+bool ElementNode::getAttributeValuePath(const char *pcszMatch, RTCString *pStr, const char *pcszNamespace /*= NULL*/) const
{
- if (getAttributeValue(pcszMatch, str))
+ if (getAttributeValue(pcszMatch, pStr, pcszNamespace))
{
- str.findReplace('\\', '/');
+ pStr->findReplace('\\', '/');
return true;
}
@@ -856,85 +1030,85 @@ bool ElementNode::getAttributeValuePath(const char *pcszMatch, RTCString &str) c
/**
* Convenience method which attempts to find the attribute with the given
- * name and returns its value as a signed integer. This calls
- * RTStrToInt32Ex internally and will only output the integer if that
- * function returns no error.
+ * name and returns its value as a signed 32-bit integer.
*
- * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
- * @param i out: attribute value; overwritten only if attribute was found
- * @return TRUE if attribute was found and str was thus updated.
+ * @param pcszMatch Name of attribute to find.
+ * @param piValue Where to return the value.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
*/
-bool ElementNode::getAttributeValue(const char *pcszMatch, int32_t &i) const
+bool ElementNode::getAttributeValue(const char *pcszMatch, int32_t *piValue, const char *pcszNamespace /*= NULL*/) const
{
- const char *pcsz;
- if ( (getAttributeValue(pcszMatch, pcsz))
- && (VINF_SUCCESS == RTStrToInt32Ex(pcsz, NULL, 0, &i))
- )
- return true;
-
+ const char *pcsz = findAttributeValue(pcszMatch, pcszNamespace);
+ if (pcsz)
+ {
+ int rc = RTStrToInt32Ex(pcsz, NULL, 0, piValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
return false;
}
/**
* Convenience method which attempts to find the attribute with the given
- * name and returns its value as an unsigned integer.This calls
- * RTStrToUInt32Ex internally and will only output the integer if that
- * function returns no error.
+ * name and returns its value as an unsigned 32-bit integer.
*
- * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
- * @param i out: attribute value; overwritten only if attribute was found
- * @return TRUE if attribute was found and str was thus updated.
+ * @param pcszMatch Name of attribute to find.
+ * @param puValue Where to return the value.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
*/
-bool ElementNode::getAttributeValue(const char *pcszMatch, uint32_t &i) const
+bool ElementNode::getAttributeValue(const char *pcszMatch, uint32_t *puValue, const char *pcszNamespace /*= NULL*/) const
{
- const char *pcsz;
- if ( (getAttributeValue(pcszMatch, pcsz))
- && (VINF_SUCCESS == RTStrToUInt32Ex(pcsz, NULL, 0, &i))
- )
- return true;
-
+ const char *pcsz = findAttributeValue(pcszMatch, pcszNamespace);
+ if (pcsz)
+ {
+ int rc = RTStrToUInt32Ex(pcsz, NULL, 0, puValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
return false;
}
/**
* Convenience method which attempts to find the attribute with the given
- * name and returns its value as a signed long integer. This calls
- * RTStrToInt64Ex internally and will only output the integer if that
- * function returns no error.
+ * name and returns its value as a signed 64-bit integer.
*
- * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
- * @param i out: attribute value
- * @return TRUE if attribute was found and str was thus updated.
+ * @param pcszMatch Name of attribute to find.
+ * @param piValue Where to return the value.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
*/
-bool ElementNode::getAttributeValue(const char *pcszMatch, int64_t &i) const
+bool ElementNode::getAttributeValue(const char *pcszMatch, int64_t *piValue, const char *pcszNamespace /*= NULL*/) const
{
- const char *pcsz;
- if ( (getAttributeValue(pcszMatch, pcsz))
- && (VINF_SUCCESS == RTStrToInt64Ex(pcsz, NULL, 0, &i))
- )
- return true;
-
+ const char *pcsz = findAttributeValue(pcszMatch, pcszNamespace);
+ if (pcsz)
+ {
+ int rc = RTStrToInt64Ex(pcsz, NULL, 0, piValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
return false;
}
/**
* Convenience method which attempts to find the attribute with the given
- * name and returns its value as an unsigned long integer.This calls
- * RTStrToUInt64Ex internally and will only output the integer if that
- * function returns no error.
+ * name and returns its value as an unsigned 64-bit integer.
*
- * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
- * @param i out: attribute value; overwritten only if attribute was found
- * @return TRUE if attribute was found and str was thus updated.
+ * @param pcszMatch Name of attribute to find.
+ * @param puValue Where to return the value.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
*/
-bool ElementNode::getAttributeValue(const char *pcszMatch, uint64_t &i) const
+bool ElementNode::getAttributeValue(const char *pcszMatch, uint64_t *puValue, const char *pcszNamespace /*= NULL*/) const
{
- const char *pcsz;
- if ( (getAttributeValue(pcszMatch, pcsz))
- && (VINF_SUCCESS == RTStrToUInt64Ex(pcsz, NULL, 0, &i))
- )
- return true;
-
+ const char *pcsz = findAttributeValue(pcszMatch, pcszNamespace);
+ if (pcsz)
+ {
+ int rc = RTStrToUInt64Ex(pcsz, NULL, 0, puValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
return false;
}
@@ -943,29 +1117,30 @@ bool ElementNode::getAttributeValue(const char *pcszMatch, uint64_t &i) const
* name and returns its value as a boolean. This accepts "true", "false",
* "yes", "no", "1" or "0" as valid values.
*
- * @param pcszMatch name of attribute to find (see findAttribute() for namespace remarks)
- * @param f out: attribute value; overwritten only if attribute was found
- * @return TRUE if attribute was found and str was thus updated.
+ * @param pcszMatch Name of attribute to find.
+ * @param pfValue Where to return the value.
+ * @param pcszNamespace The attribute name space prefix or NULL.
+ * @returns Boolean success indicator.
*/
-bool ElementNode::getAttributeValue(const char *pcszMatch, bool &f) const
+bool ElementNode::getAttributeValue(const char *pcszMatch, bool *pfValue, const char *pcszNamespace /*= NULL*/) const
{
- const char *pcsz;
- if (getAttributeValue(pcszMatch, pcsz))
+ const char *pcsz = findAttributeValue(pcszMatch, pcszNamespace);
+ if (pcsz)
{
- if ( (!strcmp(pcsz, "true"))
- || (!strcmp(pcsz, "yes"))
- || (!strcmp(pcsz, "1"))
+ if ( !strcmp(pcsz, "true")
+ || !strcmp(pcsz, "yes")
+ || !strcmp(pcsz, "1")
)
{
- f = true;
+ *pfValue = true;
return true;
}
- if ( (!strcmp(pcsz, "false"))
- || (!strcmp(pcsz, "no"))
- || (!strcmp(pcsz, "0"))
+ if ( !strcmp(pcsz, "false")
+ || !strcmp(pcsz, "no")
+ || !strcmp(pcsz, "0")
)
{
- f = false;
+ *pfValue = false;
return true;
}
}
@@ -973,6 +1148,81 @@ bool ElementNode::getAttributeValue(const char *pcszMatch, bool &f) const
return false;
}
+
+bool ElementNode::getElementValue(int32_t *piValue) const
+{
+ const char *pszValue = getValue();
+ if (pszValue)
+ {
+ int rc = RTStrToInt32Ex(pszValue, NULL, 0, piValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
+ return false;
+}
+
+bool ElementNode::getElementValue(uint32_t *puValue) const
+{
+ const char *pszValue = getValue();
+ if (pszValue)
+ {
+ int rc = RTStrToUInt32Ex(pszValue, NULL, 0, puValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
+ return false;
+}
+
+bool ElementNode::getElementValue(int64_t *piValue) const
+{
+ const char *pszValue = getValue();
+ if (pszValue)
+ {
+ int rc = RTStrToInt64Ex(pszValue, NULL, 0, piValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
+ return false;
+}
+
+bool ElementNode::getElementValue(uint64_t *puValue) const
+{
+ const char *pszValue = getValue();
+ if (pszValue)
+ {
+ int rc = RTStrToUInt64Ex(pszValue, NULL, 0, puValue);
+ if (rc == VINF_SUCCESS)
+ return true;
+ }
+ return false;
+}
+
+bool ElementNode::getElementValue(bool *pfValue) const
+{
+ const char *pszValue = getValue();
+ if (pszValue)
+ {
+ if ( !strcmp(pszValue, "true")
+ || !strcmp(pszValue, "yes")
+ || !strcmp(pszValue, "1")
+ )
+ {
+ *pfValue = true;
+ return true;
+ }
+ if ( !strcmp(pszValue, "false")
+ || !strcmp(pszValue, "no")
+ || !strcmp(pszValue, "0")
+ )
+ {
+ *pfValue = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+
/**
* Creates a new child element node and appends it to the list
* of children in "this".
@@ -980,23 +1230,22 @@ bool ElementNode::getAttributeValue(const char *pcszMatch, bool &f) const
* @param pcszElementName
* @return
*/
-ElementNode* ElementNode::createChild(const char *pcszElementName)
+ElementNode *ElementNode::createChild(const char *pcszElementName)
{
// we must be an element, not an attribute
- if (!m_plibNode)
+ if (!m_pLibNode)
throw ENodeIsNotElement(RT_SRC_POS);
// libxml side: create new node
- xmlNode *plibNode;
- if (!(plibNode = xmlNewNode(NULL, // namespace
+ xmlNode *pLibNode;
+ if (!(pLibNode = xmlNewNode(NULL, // namespace
(const xmlChar*)pcszElementName)))
throw std::bad_alloc();
- xmlAddChild(m_plibNode, plibNode);
+ xmlAddChild(m_pLibNode, pLibNode);
// now wrap this in C++
- ElementNode *p = new ElementNode(m_pelmRoot, this, plibNode);
- boost::shared_ptr<ElementNode> pNew(p);
- m->children.push_back(pNew);
+ ElementNode *p = new ElementNode(m_pElmRoot, this, &m_children, pLibNode);
+ RTListAppend(&m_children, &p->m_listEntry);
return p;
}
@@ -1009,18 +1258,17 @@ ElementNode* ElementNode::createChild(const char *pcszElementName)
* @param pcszContent
* @return
*/
-ContentNode* ElementNode::addContent(const char *pcszContent)
+ContentNode *ElementNode::addContent(const char *pcszContent)
{
// libxml side: create new node
- xmlNode *plibNode;
- if (!(plibNode = xmlNewText((const xmlChar*)pcszContent)))
+ xmlNode *pLibNode = xmlNewText((const xmlChar*)pcszContent);
+ if (!pLibNode)
throw std::bad_alloc();
- xmlAddChild(m_plibNode, plibNode);
+ xmlAddChild(m_pLibNode, pLibNode);
// now wrap this in C++
- ContentNode *p = new ContentNode(this, plibNode);
- boost::shared_ptr<ContentNode> pNew(p);
- m->children.push_back(pNew);
+ ContentNode *p = new ContentNode(this, &m_children, pLibNode);
+ RTListAppend(&m_children, &p->m_listEntry);
return p;
}
@@ -1032,42 +1280,40 @@ ContentNode* ElementNode::addContent(const char *pcszContent)
* otherwise a new attribute is created. Returns the attribute node
* that was either created or changed.
*
- * @param pcszName
- * @param pcszValue
- * @return
+ * @param pcszName The attribute name.
+ * @param pcszValue The attribute value.
+ * @return Pointer to the attribute node that was created or modified.
*/
-AttributeNode* ElementNode::setAttribute(const char *pcszName, const char *pcszValue)
+AttributeNode *ElementNode::setAttribute(const char *pcszName, const char *pcszValue)
{
- AttributeNode *pattrReturn;
- Data::AttributesMap::const_iterator it;
-
- it = m->attribs.find(pcszName);
- if (it == m->attribs.end())
- {
- // libxml side: xmlNewProp creates an attribute
- xmlAttr *plibAttr = xmlNewProp(m_plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
-
- // C++ side: create an attribute node around it
- const char *pcszKey;
- boost::shared_ptr<AttributeNode> pNew(new AttributeNode(*m_pelmRoot, this, plibAttr, &pcszKey));
- // store
- m->attribs[pcszKey] = pNew;
- pattrReturn = pNew.get();
- }
- else
+ /*
+ * Do we already have an attribute and should we just update it?
+ */
+ AttributeNode *pAttr;
+ RTListForEachCpp(&m_attributes, pAttr, AttributeNode, m_listEntry)
{
- // overwrite existing libxml attribute node
- xmlAttrPtr plibAttr = xmlSetProp(m_plibNode, (xmlChar*)pcszName, (xmlChar*)pcszValue);
-
- // and fix our existing C++ side around it
- boost::shared_ptr<AttributeNode> pattr = it->second;
- pattr->m_plibAttr = plibAttr; // in case the xmlAttrPtr is different, I'm not sure
+ if (pAttr->nameEquals(pcszName))
+ {
+ /* Overwrite existing libxml attribute node ... */
+ xmlAttrPtr pLibAttr = xmlSetProp(m_pLibNode, (xmlChar *)pcszName, (xmlChar *)pcszValue);
- pattrReturn = pattr.get();
+ /* ... and update our C++ wrapper in case the attrib pointer changed. */
+ pAttr->m_pLibAttr = pLibAttr;
+ return pAttr;
+ }
}
- return pattrReturn;
+ /*
+ * No existing attribute, create a new one.
+ */
+ /* libxml side: xmlNewProp creates an attribute. */
+ xmlAttr *pLibAttr = xmlNewProp(m_pLibNode, (xmlChar *)pcszName, (xmlChar *)pcszValue);
+
+ /* C++ side: Create an attribute node around it. */
+ pAttr = new AttributeNode(m_pElmRoot, this, &m_attributes, pLibAttr);
+ RTListAppend(&m_attributes, &pAttr->m_listEntry);
+ return pAttr;
}
/**
@@ -1196,53 +1442,41 @@ AttributeNode* ElementNode::setAttribute(const char *pcszName, bool f)
}
/**
- * Private constructor for a new attribute node. This one is special:
- * in ppcszKey, it returns a pointer to a string buffer that should be
- * used to index the attribute correctly with namespaces.
+ * Private constructor for a new attribute node.
*
- * @param pParent
- * @param elmRoot
- * @param plibAttr
- * @param ppcszKey
+ * @param pElmRoot Pointer to the root element. Needed for getting the
+ * default name space.
+ * @param pParent Pointer to the parent element (always an ElementNode,
+ * despite the type). NULL for the root node.
+ * @param pListAnchor Pointer to the m_children member of the parent. NULL
+ * for the root node.
+ * @param pLibNode Pointer to the libxml2 node structure.
*/
-AttributeNode::AttributeNode(const ElementNode &elmRoot,
+AttributeNode::AttributeNode(const ElementNode *pElmRoot,
Node *pParent,
- xmlAttr *plibAttr,
- const char **ppcszKey)
+ PRTLISTANCHOR pListAnchor,
+ xmlAttr *pLibAttr)
: Node(IsAttribute,
pParent,
+ pListAnchor,
NULL,
- plibAttr)
+ pLibAttr)
{
- m_pcszName = (const char*)plibAttr->name;
+ m_pcszName = (const char *)pLibAttr->name;
- *ppcszKey = m_pcszName;
-
- if ( plibAttr->ns
- && plibAttr->ns->prefix
- )
+ if ( pLibAttr->ns
+ && pLibAttr->ns->prefix)
{
- m_pcszNamespacePrefix = (const char*)plibAttr->ns->prefix;
- m_pcszNamespaceHref = (const char*)plibAttr->ns->href;
-
- if ( !elmRoot.m_pcszNamespaceHref
- || (strcmp(m_pcszNamespaceHref, elmRoot.m_pcszNamespaceHref))
- )
- {
- // not default namespace:
- m_strKey = m_pcszNamespacePrefix;
- m_strKey.append(':');
- m_strKey.append(m_pcszName);
-
- *ppcszKey = m_strKey.c_str();
- }
+ m_pcszNamespacePrefix = (const char *)pLibAttr->ns->prefix;
+ m_pcszNamespaceHref = (const char *)pLibAttr->ns->href;
}
}
-ContentNode::ContentNode(Node *pParent, xmlNode *plibNode)
+ContentNode::ContentNode(Node *pParent, PRTLISTANCHOR pListAnchor, xmlNode *pLibNode)
: Node(IsContent,
pParent,
- plibNode,
+ pListAnchor,
+ pLibNode,
NULL)
{
}
@@ -1380,9 +1614,9 @@ Document::~Document()
*/
void Document::refreshInternals() // private
{
- m->pRootElement = new ElementNode(NULL, NULL, xmlDocGetRootElement(m->plibDocument));
+ m->pRootElement = new ElementNode(NULL, NULL, NULL, xmlDocGetRootElement(m->plibDocument));
- m->pRootElement->buildChildren(*m->pRootElement);
+ ElementNode::buildChildren(m->pRootElement);
}
/**
@@ -1390,7 +1624,7 @@ void Document::refreshInternals() // private
* Const variant.
* @return
*/
-const ElementNode* Document::getRootElement() const
+const ElementNode *Document::getRootElement() const
{
return m->pRootElement;
}
@@ -1400,41 +1634,43 @@ const ElementNode* Document::getRootElement() const
* Non-const variant.
* @return
*/
-ElementNode* Document::getRootElement()
+ElementNode *Document::getRootElement()
{
return m->pRootElement;
}
/**
- * Creates a new element node and sets it as the root element. This will
- * only work if the document is empty; otherwise EDocumentNotEmpty is thrown.
+ * Creates a new element node and sets it as the root element.
+ *
+ * This will only work if the document is empty; otherwise EDocumentNotEmpty is
+ * thrown.
*/
-ElementNode* Document::createRootElement(const char *pcszRootElementName,
+ElementNode *Document::createRootElement(const char *pcszRootElementName,
const char *pcszComment /* = NULL */)
{
if (m->pRootElement || m->plibDocument)
throw EDocumentNotEmpty(RT_SRC_POS);
// libxml side: create document, create root node
- m->plibDocument = xmlNewDoc((const xmlChar*)"1.0");
- xmlNode *plibRootNode;
- if (!(plibRootNode = xmlNewNode(NULL, // namespace
- (const xmlChar*)pcszRootElementName)))
+ m->plibDocument = xmlNewDoc((const xmlChar *)"1.0");
+ xmlNode *plibRootNode = xmlNewNode(NULL /*namespace*/ , (const xmlChar *)pcszRootElementName);
+ if (!plibRootNode)
throw std::bad_alloc();
xmlDocSetRootElement(m->plibDocument, plibRootNode);
+
// now wrap this in C++
- m->pRootElement = new ElementNode(NULL, NULL, plibRootNode);
+ m->pRootElement = new ElementNode(NULL, NULL, NULL, plibRootNode);
// add document global comment if specified
if (pcszComment != NULL)
{
- xmlNode *pComment;
- if (!(pComment = xmlNewDocComment(m->plibDocument,
- (const xmlChar *)pcszComment)))
+ xmlNode *pComment = xmlNewDocComment(m->plibDocument, (const xmlChar *)pcszComment);
+ if (!pComment)
throw std::bad_alloc();
xmlAddPrevSibling(plibRootNode, pComment);
+
// now wrap this in C++
- m->pComment = new ElementNode(NULL, NULL, pComment);
+ m->pComment = new ElementNode(NULL, NULL, NULL, pComment);
}
return m->pRootElement;
@@ -1480,12 +1716,13 @@ XmlMemParser::~XmlMemParser()
*
* The document that is passed in will be reset before being filled if not empty.
*
- * @param pvBuf in: memory buffer to parse.
- * @param cbSize in: size of the memory buffer.
- * @param strFilename in: name fo file to parse.
- * @param doc out: document to be reset and filled with data according to file contents.
+ * @param pvBuf Memory buffer to parse.
+ * @param cbSize Size of the memory buffer.
+ * @param strFilename Refernece to the name of the file we're parsing.
+ * @param doc Reference to the output document. This will be reset
+ * and filled with data according to file contents.
*/
-void XmlMemParser::read(const void* pvBuf, size_t cbSize,
+void XmlMemParser::read(const void *pvBuf, size_t cbSize,
const RTCString &strFilename,
Document &doc)
{