Beispiel #1
0
void UIMediumEnumerator::sltHandleSnapshotDeleted(QString strMachineID, QString strSnapshotID)
{
    LogRel2(("GUI: UIMediumEnumerator: Snapshot-deleted event received, Machine ID = {%s}, Snapshot ID = {%s}\n",
             strMachineID.toUtf8().constData(), strSnapshotID.toUtf8().constData()));

    /* Gather previously used UIMedium IDs: */
    QStringList previousUIMediumIDs;
    calculateCachedUsage(strMachineID, previousUIMediumIDs, false /* take into account current state only */);
    LogRel2(("GUI: UIMediumEnumerator:  Old usage: %s\n",
             previousUIMediumIDs.isEmpty() ? "<empty>" : previousUIMediumIDs.join(", ").toUtf8().constData()));

    /* Gather currently used CMediums and their IDs: */
    CMediumMap currentCMediums;
    QStringList currentCMediumIDs;
    calculateActualUsage(strMachineID, currentCMediums, currentCMediumIDs, true /* take into account current state only */);
    LogRel2(("GUI: UIMediumEnumerator:  New usage: %s\n",
             currentCMediumIDs.isEmpty() ? "<empty>" : currentCMediumIDs.join(", ").toUtf8().constData()));

    /* Update everything: */
    recacheFromCachedUsage(previousUIMediumIDs);
    recacheFromActualUsage(currentCMediums, currentCMediumIDs);

    LogRel2(("GUI: UIMediumEnumerator: Snapshot-deleted event processed, Machine ID = {%s}, Snapshot ID = {%s}\n",
             strMachineID.toUtf8().constData(), strSnapshotID.toUtf8().constData()));
}
Beispiel #2
0
/**
 * Set current state of a keyboard modifier.
 *
 * @param   idModifier        Modifier to set (VK_CAPITAL, VK_SCROLL or VK_NUMLOCK)
 * @param   fState            State to set
 */
static void winSetModifierState(int idModifier, bool fState)
{
    AssertReturnVoid((idModifier == VK_CAPITAL) || (idModifier == VK_SCROLL) || (idModifier == VK_NUMLOCK));

    /* If the modifier is already in desired state, just do nothing. Otherwise, toggle it. */
    if (winGetModifierState(idModifier) != fState)
    {
        /* Simulate KeyUp+KeyDown keystroke */
        keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY, 0);
        keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);

        /* Process posted above keyboard events immediately: */
        MSG msg;
        while (::PeekMessage(&msg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE))
            ::DispatchMessage(&msg);

        LogRel2(("HID LEDs sync: setting %s state to %s (0x%X).\n",
                 VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC)));
    }
    else
    {
        LogRel2(("HID LEDs sync: setting %s state: skipped: state is already %s (0x%X).\n",
                 VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC)));
    }
}
Beispiel #3
0
void UIMediumEnumerator::sltHandleMachineRegistration(QString strMachineID, bool fRegistered)
{
    LogRel2(("GUI: UIMediumEnumerator: Machine %s event received, ID = %s\n",
             fRegistered ? "registration" : "unregistration",
             strMachineID.toUtf8().constData()));

    /* Machine was registered: */
    if (fRegistered)
    {
        /* Gather currently used CMediums and their IDs: */
        CMediumMap currentCMediums;
        QStringList currentCMediumIDs;
        calculateActualUsage(strMachineID, currentCMediums, currentCMediumIDs, false /* take into account current state only */);
        LogRel2(("GUI: UIMediumEnumerator:  New usage: %s\n",
                 currentCMediumIDs.isEmpty() ? "<empty>" : currentCMediumIDs.join(", ").toUtf8().constData()));
        /* Update cache with currently used CMediums: */
        recacheFromActualUsage(currentCMediums, currentCMediumIDs);
    }
    /* Machine was unregistered: */
    else
    {
        /* Gather previously used UIMedium IDs: */
        QStringList previousUIMediumIDs;
        calculateCachedUsage(strMachineID, previousUIMediumIDs, false /* take into account current state only */);
        LogRel2(("GUI: UIMediumEnumerator:  Old usage: %s\n",
                 previousUIMediumIDs.isEmpty() ? "<empty>" : previousUIMediumIDs.join(", ").toUtf8().constData()));
        /* Update cache for previously used UIMediums: */
        recacheFromCachedUsage(previousUIMediumIDs);
    }

    LogRel2(("GUI: UIMediumEnumerator: Machine %s event processed, ID = %s\n",
             fRegistered ? "registration" : "unregistration",
             strMachineID.toUtf8().constData()));
}
/**
 * @note This function will free m!
 */
int udp_output(PNATState pData, struct socket *so, struct mbuf *m,
               struct sockaddr_in *addr)
{
    struct sockaddr_in saddr, daddr;

    Assert(so->so_type == IPPROTO_UDP);
    LogFlowFunc(("ENTER: so = %R[natsock], m = %p, saddr = %RTnaipv4\n", so, m, addr->sin_addr.s_addr));

    if (so->so_laddr.s_addr == INADDR_ANY)
    {
        if (pData->guest_addr_guess.s_addr != INADDR_ANY)
        {
            LogRel2(("NAT: port-forward: using %RTnaipv4 for %R[natsock]\n",
                     pData->guest_addr_guess.s_addr, so));
            so->so_laddr = pData->guest_addr_guess;
        }
        else
        {
            LogRel2(("NAT: port-forward: guest address unknown for %R[natsock]\n", so));
            m_freem(pData, m);
            return 0;
        }
    }

    saddr = *addr;
    if ((so->so_faddr.s_addr & RT_H2N_U32(pData->netmask)) == pData->special_addr.s_addr)
    {
        saddr.sin_addr.s_addr = so->so_faddr.s_addr;
        if (slirpIsWideCasting(pData, so->so_faddr.s_addr))
        {
            /**
             * We haven't got real firewall but have got its submodule libalias.
             */
            m->m_flags |= M_SKIP_FIREWALL;
            /**
             * udp/137 port is Name Service in NetBIOS protocol. for some reasons Windows guest rejects
             * accept data from non-aliased server.
             */
            if (   (so->so_fport == so->so_lport)
                && (so->so_fport == RT_H2N_U16(137)))
                saddr.sin_addr.s_addr = alias_addr.s_addr;
            else
                saddr.sin_addr.s_addr = addr->sin_addr.s_addr;
            so->so_faddr.s_addr = addr->sin_addr.s_addr;
        }
    }

    /* Any UDP packet to the loopback address must be translated to be from
     * the forwarding address, i.e. 10.0.2.2. */
    if (   (saddr.sin_addr.s_addr & RT_H2N_U32_C(IN_CLASSA_NET))
        == RT_H2N_U32_C(INADDR_LOOPBACK & IN_CLASSA_NET))
        saddr.sin_addr.s_addr = alias_addr.s_addr;

    daddr.sin_addr = so->so_laddr;
    daddr.sin_port = so->so_lport;

