Exemplo n.º 1
0
/**
 * Initializes the COM runtime.
 *
 * This method must be called on each thread of the client application that
 * wants to access COM facilities. The initialization must be performed before
 * calling any other COM method or attempting to instantiate COM objects.
 *
 * On platforms using XPCOM, this method uses the following scheme to search for
 * XPCOM runtime:
 *
 * 1. If the VBOX_APP_HOME environment variable is set, the path it specifies
 *    is used to search XPCOM libraries and components. If this method fails to
 *    initialize XPCOM runtime using this path, it will immediately return a
 *    failure and will NOT check for other paths as described below.
 *
 * 2. If VBOX_APP_HOME is not set, this methods tries the following paths in the
 *    given order:
 *
 *    a) Compiled-in application data directory (as returned by
 *       RTPathAppPrivateArch())
 *    b) "/usr/lib/virtualbox" (Linux only)
 *    c) "/opt/VirtualBox" (Linux only)
 *
 *    The first path for which the initialization succeeds will be used.
 *
 * On MS COM platforms, the COM runtime is provided by the system and does not
 * need to be searched for.
 *
 * Once the COM subsystem is no longer necessary on a given thread, Shutdown()
 * must be called to free resources allocated for it. Note that a thread may
 * call Initialize() several times but for each of tese calls there must be a
 * corresponding Shutdown() call.
 *
 * @return S_OK on success and a COM result code in case of failure.
 */
HRESULT Initialize(bool fGui)
{
    HRESULT rc = E_FAIL;

#if !defined(VBOX_WITH_XPCOM)

    /*
     * We initialize COM in GUI thread in STA, to be compliant with QT and
     * OLE requirments (for example to allow D&D), while other threads
     * initialized in regular MTA. To allow fast proxyless access from
     * GUI thread to COM objects, we explicitly provide our COM objects
     * with free threaded marshaller.
     * !!!!! Please think twice before touching this code !!!!!
     */
    DWORD flags = fGui ?
                  COINIT_APARTMENTTHREADED
                | COINIT_SPEED_OVER_MEMORY
                :
                  COINIT_MULTITHREADED
                | COINIT_DISABLE_OLE1DDE
                | COINIT_SPEED_OVER_MEMORY;

    rc = CoInitializeEx(NULL, flags);

    /* the overall result must be either S_OK or S_FALSE (S_FALSE means
     * "already initialized using the same apartment model") */
    AssertMsg(rc == S_OK || rc == S_FALSE, ("rc=%08X\n", rc));

    /* To be flow compatible with the XPCOM case, we return here if this isn't
     * the main thread or if it isn't its first initialization call.
     * Note! CoInitializeEx and CoUninitialize does it's own reference
     *       counting, so this exercise is entirely for the EventQueue init. */
    bool fRc;
    RTTHREAD hSelf = RTThreadSelf();
    if (hSelf != NIL_RTTHREAD)
        ASMAtomicCmpXchgHandle(&gCOMMainThread, hSelf, NIL_RTTHREAD, fRc);
    else
        fRc = false;

    if (fGui)
        Assert(RTThreadIsMain(hSelf));

    if (!fRc)
    {
        if (   gCOMMainThread == hSelf
            && SUCCEEDED(rc))
            gCOMMainInitCount++;

        AssertComRC(rc);
        return rc;
    }
    Assert(RTThreadIsMain(hSelf));

    /* this is the first main thread initialization */
    Assert(gCOMMainInitCount == 0);
    if (SUCCEEDED(rc))
        gCOMMainInitCount = 1;

#else /* !defined (VBOX_WITH_XPCOM) */

    /* Unused here */
    NOREF(fGui);

    if (ASMAtomicXchgBool(&gIsXPCOMInitialized, true) == true)
    {
        /* XPCOM is already initialized on the main thread, no special
         * initialization is necessary on additional threads. Just increase
         * the init counter if it's a main thread again (to correctly support
         * nested calls to Initialize()/Shutdown() for compatibility with
         * Win32). */

        nsCOMPtr<nsIEventQueue> eventQ;
        rc = NS_GetMainEventQ(getter_AddRefs(eventQ));

        if (NS_SUCCEEDED(rc))
        {
            PRBool isOnMainThread = PR_FALSE;
            rc = eventQ->IsOnCurrentThread(&isOnMainThread);
            if (NS_SUCCEEDED(rc) && isOnMainThread)
                ++gXPCOMInitCount;
        }

        AssertComRC(rc);
        return rc;
    }
    Assert(RTThreadIsMain(RTThreadSelf()));

    /* this is the first initialization */
    gXPCOMInitCount = 1;
    bool const fInitEventQueues = true;

    /* prepare paths for registry files */
    char szCompReg[RTPATH_MAX];
    char szXptiDat[RTPATH_MAX];

    int vrc = GetVBoxUserHomeDirectory(szCompReg, sizeof(szCompReg));
    AssertRCReturn(vrc, NS_ERROR_FAILURE);
    strcpy(szXptiDat, szCompReg);

    vrc = RTPathAppend(szCompReg, sizeof(szCompReg), "compreg.dat");
    AssertRCReturn(vrc, NS_ERROR_FAILURE);
    vrc = RTPathAppend(szXptiDat, sizeof(szXptiDat), "xpti.dat");
    AssertRCReturn(vrc, NS_ERROR_FAILURE);

    LogFlowFunc(("component registry  : \"%s\"\n", szCompReg));
    LogFlowFunc(("XPTI data file      : \"%s\"\n", szXptiDat));

#if defined (XPCOM_GLUE)
    XPCOMGlueStartup(nsnull);
#endif

    static const char *kAppPathsToProbe[] =
    {
        NULL, /* 0: will use VBOX_APP_HOME */
        NULL, /* 1: will try RTPathAppPrivateArch() */
#ifdef RT_OS_LINUX
        "/usr/lib/virtualbox",
        "/opt/VirtualBox",
#elif RT_OS_SOLARIS
        "/opt/VirtualBox/amd64",
        "/opt/VirtualBox/i386",
#elif RT_OS_DARWIN
        "/Application/VirtualBox.app/Contents/MacOS",
#endif
    };

    /* Find out the directory where VirtualBox binaries are located */
    for (size_t i = 0; i < RT_ELEMENTS(kAppPathsToProbe); ++ i)
    {
        char szAppHomeDir[RTPATH_MAX];

        if (i == 0)
        {
            /* Use VBOX_APP_HOME if present */
            vrc = RTEnvGetEx(RTENV_DEFAULT, "VBOX_APP_HOME", szAppHomeDir, sizeof(szAppHomeDir), NULL);
            if (vrc == VERR_ENV_VAR_NOT_FOUND)
                continue;
            AssertRC(vrc);
        }
        else if (i == 1)
        {
            /* Use RTPathAppPrivateArch() first */
            vrc = RTPathAppPrivateArch(szAppHomeDir, sizeof(szAppHomeDir));
            AssertRC(vrc);
        }
        else
        {
            /* Iterate over all other paths */
            szAppHomeDir[RTPATH_MAX - 1] = '\0';
            strncpy(szAppHomeDir, kAppPathsToProbe[i], RTPATH_MAX - 1);
            vrc = VINF_SUCCESS;
        }
        if (RT_FAILURE(vrc))
        {
            rc = NS_ERROR_FAILURE;
            continue;
        }

        char szCompDir[RTPATH_MAX];
        vrc = RTPathAppend(strcpy(szCompDir, szAppHomeDir), sizeof(szCompDir), "components");
        if (RT_FAILURE(vrc))
        {
            rc = NS_ERROR_FAILURE;
            continue;
        }
        LogFlowFunc(("component directory : \"%s\"\n", szCompDir));

        nsCOMPtr<DirectoryServiceProvider> dsProv;
        dsProv = new DirectoryServiceProvider();
        if (dsProv)
            rc = dsProv->init(szCompReg, szXptiDat, szCompDir, szAppHomeDir);
        else
            rc = NS_ERROR_OUT_OF_MEMORY;
        if (NS_FAILED(rc))
            break;

        /* Setup the application path for NS_InitXPCOM2. Note that we properly
         * answer the NS_XPCOM_CURRENT_PROCESS_DIR query in our directory
         * service provider but it seems to be activated after the directory
         * service is used for the first time (see the source NS_InitXPCOM2). So
         * use the same value here to be on the safe side. */
        nsCOMPtr <nsIFile> appDir;
        {
            char *appDirCP = NULL;
            vrc = RTStrUtf8ToCurrentCP(&appDirCP, szAppHomeDir);
            if (RT_SUCCESS(vrc))
            {
                nsCOMPtr<nsILocalFile> file;
                rc = NS_NewNativeLocalFile(nsEmbedCString(appDirCP),
                                           PR_FALSE, getter_AddRefs(file));
                if (NS_SUCCEEDED(rc))
                    appDir = do_QueryInterface(file, &rc);

                RTStrFree(appDirCP);
            }
            else
                rc = NS_ERROR_FAILURE;
        }
        if (NS_FAILED(rc))
            break;

        /* Set VBOX_XPCOM_HOME to the same app path to make XPCOM sources that
         * still use it instead of the directory service happy */
        vrc = RTEnvSetEx(RTENV_DEFAULT, "VBOX_XPCOM_HOME", szAppHomeDir);
        AssertRC(vrc);

        /* Finally, initialize XPCOM */
        {
            nsCOMPtr<nsIServiceManager> serviceManager;
            rc = NS_InitXPCOM2(getter_AddRefs(serviceManager), appDir, dsProv);
            if (NS_SUCCEEDED(rc))
            {
                nsCOMPtr<nsIComponentRegistrar> registrar =
                    do_QueryInterface(serviceManager, &rc);
                if (NS_SUCCEEDED(rc))
                {
                    rc = registrar->AutoRegister(nsnull);
                    if (NS_SUCCEEDED(rc))
                    {
                        /* We succeeded, stop probing paths */
                        LogFlowFunc(("Succeeded.\n"));
                        break;
                    }
                }
            }
        }

        /* clean up before the new try */
        rc = NS_ShutdownXPCOM(nsnull);

        if (i == 0)
        {
            /* We failed with VBOX_APP_HOME, don't probe other paths */
            break;
        }
    }

#endif /* !defined (VBOX_WITH_XPCOM) */

    // for both COM and XPCOM, we only get here if this is the main thread;
    // only then initialize the autolock system (AutoLock.cpp)
    Assert(RTThreadIsMain(RTThreadSelf()));
    util::InitAutoLockSystem();

    AssertComRC(rc);

    /*
     * Init the main event queue (ASSUMES it cannot fail).
     */
    if (SUCCEEDED(rc))
        EventQueue::init();

    return rc;
}
DECLCALLBACK(int) VBoxClipboardWorker(void *pInstance, bool volatile *pfShutdown)
{
    AssertPtr(pInstance);
    LogFlowFunc(("pInstance=%p\n", pInstance));

    /*
     * Tell the control thread that it can continue
     * spawning services.
     */
    RTThreadUserSignal(RTThreadSelf());

    const PVBOXCLIPBOARDCONTEXT pCtx = (PVBOXCLIPBOARDCONTEXT)pInstance;
    AssertPtr(pCtx);

    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;

    int rc;

    /* The thread waits for incoming messages from the host. */
    for (;;)
    {
        uint32_t u32Msg;
        uint32_t u32Formats;
        rc = VbglR3ClipboardGetHostMsg(pCtx->u32ClientID, &u32Msg, &u32Formats);
        if (RT_FAILURE(rc))
        {
            if (rc == VERR_INTERRUPTED)
                break;

            LogFunc(("Error getting host message, rc=%Rrc\n", rc));

            if (*pfShutdown)
                break;

            /* Wait a bit before retrying. */
            RTThreadSleep(1000);
            continue;
        }
        else
        {
            LogFlowFunc(("u32Msg=%RU32, u32Formats=0x%x\n", u32Msg, u32Formats));
            switch (u32Msg)
            {
               case VBOX_SHARED_CLIPBOARD_HOST_MSG_REPORT_FORMATS:
               {
                   /* The host has announced available clipboard formats.
                    * Forward the information to the window, so it can later
                    * respond to WM_RENDERFORMAT message. */
                   ::PostMessage(pWinCtx->hWnd, VBOX_CLIPBOARD_WM_SET_FORMATS, 0, u32Formats);
                   break;
               }

               case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
               {
                   /* The host needs data in the specified format. */
                   ::PostMessage(pWinCtx->hWnd, VBOX_CLIPBOARD_WM_READ_DATA, 0, u32Formats);
                   break;
               }

               case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
               {
                   /* The host is terminating. */
                   LogRel(("Clipboard: Terminating ...\n"));
                   ASMAtomicXchgBool(pfShutdown, true);
                   break;
               }

               default:
               {
                   LogFlowFunc(("Unsupported message from host, message=%RU32\n", u32Msg));

                   /* Wait a bit before retrying. */
                   RTThreadSleep(1000);
                   break;
               }
            }
        }

        if (*pfShutdown)
            break;
    }

    LogFlowFuncLeaveRC(rc);
    return rc;
}
/**
 * Issued by the QDrag object as soon as the current drop action has changed.
 *
 * @param dropAction            New drop action to use.
 */
