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; }
/** * Detach entry point, to detach a device to the system or suspend it. * * @param pDip The module structure instance. * @param enmCmd Attach type (ddi_attach_cmd_t) * * @return corresponding solaris error code. */ static int VBoxGuestSolarisDetach(dev_info_t *pDip, ddi_detach_cmd_t enmCmd) { LogFlow((DEVICE_NAME "::Detach\n")); switch (enmCmd) { case DDI_DETACH: { VBoxGuestSolarisRemoveIRQ(pDip); ddi_regs_map_free(&g_PciIOHandle); ddi_regs_map_free(&g_PciMMIOHandle); ddi_remove_minor_node(pDip, NULL); VBoxGuestDeleteDevExt(&g_DevExt); g_pDip = NULL; return DDI_SUCCESS; } case DDI_SUSPEND: { /** @todo implement suspend for guest driver. */ return DDI_SUCCESS; } default: return DDI_FAILURE; } }
/** * Unload the driver. * * @param pDrvObj Driver object. */ static void vboxguestwinUnload(PDRIVER_OBJECT pDrvObj) { Log(("VBoxGuest::vboxguestwinGuestUnload\n")); #ifdef TARGET_NT4 vboxguestwinCleanup(pDrvObj->DeviceObject); /* Destroy device extension and clean up everything else. */ if (pDrvObj->DeviceObject && pDrvObj->DeviceObject->DeviceExtension) VBoxGuestDeleteDevExt((PVBOXGUESTDEVEXT)pDrvObj->DeviceObject->DeviceExtension); /* * 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); IoDeleteDevice(pDrvObj->DeviceObject); #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 Log(("VBoxGuest::vboxguestwinGuestUnload: returning\n")); }
/** * Unload the module. */ static void __exit vboxguestLinuxModExit(void) { /* * Inverse order of init. */ vboxguestLinuxTermDeviceNodes(); #ifdef VBOXGUEST_WITH_INPUT_DRIVER vboxguestLinuxTermInputDevice(); #endif VBoxGuestCloseSession(&g_DevExt, g_pKernelSession); VBoxGuestDeleteDevExt(&g_DevExt); vboxguestLinuxTermISR(); vboxguestLinuxTermPci(); RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); RTLogDestroy(RTLogSetDefaultInstance(NULL)); RTR0Term(); }
/** * Initialize module. * * @returns appropriate status code. */ static int __init vboxguestLinuxModInit(void) { static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; PRTLOGGER pRelLogger; int rc; /* * Initialize IPRT first. */ rc = RTR0Init(0); if (RT_FAILURE(rc)) { printk(KERN_ERR DEVICE_NAME ": RTR0Init failed, rc=%d.\n", rc); return -EINVAL; } /* * 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 /* fFlags */, "all", "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_STDOUT | RTLOGDEST_DEBUGGER | RTLOGDEST_USER, NULL); if (RT_SUCCESS(rc)) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) RTLogGroupSettings(pRelLogger, g_szLogGrp); RTLogFlags(pRelLogger, g_szLogFlags); RTLogDestinations(pRelLogger, g_szLogDst); #endif RTLogRelSetDefaultInstance(pRelLogger); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) g_fLoggerCreated = true; #endif /* * Locate and initialize the PCI device. */ rc = vboxguestLinuxInitPci(); if (rc >= 0) { /* * Register the interrupt service routine for it. */ rc = vboxguestLinuxInitISR(); if (rc >= 0) { /* * Call the common device extension initializer. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_X86) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux26; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) && defined(RT_ARCH_AMD64) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux26_x64; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && defined(RT_ARCH_X86) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux24; #elif LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 0) && defined(RT_ARCH_AMD64) VBOXOSTYPE enmOSType = VBOXOSTYPE_Linux24_x64; #else # warning "huh? which arch + version is this?" VBOXOSTYPE enmOsType = VBOXOSTYPE_Linux; #endif rc = VBoxGuestInitDevExt(&g_DevExt, g_IOPortBase, g_pvMMIOBase, g_cbMMIO, enmOSType, VMMDEV_EVENT_MOUSE_POSITION_CHANGED); if (RT_SUCCESS(rc)) { /* * Create the kernel session for this driver. */ rc = VBoxGuestCreateKernelSession(&g_DevExt, &g_pKernelSession); if (RT_SUCCESS(rc)) { /* * Create the kernel input device. */ #ifdef VBOXGUEST_WITH_INPUT_DRIVER rc = vboxguestLinuxCreateInputDevice(); if (rc >= 0) { #endif /* * Finally, create the device nodes. */ rc = vboxguestLinuxInitDeviceNodes(); if (rc >= 0) { /* some useful information for the user but don't show this on the console */ LogRel((DEVICE_NAME ": major %d, IRQ %d, I/O port %RTiop, MMIO at %RHp (size 0x%x)\n", g_iModuleMajor, g_pPciDev->irq, g_IOPortBase, g_MMIOPhysAddr, g_cbMMIO)); printk(KERN_DEBUG DEVICE_NAME ": Successfully loaded version " VBOX_VERSION_STRING " (interface " RT_XSTR(VMMDEV_VERSION) ")\n"); return rc; } /* bail out */ #ifdef VBOXGUEST_WITH_INPUT_DRIVER vboxguestLinuxTermInputDevice(); } else { LogRel((DEVICE_NAME ": vboxguestCreateInputDevice failed with rc=%Rrc\n", rc)); rc = RTErrConvertFromErrno(rc); } #endif VBoxGuestCloseSession(&g_DevExt, g_pKernelSession); } VBoxGuestDeleteDevExt(&g_DevExt); } else { LogRel((DEVICE_NAME ": VBoxGuestInitDevExt failed with rc=%Rrc\n", rc)); rc = RTErrConvertFromErrno(rc); } vboxguestLinuxTermISR(); } vboxguestLinuxTermPci(); } RTLogDestroy(RTLogRelSetDefaultInstance(NULL)); RTLogDestroy(RTLogSetDefaultInstance(NULL)); RTR0Term(); return rc; }
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; }
/** * 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: IOService started\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
/** * Attach entry point, to attach a device to the system or resume it. * * @param pDip The module structure instance. * @param enmCmd Attach type (ddi_attach_cmd_t) * * @return corresponding solaris error code. */ static int VBoxGuestSolarisAttach(dev_info_t *pDip, ddi_attach_cmd_t enmCmd) { LogFlow((DEVICE_NAME "::Attach\n")); switch (enmCmd) { case DDI_ATTACH: { if (g_pDip) { LogRel((DEVICE_NAME "::Attach: Only one instance supported.\n")); return DDI_FAILURE; } int instance = ddi_get_instance(pDip); /* * Enable resources for PCI access. */ ddi_acc_handle_t PciHandle; int rc = pci_config_setup(pDip, &PciHandle); if (rc == DDI_SUCCESS) { /* * Map the register address space. */ caddr_t baseAddr; ddi_device_acc_attr_t deviceAttr; deviceAttr.devacc_attr_version = DDI_DEVICE_ATTR_V0; deviceAttr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC; deviceAttr.devacc_attr_dataorder = DDI_STRICTORDER_ACC; deviceAttr.devacc_attr_access = DDI_DEFAULT_ACC; rc = ddi_regs_map_setup(pDip, 1, &baseAddr, 0, 0, &deviceAttr, &g_PciIOHandle); if (rc == DDI_SUCCESS) { /* * Read size of the MMIO region. */ g_uIOPortBase = (uintptr_t)baseAddr; rc = ddi_dev_regsize(pDip, 2, &g_cbMMIO); if (rc == DDI_SUCCESS) { rc = ddi_regs_map_setup(pDip, 2, &g_pMMIOBase, 0, g_cbMMIO, &deviceAttr, &g_PciMMIOHandle); if (rc == DDI_SUCCESS) { /* * Add IRQ of VMMDev. */ rc = VBoxGuestSolarisAddIRQ(pDip); if (rc == DDI_SUCCESS) { /* * Call the common device extension initializer. */ rc = VBoxGuestInitDevExt(&g_DevExt, g_uIOPortBase, g_pMMIOBase, g_cbMMIO, #if ARCH_BITS == 64 VBOXOSTYPE_Solaris_x64, #else VBOXOSTYPE_Solaris, #endif VMMDEV_EVENT_MOUSE_POSITION_CHANGED); if (RT_SUCCESS(rc)) { rc = ddi_create_minor_node(pDip, DEVICE_NAME, S_IFCHR, instance, DDI_PSEUDO, 0); if (rc == DDI_SUCCESS) { g_pDip = pDip; pci_config_teardown(&PciHandle); return DDI_SUCCESS; } LogRel((DEVICE_NAME "::Attach: ddi_create_minor_node failed.\n")); VBoxGuestDeleteDevExt(&g_DevExt); } else LogRel((DEVICE_NAME "::Attach: VBoxGuestInitDevExt failed.\n")); VBoxGuestSolarisRemoveIRQ(pDip); } else LogRel((DEVICE_NAME "::Attach: VBoxGuestSolarisAddIRQ failed.\n")); ddi_regs_map_free(&g_PciMMIOHandle); } else LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for MMIO region failed.\n")); } else LogRel((DEVICE_NAME "::Attach: ddi_dev_regsize for MMIO region failed.\n")); ddi_regs_map_free(&g_PciIOHandle); } else LogRel((DEVICE_NAME "::Attach: ddi_regs_map_setup for IOport failed.\n")); pci_config_teardown(&PciHandle); } else LogRel((DEVICE_NAME "::Attach: pci_config_setup failed rc=%d.\n", rc)); return DDI_FAILURE; } case DDI_RESUME: { /** @todo implement resume for guest driver. */ return DDI_SUCCESS; } default: return DDI_FAILURE; } }
/** * PnP Request handler. * * @param pDevObj Device object. * @param pIrp Request packet. */ NTSTATUS vboxguestwinPnP(PDEVICE_OBJECT pDevObj, PIRP pIrp) { PVBOXGUESTDEVEXT pDevExt = (PVBOXGUESTDEVEXT)pDevObj->DeviceExtension; PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(pIrp); #ifdef LOG_ENABLED static char* aszFnctName[] = { "IRP_MN_START_DEVICE", "IRP_MN_QUERY_REMOVE_DEVICE", "IRP_MN_REMOVE_DEVICE", "IRP_MN_CANCEL_REMOVE_DEVICE", "IRP_MN_STOP_DEVICE", "IRP_MN_QUERY_STOP_DEVICE", "IRP_MN_CANCEL_STOP_DEVICE", "IRP_MN_QUERY_DEVICE_RELATIONS", "IRP_MN_QUERY_INTERFACE", "IRP_MN_QUERY_CAPABILITIES", "IRP_MN_QUERY_RESOURCES", "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", "IRP_MN_QUERY_DEVICE_TEXT", "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", "", "IRP_MN_READ_CONFIG", "IRP_MN_WRITE_CONFIG", "IRP_MN_EJECT", "IRP_MN_SET_LOCK", "IRP_MN_QUERY_ID", "IRP_MN_QUERY_PNP_DEVICE_STATE", "IRP_MN_QUERY_BUS_INFORMATION", "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")); #endif NTSTATUS rc = STATUS_SUCCESS; switch (pStack->MinorFunction) { case IRP_MN_START_DEVICE: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: START_DEVICE\n")); /* This must be handled first by the lower driver. */ rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE); if ( NT_SUCCESS(rc) && NT_SUCCESS(pIrp->IoStatus.Status)) { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: 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)); rc = STATUS_UNSUCCESSFUL; } else { rc = vboxguestwinInit(pDevObj, pIrp); } } if (NT_ERROR(rc)) { Log(("VBoxGuest::vboxguestwinGuestPnp: START_DEVICE: Error: rc = 0x%x\n", rc)); /* Need to unmap memory in case of errors ... */ vboxguestwinUnmapVMMDevMemory(pDevExt); } break; } case IRP_MN_CANCEL_REMOVE_DEVICE: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_REMOVE_DEVICE\n")); /* This must be handled first by the lower driver. */ rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE); if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGREMOVE) { /* Return to the state prior to receiving the IRP_MN_QUERY_REMOVE_DEVICE request. */ pDevExt->win.s.devState = pDevExt->win.s.prevDevState; } /* Complete the IRP. */ break; } case IRP_MN_SURPRISE_REMOVAL: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: IRP_MN_SURPRISE_REMOVAL\n")); VBOXGUEST_UPDATE_DEVSTATE(pDevExt, SURPRISEREMOVED); /* Do nothing here actually. Cleanup is done in IRP_MN_REMOVE_DEVICE. * This request is not expected for VBoxGuest. */ LogRel(("VBoxGuest: unexpected device removal\n")); /* Pass to the lower driver. */ pIrp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(pIrp); rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); /* Do not complete the IRP. */ return rc; } case IRP_MN_QUERY_REMOVE_DEVICE: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_REMOVE_DEVICE\n")); #ifdef VBOX_REBOOT_ON_UNINSTALL Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_REMOVE_DEVICE: Device cannot be removed without a reboot.\n")); rc = STATUS_UNSUCCESSFUL; #endif /* VBOX_REBOOT_ON_UNINSTALL */ if (NT_SUCCESS(rc)) { VBOXGUEST_UPDATE_DEVSTATE(pDevExt, PENDINGREMOVE); /* This IRP passed down to lower driver. */ pIrp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(pIrp); rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); Log(("VBoxGuest::vboxguestwinGuestPnp: 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. * I.e. just return the status we got from IoCallDriver */ return rc; } /* Complete the IRP on failure. */ break; } case IRP_MN_REMOVE_DEVICE: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: 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)); /* * We need to send the remove down the stack before we detach, * but we don't need to wait for the completion of this operation * (and to register a completion routine). */ pIrp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(pIrp); rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Next lower driver replied rc = 0x%x\n", rc)); IoDetachDevice(pDevExt->win.s.pNextLowerDriver); Log(("VBoxGuest::vboxguestwinGuestPnp: REMOVE_DEVICE: Removing device ...\n")); /* Destroy device extension and clean up everything else. */ VBoxGuestDeleteDevExt(pDevExt); /* Remove DOS device + symbolic link. */ UNICODE_STRING win32Name; RtlInitUnicodeString(&win32Name, VBOXGUEST_DEVICE_NAME_DOS); IoDeleteSymbolicLink(&win32Name); Log(("VBoxGuest::vboxguestwinGuestPnp: 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")); /* Propagating rc from IoCallDriver. */ return rc; /* Make sure that we don't do anything below here anymore! */ } case IRP_MN_CANCEL_STOP_DEVICE: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: CANCEL_STOP_DEVICE\n")); /* This must be handled first by the lower driver. */ rc = vboxguestwinSendIrpSynchronously(pDevExt->win.s.pNextLowerDriver, pIrp, TRUE); if (NT_SUCCESS(rc) && pDevExt->win.s.devState == PENDINGSTOP) { /* Return to the state prior to receiving the IRP_MN_QUERY_STOP_DEVICE request. */ pDevExt->win.s.devState = pDevExt->win.s.prevDevState; } /* Complete the IRP. */ break; } case IRP_MN_QUERY_STOP_DEVICE: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: QUERY_STOP_DEVICE\n")); #ifdef VBOX_REBOOT_ON_UNINSTALL Log(("VBoxGuest::vboxguestwinGuestPnp: QUERY_STOP_DEVICE: Device cannot be stopped without a reboot!\n")); pIrp->IoStatus.Status = STATUS_UNSUCCESSFUL; #endif /* VBOX_REBOOT_ON_UNINSTALL */ if (NT_SUCCESS(rc)) { VBOXGUEST_UPDATE_DEVSTATE(pDevExt, PENDINGSTOP); /* This IRP passed down to lower driver. */ pIrp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(pIrp); rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); Log(("VBoxGuest::vboxguestwinGuestPnp: 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. * I.e. just return the status we got from IoCallDriver */ return rc; } /* Complete the IRP on failure. */ break; } case IRP_MN_STOP_DEVICE: { Log(("VBoxGuest::vboxguestwinVBoxGuestPnP: 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)); /* 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)); return rc; } default: { IoSkipCurrentIrpStackLocation(pIrp); rc = IoCallDriver(pDevExt->win.s.pNextLowerDriver, pIrp); return rc; } } pIrp->IoStatus.Status = rc; IoCompleteRequest(pIrp, IO_NO_INCREMENT); Log(("VBoxGuest::vboxguestwinGuestPnp: Returning with rc = 0x%x\n", rc)); return rc; }