    return udp_output2(pData, so, m, &saddr, &daddr, so->so_iptos);
}
Beispiel #5
0
void UIMachineViewNormal::adjustGuestScreenSize()
{
    /* Should we adjust guest-screen size? Logging paranoia is required here to reveal the truth. */
    LogRel(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Adjust guest-screen size if necessary.\n"));
    bool fAdjust = false;

    /* Step 1: Is the guest-screen of another size than necessary? */
    if (!fAdjust)
    {
        /* Acquire frame-buffer size: */
        QSize frameBufferSize(frameBuffer()->width(), frameBuffer()->height());
        /* Take the scale-factor(s) into account: */
        frameBufferSize = scaledForward(frameBufferSize);

        /* Acquire central-widget size: */
        const QSize centralWidgetSize = machineWindow()->centralWidget()->size();

        if (frameBufferSize != centralWidgetSize)
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-screen is of another size than necessary, adjustment is required.\n"));
            fAdjust = true;
        }
    }

    /* Step 2: Is guest-additions supports graphics? */
    if (fAdjust)
    {
        if (!uisession()->isGuestSupportsGraphics())
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-additions are not supporting graphics, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }
    /* Step 3: Is guest-screen visible? */
    if (fAdjust)
    {
        if (!uisession()->isScreenVisible(screenId()))
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-screen is not visible, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }
    /* Step 4: Is guest-screen auto-resize enabled? */
    if (fAdjust)
    {
        if (!m_bIsGuestAutoresizeEnabled)
        {
            LogRel2(("GUI: UIMachineViewNormal::adjustGuestScreenSize: Guest-screen auto-resize is disabled, adjustment is omitted.\n"));
            fAdjust = false;
        }
    }

    /* Final step: Adjust if requested/allowed. */
    if (fAdjust)
    {
        sltPerformGuestResize(machineWindow()->centralWidget()->size());
    }
}
Beispiel #6
0
/*
 * We differentiate between a function handler for the guest and one for the host.
 */
static DECLCALLBACK(int) svcHostCall (void *,
                                      uint32_t u32Function,
                                      uint32_t cParms,
                                      VBOXHGCMSVCPARM paParms[])
{
    int rc = VINF_SUCCESS;

    LogRel2(("svcHostCall: fn = %d, cParms = %d, pparms = %d\n",
         u32Function, cParms, paParms));

    switch (u32Function)
    {
        case VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE:
        {
            LogRel2(("svcCall: VBOX_SHARED_CLIPBOARD_HOST_FN_SET_MODE\n"));

            if (cParms != 1)
            {
                rc = VERR_INVALID_PARAMETER;
            }
            else if (   paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT   /* mode */
                    )
            {
                rc = VERR_INVALID_PARAMETER;
            }
            else
            {
                uint32_t u32Mode = VBOX_SHARED_CLIPBOARD_MODE_OFF;

                rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Mode);

                /* The setter takes care of invalid values. */
                vboxSvcClipboardModeSet (u32Mode);
            }
        } break;

        case VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS:
        {
            uint32_t u32Headless = g_fHeadless;

            rc = VERR_INVALID_PARAMETER;
            if (cParms != 1)
                break;
            rc = VBoxHGCMParmUInt32Get (&paParms[0], &u32Headless);
            if (RT_SUCCESS(rc))
                LogRelFlow(("svcCall: VBOX_SHARED_CLIPBOARD_HOST_FN_SET_HEADLESS, u32Headless=%u\n",
                            (unsigned) u32Headless));
            g_fHeadless = RT_BOOL(u32Headless);
        } break;

        default:
            break;
    }

    LogRelFlow(("svcHostCall: rc = %Rrc\n", rc));
    return rc;
}
Beispiel #7
0
/**
 * Broadcast HID modifier states.
 *
 * @param   fNumLockOn        NUM LOCK state
 * @param   fCapsLockOn       CAPS LOCK state
 * @param   fScrollLockOn     SCROLL LOCK state
 */