void UIDnDMIMEData::sltDropActionChanged(Qt::DropAction dropAction)
{
    LogFlowFunc(("dropAction=0x%x\n", dropAction));
    m_curAction = dropAction;
}
Exemplo n.º 4
0
/* This function will free m0! */
int
ip_output0(PNATState pData, struct socket *so, struct mbuf *m0, int urg)
{
    register struct ip *ip;
    register struct mbuf *m = m0;
    register int hlen = sizeof(struct ip);
    int len, off, error = 0;
    struct ethhdr *eh = NULL;
    uint8_t eth_dst[ETH_ALEN];
    int rc = 1;

    STAM_PROFILE_START(&pData->StatIP_output, a);

#ifdef LOG_ENABLED
    LogFlowFunc(("ip_output: so = %R[natsock], m0 = %lx\n", so, (long)m0));
#else
    NOREF(so);
#endif

    M_ASSERTPKTHDR(m);
    Assert(m->m_pkthdr.header);

#if 0 /* We do no options */
    if (opt)
    {
        m = ip_insertoptions(m, opt, &len);
        hlen = len;
    }
#endif
    ip = mtod(m, struct ip *);
    LogFunc(("ip(src:%RTnaipv4, dst:%RTnaipv4)\n", ip->ip_src, ip->ip_dst));
    /*
     * Fill in IP header.
     */
    ip->ip_v = IPVERSION;
    ip->ip_off &= IP_DF;
    ip->ip_id = RT_H2N_U16(ip_currid++);
    ip->ip_hl = hlen >> 2;
    ipstat.ips_localout++;

    /* Current TCP/IP stack hasn't routing information at
     * all so we need to calculate destination ethernet address
     */
    rc = rt_lookup_in_cache(pData, ip->ip_dst.s_addr, eth_dst);
    if (RT_FAILURE(rc))
        goto exit_drop_package;

    eh = (struct ethhdr *)(m->m_data - ETH_HLEN);
    /*
     * If small enough for interface, can just send directly.
     */
    if ((u_int16_t)ip->ip_len <= if_mtu)
    {
        ip->ip_len = RT_H2N_U16((u_int16_t)ip->ip_len);
        ip->ip_off = RT_H2N_U16((u_int16_t)ip->ip_off);
        ip->ip_sum = 0;
        ip->ip_sum = cksum(m, hlen);

        if (!(m->m_flags & M_SKIP_FIREWALL)){
            struct m_tag *t;
            STAM_PROFILE_START(&pData->StatALIAS_output, b);
            rc = LibAliasOut(pData->proxy_alias, mtod(m, char *), m_length(m, NULL));
            if (rc == PKT_ALIAS_IGNORED)
            {
                Log(("NAT: packet was droppped\n"));
                goto exit_drop_package;
            }
            STAM_PROFILE_STOP(&pData->StatALIAS_output, b);
        }
        else
/**
 * Reads a completed/error'd URB from the client driver (no waiting).
 *
 * @param   pDevSol         The Solaris device instance.
 */
static PVUSBURB usbProxySolarisUrbComplete(PUSBPROXYDEVSOL pDevSol)
{
    LogFlowFunc((USBPROXY ":usbProxySolarisUrbComplete pDevSol=%p\n", pDevSol));

    VBOXUSBREQ_URB UrbReq;
    bzero(&UrbReq, sizeof(UrbReq));

    int rc = usbProxySolarisIOCtl(pDevSol, VBOXUSB_IOCTL_REAP_URB, &UrbReq, sizeof(UrbReq));
    if (RT_SUCCESS(rc))
    {
        if (UrbReq.pvUrbR3)
        {
            PUSBPROXYURBSOL pUrbSol = (PUSBPROXYURBSOL)UrbReq.pvUrbR3;
            PVUSBURB pUrb           = pUrbSol->pVUsbUrb;
            if (RT_LIKELY(pUrb))
            {
                Assert(pUrb->u32Magic == VUSBURB_MAGIC);

                /*
                 * Update the URB.
                 */
                if (   pUrb->enmType == VUSBXFERTYPE_ISOC
                    && pUrb->enmDir == VUSBDIRECTION_IN)
                {
                    size_t cbData = 0;
                    for (unsigned i = 0; i < UrbReq.cIsocPkts; i++)
                    {
                        pUrb->aIsocPkts[i].cb = UrbReq.aIsocPkts[i].cbActPkt;
                        cbData += UrbReq.aIsocPkts[i].cbActPkt;
                        pUrb->aIsocPkts[i].enmStatus = UrbReq.aIsocPkts[i].enmStatus;
                    }

                    LogFlow((USBPROXY ":usbProxySolarisUrbComplete ISOC cbData=%d cbActPktSum=%d\n", pUrb->cbData, cbData));
                    pUrb->cbData = cbData;
                    pUrb->enmStatus = UrbReq.enmStatus;
                }
                else
                {
                    pUrb->cbData    = UrbReq.cbData;
                    pUrb->enmStatus = UrbReq.enmStatus;
                }

                RTCritSectEnter(&pDevSol->CritSect);

                /*
                 * Remove from the active list.
                 */
                if (pUrbSol->pNext)
                    pUrbSol->pNext->pPrev = pUrbSol->pPrev;
                if (pUrbSol->pPrev)
                    pUrbSol->pPrev->pNext = pUrbSol->pNext;
                else
                {
                    Assert(pDevSol->pInFlightHead == pUrbSol);
                    pDevSol->pInFlightHead = pUrbSol->pNext;
                }

                /*
                 * Link it into the taxing list.
                 */
                pUrbSol->pNext = NULL;
                pUrbSol->pPrev = pDevSol->pTaxingTail;
                if (pDevSol->pTaxingTail)
                    pDevSol->pTaxingTail->pNext = pUrbSol;
                else
                    pDevSol->pTaxingHead = pUrbSol;
                pDevSol->pTaxingTail = pUrbSol;

                RTCritSectLeave(&pDevSol->CritSect);

                LogFlow((USBPROXY "usbProxySolarisUrbComplete: cb=%d EndPt=%#x enmDir=%d enmStatus=%s (%d) \n",
                         pUrb->cbData, pUrb->EndPt, pUrb->enmDir, pUrb->enmStatus == VUSBSTATUS_OK ? "OK" : "** Failed **", pUrb->enmStatus));
//                if (pUrb->cbData < 2049)
//                    LogFlow((USBPROXY "%.*Rhxd\n", pUrb->cbData, pUrb->abData));
                return pUrb;
            }
        }
    }
    else
    {
        if (rc != VERR_VUSB_DEVICE_NOT_ATTACHED)
            LogRel((USBPROXY ":Reaping URB failed. rc=%Rrc\n", rc));
    }

    return NULL;
}
Exemplo n.º 6
0
static void parallelR3IrqClear(PARALLELPORT *pThis)
{
    LogFlowFunc(("%d 0\n", pThis->iIrq));
    PDMDevHlpISASetIrqNoWait(pThis->CTX_SUFF(pDevIns), pThis->iIrq, 0);
}
Exemplo n.º 7
0
static DECLCALLBACK(int) drvscsiReqTransferEnqueue(VSCSILUN hVScsiLun,
                                                   void *pvScsiLunUser,
                                                   VSCSIIOREQ hVScsiIoReq)
{
    int rc = VINF_SUCCESS;
    PDRVSCSI pThis = (PDRVSCSI)pvScsiLunUser;

    if (pThis->pDrvBlockAsync)
    {
        /* async I/O path. */
        VSCSIIOREQTXDIR enmTxDir;

        LogFlowFunc(("Enqueuing hVScsiIoReq=%#p\n", hVScsiIoReq));

        enmTxDir = VSCSIIoReqTxDirGet(hVScsiIoReq);

        switch (enmTxDir)
        {
            case VSCSIIOREQTXDIR_FLUSH:
            {
                rc = pThis->pDrvBlockAsync->pfnStartFlush(pThis->pDrvBlockAsync, hVScsiIoReq);
                if (   RT_FAILURE(rc)
                    && rc != VERR_VD_ASYNC_IO_IN_PROGRESS
                    && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
                    LogRel(("SCSI#%u: Flush returned rc=%Rrc\n",
                            pThis->pDrvIns->iInstance, rc));
                break;
            }
            case VSCSIIOREQTXDIR_UNMAP:
            {
                PCRTRANGE paRanges;
                unsigned cRanges;

                rc = VSCSIIoReqUnmapParamsGet(hVScsiIoReq, &paRanges, &cRanges);
                AssertRC(rc);

                pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
                rc = pThis->pDrvBlockAsync->pfnStartDiscard(pThis->pDrvBlockAsync, paRanges, cRanges, hVScsiIoReq);
                if (   RT_FAILURE(rc)
                    && rc != VERR_VD_ASYNC_IO_IN_PROGRESS
                    && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
                    LogRel(("SCSI#%u: Discard returned rc=%Rrc\n",
                            pThis->pDrvIns->iInstance, rc));
                break;
            }
            case VSCSIIOREQTXDIR_READ:
            case VSCSIIOREQTXDIR_WRITE:
            {
                uint64_t  uOffset    = 0;
                size_t    cbTransfer = 0;
                size_t    cbSeg      = 0;
                PCRTSGSEG paSeg      = NULL;
                unsigned  cSeg       = 0;

                rc = VSCSIIoReqParamsGet(hVScsiIoReq, &uOffset, &cbTransfer,
                                         &cSeg, &cbSeg, &paSeg);
                AssertRC(rc);

                if (enmTxDir == VSCSIIOREQTXDIR_READ)
                {
                    pThis->pLed->Asserted.s.fReading = pThis->pLed->Actual.s.fReading = 1;
                    rc = pThis->pDrvBlockAsync->pfnStartRead(pThis->pDrvBlockAsync, uOffset,
                                                             paSeg, cSeg, cbTransfer,
                                                             hVScsiIoReq);
                    STAM_REL_COUNTER_ADD(&pThis->StatBytesRead, cbTransfer);
                }
                else
                {
                    pThis->pLed->Asserted.s.fWriting = pThis->pLed->Actual.s.fWriting = 1;
                    rc = pThis->pDrvBlockAsync->pfnStartWrite(pThis->pDrvBlockAsync, uOffset,
                                                              paSeg, cSeg, cbTransfer,
                                                              hVScsiIoReq);
                    STAM_REL_COUNTER_ADD(&pThis->StatBytesWritten, cbTransfer);
                }

                if (   RT_FAILURE(rc)
                    && rc != VERR_VD_ASYNC_IO_IN_PROGRESS
                    && pThis->cErrors++ < MAX_LOG_REL_ERRORS)
                    LogRel(("SCSI#%u: %s at offset %llu (%u bytes left) returned rc=%Rrc\n",
                            pThis->pDrvIns->iInstance,
                            enmTxDir == VSCSIIOREQTXDIR_READ
                            ? "Read"
                            : "Write",
                            uOffset,
                            cbTransfer, rc));
                break;
            }
            default:
                AssertMsgFailed(("Invalid transfer direction %u\n", enmTxDir));
        }

        if (rc == VINF_VD_ASYNC_IO_FINISHED)
        {
            if (enmTxDir == VSCSIIOREQTXDIR_READ)
                pThis->pLed->Actual.s.fReading = 0;
            else if (enmTxDir == VSCSIIOREQTXDIR_WRITE)
                pThis->pLed->Actual.s.fWriting = 0;
            else
                AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));

            VSCSIIoReqCompleted(hVScsiIoReq, VINF_SUCCESS, false);
            rc = VINF_SUCCESS;
        }
        else if (rc == VERR_VD_ASYNC_IO_IN_PROGRESS)
            rc = VINF_SUCCESS;
        else if (RT_FAILURE(rc))
        {
            if (enmTxDir == VSCSIIOREQTXDIR_READ)
                pThis->pLed->Actual.s.fReading = 0;
            else if (enmTxDir == VSCSIIOREQTXDIR_WRITE)
                pThis->pLed->Actual.s.fWriting = 0;
            else
                AssertMsg(enmTxDir == VSCSIIOREQTXDIR_FLUSH, ("Invalid transfer direction %u\n", enmTxDir));

            VSCSIIoReqCompleted(hVScsiIoReq, rc, drvscsiIsRedoPossible(rc));
            rc = VINF_SUCCESS;
        }
        else
            AssertMsgFailed(("Invalid return code rc=%Rrc\n", rc));
    }
    else
    {
        /* I/O thread. */
        rc = RTReqQueueCallEx(pThis->hQueueRequests, NULL, 0, RTREQFLAGS_NO_WAIT,
                              (PFNRT)drvscsiProcessRequestOne, 2, pThis, hVScsiIoReq);
    }

    return rc;
}
Exemplo n.º 8
0
HRESULT Guest::taskCopyFileToGuest(GuestTask *aTask)
{
    LogFlowFuncEnter();

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    /*
     * Do *not* take a write lock here since we don't (and won't)
     * touch any class-specific data (of IGuest) here - only the member functions
     * which get called here can do that.
     */

    HRESULT rc = S_OK;

    try
    {
        ComObjPtr<Guest> pGuest = aTask->pGuest;

        /* Does our source file exist? */
        if (!RTFileExists(aTask->strSource.c_str()))
        {
            rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                 Guest::tr("Source file \"%s\" does not exist, or is not a file"),
                                                 aTask->strSource.c_str());
        }
        else
        {
            RTFILE fileSource;
            int vrc = RTFileOpen(&fileSource, aTask->strSource.c_str(),
                                 RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_WRITE);
            if (RT_FAILURE(vrc))
            {
                rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                     Guest::tr("Could not open source file \"%s\" for reading (%Rrc)"),
                                                     aTask->strSource.c_str(),  vrc);
            }
            else
            {
                uint64_t cbSize;
                vrc = RTFileGetSize(fileSource, &cbSize);
                if (RT_FAILURE(vrc))
                {
                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                         Guest::tr("Could not query file size of \"%s\" (%Rrc)"),
                                                         aTask->strSource.c_str(), vrc);
                }
                else
                {
                    com::SafeArray<IN_BSTR> args;
                    com::SafeArray<IN_BSTR> env;

                    /*
                     * Prepare tool command line.
                     */
                    char szOutput[RTPATH_MAX];
                    if (RTStrPrintf(szOutput, sizeof(szOutput), "--output=%s", aTask->strDest.c_str()) <= sizeof(szOutput) - 1)
                    {
                        /*
                         * Normalize path slashes, based on the detected guest.
                         */
                        Utf8Str osType = mData.mOSTypeId;
                        if (   osType.contains("Microsoft", Utf8Str::CaseInsensitive)
                            || osType.contains("Windows", Utf8Str::CaseInsensitive))
                        {
                            /* We have a Windows guest. */
                            RTPathChangeToDosSlashes(szOutput, true /* Force conversion. */);
                        }
                        else /* ... or something which isn't from Redmond ... */
                        {
                            RTPathChangeToUnixSlashes(szOutput, true /* Force conversion. */);
                        }

                        args.push_back(Bstr(szOutput).raw());             /* We want to write a file ... */
                    }
                    else
                    {
                        rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                             Guest::tr("Error preparing command line"));
                    }

                    ComPtr<IProgress> execProgress;
                    ULONG uPID;
                    if (SUCCEEDED(rc))
                    {
                        LogRel(("Copying file \"%s\" to guest \"%s\" (%u bytes) ...\n",
                                aTask->strSource.c_str(), aTask->strDest.c_str(), cbSize));
                        /*
                         * Okay, since we gathered all stuff we need until now to start the
                         * actual copying, start the guest part now.
                         */
                        rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
                                                           Bstr("Copying file to guest").raw(),
                                                           ComSafeArrayAsInParam(args),
                                                           ComSafeArrayAsInParam(env),
                                                           Bstr(aTask->strUserName).raw(),
                                                           Bstr(aTask->strPassword).raw(),
                                                           ExecuteProcessFlag_WaitForProcessStartOnly,
                                                           NULL, NULL,
                                                           execProgress.asOutParam(), &uPID);
                        if (FAILED(rc))
                            rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
                    }

                    if (SUCCEEDED(rc))
                    {
                        BOOL fCompleted = FALSE;
                        BOOL fCanceled = FALSE;
                        uint64_t cbTransferedTotal = 0;

                        SafeArray<BYTE> aInputData(_64K);
                        while (   SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
                               && !fCompleted)
                        {
                            size_t cbToRead = cbSize;
                            size_t cbRead = 0;
                            if (cbSize) /* If we have nothing to read, take a shortcut. */
                            {
                                /** @todo Not very efficient, but works for now. */
                                vrc = RTFileSeek(fileSource, cbTransferedTotal,
                                                 RTFILE_SEEK_BEGIN, NULL /* poffActual */);
                                if (RT_SUCCESS(vrc))
                                {
                                    vrc = RTFileRead(fileSource, (uint8_t*)aInputData.raw(),
                                                     RT_MIN(cbToRead, _64K), &cbRead);
                                    /*
                                     * Some other error occured? There might be a chance that RTFileRead
                                     * could not resolve/map the native error code to an IPRT code, so just
                                     * print a generic error.
                                     */
                                    if (RT_FAILURE(vrc))
                                    {
                                        rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                             Guest::tr("Could not read from file \"%s\" (%Rrc)"),
                                                                             aTask->strSource.c_str(), vrc);
                                        break;
                                    }
                                }
                                else
                                {
                                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                         Guest::tr("Seeking file \"%s\" failed; offset = %RU64 (%Rrc)"),
                                                                         aTask->strSource.c_str(), cbTransferedTotal, vrc);
                                    break;
                                }
                            }
                            /* Resize buffer to reflect amount we just have read.
                             * Size 0 is allowed! */
                            aInputData.resize(cbRead);

                            ULONG uFlags = ProcessInputFlag_None;
                            /* Did we reach the end of the content we want to transfer (last chunk)? */
                            if (   (cbRead < _64K)
                                /* Did we reach the last block which is exactly _64K? */
                                || (cbToRead - cbRead == 0)
                                /* ... or does the user want to cancel? */
                                || (   SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
                                    && fCanceled)
                               )
                            {
                                uFlags |= ProcessInputFlag_EndOfFile;
                            }

                            ULONG uBytesWritten = 0;
                            rc = pGuest->SetProcessInput(uPID, uFlags,
                                                         0 /* Infinite timeout */,
                                                         ComSafeArrayAsInParam(aInputData), &uBytesWritten);
                            if (FAILED(rc))
                            {
                                rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
                                break;
                            }

                            Assert(cbRead <= cbToRead);
                            Assert(cbToRead >= cbRead);
                            cbToRead -= cbRead;

                            cbTransferedTotal += uBytesWritten;
                            Assert(cbTransferedTotal <= cbSize);
                            aTask->pProgress->SetCurrentOperationProgress(cbTransferedTotal / (cbSize / 100.0));

                            /* End of file reached? */
                            if (cbToRead == 0)
                                break;

                            /* Did the user cancel the operation above? */
                            if (fCanceled)
                                break;

                            /* Progress canceled by Main API? */
                            if (   SUCCEEDED(execProgress->COMGETTER(Canceled(&fCanceled)))
                                && fCanceled)
                            {
                                rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                     Guest::tr("Copy operation of file \"%s\" was canceled on guest side"),
                                                                     aTask->strSource.c_str());
                                break;
                            }
                        }

                        if (SUCCEEDED(rc))
                        {
                            /*
                             * If we got here this means the started process either was completed,
                             * canceled or we simply got all stuff transferred.
                             */
                            ExecuteProcessStatus_T retStatus;
                            ULONG uRetExitCode;

                            rc = executeWaitForExit(uPID, execProgress, 0 /* No timeout */,
                                                    &retStatus, &uRetExitCode);
                            if (FAILED(rc))
                            {
                                rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
                            }
                            else
                            {
                                if (   uRetExitCode != 0
                                    || retStatus    != ExecuteProcessStatus_TerminatedNormally)
                                {
                                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                         Guest::tr("Guest process reported error %u (status: %u) while copying file \"%s\" to \"%s\""),
                                                                         uRetExitCode, retStatus, aTask->strSource.c_str(), aTask->strDest.c_str());
                                }
                            }
                        }

                        if (SUCCEEDED(rc))
                        {
                            if (fCanceled)
                            {
                                /*
                                 * In order to make the progress object to behave nicely, we also have to
                                 * notify the object with a complete event when it's canceled.
                                 */
                                aTask->pProgress->notifyComplete(VBOX_E_IPRT_ERROR,
                                                                COM_IIDOF(IGuest),
                                                                Guest::getStaticComponentName(),
                                                                Guest::tr("Copying file \"%s\" canceled"), aTask->strSource.c_str());
                            }
                            else
                            {
                                /*
                                 * Even if we succeeded until here make sure to check whether we really transfered
                                 * everything.
                                 */
                                if (   cbSize > 0
                                    && cbTransferedTotal == 0)
                                {
                                    /* If nothing was transfered but the file size was > 0 then "vbox_cat" wasn't able to write
                                     * to the destination -> access denied. */
                                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                         Guest::tr("Access denied when copying file \"%s\" to \"%s\""),
                                                                         aTask->strSource.c_str(), aTask->strDest.c_str());
                                }
                                else if (cbTransferedTotal < cbSize)
                                {
                                    /* If we did not copy all let the user know. */
                                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                         Guest::tr("Copying file \"%s\" failed (%u/%u bytes transfered)"),
                                                                         aTask->strSource.c_str(), cbTransferedTotal, cbSize);
                                }
                                else /* Yay, all went fine! */
                                    aTask->pProgress->notifyComplete(S_OK);
                            }
                        }
                    }
                }
                RTFileClose(fileSource);
            }
        }
    }
    catch (HRESULT aRC)
    {
        rc = aRC;
    }

    /* Clean up */
    aTask->rc = rc;

    LogFlowFunc(("rc=%Rhrc\n", rc));
    LogFlowFuncLeave();

    return VINF_SUCCESS;
}
Exemplo n.º 9
0
HRESULT Guest::taskCopyFileFromGuest(GuestTask *aTask)
{
    LogFlowFuncEnter();

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    /*
     * Do *not* take a write lock here since we don't (and won't)
     * touch any class-specific data (of IGuest) here - only the member functions
     * which get called here can do that.
     */

    HRESULT rc = S_OK;

    try
    {
        ComObjPtr<Guest> pGuest = aTask->pGuest;

        /* Does our source file exist? */
        BOOL fFileExists;
        rc = pGuest->FileExists(Bstr(aTask->strSource).raw(),
                                Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(),
                                &fFileExists);
        if (SUCCEEDED(rc))
        {
            if (!fFileExists)
                rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                     Guest::tr("Source file \"%s\" does not exist, or is not a file"),
                                                     aTask->strSource.c_str());
        }
        else
            rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);

        /* Query file size to make an estimate for our progress object. */
        if (SUCCEEDED(rc))
        {
            LONG64 lFileSize;
            rc = pGuest->FileQuerySize(Bstr(aTask->strSource).raw(),
                                       Bstr(aTask->strUserName).raw(), Bstr(aTask->strPassword).raw(),
                                       &lFileSize);
            if (FAILED(rc))
                rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);

            com::SafeArray<IN_BSTR> args;
            com::SafeArray<IN_BSTR> env;

            if (SUCCEEDED(rc))
            {
                /*
                 * Prepare tool command line.
                 */
                char szSource[RTPATH_MAX];
                if (RTStrPrintf(szSource, sizeof(szSource), "%s", aTask->strSource.c_str()) <= sizeof(szSource) - 1)
                {
                    /*
                     * Normalize path slashes, based on the detected guest.
                     */
                    Utf8Str osType = mData.mOSTypeId;
                    if (   osType.contains("Microsoft", Utf8Str::CaseInsensitive)
                        || osType.contains("Windows", Utf8Str::CaseInsensitive))
                    {
                        /* We have a Windows guest. */
                        RTPathChangeToDosSlashes(szSource, true /* Force conversion. */);
                    }
                    else /* ... or something which isn't from Redmond ... */
                    {
                        RTPathChangeToUnixSlashes(szSource, true /* Force conversion. */);
                    }

                    args.push_back(Bstr(szSource).raw()); /* Tell our cat tool which file to output. */
                }
                else
                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                         Guest::tr("Error preparing command line"));
            }

            ComPtr<IProgress> execProgress;
            ULONG uPID;
            if (SUCCEEDED(rc))
            {
                LogRel(("Copying file \"%s\" to host \"%s\" (%u bytes) ...\n",
                        aTask->strSource.c_str(), aTask->strDest.c_str(), lFileSize));

                /*
                 * Okay, since we gathered all stuff we need until now to start the
                 * actual copying, start the guest part now.
                 */
                rc = pGuest->executeAndWaitForTool(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
                                                   Bstr("Copying file to host").raw(),
                                                   ComSafeArrayAsInParam(args),
                                                   ComSafeArrayAsInParam(env),
                                                   Bstr(aTask->strUserName).raw(),
                                                   Bstr(aTask->strPassword).raw(),
                                                     ExecuteProcessFlag_WaitForProcessStartOnly
                                                   | ExecuteProcessFlag_WaitForStdOut,
                                                   NULL, NULL,
                                                   execProgress.asOutParam(), &uPID);
                if (FAILED(rc))
                    rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
            }

            if (SUCCEEDED(rc))
            {
                BOOL fCompleted = FALSE;
                BOOL fCanceled = FALSE;

                RTFILE hFileDest;
                int vrc = RTFileOpen(&hFileDest, aTask->strDest.c_str(),
                                     RTFILE_O_WRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE);
                if (RT_FAILURE(vrc))
                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                         Guest::tr("Unable to create/open destination file \"%s\", rc=%Rrc"),
                                                         aTask->strDest.c_str(), vrc);
                else
                {
                    size_t cbToRead = lFileSize;
                    size_t cbTransfered = 0;
                    while (   SUCCEEDED(execProgress->COMGETTER(Completed(&fCompleted)))
                           && !fCompleted)
                    {
                        SafeArray<BYTE> aOutputData;
                        rc = pGuest->GetProcessOutput(uPID, ProcessOutputFlag_None /* StdOut */,
                                                      0 /* No timeout. */,
                                                      _64K, ComSafeArrayAsOutParam(aOutputData));
                        if (SUCCEEDED(rc))
                        {
                            if (aOutputData.size())
                            {
                                vrc = RTFileWrite(hFileDest, aOutputData.raw(), aOutputData.size(), NULL /* No partial writes */);
                                if (RT_FAILURE(vrc))
                                {
                                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                         Guest::tr("Error writing to file \"%s\" (%u bytes left), rc=%Rrc"),
                                                                         aTask->strSource.c_str(), cbToRead, vrc);
                                    break;
                                }

                                Assert(cbToRead >= aOutputData.size());
                                cbToRead -= aOutputData.size();
                                cbTransfered += aOutputData.size();

                                aTask->pProgress->SetCurrentOperationProgress(cbTransfered / (lFileSize / 100.0));
                            }

                            /* Nothing read this time; try next round. */
                        }
                        else
                        {
                            rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
                            break;
                        }
                    }

                    RTFileClose(hFileDest);

                    if (SUCCEEDED(rc))
                    {
                        if (   cbTransfered
                            && (cbTransfered != lFileSize))
                        {
                            /*
                             * Only bitch about an unexpected end of a file when there already
                             * was data read from that file. If this was the very first read we can
                             * be (almost) sure that this file is not meant to be read by the specified user.
                             */
                            rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                 Guest::tr("Unexpected end of file \"%s\" (%u bytes total, %u bytes transferred)"),
                                                                 aTask->strSource.c_str(), lFileSize, cbTransfered);
                        }

                        if (SUCCEEDED(rc))
                            aTask->pProgress->notifyComplete(S_OK);
                    }
                }
            }
        }
    }
    catch (HRESULT aRC)
    {
        rc = aRC;
    }

    /* Clean up */
    aTask->rc = rc;

    LogFlowFunc(("rc=%Rhrc\n", rc));
    LogFlowFuncLeave();

    return VINF_SUCCESS;
}
Exemplo n.º 10
0
int DnDManager::addMessage(uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
{
    int rc = VINF_SUCCESS;
    switch (uMsg)
    {
        case DragAndDropSvc::HOST_DND_HG_EVT_ENTER:
        {
            clear();
            LogFlowFunc(("HOST_DND_HG_EVT_ENTER\n"));
            DO(("HOST_DND_HG_EVT_ENTER\n"));
            /* Verify parameter count and types. */
            if (   cParms != 7
                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
                || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
                || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
                || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
                || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
                || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
                || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                m_fOpInProcess = true;
                DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
                m_dndMessageQueue.append(pMessage);
            }
            break;
        }
        case DragAndDropSvc::HOST_DND_HG_EVT_MOVE:
        {
            LogFlowFunc(("HOST_DND_HG_EVT_MOVE\n"));
            DO(("HOST_DND_HG_EVT_MOVE\n"));
            /* Verify parameter count and types. */
            if (   cParms != 7
                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
                || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
                || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
                || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
                || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
                || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
                || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                m_fOpInProcess = true;
                DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
                m_dndMessageQueue.append(pMessage);
            }
            break;
        }
        case DragAndDropSvc::HOST_DND_HG_EVT_LEAVE:
        {
            LogFlowFunc(("HOST_DND_HG_EVT_LEAVE\n"));
            DO(("HOST_DND_HG_EVT_LEAVE\n"));

            /* Verify parameter count and types. */
            if (cParms != 0)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
                m_dndMessageQueue.append(pMessage);
            }
            m_fOpInProcess = false;
            break;
        }
        case DragAndDropSvc::HOST_DND_HG_EVT_DROPPED:
        {
            LogFlowFunc(("HOST_DND_HG_EVT_DROPPED\n"));
            DO(("HOST_DND_HG_EVT_DROPPED\n"));
            /* Verify parameter count and types. */
            if (   cParms != 7
                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
                || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* x-pos */
                || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* y-pos */
                || paParms[3].type != VBOX_HGCM_SVC_PARM_32BIT /* default action */
                || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* allowed actions */
                || paParms[5].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
                || paParms[6].type != VBOX_HGCM_SVC_PARM_32BIT /* size */)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
                m_dndMessageQueue.append(pMessage);
            }
            break;
        }
        case DragAndDropSvc::HOST_DND_HG_SND_DATA:
        {
            LogFlowFunc(("HOST_DND_HG_SND_DATA\n"));
            DO(("HOST_DND_HG_SND_DATA\n"));

            /* Verify parameter count and types. */
            if (   cParms != 5
                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */
                || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR   /* format */
                || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
                || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR   /* data */
                || paParms[4].type != VBOX_HGCM_SVC_PARM_32BIT /* data size */)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                DnDHGSendDataMessage *pMessage = new DnDHGSendDataMessage(uMsg, cParms, paParms, m_pfnProgressCallback, m_pvProgressUser);
                m_dndMessageQueue.append(pMessage);
            }
            break;
        }
