diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
|---|---|---|
| committer | <> | 2014-05-08 15:03:54 +0000 |
| commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
| tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/Additions/common/VBoxGuest | |
| parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
| download | VirtualBox-master.tar.gz | |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/Additions/common/VBoxGuest')
27 files changed, 3986 insertions, 925 deletions
diff --git a/src/VBox/Additions/common/VBoxGuest/Makefile.kmk b/src/VBox/Additions/common/VBoxGuest/Makefile.kmk index 8ff81a91..ecaa22c4 100644 --- a/src/VBox/Additions/common/VBoxGuest/Makefile.kmk +++ b/src/VBox/Additions/common/VBoxGuest/Makefile.kmk @@ -19,22 +19,26 @@ SUB_DEPTH = ../../../../.. include $(KBUILD_PATH)/subheader.kmk -if1of ($(KBUILD_TARGET), freebsd $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linux,) os2 solaris win) +if1of ($(KBUILD_TARGET), darwin freebsd haiku $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linux,) os2 solaris win) # # VBoxGuest - The Guest Additions Driver. # SYSMODS += VBoxGuest VBoxGuest_TEMPLATE = VBOXGUESTR0 VBoxGuest_NAME.freebsd = vboxguest + VBoxGuest_NAME.haiku = vboxguest VBoxGuest_NAME.linux = vboxguest VBoxGuest_NAME.solaris = vboxguest + VBoxGuest_INST.darwin = $(INST_ADDITIONS)VBoxGuest.kext/Contents/MacOS/ ifdef VBOX_SIGN_ADDITIONS # See Additions/WINNT/Makefile.kmk? VBoxGuest_INSTTYPE.win = none VBoxGuest_DEBUG_INSTTYPE.win = both endif + VBoxGuest_DEFS.haiku = VBOX_SVN_REV=$(VBOX_SVN_REV) _KERNEL_MODE=1 VBoxGuest_DEFS.linux = KBUILD_MODNAME=KBUILD_STR\(vboxguest\) KBUILD_BASENAME=KBUILD_STR\(vboxguest\) DEBUG_HASH=2 DEBUG_HASH2=3 EXPORT_SYMTAB VBoxGuest_DEFS.solaris = VBOX_SVN_REV=$(VBOX_SVN_REV) VBoxGuest_DEFS.win = # VBOX_WITH_VRDP_SESSION_HANDLING + VBoxGuest_DEFS.darwin = VBOX_GUESTDRV_WITH_RELEASE_LOGGER ifeq ($(KBUILD_TYPE),release) # Allow stopping/removing the driver without a reboot # in debug mode; this is very useful for testing the shutdown stuff! @@ -48,7 +52,9 @@ if1of ($(KBUILD_TARGET), freebsd $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linu $(if $(VBOX_WITH_DPC_LATENCY_CHECKER),VBOX_WITH_DPC_LATENCY_CHECKER,) VBoxGuest_DEPS.solaris += $(VBOX_SVN_REV_KMK) VBoxGuest_DEPS.linux += $(VBOX_SVN_REV_HEADER) + VBoxGuest_DEPS.haiku += $(VBOX_SVN_REV_HEADER) VBoxGuest_DEPS.freebsd += $(VBOX_SVN_REV_HEADER) + VBoxGuest_DEPS.darwin += $(VBOX_SVN_REV_HEADER) VBoxGuest_DEFS = VBGL_VBOXGUEST VBOX_WITH_HGCM VBoxGuest_INCS = . VBoxGuest_INCS.freebsd = $(VBoxGuest_0_OUTDIR) $(PATH_STAGE)/gen-sys-hdrs @@ -74,7 +80,7 @@ if1of ($(KBUILD_TARGET), freebsd $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linu VBoxGuest.cpp_SDKS = $(VBOX_WINDDK_GST_WLH) endif endif # win - ifn1of ($(KBUILD_TARGET), linux freebsd solaris) + ifn1of ($(KBUILD_TARGET), linux freebsd solaris haiku) VBoxGuest_SOURCES = VBoxGuest-$(KBUILD_TARGET).cpp else VBoxGuest_SOURCES = VBoxGuest-$(KBUILD_TARGET).c @@ -94,6 +100,16 @@ if1of ($(KBUILD_TARGET), freebsd $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linu $(PATH_STAGE)/gen-sys-hdrs/pci_if.h \ $(PATH_STAGE)/gen-sys-hdrs/bus_if.h \ $(PATH_STAGE)/gen-sys-hdrs/device_if.h + ifeq ($(KBUILD_TARGET),haiku) + # Haiku drivers cannot export symbols for other drivers, but modules can. + # Therefore vboxguest is a module containing the ring-0 guest lib, and vboxdev/vboxsf + # use this module to access the guest lib + SYSMODS += VBoxDev + VBoxDev_TEMPLATE = VBOXGUESTR0 + VBoxDev_NAME = vboxdev + VBoxDev_DEFS = VBOX_SVN_REV=$(VBOX_SVN_REV) _KERNEL_MODE=1 VBGL_VBOXGUEST VBOX_WITH_HGCM IN_RING0 + VBoxDev_SOURCES = VBoxDev-haiku.c VBoxGuest-haiku-stubs.c + endif else # OS/2: # The library order is crucial, so a bit of trickery is necessary. # A library is used to make sure that VBoxGuestA-os2.asm is first in the link. (temporary hack?) @@ -151,6 +167,32 @@ if1of ($(KBUILD_TARGET), freebsd $(if $(defined VBOX_WITH_ADDITION_DRIVERS),linu endif # win endif # enabled + +ifeq ($(KBUILD_TARGET), darwin) + # Files necessary to make a darwin kernel extension bundle. + INSTALLS += VBoxGuest.kext + VBoxGuest.kext_INST = $(INST_ADDITIONS)/VBoxGuest.kext/Contents/ + VBoxGuest.kext_SOURCES = $(VBoxGuest.kext_0_OUTDIR)/Info.plist + VBoxGuest.kext_CLEAN = $(VBoxGuest.kext_0_OUTDIR)/Info.plist + +$$(VBoxGuest.kext_0_OUTDIR)/Info.plist: \ + $(PATH_SUB_CURRENT)/darwin/Info.plist \ + $(VBOX_VERSION_MK) | $$(dir $$@) + $(call MSG_GENERATE,VBoxGuest,$@,$<) + $(QUIET)$(RM) -f $@ + $(QUIET)$(SED) \ + -e 's/@VBOX_VERSION_STRING@/$(VBOX_VERSION_STRING)/g' \ + -e 's/@VBOX_VERSION_MAJOR@/$(VBOX_VERSION_MAJOR)/g' \ + -e 's/@VBOX_VERSION_MINOR@/$(VBOX_VERSION_MINOR)/g' \ + -e 's/@VBOX_VERSION_BUILD@/$(VBOX_VERSION_BUILD)/g' \ + -e 's/@VBOX_VENDOR@/$(VBOX_VENDOR)/g' \ + -e 's/@VBOX_PRODUCT@/$(VBOX_PRODUCT)/g' \ + -e 's/@VBOX_C_YEAR@/$(VBOX_C_YEAR)/g' \ + --output $@ \ + $< +endif # darwin + + ifeq ($(KBUILD_TARGET),linux) # # Install the source files and script(s). diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxDev-haiku.c b/src/VBox/Additions/common/VBoxGuest/VBoxDev-haiku.c new file mode 100644 index 00000000..82163323 --- /dev/null +++ b/src/VBox/Additions/common/VBoxGuest/VBoxDev-haiku.c @@ -0,0 +1,446 @@ +/* $Id: VBoxDev-haiku.c $ */ +/** @file + * VBoxGuest kernel driver, Haiku Guest Additions, 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. + */ + +/* + * This code is based on: + * + * VirtualBox Guest Additions for Haiku. + * Copyright (c) 2011 Mike Smith <mike@scgtrp.net> + * François Revol <revol@free.fr> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#include <sys/param.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <OS.h> +#include <Drivers.h> +#include <KernelExport.h> +#include <PCI.h> + +#include "VBoxGuest-haiku.h" +#include "VBoxGuestInternal.h" +#include <VBox/log.h> +#include <iprt/assert.h> +#include <iprt/initterm.h> +#include <iprt/process.h> +#include <iprt/mem.h> +#include <iprt/asm.h> + +#define DRIVER_NAME "vboxdev" +#define DEVICE_NAME "misc/vboxguest" +#define MODULE_NAME "generic/vboxguest" + +/******************************************************************************* +* Internal Functions * +*******************************************************************************/ +static status_t VBoxGuestHaikuOpen(const char *name, uint32 flags, void **cookie); +static status_t VBoxGuestHaikuClose(void *cookie); +static status_t VBoxGuestHaikuFree(void *cookie); +static status_t VBoxGuestHaikuIOCtl(void *cookie, uint32 op, void *data, size_t len); +static status_t VBoxGuestHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync); +static status_t VBoxGuestHaikuDeselect(void *cookie, uint8 event, selectsync *sync); +static status_t VBoxGuestHaikuWrite(void *cookie, off_t position, const void *data, size_t *numBytes); +static status_t VBoxGuestHaikuRead(void *cookie, off_t position, void *data, size_t *numBytes); + +static device_hooks g_VBoxGuestHaikuDeviceHooks = +{ + VBoxGuestHaikuOpen, + VBoxGuestHaikuClose, + VBoxGuestHaikuFree, + VBoxGuestHaikuIOCtl, + VBoxGuestHaikuRead, + VBoxGuestHaikuWrite, + VBoxGuestHaikuSelect, + VBoxGuestHaikuDeselect, +}; + + +/** + * Driver open hook. + * + * @param name The name of the device as returned by publish_devices. + * @param flags Open flags. + * @param cookie Where to store the session pointer. + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuOpen(const char *name, uint32 flags, void **cookie) +{ + int rc; + PVBOXGUESTSESSION pSession; + + LogFlow((DRIVER_NAME ":VBoxGuestHaikuOpen\n")); + + /* + * Create a new session. + */ + rc = VBoxGuestCreateUserSession(&g_DevExt, &pSession); + if (RT_SUCCESS(rc)) + { + Log((DRIVER_NAME ":VBoxGuestHaikuOpen success: g_DevExt=%p pSession=%p rc=%d pid=%d\n",&g_DevExt, pSession, rc,(int)RTProcSelf())); + ASMAtomicIncU32(&cUsers); + *cookie = pSession; + return B_OK; + } + + LogRel((DRIVER_NAME ":VBoxGuestHaikuOpen: failed. rc=%d\n", rc)); + return RTErrConvertToErrno(rc); +} + + +/** + * Driver close hook. + * @param cookie The session. + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuClose(void *cookie) +{ + PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; + Log(("VBoxGuestHaikuClose: pSession=%p\n", pSession)); + + /** @todo r=ramshankar: should we really be using the session spinlock here? */ + RTSpinlockAcquire(g_DevExt.SessionSpinlock); + + /* @todo we don't know if it belongs to this session!! */ + if (sState.selectSync) + { + //dprintf(DRIVER_NAME "close: unblocking select %p %x\n", sState.selectSync, sState.selectEvent); + notify_select_event(sState.selectSync, sState.selectEvent); + sState.selectEvent = (uint8_t)0; + sState.selectRef = (uint32_t)0; + sState.selectSync = (void *)NULL; + } + + RTSpinlockRelease(g_DevExt.SessionSpinlock); + return B_OK; +} + + +/** + * Driver free hook. + * @param cookie The session. + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuFree(void *cookie) +{ + PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; + Log(("VBoxGuestHaikuFree: pSession=%p\n", pSession)); + + /* + * Close the session if it's still hanging on to the device... + */ + if (VALID_PTR(pSession)) + { + VBoxGuestCloseSession(&g_DevExt, pSession); + ASMAtomicDecU32(&cUsers); + } + else + Log(("VBoxGuestHaikuFree: si_drv1=%p!\n", pSession)); + return B_OK; +} + + +/** + * Driver IOCtl entry. + * @param cookie The session. + * @param op The operation to perform. + * @param data The data associated with the operation. + * @param len Size of the data in bytes. + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuIOCtl(void *cookie, uint32 op, void *data, size_t len) +{ + PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; + Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl cookie=%p op=0x%08x data=%p len=%lu)\n", cookie, op, data, len)); + + int rc = B_OK; + + /* + * Validate the input. + */ + if (RT_UNLIKELY(!VALID_PTR(pSession))) + return EINVAL; + + /* + * Validate the request wrapper. + */ +#if 0 + if (IOCPARM_LEN(ulCmd) != sizeof(VBGLBIGREQ)) + { + Log((DRIVER_NAME ": VBoxGuestHaikuIOCtl: bad request %lu size=%lu expected=%d\n", ulCmd, IOCPARM_LEN(ulCmd), + sizeof(VBGLBIGREQ))); + return ENOTTY; + } +#endif + + if (RT_UNLIKELY(len > _1M * 16)) + { + dprintf(DRIVER_NAME ": VBoxGuestHaikuIOCtl: bad size %#x; pArg=%p Cmd=%lu.\n", (unsigned)len, data, op); + return EINVAL; + } + + /* + * Read the request. + */ + void *pvBuf = NULL; + if (RT_LIKELY(len > 0)) + { + pvBuf = RTMemTmpAlloc(len); + if (RT_UNLIKELY(!pvBuf)) + { + LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: RTMemTmpAlloc failed to alloc %d bytes.\n", len)); + return ENOMEM; + } + + /** @todo r=ramshankar: replace with RTR0MemUserCopyFrom() */ + rc = user_memcpy(pvBuf, data, len); + if (RT_UNLIKELY(rc < 0)) + { + RTMemTmpFree(pvBuf); + LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: user_memcpy failed; pvBuf=%p data=%p op=%d. rc=%d\n", pvBuf, data, op, rc)); + return EFAULT; + } + if (RT_UNLIKELY(!VALID_PTR(pvBuf))) + { + RTMemTmpFree(pvBuf); + LogRel((DRIVER_NAME ":VBoxGuestHaikuIOCtl: pvBuf invalid pointer %p\n", pvBuf)); + return EINVAL; + } + } + Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: pSession=%p pid=%d.\n", pSession,(int)RTProcSelf())); + + /* + * Process the IOCtl. + */ + size_t cbDataReturned; + rc = VBoxGuestCommonIOCtl(op, &g_DevExt, pSession, pvBuf, len, &cbDataReturned); + if (RT_SUCCESS(rc)) + { + rc = 0; + if (RT_UNLIKELY(cbDataReturned > len)) + { + Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: too much output data %d expected %d\n", cbDataReturned, len)); + cbDataReturned = len; + } + if (cbDataReturned > 0) + { + rc = user_memcpy(data, pvBuf, cbDataReturned); + if (RT_UNLIKELY(rc < 0)) + { + Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: user_memcpy failed; pvBuf=%p pArg=%p Cmd=%lu. rc=%d\n", pvBuf, data, op, rc)); + rc = EFAULT; + } + } + } + else + { + Log((DRIVER_NAME ":VBoxGuestHaikuIOCtl: VBoxGuestCommonIOCtl failed. rc=%d\n", rc)); + rc = EFAULT; + } + RTMemTmpFree(pvBuf); + return rc; +} + + +/** + * Driver select hook. + * + * @param cookie The session. + * @param event The event. + * @param ref ??? + * @param sync ??? + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuSelect(void *cookie, uint8 event, uint32 ref, selectsync *sync) +{ + PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; + status_t err = B_OK; + + switch (event) + { + case B_SELECT_READ: + break; + default: + return EINVAL; + } + + RTSpinlockAcquire(g_DevExt.SessionSpinlock); + + uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq); + if (pSession->u32MousePosChangedSeq != u32CurSeq) + { + pSession->u32MousePosChangedSeq = u32CurSeq; + notify_select_event(sync, event); + } + else if (sState.selectSync == NULL) + { + sState.selectEvent = (uint8_t)event; + sState.selectRef = (uint32_t)ref; + sState.selectSync = (void *)sync; + } + else + err = B_WOULD_BLOCK; + + RTSpinlockRelease(g_DevExt.SessionSpinlock); + + return err; +} + + +/** + * Driver deselect hook. + * @param cookie The session. + * @param event The event. + * @param sync ??? + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuDeselect(void *cookie, uint8 event, selectsync *sync) +{ + PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; + status_t err = B_OK; + //dprintf(DRIVER_NAME "deselect(,%d,%p)\n", event, sync); + + RTSpinlockAcquire(g_DevExt.SessionSpinlock); + + if (sState.selectSync == sync) + { + //dprintf(DRIVER_NAME "deselect: dropping: %p %x\n", sState.selectSync, sState.selectEvent); + sState.selectEvent = (uint8_t)0; + sState.selectRef = (uint32_t)0; + sState.selectSync = NULL; + } + else + err = B_OK; + + RTSpinlockRelease(g_DevExt.SessionSpinlock); + return err; +} + + +/** + * Driver write hook. + * @param cookie The session. + * @param position The offset. + * @param data Pointer to the data. + * @param numBytes Where to store the number of bytes written. + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuWrite(void *cookie, off_t position, const void *data, size_t *numBytes) +{ + *numBytes = 0; + return B_OK; +} + + +/** + * Driver read hook. + * @param cookie The session. + * @param position The offset. + * @param data Pointer to the data. + * @param numBytes Where to store the number of bytes read. + * + * @return Haiku status code. + */ +static status_t VBoxGuestHaikuRead(void *cookie, off_t position, void *data, size_t *numBytes) +{ + PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; + + if (*numBytes == 0) + return B_OK; + + uint32_t u32CurSeq = ASMAtomicUoReadU32(&g_DevExt.u32MousePosChangedSeq); + if (pSession->u32MousePosChangedSeq != u32CurSeq) + { + pSession->u32MousePosChangedSeq = u32CurSeq; + *numBytes = 1; + return B_OK; + } + + *numBytes = 0; + return B_OK; +} + + +int32 api_version = B_CUR_DRIVER_API_VERSION; + +status_t init_hardware() +{ + return get_module(MODULE_NAME, (module_info **)&g_VBoxGuest); +} + +status_t init_driver() +{ + return B_OK; +} + +device_hooks* find_device(const char *name) +{ + static device_hooks g_VBoxGuestHaikuDeviceHooks = + { + VBoxGuestHaikuOpen, + VBoxGuestHaikuClose, + VBoxGuestHaikuFree, + VBoxGuestHaikuIOCtl, + VBoxGuestHaikuRead, + VBoxGuestHaikuWrite, + VBoxGuestHaikuSelect, + VBoxGuestHaikuDeselect + }; + return &g_VBoxGuestHaikuDeviceHooks; +} + +const char** publish_devices() +{ + static const char *devices[] = { DEVICE_NAME, NULL }; + return devices; +} + +void uninit_driver() +{ + put_module(MODULE_NAME); +} + diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-darwin.cpp b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-darwin.cpp new file mode 100644 index 00000000..3eb7dab4 --- /dev/null +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-darwin.cpp @@ -0,0 +1,1085 @@ +/* $Id: VBoxGuest-darwin.cpp $ */ +/** @file + * VBoxGuest - Darwin Specifics. + */ + +/* + * 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. + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#define LOG_GROUP LOG_GROUP_VBGD +/* + * Deal with conflicts first. + * PVM - BSD mess, that FreeBSD has correct a long time ago. + * iprt/types.h before sys/param.h - prevents UINT32_C and friends. + */ +#include <iprt/types.h> +#include <sys/param.h> +#undef PVM + +#include <IOKit/IOLib.h> /* Assert as function */ + +#include <VBox/version.h> +#include <iprt/asm.h> +#include <iprt/initterm.h> +#include <iprt/assert.h> +#include <iprt/spinlock.h> +#include <iprt/semaphore.h> +#include <iprt/process.h> +#include <iprt/alloc.h> +#include <iprt/power.h> +#include <VBox/err.h> +#include <VBox/log.h> + +#include <mach/kmod.h> +#include <miscfs/devfs/devfs.h> +#include <sys/conf.h> +#include <sys/errno.h> +#include <sys/ioccom.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/kauth.h> +#include <IOKit/IOService.h> +#include <IOKit/IOUserClient.h> +#include <IOKit/pwr_mgt/RootDomain.h> +#include <IOKit/pci/IOPCIDevice.h> +#include <IOKit/IOBufferMemoryDescriptor.h> +#include <IOKit/IOFilterInterruptEventSource.h> +#include "VBoxGuestInternal.h" + + +/******************************************************************************* +* Defined Constants And Macros * +*******************************************************************************/ + +/** The system device node name. */ +#define DEVICE_NAME_SYS "vboxguest" +/** The user device node name. */ +#define DEVICE_NAME_USR "vboxguestu" + + + +/******************************************************************************* +* Internal Functions * +*******************************************************************************/ +RT_C_DECLS_BEGIN +static kern_return_t VbgdDarwinStart(struct kmod_info *pKModInfo, void *pvData); +static kern_return_t VbgdDarwinStop(struct kmod_info *pKModInfo, void *pvData); +static int VbgdDarwinCharDevRemove(void); + +static int VbgdDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess); +static int VbgdDarwinClose(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess); +static int VbgdDarwinIOCtlSlow(PVBOXGUESTSESSION pSession, u_long iCmd, caddr_t pData, struct proc *pProcess); +static int VbgdDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess); + +static int VbgdDarwinErr2DarwinErr(int rc); + +static IOReturn VbgdDarwinSleepHandler(void *pvTarget, void *pvRefCon, UInt32 uMessageType, IOService *pProvider, void *pvMessageArgument, vm_size_t argSize); +RT_C_DECLS_END + + +/******************************************************************************* +* Structures and Typedefs * +*******************************************************************************/ +/** + * The service class for handling the VMMDev PCI device. + * + * Instantiated when the module is loaded (and on PCI hotplugging?). + */ +class org_virtualbox_VBoxGuest : public IOService +{ + OSDeclareDefaultStructors(org_virtualbox_VBoxGuest); + +private: + IOPCIDevice *m_pIOPCIDevice; + IOMemoryMap *m_pMap; + IOFilterInterruptEventSource *m_pInterruptSrc; + + bool setupVmmDevInterrupts(IOService *pProvider); + bool disableVmmDevInterrupts(void); + bool isVmmDev(IOPCIDevice *pIOPCIDevice); + +public: + virtual bool start(IOService *pProvider); + virtual void stop(IOService *pProvider); + virtual bool terminate(IOOptionBits fOptions); +}; + +OSDefineMetaClassAndStructors(org_virtualbox_VBoxGuest, IOService); + + +/** + * An attempt at getting that clientDied() notification. + * I don't think it'll work as I cannot figure out where/what creates the correct + * port right. + * + * Instantiated when userland does IOServiceOpen(). + */ +class org_virtualbox_VBoxGuestClient : public IOUserClient +{ + OSDeclareDefaultStructors(org_virtualbox_VBoxGuestClient); + +private: + PVBOXGUESTSESSION m_pSession; /**< The session. */ + task_t m_Task; /**< The client task. */ + org_virtualbox_VBoxGuest *m_pProvider; /**< The service provider. */ + +public: + virtual bool initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type); + virtual bool start(IOService *pProvider); + static void sessionClose(RTPROCESS Process); + virtual IOReturn clientClose(void); +}; + +OSDefineMetaClassAndStructors(org_virtualbox_VBoxGuestClient, IOUserClient); + + + +/******************************************************************************* +* Global Variables * +*******************************************************************************/ +/** + * Declare the module stuff. + */ +RT_C_DECLS_BEGIN +extern kern_return_t _start(struct kmod_info *pKModInfo, void *pvData); +extern kern_return_t _stop(struct kmod_info *pKModInfo, void *pvData); + +KMOD_EXPLICIT_DECL(VBoxGuest, VBOX_VERSION_STRING, _start, _stop) +DECLHIDDEN(kmod_start_func_t *) _realmain = VbgdDarwinStart; +DECLHIDDEN(kmod_stop_func_t *) _antimain = VbgdDarwinStop; +DECLHIDDEN(int) _kext_apple_cc = __APPLE_CC__; +RT_C_DECLS_END + + +/** + * Device extention & session data association structure. + */ +static VBOXGUESTDEVEXT g_DevExt; + +/** + * The character device switch table for the driver. + */ +static struct cdevsw g_DevCW = +{ + /*.d_open = */ VbgdDarwinOpen, + /*.d_close = */ VbgdDarwinClose, + /*.d_read = */ eno_rdwrt, + /*.d_write = */ eno_rdwrt, + /*.d_ioctl = */ VbgdDarwinIOCtl, + /*.d_stop = */ eno_stop, + /*.d_reset = */ eno_reset, + /*.d_ttys = */ NULL, + /*.d_select = */ eno_select, + /*.d_mmap = */ eno_mmap, + /*.d_strategy = */ eno_strat, + /*.d_getc = */ eno_getc, + /*.d_putc = */ eno_putc, + /*.d_type = */ 0 +}; + +/** Major device number. */ +static int g_iMajorDeviceNo = -1; +/** Registered devfs device handle. */ +static void *g_hDevFsDeviceSys = NULL; +/** Registered devfs device handle for the user device. */ +static void *g_hDevFsDeviceUsr = NULL; /**< @todo 4 later */ + +/** Spinlock protecting g_apSessionHashTab. */ +static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK; +/** Hash table */ +static PVBOXGUESTSESSION g_apSessionHashTab[19]; +/** Calculates the index into g_apSessionHashTab.*/ +#define SESSION_HASH(pid) ((pid) % RT_ELEMENTS(g_apSessionHashTab)) +/** The number of open sessions. */ +static int32_t volatile g_cSessions = 0; +/** The number of IOService class instances. */ +static bool volatile g_fInstantiated = 0; +/** The notifier handle for the sleep callback handler. */ +static IONotifier *g_pSleepNotifier = NULL; + + + +/** + * Start the kernel module. + */ +static kern_return_t VbgdDarwinStart(struct kmod_info *pKModInfo, void *pvData) +{ +#ifdef DEBUG + printf("VbgdDarwinStart\n"); +#endif + + /* + * Initialize IPRT. + */ + int rc = RTR0Init(0); + if (RT_FAILURE(rc)) + { + printf("VBoxGuest: RTR0Init failed with rc=%d\n", rc); + return KMOD_RETURN_FAILURE; + } + + return KMOD_RETURN_SUCCESS; +} + + +/* Register VBoxGuest char device */ +static int VbgdDarwinCharDevInit(void) +{ + int rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestDarwin"); + if (RT_FAILURE(rc)) + { + return KMOD_RETURN_FAILURE; + } + + /* + * Registering ourselves as a character device. + */ + g_iMajorDeviceNo = cdevsw_add(-1, &g_DevCW); + if (g_iMajorDeviceNo < 0) + { + VbgdDarwinCharDevRemove(); + return KMOD_RETURN_FAILURE; + } + + g_hDevFsDeviceSys = devfs_make_node(makedev(g_iMajorDeviceNo, 0), DEVFS_CHAR, + UID_ROOT, GID_WHEEL, 0666, DEVICE_NAME_SYS); + if (!g_hDevFsDeviceSys) + { + VbgdDarwinCharDevRemove(); + return KMOD_RETURN_FAILURE; + } + + /* Register a sleep/wakeup notification callback */ + g_pSleepNotifier = registerPrioritySleepWakeInterest(&VbgdDarwinSleepHandler, &g_DevExt, NULL); + if (g_pSleepNotifier == NULL) + { + VbgdDarwinCharDevRemove(); + return KMOD_RETURN_FAILURE; + } + + return KMOD_RETURN_SUCCESS; +} + + +/** + * Stop the kernel module. + */ +static kern_return_t VbgdDarwinStop(struct kmod_info *pKModInfo, void *pvData) +{ + RTR0TermForced(); +#ifdef DEBUG + printf("VbgdDarwinStop - done\n"); +#endif + return KMOD_RETURN_SUCCESS; +} + + +/* Unregister VBoxGuest char device */ +static int +VbgdDarwinCharDevRemove(void) +{ + int rc = KMOD_RETURN_SUCCESS; + + if (g_pSleepNotifier) + { + g_pSleepNotifier->remove(); + g_pSleepNotifier = NULL; + } + + if (g_hDevFsDeviceSys) + { + devfs_remove(g_hDevFsDeviceSys); + g_hDevFsDeviceSys = NULL; + } + + if (g_hDevFsDeviceUsr) + { + devfs_remove(g_hDevFsDeviceUsr); + g_hDevFsDeviceUsr = NULL; + } + + if (g_iMajorDeviceNo != -1) + { + int rc2 = cdevsw_remove(g_iMajorDeviceNo, &g_DevCW); + Assert(rc2 == g_iMajorDeviceNo); + g_iMajorDeviceNo = -1; + } + + if (g_Spinlock != NIL_RTSPINLOCK) + { + int rc2 = RTSpinlockDestroy(g_Spinlock); AssertRC(rc2); + g_Spinlock = NIL_RTSPINLOCK; + } + + return rc; +} + + +/** + * Device open. Called on open /dev/vboxguest and (later) /dev/vboxguestu. + * + * @param Dev The device number. + * @param fFlags ???. + * @param fDevType ???. + * @param pProcess The process issuing this request. + */ +static int VbgdDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) +{ + /* + * Only two minor devices numbers are allowed. + */ + if (minor(Dev) != 0 && minor(Dev) != 1) + return EACCES; + + /* + * Find the session created by org_virtualbox_VBoxGuestClient, fail + * if no such session, and mark it as opened. We set the uid & gid + * here too, since that is more straight forward at this point. + */ + //const bool fUnrestricted = minor(Dev) == 0; + int rc = VINF_SUCCESS; + PVBOXGUESTSESSION pSession = NULL; + kauth_cred_t pCred = kauth_cred_proc_ref(pProcess); + if (pCred) + { + RTPROCESS Process = RTProcSelf(); + unsigned iHash = SESSION_HASH(Process); + RTSpinlockAcquire(g_Spinlock); + + pSession = g_apSessionHashTab[iHash]; + while (pSession && pSession->Process != Process) + pSession = pSession->pNextHash; + if (pSession) + { + if (!pSession->fOpened) + { + pSession->fOpened = true; + /*pSession->fUnrestricted = fUnrestricted; - later */ + } + else + rc = VERR_ALREADY_LOADED; + } + else + rc = VERR_GENERAL_FAILURE; + + RTSpinlockReleaseNoInts(g_Spinlock); +#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 + kauth_cred_unref(&pCred); +#else /* 10.4 */ + /* The 10.4u SDK headers and 10.4.11 kernel source have inconsistent definitions + of kauth_cred_unref(), so use the other (now deprecated) API for releasing it. */ + kauth_cred_rele(pCred); +#endif /* 10.4 */ + } + else + rc = VERR_INVALID_PARAMETER; + + Log(("VbgdDarwinOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, proc_pid(pProcess))); + return VbgdDarwinErr2DarwinErr(rc); +} + + +/** + * Close device. + */ +static int VbgdDarwinClose(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) +{ + Log(("VbgdDarwinClose: pid=%d\n", (int)RTProcSelf())); + Assert(proc_pid(pProcess) == (int)RTProcSelf()); + + /* + * Hand the session closing to org_virtualbox_VBoxGuestClient. + */ + org_virtualbox_VBoxGuestClient::sessionClose(RTProcSelf()); + return 0; +} + + +/** + * Device I/O Control entry point. + * + * @returns Darwin for slow IOCtls and VBox status code for the fast ones. + * @param Dev The device number (major+minor). + * @param iCmd The IOCtl command. + * @param pData Pointer to the data (if any it's a VBOXGUESTIOCTLDATA (kernel copy)). + * @param fFlags Flag saying we're a character device (like we didn't know already). + * @param pProcess The process issuing this request. + */ +static int VbgdDarwinIOCtl(dev_t Dev, u_long iCmd, caddr_t pData, int fFlags, struct proc *pProcess) +{ + //const bool fUnrestricted = minor(Dev) == 0; + const RTPROCESS Process = proc_pid(pProcess); + const unsigned iHash = SESSION_HASH(Process); + PVBOXGUESTSESSION pSession; + + /* + * Find the session. + */ + RTSpinlockAcquire(g_Spinlock); + pSession = g_apSessionHashTab[iHash]; + while (pSession && pSession->Process != Process /*later: && pSession->fUnrestricted == fUnrestricted*/ && pSession->fOpened) + pSession = pSession->pNextHash; + RTSpinlockReleaseNoInts(g_Spinlock); + if (!pSession) + { + Log(("VBoxDrvDarwinIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#lx\n", + (int)Process, iCmd)); + return EINVAL; + } + + /* + * No high speed IOCtls here yet. + */ + + return VbgdDarwinIOCtlSlow(pSession, iCmd, pData, pProcess); +} + + +/** + * Worker for VbgdDarwinIOCtl that takes the slow IOCtl functions. + * + * @returns Darwin errno. + * + * @param pSession The session. + * @param iCmd The IOCtl command. + * @param pData Pointer to the kernel copy of the data buffer. + * @param pProcess The calling process. + */ +static int VbgdDarwinIOCtlSlow(PVBOXGUESTSESSION pSession, u_long iCmd, caddr_t pData, struct proc *pProcess) +{ + LogFlow(("VbgdDarwinIOCtlSlow: pSession=%p iCmd=%p pData=%p pProcess=%p\n", pSession, iCmd, pData, pProcess)); + + + /* + * Buffered or unbuffered? + */ + void *pvReqData; + user_addr_t pUser = 0; + void *pvPageBuf = NULL; + uint32_t cbReq = IOCPARM_LEN(iCmd); + if ((IOC_DIRMASK & iCmd) == IOC_INOUT) + { + /* + * Raw buffered request data, common code validates it. + */ + pvReqData = pData; + } + else if ((IOC_DIRMASK & iCmd) == IOC_VOID && !cbReq) + { + /* + * Get the header and figure out how much we're gonna have to read. + */ + VBGLBIGREQ Hdr; + pUser = (user_addr_t)*(void **)pData; + int rc = copyin(pUser, &Hdr, sizeof(Hdr)); + if (RT_UNLIKELY(rc)) + { + Log(("VbgdDarwinIOCtlSlow: copyin(%llx,Hdr,) -> %#x; iCmd=%#lx\n", (unsigned long long)pUser, rc, iCmd)); + return rc; + } + if (RT_UNLIKELY(Hdr.u32Magic != VBGLBIGREQ_MAGIC)) + { + Log(("VbgdDarwinIOCtlSlow: bad magic u32Magic=%#x; iCmd=%#lx\n", Hdr.u32Magic, iCmd)); + return EINVAL; + } + cbReq = Hdr.cbData; + if (RT_UNLIKELY(cbReq > _1M*16)) + { + Log(("VbgdDarwinIOCtlSlow: %#x; iCmd=%#lx\n", Hdr.cbData, iCmd)); + return EINVAL; + } + pUser = Hdr.pvDataR3; + + /* + * Allocate buffer and copy in the data. + */ + pvReqData = RTMemTmpAlloc(cbReq); + if (!pvReqData) + pvPageBuf = pvReqData = IOMallocAligned(RT_ALIGN_Z(cbReq, PAGE_SIZE), 8); + if (RT_UNLIKELY(!pvReqData)) + { + Log(("VbgdDarwinIOCtlSlow: failed to allocate buffer of %d bytes; iCmd=%#lx\n", cbReq, iCmd)); + return ENOMEM; + } + rc = copyin(pUser, pvReqData, Hdr.cbData); + if (RT_UNLIKELY(rc)) + { + Log(("VbgdDarwinIOCtlSlow: copyin(%llx,%p,%#x) -> %#x; iCmd=%#lx\n", + (unsigned long long)pUser, pvReqData, Hdr.cbData, rc, iCmd)); + if (pvPageBuf) + IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); + else + RTMemTmpFree(pvReqData); + return rc; + } + } + else + { + Log(("VbgdDarwinIOCtlSlow: huh? cbReq=%#x iCmd=%#lx\n", cbReq, iCmd)); + return EINVAL; + } + + /* + * Process the IOCtl. + */ + size_t cbReqRet = 0; + int rc = VBoxGuestCommonIOCtl(iCmd, &g_DevExt, pSession, pvReqData, cbReq, &cbReqRet); + if (RT_SUCCESS(rc)) + { + /* + * If not buffered, copy back the buffer before returning. + */ + if (pUser) + { + if (cbReqRet > cbReq) + { + Log(("VbgdDarwinIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbReqRet, cbReq, iCmd)); + cbReqRet = cbReq; + } + rc = copyout(pvReqData, pUser, cbReqRet); + if (RT_UNLIKELY(rc)) + Log(("VbgdDarwinIOCtlSlow: copyout(%p,%llx,%#x) -> %d; uCmd=%#lx!\n", + pvReqData, (unsigned long long)pUser, cbReqRet, rc, iCmd)); + + /* cleanup */ + if (pvPageBuf) + IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); + else + RTMemTmpFree(pvReqData); + } + else + rc = 0; + } + else + { + /* + * The request failed, just clean up. + */ + if (pUser) + { + if (pvPageBuf) + IOFreeAligned(pvPageBuf, RT_ALIGN_Z(cbReq, PAGE_SIZE)); + else + RTMemTmpFree(pvReqData); + } + + Log(("VbgdDarwinIOCtlSlow: pid=%d iCmd=%lx pData=%p failed, rc=%d\n", proc_pid(pProcess), iCmd, (void *)pData, rc)); + rc = EINVAL; + } + + Log2(("VbgdDarwinIOCtlSlow: returns %d\n", rc)); + return rc; +} + + +/* + * The VBoxGuest IDC entry points. + * + * This code is shared with the other unixy OSes. + */ +#include "VBoxGuestIDC-unix.c.h" + + +void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) +{ + NOREF(pDevExt); +} + + +/** + * Callback for blah blah blah. + */ +IOReturn VbgdDarwinSleepHandler(void * /* pvTarget */, void *pvRefCon, UInt32 uMessageType, IOService * /* pProvider */, void * /* pvMessageArgument */, vm_size_t /* argSize */) +{ + LogFlow(("VBoxGuest: Got sleep/wake notice. Message type was %X\n", (uint)uMessageType)); + + if (uMessageType == kIOMessageSystemWillSleep) + RTPowerSignalEvent(RTPOWEREVENT_SUSPEND); + else if (uMessageType == kIOMessageSystemHasPoweredOn) + RTPowerSignalEvent(RTPOWEREVENT_RESUME); + + acknowledgeSleepWakeNotification(pvRefCon); + + return 0; +} + + +/** + * Converts an IPRT error code to a darwin error code. + * + * @returns corresponding darwin error code. + * @param rc IPRT status code. + */ +static int VbgdDarwinErr2DarwinErr(int rc) +{ + switch (rc) + { + case VINF_SUCCESS: return 0; + case VERR_GENERAL_FAILURE: return EACCES; + case VERR_INVALID_PARAMETER: return EINVAL; + case VERR_INVALID_MAGIC: return EILSEQ; + case VERR_INVALID_HANDLE: return ENXIO; + case VERR_INVALID_POINTER: return EFAULT; + case VERR_LOCK_FAILED: return ENOLCK; + case VERR_ALREADY_LOADED: return EEXIST; + case VERR_PERMISSION_DENIED: return EPERM; + case VERR_VERSION_MISMATCH: return ENOSYS; + } + + return EPERM; +} + + +/* + * + * org_virtualbox_VBoxGuest + * + */ + +/** + * Just a plug + */ +static void +interruptHandler(OSObject *pOwner, IOInterruptEventSource *pSrc, int cInts) +{ + NOREF(pOwner); + NOREF(pSrc); + NOREF(cInts); +} + +/** + * Callback triggered when interrupt occurs. + */ +static bool +checkForInterrupt(OSObject *pOwner, IOFilterInterruptEventSource *pSrc) +{ + if (!pSrc) + return false; + + bool fTaken = VBoxGuestCommonISR(&g_DevExt); + if (!fTaken) + printf("VBoxGuestCommonISR error\n"); + + return fTaken; +} + +bool +org_virtualbox_VBoxGuest::setupVmmDevInterrupts(IOService *pProvider) +{ + IOWorkLoop *pWorkLoop = (IOWorkLoop *)getWorkLoop(); + + if (!pWorkLoop) + return false; + + m_pInterruptSrc = IOFilterInterruptEventSource::filterInterruptEventSource(this, + &interruptHandler, + &checkForInterrupt, + pProvider); + + if (kIOReturnSuccess != pWorkLoop->addEventSource(m_pInterruptSrc)) + { + m_pInterruptSrc->disable(); + m_pInterruptSrc->release(); + m_pInterruptSrc = 0; + return false; + } + + m_pInterruptSrc->enable(); + + return true; +} + +bool +org_virtualbox_VBoxGuest::disableVmmDevInterrupts(void) +{ + IOWorkLoop *pWorkLoop = (IOWorkLoop *)getWorkLoop(); + + if (!pWorkLoop) + return false; + + if (!m_pInterruptSrc) + return false; + + m_pInterruptSrc->disable(); + pWorkLoop->removeEventSource(m_pInterruptSrc); + m_pInterruptSrc->release(); + m_pInterruptSrc = 0; + + return true; +} + +bool org_virtualbox_VBoxGuest::isVmmDev(IOPCIDevice *pIOPCIDevice) +{ + UInt16 uVendorId, uDeviceId; + + if (!pIOPCIDevice) + return false; + + uVendorId = m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID); + uDeviceId = m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID); + + if (uVendorId == VMMDEV_VENDORID && uDeviceId == VMMDEV_DEVICEID) + return true; + + return true; +} + + +/** + * Start this service. + */ +bool org_virtualbox_VBoxGuest::start(IOService *pProvider) +{ + if (!IOService::start(pProvider)) + return false; + + /* Low level initialization should be performed only once */ + if (!ASMAtomicCmpXchgBool(&g_fInstantiated, true, false)) + { + IOService::stop(pProvider); + return false; + } + + m_pIOPCIDevice = OSDynamicCast(IOPCIDevice, pProvider); + if (m_pIOPCIDevice) + { + if (isVmmDev(m_pIOPCIDevice)) + { + /* Enable memory response from VMM device */ + m_pIOPCIDevice->setMemoryEnable(true); + m_pIOPCIDevice->setIOEnable(true); + + IOMemoryDescriptor *pMem = m_pIOPCIDevice->getDeviceMemoryWithIndex(0); + if (pMem) + { + IOPhysicalAddress IOPortBasePhys = pMem->getPhysicalAddress(); + /* Check that returned value is from I/O port range (at least it is 16-bit lenght) */ + if((IOPortBasePhys >> 16) == 0) + { + + RTIOPORT IOPortBase = (RTIOPORT)IOPortBasePhys; + void *pvMMIOBase = NULL; + uint32_t cbMMIO = 0; + m_pMap = m_pIOPCIDevice->mapDeviceMemoryWithIndex(1); + if (m_pMap) + { + pvMMIOBase = (void *)m_pMap->getVirtualAddress(); + cbMMIO = m_pMap->getLength(); + } + + int rc = VBoxGuestInitDevExt(&g_DevExt, + IOPortBase, + pvMMIOBase, + cbMMIO, +#if ARCH_BITS == 64 + VBOXOSTYPE_MacOS_x64, +#else + VBOXOSTYPE_MacOS, +#endif + 0); + if (RT_SUCCESS(rc)) + { + rc = VbgdDarwinCharDevInit(); + if (rc == KMOD_RETURN_SUCCESS) + { + if (setupVmmDevInterrupts(pProvider)) + { + /* register the service. */ + registerService(); + LogRel(("VBoxGuest: Successfully started I/O kit class instance.\n")); + return true; + } + + LogRel(("VBoxGuest: Failed to set up interrupts\n")); + VbgdDarwinCharDevRemove(); + } + else + LogRel(("VBoxGuest: Failed to initialize character device (rc=%d).\n", rc)); + + VBoxGuestDeleteDevExt(&g_DevExt); + } + else + LogRel(("VBoxGuest: Failed to initialize common code (rc=%d).\n", rc)); + + if (m_pMap) + { + m_pMap->release(); + m_pMap = NULL; + } + } + } + else + LogRel(("VBoxGuest: The device missing is the I/O port range (#0).\n")); + } + else + LogRel(("VBoxGuest: Not the VMMDev (%#x:%#x).\n", + m_pIOPCIDevice->configRead16(kIOPCIConfigVendorID), m_pIOPCIDevice->configRead16(kIOPCIConfigDeviceID))); + } + else + LogRel(("VBoxGuest: Provider is not an instance of IOPCIDevice.\n")); + + ASMAtomicXchgBool(&g_fInstantiated, false); + + IOService::stop(pProvider); + + return false; +} + + +/** + * Stop this service. + */ +void org_virtualbox_VBoxGuest::stop(IOService *pProvider) +{ + LogFlow(("org_virtualbox_VBoxGuest::stop([%p], %p)\n", this, pProvider)); + + AssertReturnVoid(ASMAtomicReadBool(&g_fInstantiated)); + + /* Low level termination should be performed only once */ + if (!disableVmmDevInterrupts()) + LogRel(("vboxguest: unable to unregister interrupt handler\n")); + + VbgdDarwinCharDevRemove(); + VBoxGuestDeleteDevExt(&g_DevExt); + + if (m_pMap) + { + m_pMap->release(); + m_pMap = NULL; + } + + IOService::stop(pProvider); + + ASMAtomicWriteBool(&g_fInstantiated, false); + + LogRel(("vboxguest module unloaded\n")); +} + + +/** + * Termination request. + * + * @return true if we're ok with shutting down now, false if we're not. + * @param fOptions Flags. + */ +bool org_virtualbox_VBoxGuest::terminate(IOOptionBits fOptions) +{ + bool fRc; + LogFlow(("org_virtualbox_VBoxGuest::terminate: reference_count=%d g_cSessions=%d (fOptions=%#x)\n", + KMOD_INFO_NAME.reference_count, ASMAtomicUoReadS32(&g_cSessions), fOptions)); + if ( KMOD_INFO_NAME.reference_count != 0 + || ASMAtomicUoReadS32(&g_cSessions)) + fRc = false; + else + fRc = IOService::terminate(fOptions); + LogFlow(("org_virtualbox_SupDrv::terminate: returns %d\n", fRc)); + return fRc; +} + + +/* + * + * org_virtualbox_VBoxGuestClient + * + */ + + +/** + * Initializer called when the client opens the service. + */ +bool org_virtualbox_VBoxGuestClient::initWithTask(task_t OwningTask, void *pvSecurityId, UInt32 u32Type) +{ + LogFlow(("org_virtualbox_VBoxGuestClient::initWithTask([%p], %#x, %p, %#x) (cur pid=%d proc=%p)\n", + this, OwningTask, pvSecurityId, u32Type, RTProcSelf(), RTR0ProcHandleSelf())); + AssertMsg((RTR0PROCESS)OwningTask == RTR0ProcHandleSelf(), ("%p %p\n", OwningTask, RTR0ProcHandleSelf())); + + if (!OwningTask) + return false; + if (IOUserClient::initWithTask(OwningTask, pvSecurityId , u32Type)) + { + m_Task = OwningTask; + m_pSession = NULL; + m_pProvider = NULL; + return true; + } + return false; +} + + +/** + * Start the client service. + */ +bool org_virtualbox_VBoxGuestClient::start(IOService *pProvider) +{ + LogFlow(("org_virtualbox_VBoxGuestClient::start([%p], %p) (cur pid=%d proc=%p)\n", + this, pProvider, RTProcSelf(), RTR0ProcHandleSelf() )); + AssertMsgReturn((RTR0PROCESS)m_Task == RTR0ProcHandleSelf(), + ("%p %p\n", m_Task, RTR0ProcHandleSelf()), + false); + + if (IOUserClient::start(pProvider)) + { + m_pProvider = OSDynamicCast(org_virtualbox_VBoxGuest, pProvider); + if (m_pProvider) + { + Assert(!m_pSession); + + /* + * Create a new session. + */ + int rc = VBoxGuestCreateUserSession(&g_DevExt, &m_pSession); + if (RT_SUCCESS(rc)) + { + m_pSession->fOpened = false; + /* The fUnrestricted field is set on open. */ + + /* + * Insert it into the hash table, checking that there isn't + * already one for this process first. (One session per proc!) + */ + unsigned iHash = SESSION_HASH(m_pSession->Process); + RTSpinlockAcquire(g_Spinlock); + + PVBOXGUESTSESSION pCur = g_apSessionHashTab[iHash]; + if (pCur && pCur->Process != m_pSession->Process) + { + do pCur = pCur->pNextHash; + while (pCur && pCur->Process != m_pSession->Process); + } + if (!pCur) + { + m_pSession->pNextHash = g_apSessionHashTab[iHash]; + g_apSessionHashTab[iHash] = m_pSession; + m_pSession->pvVBoxGuestClient = this; + ASMAtomicIncS32(&g_cSessions); + rc = VINF_SUCCESS; + } + else + rc = VERR_ALREADY_LOADED; + + RTSpinlockRelease(g_Spinlock); + if (RT_SUCCESS(rc)) + { + Log(("org_virtualbox_VBoxGuestClient::start: created session %p for pid %d\n", m_pSession, (int)RTProcSelf())); + return true; + } + + LogFlow(("org_virtualbox_VBoxGuestClient::start: already got a session for this process (%p)\n", pCur)); + VBoxGuestCloseSession(&g_DevExt, m_pSession); + } + + m_pSession = NULL; + LogFlow(("org_virtualbox_VBoxGuestClient::start: rc=%Rrc from supdrvCreateSession\n", rc)); + } + else + LogFlow(("org_virtualbox_VBoxGuestClient::start: %p isn't org_virtualbox_VBoxGuest\n", pProvider)); + } + return false; +} + + +/** + * Common worker for clientClose and VBoxDrvDarwinClose. + */ +/* static */ void org_virtualbox_VBoxGuestClient::sessionClose(RTPROCESS Process) +{ + /* + * Find the session and remove it from the hash table. + * + * Note! Only one session per process. (Both start() and + * VbgdDarwinOpen makes sure this is so.) + */ + const unsigned iHash = SESSION_HASH(Process); + RTSpinlockAcquire(g_Spinlock); + PVBOXGUESTSESSION pSession = g_apSessionHashTab[iHash]; + if (pSession) + { + if (pSession->Process == Process) + { + g_apSessionHashTab[iHash] = pSession->pNextHash; + pSession->pNextHash = NULL; + ASMAtomicDecS32(&g_cSessions); + } + else + { + PVBOXGUESTSESSION pPrev = pSession; + pSession = pSession->pNextHash; + while (pSession) + { + if (pSession->Process == Process) + { + pPrev->pNextHash = pSession->pNextHash; + pSession->pNextHash = NULL; + ASMAtomicDecS32(&g_cSessions); + break; + } + + /* next */ + pPrev = pSession; + pSession = pSession->pNextHash; + } + } + } + RTSpinlockRelease(g_Spinlock); + if (!pSession) + { + Log(("VBoxGuestClient::sessionClose: pSession == NULL, pid=%d; freed already?\n", (int)Process)); + return; + } + + /* + * Remove it from the client object. + */ + org_virtualbox_VBoxGuestClient *pThis = (org_virtualbox_VBoxGuestClient *)pSession->pvVBoxGuestClient; + pSession->pvVBoxGuestClient = NULL; + if (pThis) + { + Assert(pThis->m_pSession == pSession); + pThis->m_pSession = NULL; + } + + /* + * Close the session. + */ + VBoxGuestCloseSession(&g_DevExt, pSession); +} + + +/** + * Client exits normally. + */ +IOReturn org_virtualbox_VBoxGuestClient::clientClose(void) +{ + LogFlow(("org_virtualbox_VBoxGuestClient::clientClose([%p]) (cur pid=%d proc=%p)\n", this, RTProcSelf(), RTR0ProcHandleSelf())); + AssertMsg((RTR0PROCESS)m_Task == RTR0ProcHandleSelf(), ("%p %p\n", m_Task, RTR0ProcHandleSelf())); + + /* + * Clean up the session if it's still around. + * + * We cannot rely 100% on close, and in the case of a dead client + * we'll end up hanging inside vm_map_remove() if we postpone it. + */ + if (m_pSession) + { + sessionClose(RTProcSelf()); + Assert(!m_pSession); + } + + m_pProvider = NULL; + terminate(); + + return kIOReturnSuccess; +} + diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-freebsd.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-freebsd.c index 1720abb2..1552f715 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-freebsd.c +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-freebsd.c @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 Oracle Corporation + * Copyright (C) 2007-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/Additions/common/VBoxGuest/VBoxGuest-haiku-stubs.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku-stubs.c new file mode 100644 index 00000000..122df9e7 --- /dev/null +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku-stubs.c @@ -0,0 +1,448 @@ +/* $Id: VBoxGuest-haiku-stubs.c $ */ +/** @file + * VBoxGuest kernel module, Haiku Guest Additions, stubs. + */ + +/* + * 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. + */ + +/* + * This code is based on: + * + * VirtualBox Guest Additions for Haiku. + * Copyright (c) 2011 Mike Smith <mike@scgtrp.net> + * François Revol <revol@free.fr> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * This file provides stubs for calling VBox runtime functions through the vboxguest module. + * It should be linked into any driver or module that uses the VBox runtime, except vboxguest + * itself (which contains the actual library and therefore doesn't need stubs to call it). + */ + +#include "VBoxGuest-haiku.h" +#include "VBoxGuestInternal.h" +#include <VBox/log.h> +#include <iprt/assert.h> +#include <iprt/initterm.h> +#include <iprt/process.h> +#include <iprt/mem.h> +#include <iprt/asm.h> +#include <iprt/mp.h> +#include <iprt/power.h> +#include <iprt/thread.h> + +// >>> file('/tmp/stubs.c', 'w').writelines([re.sub(r'^(?P<returntype>[^(]+) \(\*_(?P<functionname>[A-Za-z0-9_]+)\)\((?P<params>[^)]+)\);', lambda m: '%s %s(%s)\n{\n %sg_VBoxGuest->_%s(%s);\n}\n' % (m.group(1), m.group(2), m.group(3), ('return ' if m.group(1) != 'void' else ''), m.group(2), (', '.join(a.split(' ')[-1].replace('*', '') for a in m.group(3).split(',')) if m.group(3) != 'void' else '')), f) for f in functions]) + +struct vboxguest_module_info *g_VBoxGuest; + +size_t RTLogBackdoorPrintf(const char *pszFormat, ...) +{ + va_list args; + size_t cb; + + va_start(args, pszFormat); + cb = g_VBoxGuest->_RTLogBackdoorPrintf(pszFormat, args); + va_end(args); + + return cb; +} +size_t RTLogBackdoorPrintfV(const char *pszFormat, va_list args) +{ + return g_VBoxGuest->_RTLogBackdoorPrintfV(pszFormat, args); +} +int RTLogSetDefaultInstanceThread(PRTLOGGER pLogger, uintptr_t uKey) +{ + return g_VBoxGuest->_RTLogSetDefaultInstanceThread(pLogger, uKey); +} +int RTMemAllocExTag(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv) +{ + return g_VBoxGuest->_RTMemAllocExTag(cb, cbAlignment, fFlags, pszTag, ppv); +} +void* RTMemContAlloc(PRTCCPHYS pPhys, size_t cb) +{ + return g_VBoxGuest->_RTMemContAlloc(pPhys, cb); +} +void RTMemContFree(void *pv, size_t cb) +{ + g_VBoxGuest->_RTMemContFree(pv, cb); +} +void RTMemFreeEx(void *pv, size_t cb) +{ + g_VBoxGuest->_RTMemFreeEx(pv, cb); +} +bool RTMpIsCpuPossible(RTCPUID idCpu) +{ + return g_VBoxGuest->_RTMpIsCpuPossible(idCpu); +} +int RTMpNotificationDeregister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser) +{ + return g_VBoxGuest->_RTMpNotificationDeregister(pfnCallback, pvUser); +} +int RTMpNotificationRegister(PFNRTMPNOTIFICATION pfnCallback, void *pvUser) +{ + return g_VBoxGuest->_RTMpNotificationRegister(pfnCallback, pvUser); +} +int RTMpOnAll(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) +{ + return g_VBoxGuest->_RTMpOnAll(pfnWorker, pvUser1, pvUser2); +} +int RTMpOnOthers(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) +{ + return g_VBoxGuest->_RTMpOnOthers(pfnWorker, pvUser1, pvUser2); +} +int RTMpOnSpecific(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2) +{ + return g_VBoxGuest->_RTMpOnSpecific(idCpu, pfnWorker, pvUser1, pvUser2); +} +int RTPowerNotificationDeregister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser) +{ + return g_VBoxGuest->_RTPowerNotificationDeregister(pfnCallback, pvUser); +} +int RTPowerNotificationRegister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser) +{ + return g_VBoxGuest->_RTPowerNotificationRegister(pfnCallback, pvUser); +} +int RTPowerSignalEvent(RTPOWEREVENT enmEvent) +{ + return g_VBoxGuest->_RTPowerSignalEvent(enmEvent); +} +void RTR0AssertPanicSystem(void) +{ + g_VBoxGuest->_RTR0AssertPanicSystem(); +} +int RTR0Init(unsigned fReserved) +{ + return g_VBoxGuest->_RTR0Init(fReserved); +} +void* RTR0MemObjAddress(RTR0MEMOBJ MemObj) +{ + return g_VBoxGuest->_RTR0MemObjAddress(MemObj); +} +RTR3PTR RTR0MemObjAddressR3(RTR0MEMOBJ MemObj) +{ + return g_VBoxGuest->_RTR0MemObjAddressR3(MemObj); +} +int RTR0MemObjAllocContTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjAllocContTag(pMemObj, cb, fExecutable, pszTag); +} +int RTR0MemObjAllocLowTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjAllocLowTag(pMemObj, cb, fExecutable, pszTag); +} +int RTR0MemObjAllocPageTag(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjAllocPageTag(pMemObj, cb, fExecutable, pszTag); +} +int RTR0MemObjAllocPhysExTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjAllocPhysExTag(pMemObj, cb, PhysHighest, uAlignment, pszTag); +} +int RTR0MemObjAllocPhysNCTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjAllocPhysNCTag(pMemObj, cb, PhysHighest, pszTag); +} +int RTR0MemObjAllocPhysTag(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjAllocPhysTag(pMemObj, cb, PhysHighest, pszTag); +} +int RTR0MemObjEnterPhysTag(PRTR0MEMOBJ pMemObj, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjEnterPhysTag(pMemObj, Phys, cb, uCachePolicy, pszTag); +} +int RTR0MemObjFree(RTR0MEMOBJ MemObj, bool fFreeMappings) +{ + return g_VBoxGuest->_RTR0MemObjFree(MemObj, fFreeMappings); +} +RTHCPHYS RTR0MemObjGetPagePhysAddr(RTR0MEMOBJ MemObj, size_t iPage) +{ + return g_VBoxGuest->_RTR0MemObjGetPagePhysAddr(MemObj, iPage); +} +bool RTR0MemObjIsMapping(RTR0MEMOBJ MemObj) +{ + return g_VBoxGuest->_RTR0MemObjIsMapping(MemObj); +} +int RTR0MemObjLockKernelTag(PRTR0MEMOBJ pMemObj, void *pv, size_t cb, uint32_t fAccess, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjLockKernelTag(pMemObj, pv, cb, fAccess, pszTag); +} +int RTR0MemObjLockUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, RTR0PROCESS R0Process, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjLockUserTag(pMemObj, R3Ptr, cb, fAccess, R0Process, pszTag); +} +int RTR0MemObjMapKernelExTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment, unsigned fProt, size_t offSub, size_t cbSub, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjMapKernelExTag(pMemObj, MemObjToMap, pvFixed, uAlignment, fProt, offSub, cbSub, pszTag); +} +int RTR0MemObjMapKernelTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment, unsigned fProt, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjMapKernelTag(pMemObj, MemObjToMap, pvFixed, uAlignment, fProt, pszTag); +} +int RTR0MemObjMapUserTag(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed, size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjMapUserTag(pMemObj, MemObjToMap, R3PtrFixed, uAlignment, fProt, R0Process, pszTag); +} +int RTR0MemObjProtect(RTR0MEMOBJ hMemObj, size_t offSub, size_t cbSub, uint32_t fProt) +{ + return g_VBoxGuest->_RTR0MemObjProtect(hMemObj, offSub, cbSub, fProt); +} +int RTR0MemObjReserveKernelTag(PRTR0MEMOBJ pMemObj, void *pvFixed, size_t cb, size_t uAlignment, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjReserveKernelTag(pMemObj, pvFixed, cb, uAlignment, pszTag); +} +int RTR0MemObjReserveUserTag(PRTR0MEMOBJ pMemObj, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, RTR0PROCESS R0Process, const char *pszTag) +{ + return g_VBoxGuest->_RTR0MemObjReserveUserTag(pMemObj, R3PtrFixed, cb, uAlignment, R0Process, pszTag); +} +size_t RTR0MemObjSize(RTR0MEMOBJ MemObj) +{ + return g_VBoxGuest->_RTR0MemObjSize(MemObj); +} +RTR0PROCESS RTR0ProcHandleSelf(void) +{ + return g_VBoxGuest->_RTR0ProcHandleSelf(); +} +void RTR0Term(void) +{ + g_VBoxGuest->_RTR0Term(); +} +void RTR0TermForced(void) +{ + g_VBoxGuest->_RTR0TermForced(); +} +RTPROCESS RTProcSelf(void) +{ + return g_VBoxGuest->_RTProcSelf(); +} +uint32_t RTSemEventGetResolution(void) +{ + return g_VBoxGuest->_RTSemEventGetResolution(); +} +uint32_t RTSemEventMultiGetResolution(void) +{ + return g_VBoxGuest->_RTSemEventMultiGetResolution(); +} +int RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout) +{ + return g_VBoxGuest->_RTSemEventMultiWaitEx(hEventMultiSem, fFlags, uTimeout); +} +int RTSemEventMultiWaitExDebug(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout, RTHCUINTPTR uId, RT_SRC_POS_DECL) +{ + return g_VBoxGuest->_RTSemEventMultiWaitExDebug(hEventMultiSem, fFlags, uTimeout, uId, pszFile, iLine, pszFunction); +} +int RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout) +{ + return g_VBoxGuest->_RTSemEventWaitEx(hEventSem, fFlags, uTimeout); +} +int RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, RTHCUINTPTR uId, RT_SRC_POS_DECL) +{ + return g_VBoxGuest->_RTSemEventWaitExDebug(hEventSem, fFlags, uTimeout, uId, pszFile, iLine, pszFunction); +} +bool RTThreadIsInInterrupt(RTTHREAD hThread) +{ + return g_VBoxGuest->_RTThreadIsInInterrupt(hThread); +} +void RTThreadPreemptDisable(PRTTHREADPREEMPTSTATE pState) +{ + g_VBoxGuest->_RTThreadPreemptDisable(pState); +} +bool RTThreadPreemptIsEnabled(RTTHREAD hThread) +{ + return g_VBoxGuest->_RTThreadPreemptIsEnabled(hThread); +} +bool RTThreadPreemptIsPending(RTTHREAD hThread) +{ + return g_VBoxGuest->_RTThreadPreemptIsPending(hThread); +} +bool RTThreadPreemptIsPendingTrusty(void) +{ + return g_VBoxGuest->_RTThreadPreemptIsPendingTrusty(); +} +bool RTThreadPreemptIsPossible(void) +{ + return g_VBoxGuest->_RTThreadPreemptIsPossible(); +} +void RTThreadPreemptRestore(PRTTHREADPREEMPTSTATE pState) +{ + g_VBoxGuest->_RTThreadPreemptRestore(pState); +} +uint32_t RTTimerGetSystemGranularity(void) +{ + return g_VBoxGuest->_RTTimerGetSystemGranularity(); +} +int RTTimerReleaseSystemGranularity(uint32_t u32Granted) +{ + return g_VBoxGuest->_RTTimerReleaseSystemGranularity(u32Granted); +} +int RTTimerRequestSystemGranularity(uint32_t u32Request, uint32_t *pu32Granted) +{ + return g_VBoxGuest->_RTTimerRequestSystemGranularity(u32Request, pu32Granted); +} +void RTSpinlockAcquire(RTSPINLOCK Spinlock) +{ + g_VBoxGuest->_RTSpinlockAcquire(Spinlock); +} +void RTSpinlockRelease(RTSPINLOCK Spinlock) +{ + g_VBoxGuest->_RTSpinlockRelease(Spinlock); +} +void RTSpinlockReleaseNoInts(RTSPINLOCK Spinlock) +{ + g_VBoxGuest->_RTSpinlockReleaseNoInts(Spinlock); +} +void* RTMemTmpAllocTag(size_t cb, const char *pszTag) +{ + return g_VBoxGuest->_RTMemTmpAllocTag(cb, pszTag); +} +void RTMemTmpFree(void *pv) +{ + g_VBoxGuest->_RTMemTmpFree(pv); +} +PRTLOGGER RTLogDefaultInstance(void) +{ + return g_VBoxGuest->_RTLogDefaultInstance(); +} +PRTLOGGER RTLogRelDefaultInstance(void) +{ + return g_VBoxGuest->_RTLogRelDefaultInstance(); +} +int RTErrConvertToErrno(int iErr) +{ + return g_VBoxGuest->_RTErrConvertToErrno(iErr); +} +int VBoxGuestCommonIOCtl(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, void *pvData, size_t cbData, size_t *pcbDataReturned) +{ + return g_VBoxGuest->_VBoxGuestCommonIOCtl(iFunction, pDevExt, pSession, pvData, cbData, pcbDataReturned); +} +int VBoxGuestCreateUserSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *ppSession) +{ + return g_VBoxGuest->_VBoxGuestCreateUserSession(pDevExt, ppSession); +} +void VBoxGuestCloseSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession) +{ + g_VBoxGuest->_VBoxGuestCloseSession(pDevExt, pSession); +} +void* VBoxGuestIDCOpen(uint32_t *pu32Version) +{ + return g_VBoxGuest->_VBoxGuestIDCOpen(pu32Version); +} +int VBoxGuestIDCClose(void *pvSession) +{ + return g_VBoxGuest->_VBoxGuestIDCClose(pvSession); +} +int VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned) +{ + return g_VBoxGuest->_VBoxGuestIDCCall(pvSession, iCmd, pvData, cbData, pcbDataReturned); +} +void RTAssertMsg1Weak(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction) +{ + g_VBoxGuest->_RTAssertMsg1Weak(pszExpr, uLine, pszFile, pszFunction); +} +void RTAssertMsg2Weak(const char *pszFormat, ...) +{ + va_list va; + va_start(va, pszFormat); + RTAssertMsg2WeakV(pszFormat, va); + va_end(va); +} +void RTAssertMsg2WeakV(const char *pszFormat, va_list va) +{ + g_VBoxGuest->_RTAssertMsg2WeakV(pszFormat, va); +} +bool RTAssertShouldPanic(void) +{ + return g_VBoxGuest->_RTAssertShouldPanic(); +} +int RTSemFastMutexCreate(PRTSEMFASTMUTEX phFastMtx) +{ + return g_VBoxGuest->_RTSemFastMutexCreate(phFastMtx); +} +int RTSemFastMutexDestroy(RTSEMFASTMUTEX hFastMtx) +{ + return g_VBoxGuest->_RTSemFastMutexDestroy(hFastMtx); +} +int RTSemFastMutexRelease(RTSEMFASTMUTEX hFastMtx) +{ + return g_VBoxGuest->_RTSemFastMutexRelease(hFastMtx); +} +int RTSemFastMutexRequest(RTSEMFASTMUTEX hFastMtx) +{ + return g_VBoxGuest->_RTSemFastMutexRequest(hFastMtx); +} +int RTSemMutexCreate(PRTSEMMUTEX phFastMtx) +{ + return g_VBoxGuest->_RTSemMutexCreate(phFastMtx); +} +int RTSemMutexDestroy(RTSEMMUTEX hFastMtx) +{ + return g_VBoxGuest->_RTSemMutexDestroy(hFastMtx); +} +int RTSemMutexRelease(RTSEMMUTEX hFastMtx) +{ + return g_VBoxGuest->_RTSemMutexRelease(hFastMtx); +} +int RTSemMutexRequest(RTSEMMUTEX hFastMtx, RTMSINTERVAL cMillies) +{ + return g_VBoxGuest->_RTSemMutexRequest(hFastMtx, cMillies); +} +int RTHeapSimpleRelocate(RTHEAPSIMPLE hHeap, uintptr_t offDelta) +{ + return g_VBoxGuest->_RTHeapSimpleRelocate(hHeap, offDelta); +} +int RTHeapOffsetInit(PRTHEAPOFFSET phHeap, void *pvMemory, size_t cbMemory) +{ + return g_VBoxGuest->_RTHeapOffsetInit(phHeap, pvMemory, cbMemory); +} +int RTHeapSimpleInit(PRTHEAPSIMPLE pHeap, void *pvMemory, size_t cbMemory) +{ + return g_VBoxGuest->_RTHeapSimpleInit(pHeap, pvMemory, cbMemory); +} +void* RTHeapOffsetAlloc(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment) +{ + return g_VBoxGuest->_RTHeapOffsetAlloc(hHeap, cb, cbAlignment); +} +void* RTHeapSimpleAlloc(RTHEAPSIMPLE Heap, size_t cb, size_t cbAlignment) +{ + return g_VBoxGuest->_RTHeapSimpleAlloc(Heap, cb, cbAlignment); +} +void RTHeapOffsetFree(RTHEAPOFFSET hHeap, void *pv) +{ + g_VBoxGuest->_RTHeapOffsetFree(hHeap, pv); +} +void RTHeapSimpleFree(RTHEAPSIMPLE Heap, void *pv) +{ + g_VBoxGuest->_RTHeapSimpleFree(Heap, pv); +} + diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.c new file mode 100644 index 00000000..5aa31702 --- /dev/null +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.c @@ -0,0 +1,553 @@ +/* $Id: VBoxGuest-haiku.c $ */ +/** @file + * VBoxGuest kernel module, Haiku Guest Additions, 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. + */ + +/* + * This code is based on: + * + * VirtualBox Guest Additions for Haiku. + * Copyright (c) 2011 Mike Smith <mike@scgtrp.net> + * François Revol <revol@free.fr> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +/******************************************************************************* +* Header Files * +*******************************************************************************/ +#define IN_VBOXGUEST +#include <sys/param.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <OS.h> +#include <Drivers.h> +#include <KernelExport.h> +#include <PCI.h> + +#include "VBoxGuest-haiku.h" +#include "VBoxGuestInternal.h" +#include <VBox/log.h> +#include <iprt/assert.h> +#include <iprt/initterm.h> +#include <iprt/process.h> +#include <iprt/mem.h> +#include <iprt/memobj.h> +#include <iprt/asm.h> +#include <iprt/timer.h> +#include <iprt/heap.h> + +#define MODULE_NAME VBOXGUEST_MODULE_NAME + +/* + * IRQ related functions. + */ +static void VBoxGuestHaikuRemoveIRQ(void *pvState); +static int VBoxGuestHaikuAddIRQ(void *pvState); +static int32 VBoxGuestHaikuISR(void *pvState); + +/* + * Available functions for kernel drivers. + */ +DECLVBGL(int) VBoxGuestHaikuServiceCall(void *pvSession, unsigned uCmd, void *pvData, size_t cbData, size_t *pcbDataReturned); +DECLVBGL(void *) VBoxGuestHaikuServiceOpen(uint32_t *pu32Version); +DECLVBGL(int) VBoxGuestHaikuServiceClose(void *pvSession); +DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version); +DECLVBGL(int) VBoxGuestIDCClose(void *pvSession); +DECLVBGL(int) VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned); + +static status_t std_ops(int32 op, ...); + +static RTSPINLOCK g_Spinlock = NIL_RTSPINLOCK; + +int32 api_version = B_CUR_DRIVER_API_VERSION; + +/** List of cloned device. Managed by the kernel. */ +//static struct clonedevs *g_pVBoxGuestHaikuClones; +/** The dev_clone event handler tag. */ +//static eventhandler_tag g_VBoxGuestHaikuEHTag; +/** selinfo structure used for polling. */ +//static struct selinfo g_SelInfo; +/** PCI Bus Manager Module */ +static pci_module_info *gPCI; + +static struct vboxguest_module_info g_VBoxGuest = +{ + { + MODULE_NAME, + 0, + std_ops + }, + { 0 }, + { 0 }, + 0, + RTLogBackdoorPrintf, + RTLogBackdoorPrintfV, + RTLogSetDefaultInstanceThread, + RTMemAllocExTag, + RTMemContAlloc, + RTMemContFree, + RTMemFreeEx, + RTMpIsCpuPossible, + RTMpNotificationDeregister, + RTMpNotificationRegister, + RTMpOnAll, + RTMpOnOthers, + RTMpOnSpecific, + RTPowerNotificationDeregister, + RTPowerNotificationRegister, + RTPowerSignalEvent, + RTR0AssertPanicSystem, + RTR0Init, + RTR0MemObjAddress, + RTR0MemObjAddressR3, + RTR0MemObjAllocContTag, + RTR0MemObjAllocLowTag, + RTR0MemObjAllocPageTag, + RTR0MemObjAllocPhysExTag, + RTR0MemObjAllocPhysNCTag, + RTR0MemObjAllocPhysTag, + RTR0MemObjEnterPhysTag, + RTR0MemObjFree, + RTR0MemObjGetPagePhysAddr, + RTR0MemObjIsMapping, + RTR0MemObjLockKernelTag, + RTR0MemObjLockUserTag, + RTR0MemObjMapKernelExTag, + RTR0MemObjMapKernelTag, + RTR0MemObjMapUserTag, + RTR0MemObjProtect, + RTR0MemObjReserveKernelTag, + RTR0MemObjReserveUserTag, + RTR0MemObjSize, + RTR0ProcHandleSelf, + RTR0Term, + RTR0TermForced, + RTProcSelf, + RTSemEventGetResolution, + RTSemEventMultiGetResolution, + RTSemEventMultiWaitEx, + RTSemEventMultiWaitExDebug, + RTSemEventWaitEx, + RTSemEventWaitExDebug, + RTThreadIsInInterrupt, + RTThreadPreemptDisable, + RTThreadPreemptIsEnabled, + RTThreadPreemptIsPending, + RTThreadPreemptIsPendingTrusty, + RTThreadPreemptIsPossible, + RTThreadPreemptRestore, + RTTimerGetSystemGranularity, + RTTimerReleaseSystemGranularity, + RTTimerRequestSystemGranularity, + RTSpinlockAcquire, + RTSpinlockRelease, + RTSpinlockReleaseNoInts, + RTMemTmpAllocTag, + RTMemTmpFree, + RTLogDefaultInstance, + RTLogRelDefaultInstance, + RTErrConvertToErrno, + VBoxGuestCommonIOCtl, + VBoxGuestCreateUserSession, + VBoxGuestCloseSession, + VBoxGuestIDCOpen, + VBoxGuestIDCClose, + VBoxGuestIDCCall, + RTAssertMsg1Weak, + RTAssertMsg2Weak, + RTAssertMsg2WeakV, + RTAssertShouldPanic, + RTSemFastMutexCreate, + RTSemFastMutexDestroy, + RTSemFastMutexRelease, + RTSemFastMutexRequest, + RTSemMutexCreate, + RTSemMutexDestroy, + RTSemMutexRelease, + RTSemMutexRequest, + RTHeapSimpleRelocate, + RTHeapOffsetInit, + RTHeapSimpleInit, + RTHeapOffsetAlloc, + RTHeapSimpleAlloc, + RTHeapOffsetFree, + RTHeapSimpleFree +}; + +#if 0 +/** + * DEVFS event handler. + */ +static void VBoxGuestHaikuClone(void *pvArg, struct ucred *pCred, char *pszName, int cchName, struct cdev **ppDev) +{ + int iUnit; + int rc; + + Log(("VBoxGuestHaikuClone: pszName=%s ppDev=%p\n", pszName, ppDev)); + + /* + * One device node per user, si_drv1 points to the session. + * /dev/vboxguest<N> where N = {0...255}. + */ + if (!ppDev) + return; + if (strcmp(pszName, "vboxguest") == 0) + iUnit = -1; + else if (dev_stdclone(pszName, NULL, "vboxguest", &iUnit) != 1) + return; + if (iUnit >= 256) + { + Log(("VBoxGuestHaikuClone: iUnit=%d >= 256 - rejected\n", iUnit)); + return; + } + + Log(("VBoxGuestHaikuClone: pszName=%s iUnit=%d\n", pszName, iUnit)); + + rc = clone_create(&g_pVBoxGuestHaikuClones, &g_VBoxGuestHaikuDeviceHooks, &iUnit, ppDev, 0); + Log(("VBoxGuestHaikuClone: clone_create -> %d; iUnit=%d\n", rc, iUnit)); + if (rc) + { + *ppDev = make_dev(&g_VBoxGuestHaikuDeviceHooks, + iUnit, + UID_ROOT, + GID_WHEEL, + 0644, + "vboxguest%d", iUnit); + if (*ppDev) + { + dev_ref(*ppDev); + (*ppDev)->si_flags |= SI_CHEAPCLONE; + Log(("VBoxGuestHaikuClone: Created *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", + *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); + (*ppDev)->si_drv1 = (*ppDev)->si_drv2 = NULL; + } + else + Log(("VBoxGuestHaikuClone: make_dev iUnit=%d failed\n", iUnit)); + } + else + Log(("VBoxGuestHaikuClone: Existing *ppDev=%p iUnit=%d si_drv1=%p si_drv2=%p\n", + *ppDev, iUnit, (*ppDev)->si_drv1, (*ppDev)->si_drv2)); +} +#endif + + +static status_t VBoxGuestHaikuDetach(void) +{ + struct VBoxGuestDeviceState *pState = &sState; + + if (cUsers > 0) + return EBUSY; + + /* + * Reverse what we did in VBoxGuestHaikuAttach. + */ + VBoxGuestHaikuRemoveIRQ(pState); + + if (pState->iVMMDevMemAreaId) + delete_area(pState->iVMMDevMemAreaId); + + VBoxGuestDeleteDevExt(&g_DevExt); + +#ifdef DO_LOG + RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); + RTLogSetDefaultInstance(NULL); +// RTLogDestroy(RTLogSetDefaultInstance(NULL)); +#endif + + RTSpinlockDestroy(g_Spinlock); + g_Spinlock = NIL_RTSPINLOCK; + + RTR0Term(); + return B_OK; +} + + +/** + * Interrupt service routine. + * + * @returns Whether the interrupt was from VMMDev. + * @param pvState Opaque pointer to the device state. + */ +static int32 VBoxGuestHaikuISR(void *pvState) +{ + LogFlow((MODULE_NAME ":VBoxGuestHaikuISR pvState=%p\n", pvState)); + + bool fOurIRQ = VBoxGuestCommonISR(&g_DevExt); + if (fOurIRQ) + return B_HANDLED_INTERRUPT; + return B_UNHANDLED_INTERRUPT; +} + + +void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) +{ + LogFlow((MODULE_NAME "::NativeISRMousePollEvent:\n")); + + status_t err = B_OK; + //dprintf(MODULE_NAME ": isr mouse\n"); + + /* + * Wake up poll waiters. + */ + //selwakeup(&g_SelInfo); + //XXX:notify_select_event(); + RTSpinlockAcquire(g_Spinlock); + + if (sState.selectSync) + { + //dprintf(MODULE_NAME ": isr mouse: notify\n"); + notify_select_event(sState.selectSync, sState.selectEvent); + sState.selectEvent = (uint8_t)0; + sState.selectRef = (uint32_t)0; + sState.selectSync = NULL; + } + else + err = B_ERROR; + + RTSpinlockRelease(g_Spinlock); +} + + +/** + * Sets IRQ for VMMDev. + * + * @returns Haiku error code. + * @param pvState Pointer to the state info structure. + */ +static int VBoxGuestHaikuAddIRQ(void *pvState) +{ + status_t err; + struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState; + + AssertReturn(pState, VERR_INVALID_PARAMETER); + + err = install_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState, 0); + if (err == B_OK) + return VINF_SUCCESS; + return VERR_DEV_IO_ERROR; +} + + +/** + * Removes IRQ for VMMDev. + * + * @param pvState Opaque pointer to the state info structure. + */ +static void VBoxGuestHaikuRemoveIRQ(void *pvState) +{ + struct VBoxGuestDeviceState *pState = (struct VBoxGuestDeviceState *)pvState; + AssertPtr(pState); + + remove_io_interrupt_handler(pState->iIrqResId, VBoxGuestHaikuISR, pState); +} + + +static status_t VBoxGuestHaikuAttach(const pci_info *pDevice) +{ + status_t status; + int rc = VINF_SUCCESS; + int iResId = 0; + struct VBoxGuestDeviceState *pState = &sState; + static const char *const s_apszGroups[] = VBOX_LOGGROUP_NAMES; + PRTLOGGER pRelLogger; + + AssertReturn(pDevice, B_BAD_VALUE); + + cUsers = 0; + + /* + * Initialize IPRT R0 driver, which internally calls OS-specific r0 init. + */ + rc = RTR0Init(0); + if (RT_FAILURE(rc)) + { + /** @todo r=ramshankar: use dprintf here. */ + LogFunc(("RTR0Init failed.\n")); + return ENXIO; + } + + rc = RTSpinlockCreate(&g_Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxGuestHaiku"); + if (RT_FAILURE(rc)) + { + LogRel(("VBoxGuestHaikuAttach: RTSpinlock create failed. rc=%Rrc\n", rc)); + return ENXIO; + } + +#ifdef DO_LOG + /* + * Create the release log. + * (We do that here instead of common code because we want to log + * early failures using the LogRel macro.) + */ + rc = RTLogCreate(&pRelLogger, 0 | RTLOGFLAGS_PREFIX_THREAD /* fFlags */, "all", + "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, + RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL); + dprintf(MODULE_NAME ": RTLogCreate: %d\n", rc); + if (RT_SUCCESS(rc)) + { + //RTLogGroupSettings(pRelLogger, g_szLogGrp); + //RTLogFlags(pRelLogger, g_szLogFlags); + //RTLogDestinations(pRelLogger, "/var/log/vboxguest.log"); + RTLogRelSetDefaultInstance(pRelLogger); + RTLogSetDefaultInstance(pRelLogger); //XXX + } +#endif + + /* + * Allocate I/O port resource. + */ + pState->uIOPortBase = pDevice->u.h0.base_registers[0]; + /* @todo check flags for IO? */ + if (pState->uIOPortBase) + { + /* + * Map the MMIO region. + */ + uint32 phys = pDevice->u.h0.base_registers[1]; + /* @todo Check flags for mem? */ + pState->VMMDevMemSize = pDevice->u.h0.base_register_sizes[1]; + pState->iVMMDevMemAreaId = map_physical_memory("VirtualBox Guest MMIO", phys, pState->VMMDevMemSize, + B_ANY_KERNEL_BLOCK_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, + &pState->pMMIOBase); + if (pState->iVMMDevMemAreaId > 0 && pState->pMMIOBase) + { + /* + * Call the common device extension initializer. + */ + rc = VBoxGuestInitDevExt(&g_DevExt, pState->uIOPortBase, pState->pMMIOBase, pState->VMMDevMemSize, +#if ARCH_BITS == 64 + VBOXOSTYPE_Haiku_x64, +#else + VBOXOSTYPE_Haiku, +#endif + VMMDEV_EVENT_MOUSE_POSITION_CHANGED); + if (RT_SUCCESS(rc)) + { + /* + * Add IRQ of VMMDev. + */ + pState->iIrqResId = pDevice->u.h0.interrupt_line; + rc = VBoxGuestHaikuAddIRQ(pState); + if (RT_SUCCESS(rc)) + { + LogRel((MODULE_NAME ": loaded successfully\n")); + return B_OK; + } + + LogRel((MODULE_NAME ":VBoxGuestInitDevExt failed.\n")); + VBoxGuestDeleteDevExt(&g_DevExt); + } + else + LogRel((MODULE_NAME ":VBoxGuestHaikuAddIRQ failed.\n")); + } + else + LogRel((MODULE_NAME ":MMIO region setup failed.\n")); + } + else + LogRel((MODULE_NAME ":IOport setup failed.\n")); + + RTR0Term(); + return ENXIO; +} + + +static status_t VBoxGuestHaikuProbe(pci_info *pDevice) +{ + if ((pDevice->vendor_id == VMMDEV_VENDORID) && (pDevice->device_id == VMMDEV_DEVICEID)) + return B_OK; + + return ENXIO; +} + + +status_t init_module(void) +{ + status_t err = B_ENTRY_NOT_FOUND; + pci_info info; + int ix = 0; + + err = get_module(B_PCI_MODULE_NAME, (module_info **)&gPCI); + if (err != B_OK) + return err; + + while ((*gPCI->get_nth_pci_info)(ix++, &info) == B_OK) + { + if (VBoxGuestHaikuProbe(&info) == 0) + { + /* We found it */ + err = VBoxGuestHaikuAttach(&info); + return err; + } + } + + return B_ENTRY_NOT_FOUND; +} + + +void uninit_module(void) +{ + VBoxGuestHaikuDetach(); + put_module(B_PCI_MODULE_NAME); +} + + +static status_t std_ops(int32 op, ...) +{ + switch (op) + { + case B_MODULE_INIT: + return init_module(); + + case B_MODULE_UNINIT: + { + uninit_module(); + return B_OK; + } + + default: + return B_ERROR; + } +} + + +_EXPORT module_info *modules[] = +{ + (module_info *)&g_VBoxGuest, + NULL +}; + +/* Common code that depend on g_DevExt. */ +#include "VBoxGuestIDC-unix.c.h" + diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.h b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.h new file mode 100644 index 00000000..d577448c --- /dev/null +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-haiku.h @@ -0,0 +1,226 @@ +/* $Id: VBoxGuest-haiku.h $ */ +/** @file + * VBoxGuest kernel module, Haiku Guest Additions, header. + */ + +/* + * 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. + */ + +/* + * This code is based on: + * + * VirtualBox Guest Additions for Haiku. + * Copyright (c) 2011 Mike Smith <mike@scgtrp.net> + * François Revol <revol@free.fr> + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef ___VBoxGuest_haiku_h +#define ___VBoxGuest_haiku_h + +#include <OS.h> +#include <Drivers.h> +#include <drivers/module.h> + +#include "VBoxGuestInternal.h" +#include <VBox/log.h> +#include <iprt/assert.h> +#include <iprt/initterm.h> +#include <iprt/process.h> +#include <iprt/mem.h> +#include <iprt/asm.h> +#include <iprt/mp.h> +#include <iprt/power.h> +#include <iprt/thread.h> + +/** The module name. */ +#define VBOXGUEST_MODULE_NAME "generic/vboxguest" + +struct VBoxGuestDeviceState +{ + /** Resource ID of the I/O port */ + int iIOPortResId; + /** Pointer to the I/O port resource. */ +// struct resource *pIOPortRes; + /** Start address of the IO Port. */ + uint16_t uIOPortBase; + /** Resource ID of the MMIO area */ + area_id iVMMDevMemAreaId; + /** Pointer to the MMIO resource. */ +// struct resource *pVMMDevMemRes; + /** Handle of the MMIO resource. */ +// bus_space_handle_t VMMDevMemHandle; + /** Size of the memory area. */ + size_t VMMDevMemSize; + /** Mapping of the register space */ + void *pMMIOBase; + /** IRQ number */ + int iIrqResId; + /** IRQ resource handle. */ +// struct resource *pIrqRes; + /** Pointer to the IRQ handler. */ +// void *pfnIrqHandler; + /** VMMDev version */ + uint32_t u32Version; + + /** The (only) select data we wait on. */ + //XXX: should leave in pSession ? + uint8_t selectEvent; + uint32_t selectRef; + void *selectSync; +}; + +struct vboxguest_module_info +{ + module_info module; + + VBOXGUESTDEVEXT devExt; + struct VBoxGuestDeviceState _sState; + volatile uint32_t _cUsers; + + size_t(*_RTLogBackdoorPrintf)(const char *pszFormat, ...); + size_t(*_RTLogBackdoorPrintfV)(const char *pszFormat, va_list args); + int (*_RTLogSetDefaultInstanceThread)(PRTLOGGER pLogger, uintptr_t uKey); + int (*_RTMemAllocExTag)(size_t cb, size_t cbAlignment, uint32_t fFlags, const char *pszTag, void **ppv); + void* (*_RTMemContAlloc)(PRTCCPHYS pPhys, size_t cb); + void (*_RTMemContFree)(void *pv, size_t cb); + void (*_RTMemFreeEx)(void *pv, size_t cb); + bool (*_RTMpIsCpuPossible)(RTCPUID idCpu); + int (*_RTMpNotificationDeregister)(PFNRTMPNOTIFICATION pfnCallback, void *pvUser); + int (*_RTMpNotificationRegister)(PFNRTMPNOTIFICATION pfnCallback, void *pvUser); + int (*_RTMpOnAll)(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2); + int (*_RTMpOnOthers)(PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2); + int (*_RTMpOnSpecific)(RTCPUID idCpu, PFNRTMPWORKER pfnWorker, void *pvUser1, void *pvUser2); + int (*_RTPowerNotificationDeregister)(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser); + int (*_RTPowerNotificationRegister)(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser); + int (*_RTPowerSignalEvent)(RTPOWEREVENT enmEvent); + void (*_RTR0AssertPanicSystem)(void); + int (*_RTR0Init)(unsigned fReserved); + void* (*_RTR0MemObjAddress)(RTR0MEMOBJ MemObj); + RTR3PTR(*_RTR0MemObjAddressR3)(RTR0MEMOBJ MemObj); + int (*_RTR0MemObjAllocContTag)(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag); + int (*_RTR0MemObjAllocLowTag)(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag); + int (*_RTR0MemObjAllocPageTag)(PRTR0MEMOBJ pMemObj, size_t cb, bool fExecutable, const char *pszTag); + int (*_RTR0MemObjAllocPhysExTag)(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, size_t uAlignment, const char *pszTag); + int (*_RTR0MemObjAllocPhysNCTag)(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag); + int (*_RTR0MemObjAllocPhysTag)(PRTR0MEMOBJ pMemObj, size_t cb, RTHCPHYS PhysHighest, const char *pszTag); + int (*_RTR0MemObjEnterPhysTag)(PRTR0MEMOBJ pMemObj, RTHCPHYS Phys, size_t cb, uint32_t uCachePolicy, const char *pszTag); + int (*_RTR0MemObjFree)(RTR0MEMOBJ MemObj, bool fFreeMappings); + RTHCPHYS(*_RTR0MemObjGetPagePhysAddr)(RTR0MEMOBJ MemObj, size_t iPage); + bool (*_RTR0MemObjIsMapping)(RTR0MEMOBJ MemObj); + int (*_RTR0MemObjLockKernelTag)(PRTR0MEMOBJ pMemObj, void *pv, size_t cb, uint32_t fAccess, const char *pszTag); + int (*_RTR0MemObjLockUserTag)(PRTR0MEMOBJ pMemObj, RTR3PTR R3Ptr, size_t cb, uint32_t fAccess, + RTR0PROCESS R0Process, const char *pszTag); + int (*_RTR0MemObjMapKernelExTag)(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, size_t uAlignment, + unsigned fProt, size_t offSub, size_t cbSub, const char *pszTag); + int (*_RTR0MemObjMapKernelTag)(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, void *pvFixed, + size_t uAlignment, unsigned fProt, const char *pszTag); + int (*_RTR0MemObjMapUserTag)(PRTR0MEMOBJ pMemObj, RTR0MEMOBJ MemObjToMap, RTR3PTR R3PtrFixed, + size_t uAlignment, unsigned fProt, RTR0PROCESS R0Process, const char *pszTag); + int (*_RTR0MemObjProtect)(RTR0MEMOBJ hMemObj, size_t offSub, size_t cbSub, uint32_t fProt); + int (*_RTR0MemObjReserveKernelTag)(PRTR0MEMOBJ pMemObj, void *pvFixed, size_t cb, size_t uAlignment, const char *pszTag); + int (*_RTR0MemObjReserveUserTag)(PRTR0MEMOBJ pMemObj, RTR3PTR R3PtrFixed, size_t cb, size_t uAlignment, + RTR0PROCESS R0Process, const char *pszTag); + size_t(*_RTR0MemObjSize)(RTR0MEMOBJ MemObj); + RTR0PROCESS(*_RTR0ProcHandleSelf)(void); + void (*_RTR0Term)(void); + void (*_RTR0TermForced)(void); + RTPROCESS(*_RTProcSelf)(void); + uint32_t(*_RTSemEventGetResolution)(void); + uint32_t(*_RTSemEventMultiGetResolution)(void); + int (*_RTSemEventMultiWaitEx)(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout); + int (*_RTSemEventMultiWaitExDebug)(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL); + int (*_RTSemEventWaitEx)(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout); + int (*_RTSemEventWaitExDebug)(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, + RTHCUINTPTR uId, RT_SRC_POS_DECL); + bool (*_RTThreadIsInInterrupt)(RTTHREAD hThread); + void (*_RTThreadPreemptDisable)(PRTTHREADPREEMPTSTATE pState); + bool (*_RTThreadPreemptIsEnabled)(RTTHREAD hThread); + bool (*_RTThreadPreemptIsPending)(RTTHREAD hThread); + bool (*_RTThreadPreemptIsPendingTrusty)(void); + bool (*_RTThreadPreemptIsPossible)(void); + void (*_RTThreadPreemptRestore)(PRTTHREADPREEMPTSTATE pState); + uint32_t(*_RTTimerGetSystemGranularity)(void); + int (*_RTTimerReleaseSystemGranularity)(uint32_t u32Granted); + int (*_RTTimerRequestSystemGranularity)(uint32_t u32Request, uint32_t *pu32Granted); + void (*_RTSpinlockAcquire)(RTSPINLOCK Spinlock); + void (*_RTSpinlockRelease)(RTSPINLOCK Spinlock); + void (*_RTSpinlockReleaseNoInts)(RTSPINLOCK Spinlock); + void* (*_RTMemTmpAllocTag)(size_t cb, const char *pszTag); + void (*_RTMemTmpFree)(void *pv); + PRTLOGGER(*_RTLogDefaultInstance)(void); + PRTLOGGER(*_RTLogRelDefaultInstance)(void); + int (*_RTErrConvertToErrno)(int iErr); + int (*_VBoxGuestCommonIOCtl)(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, + void *pvData, size_t cbData, size_t *pcbDataReturned); + int (*_VBoxGuestCreateUserSession)(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *ppSession); + void (*_VBoxGuestCloseSession)(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession); + void* (*_VBoxGuestIDCOpen)(uint32_t *pu32Version); + int (*_VBoxGuestIDCClose)(void *pvSession); + int (*_VBoxGuestIDCCall)(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned); + void (*_RTAssertMsg1Weak)(const char *pszExpr, unsigned uLine, const char *pszFile, const char *pszFunction); + void (*_RTAssertMsg2Weak)(const char *pszFormat, ...); + void (*_RTAssertMsg2WeakV)(const char *pszFormat, va_list va); + bool (*_RTAssertShouldPanic)(void); + int (*_RTSemFastMutexCreate)(PRTSEMFASTMUTEX phFastMtx); + int (*_RTSemFastMutexDestroy)(RTSEMFASTMUTEX hFastMtx); + int (*_RTSemFastMutexRelease)(RTSEMFASTMUTEX hFastMtx); + int (*_RTSemFastMutexRequest)(RTSEMFASTMUTEX hFastMtx); + int (*_RTSemMutexCreate)(PRTSEMMUTEX phFastMtx); + int (*_RTSemMutexDestroy)(RTSEMMUTEX hFastMtx); + int (*_RTSemMutexRelease)(RTSEMMUTEX hFastMtx); + int (*_RTSemMutexRequest)(RTSEMMUTEX hFastMtx, RTMSINTERVAL cMillies); + int (*_RTHeapSimpleRelocate)(RTHEAPSIMPLE hHeap, uintptr_t offDelta); + int (*_RTHeapOffsetInit)(PRTHEAPOFFSET phHeap, void *pvMemory, size_t cbMemory); + int (*_RTHeapSimpleInit)(PRTHEAPSIMPLE pHeap, void *pvMemory, size_t cbMemory); + void* (*_RTHeapOffsetAlloc)(RTHEAPOFFSET hHeap, size_t cb, size_t cbAlignment); + void* (*_RTHeapSimpleAlloc)(RTHEAPSIMPLE Heap, size_t cb, size_t cbAlignment); + void (*_RTHeapOffsetFree)(RTHEAPOFFSET hHeap, void *pv); + void (*_RTHeapSimpleFree)(RTHEAPSIMPLE Heap, void *pv); +}; + + +#ifdef IN_VBOXGUEST +#define g_DevExt (g_VBoxGuest.devExt) +#define cUsers (g_VBoxGuest._cUsers) +#define sState (g_VBoxGuest._sState) +#else +#define g_DevExt (g_VBoxGuest->devExt) +#define cUsers (g_VBoxGuest->_cUsers) +#define sState (g_VBoxGuest->_sState) +extern struct vboxguest_module_info *g_VBoxGuest; +#endif + +#endif /* ___VBoxGuest_haiku_h */ + diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c index b4270bae..a4824893 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c @@ -1,4 +1,4 @@ -/* $Rev: 80789 $ */ +/* $Rev: 88900 $ */ /** @file * VBoxGuest - Linux specifics. * @@ -7,7 +7,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; @@ -196,7 +196,11 @@ static struct miscdevice g_MiscDeviceUser = /** PCI hotplug structure. */ -static const struct pci_device_id __devinitdata g_VBoxGuestPciId[] = +static const struct pci_device_id +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 8, 0) +__devinitdata +#endif +g_VBoxGuestPciId[] = { { vendor: VMMDEV_VENDORID, @@ -936,9 +940,9 @@ void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) * Wake up everyone that's in a poll() and post anyone that has * subscribed to async notifications. */ - Log(("VBoxGuestNativeISRMousePollEvent: wake_up_all\n")); + Log3(("VBoxGuestNativeISRMousePollEvent: wake_up_all\n")); wake_up_all(&g_PollEventQueue); - Log(("VBoxGuestNativeISRMousePollEvent: kill_fasync\n")); + Log3(("VBoxGuestNativeISRMousePollEvent: kill_fasync\n")); kill_fasync(&g_pFAsyncQueue, SIGIO, POLL_IN); #ifdef VBOXGUEST_WITH_INPUT_DRIVER /* Report events to the kernel input device */ @@ -957,7 +961,7 @@ void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) # endif } #endif - Log(("VBoxGuestNativeISRMousePollEvent: done\n")); + Log3(("VBoxGuestNativeISRMousePollEvent: done\n")); } diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.cpp b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.cpp index a74f5595..c4ba2219 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.cpp +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * 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; @@ -19,7 +19,7 @@ * * VBoxDrv - OS/2 specifics. * - * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> + * Copyright (c) 2007-2012 knut st. osmundsen <bird-src-spam@anduin.net> * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.def b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.def index 4728686e..15c04914 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.def +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-os2.def @@ -4,7 +4,7 @@ ; ; -; Copyright (C) 2007 Oracle Corporation +; Copyright (C) 2007-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/Additions/common/VBoxGuest/VBoxGuest-solaris.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c index a94e3848..7c7ff3fc 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.c @@ -696,6 +696,8 @@ static int VBoxGuestSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArg, int Mode, cr * which are not really failures that require logging. */ Log((DEVICE_NAME "::IOCtl: VBoxGuestCommonIOCtl failed. Cmd=%#x rc=%d\n", Cmd, rc)); + if (rc == VERR_PERMISSION_DENIED) /* RTErrConvertToErrno() below will ring-0 debug assert if we don't do this. */ + rc = VERR_ACCESS_DENIED; rc = RTErrConvertToErrno(rc); } *pVal = rc; diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.conf b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.conf index 6c23af13..1e2c814f 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.conf +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-solaris.conf @@ -1,7 +1,7 @@ # # OpenSolaris Guest Driver Configuration # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-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/Additions/common/VBoxGuest/VBoxGuest-win-legacy.cpp b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win-legacy.cpp index 5f1ce5d7..3dd55441 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win-legacy.cpp +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win-legacy.cpp @@ -1,8 +1,10 @@ +/* $Id: VBoxGuest-win-legacy.cpp $ */ /** @file - * * VBoxGuest-win-legacy - Windows NT4 specifics. - * - * 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; @@ -22,15 +24,12 @@ #include <VBox/log.h> #include <VBox/version.h> #include <VBox/VBoxGuestLib.h> +#include <iprt/string.h> /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ - -/* Reenable logging, this was #undef'ed on iprt/log.h for RING0. */ -#define LOG_ENABLED - #ifndef PCI_MAX_BUSES # define PCI_MAX_BUSES 256 #endif @@ -40,13 +39,12 @@ * Internal Functions * *******************************************************************************/ RT_C_DECLS_BEGIN -NTSTATUS vboxguestwinnt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath); -static NTSTATUS vboxguestwinnt4FindPCIDevice(PULONG pBusNumber, PPCI_SLOT_NUMBER pSlotNumber); +static NTSTATUS vbgdNt4FindPciDevice(PULONG pulBusNumber, PPCI_SLOT_NUMBER pSlotNumber); RT_C_DECLS_END #ifdef ALLOC_PRAGMA -#pragma alloc_text (INIT, vboxguestwinnt4CreateDevice) -#pragma alloc_text (INIT, vboxguestwinnt4FindPCIDevice) +# pragma alloc_text(INIT, vbgdNt4CreateDevice) +# pragma alloc_text(INIT, vbgdNt4FindPciDevice) #endif @@ -55,97 +53,86 @@ RT_C_DECLS_END * * @returns NT status code. * - * @param pDrvObj - * @param pDevObj - * @param pRegPath + * @param pDrvObj The driver object. + * @param pDevObj Unused. NULL. Dunno why it's here, makes no sense. + * @param pRegPath The driver registry path. */ -NTSTATUS vboxguestwinnt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath) +NTSTATUS vbgdNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath) { - int vrc = VINF_SUCCESS; - NTSTATUS rc = STATUS_SUCCESS; - - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: pDrvObj=%p, pDevObj=%p, pRegPath=%p\n", - pDrvObj, pDevObj, pRegPath)); + Log(("VBoxGuest::vbgdNt4CreateDevice: pDrvObj=%p, pDevObj=%p, pRegPath=%p\n", pDrvObj, pDevObj, pRegPath)); /* * Find our virtual PCI device */ - ULONG uBusNumber, uSlotNumber; - rc = vboxguestwinnt4FindPCIDevice(&uBusNumber, (PCI_SLOT_NUMBER*)&uSlotNumber); + ULONG uBusNumber; + PCI_SLOT_NUMBER SlotNumber; + NTSTATUS rc = vbgdNt4FindPciDevice(&uBusNumber, &SlotNumber); if (NT_ERROR(rc)) - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Device not found!\n")); - - bool fSymbolicLinkCreated = false; - UNICODE_STRING szDosName; - PDEVICE_OBJECT pDeviceObject = NULL; - if (NT_SUCCESS(rc)) { - /* - * Create device. - */ - UNICODE_STRING szDevName; - RtlInitUnicodeString(&szDevName, VBOXGUEST_DEVICE_NAME_NT); - rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXT), &szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); - if (NT_SUCCESS(rc)) - { - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Device created\n")); - - RtlInitUnicodeString(&szDosName, VBOXGUEST_DEVICE_NAME_DOS); - rc = IoCreateSymbolicLink(&szDosName, &szDevName); - if (NT_SUCCESS(rc)) - { - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Symlink created\n")); - fSymbolicLinkCreated = true; - } - else - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: IoCreateSymbolicLink failed with rc = %#x\n", rc)); - } - else - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: IoCreateDevice failed with rc = %#x\n", rc)); + Log(("VBoxGuest::vbgdNt4CreateDevice: Device not found!\n")); + return rc; } /* - * Setup the device extension. + * Create device. */ - PVBOXGUESTDEVEXT pDevExt = NULL; + UNICODE_STRING szDevName; + RtlInitUnicodeString(&szDevName, VBOXGUEST_DEVICE_NAME_NT); + PDEVICE_OBJECT pDeviceObject = NULL; + rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &szDevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); if (NT_SUCCESS(rc)) { - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Setting up device extension ...\n")); + Log(("VBoxGuest::vbgdNt4CreateDevice: Device created\n")); - pDevExt = (PVBOXGUESTDEVEXT)pDeviceObject->DeviceExtension; - RtlZeroMemory(pDevExt, sizeof(VBOXGUESTDEVEXT)); - } + UNICODE_STRING DosName; + RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); + rc = IoCreateSymbolicLink(&DosName, &szDevName); + if (NT_SUCCESS(rc)) + { + Log(("VBoxGuest::vbgdNt4CreateDevice: Symlink created\n")); - if (NT_SUCCESS(rc) && pDevExt) - { - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Device extension created\n")); + /* + * Setup the device extension. + */ + Log(("VBoxGuest::vbgdNt4CreateDevice: Setting up device extension ...\n")); - /* Store a reference to ourself. */ - pDevExt->win.s.pDeviceObject = pDeviceObject; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; + RT_ZERO(*pDevExt); - /* Store bus and slot number we've queried before. */ - pDevExt->win.s.busNumber = uBusNumber; - pDevExt->win.s.slotNumber = uSlotNumber; + Log(("VBoxGuest::vbgdNt4CreateDevice: Device extension created\n")); - #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION - rc = hlpRegisterBugCheckCallback(pDevExt); - #endif - } + /* Store a reference to ourself. */ + pDevExt->pDeviceObject = pDeviceObject; - /* Do the actual VBox init ... */ - if (NT_SUCCESS(rc)) - rc = vboxguestwinInit(pDrvObj, pDeviceObject, pRegPath); + /* Store bus and slot number we've queried before. */ + pDevExt->busNumber = uBusNumber; + pDevExt->slotNumber = SlotNumber.u.AsULONG; - /* Clean up in case of errors. */ - if (NT_ERROR(rc)) - { - if (fSymbolicLinkCreated && szDosName.Length > 0) - IoDeleteSymbolicLink(&szDosName); - if (pDeviceObject) - IoDeleteDevice(pDeviceObject); - } +#ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION + rc = hlpRegisterBugCheckCallback(pDevExt); +#endif - Log(("VBoxGuest::vboxguestwinnt4CreateDevice: Returning rc = 0x%x\n", rc)); + /* Do the actual VBox init ... */ + if (NT_SUCCESS(rc)) + { + rc = vbgdNtInit(pDrvObj, pDeviceObject, pRegPath); + if (NT_SUCCESS(rc)) + { + Log(("VBoxGuest::vbgdNt4CreateDevice: Returning rc = 0x%x (succcess)\n", rc)); + return rc; + } + + /* bail out */ + } + IoDeleteSymbolicLink(&DosName); + } + else + Log(("VBoxGuest::vbgdNt4CreateDevice: IoCreateSymbolicLink failed with rc = %#x\n", rc)); + IoDeleteDevice(pDeviceObject); + } + else + Log(("VBoxGuest::vbgdNt4CreateDevice: IoCreateDevice failed with rc = %#x\n", rc)); + Log(("VBoxGuest::vbgdNt4CreateDevice: Returning rc = 0x%x\n", rc)); return rc; } @@ -155,70 +142,57 @@ NTSTATUS vboxguestwinnt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDev * * @returns NT status code. * - * @param pBusNumber - * @param pSlotNumber - * + * @param pulBusNumber Where to return the bus number on success. + * @param pSlotNumber Where to return the slot number on success. */ -static NTSTATUS vboxguestwinnt4FindPCIDevice(PULONG pBusNumber, PPCI_SLOT_NUMBER pSlotNumber) +static NTSTATUS vbgdNt4FindPciDevice(PULONG pulBusNumber, PPCI_SLOT_NUMBER pSlotNumber) { - NTSTATUS rc; - - ULONG busNumber; - ULONG deviceNumber; - ULONG functionNumber; - PCI_SLOT_NUMBER slotNumber; - PCI_COMMON_CONFIG pciData; - - Log(("VBoxGuest::vboxguestwinnt4FindPCIDevice\n")); + Log(("VBoxGuest::vbgdNt4FindPciDevice\n")); - rc = STATUS_DEVICE_DOES_NOT_EXIST; - slotNumber.u.AsULONG = 0; + PCI_SLOT_NUMBER SlotNumber; + SlotNumber.u.AsULONG = 0; /* Scan each bus. */ - for (busNumber = 0; busNumber < PCI_MAX_BUSES; busNumber++) + for (ULONG ulBusNumber = 0; ulBusNumber < PCI_MAX_BUSES; ulBusNumber++) { /* Scan each device. */ - for (deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++) + for (ULONG deviceNumber = 0; deviceNumber < PCI_MAX_DEVICES; deviceNumber++) { - slotNumber.u.bits.DeviceNumber = deviceNumber; + SlotNumber.u.bits.DeviceNumber = deviceNumber; /* Scan each function (not really required...). */ - for (functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++) + for (ULONG functionNumber = 0; functionNumber < PCI_MAX_FUNCTION; functionNumber++) { - slotNumber.u.bits.FunctionNumber = functionNumber; + SlotNumber.u.bits.FunctionNumber = functionNumber; /* Have a look at what's in this slot. */ - if (!HalGetBusData(PCIConfiguration, busNumber, slotNumber.u.AsULONG, - &pciData, sizeof(ULONG))) + PCI_COMMON_CONFIG PciData; + if (!HalGetBusData(PCIConfiguration, ulBusNumber, SlotNumber.u.AsULONG, &PciData, sizeof(ULONG))) { /* No such bus, we're done with it. */ deviceNumber = PCI_MAX_DEVICES; break; } - if (pciData.VendorID == PCI_INVALID_VENDORID) - { + if (PciData.VendorID == PCI_INVALID_VENDORID) /* We have to proceed to the next function. */ continue; - } /* Check if it's another device. */ - if ((pciData.VendorID != VMMDEV_VENDORID) || - (pciData.DeviceID != VMMDEV_DEVICEID)) - { + if ( PciData.VendorID != VMMDEV_VENDORID + || PciData.DeviceID != VMMDEV_DEVICEID) continue; - } /* Hooray, we've found it! */ - Log(("VBoxGuest::vboxguestwinnt4FindPCIDevice: Device found!\n")); + Log(("VBoxGuest::vbgdNt4FindPciDevice: Device found!\n")); - *pBusNumber = busNumber; - *pSlotNumber = slotNumber; - rc = STATUS_SUCCESS; + *pulBusNumber = ulBusNumber; + *pSlotNumber = SlotNumber; + return STATUS_SUCCESS; } } } - return rc; + return STATUS_DEVICE_DOES_NOT_EXIST; } diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win-pnp.cpp b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win-pnp.cpp index fb844b78..73ec6ff4 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win-pnp.cpp +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win-pnp.cpp @@ -1,8 +1,10 @@ +/* $Id: VBoxGuest-win-pnp.cpp $ */ /** @file - * * VBoxGuest-win-pnp - Windows Plug'n'Play specifics. - * - * 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; @@ -27,38 +29,29 @@ /******************************************************************************* * Defined Constants And Macros * *******************************************************************************/ -extern winVersion_t g_winVersion; - RT_C_DECLS_BEGIN -static NTSTATUS vboxguestwinSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pIrp, BOOLEAN fStrict); -static NTSTATUS vboxguestwinPnPIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent); -static VOID vboxguestwinShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList); +static NTSTATUS vbgdNtSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pIrp, BOOLEAN fStrict); +static NTSTATUS vbgdNtPnPIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent); +static VOID vbgdNtShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList); RT_C_DECLS_END #ifdef ALLOC_PRAGMA -#pragma alloc_text (PAGE, vboxguestwinPnP) -#pragma alloc_text (PAGE, vboxguestwinPower) -#pragma alloc_text (PAGE, vboxguestwinSendIrpSynchronously) -#pragma alloc_text (PAGE, vboxguestwinShowDeviceResources) +# pragma alloc_text(PAGE, vbgdNtPnP) +# pragma alloc_text(PAGE, vbgdNtPower) +# pragma alloc_text(PAGE, vbgdNtSendIrpSynchronously) +# pragma alloc_text(PAGE, vbgdNtShowDeviceResources) #endif -/* Reenable logging, this was #undef'ed on iprt/log.h for RING0. */ -#define LOG_ENABLED - - -/******************************************************************************* -* Internal Functions * -*******************************************************************************/ /** * Irp completion routine for PnP Irps we send. * * @param pDevObj Device object. * @param pIrp Request packet. - * @param event Semaphore. + * @param pEvent Semaphore. * @return NT status code */ -static NTSTATUS vboxguestwinPnpIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent) +static NTSTATUS vbgdNtPnpIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PKEVENT pEvent) { KeSetEvent(pEvent, 0, FALSE); return STATUS_MORE_PROCESSING_REQUIRED; @@ -73,21 +66,21 @@ static NTSTATUS vboxguestwinPnpIrpComplete(PDEVICE_OBJECT pDevObj, PIRP pIrp, PK * @param fStrict When set, returns an error if the IRP gives an error. * @return NT status code */ -static NTSTATUS vboxguestwinSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pIrp, BOOLEAN fStrict) +static NTSTATUS vbgdNtSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pIrp, BOOLEAN fStrict) { - KEVENT event; + KEVENT Event; - KeInitializeEvent(&event, SynchronizationEvent, FALSE); + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); IoCopyCurrentIrpStackLocationToNext(pIrp); - IoSetCompletionRoutine(pIrp, (PIO_COMPLETION_ROUTINE)vboxguestwinPnpIrpComplete, - &event, TRUE, TRUE, TRUE); + IoSetCompletionRoutine(pIrp, (PIO_COMPLETION_ROUTINE)vbgdNtPnpIrpComplete, + &Event, TRUE, TRUE, TRUE); NTSTATUS rc = IoCallDriver(pDevObj, pIrp); if (rc == STATUS_PENDING) { - KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL); + KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); rc = pIrp->IoStatus.Status; } @@ -97,7 +90,7 @@ static NTSTATUS vboxguestwinSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pI rc = STATUS_SUCCESS; } - Log(("VBoxGuest::vboxguestwinSendIrpSynchronously: Returning 0x%x\n", rc)); + Log(("VBoxGuest::vbgdNtSendIrpSynchronously: Returning 0x%x\n", rc)); return rc; } @@ -108,13 +101,13 @@ static NTSTATUS vboxguestwinSendIrpSynchronously(PDEVICE_OBJECT pDevObj, PIRP pI * @param pDevObj Device object. * @param pIrp Request packet. */ -NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) +NTSTATUS vbgdNtPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) { - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; - PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; + PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); #ifdef LOG_ENABLED - static char* aszFnctName[] = + static char *s_apszFnctName[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", @@ -130,7 +123,7 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", - "", + "IRP_MN_0xE", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", @@ -141,10 +134,8 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) "IRP_MN_DEVICE_USAGE_NOTIFICATION", "IRP_MN_SURPRISE_REMOVAL", }; - Log(("VBoxGuest::vboxguestwinGuestPnp: MinorFunction: %s\n", - pStack->MinorFunction < (sizeof(aszFnctName) / sizeof(aszFnctName[0])) - ? aszFnctName[pStack->MinorFunction] - : "Unknown")); + Log(("VBoxGuest::vbgdNtGuestPnp: MinorFunction: %s\n", + pStack->MinorFunction < RT_ELEMENTS(s_apszFnctName) ? s_apszFnctName[pStack->MinorFunction] : "Unknown")); #endif NTSTATUS rc = STATUS_SUCCESS; @@ -152,50 +143,50 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) { case IRP_MN_START_DEVICE: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: START_DEVICE\n")); /* This must be handled first by the lower driver. */ - rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE); + rc = vbgdNtSendIrpSynchronously(pDevExt->pNextLowerDriver, pIrp, TRUE); if ( NT_SUCCESS(rc) && NT_SUCCESS(pIrp->IoStatus.Status)) { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n", + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: START_DEVICE: pStack->Parameters.StartDevice.AllocatedResources = %p\n", pStack->Parameters.StartDevice.AllocatedResources)); if (!pStack->Parameters.StartDevice.AllocatedResources) { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE: No resources, pDevExt = %p, nextLowerDriver = %p!\n", - pDevExt, pDevExt ? pDevExt->win.s.pNextLowerDriver : NULL)); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: START_DEVICE: No resources, pDevExt = %p, nextLowerDriver = %p!\n", + pDevExt, pDevExt ? pDevExt->pNextLowerDriver : NULL)); rc = STATUS_UNSUCCESSFUL; } else { - rc = vboxguestwinInit(pDevObj, pIrp); + rc = vbgdNtInit(pDevObj, pIrp); } } if (NT_ERROR(rc)) { - Log(("VBoxGuest::vboxguestwinGuestPnp: START_DEVICE: Error: rc = 0x%x\n", rc)); + Log(("VBoxGuest::vbgdNtGuestPnp: START_DEVICE: Error: rc = 0x%x\n", rc)); /* Need to unmap memory in case of errors ... */ - vboxguestwinUnmapVMMDevMemory(pDevExt); + vbgdNtUnmapVMMDevMemory(pDevExt); } break; } case IRP_MN_CANCEL_REMOVE_DEVICE: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_REMOVE_DEVICE\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: CANCEL_REMOVE_DEVICE\n")); /* This must be handled first by the lower driver. */ - rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE); + rc = vbgdNtSendIrpSynchronously(pDevExt->pNextLowerDriver, pIrp, TRUE); - if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGREMOVE) + if (NT_SUCCESS(rc) && pDevExt->devState == PENDINGREMOVE) { /* Return to the state prior to receiving the IRP_MN_QUERY_REMOVE_DEVICE request. */ - pDevExt->win.s.devState = pDevExt->win.s.prevDevState; + pDevExt->devState = pDevExt->prevDevState; } /* Complete the IRP. */ @@ -204,7 +195,7 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) case IRP_MN_SURPRISE_REMOVAL: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: IRP_MN_SURPRISE_REMOVAL\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: IRP_MN_SURPRISE_REMOVAL\n")); VBOXGUEST_UPDATE_DEVSTATE(pDevExt, SURPRISEREMOVED); @@ -218,7 +209,7 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) IoSkipCurrentIrpStackLocation(pIrp); - rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); + rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); /* Do not complete the IRP. */ return rc; @@ -226,12 +217,12 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) case IRP_MN_QUERY_REMOVE_DEVICE: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_REMOVE_DEVICE\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: QUERY_REMOVE_DEVICE\n")); #ifdef VBOX_REBOOT_ON_UNINSTALL - Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n")); + Log(("VBoxGuest::vbgdNtGuestPnp: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n")); rc = STATUS_UNSUCCESSFUL; -#endif /* VBOX_REBOOT_ON_UNINSTALL */ +#endif if (NT_SUCCESS(rc)) { @@ -242,8 +233,8 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) IoSkipCurrentIrpStackLocation(pIrp); - rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); - Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); + rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); + Log(("VBoxGuest::vbgdNtGuestPnp: QUERY_REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); /* we must not do anything the IRP after doing IoSkip & CallDriver * since the driver below us will complete (or already have completed) the IRP. @@ -257,14 +248,15 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) case IRP_MN_REMOVE_DEVICE: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: REMOVE_DEVICE\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: REMOVE_DEVICE\n")); VBOXGUEST_UPDATE_DEVSTATE(pDevExt, REMOVED); /* Free hardware resources. */ - /* @todo this should actually free I/O ports, interrupts, etc. */ - rc = vboxguestwinCleanup(pDevObj); - Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: vboxguestwinCleanup rc = 0x%08X\n", rc)); + /** @todo this should actually free I/O ports, interrupts, etc. + * Update/bird: vbgdNtCleanup actually does that... So, what's there to do? */ + rc = vbgdNtCleanup(pDevObj); + Log(("VBoxGuest::vbgdNtGuestPnp: REMOVE_DEVICE: vbgdNtCleanup rc = 0x%08X\n", rc)); /* * We need to send the remove down the stack before we detach, @@ -275,28 +267,28 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) IoSkipCurrentIrpStackLocation(pIrp); - rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); - Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); + rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); + Log(("VBoxGuest::vbgdNtGuestPnp: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); - IoDetachDevice(pDevExt->win.s.pNextLowerDriver); + IoDetachDevice(pDevExt->pNextLowerDriver); - Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Removing device ...\n")); + Log(("VBoxGuest::vbgdNtGuestPnp: REMOVE_DEVICE: Removing device ...\n")); /* Destroy device extension and clean up everything else. */ - VBoxGuestDeleteDevExt(pDevExt); + VBoxGuestDeleteDevExt(&pDevExt->Core); /* Remove DOS device + symbolic link. */ UNICODE_STRING win32Name; RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS); IoDeleteSymbolicLink(&win32Name); - Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Deleting device ...\n")); + Log(("VBoxGuest::vbgdNtGuestPnp: REMOVE_DEVICE: Deleting device ...\n")); /* Last action: Delete our device! pDevObj is *not* failed * anymore after this call! */ IoDeleteDevice(pDevObj); - Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Device removed!\n")); + Log(("VBoxGuest::vbgdNtGuestPnp: REMOVE_DEVICE: Device removed!\n")); /* Propagating rc from IoCallDriver. */ return rc; /* Make sure that we don't do anything below here anymore! */ @@ -304,15 +296,15 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) case IRP_MN_CANCEL_STOP_DEVICE: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_STOP_DEVICE\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: CANCEL_STOP_DEVICE\n")); /* This must be handled first by the lower driver. */ - rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE); + rc = vbgdNtSendIrpSynchronously(pDevExt->pNextLowerDriver, pIrp, TRUE); - if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGSTOP) + if (NT_SUCCESS(rc) && pDevExt->devState == PENDINGSTOP) { /* Return to the state prior to receiving the IRP_MN_QUERY_STOP_DEVICE request. */ - pDevExt->win.s.devState = pDevExt->win.s.prevDevState; + pDevExt->devState = pDevExt->prevDevState; } /* Complete the IRP. */ @@ -321,12 +313,12 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) case IRP_MN_QUERY_STOP_DEVICE: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_STOP_DEVICE\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: QUERY_STOP_DEVICE\n")); #ifdef VBOX_REBOOT_ON_UNINSTALL - Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n")); + Log(("VBoxGuest::vbgdNtGuestPnp: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n")); pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; -#endif /* VBOX_REBOOT_ON_UNINSTALL */ +#endif if (NT_SUCCESS(rc)) { @@ -337,8 +329,8 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) IoSkipCurrentIrpStackLocation(pIrp); - rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); - Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); + rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); + Log(("VBoxGuest::vbgdNtGuestPnp: QUERY_STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); /* we must not do anything with the IRP after doing IoSkip & CallDriver * since the driver below us will complete (or already have completed) the IRP. @@ -352,22 +344,23 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) case IRP_MN_STOP_DEVICE: { - Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: STOP_DEVICE\n")); + Log(("VBoxGuest::vbgdNtVBoxGuestPnP: STOP_DEVICE\n")); VBOXGUEST_UPDATE_DEVSTATE(pDevExt, STOPPED); /* Free hardware resources. */ - /* @todo this should actually free I/O ports, interrupts, etc. */ - rc = vboxguestwinCleanup(pDevObj); - Log(("VBoxGuest::vboxguestwinGuestPnp: STOP_DEVICE: cleaning up, rc = 0x%x\n", rc)); + /** @todo this should actually free I/O ports, interrupts, etc. + * Update/bird: vbgdNtCleanup actually does that... So, what's there to do? */ + rc = vbgdNtCleanup(pDevObj); + Log(("VBoxGuest::vbgdNtGuestPnp: STOP_DEVICE: cleaning up, rc = 0x%x\n", rc)); /* Pass to the lower driver. */ pIrp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(pIrp); - rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); - Log(("VBoxGuest::vboxguestwinGuestPnp: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); + rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); + Log(("VBoxGuest::vbgdNtGuestPnp: STOP_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); return rc; } @@ -375,7 +368,7 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) default: { IoSkipCurrentIrpStackLocation(pIrp); - rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); + rc = IoCallDriver(pDevExt->pNextLowerDriver, pIrp); return rc; } } @@ -383,7 +376,7 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) pIrp->IoStatus.Status = rc; IoCompleteRequest(pIrp, IO_NO_INCREMENT); - Log(("VBoxGuest::vboxguestwinGuestPnp: Returning with rc = 0x%x\n", rc)); + Log(("VBoxGuest::vbgdNtGuestPnp: Returning with rc = 0x%x\n", rc)); return rc; } @@ -396,19 +389,17 @@ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) * @param pIrp IO request packet. * @param pContext Context value passed to IoSetCompletionRoutine in VBoxGuestPower. */ -NTSTATUS vboxguestwinPowerComplete(IN PDEVICE_OBJECT pDevObj, - IN PIRP pIrp, IN PVOID pContext) +static NTSTATUS vbgdNtPowerComplete(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp, IN PVOID pContext) { - PIO_STACK_LOCATION pIrpSp; - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pContext; +#ifdef VBOX_STRICT + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pContext; + PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp); - ASSERT(pDevExt); - ASSERT(pDevExt->signature == DEVICE_EXTENSION_SIGNATURE); + Assert(pDevExt); - pIrpSp = IoGetCurrentIrpStackLocation(pIrp); if (pIrpSp) { - ASSERT(pIrpSp->MajorFunction == IRP_MJ_POWER); + Assert(pIrpSp->MajorFunction == IRP_MJ_POWER); if (NT_SUCCESS(pIrp->IoStatus.Status)) { switch (pIrpSp->MinorFunction) @@ -429,6 +420,7 @@ NTSTATUS vboxguestwinPowerComplete(IN PDEVICE_OBJECT pDevObj, } } } +#endif return STATUS_SUCCESS; } @@ -441,56 +433,55 @@ NTSTATUS vboxguestwinPowerComplete(IN PDEVICE_OBJECT pDevObj, * @param pDevObj device object * @param pIrp IRP */ -NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) +NTSTATUS vbgdNtPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) { - PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; - POWER_STATE_TYPE powerType; - POWER_STATE powerState; - POWER_ACTION powerAction; + PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; + POWER_STATE_TYPE enmPowerType = pStack->Parameters.Power.Type; + POWER_STATE PowerState = pStack->Parameters.Power.State; + POWER_ACTION enmPowerAction = pStack->Parameters.Power.ShutdownType; - Log(("VBoxGuest::vboxguestwinGuestPower\n")); - - powerType = pStack->Parameters.Power.Type; - powerAction = pStack->Parameters.Power.ShutdownType; - powerState = pStack->Parameters.Power.State; + Log(("VBoxGuest::vbgdNtGuestPower\n")); switch (pStack->MinorFunction) { case IRP_MN_SET_POWER: { - Log(("VBoxGuest::vboxguestwinGuestPower: IRP_MN_SET_POWER, type= %d\n", powerType)); - switch (powerType) + Log(("VBoxGuest::vbgdNtGuestPower: IRP_MN_SET_POWER, type= %d\n", enmPowerType)); + switch (enmPowerType) { case SystemPowerState: { - Log(("VBoxGuest::vboxguestwinGuestPower: SystemPowerState, action = %d, state = %d\n", powerAction, powerState)); + Log(("VBoxGuest::vbgdNtGuestPower: SystemPowerState, action = %d, state = %d/%d\n", + enmPowerAction, PowerState.SystemState, PowerState.DeviceState)); - switch (powerAction) + switch (enmPowerAction) { case PowerActionSleep: /* System now is in a working state. */ - if (powerState.SystemState == PowerSystemWorking) + if (PowerState.SystemState == PowerSystemWorking) { if ( pDevExt - && pDevExt->win.s.LastSystemPowerAction == PowerActionHibernate) + && pDevExt->LastSystemPowerAction == PowerActionHibernate) { - Log(("VBoxGuest::vboxguestwinGuestPower: Returning from hibernation!\n")); - int rc = VBoxGuestReinitDevExtAfterHibernation(pDevExt, vboxguestwinVersionToOSType(g_winVersion)); + Log(("VBoxGuest::vbgdNtGuestPower: Returning from hibernation!\n")); + int rc = VBoxGuestReinitDevExtAfterHibernation(&pDevExt->Core, + vbgdNtVersionToOSType(g_enmVbgdNtVer)); if (RT_FAILURE(rc)) - Log(("VBoxGuest::vboxguestwinGuestPower: Cannot re-init VMMDev chain, rc = %d!\n", rc)); + Log(("VBoxGuest::vbgdNtGuestPower: Cannot re-init VMMDev chain, rc = %d!\n", rc)); } } break; case PowerActionShutdownReset: { - Log(("VBoxGuest::vboxguestwinGuestPower: Power action reset!\n")); + Log(("VBoxGuest::vbgdNtGuestPower: Power action reset!\n")); /* Tell the VMM that we no longer support mouse pointer integration. */ VMMDevReqMouseStatus *pReq = NULL; - int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof (VMMDevReqMouseStatus), VMMDevReq_SetMouseStatus); + int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pReq, sizeof (VMMDevReqMouseStatus), + VMMDevReq_SetMouseStatus); if (RT_SUCCESS(vrc)) { pReq->mouseFeatures = 0; @@ -500,8 +491,7 @@ NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) vrc = VbglGRPerform(&pReq->header); if (RT_FAILURE(vrc)) { - Log(("VBoxGuest::PowerStateRequest: error communicating new power status to VMMDev. " - "vrc = %Rrc\n", vrc)); + Log(("VBoxGuest::PowerStateRequest: error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); } VbglGRFree(&pReq->header); @@ -515,12 +505,12 @@ NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) case PowerActionShutdown: case PowerActionShutdownOff: { - Log(("VBoxGuest::vboxguestwinGuestPower: Power action shutdown!\n")); - if (powerState.SystemState >= PowerSystemShutdown) + Log(("VBoxGuest::vbgdNtGuestPower: Power action shutdown!\n")); + if (PowerState.SystemState >= PowerSystemShutdown) { - Log(("VBoxGuest::vboxguestwinGuestPower: Telling the VMMDev to close the VM ...\n")); + Log(("VBoxGuest::vbgdNtGuestPower: Telling the VMMDev to close the VM ...\n")); - VMMDevPowerStateRequest *pReq = pDevExt->win.s.pPowerStateRequest; + VMMDevPowerStateRequest *pReq = pDevExt->pPowerStateRequest; int vrc = VERR_NOT_IMPLEMENTED; if (pReq) { @@ -530,10 +520,7 @@ NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) vrc = VbglGRPerform(&pReq->header); } if (RT_FAILURE(vrc)) - { - Log(("VBoxGuest::PowerStateRequest: Error communicating new power status to VMMDev. " - "vrc = %Rrc\n", vrc)); - } + Log(("VBoxGuest::PowerStateRequest: Error communicating new power status to VMMDev. vrc = %Rrc\n", vrc)); /* No need to do cleanup here; at this point we should've been * turned off by VMMDev already! */ @@ -543,7 +530,7 @@ NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) case PowerActionHibernate: - Log(("VBoxGuest::vboxguestwinGuestPower: Power action hibernate!\n")); + Log(("VBoxGuest::vbgdNtGuestPower: Power action hibernate!\n")); break; } @@ -552,7 +539,7 @@ NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) * This becomes handy when we return from hibernation for example. */ if (pDevExt) - pDevExt->win.s.LastSystemPowerAction = powerAction; + pDevExt->LastSystemPowerAction = enmPowerAction; break; } @@ -566,21 +553,22 @@ NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp) } /* - * Whether we are completing or relaying this power IRP, - * we must call PoStartNextPowerIrp. + * Whether we are completing or relaying this power IRP, + * we must call PoStartNextPowerIrp. */ PoStartNextPowerIrp(pIrp); /* - * Send the IRP down the driver stack, - * using PoCallDriver (not IoCallDriver, as for non-power irps). + * Send the IRP down the driver stack, using PoCallDriver + * (not IoCallDriver, as for non-power irps). */ IoCopyCurrentIrpStackLocationToNext(pIrp); IoSetCompletionRoutine(pIrp, - vboxguestwinPowerComplete, + vbgdNtPowerComplete, (PVOID)pDevExt, TRUE, TRUE, TRUE); - return PoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); + return PoCallDriver(pDevExt->pNextLowerDriver, pIrp); } + diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp index 9299ae5b..d4ba77b2 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.cpp @@ -1,8 +1,10 @@ +/* $Id: VBoxGuest-win.cpp $ */ /** @file - * * VBoxGuest - Windows specifics. - * - * 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; @@ -25,6 +27,7 @@ #include <VBox/log.h> #include <VBox/VBoxGuestLib.h> +#include <iprt/string.h> /* * XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist @@ -35,22 +38,23 @@ # undef ExFreePool #endif + /******************************************************************************* * Internal Functions * *******************************************************************************/ RT_C_DECLS_BEGIN -static NTSTATUS vboxguestwinAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj); -static void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj); -static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp); -static NTSTATUS vboxguestwinClose(PDEVICE_OBJECT pDevObj, PIRP pIrp); -static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp); -static NTSTATUS vboxguestwinInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp); -static NTSTATUS vboxguestwinRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue); -static NTSTATUS vboxguestwinSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp); -static NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp); -static NTSTATUS vboxguestwinNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp); +static NTSTATUS vbgdNtAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj); +static void vbgdNtUnload(PDRIVER_OBJECT pDrvObj); +static NTSTATUS vbgdNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp); +static NTSTATUS vbgdNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp); +static NTSTATUS vbgdNtIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp); +static NTSTATUS vbgdNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp); +static NTSTATUS vbgdNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue); +static NTSTATUS vbgdNtSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp); +static NTSTATUS vbgdNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp); +static NTSTATUS vbgdNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp); #ifdef DEBUG -static void vboxguestwinDoTests(void); +static void vbgdNtDoTests(void); #endif RT_C_DECLS_END @@ -63,19 +67,24 @@ ULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath); RT_C_DECLS_END #ifdef ALLOC_PRAGMA -#pragma alloc_text (INIT, DriverEntry) -#pragma alloc_text (PAGE, vboxguestwinAddDevice) -#pragma alloc_text (PAGE, vboxguestwinUnload) -#pragma alloc_text (PAGE, vboxguestwinCreate) -#pragma alloc_text (PAGE, vboxguestwinClose) -#pragma alloc_text (PAGE, vboxguestwinIOCtl) -#pragma alloc_text (PAGE, vboxguestwinShutdown) -#pragma alloc_text (PAGE, vboxguestwinNotSupportedStub) -#pragma alloc_text (PAGE, vboxguestwinScanPCIResourceList) +# pragma alloc_text(INIT, DriverEntry) +# pragma alloc_text(PAGE, vbgdNtAddDevice) +# pragma alloc_text(PAGE, vbgdNtUnload) +# pragma alloc_text(PAGE, vbgdNtCreate) +# pragma alloc_text(PAGE, vbgdNtClose) +# pragma alloc_text(PAGE, vbgdNtShutdown) +# pragma alloc_text(PAGE, vbgdNtNotSupportedStub) +# pragma alloc_text(PAGE, vbgdNtScanPCIResourceList) #endif -/** The detected Windows version. */ -winVersion_t g_winVersion; + +/******************************************************************************* +* Global Variables * +*******************************************************************************/ +/** The detected NT (windows) version. */ +VBGDNTVER g_enmVbgdNtVer = VBGDNTVER_INVALID; + + /** * Driver entry point. @@ -90,61 +99,70 @@ ULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath) Log(("VBoxGuest::DriverEntry. Driver built: %s %s\n", __DATE__, __TIME__)); - ULONG majorVersion; - ULONG minorVersion; - ULONG buildNumber; - BOOLEAN bCheckedBuild = PsGetVersion(&majorVersion, &minorVersion, &buildNumber, NULL); - Log(("VBoxGuest::DriverEntry: Running on Windows NT version %d.%d, build %d\n", majorVersion, minorVersion, buildNumber)); - if (bCheckedBuild) + /* + * Check if the the NT version is supported and initializing + * g_enmVbgdNtVer in the process. + */ + ULONG ulMajorVer; + ULONG ulMinorVer; + ULONG ulBuildNo; + BOOLEAN fCheckedBuild = PsGetVersion(&ulMajorVer, &ulMinorVer, &ulBuildNo, NULL); + Log(("VBoxGuest::DriverEntry: Running on Windows NT version %u.%u, build %u\n", ulMajorVer, ulMinorVer, ulBuildNo)); + if (fCheckedBuild) Log(("VBoxGuest::DriverEntry: Running on a Windows checked build (debug)!\n")); #ifdef DEBUG - vboxguestwinDoTests(); + vbgdNtDoTests(); #endif - switch (majorVersion) + switch (ulMajorVer) { case 6: /* Windows Vista or Windows 7 (based on minor ver) */ - switch (minorVersion) + switch (ulMinorVer) { case 0: /* Note: Also could be Windows 2008 Server! */ - g_winVersion = WINVISTA; + g_enmVbgdNtVer = VBGDNTVER_WINVISTA; break; case 1: /* Note: Also could be Windows 2008 Server R2! */ - g_winVersion = WIN7; + g_enmVbgdNtVer = VBGDNTVER_WIN7; break; case 2: - g_winVersion = WIN8; + g_enmVbgdNtVer = VBGDNTVER_WIN8; + break; + case 3: + g_enmVbgdNtVer = VBGDNTVER_WIN81; break; default: - Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n", - majorVersion, minorVersion)); + Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n", ulMajorVer, ulMinorVer)); rc = STATUS_DRIVER_UNABLE_TO_LOAD; break; } break; case 5: - switch (minorVersion) + switch (ulMinorVer) { case 2: - g_winVersion = WIN2K3; + g_enmVbgdNtVer = VBGDNTVER_WIN2K3; break; case 1: - g_winVersion = WINXP; + g_enmVbgdNtVer = VBGDNTVER_WINXP; break; case 0: - g_winVersion = WIN2K; + g_enmVbgdNtVer = VBGDNTVER_WIN2K; break; default: - Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n", - majorVersion, minorVersion)); + Log(("VBoxGuest::DriverEntry: Unknown version of Windows (%u.%u), refusing!\n", ulMajorVer, ulMinorVer)); rc = STATUS_DRIVER_UNABLE_TO_LOAD; } break; case 4: - g_winVersion = WINNT4; + g_enmVbgdNtVer = VBGDNTVER_WINNT4; break; default: - Log(("VBoxGuest::DriverEntry: At least Windows NT4 required!\n")); + if (ulMajorVer < 4) + Log(("VBoxGuest::DriverEntry: At least Windows NT4 required! (%u.%u)\n", ulMajorVer, ulMinorVer)); + else + Log(("VBoxGuest::DriverEntry: Too new version %u.%u!\n", ulMajorVer, ulMinorVer)); rc = STATUS_DRIVER_UNABLE_TO_LOAD; + break; } if (NT_SUCCESS(rc)) @@ -152,21 +170,21 @@ ULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath) /* * Setup the driver entry points in pDrvObj. */ - pDrvObj->DriverUnload = vboxguestwinUnload; - pDrvObj->MajorFunction[IRP_MJ_CREATE] = vboxguestwinCreate; - pDrvObj->MajorFunction[IRP_MJ_CLOSE] = vboxguestwinClose; - pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vboxguestwinIOCtl; - pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vboxguestwinInternalIOCtl; - pDrvObj->MajorFunction[IRP_MJ_SHUTDOWN] = vboxguestwinShutdown; - pDrvObj->MajorFunction[IRP_MJ_READ] = vboxguestwinNotSupportedStub; - pDrvObj->MajorFunction[IRP_MJ_WRITE] = vboxguestwinNotSupportedStub; + pDrvObj->DriverUnload = vbgdNtUnload; + pDrvObj->MajorFunction[IRP_MJ_CREATE] = vbgdNtCreate; + pDrvObj->MajorFunction[IRP_MJ_CLOSE] = vbgdNtClose; + pDrvObj->MajorFunction[IRP_MJ_DEVICE_CONTROL] = vbgdNtIOCtl; + pDrvObj->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = vbgdNtInternalIOCtl; + pDrvObj->MajorFunction[IRP_MJ_SHUTDOWN] = vbgdNtShutdown; + pDrvObj->MajorFunction[IRP_MJ_READ] = vbgdNtNotSupportedStub; + pDrvObj->MajorFunction[IRP_MJ_WRITE] = vbgdNtNotSupportedStub; #ifdef TARGET_NT4 - rc = vboxguestwinnt4CreateDevice(pDrvObj, NULL /* pDevObj */, pRegPath); + rc = vbgdNt4CreateDevice(pDrvObj, NULL /* pDevObj */, pRegPath); #else - pDrvObj->MajorFunction[IRP_MJ_PNP] = vboxguestwinPnP; - pDrvObj->MajorFunction[IRP_MJ_POWER] = vboxguestwinPower; - pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vboxguestwinSystemControl; - pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vboxguestwinAddDevice; + pDrvObj->MajorFunction[IRP_MJ_PNP] = vbgdNtPnP; + pDrvObj->MajorFunction[IRP_MJ_POWER] = vbgdNtPower; + pDrvObj->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = vbgdNtSystemControl; + pDrvObj->DriverExtension->AddDevice = (PDRIVER_ADD_DEVICE)vbgdNtAddDevice; #endif } @@ -183,84 +201,79 @@ ULONG DriverEntry(PDRIVER_OBJECT pDrvObj, PUNICODE_STRING pRegPath) * @param pDrvObj Driver object * @param pDevObj Device object */ -static NTSTATUS vboxguestwinAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj) +static NTSTATUS vbgdNtAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj) { NTSTATUS rc; - Log(("VBoxGuest::vboxguestwinGuestAddDevice\n")); + Log(("VBoxGuest::vbgdNtGuestAddDevice\n")); /* * Create device. */ + UNICODE_STRING DevName; + RtlInitUnicodeString(&DevName, VBOXGUEST_DEVICE_NAME_NT); PDEVICE_OBJECT pDeviceObject = NULL; - PVBOXGUESTDEVEXT pDevExt = NULL; - UNICODE_STRING devName; - UNICODE_STRING win32Name; - RtlInitUnicodeString(&devName, VBOXGUEST_DEVICE_NAME_NT); - rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXT), &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); + rc = IoCreateDevice(pDrvObj, sizeof(VBOXGUESTDEVEXTWIN), &DevName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject); if (NT_SUCCESS(rc)) { /* * Create symbolic link (DOS devices). */ - RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS); - rc = IoCreateSymbolicLink(&win32Name, &devName); + UNICODE_STRING DosName; + RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); + rc = IoCreateSymbolicLink(&DosName, &DevName); if (NT_SUCCESS(rc)) { /* * Setup the device extension. */ - pDevExt = (PVBOXGUESTDEVEXT)pDeviceObject->DeviceExtension; - RtlZeroMemory(pDevExt, sizeof(VBOXGUESTDEVEXT)); + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDeviceObject->DeviceExtension; + RT_ZERO(*pDevExt); - KeInitializeSpinLock(&pDevExt->win.s.MouseEventAccessLock); + KeInitializeSpinLock(&pDevExt->MouseEventAccessLock); - pDevExt->win.s.pDeviceObject = pDeviceObject; - pDevExt->win.s.prevDevState = STOPPED; - pDevExt->win.s.devState = STOPPED; + pDevExt->pDeviceObject = pDeviceObject; + pDevExt->prevDevState = STOPPED; + pDevExt->devState = STOPPED; - pDevExt->win.s.pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj); - if (pDevExt->win.s.pNextLowerDriver == NULL) + pDevExt->pNextLowerDriver = IoAttachDeviceToDeviceStack(pDeviceObject, pDevObj); + if (pDevExt->pNextLowerDriver != NULL) { - Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n")); - rc = STATUS_DEVICE_NOT_CONNECTED; - } - } - else - Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoCreateSymbolicLink failed with rc=%#x!\n", rc)); - } - else - Log(("VBoxGuest::vboxguestwinGuestAddDevice: IoCreateDevice failed with rc=%#x!\n", rc)); - - if (NT_SUCCESS(rc)) - { - /* - * If we reached this point we're fine with the basic driver setup, - * so continue to init our own things. - */ + /* + * If we reached this point we're fine with the basic driver setup, + * so continue to init our own things. + */ #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION - vboxguestwinBugCheckCallback(pDevExt); /* Ignore failure! */ + vbgdNtBugCheckCallback(pDevExt); /* Ignore failure! */ #endif - /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */ - pDeviceObject->Flags |= DO_POWER_PAGABLE; + if (NT_SUCCESS(rc)) + { + /* VBoxGuestPower is pageable; ensure we are not called at elevated IRQL */ + pDeviceObject->Flags |= DO_POWER_PAGABLE; - /* Driver is ready now. */ - pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - } + /* Driver is ready now. */ + pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + Log(("VBoxGuest::vbgdNtGuestAddDevice: returning with rc = 0x%x (success)\n", rc)); + return rc; + } - /* Cleanup on error. */ - if (NT_ERROR(rc)) - { - if (pDevExt) - { - if (pDevExt->win.s.pNextLowerDriver) - IoDetachDevice(pDevExt->win.s.pNextLowerDriver); + IoDetachDevice(pDevExt->pNextLowerDriver); + } + else + { + Log(("VBoxGuest::vbgdNtGuestAddDevice: IoAttachDeviceToDeviceStack did not give a nextLowerDriver!\n")); + rc = STATUS_DEVICE_NOT_CONNECTED; + } + + /* bail out */ + IoDeleteSymbolicLink(&DosName); } - IoDeleteSymbolicLink(&win32Name); - if (pDeviceObject) - IoDeleteDevice(pDeviceObject); + else + Log(("VBoxGuest::vbgdNtGuestAddDevice: IoCreateSymbolicLink failed with rc=%#x!\n", rc)); + IoDeleteDevice(pDeviceObject); } - - Log(("VBoxGuest::vboxguestwinGuestAddDevice: returning with rc = 0x%x\n", rc)); + else + Log(("VBoxGuest::vbgdNtGuestAddDevice: IoCreateDevice failed with rc=%#x!\n", rc)); + Log(("VBoxGuest::vbgdNtGuestAddDevice: returning with rc = 0x%x\n", rc)); return rc; } #endif @@ -271,17 +284,16 @@ static NTSTATUS vboxguestwinAddDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDe * * @param pResourceList list of device resources. */ -static void vboxguestwinShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList) +static void vbgdNtShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceList) { #ifdef LOG_ENABLED - PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = pResourceList->PartialDescriptors; - ULONG nres = pResourceList->Count; - ULONG i; + PCM_PARTIAL_RESOURCE_DESCRIPTOR pResource = pResourceList->PartialDescriptors; + ULONG cResources = pResourceList->Count; - for (i = 0; i < nres; ++i, ++resource) + for (ULONG i = 0; i < cResources; ++i, ++pResource) { - ULONG uType = resource->Type; - static char* aszName[] = + ULONG uType = pResource->Type; + static char const * const s_apszName[] = { "CmResourceTypeNull", "CmResourceTypePort", @@ -295,28 +307,27 @@ static void vboxguestwinShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceL "CmResourceTypeSubAllocateFrom", }; - Log(("VBoxGuest::vboxguestwinShowDeviceResources: Type %s", - uType < (sizeof(aszName) / sizeof(aszName[0])) - ? aszName[uType] : "Unknown")); + Log(("VBoxGuest::vbgdNtShowDeviceResources: Type %s", + uType < RT_ELEMENTS(s_apszName) ? s_apszName[uType] : "Unknown")); switch (uType) { case CmResourceTypePort: case CmResourceTypeMemory: - Log(("VBoxGuest::vboxguestwinShowDeviceResources: Start %8X%8.8lX length %X\n", - resource->u.Port.Start.HighPart, resource->u.Port.Start.LowPart, - resource->u.Port.Length)); + Log(("VBoxGuest::vbgdNtShowDeviceResources: Start %8X%8.8lX length %X\n", + pResource->u.Port.Start.HighPart, pResource->u.Port.Start.LowPart, + pResource->u.Port.Length)); break; case CmResourceTypeInterrupt: - Log(("VBoxGuest::vboxguestwinShowDeviceResources: Level %X, Vector %X, Affinity %X\n", - resource->u.Interrupt.Level, resource->u.Interrupt.Vector, - resource->u.Interrupt.Affinity)); + Log(("VBoxGuest::vbgdNtShowDeviceResources: Level %X, Vector %X, Affinity %X\n", + pResource->u.Interrupt.Level, pResource->u.Interrupt.Vector, + pResource->u.Interrupt.Affinity)); break; case CmResourceTypeDma: - Log(("VBoxGuest::vboxguestwinShowDeviceResources: Channel %d, Port %X\n", - resource->u.Dma.Channel, resource->u.Dma.Port)); + Log(("VBoxGuest::vbgdNtShowDeviceResources: Channel %d, Port %X\n", + pResource->u.Dma.Channel, pResource->u.Dma.Port)); break; default: @@ -335,24 +346,24 @@ static void vboxguestwinShowDeviceResources(PCM_PARTIAL_RESOURCE_LIST pResourceL * @param pIrp Request packet. */ #ifndef TARGET_NT4 -NTSTATUS vboxguestwinInit(PDEVICE_OBJECT pDevObj, PIRP pIrp) +NTSTATUS vbgdNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp) #else -NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath) +NTSTATUS vbgdNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath) #endif { - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; #ifndef TARGET_NT4 - PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); + PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); #endif - Log(("VBoxGuest::vboxguestwinInit\n")); + Log(("VBoxGuest::vbgdNtInit\n")); int rc = STATUS_SUCCESS; #ifdef TARGET_NT4 /* * Let's have a look at what our PCI adapter offers. */ - Log(("VBoxGuest::vboxguestwinInit: Starting to scan PCI resources of VBoxGuest ...\n")); + Log(("VBoxGuest::vbgdNtInit: Starting to scan PCI resources of VBoxGuest ...\n")); /* Assign the PCI resources. */ PCM_RESOURCE_LIST pResourceList = NULL; @@ -360,18 +371,17 @@ NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICO RtlInitUnicodeString(&classNameString, L"VBoxGuestAdapter"); rc = HalAssignSlotResources(pRegPath, &classNameString, pDrvObj, pDevObj, - PCIBus, pDevExt->win.s.busNumber, pDevExt->win.s.slotNumber, + PCIBus, pDevExt->busNumber, pDevExt->slotNumber, &pResourceList); if (pResourceList && pResourceList->Count > 0) - vboxguestwinShowDeviceResources(&pResourceList->List[0].PartialResourceList); + vbgdNtShowDeviceResources(&pResourceList->List[0].PartialResourceList); if (NT_SUCCESS(rc)) - rc = vboxguestwinScanPCIResourceList(pResourceList, pDevExt); + rc = vbgdNtScanPCIResourceList(pResourceList, pDevExt); #else if (pStack->Parameters.StartDevice.AllocatedResources->Count > 0) - vboxguestwinShowDeviceResources(&pStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList); + vbgdNtShowDeviceResources(&pStack->Parameters.StartDevice.AllocatedResources->List[0].PartialResourceList); if (NT_SUCCESS(rc)) - rc = vboxguestwinScanPCIResourceList(pStack->Parameters.StartDevice.AllocatedResourcesTranslated, - pDevExt); + rc = vbgdNtScanPCIResourceList(pStack->Parameters.StartDevice.AllocatedResourcesTranslated, pDevExt); #endif if (NT_SUCCESS(rc)) { @@ -381,40 +391,40 @@ NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICO */ void *pvMMIOBase = NULL; uint32_t cbMMIO = 0; - rc = vboxguestwinMapVMMDevMemory(pDevExt, - pDevExt->win.s.vmmDevPhysMemoryAddress, - pDevExt->win.s.vmmDevPhysMemoryLength, - &pvMMIOBase, - &cbMMIO); + rc = vbgdNtMapVMMDevMemory(pDevExt, + pDevExt->vmmDevPhysMemoryAddress, + pDevExt->vmmDevPhysMemoryLength, + &pvMMIOBase, + &cbMMIO); if (NT_SUCCESS(rc)) { - pDevExt->pVMMDevMemory = (VMMDevMemory *)pvMMIOBase; + pDevExt->Core.pVMMDevMemory = (VMMDevMemory *)pvMMIOBase; - Log(("VBoxGuest::vboxguestwinInit: pvMMIOBase = 0x%p, pDevExt = 0x%p, pDevExt->pVMMDevMemory = 0x%p\n", - pvMMIOBase, pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL)); + Log(("VBoxGuest::vbgdNtInit: pvMMIOBase = 0x%p, pDevExt = 0x%p, pDevExt->Core.pVMMDevMemory = 0x%p\n", + pvMMIOBase, pDevExt, pDevExt ? pDevExt->Core.pVMMDevMemory : NULL)); - int vrc = VBoxGuestInitDevExt(pDevExt, - pDevExt->IOPortBase, + int vrc = VBoxGuestInitDevExt(&pDevExt->Core, + pDevExt->Core.IOPortBase, pvMMIOBase, cbMMIO, - vboxguestwinVersionToOSType(g_winVersion), + vbgdNtVersionToOSType(g_enmVbgdNtVer), VMMDEV_EVENT_MOUSE_POSITION_CHANGED); if (RT_FAILURE(vrc)) { - Log(("VBoxGuest::vboxguestwinInit: Could not init device extension, rc = %Rrc!\n", vrc)); + Log(("VBoxGuest::vbgdNtInit: Could not init device extension, rc = %Rrc!\n", vrc)); rc = STATUS_DEVICE_CONFIGURATION_ERROR; } } else - Log(("VBoxGuest::vboxguestwinInit: Could not map physical address of VMMDev, rc = 0x%x!\n", rc)); + Log(("VBoxGuest::vbgdNtInit: Could not map physical address of VMMDev, rc = 0x%x!\n", rc)); } if (NT_SUCCESS(rc)) { - int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->win.s.pPowerStateRequest, - sizeof (VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus); + int vrc = VbglGRAlloc((VMMDevRequestHeader **)&pDevExt->pPowerStateRequest, + sizeof(VMMDevPowerStateRequest), VMMDevReq_SetPowerStatus); if (RT_FAILURE(vrc)) { - Log(("VBoxGuest::vboxguestwinInit: Alloc for pPowerStateRequest failed, rc = %Rrc\n", vrc)); + Log(("VBoxGuest::vbgdNtInit: Alloc for pPowerStateRequest failed, rc = %Rrc\n", vrc)); rc = STATUS_UNSUCCESSFUL; } } @@ -424,68 +434,68 @@ NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICO /* * Register DPC and ISR. */ - Log(("VBoxGuest::vboxguestwinInit: Initializing DPC/ISR ...\n")); + Log(("VBoxGuest::vbgdNtInit: Initializing DPC/ISR ...\n")); - IoInitializeDpcRequest(pDevExt->win.s.pDeviceObject, vboxguestwinDpcHandler); + IoInitializeDpcRequest(pDevExt->pDeviceObject, vbgdNtDpcHandler); #ifdef TARGET_NT4 ULONG uInterruptVector; KIRQL irqLevel; /* Get an interrupt vector. */ /* Only proceed if the device provides an interrupt. */ - if ( pDevExt->win.s.interruptLevel - || pDevExt->win.s.interruptVector) + if ( pDevExt->interruptLevel + || pDevExt->interruptVector) { - Log(("VBoxGuest::vboxguestwinInit: Getting interrupt vector (HAL): Bus: %u, IRQL: %u, Vector: %u\n", - pDevExt->win.s.busNumber, pDevExt->win.s.interruptLevel, pDevExt->win.s.interruptVector)); + Log(("VBoxGuest::vbgdNtInit: Getting interrupt vector (HAL): Bus: %u, IRQL: %u, Vector: %u\n", + pDevExt->busNumber, pDevExt->interruptLevel, pDevExt->interruptVector)); uInterruptVector = HalGetInterruptVector(PCIBus, - pDevExt->win.s.busNumber, - pDevExt->win.s.interruptLevel, - pDevExt->win.s.interruptVector, + pDevExt->busNumber, + pDevExt->interruptLevel, + pDevExt->interruptVector, &irqLevel, - &pDevExt->win.s.interruptAffinity); - Log(("VBoxGuest::vboxguestwinInit: HalGetInterruptVector returns vector %u\n", uInterruptVector)); + &pDevExt->interruptAffinity); + Log(("VBoxGuest::vbgdNtInit: HalGetInterruptVector returns vector %u\n", uInterruptVector)); if (uInterruptVector == 0) - Log(("VBoxGuest::vboxguestwinInit: No interrupt vector found!\n")); + Log(("VBoxGuest::vbgdNtInit: No interrupt vector found!\n")); } else - Log(("VBoxGuest::vboxguestwinInit: Device does not provide an interrupt!\n")); + Log(("VBoxGuest::vbgdNtInit: Device does not provide an interrupt!\n")); #endif - if (pDevExt->win.s.interruptVector) + if (pDevExt->interruptVector) { - Log(("VBoxGuest::vboxguestwinInit: Connecting interrupt ...\n")); + Log(("VBoxGuest::vbgdNtInit: Connecting interrupt ...\n")); - rc = IoConnectInterrupt(&pDevExt->win.s.pInterruptObject, /* Out: interrupt object. */ - (PKSERVICE_ROUTINE)vboxguestwinIsrHandler, /* Our ISR handler. */ - pDevExt, /* Device context. */ - NULL, /* Optional spinlock. */ + rc = IoConnectInterrupt(&pDevExt->pInterruptObject, /* Out: interrupt object. */ + (PKSERVICE_ROUTINE)vbgdNtIsrHandler, /* Our ISR handler. */ + pDevExt, /* Device context. */ + NULL, /* Optional spinlock. */ #ifdef TARGET_NT4 - uInterruptVector, /* Interrupt vector. */ - irqLevel, /* Interrupt level. */ - irqLevel, /* Interrupt level. */ + uInterruptVector, /* Interrupt vector. */ + irqLevel, /* Interrupt level. */ + irqLevel, /* Interrupt level. */ #else - pDevExt->win.s.interruptVector, /* Interrupt vector. */ - (KIRQL)pDevExt->win.s.interruptLevel, /* Interrupt level. */ - (KIRQL)pDevExt->win.s.interruptLevel, /* Interrupt level. */ + pDevExt->interruptVector, /* Interrupt vector. */ + (KIRQL)pDevExt->interruptLevel, /* Interrupt level. */ + (KIRQL)pDevExt->interruptLevel, /* Interrupt level. */ #endif - pDevExt->win.s.interruptMode, /* LevelSensitive or Latched. */ - TRUE, /* Shareable interrupt. */ - pDevExt->win.s.interruptAffinity, /* CPU affinity. */ - FALSE); /* Don't save FPU stack. */ + pDevExt->interruptMode, /* LevelSensitive or Latched. */ + TRUE, /* Shareable interrupt. */ + pDevExt->interruptAffinity, /* CPU affinity. */ + FALSE); /* Don't save FPU stack. */ if (NT_ERROR(rc)) - Log(("VBoxGuest::vboxguestwinInit: Could not connect interrupt, rc = 0x%x\n", rc)); + Log(("VBoxGuest::vbgdNtInit: Could not connect interrupt, rc = 0x%x\n", rc)); } else - Log(("VBoxGuest::vboxguestwinInit: No interrupt vector found!\n")); + Log(("VBoxGuest::vbgdNtInit: No interrupt vector found!\n")); } #ifdef VBOX_WITH_HGCM - Log(("VBoxGuest::vboxguestwinInit: Allocating kernel session data ...\n")); - int vrc = VBoxGuestCreateKernelSession(pDevExt, &pDevExt->win.s.pKernelSession); + Log(("VBoxGuest::vbgdNtInit: Allocating kernel session data ...\n")); + int vrc = VBoxGuestCreateKernelSession(&pDevExt->Core, &pDevExt->pKernelSession); if (RT_FAILURE(vrc)) { - Log(("VBoxGuest::vboxguestwinInit: Failed to allocated kernel session data! rc = %Rrc\n", rc)); + Log(("VBoxGuest::vbgdNtInit: Failed to allocated kernel session data! rc = %Rrc\n", rc)); rc = STATUS_UNSUCCESSFUL; } #endif @@ -493,25 +503,25 @@ NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICO if (RT_SUCCESS(rc)) { ULONG ulValue = 0; - NTSTATUS s = vboxguestwinRegistryReadDWORD(RTL_REGISTRY_SERVICES, L"VBoxGuest", L"LoggingEnabled", - &ulValue); - if (NT_SUCCESS(s)) + NTSTATUS rcNt = vbgdNtRegistryReadDWORD(RTL_REGISTRY_SERVICES, L"VBoxGuest", L"LoggingEnabled", &ulValue); + if (NT_SUCCESS(rcNt)) { - pDevExt->fLoggingEnabled = ulValue >= 0xFF; - if (pDevExt->fLoggingEnabled) + pDevExt->Core.fLoggingEnabled = ulValue >= 0xFF; + if (pDevExt->Core.fLoggingEnabled) Log(("Logging to release log enabled (0x%x)", ulValue)); } /* Ready to rumble! */ - Log(("VBoxGuest::vboxguestwinInit: Device is ready!\n")); + Log(("VBoxGuest::vbgdNtInit: Device is ready!\n")); VBOXGUEST_UPDATE_DEVSTATE(pDevExt, WORKING); } else - { - pDevExt->win.s.pInterruptObject = NULL; - } + pDevExt->pInterruptObject = NULL; - Log(("VBoxGuest::vboxguestwinInit: Returned with rc = 0x%x\n", rc)); + /** @todo r=bird: The error cleanup here is completely missing. We'll leak a + * whole bunch of things... */ + + Log(("VBoxGuest::vbgdNtInit: Returned with rc = 0x%x\n", rc)); return rc; } @@ -522,38 +532,38 @@ NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICO * * @param pDrvObj Driver object. */ -NTSTATUS vboxguestwinCleanup(PDEVICE_OBJECT pDevObj) +NTSTATUS vbgdNtCleanup(PDEVICE_OBJECT pDevObj) { - Log(("VBoxGuest::vboxguestwinCleanup\n")); + Log(("VBoxGuest::vbgdNtCleanup\n")); - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; if (pDevExt) { #if 0 /* @todo: test & enable cleaning global session data */ #ifdef VBOX_WITH_HGCM - if (pDevExt->win.s.pKernelSession) + if (pDevExt->pKernelSession) { - VBoxGuestCloseSession(pDevExt, pDevExt->win.s.pKernelSession); - pDevExt->win.s.pKernelSession = NULL; + VBoxGuestCloseSession(pDevExt, pDevExt->pKernelSession); + pDevExt->pKernelSession = NULL; } #endif #endif - if (pDevExt->win.s.pInterruptObject) + if (pDevExt->pInterruptObject) { - IoDisconnectInterrupt(pDevExt->win.s.pInterruptObject); - pDevExt->win.s.pInterruptObject = NULL; + IoDisconnectInterrupt(pDevExt->pInterruptObject); + pDevExt->pInterruptObject = NULL; } - /* @todo: cleanup the rest stuff */ + /** @todo: cleanup the rest stuff */ #ifdef VBOX_WITH_GUEST_BUGCHECK_DETECTION hlpDeregisterBugCheckCallback(pDevExt); /* ignore failure! */ #endif /* According to MSDN we have to unmap previously mapped memory. */ - vboxguestwinUnmapVMMDevMemory(pDevExt); + vbgdNtUnmapVMMDevMemory(pDevExt); } return STATUS_SUCCESS; } @@ -564,11 +574,11 @@ NTSTATUS vboxguestwinCleanup(PDEVICE_OBJECT pDevObj) * * @param pDrvObj Driver object. */ -static void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj) +static void vbgdNtUnload(PDRIVER_OBJECT pDrvObj) { - Log(("VBoxGuest::vboxguestwinGuestUnload\n")); + Log(("VBoxGuest::vbgdNtGuestUnload\n")); #ifdef TARGET_NT4 - vboxguestwinCleanup(pDrvObj->DeviceObject); + vbgdNtCleanup(pDrvObj->DeviceObject); /* Destroy device extension and clean up everything else. */ if (pDrvObj->DeviceObject && pDrvObj->DeviceObject->DeviceExtension) @@ -578,18 +588,18 @@ static void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj) * I don't think it's possible to unload a driver which processes have * opened, at least we'll blindly assume that here. */ - UNICODE_STRING win32Name; - RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS); - NTSTATUS rc = IoDeleteSymbolicLink(&win32Name); + UNICODE_STRING DosName; + RtlInitUnicodeString(&DosName, VBOXGUEST_DEVICE_NAME_DOS); + NTSTATUS rc = IoDeleteSymbolicLink(&DosName); IoDeleteDevice(pDrvObj->DeviceObject); -#else /* TARGET_NT4 */ +#else /* !TARGET_NT4 */ /* On a PnP driver this routine will be called after * IRP_MN_REMOVE_DEVICE (where we already did the cleanup), * so don't do anything here (yet). */ -#endif +#endif /* !TARGET_NT4 */ - Log(("VBoxGuest::vboxguestwinGuestUnload: returning\n")); + Log(("VBoxGuest::vbgdNtGuestUnload: returning\n")); } @@ -599,19 +609,18 @@ static void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj) * @param pDevObj Device object. * @param pIrp Request packet. */ -static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) +static NTSTATUS vbgdNtCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) { /** @todo AssertPtrReturn(pIrp); */ - PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); + PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); /** @todo AssertPtrReturn(pStack); */ - PFILE_OBJECT pFileObj = pStack->FileObject; - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; - NTSTATUS rc = STATUS_SUCCESS; + PFILE_OBJECT pFileObj = pStack->FileObject; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; + NTSTATUS rc = STATUS_SUCCESS; - if (pDevExt->win.s.devState != WORKING) + if (pDevExt->devState != WORKING) { - Log(("VBoxGuest::vboxguestwinGuestCreate: device is not working currently: %d!\n", - pDevExt->win.s.devState)); + Log(("VBoxGuest::vbgdNtGuestCreate: device is not working currently: %d!\n", pDevExt->devState)); rc = STATUS_UNSUCCESSFUL; } else if (pStack->Parameters.Create.Options & FILE_DIRECTORY_FILE) @@ -620,7 +629,7 @@ static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) * We are not remotely similar to a directory... * (But this is possible.) */ - Log(("VBoxGuest::vboxguestwinGuestCreate: Uhm, we're not a directory!\n")); + Log(("VBoxGuest::vbgdNtGuestCreate: Uhm, we're not a directory!\n")); rc = STATUS_NOT_A_DIRECTORY; } else @@ -628,7 +637,7 @@ static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) #ifdef VBOX_WITH_HGCM if (pFileObj) { - Log(("VBoxGuest::vboxguestwinGuestCreate: File object type = %d\n", + Log(("VBoxGuest::vbgdNtGuestCreate: File object type = %d\n", pFileObj->Type)); int vrc; @@ -639,12 +648,12 @@ static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) * Create a session object if we have a valid file object. This session object * exists for every R3 process. */ - vrc = VBoxGuestCreateUserSession(pDevExt, &pSession); + vrc = VBoxGuestCreateUserSession(&pDevExt->Core, &pSession); } else { /* ... otherwise we've been called from R0! */ - vrc = VBoxGuestCreateKernelSession(pDevExt, &pSession); + vrc = VBoxGuestCreateKernelSession(&pDevExt->Core, &pSession); } if (RT_SUCCESS(vrc)) pFileObj->FsContext = pSession; @@ -657,7 +666,7 @@ static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) pIrp->IoStatus.Status = rc; IoCompleteRequest(pIrp, IO_NO_INCREMENT); - Log(("VBoxGuest::vboxguestwinGuestCreate: Returning 0x%x\n", rc)); + Log(("VBoxGuest::vbgdNtGuestCreate: Returning 0x%x\n", rc)); return rc; } @@ -668,20 +677,20 @@ static NTSTATUS vboxguestwinCreate(PDEVICE_OBJECT pDevObj, PIRP pIrp) * @param pDevObj Device object. * @param pIrp Request packet. */ -static NTSTATUS vboxguestwinClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) +static NTSTATUS vbgdNtClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) { - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; - PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); - PFILE_OBJECT pFileObj = pStack->FileObject; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; + PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); + PFILE_OBJECT pFileObj = pStack->FileObject; - Log(("VBoxGuest::vboxguestwinGuestClose: pDevExt=0x%p pFileObj=0x%p FsContext=0x%p\n", + Log(("VBoxGuest::vbgdNtGuestClose: pDevExt=0x%p pFileObj=0x%p FsContext=0x%p\n", pDevExt, pFileObj, pFileObj->FsContext)); #ifdef VBOX_WITH_HGCM /* Close both, R0 and R3 sessions. */ PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pFileObj->FsContext; if (pSession) - VBoxGuestCloseSession(pDevExt, pSession); + VBoxGuestCloseSession(&pDevExt->Core, pSession); #endif pFileObj->FsContext = NULL; @@ -699,16 +708,16 @@ static NTSTATUS vboxguestwinClose(PDEVICE_OBJECT pDevObj, PIRP pIrp) * @param pDevObj Device object. * @param pIrp Request packet. */ -static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) +static NTSTATUS vbgdNtIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS Status = STATUS_SUCCESS; - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode; char *pBuf = (char *)pIrp->AssociatedIrp.SystemBuffer; /* All requests are buffered. */ size_t cbData = pStack->Parameters.DeviceIoControl.InputBufferLength; - unsigned cbOut = 0; + size_t cbOut = 0; /* Do we have a file object associated?*/ PFILE_OBJECT pFileObj = pStack->FileObject; @@ -716,7 +725,7 @@ static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) if (pFileObj) /* ... then we might have a session object as well! */ pSession = (PVBOXGUESTSESSION)pFileObj->FsContext; - Log(("VBoxGuest::vboxguestwinIOCtl: uCmd=%u, pDevExt=0x%p, pSession=0x%p\n", + Log(("VBoxGuest::vbgdNtIOCtl: uCmd=%u, pDevExt=0x%p, pSession=0x%p\n", uCmd, pDevExt, pSession)); /* We don't have a session associated with the file object? So this seems @@ -725,8 +734,8 @@ static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) * shall have its own context of course, no hacks, pleeease. */ if (pSession == NULL) { - Log(("VBoxGuest::vboxguestwinIOCtl: Using kernel session data ...\n")); - pSession = pDevExt->win.s.pKernelSession; + Log(("VBoxGuest::vbgdNtIOCtl: Using kernel session data ...\n")); + pSession = pDevExt->pKernelSession; } /* @@ -739,14 +748,14 @@ static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) #ifdef VBOX_WITH_VRDP_SESSION_HANDLING case VBOXGUEST_IOCTL_ENABLE_VRDP_SESSION: { - LogRel(("VBoxGuest::vboxguestwinIOCtl: ENABLE_VRDP_SESSION: Currently: %sabled\n", + LogRel(("VBoxGuest::vbgdNtIOCtl: ENABLE_VRDP_SESSION: Currently: %sabled\n", pDevExt->fVRDPEnabled? "en": "dis")); if (!pDevExt->fVRDPEnabled) { KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA; pDevExt->fVRDPEnabled = true; - LogRel(("VBoxGuest::vboxguestwinIOCtl: ENABLE_VRDP_SESSION: Current active console ID: 0x%08X\n", + LogRel(("VBoxGuest::vbgdNtIOCtl: ENABLE_VRDP_SESSION: Current active console ID: 0x%08X\n", pSharedUserData->ActiveConsoleId)); pDevExt->ulOldActiveConsoleId = pSharedUserData->ActiveConsoleId; pSharedUserData->ActiveConsoleId = 2; @@ -756,14 +765,14 @@ static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) case VBOXGUEST_IOCTL_DISABLE_VRDP_SESSION: { - LogRel(("VBoxGuest::vboxguestwinIOCtl: DISABLE_VRDP_SESSION: Currently: %sabled\n", + LogRel(("VBoxGuest::vbgdNtIOCtl: DISABLE_VRDP_SESSION: Currently: %sabled\n", pDevExt->fVRDPEnabled? "en": "dis")); if (pDevExt->fVRDPEnabled) { KUSER_SHARED_DATA *pSharedUserData = (KUSER_SHARED_DATA *)KI_USER_SHARED_DATA; pDevExt->fVRDPEnabled = false; - Log(("VBoxGuest::vboxguestwinIOCtl: DISABLE_VRDP_SESSION: Current active console ID: 0x%08X\n", + Log(("VBoxGuest::vbgdNtIOCtl: DISABLE_VRDP_SESSION: Current active console ID: 0x%08X\n", pSharedUserData->ActiveConsoleId)); pSharedUserData->ActiveConsoleId = pDevExt->ulOldActiveConsoleId; pDevExt->ulOldActiveConsoleId = 0; @@ -780,16 +789,16 @@ static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) * Process the common IOCtls. */ size_t cbDataReturned; - int vrc = VBoxGuestCommonIOCtl(uCmd, pDevExt, pSession, pBuf, cbData, &cbDataReturned); + int vrc = VBoxGuestCommonIOCtl(uCmd, &pDevExt->Core, pSession, pBuf, cbData, &cbDataReturned); - Log(("VBoxGuest::vboxguestwinGuestDeviceControl: rc=%Rrc, pBuf=0x%p, cbData=%u, cbDataReturned=%u\n", + Log(("VBoxGuest::vbgdNtGuestDeviceControl: rc=%Rrc, pBuf=0x%p, cbData=%u, cbDataReturned=%u\n", vrc, pBuf, cbData, cbDataReturned)); if (RT_SUCCESS(vrc)) { if (RT_UNLIKELY(cbDataReturned > cbData)) { - Log(("VBoxGuest::vboxguestwinGuestDeviceControl: Too much output data %u - expected %u!\n", cbDataReturned, cbData)); + Log(("VBoxGuest::vbgdNtGuestDeviceControl: Too much output data %u - expected %u!\n", cbDataReturned, cbData)); cbDataReturned = cbData; Status = STATUS_BUFFER_TOO_SMALL; } @@ -800,9 +809,9 @@ static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { if ( vrc == VERR_NOT_SUPPORTED || vrc == VERR_INVALID_PARAMETER) - { Status = STATUS_INVALID_PARAMETER; - } + else if (vrc == VERR_OUT_OF_RANGE) + Status = STATUS_INVALID_BUFFER_SIZE; else Status = STATUS_UNSUCCESSFUL; } @@ -815,32 +824,29 @@ static NTSTATUS vboxguestwinIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) IoCompleteRequest(pIrp, IO_NO_INCREMENT); - //Log(("VBoxGuest::vboxguestwinGuestDeviceControl: returned cbOut=%d rc=%#x\n", cbOut, Status)); + //Log(("VBoxGuest::vbgdNtGuestDeviceControl: returned cbOut=%d rc=%#x\n", cbOut, Status)); return Status; } /** * Internal Device I/O Control entry point. * - * We do not want to allow some IOCTLs to be originated from user mode, this is - * why we have a different entry point for internal IOCTLs. - * * @param pDevObj Device object. * @param pIrp Request packet. - * - * @todo r=bird: This is no need for this extra function for the purpose of - * securing an IOCTL from user space access. VBoxGuestCommonIOCtl - * has a way to do this already, see VBOXGUEST_IOCTL_GETVMMDEVPORT. */ -static NTSTATUS vboxguestwinInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) +static NTSTATUS vbgdNtInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { NTSTATUS Status = STATUS_SUCCESS; - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); unsigned int uCmd = (unsigned int)pStack->Parameters.DeviceIoControl.IoControlCode; bool fProcessed = false; unsigned Info = 0; + /* + * Override common behavior of some operations. + */ + /** @todo r=bird: Better to add dedicated worker functions for this! */ switch (uCmd) { case VBOXGUEST_IOCTL_SET_MOUSE_NOTIFY_CALLBACK: @@ -859,9 +865,9 @@ static NTSTATUS vboxguestwinInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) /* we need a lock here to avoid concurrency with the set event functionality */ KIRQL OldIrql; - KeAcquireSpinLock(&pDevExt->win.s.MouseEventAccessLock, &OldIrql); - pDevExt->MouseNotifyCallback = *pInfo; - KeReleaseSpinLock(&pDevExt->win.s.MouseEventAccessLock, OldIrql); + KeAcquireSpinLock(&pDevExt->MouseEventAccessLock, &OldIrql); + pDevExt->Core.MouseNotifyCallback = *pInfo; + KeReleaseSpinLock(&pDevExt->MouseEventAccessLock, OldIrql); Status = STATUS_SUCCESS; break; @@ -870,8 +876,6 @@ static NTSTATUS vboxguestwinInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) default: break; } - - if (fProcessed) { pIrp->IoStatus.Status = Status; @@ -881,7 +885,10 @@ static NTSTATUS vboxguestwinInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) return Status; } - return vboxguestwinIOCtl(pDevObj, pIrp); + /* + * No override, go to common code. + */ + return vbgdNtIOCtl(pDevObj, pIrp); } @@ -892,16 +899,16 @@ static NTSTATUS vboxguestwinInternalIOCtl(PDEVICE_OBJECT pDevObj, PIRP pIrp) * @param pDevObj Device object. * @param pIrp IRP. */ -NTSTATUS vboxguestwinSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp) +NTSTATUS vbgdNtSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp) { - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; - Log(("VBoxGuest::vboxguestwinGuestSystemControl\n")); + Log(("VBoxGuest::vbgdNtGuestSystemControl\n")); /* Always pass it on to the next driver. */ IoSkipCurrentIrpStackLocation(pIrp); - return IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); + return IoCallDriver(pDevExt->pNextLowerDriver, pIrp); } @@ -912,13 +919,13 @@ NTSTATUS vboxguestwinSystemControl(PDEVICE_OBJECT pDevObj, PIRP pIrp) * @param pDevObj Device object. * @param pIrp IRP. */ -NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp) +NTSTATUS vbgdNtShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp) { - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; - Log(("VBoxGuest::vboxguestwinGuestShutdown\n")); + Log(("VBoxGuest::vbgdNtGuestShutdown\n")); - VMMDevPowerStateRequest *pReq = pDevExt->win.s.pPowerStateRequest; + VMMDevPowerStateRequest *pReq = pDevExt->pPowerStateRequest; if (pReq) { pReq->header.requestType = VMMDevReq_SetPowerStatus; @@ -927,7 +934,7 @@ NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp) int rc = VbglGRPerform(&pReq->header); if (RT_FAILURE(rc)) { - Log(("VBoxGuest::vboxguestwinGuestShutdown: Error performing request to VMMDev! " + Log(("VBoxGuest::vbgdNtGuestShutdown: Error performing request to VMMDev! " "rc = %Rrc\n", rc)); } } @@ -942,9 +949,9 @@ NTSTATUS vboxguestwinShutdown(PDEVICE_OBJECT pDevObj, PIRP pIrp) * @param pDevObj Device object. * @param pIrp IRP. */ -NTSTATUS vboxguestwinNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp) +NTSTATUS vbgdNtNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp) { - Log(("VBoxGuest::vboxguestwinGuestNotSupportedStub\n")); + Log(("VBoxGuest::vbgdNtGuestNotSupportedStub\n")); pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = STATUS_NOT_SUPPORTED; @@ -962,28 +969,28 @@ NTSTATUS vboxguestwinNotSupportedStub(PDEVICE_OBJECT pDevObj, PIRP pIrp) * @param pIrp Interrupt request packet. * @param pContext Context specific pointer. */ -void vboxguestwinDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext) +void vbgdNtDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext) { - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; - Log(("VBoxGuest::vboxguestwinGuestDpcHandler: pDevExt=0x%p\n", pDevExt)); + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pDevObj->DeviceExtension; + Log(("VBoxGuest::vbgdNtGuestDpcHandler: pDevExt=0x%p\n", pDevExt)); /* test & reset the counter */ - if (ASMAtomicXchgU32(&pDevExt->u32MousePosChangedSeq, 0)) + if (ASMAtomicXchgU32(&pDevExt->Core.u32MousePosChangedSeq, 0)) { /* we need a lock here to avoid concurrency with the set event ioctl handler thread, * i.e. to prevent the event from destroyed while we're using it */ Assert(KeGetCurrentIrql() == DISPATCH_LEVEL); - KeAcquireSpinLockAtDpcLevel(&pDevExt->win.s.MouseEventAccessLock); + KeAcquireSpinLockAtDpcLevel(&pDevExt->MouseEventAccessLock); - if (pDevExt->MouseNotifyCallback.pfnNotify) - pDevExt->MouseNotifyCallback.pfnNotify(pDevExt->MouseNotifyCallback.pvUser); + if (pDevExt->Core.MouseNotifyCallback.pfnNotify) + pDevExt->Core.MouseNotifyCallback.pfnNotify(pDevExt->Core.MouseNotifyCallback.pvUser); - KeReleaseSpinLockFromDpcLevel(&pDevExt->win.s.MouseEventAccessLock); + KeReleaseSpinLockFromDpcLevel(&pDevExt->MouseEventAccessLock); } /* Process the wake-up list we were asked by the scheduling a DPC - * in vboxguestwinIsrHandler(). */ - VBoxGuestWaitDoWakeUps(pDevExt); + * in vbgdNtIsrHandler(). */ + VBoxGuestWaitDoWakeUps(&pDevExt->Core); } @@ -994,35 +1001,35 @@ void vboxguestwinDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID * @param pInterrupt Interrupt that was triggered. * @param pServiceContext Context specific pointer. */ -BOOLEAN vboxguestwinIsrHandler(PKINTERRUPT pInterrupt, PVOID pServiceContext) +BOOLEAN vbgdNtIsrHandler(PKINTERRUPT pInterrupt, PVOID pServiceContext) { - PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pServiceContext; + PVBOXGUESTDEVEXTWIN pDevExt = (PVBOXGUESTDEVEXTWIN)pServiceContext; if (pDevExt == NULL) return FALSE; - /*Log(("VBoxGuest::vboxguestwinGuestIsrHandler: pDevExt = 0x%p, pVMMDevMemory = 0x%p\n", + /*Log(("VBoxGuest::vbgdNtGuestIsrHandler: pDevExt = 0x%p, pVMMDevMemory = 0x%p\n", pDevExt, pDevExt ? pDevExt->pVMMDevMemory : NULL));*/ /* Enter the common ISR routine and do the actual work. */ - BOOLEAN fIRQTaken = VBoxGuestCommonISR(pDevExt); + BOOLEAN fIRQTaken = VBoxGuestCommonISR(&pDevExt->Core); /* If we need to wake up some events we do that in a DPC to make * sure we're called at the right IRQL. */ if (fIRQTaken) { - Log(("VBoxGuest::vboxguestwinGuestIsrHandler: IRQ was taken! pInterrupt = 0x%p, pDevExt = 0x%p\n", + Log(("VBoxGuest::vbgdNtGuestIsrHandler: IRQ was taken! pInterrupt = 0x%p, pDevExt = 0x%p\n", pInterrupt, pDevExt)); - if (ASMAtomicUoReadU32(&pDevExt->u32MousePosChangedSeq) || !RTListIsEmpty(&pDevExt->WakeUpList)) + if (ASMAtomicUoReadU32(&pDevExt->Core.u32MousePosChangedSeq) || !RTListIsEmpty(&pDevExt->Core.WakeUpList)) { - Log(("VBoxGuest::vboxguestwinGuestIsrHandler: Requesting DPC ...\n")); - IoRequestDpc(pDevExt->win.s.pDeviceObject, pDevExt->win.s.pCurrentIrp, NULL); + Log(("VBoxGuest::vbgdNtGuestIsrHandler: Requesting DPC ...\n")); + IoRequestDpc(pDevExt->pDeviceObject, pDevExt->pCurrentIrp, NULL); } } return fIRQTaken; } -/* +/** * Overridden routine for mouse polling events. * * @param pDevExt Device extension structure. @@ -1047,8 +1054,7 @@ void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt) * not specified in ulRoot), on output this will retrieve the looked up * registry value if found. */ -NTSTATUS vboxguestwinRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, - PULONG puValue) +NTSTATUS vbgdNtRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwszName, PULONG puValue) { if (!pwszPath || !pwszName || !puValue) return STATUS_INVALID_PARAMETER; @@ -1079,17 +1085,17 @@ NTSTATUS vboxguestwinRegistryReadDWORD(ULONG ulRoot, PCWSTR pwszPath, PWSTR pwsz * @param pResList Resource list * @param pDevExt Device extension */ -NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXT pDevExt) +NTSTATUS vbgdNtScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXTWIN pDevExt) { /* Enumerate the resource list. */ - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Found %d resources\n", + Log(("VBoxGuest::vbgdNtScanPCIResourceList: Found %d resources\n", pResList->List->PartialResourceList.Count)); NTSTATUS rc = STATUS_SUCCESS; PCM_PARTIAL_RESOURCE_DESCRIPTOR pPartialData = NULL; ULONG rangeCount = 0; ULONG cMMIORange = 0; - PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->win.s.pciBaseAddress; + PVBOXGUESTWINBASEADDRESS pBaseAddress = pDevExt->pciBaseAddress; for (ULONG i = 0; i < pResList->List->PartialResourceList.Count; i++) { pPartialData = &pResList->List->PartialResourceList.PartialDescriptors[i]; @@ -1100,14 +1106,15 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD /* Overflow protection. */ if (rangeCount < PCI_TYPE0_ADDRESSES) { - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: I/O range: Base = %08x:%08x, Length = %08x\n", - pPartialData->u.Port.Start.HighPart, - pPartialData->u.Port.Start.LowPart, - pPartialData->u.Port.Length)); + Log(("VBoxGuest::vbgdNtScanPCIResourceList: I/O range: Base = %08x:%08x, Length = %08x\n", + pPartialData->u.Port.Start.HighPart, + pPartialData->u.Port.Start.LowPart, + pPartialData->u.Port.Length)); /* Save the IO port base. */ - /** @todo Not so good. */ - pDevExt->IOPortBase = (RTIOPORT)pPartialData->u.Port.Start.LowPart; + /** @todo Not so good. + * Update/bird: What is not so good? That we just consider the last range? */ + pDevExt->Core.IOPortBase = (RTIOPORT)pPartialData->u.Port.Start.LowPart; /* Save resource information. */ pBaseAddress->RangeStart = pPartialData->u.Port.Start; @@ -1115,10 +1122,10 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD pBaseAddress->RangeInMemory = FALSE; pBaseAddress->ResourceMapped = FALSE; - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: I/O range for VMMDev found! Base = %08x:%08x, Length = %08x\n", - pPartialData->u.Port.Start.HighPart, - pPartialData->u.Port.Start.LowPart, - pPartialData->u.Port.Length)); + Log(("VBoxGuest::vbgdNtScanPCIResourceList: I/O range for VMMDev found! Base = %08x:%08x, Length = %08x\n", + pPartialData->u.Port.Start.HighPart, + pPartialData->u.Port.Start.LowPart, + pPartialData->u.Port.Length)); /* Next item ... */ rangeCount++; pBaseAddress++; @@ -1128,25 +1135,21 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD case CmResourceTypeInterrupt: { - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Interrupt: Level = %x, Vector = %x, Mode = %x\n", + Log(("VBoxGuest::vbgdNtScanPCIResourceList: Interrupt: Level = %x, Vector = %x, Mode = %x\n", pPartialData->u.Interrupt.Level, pPartialData->u.Interrupt.Vector, pPartialData->Flags)); /* Save information. */ - pDevExt->win.s.interruptLevel = pPartialData->u.Interrupt.Level; - pDevExt->win.s.interruptVector = pPartialData->u.Interrupt.Vector; - pDevExt->win.s.interruptAffinity = pPartialData->u.Interrupt.Affinity; + pDevExt->interruptLevel = pPartialData->u.Interrupt.Level; + pDevExt->interruptVector = pPartialData->u.Interrupt.Vector; + pDevExt->interruptAffinity = pPartialData->u.Interrupt.Affinity; /* Check interrupt mode. */ if (pPartialData->Flags & CM_RESOURCE_INTERRUPT_LATCHED) - { - pDevExt->win.s.interruptMode = Latched; - } + pDevExt->interruptMode = Latched; else - { - pDevExt->win.s.interruptMode = LevelSensitive; - } + pDevExt->interruptMode = LevelSensitive; break; } @@ -1155,7 +1158,7 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD /* Overflow protection. */ if (rangeCount < PCI_TYPE0_ADDRESSES) { - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Memory range: Base = %08x:%08x, Length = %08x\n", + Log(("VBoxGuest::vbgdNtScanPCIResourceList: Memory range: Base = %08x:%08x, Length = %08x\n", pPartialData->u.Memory.Start.HighPart, pPartialData->u.Memory.Start.LowPart, pPartialData->u.Memory.Length)); @@ -1166,8 +1169,8 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD && (pPartialData->Flags & VBOX_CM_PRE_VISTA_MASK) == CM_RESOURCE_MEMORY_READ_WRITE) { /* Save physical MMIO base + length for VMMDev. */ - pDevExt->win.s.vmmDevPhysMemoryAddress = pPartialData->u.Memory.Start; - pDevExt->win.s.vmmDevPhysMemoryLength = (ULONG)pPartialData->u.Memory.Length; + pDevExt->vmmDevPhysMemoryAddress = pPartialData->u.Memory.Start; + pDevExt->vmmDevPhysMemoryLength = (ULONG)pPartialData->u.Memory.Length; /* Save resource information. */ pBaseAddress->RangeStart = pPartialData->u.Memory.Start; @@ -1175,7 +1178,7 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD pBaseAddress->RangeInMemory = TRUE; pBaseAddress->ResourceMapped = FALSE; - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Memory range for VMMDev found! Base = %08x:%08x, Length = %08x\n", + Log(("VBoxGuest::vbgdNtScanPCIResourceList: Memory range for VMMDev found! Base = %08x:%08x, Length = %08x\n", pPartialData->u.Memory.Start.HighPart, pPartialData->u.Memory.Start.LowPart, pPartialData->u.Memory.Length)); @@ -1185,7 +1188,7 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD } else { - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Ignoring memory: Flags = %08x\n", + Log(("VBoxGuest::vbgdNtScanPCIResourceList: Ignoring memory: Flags = %08x\n", pPartialData->Flags)); } } @@ -1194,14 +1197,14 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD default: { - Log(("VBoxGuest::vboxguestwinScanPCIResourceList: Unhandled resource found, type = %d\n", pPartialData->Type)); + Log(("VBoxGuest::vbgdNtScanPCIResourceList: Unhandled resource found, type = %d\n", pPartialData->Type)); break; } } } /* Memorize the number of resources found. */ - pDevExt->win.s.pciAddressCount = rangeCount; + pDevExt->pciAddressCount = rangeCount; return rc; } @@ -1212,48 +1215,46 @@ NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTD * @return NTSTATUS * * @param pDevExt The device extension. - * @param physicalAdr Physical address to map. - * @param ulLength Length (in bytes) to map. + * @param PhysAddr Physical address to map. + * @param cbToMap Number of bytes to map. * @param ppvMMIOBase Pointer of mapped I/O base. * @param pcbMMIO Length of mapped I/O base. */ -NTSTATUS vboxguestwinMapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt, PHYSICAL_ADDRESS physicalAdr, ULONG ulLength, - void **ppvMMIOBase, uint32_t *pcbMMIO) +NTSTATUS vbgdNtMapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt, PHYSICAL_ADDRESS PhysAddr, ULONG cbToMap, + void **ppvMMIOBase, uint32_t *pcbMMIO) { AssertPtrReturn(pDevExt, VERR_INVALID_POINTER); AssertPtrReturn(ppvMMIOBase, VERR_INVALID_POINTER); /* pcbMMIO is optional. */ NTSTATUS rc = STATUS_SUCCESS; - if (physicalAdr.LowPart > 0) /* We're mapping below 4GB. */ + if (PhysAddr.LowPart > 0) /* We're mapping below 4GB. */ { - VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(physicalAdr, ulLength, MmNonCached); - Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: pVMMDevMemory = 0x%x\n", pVMMDevMemory)); + VMMDevMemory *pVMMDevMemory = (VMMDevMemory *)MmMapIoSpace(PhysAddr, cbToMap, MmNonCached); + Log(("VBoxGuest::vbgdNtMapVMMDevMemory: pVMMDevMemory = 0x%x\n", pVMMDevMemory)); if (pVMMDevMemory) { - Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: VMMDevMemory: Version = 0x%x, Size = %d\n", + Log(("VBoxGuest::vbgdNtMapVMMDevMemory: VMMDevMemory: Version = 0x%x, Size = %d\n", pVMMDevMemory->u32Version, pVMMDevMemory->u32Size)); /* Check version of the structure; do we have the right memory version? */ - if (pVMMDevMemory->u32Version != VMMDEV_MEMORY_VERSION) - { - Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: Wrong version (%u), refusing operation!\n", - pVMMDevMemory->u32Version)); - - /* Not our version, refuse operation and unmap the memory. */ - vboxguestwinUnmapVMMDevMemory(pDevExt); - rc = STATUS_UNSUCCESSFUL; - } - else + if (pVMMDevMemory->u32Version == VMMDEV_MEMORY_VERSION) { /* Save results. */ *ppvMMIOBase = pVMMDevMemory; if (pcbMMIO) /* Optional. */ *pcbMMIO = pVMMDevMemory->u32Size; - Log(("VBoxGuest::vboxguestwinMapVMMDevMemory: VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n", + Log(("VBoxGuest::vbgdNtMapVMMDevMemory: VMMDevMemory found and mapped! pvMMIOBase = 0x%p\n", *ppvMMIOBase)); } + else + { + /* Not our version, refuse operation and unmap the memory. */ + Log(("VBoxGuest::vbgdNtMapVMMDevMemory: Wrong version (%u), refusing operation!\n", pVMMDevMemory->u32Version)); + vbgdNtUnmapVMMDevMemory(pDevExt); + rc = STATUS_UNSUCCESSFUL; + } } else rc = STATUS_UNSUCCESSFUL; @@ -1267,34 +1268,34 @@ NTSTATUS vboxguestwinMapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt, PHYSICAL_ADDRESS * * @param pDevExt The device extension. */ -void vboxguestwinUnmapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt) +void vbgdNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt) { - Log(("VBoxGuest::vboxguestwinUnmapVMMDevMemory: pVMMDevMemory = 0x%x\n", pDevExt->pVMMDevMemory)); - if (pDevExt->pVMMDevMemory) + Log(("VBoxGuest::vbgdNtUnmapVMMDevMemory: pVMMDevMemory = 0x%x\n", pDevExt->Core.pVMMDevMemory)); + if (pDevExt->Core.pVMMDevMemory) { - MmUnmapIoSpace((void*)pDevExt->pVMMDevMemory, pDevExt->win.s.vmmDevPhysMemoryLength); - pDevExt->pVMMDevMemory = NULL; + MmUnmapIoSpace((void*)pDevExt->Core.pVMMDevMemory, pDevExt->vmmDevPhysMemoryLength); + pDevExt->Core.pVMMDevMemory = NULL; } - pDevExt->win.s.vmmDevPhysMemoryAddress.QuadPart = 0; - pDevExt->win.s.vmmDevPhysMemoryLength = 0; + pDevExt->vmmDevPhysMemoryAddress.QuadPart = 0; + pDevExt->vmmDevPhysMemoryLength = 0; } -VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer) +VBOXOSTYPE vbgdNtVersionToOSType(VBGDNTVER enmNtVer) { VBOXOSTYPE enmOsType; - switch (winVer) + switch (enmNtVer) { - case WINNT4: + case VBGDNTVER_WINNT4: enmOsType = VBOXOSTYPE_WinNT4; break; - case WIN2K: + case VBGDNTVER_WIN2K: enmOsType = VBOXOSTYPE_Win2k; break; - case WINXP: + case VBGDNTVER_WINXP: #if ARCH_BITS == 64 enmOsType = VBOXOSTYPE_WinXP_x64; #else @@ -1302,7 +1303,7 @@ VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer) #endif break; - case WIN2K3: + case VBGDNTVER_WIN2K3: #if ARCH_BITS == 64 enmOsType = VBOXOSTYPE_Win2k3_x64; #else @@ -1310,7 +1311,7 @@ VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer) #endif break; - case WINVISTA: + case VBGDNTVER_WINVISTA: #if ARCH_BITS == 64 enmOsType = VBOXOSTYPE_WinVista_x64; #else @@ -1318,7 +1319,7 @@ VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer) #endif break; - case WIN7: + case VBGDNTVER_WIN7: #if ARCH_BITS == 64 enmOsType = VBOXOSTYPE_Win7_x64; #else @@ -1326,7 +1327,7 @@ VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer) #endif break; - case WIN8: + case VBGDNTVER_WIN8: #if ARCH_BITS == 64 enmOsType = VBOXOSTYPE_Win8_x64; #else @@ -1334,6 +1335,14 @@ VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer) #endif break; + case VBGDNTVER_WIN81: +#if ARCH_BITS == 64 + enmOsType = VBOXOSTYPE_Win81_x64; +#else + enmOsType = VBOXOSTYPE_Win81; +#endif + break; + default: /* We don't know, therefore NT family. */ enmOsType = VBOXOSTYPE_WinNT; @@ -1350,8 +1359,7 @@ VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer) static uint32_t vboxugestwinAtomicBitsTestAndClear(void *pu32Bits, uint32_t u32Mask) { AssertPtrReturn(pu32Bits, 0); - LogFlowFunc(("*pu32Bits=0x%x, u32Mask=0x%x\n", *(long *)pu32Bits, - u32Mask)); + LogFlowFunc(("*pu32Bits=0x%x, u32Mask=0x%x\n", *(uint32_t *)pu32Bits, u32Mask)); uint32_t u32Result = 0; uint32_t u32WorkingMask = u32Mask; int iBitOffset = ASMBitFirstSetU32 (u32WorkingMask); @@ -1369,8 +1377,7 @@ static uint32_t vboxugestwinAtomicBitsTestAndClear(void *pu32Bits, uint32_t u32M } -static void vboxguestwinTestAtomicTestAndClearBitsU32(uint32_t u32Mask, uint32_t u32Bits, - uint32_t u32Exp) +static void vbgdNtTestAtomicTestAndClearBitsU32(uint32_t u32Mask, uint32_t u32Bits, uint32_t u32Exp) { ULONG u32Bits2 = u32Bits; uint32_t u32Result = vboxugestwinAtomicBitsTestAndClear(&u32Bits2, u32Mask); @@ -1385,104 +1392,134 @@ static void vboxguestwinTestAtomicTestAndClearBitsU32(uint32_t u32Mask, uint32_t } -static void vboxguestwinDoTests() +static void vbgdNtDoTests(void) { - vboxguestwinTestAtomicTestAndClearBitsU32(0x00, 0x23, 0); - vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0, 0); - vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x22, 0); - vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x23, 0x1); - vboxguestwinTestAtomicTestAndClearBitsU32(0x11, 0x32, 0x10); - vboxguestwinTestAtomicTestAndClearBitsU32(0x22, 0x23, 0x22); + vbgdNtTestAtomicTestAndClearBitsU32(0x00, 0x23, 0); + vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0, 0); + vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x22, 0); + vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x23, 0x1); + vbgdNtTestAtomicTestAndClearBitsU32(0x11, 0x32, 0x10); + vbgdNtTestAtomicTestAndClearBitsU32(0x22, 0x23, 0x22); } #endif /* DEBUG */ #ifdef VBOX_WITH_DPC_LATENCY_CHECKER -#pragma pack(1) + +/* + * DPC latency checker. + */ + +/** + * One DPC latency sample. + */ typedef struct DPCSAMPLE { - LARGE_INTEGER PerfDelta; - LARGE_INTEGER PerfCounter; - LARGE_INTEGER PerfFrequency; - uint64_t u64TSC; + LARGE_INTEGER PerfDelta; + LARGE_INTEGER PerfCounter; + LARGE_INTEGER PerfFrequency; + uint64_t u64TSC; } DPCSAMPLE; +AssertCompileSize(DPCSAMPLE, 4*8); +/** + * The DPC latency measurement workset. + */ typedef struct DPCDATA { - KDPC Dpc; - KTIMER Timer; - KSPIN_LOCK SpinLock; + KDPC Dpc; + KTIMER Timer; + KSPIN_LOCK SpinLock; + + ULONG ulTimerRes; - ULONG ulTimerRes; + bool volatile fFinished; - LARGE_INTEGER DueTime; + /** The timer interval (relative). */ + LARGE_INTEGER DueTime; - BOOLEAN fFinished; + LARGE_INTEGER PerfCounterPrev; - LARGE_INTEGER PerfCounterPrev; + /** Align the sample array on a 64 byte boundrary just for the off chance + * that we'll get cache line aligned memory backing this structure. */ + uint32_t auPadding[ARCH_BITS == 32 ? 5 : 7]; - int iSampleCount; - DPCSAMPLE aSamples[8192]; + int cSamples; + DPCSAMPLE aSamples[8192]; } DPCDATA; -#pragma pack(1) -#define VBOXGUEST_DPC_TAG 'DPCS' +AssertCompileMemberAlignment(DPCDATA, aSamples, 64); + +# define VBOXGUEST_DPC_TAG 'DPCS' + -static VOID DPCDeferredRoutine(struct _KDPC *Dpc, - PVOID DeferredContext, - PVOID SystemArgument1, - PVOID SystemArgument2) +/** + * DPC callback routine for the DPC latency measurement code. + * + * @param pDpc The DPC, not used. + * @param pvDeferredContext Pointer to the DPCDATA. + * @param SystemArgument1 System use, ignored. + * @param SystemArgument2 System use, ignored. + */ +static VOID vbgdNtDpcLatencyCallback(PKDPC pDpc, PVOID pvDeferredContext, PVOID SystemArgument1, PVOID SystemArgument2) { - DPCDATA *pData = (DPCDATA *)DeferredContext; + DPCDATA *pData = (DPCDATA *)pvDeferredContext; KeAcquireSpinLockAtDpcLevel(&pData->SpinLock); - if (pData->iSampleCount >= RT_ELEMENTS(pData->aSamples)) + if (pData->cSamples >= RT_ELEMENTS(pData->aSamples)) + pData->fFinished = true; + else { - pData->fFinished = 1; - KeReleaseSpinLockFromDpcLevel(&pData->SpinLock); - return; - } - - DPCSAMPLE *pSample = &pData->aSamples[pData->iSampleCount++]; + DPCSAMPLE *pSample = &pData->aSamples[pData->cSamples++]; - pSample->u64TSC = ASMReadTSC(); - pSample->PerfCounter = KeQueryPerformanceCounter(&pSample->PerfFrequency); - pSample->PerfDelta.QuadPart = pSample->PerfCounter.QuadPart - pData->PerfCounterPrev.QuadPart; + pSample->u64TSC = ASMReadTSC(); + pSample->PerfCounter = KeQueryPerformanceCounter(&pSample->PerfFrequency); + pSample->PerfDelta.QuadPart = pSample->PerfCounter.QuadPart - pData->PerfCounterPrev.QuadPart; - pData->PerfCounterPrev.QuadPart = pSample->PerfCounter.QuadPart; + pData->PerfCounterPrev.QuadPart = pSample->PerfCounter.QuadPart; - KeSetTimer(&pData->Timer, pData->DueTime, &pData->Dpc); + KeSetTimer(&pData->Timer, pData->DueTime, &pData->Dpc); + } KeReleaseSpinLockFromDpcLevel(&pData->SpinLock); } -int VBoxGuestCommonIOCtl_DPC(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, - void *pvData, size_t cbData, size_t *pcbDataReturned) -{ - int rc = VINF_SUCCESS; - /* Allocate a non paged memory for samples and related data. */ +/** + * Handles the DPC latency checker request. + * + * @returns VBox status code. + */ +int VbgdNtIOCtl_DpcLatencyChecker(void) +{ + /* + * Allocate a block of non paged memory for samples and related data. + */ DPCDATA *pData = (DPCDATA *)ExAllocatePoolWithTag(NonPagedPool, sizeof(DPCDATA), VBOXGUEST_DPC_TAG); - if (!pData) { RTLogBackdoorPrintf("VBoxGuest: DPC: DPCDATA allocation failed.\n"); return VERR_NO_MEMORY; } - KeInitializeDpc(&pData->Dpc, DPCDeferredRoutine, pData); + /* + * Initialize the data. + */ + KeInitializeDpc(&pData->Dpc, vbgdNtDpcLatencyCallback, pData); KeInitializeTimer(&pData->Timer); KeInitializeSpinLock(&pData->SpinLock); - pData->fFinished = 0; - pData->iSampleCount = 0; + pData->fFinished = false; + pData->cSamples = 0; pData->PerfCounterPrev.QuadPart = 0; pData->ulTimerRes = ExSetTimerResolution(1000 * 10, 1); pData->DueTime.QuadPart = -(int64_t)pData->ulTimerRes / 10; - /* Start the DPC measurements. */ + /* + * Start the DPC measurements and wait for a full set. + */ KeSetTimer(&pData->Timer, pData->DueTime, &pData->Dpc); while (!pData->fFinished) @@ -1494,22 +1531,25 @@ int VBoxGuestCommonIOCtl_DPC(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSessio ExSetTimerResolution(0, 0); - /* Log everything to the host. */ + /* + * Log everything to the host. + */ RTLogBackdoorPrintf("DPC: ulTimerRes = %d\n", pData->ulTimerRes); - int i; - for (i = 0; i < pData->iSampleCount; i++) + for (int i = 0; i < pData->cSamples; i++) { DPCSAMPLE *pSample = &pData->aSamples[i]; RTLogBackdoorPrintf("[%d] pd %lld pc %lld pf %lld t %lld\n", - i, - pSample->PerfDelta.QuadPart, - pSample->PerfCounter.QuadPart, - pSample->PerfFrequency.QuadPart, - pSample->u64TSC); + i, + pSample->PerfDelta.QuadPart, + pSample->PerfCounter.QuadPart, + pSample->PerfFrequency.QuadPart, + pSample->u64TSC); } ExFreePoolWithTag(pData, VBOXGUEST_DPC_TAG); - return rc; + return VINF_SUCCESS; } + #endif /* VBOX_WITH_DPC_LATENCY_CHECKER */ + diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.h b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.h index a3b02659..aee63677 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.h +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-win.h @@ -1,8 +1,10 @@ +/* $Id: VBoxGuest-win.h $ */ /** @file - * * VBoxGuest - Windows specifics. - * - * 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; @@ -16,9 +18,6 @@ #ifndef ___VBoxGuest_win_h #define ___VBoxGuest_win_h -/******************************************************************************* -* Header Files * -*******************************************************************************/ #include <iprt/cdefs.h> @@ -37,14 +36,9 @@ RT_C_DECLS_END #include <VBox/VMMDev.h> #include <VBox/VBoxGuest.h> +#include "VBoxGuestInternal.h" -/******************************************************************************* -* Structures and Typedefs * -*******************************************************************************/ - -/** Pointer to the VBoxGuest per session data. */ -typedef struct VBOXGUESTSESSION *PVBOXGUESTSESSION; /** Possible device states for our state machine. */ enum DEVSTATE @@ -77,6 +71,8 @@ typedef struct VBOXGUESTWINBASEADDRESS /** Windows-specific device extension bits. */ typedef struct VBOXGUESTDEVEXTWIN { + VBOXGUESTDEVEXT Core; + /** Our functional driver object. */ PDEVICE_OBJECT pDeviceObject; /** Top of the stack. */ @@ -119,64 +115,69 @@ typedef struct VBOXGUESTDEVEXTWIN VMMDevEvents *pIrqAckEvents; /** Pre-allocated kernel session data. This is needed - * for handling kernel IOCtls. */ - PVBOXGUESTSESSION pKernelSession; + * for handling kernel IOCtls. */ + struct VBOXGUESTSESSION *pKernelSession; /** Spinlock protecting MouseNotifyCallback. Required since the consumer is * in a DPC callback and not the ISR. */ KSPIN_LOCK MouseEventAccessLock; } VBOXGUESTDEVEXTWIN, *PVBOXGUESTDEVEXTWIN; -#define VBOXGUEST_UPDATE_DEVSTATE(_pDevExt, _newDevState) do { \ - (_pDevExt)->win.s.prevDevState = (_pDevExt)->win.s.devState; \ - (_pDevExt)->win.s.devState = (_newDevState); \ -} while (0) - -/******************************************************************************* -* Defined Constants And Macros * -*******************************************************************************/ +/** NT (windows) version identifier. */ +typedef enum VBGDNTVER +{ + VBGDNTVER_INVALID = 0, + VBGDNTVER_WINNT4, + VBGDNTVER_WIN2K, + VBGDNTVER_WINXP, + VBGDNTVER_WIN2K3, + VBGDNTVER_WINVISTA, + VBGDNTVER_WIN7, + VBGDNTVER_WIN8, + VBGDNTVER_WIN81, +} VBGDNTVER; +extern VBGDNTVER g_enmVbgdNtVer; + + +#define VBOXGUEST_UPDATE_DEVSTATE(a_pDevExt, a_newDevState) \ + do { \ + (a_pDevExt)->prevDevState = (a_pDevExt)->devState; \ + (a_pDevExt)->devState = (a_newDevState); \ + } while (0) /** CM_RESOURCE_MEMORY_* flags which were used on XP or earlier. */ #define VBOX_CM_PRE_VISTA_MASK (0x3f) -/** Windows version identifier. */ -typedef enum -{ - WINNT4 = 1, - WIN2K = 2, - WINXP = 3, - WIN2K3 = 4, - WINVISTA = 5, - WIN7 = 6, - WIN8 = 7 -} winVersion_t; -extern winVersion_t winVersion; - - -/******************************************************************************* -* Declared prototypes for helper routines used in both (PnP and legacy) * -* driver versions. * -*******************************************************************************/ -#include "VBoxGuestInternal.h" RT_C_DECLS_BEGIN + #ifdef TARGET_NT4 -NTSTATUS vboxguestwinnt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath); -NTSTATUS vboxguestwinInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath); +NTSTATUS vbgdNt4CreateDevice(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath); #else -NTSTATUS vboxguestwinInit(PDEVICE_OBJECT pDevObj, PIRP pIrp); +NTSTATUS vbgdNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp); +NTSTATUS vbgdNtPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp); +NTSTATUS vbgdNtPower(PDEVICE_OBJECT pDevObj, PIRP pIrp); #endif -NTSTATUS vboxguestwinCleanup(PDEVICE_OBJECT pDevObj); -NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp); -VOID vboxguestwinDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext); -BOOLEAN vboxguestwinIsrHandler(PKINTERRUPT interrupt, PVOID serviceContext); -NTSTATUS vboxguestwinScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXT pDevExt); -NTSTATUS vboxguestwinMapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt, PHYSICAL_ADDRESS physicalAdr, ULONG ulLength, - void **ppvMMIOBase, uint32_t *pcbMMIO); -void vboxguestwinUnmapVMMDevMemory(PVBOXGUESTDEVEXT pDevExt); -VBOXOSTYPE vboxguestwinVersionToOSType(winVersion_t winVer); -NTSTATUS vboxguestwinPower(PDEVICE_OBJECT pDevObj, PIRP pIrp); + +/** @name Common routines used in both (PnP and legacy) driver versions. + * @{ + */ +#ifdef TARGET_NT4 +NTSTATUS vbgdNtInit(PDRIVER_OBJECT pDrvObj, PDEVICE_OBJECT pDevObj, PUNICODE_STRING pRegPath); +#else +NTSTATUS vbgdNtInit(PDEVICE_OBJECT pDevObj, PIRP pIrp); +#endif +NTSTATUS vbgdNtCleanup(PDEVICE_OBJECT pDevObj); +VOID vbgdNtDpcHandler(PKDPC pDPC, PDEVICE_OBJECT pDevObj, PIRP pIrp, PVOID pContext); +BOOLEAN vbgdNtIsrHandler(PKINTERRUPT interrupt, PVOID serviceContext); +NTSTATUS vbgdNtScanPCIResourceList(PCM_RESOURCE_LIST pResList, PVBOXGUESTDEVEXTWIN pDevExt); +NTSTATUS vbgdNtMapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt, PHYSICAL_ADDRESS PhysAddr, ULONG cbToMap, + void **ppvMMIOBase, uint32_t *pcbMMIO); +void vbgdNtUnmapVMMDevMemory(PVBOXGUESTDEVEXTWIN pDevExt); +VBOXOSTYPE vbgdNtVersionToOSType(VBGDNTVER enmNtVer); +/** @} */ + RT_C_DECLS_END #ifdef TARGET_NT4 @@ -184,9 +185,9 @@ RT_C_DECLS_END * XP DDK #defines ExFreePool to ExFreePoolWithTag. The latter does not exist * on NT4, so... The same for ExAllocatePool. */ -#undef ExAllocatePool -#undef ExFreePool +# undef ExAllocatePool +# undef ExFreePool #endif -#endif /* ___VBoxGuest_win_h */ +#endif /* !___VBoxGuest_win_h */ diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp b/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp index 594e0921..b1ffd3ba 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp @@ -4,7 +4,7 @@ */ /* - * Copyright (C) 2007-2012 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; @@ -54,7 +54,7 @@ # include <Windows.h> # endif #endif -#if defined(RT_OS_SOLARIS) +#if defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN) # include <iprt/rand.h> #endif @@ -70,17 +70,61 @@ static void testSetMouseStatus(void); #endif static int VBoxGuestCommonIOCtl_SetMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fFeatures); -#ifdef VBOX_WITH_DPC_LATENCY_CHECKER -int VBoxGuestCommonIOCtl_DPC(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, - void *pvData, size_t cbData, size_t *pcbDataReturned); -#endif /* VBOX_WITH_DPC_LATENCY_CHECKER */ +static int VBoxGuestCommonGuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fOrMask, uint32_t fNotMask, VBOXGUESTCAPSACQUIRE_FLAGS enmFlags); + +#define VBOXGUEST_ACQUIRE_STYLE_EVENTS (VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST | VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST) + +DECLINLINE(uint32_t) VBoxGuestCommonGetHandledEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession) +{ + if (!pDevExt->u32AcquireModeGuestCaps) + return VMMDEV_EVENT_VALID_EVENT_MASK; + + uint32_t u32AllowedGuestCaps = pSession->u32AquiredGuestCaps | (VMMDEV_EVENT_VALID_EVENT_MASK & ~pDevExt->u32AcquireModeGuestCaps); + uint32_t u32CleanupEvents = VBOXGUEST_ACQUIRE_STYLE_EVENTS; + if (u32AllowedGuestCaps & VMMDEV_GUEST_SUPPORTS_GRAPHICS) + u32CleanupEvents &= ~VMMDEV_EVENT_DISPLAY_CHANGE_REQUEST; + if (u32AllowedGuestCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS) + u32CleanupEvents &= ~VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; + + return VMMDEV_EVENT_VALID_EVENT_MASK & ~u32CleanupEvents; +} + +DECLINLINE(uint32_t) VBoxGuestCommonGetAndCleanPendingEventsLocked(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fReqEvents) +{ + uint32_t fMatches = pDevExt->f32PendingEvents & fReqEvents & VBoxGuestCommonGetHandledEventsLocked(pDevExt, pSession); + if (fMatches) + ASMAtomicAndU32(&pDevExt->f32PendingEvents, ~fMatches); + return fMatches; +} + +DECLINLINE(bool) VBoxGuestCommonGuestCapsModeSet(PVBOXGUESTDEVEXT pDevExt, uint32_t fCaps, bool fAcquire, uint32_t *pu32OtherVal) +{ + uint32_t *pVal = fAcquire ? &pDevExt->u32AcquireModeGuestCaps : &pDevExt->u32SetModeGuestCaps; + const uint32_t fNotVal = !fAcquire ? pDevExt->u32AcquireModeGuestCaps : pDevExt->u32SetModeGuestCaps; + bool fResult = true; + RTSpinlockAcquire(pDevExt->EventSpinlock); + + if (!(fNotVal & fCaps)) + *pVal |= fCaps; + else + { + AssertMsgFailed(("trying to change caps mode\n")); + fResult = false; + } + + RTSpinlockReleaseNoInts(pDevExt->EventSpinlock); + + if (pu32OtherVal) + *pu32OtherVal = fNotVal; + return fResult; +} /******************************************************************************* * Global Variables * *******************************************************************************/ static const size_t cbChangeMemBalloonReq = RT_OFFSETOF(VMMDevChangeMemBalloon, aPhysPage[VMMDEV_MEMORY_BALLOON_CHUNK_PAGES]); -#if defined(RT_OS_SOLARIS) +#if defined(RT_OS_DARWIN) || defined(RT_OS_SOLARIS) /** * Drag in the rest of IRPT since we share it with the * rest of the kernel modules on Solaris. @@ -100,7 +144,7 @@ PFNRT g_apfnVBoxGuestIPRTDeps[] = (PFNRT)RTSemMutexIsOwned, NULL }; -#endif /* RT_OS_SOLARIS */ +#endif /* RT_OS_DARWIN || RT_OS_SOLARIS */ /** @@ -418,7 +462,7 @@ static int vboxGuestSetBalloonSizeKernel(PVBOXGUESTDEVEXT pDevExt, uint32_t cBal pDevExt->MemBalloon.paMemObj = (PRTR0MEMOBJ)RTMemAllocZ(sizeof(RTR0MEMOBJ) * pDevExt->MemBalloon.cMaxChunks); if (!pDevExt->MemBalloon.paMemObj) { - LogRel(("VBoxGuestSetBalloonSizeKernel: no memory for paMemObj!\n")); + LogRel(("vboxGuestSetBalloonSizeKernel: no memory for paMemObj!\n")); return VERR_NO_MEMORY; } } @@ -706,6 +750,20 @@ int VBoxGuestInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, int rc, rc2; unsigned i; +#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER + /* + * Create the release log. + */ + static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; + PRTLOGGER pRelLogger; + rc = RTLogCreate(&pRelLogger, 0 /* fFlags */, "all", + "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER, NULL); + if (RT_SUCCESS(rc)) + RTLogRelSetDefaultInstance(pRelLogger); + /** @todo Add native hook for getting logger config parameters and setting + * them. On linux we should use the module parameter stuff... */ +#endif + /* * Adjust fFixedEvents. */ @@ -772,6 +830,10 @@ int VBoxGuestInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, pVMMDev->u32Version, VMMDEV_MEMORY_VERSION, pVMMDev->u32Size, cbMMIO)); } + pDevExt->u32AcquireModeGuestCaps = 0; + pDevExt->u32SetModeGuestCaps = 0; + pDevExt->u32GuestCaps = 0; + /* * Create the wait and session spinlocks as well as the ballooning mutex. */ @@ -856,6 +918,11 @@ int VBoxGuestInitDevExt(PVBOXGUESTDEVEXT pDevExt, uint16_t IOPortBase, rc2 = RTSemFastMutexDestroy(pDevExt->MemBalloon.hMtx); AssertRC(rc2); rc2 = RTSpinlockDestroy(pDevExt->EventSpinlock); AssertRC(rc2); rc2 = RTSpinlockDestroy(pDevExt->SessionSpinlock); AssertRC(rc2); + +#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER + RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); + RTLogDestroy(RTLogSetDefaultInstance(NULL)); +#endif return rc; /* (failed) */ } @@ -925,6 +992,12 @@ void VBoxGuestDeleteDevExt(PVBOXGUESTDEVEXT pDevExt) pDevExt->IOPortBase = 0; pDevExt->pIrqAckEvents = NULL; + +#ifdef VBOX_GUESTDRV_WITH_RELEASE_LOGGER + RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); + RTLogDestroy(RTLogSetDefaultInstance(NULL)); +#endif + } @@ -987,7 +1060,7 @@ int VBoxGuestCreateKernelSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION *pp return VINF_SUCCESS; } - +static int VBoxGuestCommonIOCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession); /** * Closes a VBoxGuest session. @@ -1001,6 +1074,10 @@ void VBoxGuestCloseSession(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession) Log(("VBoxGuestCloseSession: pSession=%p proc=%RTproc (%d) r0proc=%p\n", pSession, pSession->Process, (int)pSession->Process, (uintptr_t)pSession->R0Process)); /** @todo %RTr0proc */ + VBoxGuestCommonGuestCapsAcquire(pDevExt, pSession, 0, UINT32_MAX, VBOXGUESTCAPSACQUIRE_FLAGS_NONE); + + VBoxGuestCommonIOCtl_CancelAllWaitEvents(pDevExt, pSession); + #ifdef VBOX_WITH_HGCM for (i = 0; i < RT_ELEMENTS(pSession->aHGCMClientIds); i++) if (pSession->aHGCMClientIds[i]) @@ -1291,13 +1368,12 @@ int VBoxGuestCommonIOCtl_SetMouseNotifyCallback(PVBOXGUESTDEVEXT pDevExt, VBoxGu * * @returns VINF_SUCCESS if we've left the spinlock and can return immediately. */ -DECLINLINE(int) WaitEventCheckCondition(PVBOXGUESTDEVEXT pDevExt, VBoxGuestWaitEventInfo *pInfo, +DECLINLINE(int) WaitEventCheckCondition(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestWaitEventInfo *pInfo, int iEvent, const uint32_t fReqEvents) { - uint32_t fMatches = pDevExt->f32PendingEvents & fReqEvents; + uint32_t fMatches = VBoxGuestCommonGetAndCleanPendingEventsLocked(pDevExt, pSession, fReqEvents); if (fMatches) { - ASMAtomicAndU32(&pDevExt->f32PendingEvents, ~fMatches); RTSpinlockReleaseNoInts(pDevExt->EventSpinlock); pInfo->u32EventFlagsOut = fMatches; @@ -1333,7 +1409,7 @@ static int VBoxGuestCommonIOCtl_WaitEvent(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSE iEvent = ASMBitFirstSetU32(fReqEvents) - 1; if (RT_UNLIKELY(iEvent < 0)) { - Log(("VBoxGuestCommonIOCtl: WAITEVENT: Invalid input mask %#x!!\n", fReqEvents)); + LogRel(("VBoxGuestCommonIOCtl: WAITEVENT: Invalid input mask %#x!!\n", fReqEvents)); return VERR_INVALID_PARAMETER; } @@ -1341,7 +1417,7 @@ static int VBoxGuestCommonIOCtl_WaitEvent(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSE * Check the condition up front, before doing the wait-for-event allocations. */ RTSpinlockAcquire(pDevExt->EventSpinlock); - rc = WaitEventCheckCondition(pDevExt, pInfo, iEvent, fReqEvents); + rc = WaitEventCheckCondition(pDevExt, pSession, pInfo, iEvent, fReqEvents); if (rc == VINF_SUCCESS) return rc; @@ -1364,7 +1440,7 @@ static int VBoxGuestCommonIOCtl_WaitEvent(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSE */ RTSpinlockAcquire(pDevExt->EventSpinlock); RTListAppend(&pDevExt->WaitList, &pWait->ListNode); - rc = WaitEventCheckCondition(pDevExt, pInfo, iEvent, fReqEvents); + rc = WaitEventCheckCondition(pDevExt, pSession, pInfo, iEvent, fReqEvents); if (rc == VINF_SUCCESS) { VBoxGuestWaitFreeUnlocked(pDevExt, pWait); @@ -1465,6 +1541,7 @@ static int VBoxGuestCommonIOCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PV } RTSpinlockReleaseNoInts(pDevExt->EventSpinlock); Assert(rc == 0); + NOREF(rc); #ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP VBoxGuestWaitDoWakeUps(pDevExt); @@ -1481,7 +1558,7 @@ static int VBoxGuestCommonIOCtl_CancelAllWaitEvents(PVBOXGUESTDEVEXT pDevExt, PV * @param enmType The request type. * @param pReqHdr The request. */ -static int VBoxGuestCheckIfVMMReqAllowed(PVBOXGUESTSESSION pSession, VMMDevRequestType enmType, +static int VBoxGuestCheckIfVMMReqAllowed(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VMMDevRequestType enmType, VMMDevRequestHeader const *pReqHdr) { /* @@ -1541,12 +1618,34 @@ static int VBoxGuestCheckIfVMMReqAllowed(PVBOXGUESTSESSION pSession, VMMDevReque case VMMDevReq_GetPageSharingStatus: case VMMDevReq_DebugIsPageShared: case VMMDevReq_ReportGuestStats: + case VMMDevReq_ReportGuestUserState: case VMMDevReq_GetStatisticsChangeRequest: case VMMDevReq_ChangeMemBalloon: enmRequired = kLevel_TrustedUsers; break; /* + * Anyone. But not for CapsAcquire mode + */ + case VMMDevReq_SetGuestCapabilities: + { + VMMDevReqGuestCapabilities2 *pCaps = (VMMDevReqGuestCapabilities2*)pReqHdr; + uint32_t fAcquireCaps = 0; + if (!VBoxGuestCommonGuestCapsModeSet(pDevExt, pCaps->u32OrMask, false, &fAcquireCaps)) + { + AssertFailed(); + LogRel(("calling caps set for acquired caps %d\n", pCaps->u32OrMask)); + enmRequired = kLevel_NoOne; + break; + } + /* hack to adjust the notcaps. + * @todo: move to a better place + * user-mode apps are allowed to pass any mask to the notmask, + * the driver cleans up them accordingly */ + pCaps->u32NotMask &= ~fAcquireCaps; + /* do not break, make it fall through to the below enmRequired setting */ + } + /* * Anyone. */ case VMMDevReq_GetMouseStatus: @@ -1563,11 +1662,11 @@ static int VBoxGuestCheckIfVMMReqAllowed(PVBOXGUESTSESSION pSession, VMMDevReque case VMMDevReq_VideoModeSupported: case VMMDevReq_GetHeightReduction: case VMMDevReq_GetDisplayChangeRequest2: - case VMMDevReq_SetGuestCapabilities: case VMMDevReq_VideoModeSupported2: case VMMDevReq_VideoAccelEnable: case VMMDevReq_VideoAccelFlush: case VMMDevReq_VideoSetVisibleRegion: + case VMMDevReq_GetDisplayChangeRequestEx: case VMMDevReq_GetSeamlessChangeRequest: case VMMDevReq_GetVRDPChangeRequest: case VMMDevReq_LogString: @@ -1641,13 +1740,13 @@ static int VBoxGuestCommonIOCtl_VMMRequest(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTS if (cbReq < cbMinSize) { - Log(("VBoxGuestCommonIOCtl: VMMREQUEST: invalid hdr size %#x, expected >= %#x; type=%#x!!\n", + LogRel(("VBoxGuestCommonIOCtl: VMMREQUEST: invalid hdr size %#x, expected >= %#x; type=%#x!!\n", cbReq, cbMinSize, enmType)); return VERR_INVALID_PARAMETER; } if (cbReq > cbData) { - Log(("VBoxGuestCommonIOCtl: VMMREQUEST: invalid size %#x, expected >= %#x (hdr); type=%#x!!\n", + LogRel(("VBoxGuestCommonIOCtl: VMMREQUEST: invalid size %#x, expected >= %#x (hdr); type=%#x!!\n", cbData, cbReq, enmType)); return VERR_INVALID_PARAMETER; } @@ -1659,7 +1758,7 @@ static int VBoxGuestCommonIOCtl_VMMRequest(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTS return rc; } - rc = VBoxGuestCheckIfVMMReqAllowed(pSession, enmType, pReqHdr); + rc = VBoxGuestCheckIfVMMReqAllowed(pDevExt, pSession, enmType, pReqHdr); if (RT_FAILURE(rc)) { Log(("VBoxGuestCommonIOCtl: VMMREQUEST: Operation not allowed! type=%#x rc=%Rrc\n", enmType, rc)); @@ -1974,7 +2073,7 @@ static int VBoxGuestCommonIOCtl_HGCMCall(PVBOXGUESTDEVEXT pDevExt, if (cbData < cbActual) { LogRel(("VBoxGuestCommonIOCtl: HGCM_CALL: cbData=%#zx (%zu) required size is %#zx (%zu)\n", - cbData, cbActual)); + cbData, cbData, cbActual, cbActual)); return VERR_INVALID_PARAMETER; } @@ -2283,6 +2382,9 @@ static int VBoxGuestCommonIOCtl_SetMouseStatus(PVBOXGUESTDEVEXT pDevExt, PVBOXGU RTSpinlockAcquire(pDevExt->SessionSpinlock); + /* For all the bits which the guest is allowed to set, check whether the + * requested value is different to the current one and adjust the global + * usage counter and if appropriate the global state if so. */ for (i = 0; i < sizeof(fFeatures) * 8; i++) { if (RT_BIT_32(i) & VMMDEV_MOUSE_GUEST_MASK) @@ -2417,6 +2519,170 @@ static int VBoxGuestCommonIOCtl_Log(PVBOXGUESTDEVEXT pDevExt, const char *pch, s return VINF_SUCCESS; } +static bool VBoxGuestCommonGuestCapsValidateValues(uint32_t fCaps) +{ + if (fCaps & (~(VMMDEV_GUEST_SUPPORTS_SEAMLESS | VMMDEV_GUEST_SUPPORTS_GUEST_HOST_WINDOW_MAPPING | VMMDEV_GUEST_SUPPORTS_GRAPHICS))) + return false; + + return true; +} + +static void VBoxGuestCommonCheckEvents(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fGenFakeEvents) +{ + RTSpinlockAcquire(pDevExt->EventSpinlock); + uint32_t fEvents = fGenFakeEvents | pDevExt->f32PendingEvents; + PVBOXGUESTWAIT pWait; + PVBOXGUESTWAIT pSafe; + + RTListForEachSafe(&pDevExt->WaitList, pWait, pSafe, VBOXGUESTWAIT, ListNode) + { + uint32_t fHandledEvents = VBoxGuestCommonGetHandledEventsLocked(pDevExt, pWait->pSession); + if ( (pWait->fReqEvents & fEvents & fHandledEvents) + && !pWait->fResEvents) + { + pWait->fResEvents = pWait->fReqEvents & fEvents & fHandledEvents; + Assert(!(fGenFakeEvents & pWait->fResEvents) || pSession == pWait->pSession); + fEvents &= ~pWait->fResEvents; + RTListNodeRemove(&pWait->ListNode); +#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP + RTListAppend(&pDevExt->WakeUpList, &pWait->ListNode); +#else + RTListAppend(&pDevExt->WokenUpList, &pWait->ListNode); + int rc = RTSemEventMultiSignal(pWait->Event); + AssertRC(rc); +#endif + if (!fEvents) + break; + } + } + ASMAtomicWriteU32(&pDevExt->f32PendingEvents, fEvents); + + RTSpinlockReleaseNoInts(pDevExt->EventSpinlock); + +#ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP + VBoxGuestWaitDoWakeUps(pDevExt); +#endif +} + +static int VBoxGuestCommonGuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, uint32_t fOrMask, uint32_t fNotMask, VBOXGUESTCAPSACQUIRE_FLAGS enmFlags) +{ + uint32_t fSetCaps = 0; + + if (!VBoxGuestCommonGuestCapsValidateValues(fOrMask)) + { + LogRel(("VBoxGuestCommonGuestCapsAcquire: pSession(0x%p), OR(0x%x), NOT(0x%x), flags(0x%x) -- invalid fOrMask\n", + pSession, fOrMask, fNotMask, enmFlags)); + return VERR_INVALID_PARAMETER; + } + + if ( enmFlags != VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE + && enmFlags != VBOXGUESTCAPSACQUIRE_FLAGS_NONE) + { + LogRel(("VBoxGuestCommonGuestCapsAcquire: pSession(0x%p), OR(0x%x), NOT(0x%x), flags(0x%x) -- invalid enmFlags %d\n", + pSession, fOrMask, fNotMask, enmFlags)); + return VERR_INVALID_PARAMETER; + } + + if (!VBoxGuestCommonGuestCapsModeSet(pDevExt, fOrMask, true, &fSetCaps)) + { + LogRel(("VBoxGuestCommonGuestCapsAcquire: pSession(0x%p), OR(0x%x), NOT(0x%x), flags(0x%x) -- calling caps acquire for set caps\n", + pSession, fOrMask, fNotMask, enmFlags)); + return VERR_INVALID_STATE; + } + + if (enmFlags & VBOXGUESTCAPSACQUIRE_FLAGS_CONFIG_ACQUIRE_MODE) + { + Log(("VBoxGuestCommonGuestCapsAcquire: pSession(0x%p), OR(0x%x), NOT(0x%x), flags(0x%x) -- configured acquire caps: 0x%x\n", + pSession, fOrMask, fNotMask, enmFlags)); + return VINF_SUCCESS; + } + + /* the fNotMask no need to have all values valid, + * invalid ones will simply be ignored */ + uint32_t fCurrentOwnedCaps; + uint32_t fSessionNotCaps; + uint32_t fSessionOrCaps; + uint32_t fOtherConflictingCaps; + + fNotMask &= ~fOrMask; + + RTSpinlockAcquire(pDevExt->EventSpinlock); + + fCurrentOwnedCaps = pSession->u32AquiredGuestCaps; + fSessionNotCaps = fCurrentOwnedCaps & fNotMask; + fSessionOrCaps = fOrMask & ~fCurrentOwnedCaps; + fOtherConflictingCaps = pDevExt->u32GuestCaps & ~fCurrentOwnedCaps; + fOtherConflictingCaps &= fSessionOrCaps; + + if (!fOtherConflictingCaps) + { + if (fSessionOrCaps) + { + pSession->u32AquiredGuestCaps |= fSessionOrCaps; + pDevExt->u32GuestCaps |= fSessionOrCaps; + } + + if (fSessionNotCaps) + { + pSession->u32AquiredGuestCaps &= ~fSessionNotCaps; + pDevExt->u32GuestCaps &= ~fSessionNotCaps; + } + } + + RTSpinlockReleaseNoInts(pDevExt->EventSpinlock); + + if (fOtherConflictingCaps) + { + Log(("VBoxGuest: Caps 0x%x were busy\n", fOtherConflictingCaps)); + return VERR_RESOURCE_BUSY; + } + + /* now do host notification outside the lock */ + if (!fSessionOrCaps && !fSessionNotCaps) + { + /* no changes, return */ + return VINF_SUCCESS; + } + + int rc = VBoxGuestSetGuestCapabilities(fSessionOrCaps, fSessionNotCaps); + if (RT_FAILURE(rc)) + { + LogRel(("VBoxGuestCommonGuestCapsAcquire: VBoxGuestSetGuestCapabilities failed, rc=%Rrc\n", rc)); + + /* Failure branch + * this is generally bad since e.g. failure to release the caps may result in other sessions not being able to use it + * so we are not trying to restore the caps back to their values before the VBoxGuestCommonGuestCapsAcquire call, + * but just pretend everithing is OK. + * @todo: better failure handling mechanism? */ + } + + /* success! */ + uint32_t fGenFakeEvents = 0; + + if (fSessionOrCaps & VMMDEV_GUEST_SUPPORTS_SEAMLESS) + { + /* generate the seamless change event so that the r3 app could synch with the seamless state + * although this introduces a false alarming of r3 client, it still solve the problem of + * client state inconsistency in multiuser environment */ + fGenFakeEvents |= VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST; + } + + /* since the acquire filter mask has changed, we need to process events in any way to ensure they go from pending events field + * to the proper (un-filtered) entries */ + VBoxGuestCommonCheckEvents(pDevExt, pSession, fGenFakeEvents); + + return VINF_SUCCESS; +} + +static int VBoxGuestCommonIOCTL_GuestCapsAcquire(PVBOXGUESTDEVEXT pDevExt, PVBOXGUESTSESSION pSession, VBoxGuestCapsAquire *pAcquire) +{ + int rc = VBoxGuestCommonGuestCapsAcquire(pDevExt, pSession, pAcquire->u32OrMask, pAcquire->u32NotMask, pAcquire->enmFlags); + if (RT_FAILURE(rc)) + LogRel(("VBoxGuestCommonGuestCapsAcquire: failed rc=%Rrc\n", rc)); + pAcquire->rc = rc; + return VINF_SUCCESS; +} + /** * Common IOCtl for user to kernel and kernel to kernel communication. @@ -2477,7 +2743,7 @@ int VBoxGuestCommonIOCtl(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUES if (cbData != (cb)) \ { \ LogFunc((mnemonic ": cbData=%#zx (%zu) expected is %#zx (%zu)\n", \ - cbData, cbData, (size_t)(cb), (size_t)(cb))); \ + cbData, cbData, (size_t)(cb), (size_t)(cb))); \ return VERR_BUFFER_OVERFLOW; \ } \ if ((cb) != 0 && !VALID_PTR(pvData)) \ @@ -2497,12 +2763,6 @@ int VBoxGuestCommonIOCtl(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUES CHECKRET_MIN_SIZE("VMMREQUEST", sizeof(VMMDevRequestHeader)); rc = VBoxGuestCommonIOCtl_VMMRequest(pDevExt, pSession, (VMMDevRequestHeader *)pvData, cbData, pcbDataReturned); } -#ifdef VBOX_WITH_DPC_LATENCY_CHECKER - else if (VBOXGUEST_IOCTL_STRIP_SIZE(iFunction) == VBOXGUEST_IOCTL_STRIP_SIZE(VBOXGUEST_IOCTL_DPC)) - { - rc = VBoxGuestCommonIOCtl_DPC(pDevExt, pSession, pvData, cbData, pcbDataReturned); - } -#endif /* VBOX_WITH_DPC_LATENCY_CHECKER */ #ifdef VBOX_WITH_HGCM /* * These ones are a bit tricky. @@ -2640,10 +2900,23 @@ int VBoxGuestCommonIOCtl(unsigned iFunction, PVBOXGUESTDEVEXT pDevExt, PVBOXGUES *(uint32_t *)pvData); break; +#ifdef VBOX_WITH_DPC_LATENCY_CHECKER + case VBOXGUEST_IOCTL_DPC_LATENCY_CHECKER: + CHECKRET_SIZE("DPC_LATENCY_CHECKER", 0); + rc = VbgdNtIOCtl_DpcLatencyChecker(); + break; +#endif + + case VBOXGUEST_IOCTL_GUEST_CAPS_ACQUIRE: + CHECKRET_SIZE("GUEST_CAPS_ACQUIRE", sizeof(VBoxGuestCapsAquire)); + rc = VBoxGuestCommonIOCTL_GuestCapsAcquire(pDevExt, pSession, (VBoxGuestCapsAquire*)pvData); + *pcbDataReturned = sizeof(VBoxGuestCapsAquire); + break; + default: { - LogRel(("VBoxGuestCommonIOCtl: Unknown request iFunction=%#x Stripped size=%#x\n", iFunction, - VBOXGUEST_IOCTL_STRIP_SIZE(iFunction))); + LogRel(("VBoxGuestCommonIOCtl: Unknown request iFunction=%#x stripped size=%#x\n", + iFunction, VBOXGUEST_IOCTL_STRIP_SIZE(iFunction))); rc = VERR_NOT_SUPPORTED; break; } @@ -2704,7 +2977,7 @@ bool VBoxGuestCommonISR(PVBOXGUESTDEVEXT pDevExt) PVBOXGUESTWAIT pWait; PVBOXGUESTWAIT pSafe; - Log(("VBoxGuestCommonISR: acknowledge events succeeded %#RX32\n", fEvents)); + Log3(("VBoxGuestCommonISR: acknowledge events succeeded %#RX32\n", fEvents)); /* * VMMDEV_EVENT_MOUSE_POSITION_CHANGED can only be polled for. @@ -2748,10 +3021,11 @@ bool VBoxGuestCommonISR(PVBOXGUESTDEVEXT pDevExt) fEvents |= pDevExt->f32PendingEvents; RTListForEachSafe(&pDevExt->WaitList, pWait, pSafe, VBOXGUESTWAIT, ListNode) { - if ( (pWait->fReqEvents & fEvents) + uint32_t fHandledEvents = VBoxGuestCommonGetHandledEventsLocked(pDevExt, pWait->pSession); + if ( (pWait->fReqEvents & fEvents & fHandledEvents) && !pWait->fResEvents) { - pWait->fResEvents = pWait->fReqEvents & fEvents; + pWait->fResEvents = pWait->fReqEvents & fEvents & fHandledEvents; fEvents &= ~pWait->fResEvents; RTListNodeRemove(&pWait->ListNode); #ifdef VBOXGUEST_USE_DEFERRED_WAKE_UP @@ -2800,6 +3074,7 @@ bool VBoxGuestCommonISR(PVBOXGUESTDEVEXT pDevExt) ASMAtomicDecU32(&pDevExt->cISR); Assert(rc == 0); + NOREF(rc); return fOurIrq; } diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuestA-os2.asm b/src/VBox/Additions/common/VBoxGuest/VBoxGuestA-os2.asm index bb8757f1..008dd625 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuestA-os2.asm +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuestA-os2.asm @@ -4,7 +4,7 @@ ; ; -; Copyright (C) 2007 knut st. osmundsen <bird-src-spam@anduin.net> +; 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; @@ -20,7 +20,7 @@ ; ; VBoxDrv - OS/2 assembly file, the first file in the link. ; -; Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net> +; Copyright (c) 2007-2010 knut st. osmundsen <bird-src-spam@anduin.net> ; ; Permission is hereby granted, free of charge, to any person ; obtaining a copy of this software and associated documentation diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuestIDC-unix.c.h b/src/VBox/Additions/common/VBoxGuest/VBoxGuestIDC-unix.c.h index 87ad299b..de0a5125 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuestIDC-unix.c.h +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuestIDC-unix.c.h @@ -1,4 +1,4 @@ -/* $Rev: 78530 $ */ +/* $Rev: 84795 $ */ /** @file * VBoxGuest - Inter Driver Communication, unix implementation. * @@ -6,7 +6,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; @@ -28,9 +28,12 @@ /** @todo Use some header that we have in common with VBoxGuestLib.h... */ -DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version); -DECLVBGL(int) VBoxGuestIDCClose(void *pvSession); -DECLVBGL(int) VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned); +/** @todo fix DECLVBGL usage. */ +RT_C_DECLS_BEGIN +DECLEXPORT(void *) VBOXCALL VBoxGuestIDCOpen(uint32_t *pu32Version); +DECLEXPORT(int) VBOXCALL VBoxGuestIDCClose(void *pvSession); +DECLEXPORT(int) VBOXCALL VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned); +RT_C_DECLS_END /** @@ -39,7 +42,7 @@ DECLVBGL(int) VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, siz * @returns Opaque pointer to session object. * @param pu32Version Where to store VMMDev version. */ -DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version) +DECLEXPORT(void *) VBOXCALL VBoxGuestIDCOpen(uint32_t *pu32Version) { PVBOXGUESTSESSION pSession; int rc; @@ -96,7 +99,7 @@ DECLVBGL(void *) VBoxGuestIDCOpen(uint32_t *pu32Version) * @returns VBox error code. * @param pvState Opaque pointer to the session object. */ -DECLVBGL(int) VBoxGuestIDCClose(void *pvSession) +DECLEXPORT(int) VBOXCALL VBoxGuestIDCClose(void *pvSession) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession; LogFlow(("VBoxGuestIDCClose:\n")); @@ -131,7 +134,7 @@ DECLVBGL(int) VBoxGuestIDCClose(void *pvSession) * @param cbData Size of the data buffer. * @param pcbDataReturned Where to store the amount of returned data. */ -DECLVBGL(int) VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned) +DECLEXPORT(int) VBOXCALL VBoxGuestIDCCall(void *pvSession, unsigned iCmd, void *pvData, size_t cbData, size_t *pcbDataReturned) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)pvSession; LogFlow(("VBoxGuestIDCCall: %pvSession=%p Cmd=%u pvData=%p cbData=%d\n", pvSession, iCmd, pvData, cbData)); diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h b/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h index 5a15aeee..e91b7678 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuestInternal.h @@ -107,7 +107,6 @@ typedef struct VBOXGUESTMEMBALLOON /** Pointer to a memory balloon. */ typedef VBOXGUESTMEMBALLOON *PVBOXGUESTMEMBALLOON; - /** * VBox guest device (data) extension. */ @@ -180,17 +179,12 @@ typedef struct VBOXGUESTDEVEXT uint32_t volatile cISR; /** Callback and user data for a kernel mouse handler. */ VBoxGuestMouseSetNotifyCallback MouseNotifyCallback; - - /** Windows part. */ - union - { -#ifdef ___VBoxGuest_win_h - VBOXGUESTDEVEXTWIN s; -#else - uint32_t dummy; -#endif - } win; - + /* list of caps used in acquire mode */ + uint32_t u32AcquireModeGuestCaps; + /* list of caps used in set mode */ + uint32_t u32SetModeGuestCaps; + /* currently acquired (and reported) guest caps */ + uint32_t u32GuestCaps; } VBOXGUESTDEVEXT; /** Pointer to the VBoxGuest driver data. */ typedef VBOXGUESTDEVEXT *PVBOXGUESTDEVEXT; @@ -205,7 +199,7 @@ typedef VBOXGUESTDEVEXT *PVBOXGUESTDEVEXT; */ typedef struct VBOXGUESTSESSION { -#if defined(RT_OS_OS2) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS) +#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_OS2) || defined(RT_OS_SOLARIS) /** Pointer to the next session with the same hash. */ PVBOXGUESTSESSION pNextHash; #endif @@ -234,7 +228,14 @@ typedef struct VBOXGUESTSESSION /** Mouse features supported. A feature enabled in any guest session will * be enabled for the host. */ uint32_t volatile fMouseStatus; - +#ifdef RT_OS_DARWIN + /** Pointer to the associated org_virtualbox_VBoxGuestClient object. */ + void *pvVBoxGuestClient; + /** Whether this session has been opened or not. */ + bool fOpened; +#endif + /* Guest Caps Acquired & Reported by this session */ + uint32_t u32AquiredGuestCaps; } VBOXGUESTSESSION; RT_C_DECLS_BEGIN @@ -274,6 +275,11 @@ DECLVBGL(int) VBoxGuestNativeServiceCall(void *pvOpaque, unsigned int iCmd, v */ void VBoxGuestNativeISRMousePollEvent(PVBOXGUESTDEVEXT pDevExt); + +#ifdef VBOX_WITH_DPC_LATENCY_CHECKER +int VbgdNtIOCtl_DpcLatencyChecker(void); +#endif + RT_C_DECLS_END #endif diff --git a/src/VBox/Additions/common/VBoxGuest/darwin/Info.plist b/src/VBox/Additions/common/VBoxGuest/darwin/Info.plist new file mode 100644 index 00000000..30cd22b9 --- /dev/null +++ b/src/VBox/Additions/common/VBoxGuest/darwin/Info.plist @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> <string>English</string> + <key>CFBundleExecutable</key> <string>VBoxGuest</string> + <key>CFBundleIdentifier</key> <string>org.virtualbox.kext.VBoxGuest</string> + <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> + <key>CFBundleName</key> <string>VBoxGuest</string> + <key>CFBundlePackageType</key> <string>KEXT</string> + <key>CFBundleSignature</key> <string>????</string> + <key>NSHumanReadableCopyright</key> <string>Copyright © 2007-@VBOX_C_YEAR@ @VBOX_VENDOR@</string> + <key>CFBundleGetInfoString</key> <string>@VBOX_PRODUCT@ @VBOX_VERSION_STRING@, © 2007-@VBOX_C_YEAR@ @VBOX_VENDOR@</string> + <key>CFBundleVersion</key> <string>@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@.@VBOX_VERSION_BUILD@</string> + <key>CFBundleShortVersionString</key> <string>@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@.@VBOX_VERSION_BUILD@</string> + <key>OSBundleCompatibleVersion</key> <string>@VBOX_VERSION_MAJOR@.@VBOX_VERSION_MINOR@.@VBOX_VERSION_BUILD@</string> + <key>IOKitPersonalities</key> + <dict> + <key>VBoxGuest</key> + <dict> + <key>CFBundleIdentifier</key> <string>org.virtualbox.kext.VBoxGuest</string> + <key>IOClass</key> <string>org_virtualbox_VBoxGuest</string> + <key>IOMatchCategory</key> <string>org_virtualbox_VBoxGuest</string> + <key>IOUserClientClass</key> <string>org_virtualbox_VBoxGuestClient</string> + <key>IOKitDebug</key> <integer>65535</integer> + <key>IOProviderClass</key> <string>IOPCIDevice</string> + <key>IONameMatch</key> <string>pci80ee,cafe</string> + </dict> + </dict> + <key>OSBundleLibraries</key> + <dict> + <key>com.apple.iokit.IOPCIFamily</key> <string>2.5</string> <!-- TODO: Figure the version in mac os x 10.4. --> + <key>com.apple.kpi.bsd</key> <string>8.0.0</string> + <key>com.apple.kpi.mach</key> <string>8.0.0</string> + <key>com.apple.kpi.libkern</key> <string>8.0.0</string> + <key>com.apple.kpi.unsupported</key> <string>8.0.0</string> + <key>com.apple.kpi.iokit</key> <string>8.0.0</string> + </dict> + <key>OSBundleLibraries_x86_64</key> + <dict> + <key>com.apple.iokit.IOPCIFamily</key> <string>2.6</string> + <key>com.apple.kpi.bsd</key> <string>10.0.0d4</string> + <key>com.apple.kpi.mach</key> <string>10.0.0d3</string> + <key>com.apple.kpi.libkern</key> <string>10.0.0d3</string> + <key>com.apple.kpi.iokit</key> <string>10.0.0d3</string> + <key>com.apple.kpi.unsupported</key> <string>10.0.0d3</string> + </dict> +</dict> +</plist> + diff --git a/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile b/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile index c0326547..a25cc9f2 100644 --- a/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile +++ b/src/VBox/Additions/common/VBoxGuest/freebsd/Makefile @@ -4,7 +4,7 @@ # # -# Copyright (C) 2006-2009 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/Additions/common/VBoxGuest/linux/Makefile b/src/VBox/Additions/common/VBoxGuest/linux/Makefile index 5b03a9a1..09f8bbc1 100644 --- a/src/VBox/Additions/common/VBoxGuest/linux/Makefile +++ b/src/VBox/Additions/common/VBoxGuest/linux/Makefile @@ -1,10 +1,10 @@ -# $Revision: 79403 $ +# $Revision: 83575 $ ## @file # VirtualBox Guest Additions Module Makefile. # # -# 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/Additions/common/VBoxGuest/linux/files_vboxguest b/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest index f733baa0..f9f8a9d7 100755 --- a/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest +++ b/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest @@ -5,7 +5,7 @@ # # -# Copyright (C) 2007-2010 Oracle Corporation +# Copyright (C) 2007-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/Additions/common/VBoxGuest/win/VBoxGuest.inf b/src/VBox/Additions/common/VBoxGuest/win/VBoxGuest.inf index 09b56d39..04932fca 100644 --- a/src/VBox/Additions/common/VBoxGuest/win/VBoxGuest.inf +++ b/src/VBox/Additions/common/VBoxGuest/win/VBoxGuest.inf @@ -1,7 +1,10 @@ +; $Id: VBoxGuest.inf $ +;; @file +; INF file for installing the VirtualBox Windows guest driver. ; -; INF file for installing the VirtualBox Windows guest driver + ; -; 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; diff --git a/src/VBox/Additions/common/VBoxGuest/win/VBoxGuestInst.cpp b/src/VBox/Additions/common/VBoxGuest/win/VBoxGuestInst.cpp index eb9a7b69..3f76ef9d 100644 --- a/src/VBox/Additions/common/VBoxGuest/win/VBoxGuestInst.cpp +++ b/src/VBox/Additions/common/VBoxGuest/win/VBoxGuestInst.cpp @@ -1,8 +1,10 @@ +/* $Id: VBoxGuestInst.cpp $ */ /** @file - * - * Small tool to (un)install the VBoxGuest device driver - * - * Copyright (C) 2006-2007 Oracle Corporation + * Small tool to (un)install the VBoxGuest device driver. + */ + +/* + * 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; @@ -30,7 +32,7 @@ -int installDriver(void) +static int installDriver(void) { /* * Assume it didn't exist, so we'll create the service. @@ -57,17 +59,14 @@ int installDriver(void) "System", NULL, NULL, NULL, NULL); if (!hService) - { printf("CreateService failed! lasterr=%d\n", GetLastError()); - } else - { + else CloseServiceHandle(hService); - } CloseServiceHandle(hSMgrCreate); return hService ? 0 : -1; } -int uninstallDriver(void) +static int uninstallDriver(void) { int rc = -1; SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_CHANGE_CONFIG); @@ -96,8 +95,9 @@ int uninstallDriver(void) return rc; } +#ifdef TESTMODE -HANDLE openDriver(void) +static HANDLE openDriver(void) { HANDLE hDevice; @@ -115,43 +115,32 @@ HANDLE openDriver(void) return hDevice; } -int closeDriver(HANDLE hDevice) +static int closeDriver(HANDLE hDevice) { CloseHandle(hDevice); return 0; } -#ifdef TESTMODE -typedef struct TESTFOO -{ - int values[16]; -} TESTFOO, *PTESTFOO; - -int performTest(void) +static int performTest(void) { int rc = 0; HANDLE hDevice = openDriver(); if (hDevice != INVALID_HANDLE_VALUE) - { - DWORD cbReturned; - closeDriver(hDevice); - } else - { + else printf("openDriver failed!\n"); - } - return rc; } -#endif -void displayHelpAndExit(char *programName) +#endif /* TESTMODE */ + +static int usage(char *programName) { printf("error, syntax: %s [install|uninstall]\n", programName); - exit(1); + return 1; } int main(int argc, char **argv) @@ -162,50 +151,36 @@ int main(int argc, char **argv) #endif if (argc != 2) - { - displayHelpAndExit(argv[0]); - } + return usage(argv[0]); + if (strcmp(argv[1], "install") == 0) - { installMode = true; - } else - if (strcmp(argv[1], "uninstall") == 0) - { + else if (strcmp(argv[1], "uninstall") == 0) installMode = false; - } else #ifdef TESTMODE - if (strcmp(argv[1], "test") == 0) - { + else if (strcmp(argv[1], "test") == 0) testMode = true; - } else #endif - { - displayHelpAndExit(argv[0]); - } + else + return usage(argv[0]); - int rc; + int rc; #ifdef TESTMODE if (testMode) - { rc = performTest(); - } else + else #endif if (installMode) - { rc = installDriver(); - } else - { + else rc = uninstallDriver(); - } if (rc == 0) - { printf("operation completed successfully!\n"); - } else - { + else printf("error: operation failed with status code %d\n", rc); - } return rc; } + diff --git a/src/VBox/Additions/common/VBoxGuest/win/VBoxGuestMsg.mc b/src/VBox/Additions/common/VBoxGuest/win/VBoxGuestMsg.mc deleted file mode 100644 index 65a14b5f..00000000 --- a/src/VBox/Additions/common/VBoxGuest/win/VBoxGuestMsg.mc +++ /dev/null @@ -1,60 +0,0 @@ -; -; VBoxGuest Device Driver Messages -; -; Copyright (C) 2006-2007 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. -; - - -;// -;// Status values are 32 bit values arranged as follows: -;// -;// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 -;// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 -;// +---+-+-------------------------+-------------------------------+ -;// |Sev|C| Facility | Code | -;// +---+-+-------------------------+-------------------------------+ -;// -;// where -;// -;// Sev - is the severity code -;// -;// 00 - Success -;// 01 - Informational -;// 10 - Warning -;// 11 - Error -;// -;// C - is the Customer code flag -;// -;// Facility - is the facility code -;// -;// Code - is the facility's status code -;// -; -MessageIdTypedef=NTSTATUS - -SeverityNames=(Success=0x0:STATUS_SEVERITY_SUCCESS - Informational=0x1:STATUS_SEVERITY_INFORMATIONAL - Warning=0x2:STATUS_SEVERITY_WARNING - Error=0x3:STATUS_SEVERITY_ERROR - ) - -FacilityNames=(System=0x0 - RpcRuntime=0x2:FACILITY_RPC_RUNTIME - RpcStubs=0x3:FACILITY_RPC_STUBS - Io=0x4:FACILITY_IO_ERROR_CODE - VBoxGuestClass=0xee:FACILITY_VBOXGUESTCLASS_ERROR_CODE - ) - - -MessageId=0x0001 Facility=VBoxGuestClass Severity=Informational SymbolicName=VBOXGUESTCLASS_FOO -Language=English -VBoxGuest has something to say %1. -. |