void WinHidDevicesBroadcastLeds(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn)
{
    LogRel2(("HID LEDs sync: start broadcast guest modifier states: NUM(%s) CAPS(%s) SCROLL(%s)\n",
             VBOX_BOOL_TO_STR_STATE(fNumLockOn),
             VBOX_BOOL_TO_STR_STATE(fCapsLockOn),
             VBOX_BOOL_TO_STR_STATE(fScrollLockOn)));

    if (winSetHidLeds(fNumLockOn, fCapsLockOn, fScrollLockOn))
        LogRel2(("HID LEDs sync: broadcast completed\n"));
    else
        LogRel2(("HID LEDs sync: broadcast failed\n"));
}
void UIVMLogViewerDialog::loadSettings()
{
    /* Acquire widget: */
    const UIVMLogViewerWidget *pWidget = qobject_cast<const UIVMLogViewerWidget*>(widget());

    /* Restore window geometry: */
    const QRect desktopRect = gpDesktop->availableGeometry(this);
    int iDefaultWidth = desktopRect.width() / 2;
    int iDefaultHeight = desktopRect.height() * 3 / 4;

    /* Try obtain the default width of the current logviewer: */
    if (pWidget)
    {
        int iWidth =  pWidget->defaultLogPageWidth();
        if (iWidth != 0)
            iDefaultWidth = iWidth;
    }

    QRect defaultGeometry(0, 0, iDefaultWidth, iDefaultHeight);
    if (centerWidget())
        defaultGeometry.moveCenter(centerWidget()->geometry().center());

    /* Load geometry from extradata: */
    QRect geometry = gEDataManager->logWindowGeometry(this, defaultGeometry);

    /* Restore geometry: */
    LogRel2(("GUI: UIVMLogViewer: Restoring geometry to: Origin=%dx%d, Size=%dx%d\n",
             geometry.x(), geometry.y(), geometry.width(), geometry.height()));
    setDialogGeometry(geometry);
}
Beispiel #9
0
static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
{
#ifndef UNIT_TEST
    /* If there are any pending requests, they must be completed here. Since
     * the service is single threaded, there could be only requests
     * which the service itself has postponed.
     *
     * HGCM knows that the state is being saved and that the pfnComplete
     * calls are just clean ups. These requests are saved by the VMMDev.
     *
     * When the state will be restored, these requests will be reissued
     * by VMMDev. The service therefore must save state as if there were no
     * pending request.
     */
    LogRel2 (("svcSaveState: u32ClientID = %d\n", u32ClientID));

    VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;

    /* This field used to be the length. We're using it as a version field
       with the high bit set. */
    SSMR3PutU32 (pSSM, UINT32_C (0x80000002));
    int rc = SSMR3PutStructEx (pSSM, pClient, sizeof(*pClient), 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL);
    AssertRCReturn (rc, rc);

    if (pClient->fAsync)
    {
        g_pHelpers->pfnCallComplete (pClient->async.callHandle, VINF_SUCCESS /* error code is not important here. */);
        pClient->fAsync = false;
    }

    vboxSvcClipboardCompleteReadData (pClient, VINF_SUCCESS, 0);

#endif /* !UNIT_TEST */
    return VINF_SUCCESS;
}
Beispiel #10
0
static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
{
    VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;

    int rc = VINF_SUCCESS;

    /* If there is already a client connected then we want to release it first. */
    if (g_pClient != NULL)
    {
        uint32_t u32OldClientID = g_pClient->u32ClientID;

        svcDisconnect(NULL, u32OldClientID, g_pClient);
        /* And free the resources in the hgcm subsystem. */
        g_pHelpers->pfnDisconnectClient(g_pHelpers->pvInstance, u32OldClientID);
    }

    /* Register the client. */
    memset (pClient, 0, sizeof (*pClient));

    pClient->u32ClientID = u32ClientID;

    rc = vboxClipboardConnect (pClient, vboxSvcClipboardGetHeadless());

    if (RT_SUCCESS (rc))
    {
        g_pClient = pClient;
    }

    LogRel2(("vboxClipboardConnect: rc = %Rrc\n", rc));

    return rc;
}
GuestDnD::GuestDnD(const ComObjPtr<Guest> &pGuest)
    : m_pGuest(pGuest)
{
    LogFlowFuncEnter();

    m_pResponse = new GuestDnDResponse(pGuest);

    /* List of supported default MIME types. */
    LogRel2(("DnD: Supported default host formats:\n"));
    const com::Utf8Str arrEntries[] = { VBOX_DND_FORMATS_DEFAULT };
    for (size_t i = 0; i < RT_ELEMENTS(arrEntries); i++)
    {
        m_strDefaultFormats.push_back(arrEntries[i]);
        LogRel2(("DnD: \t%s\n", arrEntries[i].c_str()));
    }
}
Beispiel #12
0
/** @todo GuestDnDResponse *pResp needs to go. */
int GuestDnDBase::waitForEvent(GuestDnDCallbackEvent *pEvent, GuestDnDResponse *pResp, RTMSINTERVAL msTimeout)
{
    AssertPtrReturn(pEvent, VERR_INVALID_POINTER);
    AssertPtrReturn(pResp, VERR_INVALID_POINTER);

    int rc;

    LogFlowFunc(("msTimeout=%RU32\n", msTimeout));

    uint64_t tsStart = RTTimeMilliTS();
    do
    {
        /*
         * Wait until our desired callback triggered the
         * wait event. As we don't want to block if the guest does not
         * respond, do busy waiting here.
         */
        rc = pEvent->Wait(500 /* ms */);
        if (RT_SUCCESS(rc))
        {
            rc = pEvent->Result();
            LogFlowFunc(("Callback done, result is %Rrc\n", rc));
            break;
        }
        else if (rc == VERR_TIMEOUT) /* Continue waiting. */
            rc = VINF_SUCCESS;

        if (   msTimeout != RT_INDEFINITE_WAIT
            && RTTimeMilliTS() - tsStart > msTimeout)
        {
            rc = VERR_TIMEOUT;
            LogRel2(("DnD: Error: Guest did not respond within time\n"));
        }
        else if (pResp->isProgressCanceled()) /** @todo GuestDnDResponse *pResp needs to go. */
        {
            LogRel2(("DnD: Operation was canceled by user\n"));
            rc = VERR_CANCELLED;
        }

    } while (RT_SUCCESS(rc));

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Beispiel #13
0
/**
 * Restore host modifier states and free memory.
 */
void WinHidDevicesApplyAndReleaseLedsState(void *pData)
{
    VBoxModifiersState_t *pState = (VBoxModifiersState_t *)pData;

    if (pState)
    {
        LogRel2(("HID LEDs sync: attempt to restore host state: NUM(%s) CAPS(%s) SCROLL(%s)\n",
                 VBOX_BOOL_TO_STR_STATE(pState->fNumLockOn),
                 VBOX_BOOL_TO_STR_STATE(pState->fCapsLockOn),
                 VBOX_BOOL_TO_STR_STATE(pState->fScrollLockOn)));

        if (winSetHidLeds(pState->fNumLockOn, pState->fCapsLockOn, pState->fScrollLockOn))
            LogRel2(("HID LEDs sync: host state restored\n"));
        else
            LogRel2(("HID LEDs sync: host state restore failed\n"));

        free(pState);
    }
}
Beispiel #14
0
/**
 * Set current state of a keyboard modifier.
 *
 * @param   idModifier        Modifier to set (VK_CAPITAL, VK_SCROLL or VK_NUMLOCK)
 * @param   fState            State to set
 */
static void winSetModifierState(int idModifier, bool fState)
{
    AssertReturnVoid((idModifier == VK_CAPITAL) || (idModifier == VK_SCROLL) || (idModifier == VK_NUMLOCK));

    /* If the modifier is already in desired state, just do nothing. Otherwise, toggle it. */
    if (winGetModifierState(idModifier) != fState)
    {
        /* Simulate KeyUp+KeyDown keystroke */
        keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY, 0);
        keybd_event(idModifier, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);

        LogRel2(("HID LEDs sync: setting %s state to %s (0x%X).\n",
                 VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC)));
    }
    else
    {
        LogRel2(("HID LEDs sync: setting %s state: skipped: state is already %s (0x%X).\n",
                 VBOX_CONTROL_TO_STR_NAME(idModifier), VBOX_BOOL_TO_STR_STATE(fState), MapVirtualKey(idModifier, MAPVK_VK_TO_VSC)));
    }
}
void UIVMInformationDialog::loadSettings()
{
    /* Restore window geometry: */
    {
        /* Load geometry: */
        m_geometry = gEDataManager->informationWindowGeometry(this, m_pMachineWindow, vboxGlobal().managedVMUuid());

        /* Restore geometry: */
        LogRel2(("GUI: UIVMInformationDialog: Restoring geometry to: Origin=%dx%d, Size=%dx%d\n",
                 m_geometry.x(), m_geometry.y(), m_geometry.width(), m_geometry.height()));
        restoreGeometry();
    }
}
void UIVMLogViewerDialog::saveSettings() const
{
    /* Save window geometry to extradata: */
    const QRect saveGeometry = geometry();
#ifdef VBOX_WS_MAC
    /* darwinIsWindowMaximized expects a non-const QWidget*. thus const_cast: */
    QWidget *pw = const_cast<QWidget*>(qobject_cast<const QWidget*>(this));
    gEDataManager->setLogWindowGeometry(saveGeometry, ::darwinIsWindowMaximized(pw));
#else /* !VBOX_WS_MAC */
    gEDataManager->setLogWindowGeometry(saveGeometry, isMaximized());
#endif /* !VBOX_WS_MAC */
    LogRel2(("GUI: UIVMLogViewer: Geometry saved as: Origin=%dx%d, Size=%dx%d\n",
             saveGeometry.x(), saveGeometry.y(), saveGeometry.width(), saveGeometry.height()));
}
Beispiel #17
0
/* static */
void UIMachineWindow::handleStandardWindowButtonCallback(StandardWindowButtonType enmButtonType, bool fWithOptionKey, QWidget *pWidget)
{
    /* Handle arrived callback: */
    LogRel(("GUI: UIMachineWindow::handleStandardWindowButtonCallback: Callback for standard window button '%d' with option key '%d' received\n",
            (int)enmButtonType, (int)fWithOptionKey));
    AssertPtrReturnVoid(pWidget);
    if (UIMachineWindow *pMachineWindow = qobject_cast<UIMachineWindow*>(pWidget))
    {
        /* Redirect arrived callback: */
        LogRel2(("UIMachineWindow::handleStandardWindowButtonCallback: Redirecting callback for standard window button '%d' with option key '%d' to corresponding machine-window...\n",
                 (int)enmButtonType, (int)fWithOptionKey));
        pMachineWindow->handleStandardWindowButtonCallback(enmButtonType, fWithOptionKey);
    }
}
Beispiel #18
0
/* static */
void UIMachineWindow::handleNativeNotification(const QString &strNativeNotificationName, QWidget *pWidget)
{
    /* Handle arrived notification: */
    LogRel(("GUI: UIMachineWindow::handleNativeNotification: Notification '%s' received\n",
            strNativeNotificationName.toLatin1().constData()));
    AssertPtrReturnVoid(pWidget);
    if (UIMachineWindow *pMachineWindow = qobject_cast<UIMachineWindow*>(pWidget))
    {
        /* Redirect arrived notification: */
        LogRel2(("UIMachineWindow::handleNativeNotification: Redirecting '%s' notification to corresponding machine-window...\n",
                 strNativeNotificationName.toLatin1().constData()));
        pMachineWindow->handleNativeNotification(strNativeNotificationName);
    }
}
Beispiel #19
0
/**
 * Allocate memory and store modifier states there.
 *
 * @returns allocated memory witch contains modifier states or NULL.
 */