#ifdef VBOX_WITH_DRAG_AND_DROP_GH
        case DragAndDropSvc::HOST_DND_GH_REQ_PENDING:
        {
            LogFlowFunc(("HOST_DND_GH_REQ_PENDING\n"));
            DO(("HOST_DND_GH_REQ_PENDING\n"));

            /* Verify parameter count and types. */
            if (   cParms != 1
                || paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* screen id */)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
                m_dndMessageQueue.append(pMessage);
            }
            break;
        }
        case DragAndDropSvc::HOST_DND_GH_EVT_DROPPED:
        {
            LogFlowFunc(("HOST_DND_GH_EVT_DROPPED\n"));
            DO(("HOST_DND_GH_EVT_DROPPED\n"));

            /* Verify parameter count and types. */
            if (   cParms != 3
                || paParms[0].type != VBOX_HGCM_SVC_PARM_PTR   /* format */
                || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* format size */
                || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* action */)
                rc = VERR_INVALID_PARAMETER;
            else
            {
                DnDGenericMessage *pMessage = new DnDGenericMessage(uMsg, cParms, paParms);
                m_dndMessageQueue.append(pMessage);
            }
            break;
        }
#endif
        default: rc = VERR_NOT_IMPLEMENTED; break;
    }

    return rc;
}
Exemplo n.º 11
0
/*
 * Some sort of host operation on an vboxfs_node has failed or it has been
 * deleted. Mark this node and any children as stale, deleting knowledge
 * about any which do not have active vnodes or children
 * This also handle deleting an inactive node that was already stale.
 */