void * WinHidDevicesKeepLedsState(void)
{
    VBoxModifiersState_t *pState;

    pState = (VBoxModifiersState_t *)malloc(sizeof(VBoxModifiersState_t));
    if (pState)
    {
        pState->fNumLockOn    = winGetModifierState(VK_NUMLOCK);
        pState->fCapsLockOn   = winGetModifierState(VK_CAPITAL);
        pState->fScrollLockOn = winGetModifierState(VK_SCROLL);

        LogRel2(("HID LEDs sync: host state captured: NUM(%s) CAPS(%s) SCROLL(%s)\n",
                 VBOX_BOOL_TO_STR_STATE(pState->fNumLockOn),
                 VBOX_BOOL_TO_STR_STATE(pState->fCapsLockOn),
                 VBOX_BOOL_TO_STR_STATE(pState->fScrollLockOn)));

        return (void *)pState;
    }

    LogRel2(("HID LEDs sync: unable to allocate memory for HID LEDs synchronization data. LEDs sync will be disabled.\n"));

    return NULL;
}
void UIVMInformationDialog::saveSettings()
{
    /* Save window geometry: */
    {
        /* Save geometry: */
#ifdef VBOX_WS_MAC
        gEDataManager->setInformationWindowGeometry(m_geometry, ::darwinIsWindowMaximized(this), vboxGlobal().managedVMUuid());
#else /* VBOX_WS_MAC */
        gEDataManager->setInformationWindowGeometry(m_geometry, isMaximized(), vboxGlobal().managedVMUuid());
#endif /* !VBOX_WS_MAC */
        LogRel2(("GUI: UIVMInformationDialog: Geometry saved as: Origin=%dx%d, Size=%dx%d\n",
                 m_geometry.x(), m_geometry.y(), m_geometry.width(), m_geometry.height()));
    }
}
void UIMachineWindowFullscreen::changeEvent(QEvent *pEvent)
{
    switch (pEvent->type())
    {
        case QEvent::WindowStateChange:
        {
            /* Watch for window state changes: */
            QWindowStateChangeEvent *pChangeEvent = static_cast<QWindowStateChangeEvent*>(pEvent);
            LogRel2(("GUI: UIMachineWindowFullscreen::changeEvent: Window state changed from %d to %d\n",
                     (int)pChangeEvent->oldState(), (int)windowState()));
            if (   windowState() == Qt::WindowMinimized
                && pChangeEvent->oldState() == Qt::WindowNoState
                && !m_fIsMinimized)
            {
                /* Mark window minimized, isMinimized() is not enough due to Qt5vsX11 fight: */
                LogRel2(("GUI: UIMachineWindowFullscreen::changeEvent: Window minimized\n"));
                m_fIsMinimized = true;
            }
            else
            if (   windowState() == Qt::WindowNoState
                && pChangeEvent->oldState() == Qt::WindowMinimized
                && m_fIsMinimized)
            {
                /* Mark window restored, and do manual restoring with showInNecessaryMode(): */
                LogRel2(("GUI: UIMachineWindowFullscreen::changeEvent: Window restored\n"));
                m_fIsMinimized = false;
                showInNecessaryMode();
            }
            break;
        }
        default:
            break;
    }

    /* Call to base-class: */
    UIMachineWindow::changeEvent(pEvent);
}
Beispiel #22
0
/**
 * Tries to guess the DnD protocol version to use on the guest, based on the
 * installed Guest Additions version + revision.
 *
 * If unable to retrieve the protocol version, VERR_NOT_FOUND is returned along
 * with protocol version 1.
 *
 * @return  IPRT status code.
 * @param   puProto                 Where to store the protocol version.
 */
int GuestDnDBase::getProtocolVersion(uint32_t *puProto)
{
    AssertPtrReturn(puProto, VERR_INVALID_POINTER);

    int rc;

    uint32_t uProto        = 0;
    uint32_t uVerAdditions = 0;
    uint32_t uRevAdditions = 0;
    if (   m_pGuest
        && (uVerAdditions = m_pGuest->i_getAdditionsVersion())  > 0
        && (uRevAdditions = m_pGuest->i_getAdditionsRevision()) > 0)
    {
#ifdef DEBUG
# if 0
        /* Hardcode the to-used protocol version; nice for testing side effects. */
        uProto = 3;
        rc = VINF_SUCCESS;
# endif
#endif
        if (!uProto) /* Protocol not set yet? */
        {
            if (uVerAdditions >= VBOX_FULL_VERSION_MAKE(5, 0, 0))
            {
                if (uRevAdditions >= 103344) /* Since r103344: Protocol v3. */
                {
                    uProto = 3;
                }
                else
                    uProto = 2; /* VBox 5.0.0 - 5.0.8: Protocol v2. */
            }

            LogFlowFunc(("uVerAdditions=%RU32 (%RU32.%RU32.%RU32), r%RU32\n",
                         uVerAdditions, VBOX_FULL_VERSION_GET_MAJOR(uVerAdditions), VBOX_FULL_VERSION_GET_MINOR(uVerAdditions),
                                        VBOX_FULL_VERSION_GET_BUILD(uVerAdditions), uRevAdditions));
            rc = VINF_SUCCESS;
        }
    }
    else
    {
        uProto = 1; /* Fallback. */
        rc = VERR_NOT_FOUND;
    }

    LogRel2(("DnD: Guest is using protocol v%RU32, rc=%Rrc\n", uProto, rc));

    *puProto = uProto;
    return rc;
}
STDMETHODIMP VirtualBoxSDS::DeregisterVBoxSVC(IVBoxSVCRegistration *aVBoxSVC, LONG aPid)
{
    LogRel(("deregisterVBoxSVC: aVBoxSVC=%p aPid=%u (%#x)\n", (IVBoxSVCRegistration *)aVBoxSVC, aPid, aPid));
    HRESULT hrc;
    if (RT_VALID_PTR(aVBoxSVC))
    {
        /* Get the client user SID and name. */
        com::Utf8Str strSid;
        com::Utf8Str strUsername;
        if (i_getClientUserSid(&strSid, &strUsername))
        {
            VBoxSDSPerUserData *pUserData = i_lookupPerUserData(strSid);
            if (pUserData)
            {
                if (aVBoxSVC == (IVBoxSVCRegistration *)pUserData->m_ptrTheChosenOne)
                {
                    LogRel(("deregisterVBoxSVC: It's the chosen one for %s (%s)!\n",
                            pUserData->m_strUserSid.c_str(), pUserData->m_strUsername.c_str()));
#ifdef WITH_WATCHER
                    i_stopWatching(pUserData, pUserData->m_pidTheChosenOne);
#endif
                    pUserData->i_unchooseTheOne(false /*fIrregular*/);
                }
                else
                    LogRel(("deregisterVBoxSVC: not the choosen one (%p != %p)\n",
                            (IVBoxSVCRegistration *)aVBoxSVC, (IVBoxSVCRegistration *)pUserData->m_ptrTheChosenOne));
                pUserData->i_unlock();
                pUserData->i_release();

                hrc = S_OK;
            }
            else
            {
                LogRel(("deregisterVBoxSVC: Found no user data for %s (%s) (pid %u)\n",
                        strSid.c_str(), strUsername.c_str(), aPid));
                hrc = S_OK;
            }
        }
        else
            hrc = E_FAIL;
    }
    else
        hrc = E_INVALIDARG;
    LogRel2(("VirtualBoxSDS::deregisterVBoxSVC: returns %Rhrc\n", hrc));
    return hrc;
}
/**
 * Disconnect the host side of the shared clipboard and send a "host disconnected" message
 * to the guest side.
 */