static void
fvsnode_make_stale(struct vboxfs_node *node)
{
	struct vboxfs_node *np;
	int len;
	avl_index_t where;

	/*
	 * First deal with any children of a directory node.
	 * If a directory becomes stale, anything below it becomes stale too.
	 */
	if (!node->sf_is_stale && node->sf_type == VDIR) {
		len = strlen(node->sf_path);

		np = node;
		while ((np = AVL_NEXT(&sfnodes, node)) != NULL) {
			ASSERT(!n->sf_is_stale);

			/*
			 * quit when no longer seeing children of node
			 */
			if (n->sf_sffs != node->sf_sffs ||
			    strncmp(node->sf_path, n->sf_path, len) != 0 ||
			    n->sf_path[len] != '/')
				break;

			/*
			 * Either mark the child as stale or destroy it
			 */
			if (n->sf_vnode == NULL && n->sf_children == 0) {
				sfnode_destroy(n);
			} else {
				LogFlowFunc(("sffs_make_stale(%s) sub\n",
				    n->sf_path));
				sfnode_clear_dir_list(n);

				if (avl_find(&sfnodes, n, &where) == NULL)
					panic("sfnode_make_stale(%s)"
					    " not in sfnodes", n->sf_path);
				avl_remove(&sfnodes, n);
				n->sf_is_stale = 1;
				if (avl_find(&stale_sfnodes, n, &where) != NULL)
					panic("sffs_make_stale(%s) duplicates",
					    n->sf_path);
				avl_insert(&stale_sfnodes, n, where);
			}
		}
	}
	
	/*
	 * Now deal with the given node.
	 */
	if (node->sf_vnode == NULL && node->sf_children == 0) {
		sfnode_destroy(node);
	} else if (!node->sf_is_stale) {
		LogFlowFunc(("sffs_make_stale(%s)\n", node->sf_path));
		sfnode_clear_dir_list(node);
		if (node->sf_parent)
			sfnode_clear_dir_list(node->sf_parent);
		if (avl_find(&sfnodes, node, &where) == NULL)
			panic("sfnode_make_stale(%s) not in sfnodes",
			    node->sf_path);
		avl_remove(&sfnodes, node);
		node->sf_is_stale = 1;
		if (avl_find(&stale_sfnodes, node, &where) != NULL)
			panic("sffs_make_stale(%s) duplicates", node->sf_path);
		avl_insert(&stale_sfnodes, node, where);
	}
}
Exemplo n.º 12
0
status_t VBoxMouse::Start(const char *device, void *cookie)
{
#if 0
    status_t err;
    int rc;
    uint32_t fFeatures = 0;
    Log(("VBoxMouse::%s()\n", __FUNCTION__));

    rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
    if (RT_SUCCESS(rc))
        rc = VbglR3SetMouseStatus(fFeatures
                                  | VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
                                  | VMMDEV_MOUSE_NEW_PROTOCOL);
    if (!RT_SUCCESS(rc))
    {
        LogRel(("VBoxMouse: Error switching guest mouse into absolute mode: %d\n", rc));
        return B_DEVICE_NOT_FOUND;
    }

    err = fServiceThreadID = spawn_thread(_ServiceThreadNub,
                                          "VBoxMouse", B_NORMAL_PRIORITY, this);
    if (err >= B_OK)
    {
        resume_thread(fServiceThreadID);
        return B_OK;
    }
    else
        LogRel(("VBoxMouse: Error starting service thread: 0x%08lx\n",
                err));

    // release the mouse
    rc = VbglR3GetMouseStatus(&fFeatures, NULL, NULL);
    if (RT_SUCCESS(rc))
        rc = VbglR3SetMouseStatus(fFeatures
                                  & ~VMMDEV_MOUSE_GUEST_CAN_ABSOLUTE
                                  & ~VMMDEV_MOUSE_NEW_PROTOCOL);

    return B_ERROR;
#endif

    status_t err = B_OK;
    int rc;
    uint32_t fFeatures = 0;
    LogFlowFunc(("device=%s cookie=%p\n", device, cookie));

    rc = vboxMouseAcquire();
    if (RT_SUCCESS(rc))
    {
        err = fServiceThreadID = spawn_thread(_ServiceThreadNub, "VBoxMouse", B_NORMAL_PRIORITY, this);
        if (err >= B_OK)
        {
            resume_thread(fServiceThreadID);
            return B_OK;
        }
        else
            LogRel(("VBoxMouse::Start Error starting service thread: 0x%08lx\n", err));

        vboxMouseRelease();
        err = B_ERROR;
    }
    else
    {
        LogRel(("VBoxMouse::Start vboxMouseAcquire failed. rc=%d\n", rc));
        err = B_DEVICE_NOT_FOUND;
    }

    return err;
}
Exemplo n.º 13
0
STDMETHODIMP VBoxDnDDropTarget::Drop(IDataObject *pDataObject,
                                     DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
{
    AssertPtrReturn(pDataObject, E_INVALIDARG);
    AssertPtrReturn(pdwEffect, E_INVALIDARG);

#ifdef DEBUG
    LogFlowFunc(("mFormatEtc.cfFormat=%RI16 (%s), pDataObject=0x%p, grfKeyState=0x%x, x=%ld, y=%ld\n",
                 mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat),
                 pDataObject, grfKeyState, pt.x, pt.y));
#endif
    HRESULT hr = S_OK;

    if (mFormatEtc.cfFormat) /* Did we get a supported format yet? */
    {
        /* Make sure the data object's data format is still the same
         * as we got it in DragEnter(). */
        hr = pDataObject->QueryGetData(&mFormatEtc);
        AssertMsg(SUCCEEDED(hr),
                  ("Data format changed between DragEnter() and Drop(), cfFormat=%RI16 (%s), hr=%Rhrc\n",
                  mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat),
                  hr));
    }

    int rc = VINF_SUCCESS;

    if (SUCCEEDED(hr))
    {
        STGMEDIUM stgMed;
        hr = pDataObject->GetData(&mFormatEtc, &stgMed);
        if (SUCCEEDED(hr))
        {
            /*
             * First stage: Prepare the access to the storage medium.
             *              For now we only support HGLOBAL stuff.
             */
            PVOID pvData = NULL; /** @todo Put this in an own union? */

            switch (mFormatEtc.tymed)
            {
                case TYMED_HGLOBAL:
                    pvData = GlobalLock(stgMed.hGlobal);
                    if (!pvData)
                    {
                        LogFlowFunc(("Locking HGLOBAL storage failed with %Rrc\n",
                                     RTErrConvertFromWin32(GetLastError())));
                        rc = VERR_INVALID_HANDLE;
                        hr = E_INVALIDARG; /* Set special hr for OLE. */
                    }
                    break;

                default:
                    AssertMsgFailed(("Storage medium type %RI32 supported\n",
                                     mFormatEtc.tymed));
                    rc = VERR_NOT_SUPPORTED;
                    hr = DV_E_TYMED; /* Set special hr for OLE. */
                    break;
            }

            if (RT_SUCCESS(rc))
            {
                /* Second stage: Do the actual copying of the data object's data,
                                 based on the storage medium type. */
                switch (mFormatEtc.cfFormat)
                {
                    case CF_UNICODETEXT:
                    {
                        AssertPtr(pvData);
                        size_t cbSize = GlobalSize(pvData);
                        LogFlowFunc(("CF_UNICODETEXT 0x%p got %zu bytes\n", pvData, cbSize));
                        if (cbSize)
                        {
                            char *pszText = NULL;
                            rc = RTUtf16ToUtf8((PCRTUTF16)pvData, &pszText);
                            if (RT_SUCCESS(rc))
                            {
                                mpvData = (void *)pszText;
                                mcbData = strlen(pszText) + 1; /* Include termination. */

                                /* Note: Don't free data of pszText, mpvData now owns it. */
                            }
                        }

                        break;
                    }

                    case CF_TEXT:
                    {
                        AssertPtr(pvData);
                        size_t cbSize = GlobalSize(pvData);
                        LogFlowFunc(("CF_TEXT 0x%p got %zu bytes\n", pvData, cbSize));
                        if (cbSize)
                        {
                            char *pszText = NULL;
                            rc = RTStrCurrentCPToUtf8(&pszText, (char *)pvData);
                            if (RT_SUCCESS(rc))
                            {
                                mpvData = (void *)pszText;
                                mcbData = strlen(pszText) + 1; /* Include termination. */

                                /* Note: Don't free data of pszText, mpvData now owns it. */
                            }
                        }

                        break;
                    }

                    case CF_HDROP:
                    {
                        AssertPtr(pvData);

                        /* Convert to a string list, separated by \r\n. */
                        DROPFILES *pDropFiles = (DROPFILES *)pvData;
                        AssertPtr(pDropFiles);
                        bool fUnicode = RT_BOOL(pDropFiles->fWide);

                        /* Get the offset of the file list. */
                        Assert(pDropFiles->pFiles >= sizeof(DROPFILES));
                        /* Note: This is *not* pDropFiles->pFiles! DragQueryFile only
                         *       will work with the plain storage medium pointer! */
                        HDROP hDrop = (HDROP)(pvData);

                        /* First, get the file count. */
                        /** @todo Does this work on Windows 2000 / NT4? */
                        char *pszFiles = NULL;
                        uint32_t cchFiles = 0;
                        UINT cFiles = DragQueryFile(hDrop, UINT32_MAX /* iFile */,
                                                    NULL /* lpszFile */, 0 /* cchFile */);
                        LogFlowFunc(("CF_HDROP got %RU16 file(s)\n", cFiles));

                        for (UINT i = 0; i < cFiles; i++)
                        {
                            UINT cch = DragQueryFile(hDrop, i /* File index */,
                                                     NULL /* Query size first */,
                                                     0 /* cchFile */);
                            Assert(cch);

                            if (RT_FAILURE(rc))
                                break;

                            char *pszFile = NULL; /* UTF-8 version. */
                            UINT cchFile = 0;
                            if (fUnicode)
                            {
                                /* Allocate enough space (including terminator). */
                                WCHAR *pwszFile = (WCHAR *)RTMemAlloc((cch + 1) * sizeof(WCHAR));
                                if (pwszFile)
                                {
                                    cchFile = DragQueryFileW(hDrop, i /* File index */,
                                                             pwszFile, cch + 1 /* Include terminator */);
                                    AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n",
                                                               cchFile, cch));
                                    int rc2 = RTUtf16ToUtf8(pwszFile, &pszFile);
                                    AssertRC(rc2);
                                }
                                else
                                    rc = VERR_NO_MEMORY;
                            }
                            else /* ANSI */
                            {
                                /* Allocate enough space (including terminator). */
                                pszFile = (char *)RTMemAlloc((cch + 1) * sizeof(char));
                                if (pszFile)
                                {
                                    cchFile = DragQueryFileA(hDrop, i /* File index */,
                                                             pszFile, cchFile + 1 /* Include terminator */);
                                    AssertMsg(cchFile == cch, ("cchCopied (%RU16) does not match cchFile (%RU16)\n",
                                                               cchFile, cch));
                                }
                                else
                                    rc = VERR_NO_MEMORY;
                            }

                            if (RT_SUCCESS(rc))
                            {
                                LogFlowFunc(("\tFile: %s (cchFile=%RU32)\n",
                                             pszFile, cchFile));

                                rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */,
                                                     pszFile, cchFile);
                                if (RT_SUCCESS(rc))
                                    cchFiles += cchFile;
                            }

                            if (pszFile)
                                RTMemFree(pszFile);

                            if (RT_FAILURE(rc))
                                break;

                            /* Add separation between filenames.
                             * Note: Also do this for the last element of the list. */
                            rc = RTStrAAppendExN(&pszFiles, 1 /* cPairs */,
                                                 "\r\n", 2 /* Bytes */);
                            if (RT_SUCCESS(rc))
                                cchFiles += 2; /* Include \r\n */
                        }

                        if (RT_SUCCESS(rc))
                        {
                            cchFiles += 1; /* Add string termination. */
                            uint32_t cbFiles = cchFiles * sizeof(char);

                            LogFlowFunc(("cFiles=%u, cchFiles=%RU32, cbFiles=%RU32, pszFiles=0x%p\n",
                                         cFiles, cchFiles, cbFiles, pszFiles));

                            /* Translate the list into URI elements. */
                            DnDURIList lstURI;
                            rc = lstURI.AppendNativePathsFromList(pszFiles, cbFiles,
                                                                  DNDURILIST_FLAGS_ABSOLUTE_PATHS);
                            if (RT_SUCCESS(rc))
                            {
                                RTCString strRoot = lstURI.RootToString();
                                size_t cbRoot = strRoot.length() + 1; /* Include termination */

                                mpvData = RTMemAlloc(cbRoot);
                                if (mpvData)
                                {
                                    memcpy(mpvData, strRoot.c_str(), cbRoot);
                                    mcbData = cbRoot;
                                }
                                else
                                    rc = VERR_NO_MEMORY;
                            }
                        }

                        LogFlowFunc(("Building CF_HDROP list rc=%Rrc, pszFiles=0x%p, cFiles=%RU16, cchFiles=%RU32\n",
                                     rc, pszFiles, cFiles, cchFiles));

                        if (pszFiles)
                            RTStrFree(pszFiles);
                        break;
                    }

                    default:
                        /* Note: Should not happen due to the checks done in DragEnter(). */
                        AssertMsgFailed(("Format of type %RI16 (%s) not supported\n",
                                         mFormatEtc.cfFormat,
                                         VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat)));
                        hr = DV_E_CLIPFORMAT; /* Set special hr for OLE. */
                        break;
                }

                /*
                 * Third stage: Unlock + release access to the storage medium again.
                 */
                switch (mFormatEtc.tymed)
                {
                    case TYMED_HGLOBAL:
                        GlobalUnlock(stgMed.hGlobal);
                        break;

                    default:
                        AssertMsgFailed(("Really should not happen -- see init stage!\n"));
                        break;
                }
            }

            /* Release storage medium again. */
            ReleaseStgMedium(&stgMed);

            /* Signal waiters. */
            mDroppedRc = rc;
            RTSemEventSignal(hEventDrop);
        }
    }

    if (RT_SUCCESS(rc))
    {
        /* Note: pt is not used since we don't need to differentiate within our
         *       proxy window. */
        *pdwEffect = VBoxDnDDropTarget::GetDropEffect(grfKeyState, *pdwEffect);
    }
    else
        *pdwEffect = DROPEFFECT_NONE;

    if (mpWndParent)
        mpWndParent->hide();

    LogFlowFunc(("Returning with hr=%Rhrc (%Rrc), mFormatEtc.cfFormat=%RI16 (%s), *pdwEffect=%RI32\n",
                 hr, rc, mFormatEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(mFormatEtc.cfFormat),
                 *pdwEffect));

    return hr;
}
Exemplo n.º 14
0
STDMETHODIMP VBoxDnDDropTarget::DragEnter(IDataObject *pDataObject, DWORD grfKeyState,
                                          POINTL pt, DWORD *pdwEffect)
{
    AssertPtrReturn(pDataObject, E_INVALIDARG);
    AssertPtrReturn(pdwEffect, E_INVALIDARG);

    LogFlowFunc(("pDataObject=0x%p, grfKeyState=0x%x, x=%ld, y=%ld, dwEffect=%RU32\n",
                 pDataObject, grfKeyState, pt.x, pt.y, *pdwEffect));

    reset();

    /** @todo At the moment we only support one DnD format at a time. */

    /* Try different formats. CF_HDROP is the most common one, so start
     * with this. */
    FORMATETC fmtEtc = { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
    HRESULT hr = pDataObject->QueryGetData(&fmtEtc);
    if (hr == S_OK)
    {
        mFormats = "text/uri-list";
    }
    else
    {
        LogFlowFunc(("CF_HDROP not wanted, hr=%Rhrc\n", hr));

        /* So we couldn't retrieve the data in CF_HDROP format; try with
         * CF_UNICODETEXT + CF_TEXT formats now. Rest stays the same. */
        fmtEtc.cfFormat = CF_UNICODETEXT;
        hr = pDataObject->QueryGetData(&fmtEtc);
        if (hr == S_OK)
        {
            mFormats = "text/plain;charset=utf-8";
        }
        else
        {
            LogFlowFunc(("CF_UNICODETEXT not wanted, hr=%Rhrc\n", hr));

            fmtEtc.cfFormat = CF_TEXT;
            hr = pDataObject->QueryGetData(&fmtEtc);
            if (hr == S_OK)
            {
                mFormats = "text/plain;charset=utf-8";
            }
            else
            {
                LogFlowFunc(("CF_TEXT not wanted, hr=%Rhrc\n", hr));
                fmtEtc.cfFormat = 0; /* Mark it to not supported. */
            }
        }
    }

    /* Did we find a format that we support? */
    if (fmtEtc.cfFormat)
    {
        LogFlowFunc(("Found supported format %RI16 (%s)\n",
                     fmtEtc.cfFormat, VBoxDnDDataObject::ClipboardFormatToString(fmtEtc.cfFormat)));

        /* Make a copy of the FORMATETC structure so that we later can
         * use this for comparrison and stuff. */
        /** Note: The DVTARGETDEVICE member only is a shallow copy for now! */
        memcpy(&mFormatEtc, &fmtEtc, sizeof(FORMATETC));

        /* Which drop effect we're going to use? */
        /* Note: pt is not used since we don't need to differentiate within our
         *       proxy window. */
        *pdwEffect = VBoxDnDDropTarget::GetDropEffect(grfKeyState, *pdwEffect);
    }
    else
    {
        /* No or incompatible data -- so no drop effect required. */
        *pdwEffect = DROPEFFECT_NONE;

        switch (hr)
        {
            case ERROR_INVALID_FUNCTION:
            {
                LogRel(("DnD: Drag and drop format is not supported by VBoxTray\n"));

                /* Enumerate supported source formats. This shouldn't happen too often
                 * on day to day use, but still keep it in here. */
                IEnumFORMATETC *pEnumFormats;
                HRESULT hr2 = pDataObject->EnumFormatEtc(DATADIR_GET, &pEnumFormats);
                if (SUCCEEDED(hr2))
                {
                    LogRel(("DnD: The following formats were offered to us:\n"));

                    FORMATETC curFormatEtc;
                    while (pEnumFormats->Next(1, &curFormatEtc,
                                              NULL /* pceltFetched */) == S_OK)
                    {
                        WCHAR wszCfName[128]; /* 128 chars should be enough, rest will be truncated. */
                        hr2 = GetClipboardFormatNameW(curFormatEtc.cfFormat, wszCfName,
                                                      sizeof(wszCfName) / sizeof(WCHAR));
                        LogRel(("\tcfFormat=%RI16 (%s), tyMed=%RI32, dwAspect=%RI32, strCustomName=%ls, hr=%Rhrc\n",
                                curFormatEtc.cfFormat,
                                VBoxDnDDataObject::ClipboardFormatToString(curFormatEtc.cfFormat),
                                curFormatEtc.tymed,
                                curFormatEtc.dwAspect,
                                wszCfName, hr2));
                    }

                    pEnumFormats->Release();
                }

                break;
            }

            default:
                break;
        }
    }

    LogFlowFunc(("Returning cfFormat=%RI16, pdwEffect=%ld, hr=%Rhrc\n",
                 fmtEtc.cfFormat, *pdwEffect, hr));
    return hr;
}
/* static */
const char* VBoxDnDDataObject::ClipboardFormatToString(CLIPFORMAT fmt)
{
#ifdef VBOX_DND_DEBUG_FORMATS
    char szFormat[128];
    if (GetClipboardFormatName(fmt, szFormat, sizeof(szFormat)))
        LogFlowFunc(("wFormat=%RI16, szName=%s\n", fmt, szFormat));
#endif

    switch (fmt)
    {

    case 1:
        return "CF_TEXT";
    case 2:
        return "CF_BITMAP";
    case 3:
        return "CF_METAFILEPICT";
    case 4:
        return "CF_SYLK";
    case 5:
        return "CF_DIF";
    case 6:
        return "CF_TIFF";
    case 7:
        return "CF_OEMTEXT";
    case 8:
        return "CF_DIB";
    case 9:
        return "CF_PALETTE";
    case 10:
        return "CF_PENDATA";
    case 11:
        return "CF_RIFF";
    case 12:
        return "CF_WAVE";
    case 13:
        return "CF_UNICODETEXT";
    case 14:
        return "CF_ENHMETAFILE";
    case 15:
        return "CF_HDROP";
    case 16:
        return "CF_LOCALE";
    case 17:
        return "CF_DIBV5";
    case 18:
        return "CF_MAX";
    case 49158:
        return "FileName";
    case 49159:
        return "FileNameW";
    case 49161:
        return "DATAOBJECT";
    case 49171:
        return "Ole Private Data";
    case 49314:
        return "Shell Object Offsets";
    case 49316:
        return "File Contents";
    case 49317:
        return "File Group Descriptor";
    case 49323:
        return "Preferred Drop Effect";
    case 49380:
        return "Shell Object Offsets";
    case 49382:
        return "FileContents";
    case 49383:
        return "FileGroupDescriptor";
    case 49389:
        return "Preferred DropEffect";
    case 49268:
        return "Shell IDList Array";
    case 49619:
        return "RenPrivateFileAttachments";
    default:
        break;
    }

    return "unknown";
}
Exemplo n.º 16
0
HRESULT Guest::taskUpdateGuestAdditions(GuestTask *aTask)
{
    LogFlowFuncEnter();

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    /*
     * Do *not* take a write lock here since we don't (and won't)
     * touch any class-specific data (of IGuest) here - only the member functions
     * which get called here can do that.
     */

    HRESULT rc = S_OK;
    BOOL fCompleted;
    BOOL fCanceled;

    try
    {
        ComObjPtr<Guest> pGuest = aTask->pGuest;

        aTask->pProgress->SetCurrentOperationProgress(10);

        /*
         * Determine guest OS type and the required installer image.
         * At the moment only Windows guests are supported.
         */
        Utf8Str installerImage;
        Bstr osTypeId;
        if (   SUCCEEDED(pGuest->COMGETTER(OSTypeId(osTypeId.asOutParam())))
            && !osTypeId.isEmpty())
        {
            Utf8Str osTypeIdUtf8(osTypeId); /* Needed for .contains(). */
            if (   osTypeIdUtf8.contains("Microsoft", Utf8Str::CaseInsensitive)
                || osTypeIdUtf8.contains("Windows", Utf8Str::CaseInsensitive))
            {
                if (osTypeIdUtf8.contains("64", Utf8Str::CaseInsensitive))
                    installerImage = "VBOXWINDOWSADDITIONS_AMD64.EXE";
                else
                    installerImage = "VBOXWINDOWSADDITIONS_X86.EXE";
                /* Since the installers are located in the root directory,
                 * no further path processing needs to be done (yet). */
            }
            else /* Everything else is not supported (yet). */
                throw GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
                                                      Guest::tr("Detected guest OS (%s) does not support automatic Guest Additions updating, please update manually"),
                                                      osTypeIdUtf8.c_str());
        }
        else
            throw GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
                                                  Guest::tr("Could not detected guest OS type/version, please update manually"));
        Assert(!installerImage.isEmpty());

        /*
         * Try to open the .ISO file and locate the specified installer.
         */
        RTISOFSFILE iso;
        int vrc = RTIsoFsOpen(&iso, aTask->strSource.c_str());
        if (RT_FAILURE(vrc))
        {
            rc = GuestTask::setProgressErrorInfo(VBOX_E_FILE_ERROR, aTask->pProgress,
                                                 Guest::tr("Invalid installation medium detected: \"%s\""),
                                                 aTask->strSource.c_str());
        }
        else
        {
            uint32_t cbOffset;
            size_t cbLength;
            vrc = RTIsoFsGetFileInfo(&iso, installerImage.c_str(), &cbOffset, &cbLength);
            if (   RT_SUCCESS(vrc)
                && cbOffset
                && cbLength)
            {
                vrc = RTFileSeek(iso.file, cbOffset, RTFILE_SEEK_BEGIN, NULL);
                if (RT_FAILURE(vrc))
                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                         Guest::tr("Could not seek to setup file on installation medium \"%s\" (%Rrc)"),
                                                         aTask->strSource.c_str(), vrc);
            }
            else
            {
                switch (vrc)
                {
                    case VERR_FILE_NOT_FOUND:
                        rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                             Guest::tr("Setup file was not found on installation medium \"%s\""),
                                                             aTask->strSource.c_str());
                        break;

                    default:
                        rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                             Guest::tr("An unknown error (%Rrc) occured while retrieving information of setup file on installation medium \"%s\""),
                                                             vrc, aTask->strSource.c_str());
                        break;
                }
            }

            /* Specify the ouput path on the guest side. */
            Utf8Str strInstallerPath = "%TEMP%\\VBoxWindowsAdditions.exe";

            if (RT_SUCCESS(vrc))
            {
                /* Okay, we're ready to start our copy routine on the guest! */
                aTask->pProgress->SetCurrentOperationProgress(15);

                /* Prepare command line args. */
                com::SafeArray<IN_BSTR> args;
                com::SafeArray<IN_BSTR> env;

                args.push_back(Bstr("--output").raw());               /* We want to write a file ... */
                args.push_back(Bstr(strInstallerPath.c_str()).raw()); /* ... with this path. */

                if (SUCCEEDED(rc))
                {
                    ComPtr<IProgress> progressCat;
                    ULONG uPID;

                    /*
                     * Start built-in "vbox_cat" tool (inside VBoxService) to
                     * copy over/pipe the data into a file on the guest (with
                     * system rights, no username/password specified).
                     */
                    rc = pGuest->executeProcessInternal(Bstr(VBOXSERVICE_TOOL_CAT).raw(),
                                                          ExecuteProcessFlag_Hidden
                                                        | ExecuteProcessFlag_WaitForProcessStartOnly,
                                                        ComSafeArrayAsInParam(args),
                                                        ComSafeArrayAsInParam(env),
                                                        Bstr("").raw() /* Username. */,
                                                        Bstr("").raw() /* Password */,
                                                        5 * 1000 /* Wait 5s for getting the process started. */,
                                                        &uPID, progressCat.asOutParam(), &vrc);
                    if (FAILED(rc))
                    {
                        /* Errors which return VBOX_E_NOT_SUPPORTED can be safely skipped by the caller
                         * to silently fall back to "normal" (old) .ISO mounting. */

                        /* Due to a very limited COM error range we use vrc for a more detailed error
                         * lookup to figure out what went wrong. */
                        switch (vrc)
                        {
                            /* Guest execution service is not (yet) ready. This basically means that either VBoxService
                             * is not running (yet) or that the Guest Additions are too old (because VBoxService does not
                             * support the guest execution feature in this version). */
                            case VERR_NOT_FOUND:
                                LogRel(("Guest Additions seem not to be installed yet\n"));
                                rc = GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
                                                                     Guest::tr("Guest Additions seem not to be installed or are not ready to update yet"));
                                break;

                            /* Getting back a VERR_INVALID_PARAMETER indicates that the installed Guest Additions are supporting the guest
                             * execution but not the built-in "vbox_cat" tool of VBoxService (< 4.0). */
                            case VERR_INVALID_PARAMETER:
                                LogRel(("Guest Additions are installed but don't supported automatic updating\n"));
                                rc = GuestTask::setProgressErrorInfo(VBOX_E_NOT_SUPPORTED, aTask->pProgress,
                                                                     Guest::tr("Installed Guest Additions do not support automatic updating"));
                                break;

                            case VERR_TIMEOUT:
                                LogRel(("Guest was unable to start copying the Guest Additions setup within time\n"));
                                rc = GuestTask::setProgressErrorInfo(E_FAIL, aTask->pProgress,
                                                                     Guest::tr("Guest was unable to start copying the Guest Additions setup within time"));
                                break;

                            default:
                                rc = GuestTask::setProgressErrorInfo(E_FAIL, aTask->pProgress,
                                                                     Guest::tr("Error copying Guest Additions setup file to guest path \"%s\" (%Rrc)"),
                                                                     strInstallerPath.c_str(), vrc);
                                break;
                        }
                    }
                    else
                    {
                        LogRel(("Automatic update of Guest Additions started, using \"%s\"\n", aTask->strSource.c_str()));
                        LogRel(("Copying Guest Additions installer \"%s\" to \"%s\" on guest ...\n",
                                installerImage.c_str(), strInstallerPath.c_str()));
                        aTask->pProgress->SetCurrentOperationProgress(20);

                        /* Wait for process to exit ... */
                        SafeArray<BYTE> aInputData(_64K);
                        while (   SUCCEEDED(progressCat->COMGETTER(Completed(&fCompleted)))
                               && !fCompleted)
                        {
                            size_t cbRead;
                            /* cbLength contains remaining bytes of our installer file
                             * opened above to read. */
                            size_t cbToRead = RT_MIN(cbLength, _64K);
                            if (cbToRead)
                            {
                                vrc = RTFileRead(iso.file, (uint8_t*)aInputData.raw(), cbToRead, &cbRead);
                                if (   cbRead
                                    && RT_SUCCESS(vrc))
                                {
                                    /* Resize buffer to reflect amount we just have read. */
                                    if (cbRead > 0)
                                        aInputData.resize(cbRead);

                                    /* Did we reach the end of the content we want to transfer (last chunk)? */
                                    ULONG uFlags = ProcessInputFlag_None;
                                    if (   (cbRead < _64K)
                                        /* Did we reach the last block which is exactly _64K? */
                                        || (cbToRead - cbRead == 0)
                                        /* ... or does the user want to cancel? */
                                        || (   SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
                                            && fCanceled)
                                       )
                                    {
                                        uFlags |= ProcessInputFlag_EndOfFile;
                                    }

                                    /* Transfer the current chunk ... */
                                #ifdef DEBUG_andy
                                    LogRel(("Copying Guest Additions (%u bytes left) ...\n", cbLength));
                                #endif
                                    ULONG uBytesWritten;
                                    rc = pGuest->SetProcessInput(uPID, uFlags,
                                                                 10 * 1000 /* Wait 10s for getting the input data transfered. */,
                                                                 ComSafeArrayAsInParam(aInputData), &uBytesWritten);
                                    if (FAILED(rc))
                                    {
                                        rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
                                        break;
                                    }

                                    /* If task was canceled above also cancel the process execution. */
                                    if (fCanceled)
                                        progressCat->Cancel();

                                #ifdef DEBUG_andy
                                    LogRel(("Copying Guest Additions (%u bytes written) ...\n", uBytesWritten));
                                #endif
                                    Assert(cbLength >= uBytesWritten);
                                    cbLength -= uBytesWritten;
                                }
                                else if (RT_FAILURE(vrc))
                                {
                                    rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                         Guest::tr("Error while reading setup file \"%s\" (To read: %u, Size: %u) from installation medium (%Rrc)"),
                                                                         installerImage.c_str(), cbToRead, cbLength, vrc);
                                }
                            }

                            /* Internal progress canceled? */
                            if (   SUCCEEDED(progressCat->COMGETTER(Canceled(&fCanceled)))
                                && fCanceled)
                            {
                                aTask->pProgress->Cancel();
                                break;
                            }
                        }
                    }
                }
            }
            RTIsoFsClose(&iso);

            if (   SUCCEEDED(rc)
                && (   SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
                    && !fCanceled
                   )
               )
            {
                /*
                 * Installer was transferred successfully, so let's start it
                 * (with system rights).
                 */
                LogRel(("Preparing to execute Guest Additions update ...\n"));
                aTask->pProgress->SetCurrentOperationProgress(66);

                /* Prepare command line args for installer. */
                com::SafeArray<IN_BSTR> installerArgs;
                com::SafeArray<IN_BSTR> installerEnv;

                /** @todo Only Windows! */
                installerArgs.push_back(Bstr(strInstallerPath).raw()); /* The actual (internal) installer image (as argv[0]). */
                /* Note that starting at Windows Vista the lovely session 0 separation applies:
                 * This means that if we run an application with the profile/security context
                 * of VBoxService (system rights!) we're not able to show any UI. */
                installerArgs.push_back(Bstr("/S").raw());      /* We want to install in silent mode. */
                installerArgs.push_back(Bstr("/l").raw());      /* ... and logging enabled. */
                /* Don't quit VBoxService during upgrade because it still is used for this
                 * piece of code we're in right now (that is, here!) ... */
                installerArgs.push_back(Bstr("/no_vboxservice_exit").raw());
                /* Tell the installer to report its current installation status
                 * using a running VBoxTray instance via balloon messages in the
                 * Windows taskbar. */
                installerArgs.push_back(Bstr("/post_installstatus").raw());

                /*
                 * Start the just copied over installer with system rights
                 * in silent mode on the guest. Don't use the hidden flag since there
                 * may be pop ups the user has to process.
                 */
                ComPtr<IProgress> progressInstaller;
                ULONG uPID;
                rc = pGuest->executeProcessInternal(Bstr(strInstallerPath).raw(),
                                                    ExecuteProcessFlag_WaitForProcessStartOnly,
                                                    ComSafeArrayAsInParam(installerArgs),
                                                    ComSafeArrayAsInParam(installerEnv),
                                                    Bstr("").raw() /* Username */,
                                                    Bstr("").raw() /* Password */,
                                                    10 * 1000 /* Wait 10s for getting the process started */,
                                                    &uPID, progressInstaller.asOutParam(), &vrc);
                if (SUCCEEDED(rc))
                {
                    LogRel(("Guest Additions update is running ...\n"));

                    /* If the caller does not want to wait for out guest update process to end,
                     * complete the progress object now so that the caller can do other work. */
                    if (aTask->uFlags & AdditionsUpdateFlag_WaitForUpdateStartOnly)
                        aTask->pProgress->notifyComplete(S_OK);
                    else
                        aTask->pProgress->SetCurrentOperationProgress(70);

                    /* Wait until the Guest Additions installer finishes ... */
                    while (   SUCCEEDED(progressInstaller->COMGETTER(Completed(&fCompleted)))
                           && !fCompleted)
                    {
                        if (   SUCCEEDED(aTask->pProgress->COMGETTER(Canceled(&fCanceled)))
                            && fCanceled)
                        {
                            progressInstaller->Cancel();
                            break;
                        }
                        /* Progress canceled by Main API? */
                        if (   SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled)))
                            && fCanceled)
                        {
                            break;
                        }
                        RTThreadSleep(100);
                    }

                    ExecuteProcessStatus_T retStatus;
                    ULONG uRetExitCode, uRetFlags;
                    rc = pGuest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &retStatus);
                    if (SUCCEEDED(rc))
                    {
                        if (fCompleted)
                        {
                            if (uRetExitCode == 0)
                            {
                                LogRel(("Guest Additions update successful!\n"));
                                if (   SUCCEEDED(aTask->pProgress->COMGETTER(Completed(&fCompleted)))
                                    && !fCompleted)
                                    aTask->pProgress->notifyComplete(S_OK);
                            }
                            else
                            {
                                LogRel(("Guest Additions update failed (Exit code=%u, Status=%u, Flags=%u)\n",
                                        uRetExitCode, retStatus, uRetFlags));
                                rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                     Guest::tr("Guest Additions update failed with exit code=%u (status=%u, flags=%u)"),
                                                                     uRetExitCode, retStatus, uRetFlags);
                            }
                        }
                        else if (   SUCCEEDED(progressInstaller->COMGETTER(Canceled(&fCanceled)))
                                 && fCanceled)
                        {
                            LogRel(("Guest Additions update was canceled\n"));
                            rc = GuestTask::setProgressErrorInfo(VBOX_E_IPRT_ERROR, aTask->pProgress,
                                                                 Guest::tr("Guest Additions update was canceled by the guest with exit code=%u (status=%u, flags=%u)"),
                                                                 uRetExitCode, retStatus, uRetFlags);
                        }
                        else
                        {
                            LogRel(("Guest Additions update was canceled by the user\n"));
                        }
                    }
                    else
                        rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
                }
                else
                    rc = GuestTask::setProgressErrorInfo(rc, aTask->pProgress, pGuest);
            }
        }
    }
    catch (HRESULT aRC)
    {
        rc = aRC;
    }

    /* Clean up */
    aTask->rc = rc;

    LogFlowFunc(("rc=%Rhrc\n", rc));
    LogFlowFuncLeave();

    return VINF_SUCCESS;
}
void VBoxDnDDataObject::SetStatus(Status status)
{
    LogFlowFunc(("Setting status to %ld\n", status));
    mStatus = status;
}
Exemplo n.º 18
0
/**
 * Thread function to wait for and process seamless mode change
 * requests
 */
static DECLCALLBACK(int) VBoxSeamlessWorker(void *pInstance, bool volatile *pfShutdown)
{
    AssertPtrReturn(pInstance, VERR_INVALID_POINTER);
    LogFlowFunc(("pInstance=%p\n", pInstance));

    /*
     * Tell the control thread that it can continue
     * spawning services.
     */
    RTThreadUserSignal(RTThreadSelf());

    PVBOXSEAMLESSCONTEXT pCtx = (PVBOXSEAMLESSCONTEXT)pInstance;

    HANDLE gVBoxDriver = pCtx->pEnv->hDriver;
    VBoxGuestFilterMaskInfo maskInfo;
    DWORD cbReturned;
    BOOL fWasScreenSaverActive = FALSE, fRet;

    maskInfo.u32OrMask = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;
    maskInfo.u32NotMask = 0;
    if (!DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
    {
        DWORD dwErr = GetLastError();
        LogRel(("Seamless: DeviceIOControl(CtlMask) failed with %ld, exiting ...\n", dwErr));
        return RTErrConvertFromWin32(dwErr);
    }

    int rc = VINF_SUCCESS;

    for (;;)
    {
        /* wait for a seamless change event */
        VBoxGuestWaitEventInfo waitEvent;
        waitEvent.u32TimeoutIn = 5000;
        waitEvent.u32EventMaskIn = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;
        if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL))
        {
            /* are we supposed to stop? */
            if (*pfShutdown)
                break;

            /* did we get the right event? */
            if (waitEvent.u32EventFlagsOut & VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST)
            {
                /* We got at least one event. Read the requested resolution
                 * and try to set it until success. New events will not be seen
                 * but a new resolution will be read in this poll loop.
                 */
                for (;;)
                {
                    /* get the seamless change request */
                    VMMDevSeamlessChangeRequest seamlessChangeRequest = {0};
                    vmmdevInitRequest((VMMDevRequestHeader*)&seamlessChangeRequest, VMMDevReq_GetSeamlessChangeRequest);
                    seamlessChangeRequest.eventAck = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;

                    BOOL fSeamlessChangeQueried = DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_VMMREQUEST(sizeof(seamlessChangeRequest)), &seamlessChangeRequest, sizeof(seamlessChangeRequest),
                                                                 &seamlessChangeRequest, sizeof(seamlessChangeRequest), &cbReturned, NULL);
                    if (fSeamlessChangeQueried)
                    {
                        LogFlowFunc(("Mode changed to %d\n", seamlessChangeRequest.mode));

                        switch(seamlessChangeRequest.mode)
                        {
                        case VMMDev_Seamless_Disabled:
                            if (fWasScreenSaverActive)
                            {
                                LogRel(("Seamless: Re-enabling the screensaver\n"));
                                fRet = SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, TRUE, NULL, 0);
                                if (!fRet)
                                    LogRel(("Seamless: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %ld\n", GetLastError()));
                            }
                            PostMessage(g_hwndToolWindow, WM_VBOX_SEAMLESS_DISABLE, 0, 0);
                            break;

                        case VMMDev_Seamless_Visible_Region:
                            fRet = SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &fWasScreenSaverActive, 0);
                            if (!fRet)
                                LogRel(("Seamless: SystemParametersInfo SPI_GETSCREENSAVEACTIVE failed with %ld\n", GetLastError()));

                            if (fWasScreenSaverActive)
                                LogRel(("Seamless: Disabling the screensaver\n"));

                            fRet = SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, FALSE, NULL, 0);
                            if (!fRet)
                                LogRel(("Seamless: SystemParametersInfo SPI_SETSCREENSAVEACTIVE failed with %ld\n", GetLastError()));
                            PostMessage(g_hwndToolWindow, WM_VBOX_SEAMLESS_ENABLE, 0, 0);
                            break;

                        case VMMDev_Seamless_Host_Window:
                            break;

                        default:
                            AssertFailed();
                            break;
                        }
                        break;
                    }
                    else
                        LogRel(("Seamless: DeviceIoControl(ChangeReq) failed with %ld\n", GetLastError()));

                    if (*pfShutdown)
                        break;

                    /* sleep a bit to not eat too much CPU while retrying */
                    RTThreadSleep(10);
                }
            }
        }
        else
        {
            /* sleep a bit to not eat too much CPU in case the above call always fails */
            RTThreadSleep(10);
        }

        if (*pfShutdown)
            break;
    }

    maskInfo.u32OrMask = 0;
    maskInfo.u32NotMask = VMMDEV_EVENT_SEAMLESS_MODE_CHANGE_REQUEST;
    if (!DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
        LogRel(("Seamless: DeviceIOControl(CtlMask) failed with %ld\n", GetLastError()));

    LogFlowFuncLeaveRC(rc);
    return rc;
}
Exemplo n.º 19
0
/**
 * @callback_method_impl{FNIOMIOPORTOUT}
 */