static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
{
    VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;

    LogRel2(("svcDisconnect: u32ClientID = %d\n", u32ClientID));

    vboxSvcClipboardReportMsg (pClient, VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT, 0);

    vboxSvcClipboardCompleteReadData(pClient, VERR_NO_DATA, 0);

    vboxClipboardDisconnect (pClient);

    memset (pClient, 0, sizeof (*pClient));

    g_pClient = NULL;

    return VINF_SUCCESS;
}
Beispiel #25
0
extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
{
    int rc = VINF_SUCCESS;

    LogRelFlowFunc(("ptable = %p\n", ptable));

    if (!ptable)
    {
        rc = VERR_INVALID_PARAMETER;
    }
    else
    {
        LogRel2(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));

        if (   ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
            || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
        {
            rc = VERR_INVALID_PARAMETER;
        }
        else
        {
            g_pHelpers = ptable->pHelpers;

            ptable->cbClient = sizeof (VBOXCLIPBOARDCLIENTDATA);

            ptable->pfnUnload     = svcUnload;
            ptable->pfnConnect    = svcConnect;
            ptable->pfnDisconnect = svcDisconnect;
            ptable->pfnCall       = svcCall;
            ptable->pfnHostCall   = svcHostCall;
            ptable->pfnSaveState  = svcSaveState;
            ptable->pfnLoadState  = svcLoadState;
            ptable->pfnRegisterExtension  = svcRegisterExtension;
            ptable->pvService     = NULL;

            /* Service specific initialization. */
            rc = svcInit ();
        }
    }

    return rc;
}
static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
{
#ifndef UNIT_TEST
    /*
     * When the state will be restored, pending requests will be reissued
     * by VMMDev. The service therefore must save state as if there were no
     * pending request.
     * Pending requests, if any, will be completed in svcDisconnect.
     */
    LogRel2 (("svcSaveState: u32ClientID = %d\n", u32ClientID));

    VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;

    /* This field used to be the length. We're using it as a version field
       with the high bit set. */
    SSMR3PutU32 (pSSM, UINT32_C (0x80000002));
    int rc = SSMR3PutStructEx (pSSM, pClient, sizeof(*pClient), 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL);
    AssertRCReturn (rc, rc);
#endif /* !UNIT_TEST */
    return VINF_SUCCESS;
}
Beispiel #27
0
void UIMediumEnumerator::sltHandleMachineUpdate(QString strMachineID)
{
    LogRel2(("GUI: UIMediumEnumerator: Machine (or snapshot) event received, ID = %s\n",
             strMachineID.toUtf8().constData()));

    /* Gather previously used UIMedium IDs: */
    QStringList previousUIMediumIDs;
    calculateCachedUsage(strMachineID, previousUIMediumIDs, true /* take into account current state only */);
    LogRel2(("GUI: UIMediumEnumerator:  Old usage: %s\n",
             previousUIMediumIDs.isEmpty() ? "<empty>" : previousUIMediumIDs.join(", ").toUtf8().constData()));

    /* Gather currently used CMediums and their IDs: */
    CMediumMap currentCMediums;
    QStringList currentCMediumIDs;
    calculateActualUsage(strMachineID, currentCMediums, currentCMediumIDs, true /* take into account current state only */);
    LogRel2(("GUI: UIMediumEnumerator:  New usage: %s\n",
             currentCMediumIDs.isEmpty() ? "<empty>" : currentCMediumIDs.join(", ").toUtf8().constData()));

    /* Determine excluded mediums: */
    const QSet<QString> previousSet = previousUIMediumIDs.toSet();
    const QSet<QString> currentSet = currentCMediumIDs.toSet();
    const QSet<QString> excludedSet = previousSet - currentSet;
    const QStringList excludedUIMediumIDs = excludedSet.toList();
    if (!excludedUIMediumIDs.isEmpty())
        LogRel2(("GUI: UIMediumEnumerator:  Items excluded from usage: %s\n", excludedUIMediumIDs.join(", ").toUtf8().constData()));
    if (!currentCMediumIDs.isEmpty())
        LogRel2(("GUI: UIMediumEnumerator:  Items currently in usage: %s\n", currentCMediumIDs.join(", ").toUtf8().constData()));

    /* Update cache for excluded UIMediums: */
    recacheFromCachedUsage(excludedUIMediumIDs);

    /* Update cache for current CMediums: */
    recacheFromActualUsage(currentCMediums, currentCMediumIDs);

    LogRel2(("GUI: UIMediumEnumerator: Machine (or snapshot) event processed, ID = %s\n",
             strMachineID.toUtf8().constData()));
}
Beispiel #28
0
/**
 * Retrieves the data stored in this object and store the result in
 * pMedium.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 * @param   pMedium
 */
STDMETHODIMP UIDnDDataObject::GetData(LPFORMATETC pFormatEtc, LPSTGMEDIUM pMedium)
{
    AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
    AssertPtrReturn(pMedium, DV_E_FORMATETC);

    HRESULT hr = DV_E_FORMATETC;

    LPFORMATETC pThisFormat = NULL;
    LPSTGMEDIUM pThisMedium = NULL;

    LogFlowThisFunc(("\n"));

    /* Format supported? */
    ULONG lIndex;
    if (   LookupFormatEtc(pFormatEtc, &lIndex)
        && lIndex < m_cFormats) /* Paranoia. */
    {
        pThisMedium = &m_pStgMedium[lIndex];
        AssertPtr(pThisMedium);
        pThisFormat = &m_pFormatEtc[lIndex];
        AssertPtr(pThisFormat);

        LogFlowThisFunc(("pThisMedium=%p, pThisFormat=%p\n", pThisMedium, pThisFormat));
        LogFlowThisFunc(("mStatus=%RU32\n", m_enmStatus));
        switch (m_enmStatus)
        {
            case DnDDataObjectStatus_Dropping:
            {
#if 0
                LogRel3(("DnD: Dropping\n"));
                LogFlowFunc(("Waiting for event ...\n"));
                int rc2 = RTSemEventWait(m_SemEvent, RT_INDEFINITE_WAIT);
                LogFlowFunc(("rc=%Rrc, mStatus=%RU32\n", rc2, m_enmStatus));
#endif
                break;
            }

            case DnDDataObjectStatus_Dropped:
            {
                LogRel3(("DnD: Dropped\n"));
                LogRel3(("DnD: cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
                         pThisFormat->cfFormat, UIDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
                         pThisFormat->tymed, pThisFormat->dwAspect));
                LogRel3(("DnD: Got strFormat=%s, pvData=%p, cbData=%RU32\n",
                         m_strFormat.toUtf8().constData(), m_pvData, m_cbData));

                QVariant::Type vaType;
                QString strMIMEType;
                if (    (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (   pFormatEtc->cfFormat == CF_TEXT
                         || pFormatEtc->cfFormat == CF_UNICODETEXT)
                   )
                {
                    strMIMEType = "text/plain"; /** @todo Indicate UTF8 encoding? */
                    vaType = QVariant::String;
                }
                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                         && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                         && (pFormatEtc->cfFormat == CF_HDROP))
                {
                    strMIMEType = "text/uri-list";
                    vaType = QVariant::StringList;
                }
#if 0 /* More formats; not needed right now. */
                else if (   (pFormatEtc->tymed & TYMED_ISTREAM)
                        && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                        && (pFormatEtc->cfFormat == CF_FILECONTENTS))
                {

                }
                else if  (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                          && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                          && (pFormatEtc->cfFormat == CF_FILEDESCRIPTOR))
                {

                }
                else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                         && (pFormatEtc->cfFormat == CF_PREFERREDDROPEFFECT))
                {
                    HGLOBAL hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE | GMEM_ZEROINIT, sizeof(DWORD));
                    DWORD *pdwEffect = (DWORD *)GlobalLock(hData);
                    AssertPtr(pdwEffect);
                    *pdwEffect = DROPEFFECT_COPY;
                    GlobalUnlock(hData);

                    pMedium->hGlobal = hData;
                    pMedium->tymed = TYMED_HGLOBAL;
                }
#endif
                LogRel3(("DnD: strMIMEType=%s, vaType=%ld\n", strMIMEType.toUtf8().constData(), vaType));

                int rc;

                if (!m_fDataRetrieved)
                {
                    if (m_pDnDHandler)
                    {
                        rc = m_pDnDHandler->retrieveData(Qt::CopyAction,
                                                         strMIMEType, vaType, m_vaData);
                    }
                    else
                        rc = VERR_NOT_FOUND;

                    m_fDataRetrieved = true;
                    LogFlowFunc(("Retrieving data ended with %Rrc\n", rc));
                }
                else /* Data already been retrieved. */
                    rc = VINF_SUCCESS;

                if (   RT_SUCCESS(rc)
                    && m_vaData.isValid())
                {
                    if (   strMIMEType.startsWith("text/uri-list")
                               /* One item. */
                        && (   m_vaData.canConvert(QVariant::String)
                               /* Multiple items. */
                            || m_vaData.canConvert(QVariant::StringList))
                       )
                    {
                        QStringList lstFilesURI = m_vaData.toStringList();
                        QStringList lstFiles;
                        for (size_t i = 0; i < lstFilesURI.size(); i++)
                        {
                            char *pszFilePath = RTUriFilePath(lstFilesURI.at(i).toUtf8().constData());
                            if (pszFilePath)
                            {
                                lstFiles.append(pszFilePath);
                                RTStrFree(pszFilePath);
                            }
                            else /* Unable to parse -- refuse entire request. */
                            {
                                lstFiles.clear();
                                rc = VERR_INVALID_PARAMETER;
                                break;
                            }
                        }

                        size_t cFiles = lstFiles.size();
                        LogFlowThisFunc(("Files (%zu)\n", cFiles));
                        if (   RT_SUCCESS(rc)
                            && cFiles)
                        {
                            size_t cchFiles = 0; /* Number of characters. */
                            for (size_t i = 0; i < cFiles; i++)
                            {
                                const char *pszFile = lstFiles.at(i).toUtf8().constData();
                                cchFiles += strlen(pszFile);
                                cchFiles += 1; /* Terminating '\0'. */
                                LogFlowThisFunc(("\tFile: %s (cchFiles=%zu)\n", pszFile, cchFiles));
                            }

                            /* List termination with '\0'. */
                            cchFiles++;

                            size_t cbBuf = sizeof(DROPFILES) + (cchFiles * sizeof(RTUTF16));
                            DROPFILES *pDropFiles = (DROPFILES *)RTMemAllocZ(cbBuf);
                            if (pDropFiles)
                            {
                                /* Put the files list right after our DROPFILES structure. */
                                pDropFiles->pFiles = sizeof(DROPFILES); /* Offset to file list. */
                                pDropFiles->fWide  = 1;                 /* We use Unicode. Always. */

                                uint8_t *pCurFile = (uint8_t *)pDropFiles + pDropFiles->pFiles;
                                AssertPtr(pCurFile);

                                LogFlowThisFunc(("Encoded:\n"));
                                for (size_t i = 0; i < cFiles; i++)
                                {
                                    const char *pszFile = lstFiles.at(i).toUtf8().constData();
                                    Assert(strlen(pszFile));

                                    size_t cchCurFile;
                                    PRTUTF16 pwszFile;
                                    rc = RTStrToUtf16(pszFile, &pwszFile);
                                    if (RT_SUCCESS(rc))
                                    {
                                        cchCurFile = RTUtf16Len(pwszFile);
                                        Assert(cchCurFile);
                                        memcpy(pCurFile, pwszFile, cchCurFile * sizeof(RTUTF16));
                                        RTUtf16Free(pwszFile);
                                    }
                                    else
                                        break;

                                    pCurFile += cchCurFile * sizeof(RTUTF16);

                                    /* Terminate current file name. */
                                    *pCurFile = L'\0';
                                    pCurFile += sizeof(RTUTF16);

                                    LogFlowThisFunc(("\t#%zu: cchCurFile=%zu\n", i, cchCurFile));
                                }

                                if (RT_SUCCESS(rc))
                                {
                                    *pCurFile = L'\0'; /* Final list terminator. */

                                    /*
                                     * Fill out the medium structure we're going to report back.
                                     */
                                    pMedium->tymed          = TYMED_HGLOBAL;
                                    pMedium->pUnkForRelease = NULL;
                                    pMedium->hGlobal        = GlobalAlloc(  GMEM_ZEROINIT
                                                                          | GMEM_MOVEABLE
                                                                          | GMEM_DDESHARE, cbBuf);
                                    if (pMedium->hGlobal)
                                    {
                                        LPVOID pvMem = GlobalLock(pMedium->hGlobal);
                                        if (pvMem)
                                        {
                                            memcpy(pvMem, pDropFiles, cbBuf);
                                            GlobalUnlock(pMedium->hGlobal);

                                            hr = S_OK;
                                        }
                                        else
                                            rc = VERR_ACCESS_DENIED;
                                    }
                                    else
                                        rc = VERR_NO_MEMORY;

                                    LogFlowThisFunc(("Copying to TYMED_HGLOBAL (%zu bytes): %Rrc\n", cbBuf, rc));
                                }

                                RTMemFree(pDropFiles);
                            }
                            else
                                rc = VERR_NO_MEMORY;

                            if (RT_FAILURE(rc))
                                LogFlowThisFunc(("Failed with %Rrc\n", rc));
                        }
                    }
                    else if (   strMIMEType.startsWith("text/plain")
                             && m_vaData.canConvert(QVariant::String))
                    {
                        const bool fUnicode = pFormatEtc->cfFormat == CF_UNICODETEXT;
                        const size_t cbCh   = fUnicode
                                            ? sizeof(WCHAR) : sizeof(char);

                        QString strText = m_vaData.toString();
                        size_t cbSrc = strText.length() * cbCh;
                        Assert(cbSrc);
                        LPCVOID pvSrc = fUnicode
                                      ? (void *)strText.unicode()
                                      : (void *)strText.toUtf8().constData();
                        AssertPtr(pvSrc);

                        LogFlowFunc(("pvSrc=0x%p, cbSrc=%zu, cbCh=%zu, fUnicode=%RTbool\n",
                                     pvSrc, cbSrc, cbCh, fUnicode));

                        pMedium->tymed          = TYMED_HGLOBAL;
                        pMedium->pUnkForRelease = NULL;
                        pMedium->hGlobal        = GlobalAlloc(GHND | GMEM_SHARE, cbSrc);
                        if (pMedium->hGlobal)
                        {
                            LPVOID pvDst = GlobalLock(pMedium->hGlobal);
                            if (pvDst)
                            {
                                memcpy(pvDst, pvSrc, cbSrc);
                                GlobalUnlock(pMedium->hGlobal);
                            }
                            else
                                rc = VERR_ACCESS_DENIED;

                            hr = S_OK;
                        }
                        else
                            hr  = VERR_NO_MEMORY;
                    }
                    else
                        LogRel2(("DnD: MIME type '%s' not supported\n", strMIMEType.toUtf8().constData()));

                    LogFlowThisFunc(("Handling formats ended with rc=%Rrc\n", rc));
                }

                break;
            }

            default:
                break;
        }
    }

    /*
     * Fallback in error case.
     */
    if (FAILED(hr))
    {
        if (pThisMedium)
        {
            switch (pThisMedium->tymed)
            {

            case TYMED_HGLOBAL:
                pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
                                                             pThisFormat->cfFormat,
                                                             0 /* Flags */);
                break;

            default:
                break;
            }
        }

        if (pFormatEtc)
            pMedium->tymed = pFormatEtc->tymed;

        pMedium->pUnkForRelease = NULL;
    }

    LogFlowThisFunc(("Returning hr=%Rhrc\n", hr));
    return hr;
}
HRESULT HostDnsServiceWin::updateInfo()
{
    HostDnsInformation info;

    LONG lrc;
    int rc;

    std::string strDomain;
    std::string strSearchList;  /* NB: comma separated, no spaces */


    /*
     * We ignore "DhcpDomain" key here since it's not stable.  If
     * there are two active interfaces that use DHCP (in particular
     * when host uses OpenVPN) then DHCP ACKs will take turns updating
     * that key.  Instead we call GetAdaptersAddresses() below (which
     * is what ipconfig.exe seems to do).
     */
    for (DWORD regIndex = 0; /**/; ++regIndex) {
        char keyName[256];
        DWORD cbKeyName = sizeof(keyName);
        DWORD keyType = 0;
        char keyData[1024];
        DWORD cbKeyData = sizeof(keyData);

        lrc = RegEnumValueA(m->hKeyTcpipParameters, regIndex,
                            keyName, &cbKeyName, 0,
                            &keyType, (LPBYTE)keyData, &cbKeyData);

        if (lrc == ERROR_NO_MORE_ITEMS)
            break;

        if (lrc == ERROR_MORE_DATA) /* buffer too small; handle? */
            continue;

        if (lrc != ERROR_SUCCESS)
        {
            LogRel2(("HostDnsServiceWin: RegEnumValue error %d\n", (int)lrc));
            return E_FAIL;
        }

        if (keyType != REG_SZ)
            continue;

        if (cbKeyData > 0 && keyData[cbKeyData - 1] == '\0')
            --cbKeyData;     /* don't count trailing NUL if present */

        if (RTStrICmp("Domain", keyName) == 0)
        {
            strDomain.assign(keyData, cbKeyData);
            LogRel2(("HostDnsServiceWin: Domain=\"%s\"\n", strDomain.c_str()));
        }
        else if (RTStrICmp("DhcpDomain", keyName) == 0)
        {
            std::string strDhcpDomain(keyData, cbKeyData);
            LogRel2(("HostDnsServiceWin: DhcpDomain=\"%s\"\n", strDhcpDomain.c_str()));
        }
        else if (RTStrICmp("SearchList", keyName) == 0)
        {
            strSearchList.assign(keyData, cbKeyData);
            LogRel2(("HostDnsServiceWin: SearchList=\"%s\"\n", strSearchList.c_str()));
        }
    }

    /* statically configured domain name */
    if (!strDomain.empty())
    {
        info.domain = strDomain;
        info.searchList.push_back(strDomain);
    }

    /* statically configured search list */
    if (!strSearchList.empty())
    {
        vappend(info.searchList, strSearchList, ',');
    }


    /*
     * When name servers are configured statically it seems that the
     * value of Tcpip\Parameters\NameServer is NOT set, inly interface
     * specific NameServer value is (which triggers notification for
     * us to pick up the change).  Fortunately, DnsApi seems to do the
     * right thing there.
     */
    DNS_STATUS status;
    PIP4_ARRAY pIp4Array = NULL;

    // NB: must be set on input it seems, despite docs' claim to the contrary.
    DWORD cbBuffer = sizeof(&pIp4Array);

    status = DnsQueryConfig(DnsConfigDnsServerList,
                            DNS_CONFIG_FLAG_ALLOC, NULL, NULL,
                            &pIp4Array, &cbBuffer);

    if (status == NO_ERROR && pIp4Array != NULL)
    {
        for (DWORD i = 0; i < pIp4Array->AddrCount; ++i)
        {
            char szAddrStr[16] = "";
            RTStrPrintf(szAddrStr, sizeof(szAddrStr), "%RTnaipv4", pIp4Array->AddrArray[i]);

            LogRel2(("HostDnsServiceWin: server %d: %s\n", i+1,  szAddrStr));
            info.servers.push_back(szAddrStr);
        }

        LocalFree(pIp4Array);
    }


    /**
     * DnsQueryConfig(DnsConfigSearchList, ...) is not implemented.
     * Call GetAdaptersAddresses() that orders the returned list
     * appropriately and collect IP_ADAPTER_ADDRESSES::DnsSuffix.
     */
    do {
        PIP_ADAPTER_ADDRESSES pAddrBuf = NULL;
        ULONG cbAddrBuf = 8 * 1024;
        bool fReallocated = false;
        ULONG err;

        pAddrBuf = (PIP_ADAPTER_ADDRESSES) malloc(cbAddrBuf);
        if (pAddrBuf == NULL)
        {
            LogRel2(("HostDnsServiceWin: failed to allocate %zu bytes"
                     " of GetAdaptersAddresses buffer\n",
                     (size_t)cbAddrBuf));
            break;
        }

        while (pAddrBuf != NULL)
        {
            ULONG cbAddrBufProvided = cbAddrBuf;

            err = GetAdaptersAddresses(AF_UNSPEC,
                                         GAA_FLAG_SKIP_ANYCAST
                                       | GAA_FLAG_SKIP_MULTICAST,
                                       NULL,
                                       pAddrBuf, &cbAddrBuf);
            if (err == NO_ERROR)
            {
                break;
            }
            else if (err == ERROR_BUFFER_OVERFLOW)
            {
                LogRel2(("HostDnsServiceWin: provided GetAdaptersAddresses with %zu"
                         " but asked again for %zu bytes\n",
                         (size_t)cbAddrBufProvided, (size_t)cbAddrBuf));

                if (RT_UNLIKELY(fReallocated)) /* what? again?! */
                {
                    LogRel2(("HostDnsServiceWin: ... not going to realloc again\n"));
                    free(pAddrBuf);
                    pAddrBuf = NULL;
                    break;
                }

                PIP_ADAPTER_ADDRESSES pNewBuf = (PIP_ADAPTER_ADDRESSES) realloc(pAddrBuf, cbAddrBuf);
                if (pNewBuf == NULL)
                {
                    LogRel2(("HostDnsServiceWin: failed to reallocate %zu bytes\n", (size_t)cbAddrBuf));
                    free(pAddrBuf);
                    pAddrBuf = NULL;
                    break;
                }

                /* try again */
                pAddrBuf = pNewBuf; /* cbAddrBuf already updated */
                fReallocated = true;
            }
            else
            {
                LogRel2(("HostDnsServiceWin: GetAdaptersAddresses error %d\n", err));
                free(pAddrBuf);
                pAddrBuf = NULL;
                break;
            }
        }

        if (pAddrBuf == NULL)
            break;

        for (PIP_ADAPTER_ADDRESSES pAdp = pAddrBuf; pAdp != NULL; pAdp = pAdp->Next)
        {
            LogRel2(("HostDnsServiceWin: %ls (status %u) ...\n",
                     pAdp->FriendlyName ? pAdp->FriendlyName : L"(null)",
                     pAdp->OperStatus));

            if (pAdp->OperStatus != IfOperStatusUp)
                continue;

            if (pAdp->DnsSuffix == NULL || *pAdp->DnsSuffix == L'\0')
                continue;

            char *pszDnsSuffix = NULL;
            rc = RTUtf16ToUtf8Ex(pAdp->DnsSuffix, RTSTR_MAX,
                                 &pszDnsSuffix, 0, /* allocate */
                                 NULL);
            if (RT_FAILURE(rc))
            {
                LogRel2(("HostDnsServiceWin: failed to convert DNS suffix \"%ls\": %Rrc\n",
                        pAdp->DnsSuffix, rc));
                continue;
            }

            AssertContinue(pszDnsSuffix != NULL);
            AssertContinue(*pszDnsSuffix != '\0');
            LogRel2(("HostDnsServiceWin: ... suffix = \"%s\"\n", pszDnsSuffix));

            vappend(info.searchList, pszDnsSuffix);
            RTStrFree(pszDnsSuffix);
        }

        free(pAddrBuf);
    } while (0);


    if (info.domain.empty() && !info.searchList.empty())
        info.domain = info.searchList[0];

    if (info.searchList.size() == 1)
        info.searchList.clear();

    HostDnsMonitor::setInfo(info);

    return S_OK;
}
Beispiel #30
0
int UIDnDHandler::dragStartInternal(const QStringList &lstFormats,
                                    Qt::DropAction defAction, Qt::DropActions actions)
{
    int rc = VINF_SUCCESS;

#ifdef VBOX_WITH_DRAG_AND_DROP_GH

    LogFlowFunc(("defAction=0x%x\n", defAction));
    LogFlowFunc(("Number of formats: %d\n", lstFormats.size()));
# ifdef DEBUG
    for (int i = 0; i < lstFormats.size(); i++)
        LogFlowFunc(("\tFormat %d: %s\n", i, lstFormats.at(i).toUtf8().constData()));
# endif

# ifdef DEBUG_DND_QT
    QFile *pFileDebugQt = new QFile(DEBUG_DND_QT_LOGFILE);
    if (pFileDebugQt->open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text))
    {
        g_pStrmLogQt = new QTextStream(pFileDebugQt);

#if QT_VERSION >= 0x050000
        qInstallMessageHandler(UIDnDHandler::debugOutputQt);
#else /* QT_VERSION < 0x050000 */
        qInstallMsgHandler(UIDnDHandler::debugOutputQt);
#endif /* QT_VERSION < 0x050000 */
        qDebug("========================================================================");
    }