PDMBOTHCBDECL(int) parallelIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
{
    PARALLELPORT *pThis = PDMINS_2_DATA(pDevIns, PPARALLELPORT);
    int           rc = VINF_SUCCESS;
    RT_NOREF_PV(pvUser);

    if (cb == 1)
    {
        uint8_t u8 = u32;

        Log2(("%s: port %#06x val %#04x\n", __FUNCTION__, uPort, u32));

        uPort &= 7;
        switch (uPort)
        {
        case 0:
#ifndef IN_RING3
            NOREF(u8);
            rc = VINF_IOM_R3_IOPORT_WRITE;
#else
            pThis->regData = u8;
            if (RT_LIKELY(pThis->pDrvHostParallelConnector))
            {
                LogFlowFunc(("Set data lines 0x%X\n", u8));
                rc = pThis->pDrvHostParallelConnector->pfnWrite(pThis->pDrvHostParallelConnector, &u8, 1, PDM_PARALLEL_PORT_MODE_SPP);
                AssertRC(rc);
            }
#endif
            break;
        case 1:
            break;
        case 2:
            /* Set the reserved bits to one */
            u8 |= (LPT_CONTROL_BIT6 | LPT_CONTROL_BIT7);
            if (u8 != pThis->regControl)
            {
#ifndef IN_RING3
                return VINF_IOM_R3_IOPORT_WRITE;
#else
                if (RT_LIKELY(pThis->pDrvHostParallelConnector))
                {
                    /* Set data direction. */
                    if (u8 & LPT_CONTROL_ENABLE_BIDIRECT)
                        rc = pThis->pDrvHostParallelConnector->pfnSetPortDirection(pThis->pDrvHostParallelConnector, false /* fForward */);
                    else
                        rc = pThis->pDrvHostParallelConnector->pfnSetPortDirection(pThis->pDrvHostParallelConnector, true /* fForward */);
                    AssertRC(rc);

                    u8 &= ~LPT_CONTROL_ENABLE_BIDIRECT; /* Clear bit. */

                    rc = pThis->pDrvHostParallelConnector->pfnWriteControl(pThis->pDrvHostParallelConnector, u8);
                    AssertRC(rc);
                }
                else
                    u8 &= ~LPT_CONTROL_ENABLE_BIDIRECT; /* Clear bit. */

                pThis->regControl = u8;
#endif
            }
            break;
        case 3:
#ifndef IN_RING3
            NOREF(u8);
            rc = VINF_IOM_R3_IOPORT_WRITE;
#else
            pThis->regEppAddr = u8;
            if (RT_LIKELY(pThis->pDrvHostParallelConnector))
            {
                LogFlowFunc(("Write EPP address 0x%X\n", u8));
                rc = pThis->pDrvHostParallelConnector->pfnWrite(pThis->pDrvHostParallelConnector, &u8, 1, PDM_PARALLEL_PORT_MODE_EPP_ADDR);
                AssertRC(rc);
            }
#endif
            break;
        case 4:
#ifndef IN_RING3
            NOREF(u8);
            rc = VINF_IOM_R3_IOPORT_WRITE;
#else
            pThis->regEppData = u8;
            if (RT_LIKELY(pThis->pDrvHostParallelConnector))
            {
                LogFlowFunc(("Write EPP data 0x%X\n", u8));
                rc = pThis->pDrvHostParallelConnector->pfnWrite(pThis->pDrvHostParallelConnector, &u8, 1, PDM_PARALLEL_PORT_MODE_EPP_DATA);
                AssertRC(rc);
            }
#endif
            break;
        case 5:
            break;
        case 6:
            break;
        case 7:
        default:
            break;
        }
    }
    else
        AssertMsgFailed(("Port=%#x cb=%d u32=%#x\n", uPort, cb, u32));

    return rc;
}
/**
 * Retrieves the data stored in this object and store the result in
 * pMedium.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 * @param   pMedium
 */
STDMETHODIMP VBoxDnDDataObject::GetData(FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
    AssertPtrReturn(pFormatEtc, DV_E_FORMATETC);
    AssertPtrReturn(pMedium, DV_E_FORMATETC);

    ULONG lIndex;
    if (!LookupFormatEtc(pFormatEtc, &lIndex)) /* Format supported? */
        return DV_E_FORMATETC;
    if (lIndex >= mcFormats) /* Paranoia. */
        return DV_E_FORMATETC;

    LogFlowFunc(("pFormatEtc=%p, pMedium=%p\n", pFormatEtc, pMedium));

    FORMATETC *pThisFormat = &mpFormatEtc[lIndex];
    AssertPtr(pThisFormat);

    STGMEDIUM *pThisMedium = &mpStgMedium[lIndex];
    AssertPtr(pThisMedium);

    HRESULT hr = DV_E_FORMATETC;

    LogFlowFunc(("mStatus=%ld\n", mStatus));
    if (mStatus == Dropping)
    {
        LogFlowFunc(("Waiting for event ...\n"));
        int rc2 = RTSemEventWait(mSemEvent, RT_INDEFINITE_WAIT);
        LogFlowFunc(("rc=%Rrc, mStatus=%ld\n", rc2, mStatus));
    }

    if (mStatus == Dropped)
    {
        LogFlowFunc(("cfFormat=%RI16, sFormat=%s, tyMed=%RU32, dwAspect=%RU32\n",
                     pThisFormat->cfFormat, VBoxDnDDataObject::ClipboardFormatToString(pFormatEtc->cfFormat),
                     pThisFormat->tymed, pThisFormat->dwAspect));
        LogFlowFunc(("Got strFormat=%s, pvData=%p, cbData=%RU32\n",
                     mstrFormat.c_str(), mpvData, mcbData));

        if (mstrFormat.equalsIgnoreCase("text/uri-list"))
        {
            RTCList<RTCString> lstFilesURI = RTCString((char*)mpvData, mcbData).split("\r\n");
            RTCList<RTCString> lstFiles;
            for (size_t i = 0; i < lstFilesURI.size(); i++)
            {
                /* Extract path from URI. */
                char *pszPath = RTUriPath(lstFilesURI.at(i).c_str());
                if (   pszPath
                    && strlen(pszPath) > 1)
                {
                    pszPath++; /** @todo Skip first '/' (part of URI). Correct? */
                    pszPath = RTPathChangeToDosSlashes(pszPath, false /* fForce */);
                    lstFiles.append(pszPath);
                }
            }
#ifdef DEBUG
            LogFlowFunc(("Files (%zu)\n", lstFiles.size()));
            for (size_t i = 0; i < lstFiles.size(); i++)
                LogFlowFunc(("\tFile: %s\n", lstFiles.at(i).c_str()));
#endif

#if 0
            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;
            }
            else
#endif
                 if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (pFormatEtc->cfFormat == CF_TEXT))
            {
                pMedium->hGlobal = GlobalAlloc(GHND, mcbData + 1);
                if (pMedium->hGlobal)
                {
                    /** @todo Not working yet -- needs URI to plain ASCII conversion. */

                    char *pcDst  = (char *)GlobalLock(pMedium->hGlobal);
                    memcpy(pcDst, mpvData, mcbData);
                    pcDst[mcbData] = '\0';
                    GlobalUnlock(pMedium->hGlobal);

                    hr = S_OK;
                }
            }
            else if (   (pFormatEtc->tymed & TYMED_HGLOBAL)
                     && (pFormatEtc->dwAspect == DVASPECT_CONTENT)
                     && (pFormatEtc->cfFormat == CF_HDROP))
            {
                int rc = VINF_SUCCESS;

                size_t cchFiles = 0; /* Number of ASCII characters. */
                for (size_t i = 0; i < lstFiles.size(); i++)
                {
                    cchFiles += strlen(lstFiles.at(i).c_str());
                    cchFiles += 1; /* Terminating '\0'. */
                }

                size_t cbBuf = sizeof(DROPFILES) + ((cchFiles + 1) * sizeof(RTUTF16));
                DROPFILES *pBuf = (DROPFILES *)RTMemAllocZ(cbBuf);
                if (pBuf)
                {
                    pBuf->pFiles = sizeof(DROPFILES);
                    pBuf->fWide = 1; /* We use unicode. Always. */

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

                    for (size_t i = 0; i < lstFiles.size() && RT_SUCCESS(rc); i++)
                    {
                        size_t cchCurFile;
                        PRTUTF16 pwszFile;
                        rc = RTStrToUtf16(lstFiles.at(i).c_str(), &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);
                    }

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

                        pMedium->tymed = TYMED_HGLOBAL;
                        pMedium->pUnkForRelease = NULL;
                        pMedium->hGlobal = GlobalAlloc(  GMEM_ZEROINIT
                                                       | GMEM_MOVEABLE
                                                       | GMEM_DDESHARE, cbBuf);
                        if (pMedium->hGlobal)
                        {
                            LPVOID pMem = GlobalLock(pMedium->hGlobal);
                            if (pMem)
                            {
                                memcpy(pMem, pBuf, cbBuf);
                                GlobalUnlock(pMedium->hGlobal);

                                hr = S_OK;
                            }
                        }
                    }

                    RTMemFree(pBuf);
                }
                else
                    rc = VERR_NO_MEMORY;

                if (RT_FAILURE(rc))
                    hr = DV_E_FORMATETC;
            }
        }
    }

    if (FAILED(hr))
    {
        LogFlowFunc(("Copying medium ...\n"));
        switch (pThisMedium->tymed)
        {

        case TYMED_HGLOBAL:
            pMedium->hGlobal = (HGLOBAL)OleDuplicateData(pThisMedium->hGlobal,
                                                         pThisFormat->cfFormat, NULL);
            break;

        default:
            break;
        }

        pMedium->tymed          = pThisFormat->tymed;
        pMedium->pUnkForRelease = NULL;
    }

    LogFlowFunc(("hr=%Rhrc\n", hr));
    return hr;
}
Exemplo n.º 21
0
/**
 * Construct a block driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
static DECLCALLBACK(int) drvscsiConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    int rc = VINF_SUCCESS;
    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    LogFlowFunc(("pDrvIns=%#p pCfg=%#p\n", pDrvIns, pCfg));
    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);

    /*
     * Initialize the instance data.
     */
    pThis->pDrvIns                              = pDrvIns;
    pThis->ISCSIConnector.pfnSCSIRequestSend    = drvscsiRequestSend;

    pDrvIns->IBase.pfnQueryInterface            = drvscsiQueryInterface;

    pThis->IPort.pfnQueryDeviceLocation         = drvscsiQueryDeviceLocation;
    pThis->IPortAsync.pfnTransferCompleteNotify = drvscsiTransferCompleteNotify;
    pThis->hQueueRequests                       = NIL_RTREQQUEUE;

    /* Query the SCSI port interface above. */
    pThis->pDevScsiPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMISCSIPORT);
    AssertMsgReturn(pThis->pDevScsiPort, ("Missing SCSI port interface above\n"), VERR_PDM_MISSING_INTERFACE);

    /* Query the optional LED interface above. */
    pThis->pLedPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS);
    if (pThis->pLedPort != NULL)
    {
        /* Get The Led. */
        rc = pThis->pLedPort->pfnQueryStatusLed(pThis->pLedPort, 0, &pThis->pLed);
        if (RT_FAILURE(rc))
            pThis->pLed = &pThis->Led;
    }
    else
        pThis->pLed = &pThis->Led;

    /*
     * Validate and read configuration.
     */
    if (!CFGMR3AreValuesValid(pCfg, "NonRotationalMedium\0Readonly\0"))
        return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
                                N_("SCSI configuration error: unknown option specified"));

    rc = CFGMR3QueryBoolDef(pCfg, "NonRotationalMedium", &pThis->fNonRotational, false);
    if (RT_FAILURE(rc))
        return PDMDRV_SET_ERROR(pDrvIns, rc,
                    N_("SCSI configuration error: failed to read \"NonRotationalMedium\" as boolean"));

    rc = CFGMR3QueryBoolDef(pCfg, "Readonly", &pThis->fReadonly, false);
    if (RT_FAILURE(rc))
        return PDMDRV_SET_ERROR(pDrvIns, rc,
                                N_("SCSI configuration error: failed to read \"Readonly\" as boolean"));

    /*
     * Try attach driver below and query it's block interface.
     */
    rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pThis->pDrvBase);
    AssertMsgReturn(RT_SUCCESS(rc), ("Attaching driver below failed rc=%Rrc\n", rc), rc);

    /*
     * Query the block and blockbios interfaces.
     */
    pThis->pDrvBlock = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIBLOCK);
    if (!pThis->pDrvBlock)
    {
        AssertMsgFailed(("Configuration error: No block interface!\n"));
        return VERR_PDM_MISSING_INTERFACE;
    }
    pThis->pDrvBlockBios = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIBLOCKBIOS);
    if (!pThis->pDrvBlockBios)
    {
        AssertMsgFailed(("Configuration error: No block BIOS interface!\n"));
        return VERR_PDM_MISSING_INTERFACE;
    }

    pThis->pDrvMount = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIMOUNT);

    /* Try to get the optional async block interface. */
    pThis->pDrvBlockAsync = PDMIBASE_QUERY_INTERFACE(pThis->pDrvBase, PDMIBLOCKASYNC);

    PDMBLOCKTYPE enmType = pThis->pDrvBlock->pfnGetType(pThis->pDrvBlock);
    if (enmType != PDMBLOCKTYPE_HARD_DISK)
        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_UNSUPPORTED_BLOCK_TYPE, RT_SRC_POS,
                                   N_("Only hard disks are currently supported as SCSI devices (enmType=%d)"),
                                   enmType);

    /* Create VSCSI device and LUN. */
    pThis->VScsiIoCallbacks.pfnVScsiLunMediumGetSize      = drvscsiGetSize;
    pThis->VScsiIoCallbacks.pfnVScsiLunReqTransferEnqueue = drvscsiReqTransferEnqueue;
    pThis->VScsiIoCallbacks.pfnVScsiLunGetFeatureFlags    = drvscsiGetFeatureFlags;

    rc = VSCSIDeviceCreate(&pThis->hVScsiDevice, drvscsiVScsiReqCompleted, pThis);
    AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create VSCSI device rc=%Rrc\n"), rc);
    rc = VSCSILunCreate(&pThis->hVScsiLun, VSCSILUNTYPE_SBC, &pThis->VScsiIoCallbacks,
                        pThis);
    AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create VSCSI LUN rc=%Rrc\n"), rc);
    rc = VSCSIDeviceLunAttach(pThis->hVScsiDevice, pThis->hVScsiLun, 0);
    AssertMsgReturn(RT_SUCCESS(rc), ("Failed to attached the LUN to the SCSI device\n"), rc);

    /* Register statistics counter. */
    /** @todo aeichner: Find a way to put the instance number of the attached
     * controller device when we support more than one controller of the same type.
     * At the moment we have the 0 hardcoded. */
    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesRead, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
                            "Amount of data read.", "/Devices/SCSI0/%d/ReadBytes", pDrvIns->iInstance);
    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatBytesWritten, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,
                            "Amount of data written.", "/Devices/SCSI0/%d/WrittenBytes", pDrvIns->iInstance);

    pThis->StatIoDepth = 0;

    PDMDrvHlpSTAMRegisterF(pDrvIns, (void *)&pThis->StatIoDepth, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_COUNT,
                            "Number of active tasks.", "/Devices/SCSI0/%d/IoDepth", pDrvIns->iInstance);

    if (!pThis->pDrvBlockAsync)
    {
        /* Create request queue. */
        rc = RTReqQueueCreate(&pThis->hQueueRequests);
        AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create request queue rc=%Rrc\n"), rc);
        /* Create I/O thread. */
        rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsiAsyncIOLoop,
                                   drvscsiAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO");
        AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n"), rc);

        LogRel(("SCSI#%d: using normal I/O\n", pDrvIns->iInstance));
    }
    else
        LogRel(("SCSI#%d: using async I/O\n", pDrvIns->iInstance));

    if (   pThis->pDrvBlock->pfnDiscard
        || (   pThis->pDrvBlockAsync
            && pThis->pDrvBlockAsync->pfnStartDiscard))
        LogRel(("SCSI#%d: Enabled UNMAP support\n"));

    return VINF_SUCCESS;
}
VBoxDnDDataObject::VBoxDnDDataObject(FORMATETC *pFormatEtc,
                                     STGMEDIUM *pStgMed, ULONG cFormats)
    : mStatus(Uninitialized),
      mRefCount(1),
      mcFormats(0),
      mpvData(NULL),
      mcbData(0)
{
    HRESULT hr;

    /* Make sure that there's enough room for our fixed formats. */
    ULONG cAllFormats = cFormats + 1;

    try
    {
        mpFormatEtc = new FORMATETC[cAllFormats];
        RT_BZERO(mpFormatEtc, sizeof(FORMATETC) * cAllFormats);
        mpStgMedium = new STGMEDIUM[cAllFormats];
        RT_BZERO(mpStgMedium, sizeof(STGMEDIUM) * cAllFormats);

        if (   pFormatEtc
            && pStgMed)
        {
            for (ULONG i = 0; i < cFormats; i++)
            {
                LogFlowFunc(("Format %RU32: cfFormat=%RI16, tyMed=%RU32, dwAspect=%RU32\n",
                             i, pFormatEtc[i].cfFormat, pFormatEtc[i].tymed, pFormatEtc[i].dwAspect));
                mpFormatEtc[i] = pFormatEtc[i];
                mpStgMedium[i] = pStgMed[i];
            }
        }

        hr = S_OK;
    }
    catch (std::bad_alloc &)
    {
        hr = E_OUTOFMEMORY;
    }

    if (SUCCEEDED(hr))
    {
        int rc2 = RTSemEventCreate(&mSemEvent);
        AssertRC(rc2);

        /* Most commonly used format. */
        RegisterFormat(&mpFormatEtc[cFormats], CF_HDROP);
        mpStgMedium[cFormats++].tymed = TYMED_HGLOBAL;
#if 0
        /* IStream. */
        RegisterFormat(&mpFormatEtc[cFormats++],
                       RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR));
        RegisterFormat(&mpFormatEtc[cFormats++],
                       RegisterClipboardFormat(CFSTR_FILECONTENTS),
                       TYMED_ISTREAM, 0 /* lIndex */);

        /* Required for e.g. Windows Media Player. */
        RegisterFormat(&mpFormatEtc[cFormats++],
                       RegisterClipboardFormat(CFSTR_FILENAME));
        RegisterFormat(&mpFormatEtc[cFormats++],
                       RegisterClipboardFormat(CFSTR_FILENAMEW));
        RegisterFormat(&mpFormatEtc[cFormats++],
                       RegisterClipboardFormat(CFSTR_SHELLIDLIST));
        RegisterFormat(&mpFormatEtc[cFormats++],
                       RegisterClipboardFormat(CFSTR_SHELLIDLISTOFFSET));
#endif
        mcFormats = cFormats;
        mStatus = Initialized;
    }

    LogFlowFunc(("cFormats=%RU32, hr=%Rhrc\n", cFormats, hr));
}
/**
 * Opens the USB device.
 *
 * @returns VBox status code.
 * @param   pProxyDev       The device instance.
 * @param   pszAddress      The unique device identifier.
 *                          The format of this string is "VendorId:ProducIt:Release:StaticPath".
 * @param   pvBackend       Backend specific pointer, unused for the solaris backend.
 */