# endif

# ifdef RT_OS_WINDOWS
    UIDnDDataObject *pDataObject = new UIDnDDataObject(this, lstFormats);
    if (!pDataObject)
        return VERR_NO_MEMORY;
    UIDnDDropSource *pDropSource = new UIDnDDropSource(m_pParent, pDataObject);
    if (!pDropSource)
        return VERR_NO_MEMORY;

    DWORD dwOKEffects = DROPEFFECT_NONE;
    if (actions)
    {
        if (actions & Qt::CopyAction)
            dwOKEffects |= DROPEFFECT_COPY;
        if (actions & Qt::MoveAction)
            dwOKEffects |= DROPEFFECT_MOVE;
        if (actions & Qt::LinkAction)
            dwOKEffects |= DROPEFFECT_LINK;
    }

    DWORD dwEffect;
    LogRel2(("DnD: Starting drag and drop operation\n", dwOKEffects));
    LogRel3(("DnD: DoDragDrop dwOKEffects=0x%x\n", dwOKEffects));
    HRESULT hr = ::DoDragDrop(pDataObject, pDropSource, dwOKEffects, &dwEffect);
    LogRel3(("DnD: DoDragDrop ended with hr=%Rhrc, dwEffect=%RI32\n", hr, dwEffect));

    if (pDropSource)
        pDropSource->Release();
    if (pDataObject)
        pDataObject->Release();

# else /* !RT_OS_WINDOWS */

    QDrag *pDrag = new QDrag(m_pParent);
    if (!pDrag)
        return VERR_NO_MEMORY;

    /* Note: pMData is transferred to the QDrag object, so no need for deletion. */
    m_pMIMEData = new UIDnDMIMEData(this, lstFormats, defAction, actions);
    if (!m_pMIMEData)
    {
        delete pDrag;
        return VERR_NO_MEMORY;
    }

    /* Inform the MIME data object of any changes in the current action. */
    connect(pDrag, SIGNAL(actionChanged(Qt::DropAction)),
            m_pMIMEData, SLOT(sltDropActionChanged(Qt::DropAction)));

    /* Invoke this handler as data needs to be retrieved by our derived QMimeData class. */
    connect(m_pMIMEData, SIGNAL(sigGetData(Qt::DropAction, const QString&, QVariant::Type, QVariant&)),
            this, SLOT(sltGetData(Qt::DropAction, const QString&, QVariant::Type, QVariant&)));

    /*
     * Set MIME data object and start the (modal) drag'n drop operation on the host.
     * This does not block Qt's event loop, however (on Windows it would).
     */
    pDrag->setMimeData(m_pMIMEData);
    LogFlowFunc(("Executing modal drag'n drop operation ...\n"));

    Qt::DropAction dropAction;
#  ifdef RT_OS_DARWIN
#    ifdef VBOX_WITH_DRAG_AND_DROP_PROMISES
        dropAction = pDrag->exec(actions, defAction, true /* fUsePromises */);
#    else
        /* Without having VBOX_WITH_DRAG_AND_DROP_PROMISES enabled drag and drop
         * will not work on OS X! It also requires some handcrafted patches within Qt
         * (which also needs VBOX_WITH_DRAG_AND_DROP_PROMISES set there). */
        dropAction = Qt::IgnoreAction;
        rc = VERR_NOT_SUPPORTED;
#    endif
#  else /* !RT_OS_DARWIN */
    dropAction = pDrag->exec(actions, defAction);
#  endif /* RT_OS_DARWIN */
    LogRel3(("DnD: Ended with dropAction=%ld\n", UIDnDHandler::toVBoxDnDAction(dropAction)));

    /* Note: The UIDnDMimeData object will not be not accessible here anymore,
     *       since QDrag had its ownership and deleted it after the (blocking)
     *       QDrag::exec() call. */

    /* pDrag will be cleaned up by Qt automatically. */

# endif /* !RT_OS_WINDOWS */

    reset();

#ifdef DEBUG_DND_QT
    if (g_pStrmLogQt)
    {
        delete g_pStrmLogQt;
        g_pStrmLogQt = NULL;
    }

    if (pFileDebugQt)
    {
        pFileDebugQt->close();
        delete pFileDebugQt;
    }
#endif /* DEBUG_DND_QT */

#else /* !VBOX_WITH_DRAG_AND_DROP_GH */

    rc = VERR_NOT_SUPPORTED;

#endif /* VBOX_WITH_DRAG_AND_DROP_GH */

    LogFlowFuncLeaveRC(rc);
    return rc;
}