static DECLCALLBACK(int) usbProxySolarisOpen(PUSBPROXYDEV pProxyDev, const char *pszAddress, void *pvBackend)
{
    PUSBPROXYDEVSOL pDevSol = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVSOL);

    LogFlowFunc((USBPROXY ":usbProxySolarisOpen pProxyDev=%p pszAddress=%s pvBackend=%p\n", pProxyDev, pszAddress, pvBackend));

    /*
     * Initialize our USB R3 lib.
     */
    int rc = USBLibInit();
    if (RT_SUCCESS(rc))
    {
        /*
         * Allocate and initialize the solaris backend data.
         */
        AssertCompile(PATH_MAX >= MAXPATHLEN);
        char szDeviceIdent[PATH_MAX+48];
        rc = RTStrPrintf(szDeviceIdent, sizeof(szDeviceIdent), "%s", pszAddress);
        if (RT_SUCCESS(rc))
        {
            rc = RTCritSectInit(&pDevSol->CritSect);
            if (RT_SUCCESS(rc))
            {
                /*
                 * Create wakeup pipe.
                 */
                rc = RTPipeCreate(&pDevSol->hPipeWakeupR, &pDevSol->hPipeWakeupW, 0);
                if (RT_SUCCESS(rc))
                {
                    int Instance;
                    char *pszDevicePath = NULL;
                    rc = USBLibGetClientInfo(szDeviceIdent, &pszDevicePath, &Instance);
                    if (RT_SUCCESS(rc))
                    {
                        pDevSol->pszDevicePath = pszDevicePath;

                        /*
                         * Open the client driver.
                         */
                        RTFILE hFile;
                        rc = RTFileOpen(&hFile, pDevSol->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
                        if (RT_SUCCESS(rc))
                        {
                            pDevSol->hFile = hFile;
                            pDevSol->pProxyDev = pProxyDev;

                            /*
                             * Verify client driver version.
                             */
                            VBOXUSBREQ_GET_VERSION GetVersionReq;
                            bzero(&GetVersionReq, sizeof(GetVersionReq));
                            rc = usbProxySolarisIOCtl(pDevSol, VBOXUSB_IOCTL_GET_VERSION, &GetVersionReq, sizeof(GetVersionReq));
                            if (RT_SUCCESS(rc))
                            {
                                if (   GetVersionReq.u32Major == VBOXUSB_VERSION_MAJOR
                                    && GetVersionReq.u32Minor >= VBOXUSB_VERSION_MINOR)
                                {
                                    /*
                                     * Try & get the current cached config from Solaris.
                                     */
                                    usbProxySolarisGetActiveConfig(pDevSol);
                                    return VINF_SUCCESS;
                                }
                                else
                                {
                                    LogRel((USBPROXY ":version mismatch! driver v%d.%d expecting ~v%d.%d\n", GetVersionReq.u32Major,
                                            GetVersionReq.u32Minor, VBOXUSB_VERSION_MAJOR, VBOXUSB_VERSION_MINOR));
                                    rc = VERR_VERSION_MISMATCH;
                                }
                            }
                            else
                                LogRel((USBPROXY ":failed to query driver version. rc=%Rrc\n", rc));

                            RTFileClose(pDevSol->hFile);
                            pDevSol->hFile = NIL_RTFILE;
                            pDevSol->pProxyDev = NULL;
                        }
                        else
                            LogRel((USBPROXY ":failed to open device. rc=%Rrc pszDevicePath=%s\n", rc, pDevSol->pszDevicePath));

                        RTStrFree(pDevSol->pszDevicePath);
                        pDevSol->pszDevicePath = NULL;
                    }
                    else
                    {
                        LogRel((USBPROXY ":failed to get client info. rc=%Rrc pszDevicePath=%s\n", rc, pDevSol->pszDevicePath));
                        if (rc == VERR_NOT_FOUND)
                            rc = VERR_OPEN_FAILED;
                    }
                    RTPipeClose(pDevSol->hPipeWakeupR);
                    RTPipeClose(pDevSol->hPipeWakeupW);
                }

                RTCritSectDelete(&pDevSol->CritSect);
            }
            else
                LogRel((USBPROXY ":RTCritSectInit failed. rc=%Rrc pszAddress=%s\n", rc, pszAddress));
        }
        else
            LogRel((USBPROXY ":RTStrAPrintf failed. rc=%Rrc pszAddress=%s\n", rc, pszAddress));
    }
    else
        LogRel((USBPROXY ":USBLibInit failed. rc=%Rrc\n", rc));

    USBLibTerm();
    return rc;
}
/**
 * Only required for IStream / IStorage interfaces.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 * @param   pMedium
 */
STDMETHODIMP VBoxDnDDataObject::GetDataHere(FORMATETC *pFormatEtc, STGMEDIUM *pMedium)
{
    LogFlowFunc(("\n"));
    return DATA_E_FORMATETC;
}
static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    AssertPtr(pCtx);

    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;

    LRESULT rc = 0;

    switch (msg)
    {
        case WM_CLIPBOARDUPDATE:
        {
           Log(("WM_CLIPBOARDUPDATE\n"));

           if (GetClipboardOwner() != hwnd)
           {
               /* Clipboard was updated by another application. */
               uint32_t uFormats;
               int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats);
               if (RT_SUCCESS(vboxrc))
                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
           }
        }
        break;

        case WM_CHANGECBCHAIN:
        {
           if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
           {
               rc = DefWindowProc(hwnd, msg, wParam, lParam);
               break;
           }

           HWND hWndRemoved = (HWND)wParam;
           HWND hWndNext    = (HWND)lParam;

           LogFlowFunc(("WM_CHANGECBCHAIN: hWndRemoved=%p, hWndNext=%p, hWnd=%p\n", hWndRemoved, hWndNext, pWinCtx->hWnd));

           if (hWndRemoved == pWinCtx->hWndNextInChain)
           {
               /* The window that was next to our in the chain is being removed.
                * Relink to the new next window. */
               pWinCtx->hWndNextInChain = hWndNext;
           }
           else
           {
               if (pWinCtx->hWndNextInChain)
               {
                   /* Pass the message further. */
                   DWORD_PTR dwResult;
                   rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
                                           VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult);
                   if (!rc)
                       rc = (LRESULT)dwResult;
               }
           }
        }
        break;

        case WM_DRAWCLIPBOARD:
        {
           LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));

           if (GetClipboardOwner() != hwnd)
           {
               /* Clipboard was updated by another application. */
               /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
               uint32_t uFormats;
               int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &uFormats);
               if (RT_SUCCESS(vboxrc))
                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
           }

           if (pWinCtx->hWndNextInChain)
           {
               /* Pass the message to next windows in the clipboard chain. */
               SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, NULL);
           }
        }
        break;

        case WM_TIMER:
        {
           if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
               break;

           HWND hViewer = GetClipboardViewer();

           /* Re-register ourselves in the clipboard chain if our last ping
            * timed out or there seems to be no valid chain. */
           if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)
           {
               VBoxClipboardWinRemoveFromCBChain(pWinCtx);
               VBoxClipboardWinAddToCBChain(pWinCtx);
           }

           /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
            * processed by ourselves to the chain. */
           pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;

           hViewer = GetClipboardViewer();
           if (hViewer)
               SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,
                                   VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);
        }
        break;

        case WM_CLOSE:
        {
           /* Do nothing. Ignore the message. */
        }
        break;

        case WM_RENDERFORMAT:
        {
           /* Insert the requested clipboard format data into the clipboard. */
           uint32_t fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;

           const UINT cfFormat = (UINT)wParam;
           switch (cfFormat)
           {
              case CF_UNICODETEXT:
                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
                  break;

              case CF_DIB:
                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
                  break;

#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
              case CF_HDROP:
                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
                  break;
#endif
              default:
                  if (cfFormat >= 0xC000) /** @todo r=andy Explain. */
                  {
                      TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */

                      int cActual = GetClipboardFormatName(cfFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
                      if (cActual)
                      {
                          if (strcmp(szFormatName, "HTML Format") == 0)
                              fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
                      }
                  }
                  break;
           }

           LogFunc(("WM_RENDERFORMAT: format=%u -> fFormat=0x%x\n", cfFormat, fFormat));

           if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE)
           {
               /* Unsupported clipboard format is requested. */
               LogRel(("Clipboard: Unsupported clipboard format requested (0x%x)\n", fFormat));
               VBoxClipboardWinClear();
           }
#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
           else if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
           {

           }
#endif
           else
           {
               const uint32_t cbPrealloc = _4K;
               uint32_t cb = 0;

               /* Preallocate a buffer, most of small text transfers will fit into it. */
               HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
               LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));

               if (hMem)
               {
                   void *pMem = GlobalLock(hMem);
                   LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));

                   if (pMem)
                   {
                       /* Read the host data to the preallocated buffer. */
                       int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
                       LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));

                       if (RT_SUCCESS(vboxrc))
                       {
                           if (cb == 0)
                           {
                               /* 0 bytes returned means the clipboard is empty.
                                * Deallocate the memory and set hMem to NULL to get to
                                * the clipboard empty code path. */
                               GlobalUnlock(hMem);
                               GlobalFree(hMem);
                               hMem = NULL;
                           }
                           else if (cb > cbPrealloc)
                           {
                               GlobalUnlock(hMem);

                               /* The preallocated buffer is too small, adjust the size. */
                               hMem = GlobalReAlloc(hMem, cb, 0);
                               LogFlowFunc(("Reallocated hMem = %p\n", hMem));

                               if (hMem)
                               {
                                   pMem = GlobalLock(hMem);
                                   LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));

                                   if (pMem)
                                   {
                                       /* Read the host data to the preallocated buffer. */
                                       uint32_t cbNew = 0;
                                       vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
                                       LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));

                                       if (RT_SUCCESS(vboxrc) && cbNew <= cb)
                                       {
                                           cb = cbNew;
                                       }
                                       else
                                       {
                                           GlobalUnlock(hMem);
                                           GlobalFree(hMem);
                                           hMem = NULL;
                                       }
                                   }
                                   else
                                   {
                                       GlobalFree(hMem);
                                       hMem = NULL;
                                   }
                               }
                           }

                           if (hMem)
                           {
                               /* pMem is the address of the data. cb is the size of returned data. */
                               /* Verify the size of returned text, the memory block for clipboard
                                * must have the exact string size.
                                */
                               if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                               {
                                   size_t cbActual = 0;
                                   HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
                                   if (FAILED(hrc))
                                   {
                                       /* Discard invalid data. */
                                       GlobalUnlock(hMem);
                                       GlobalFree(hMem);
                                       hMem = NULL;
                                   }
                                   else
                                   {
                                       /* cbActual is the number of bytes, excluding those used
                                        * for the terminating null character.
                                        */
                                       cb = (uint32_t)(cbActual + 2);
                                   }
                               }
                           }

                           if (hMem)
                           {
                               GlobalUnlock(hMem);

                               hMem = GlobalReAlloc(hMem, cb, 0);
                               LogFlowFunc(("Reallocated hMem = %p\n", hMem));

                               if (hMem)
                               {
                                   /* 'hMem' contains the host clipboard data.
                                    * size is 'cb' and format is 'format'. */
                                   HANDLE hClip = SetClipboardData(cfFormat, hMem);
                                   LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));

                                   if (hClip)
                                   {
                                       /* The hMem ownership has gone to the system. Finish the processing. */
                                       break;
                                   }

                                   /* Cleanup follows. */
                               }
                           }
                       }
                       if (hMem)
                           GlobalUnlock(hMem);
                   }
                   if (hMem)
                       GlobalFree(hMem);
               }

               /* Something went wrong. */
               VBoxClipboardWinClear();
           }
        }
        break;

        case WM_RENDERALLFORMATS:
        {
           /* Do nothing. The clipboard formats will be unavailable now, because the
            * windows is to be destroyed and therefore the guest side becomes inactive.
            */
           int vboxrc = VBoxClipboardWinOpen(hwnd);
           if (RT_SUCCESS(vboxrc))
           {
               VBoxClipboardWinClear();
               VBoxClipboardWinClose();
           }
        }
        break;

        case VBOX_CLIPBOARD_WM_SET_FORMATS:
        {
           /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
           VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;

           LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));

           int vboxrc = VBoxClipboardWinOpen(hwnd);
           if (RT_SUCCESS(vboxrc))
           {
               VBoxClipboardWinClear();

               HANDLE hClip = NULL;

               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                   hClip = SetClipboardData(CF_UNICODETEXT, NULL);

               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                   hClip = SetClipboardData(CF_DIB, NULL);

               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
               {
                   UINT format = RegisterClipboardFormat("HTML Format");
                   if (format != 0)
                       hClip = SetClipboardData(format, NULL);
               }

#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
                   hClip = SetClipboardData(CF_HDROP, NULL);
#endif

               /** @todo Implement more flexible clipboard precedence for supported formats. */

               if (hClip == NULL)
                   LogRel(("Clipboard: Unsupported format(s) from host (0x%x), ignoring\n", fFormats));

               VBoxClipboardWinClose();

               LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError()));
           }
        }
        break;

        case VBOX_CLIPBOARD_WM_READ_DATA:
        {
           /* Send data in the specified format to the host. */
           uint32_t u32Formats = (uint32_t)lParam;
           HANDLE hClip = NULL;

           LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));

           int vboxrc = VBoxClipboardWinOpen(hwnd);
           if (RT_SUCCESS(vboxrc))
           {
               if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
               {
                   hClip = GetClipboardData(CF_DIB);

                   if (hClip != NULL)
                   {
                       LPVOID lp = GlobalLock(hClip);
                       if (lp != NULL)
                       {
                           vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
                                                             lp, GlobalSize(hClip));
                           GlobalUnlock(hClip);
                       }
                       else
                       {
                           hClip = NULL;
                       }
                   }
               }
               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
               {
                   hClip = GetClipboardData(CF_UNICODETEXT);

                   if (hClip != NULL)
                   {
                       LPWSTR uniString = (LPWSTR)GlobalLock(hClip);

                       if (uniString != NULL)
                       {
                           vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
                                                             uniString, (lstrlenW(uniString) + 1) * 2);
                           GlobalUnlock(hClip);
                       }
                       else
                       {
                           hClip = NULL;
                       }
                   }
               }
               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
               {
                   UINT format = RegisterClipboardFormat("HTML Format");
                   if (format != 0)
                   {
                       hClip = GetClipboardData(format);
                       if (hClip != NULL)
                       {
                           LPVOID lp = GlobalLock(hClip);

                           if (lp != NULL)
                           {
                               vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
                                                                 lp, GlobalSize(hClip));
                               GlobalUnlock(hClip);
                           }
                           else
                           {
                               hClip = NULL;
                           }
                       }
                   }
               }
#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
               {
                   hClip = GetClipboardData(CF_HDROP);
                   if (hClip)
                   {
                       HDROP hDrop = (HDROP)GlobalLock(hClip);
                       if (hDrop)
                       {
       /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
                                                             );*/
                           GlobalUnlock(hClip);
                       }
                       else
                       {
                           hClip = NULL;
                       }
                   }
               }
#endif
               VBoxClipboardWinClose();
           }

           if (hClip == NULL)
           {
               /* Requested clipboard format is not available, send empty data. */
               VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);
           }
        }
        break;

        case WM_DESTROY:
        {
           VBoxClipboardWinRemoveFromCBChain(pWinCtx);
           if (pWinCtx->oldAPI.timerRefresh)
               KillTimer(pWinCtx->hWnd, 0);
           /*
            * don't need to call PostQuitMessage cause
            * the VBoxTray already finished a message loop
            */
        }
        break;

        default:
        {
           rc = DefWindowProc(hwnd, msg, wParam, lParam);
        }
        break;
    }

#ifndef DEBUG_andy
    LogFlowFunc(("vboxClipboardProcessMsg returned with rc = %ld\n", rc));
#endif
    return rc;
}
/**
 * Query if this objects supports a specific format.
 *
 * @return  IPRT status code.
 * @return  HRESULT
 * @param   pFormatEtc
 */
STDMETHODIMP VBoxDnDDataObject::QueryGetData(FORMATETC *pFormatEtc)
{
    LogFlowFunc(("\n"));
    return (LookupFormatEtc(pFormatEtc, NULL /* puIndex */)) ? S_OK : DV_E_FORMATETC;
}
/**
 * Called by Qt's drag'n drop operation (QDrag) for retrieving the actual drag'n drop
 * data in case of a successful drag'n drop operation.
 *
 * @param strMIMEType           MIME type string.
 * @param vaType                Variant containing the actual data based on the the MIME type.
 *
 * @return QVariant
 */
QVariant UIDnDMIMEData::retrieveData(const QString &strMIMEType, QVariant::Type vaType) const
{
    LogFlowFunc(("state=%RU32, curAction=0x%x, defAction=0x%x, mimeType=%s, type=%d (%s)\n",
                 m_enmState, m_curAction, m_defAction, strMIMEType.toStdString().c_str(), vaType, QVariant::typeToName(vaType)));

    bool fCanDrop = true; /* Accept by default. */

#ifdef RT_OS_WINDOWS
    /* 
     * On Windows this function will be called several times by Qt's
     * OLE-specific internals to figure out which data formats we have
     * to offer. So just assume we can drop data here for a start.
     */ 
#elif defined(RT_OS_DARWIN)
    /*
     * On OS X we rely on an internal flag which gets set in the overriden 
     * hasFormat() function. That function only gets called on a successful drop 
     * so that we can tell if we have to start receiving data the next time 
     * we come by here. 
     */
    fCanDrop = m_fCanDrop;
#else
    /* 
     * On non-Windows our state gets updated via an own event filter
     * (see UIDnDMimeData::eventFilter). This filter will update the current
     * operation state for us (based on the mouse buttons). 
     */ 
    if (m_curAction == Qt::IgnoreAction)
    {
        LogFlowFunc(("Current drop action is 0x%x, so can't drop yet\n", m_curAction));
        fCanDrop = false;
    }
#endif

    if (fCanDrop)
    {
        /* Do we support the requested MIME type? */
        if (!m_lstFormats.contains(strMIMEType))
        {
            LogRel(("DnD: Unsupported MIME type '%s'\n", strMIMEType.toStdString().c_str()));
            fCanDrop = false;
        }

        /* Supported types. See below in the switch statement. */
        if (!(
              /* Plain text. */
                 vaType == QVariant::String
              /* Binary data. */
              || vaType == QVariant::ByteArray
                 /* URI list. */
              || vaType == QVariant::List))
        {
            LogRel(("DnD: Unsupported data type '%s'\n", QVariant::typeToName(vaType)));
            fCanDrop = false;
        }
    }

    LogRel3(("DnD: State=%ld, Action=0x%x, fCanDrop=%RTbool\n", m_enmState, m_curAction, fCanDrop));

    if (fCanDrop)
    {
        QVariant vaData;
        int rc = emit getData(strMIMEType, vaType, vaData);

        LogRel3(("DnD: Returning data of type=%s (requested MIME type=%s, requested type=%s), rc=%Rrc\n",
                 vaData.typeName() ? vaData.typeName() : "<Invalid>",
                 strMIMEType.toStdString().c_str(),
                 QVariant::typeToName(vaType) ? QVariant::typeToName(vaType) : "<Invalid>", rc));

        if (RT_SUCCESS(rc))
            return vaData;
    }

#ifdef RT_OS_DARWIN
    LogFlowFunc(("Returning data for Cocoa\n"));
    return QMimeData::retrieveData(strMIMEType, vaType);
#else
    LogFlowFunc(("Skipping request, state=%RU32 ...\n", m_enmState));
    return QVariant(QVariant::Invalid); /* Return a NULL variant. */
#endif
}
int VBoxDnDDataObject::Abort(void)
{
    LogFlowFunc(("Aborting ...\n"));
    mStatus = Aborted;
    return RTSemEventSignal(mSemEvent);
}
Exemplo n.º 29
0
/**
 * Initializes the guest object.
 */
HRESULT Guest::init(Console *aParent)
{
    LogFlowThisFunc(("aParent=%p\n", aParent));

    ComAssertRet(aParent, E_INVALIDARG);

    /* Enclose the state transition NotReady->InInit->Ready */
    AutoInitSpan autoInitSpan(this);
    AssertReturn(autoInitSpan.isOk(), E_FAIL);

    unconst(mParent) = aParent;

    /* Confirm a successful initialization when it's the case */
    autoInitSpan.setSucceeded();

    ULONG aMemoryBalloonSize;
    HRESULT hr = mParent->i_machine()->COMGETTER(MemoryBalloonSize)(&aMemoryBalloonSize);
    if (hr == S_OK) /** @todo r=andy SUCCEEDED? */
        mMemoryBalloonSize = aMemoryBalloonSize;
    else
        mMemoryBalloonSize = 0; /* Default is no ballooning */

    BOOL fPageFusionEnabled;
    hr = mParent->i_machine()->COMGETTER(PageFusionEnabled)(&fPageFusionEnabled);
    if (hr == S_OK) /** @todo r=andy SUCCEEDED? */
        mfPageFusionEnabled = fPageFusionEnabled;
    else
        mfPageFusionEnabled = false; /* Default is no page fusion*/

    mStatUpdateInterval = 0; /* Default is not to report guest statistics at all */
    mCollectVMMStats = false;

    /* Clear statistics. */
    mNetStatRx = mNetStatTx = 0;
    mNetStatLastTs = RTTimeNanoTS();
    for (unsigned i = 0 ; i < GUESTSTATTYPE_MAX; i++)
        mCurrentGuestStat[i] = 0;
    mVmValidStats = pm::VMSTATMASK_NONE;
    RT_ZERO(mCurrentGuestCpuUserStat);
    RT_ZERO(mCurrentGuestCpuKernelStat);
    RT_ZERO(mCurrentGuestCpuIdleStat);

    mMagic = GUEST_MAGIC;
    int vrc = RTTimerLRCreate(&mStatTimer, 1000 /* ms */,
                              &Guest::i_staticUpdateStats, this);
    AssertMsgRC(vrc, ("Failed to create guest statistics update timer (%Rrc)\n", vrc));

    hr = unconst(mEventSource).createObject();
    if (SUCCEEDED(hr))
        hr = mEventSource->init();

    mCpus = 1;

#ifdef VBOX_WITH_DRAG_AND_DROP
    try
    {
        GuestDnD::createInstance(this /* pGuest */);
        hr = unconst(mDnDSource).createObject();
        if (SUCCEEDED(hr))
            hr = mDnDSource->init(this /* pGuest */);
        if (SUCCEEDED(hr))
        {
            hr = unconst(mDnDTarget).createObject();
            if (SUCCEEDED(hr))
                hr = mDnDTarget->init(this /* pGuest */);
        }

        LogFlowFunc(("Drag and drop initializied with hr=%Rhrc\n", hr));
    }
    catch (std::bad_alloc &)
    {
        hr = E_OUTOFMEMORY;
    }
#endif

    LogFlowFunc(("hr=%Rhrc\n", hr));
    return hr;
}
int vboxClipboardUtf16LinToWin(PRTUTF16 pwszSrc, size_t cwSrc, PRTUTF16 pu16Dest,
                               size_t cwDest)
{
    size_t i, j;
    LogFlowFunc(("pwszSrc=%.*ls, cwSrc=%u\n", cwSrc, pwszSrc, cwSrc));
    if (!VALID_PTR(pwszSrc) || !VALID_PTR(pu16Dest))
    {
        LogRel(("vboxClipboardUtf16LinToWin: received an invalid pointer, pwszSrc=%p, pu16Dest=%p, returning VERR_INVALID_PARAMETER\n", pwszSrc, pu16Dest));
        AssertReturn(VALID_PTR(pwszSrc) && VALID_PTR(pu16Dest), VERR_INVALID_PARAMETER);
    }
    if (cwSrc == 0)
    {
        if (cwDest == 0)
        {
            LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
            return VERR_BUFFER_OVERFLOW;
        }
        pu16Dest[0] = 0;
        LogFlowFunc(("empty source string, returning\n"));
        return VINF_SUCCESS;
    }
    /* We only take little endian Utf16 */
    if (pwszSrc[0] == UTF16BEMARKER)
    {
        LogRel(("vboxClipboardUtf16LinToWin: received a big endian Utf16 string, returning VERR_INVALID_PARAMETER\n"));
        AssertReturn(pwszSrc[0] != UTF16BEMARKER, VERR_INVALID_PARAMETER);
    }
    /* Don't copy the endian marker. */
    for (i = (pwszSrc[0] == UTF16LEMARKER ? 1 : 0), j = 0; i < cwSrc; ++i, ++j)
    {
        /* Don't copy the null byte, as we add it below. */
        if (pwszSrc[i] == 0)
            break;
        if (j == cwDest)
        {
            LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
            return VERR_BUFFER_OVERFLOW;
        }
        if (pwszSrc[i] == LINEFEED)
        {
            pu16Dest[j] = CARRIAGERETURN;
            ++j;
            if (j == cwDest)
            {
                LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
                return VERR_BUFFER_OVERFLOW;
            }
        }
#ifdef RT_OS_DARWIN
        /* Check for a single carriage return (MacOS) */
        else if (pwszSrc[i] == CARRIAGERETURN)
        {
            /* set cr */
            pu16Dest[j] = CARRIAGERETURN;
            ++j;
            if (j == cwDest)
            {
                LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
                return VERR_BUFFER_OVERFLOW;
            }
            /* add the lf */
            pu16Dest[j] = LINEFEED;
            continue;
        }
#endif
        pu16Dest[j] = pwszSrc[i];
    }
    /* Add the trailing null. */
    if (j == cwDest)
    {
        LogFlowFunc(("returning VERR_BUFFER_OVERFLOW\n"));
        return VERR_BUFFER_OVERFLOW;
    }
    pu16Dest[j] = 0;
    LogFlowFunc(("rc=VINF_SUCCESS, pu16Dest=%ls\n", pu16Dest));
    return VINF_SUCCESS;
}