/**
 * performs the "base" globals initialization
 * we separate the globals initialization to globals "base" initialization which is actually
 * "general" globals initialization except for Idc not being initialized, and idc initialization.
 * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
 * thus it's not possible to make idc initialization from the driver startup routine for it.
 *
 * @returns VBox status code.
 * @param   pGlobals    Pointer to the globals. */
DECLHIDDEN(int) vboxNetAdpInitGlobalsBase(PVBOXNETADPGLOBALS pGlobals)
{
    /*
     * Initialize the common portions of the structure.
     */
    int i;
    int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
    if (RT_SUCCESS(rc))
    {
        memset(pGlobals->aAdapters, 0, sizeof(pGlobals->aAdapters));
        for (i = 0; i < (int)RT_ELEMENTS(pGlobals->aAdapters); i++)
        {
            rc = vboxNetAdpSlotCreate(pGlobals, i, &pGlobals->aAdapters[i]);
            if (RT_FAILURE(rc))
            {
                /* Clean up. */
                while (--i >= 0)
                    vboxNetAdpSlotDestroy(&pGlobals->aAdapters[i]);
                Log(("vboxNetAdpInitGlobalsBase: Failed to create fast mutex (rc=%Rrc).\n", rc));
                RTSemFastMutexDestroy(pGlobals->hFastMtx);
                return rc;
            }
        }
        pGlobals->TrunkFactory.pfnRelease = vboxNetAdpFactoryRelease;
        pGlobals->TrunkFactory.pfnCreateAndConnect = vboxNetAdpFactoryCreateAndConnect;

        strcpy(pGlobals->SupDrvFactory.szName, "VBoxNetAdp");
        pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxNetAdpQueryFactoryInterface;
    }

    return rc;
}
示例#2
0
/**
 * Initializes the HGCM VBGL bits.
 *
 * @return VBox status code.
 */
int vbglR0HGCMTerminate (void)
{
    RTSemFastMutexDestroy(g_vbgldata.mutexHGCMHandle);
    g_vbgldata.mutexHGCMHandle = NIL_RTSEMFASTMUTEX;

    return VINF_SUCCESS;
}
示例#3
0
/**
 * @copydoc RAWPCIFACTORY::pfnInitVm
 */
static DECLCALLBACK(int)  vboxPciFactoryInitVm(PRAWPCIFACTORY       pFactory,
                                               PVM                  pVM,
                                               PRAWPCIPERVM         pVmData)
{
    PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)RTMemAllocZ(sizeof(VBOXRAWPCIDRVVM));
    int rc;

    if (!pThis)
         return VERR_NO_MEMORY;

    rc = RTSemFastMutexCreate(&pThis->hFastMtx);
    if (RT_SUCCESS(rc))
    {
        rc = vboxPciOsInitVm(pThis, pVM, pVmData);

        if (RT_SUCCESS(rc))
        {
#ifdef VBOX_WITH_IOMMU
            /* If IOMMU notification routine in pVmData->pfnContigMemInfo
               is set - we have functional IOMMU hardware. */
            if (pVmData->pfnContigMemInfo)
                pVmData->fVmCaps |= PCIRAW_VMFLAGS_HAS_IOMMU;
#endif
            pThis->pPerVmData = pVmData;
            pVmData->pDriverData = pThis;
            return VINF_SUCCESS;
        }

        RTSemFastMutexDestroy(pThis->hFastMtx);
        pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
        RTMemFree(pThis);
    }

    return rc;
}
示例#4
0
/**
 * @copydoc RAWPCIDEVPORT:: pfnDestroy
 */
static DECLCALLBACK(int) vboxPciDevDestroy(PRAWPCIDEVPORT pPort)
{
    PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
    int rc;

    rc = vboxPciOsDevDestroy(pThis);
    if (rc == VINF_SUCCESS)
    {
        if (pThis->hFastMtx)
        {
            RTSemFastMutexDestroy(pThis->hFastMtx);
            pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
        }

        if (pThis->hSpinlock)
        {
            RTSpinlockDestroy(pThis->hSpinlock);
            pThis->hSpinlock = NIL_RTSPINLOCK;
        }

        vboxPciGlobalsLock(pThis->pGlobals);
        vboxPciUnlinkInstanceLocked(pThis->pGlobals, pThis);
        vboxPciGlobalsUnlock(pThis->pGlobals);

        RTMemFree(pThis);
    }

    return rc;
}
示例#5
0
/**
 * Stop all service threads and free the device chain.
 */
USBProxyBackendUsbIp::~USBProxyBackendUsbIp()
{
    LogFlowThisFunc(("\n"));

    /*
     * Stop the service.
     */
    if (isActive())
        stop();

    /*
     * Free resources.
     */
    if (m->hPollSet != NIL_RTPOLLSET)
    {
        disconnect();

        int rc = RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_PIPE);
        AssertRC(rc);
        rc = RTPollSetDestroy(m->hPollSet);
        AssertRC(rc);
        rc = RTPipeClose(m->hWakeupPipeR);
        AssertRC(rc);
        rc = RTPipeClose(m->hWakeupPipeW);
        AssertRC(rc);
    }

    if (m->pszHost)
        RTStrFree(m->pszHost);
    if (m->hMtxDevices != NIL_RTSEMFASTMUTEX)
        RTSemFastMutexDestroy(m->hMtxDevices);

    delete m;
}
示例#6
0
VBOXDDU_DECL(void) VDDbgIoLogDestroy(VDIOLOGGER hIoLogger)
{
    PVDIOLOGGERINT pIoLogger = hIoLogger;

    AssertPtrReturnVoid(pIoLogger);

    vddbgIoLoggerHeaderUpdate(pIoLogger);
    RTFileFlush(pIoLogger->hFile);
    RTFileClose(pIoLogger->hFile);
    RTMemCacheDestroy(pIoLogger->hMemCacheIoLogEntries);
    RTSemFastMutexDestroy(pIoLogger->hMtx);
    RTMemFree(pIoLogger);
}
示例#7
0
/**
 * Deletes the globals.
 *
 *
 * @param   pGlobals        Pointer to the globals.
 */
DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
{
    Assert(!pGlobals->fIDCOpen);

    /*
     * Release resources.
     */
    if (pGlobals->hFastMtx)
    {
        RTSemFastMutexDestroy(pGlobals->hFastMtx);
        pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
    }
}
示例#8
0
/**
 * Initializes the object (called right after construction).
 *
 * @returns S_OK on success and non-fatal failures, some COM error otherwise.
 */
int USBProxyBackendUsbIp::init(void)
{
    int rc = VINF_SUCCESS;

    m = new Data;

    /** @todo: Pass in some config like host and port to connect to. */

    /* Setup wakeup pipe and poll set first. */
    rc = RTSemFastMutexCreate(&m->hMtxDevices);
    if (RT_SUCCESS(rc))
    {
        rc = RTPipeCreate(&m->hWakeupPipeR, &m->hWakeupPipeW, 0);
        if (RT_SUCCESS(rc))
        {
            rc = RTPollSetCreate(&m->hPollSet);
            if (RT_SUCCESS(rc))
            {
                rc = RTPollSetAddPipe(m->hPollSet, m->hWakeupPipeR,
                                      RTPOLL_EVT_READ, USBIP_POLL_ID_PIPE);
                if (RT_SUCCESS(rc))
                {
                    /* Connect to the USB/IP host. */
                    rc = reconnect();
                    if (RT_SUCCESS(rc))
                        rc = start(); /* Start service thread. */
                }

                if (RT_FAILURE(rc))
                {
                    RTPollSetRemove(m->hPollSet, USBIP_POLL_ID_PIPE);
                    int rc2 = RTPollSetDestroy(m->hPollSet);
                    AssertRC(rc2);
                }
            }

            if (RT_FAILURE(rc))
            {
                int rc2 = RTPipeClose(m->hWakeupPipeR);
                AssertRC(rc2);
                rc2 = RTPipeClose(m->hWakeupPipeW);
                AssertRC(rc2);
            }
        }
        if (RT_FAILURE(rc))
            RTSemFastMutexDestroy(m->hMtxDevices);
    }

    return rc;
}
示例#9
0
/**
 * Destroys the given VUSB sniffer instance.
 *
 * @returns nothing.
 * @param   hSniffer              The sniffer instance to destroy.
 */
DECLHIDDEN(void) VUSBSnifferDestroy(VUSBSNIFFER hSniffer)
{
    PVUSBSNIFFERINT pThis = hSniffer;

    int rc = RTSemFastMutexRequest(pThis->hMtx);
    AssertRC(rc);

    if (pThis->hFile != NIL_RTFILE)
        RTFileClose(pThis->hFile);
    if (pThis->pbBlockData)
        RTMemFree(pThis->pbBlockData);

    RTSemFastMutexRelease(pThis->hMtx);
    RTSemFastMutexDestroy(pThis->hMtx);
    RTMemFree(pThis);
}
/**
 * performs "base" globals deinitialization
 * we separate the globals settings "base" which is actually
 * "general" globals settings except for Idc, and idc.
 * This is needed for windows filter driver, which gets loaded prior to VBoxDrv,
 * thus it's not possible to make idc initialization from the driver startup routine for it,
 * though the "base is still needed for the driver to functions".
 * @param pGlobals
 * @return none
 */
DECLHIDDEN(void) vboxNetAdpDeleteGlobalsBase(PVBOXNETADPGLOBALS pGlobals)
{
    int i;
    /*
     * Release resources.
     */
    for (i = 0; i < (int)RT_ELEMENTS(pGlobals->aAdapters); i++)
        if (RT_SUCCESS(vboxNetAdpDestroy(&pGlobals->aAdapters[i])))
            vboxNetAdpSlotDestroy(&pGlobals->aAdapters[i]);

    RTSemFastMutexDestroy(pGlobals->hFastMtx);
    pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;

#ifdef VBOXNETADP_STATIC_CONFIG
    RTSemEventDestroy(pGlobals->hTimerEvent);
    pGlobals->hTimerEvent = NIL_RTSEMEVENT;
#endif

}
示例#11
0
DECLHIDDEN(void) vboxPciDevCleanup(PVBOXRAWPCIINS pThis)
{
    pThis->DevPort.pfnDeinit(&pThis->DevPort, 0);

    if (pThis->hFastMtx)
    {
        RTSemFastMutexDestroy(pThis->hFastMtx);
        pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
    }

    if (pThis->hSpinlock)
    {
        RTSpinlockDestroy(pThis->hSpinlock);
        pThis->hSpinlock = NIL_RTSPINLOCK;
    }

    vboxPciGlobalsLock(pThis->pGlobals);
    vboxPciUnlinkInstanceLocked(pThis->pGlobals, pThis);
    vboxPciGlobalsUnlock(pThis->pGlobals);
}
示例#12
0
/**
 * Terminates the VBoxUSB filter manager.
 */
void VBoxUSBFilterTerm(void)
{
#ifdef VBOXUSBFILTERMGR_USB_SPINLOCK
    RTSpinlockDestroy(g_Spinlock);
    g_Spinlock = NIL_RTSPINLOCK;
#else
    RTSemFastMutexDestroy(g_Mtx);
    g_Mtx = NIL_RTSEMFASTMUTEX;
#endif

    for (unsigned i = USBFILTERTYPE_FIRST; i < RT_ELEMENTS(g_aLists); i++)
    {
        PVBOXUSBFILTER pCur = g_aLists[i].pHead;
        g_aLists[i].pHead = g_aLists[i].pTail = NULL;
        while (pCur)
        {
            PVBOXUSBFILTER pNext = pCur->pNext;
            vboxUSBFilterFree(pCur);
            pCur = pNext;
        }
    }
}
示例#13
0
/**
 * @copydoc RAWPCIFACTORY::pfnDeinitVm
 */
static DECLCALLBACK(void)  vboxPciFactoryDeinitVm(PRAWPCIFACTORY       pFactory,
                                                  PVM                  pVM,
                                                  PRAWPCIPERVM         pPciData)
{
    if (pPciData->pDriverData)
    {
        PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)pPciData->pDriverData;

#ifdef VBOX_WITH_IOMMU
        /* If we have IOMMU, need to unmap all guest's physical pages from IOMMU on VM termination. */
#endif

        vboxPciOsDeinitVm(pThis, pVM);

        if (pThis->hFastMtx)
        {
            RTSemFastMutexDestroy(pThis->hFastMtx);
            pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
        }

        RTMemFree(pThis);
        pPciData->pDriverData = NULL;
    }
}
示例#14
0
static int renderSPUCleanup(void)
{
    renderspuVBoxCompositorClearAll();

    if (render_spu.blitterTable)
    {
        crFreeHashtable(render_spu.blitterTable, DeleteBlitterCallback);
        render_spu.blitterTable = NULL;
    }
    else
    {
        crHashtableWalk(render_spu.windowTable, renderspuBlitterCleanupCB, NULL);

        crHashtableWalk(render_spu.dummyWindowTable, renderspuBlitterCleanupCB, NULL);
    }

    renderspuSetDefaultSharedContext(NULL);

    crFreeHashtable(render_spu.contextTable, DeleteContextCallback);
    render_spu.contextTable = NULL;
    crFreeHashtable(render_spu.windowTable, DeleteWindowCallback);
    render_spu.windowTable = NULL;
    crFreeHashtable(render_spu.dummyWindowTable, DeleteWindowCallback);
    render_spu.dummyWindowTable = NULL;
    crFreeHashtable(render_spu.barrierHash, crFree);
    render_spu.barrierHash = NULL;

#ifdef RT_OS_DARWIN
# ifndef VBOX_WITH_COCOA_QT
    render_spu.fInit = false;
    DisposeEventHandlerUPP(render_spu.hParentEventHandler);
    ReleaseWindowGroup(render_spu.pMasterGroup);
    ReleaseWindowGroup(render_spu.pParentGroup);
    if (render_spu.hRootVisibleRegion)
    {
        DisposeRgn(render_spu.hRootVisibleRegion);
        render_spu.hRootVisibleRegion = 0;
    }
    render_spu.currentBufferName = 1;
    render_spu.uiDockUpdateTS = 0;
    RTSemFastMutexDestroy(render_spu.syncMutex);
# else /* VBOX_WITH_COCOA_QT */
# endif /* VBOX_WITH_COCOA_QT */
#endif /* RT_OS_DARWIN */

#ifdef RT_OS_WINDOWS
    if (render_spu.dwWinThreadId)
    {
        HANDLE hNative;

        hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE,
                             false, render_spu.dwWinThreadId);
        if (!hNative)
        {
            crWarning("Failed to get handle for window thread(%#x)", GetLastError());
        }

        if (PostThreadMessage(render_spu.dwWinThreadId, WM_QUIT, 0, 0))
        {
            WaitForSingleObject(render_spu.hWinThreadReadyEvent, INFINITE);

            /*wait for os thread to actually finish*/
            if (hNative && WaitForSingleObject(hNative, 3000)==WAIT_TIMEOUT)
            {
                crDebug("Wait failed, terminating");
                if (!TerminateThread(hNative, 1))
                {
                    crWarning("TerminateThread failed");
                }
            }
        }

        if (hNative)
        {
            CloseHandle(hNative);
        }
    }
    CloseHandle(render_spu.hWinThreadReadyEvent);
    render_spu.hWinThreadReadyEvent = NULL;
#endif

    crUnloadOpenGL();

#ifdef CHROMIUM_THREADSAFE
    crFreeTSD(&_RenderTSD);
#endif

    return 1;
}
示例#15
0
/**
 * Creates a new instance.
 *
 * @returns VBox status code.
 * @param   pGlobals            The globals.
 * @param   pszName             The instance name.
 * @param   ppDevPort           Where to store the pointer to our port interface.
 */
static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
                              uint32_t           u32HostAddress,
                              uint32_t           fFlags,
                              PRAWPCIPERVM       pVmCtx,
                              PRAWPCIDEVPORT     *ppDevPort,
                              uint32_t           *pfDevFlags)
{
    int             rc;
    PVBOXRAWPCIINS  pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
    if (!pNew)
        return VERR_NO_MEMORY;

    pNew->pGlobals                      = pGlobals;
    pNew->hSpinlock                     = NIL_RTSPINLOCK;
    pNew->cRefs                         = 1;
    pNew->pNext                         = NULL;
    pNew->HostPciAddress                = u32HostAddress;
    pNew->pVmCtx                        = pVmCtx;

    pNew->DevPort.u32Version            = RAWPCIDEVPORT_VERSION;

    pNew->DevPort.pfnInit               = vboxPciDevInit;
    pNew->DevPort.pfnDeinit             = vboxPciDevDeinit;
    pNew->DevPort.pfnDestroy            = vboxPciDevDestroy;
    pNew->DevPort.pfnGetRegionInfo      = vboxPciDevGetRegionInfo;
    pNew->DevPort.pfnMapRegion          = vboxPciDevMapRegion;
    pNew->DevPort.pfnUnmapRegion        = vboxPciDevUnmapRegion;
    pNew->DevPort.pfnPciCfgRead         = vboxPciDevPciCfgRead;
    pNew->DevPort.pfnPciCfgWrite        = vboxPciDevPciCfgWrite;
    pNew->DevPort.pfnPciCfgRead         = vboxPciDevPciCfgRead;
    pNew->DevPort.pfnPciCfgWrite        = vboxPciDevPciCfgWrite;
    pNew->DevPort.pfnRegisterIrqHandler = vboxPciDevRegisterIrqHandler;
    pNew->DevPort.pfnUnregisterIrqHandler = vboxPciDevUnregisterIrqHandler;
    pNew->DevPort.pfnPowerStateChange   = vboxPciDevPowerStateChange;
    pNew->DevPort.u32VersionEnd         = RAWPCIDEVPORT_VERSION;

    rc = RTSpinlockCreate(&pNew->hSpinlock);

    if (RT_SUCCESS(rc))
    {
        rc = RTSemFastMutexCreate(&pNew->hFastMtx);
        if (RT_SUCCESS(rc))
        {
            rc = pNew->DevPort.pfnInit(&pNew->DevPort, fFlags);
            if (RT_SUCCESS(rc))
            {
                *ppDevPort = &pNew->DevPort;

                pNew->pNext = pGlobals->pInstanceHead;
                pGlobals->pInstanceHead = pNew;
            }
            else
            {
                RTSemFastMutexDestroy(pNew->hFastMtx);
                RTSpinlockDestroy(pNew->hSpinlock);
                RTMemFree(pNew);
            }
        }
    }

    return rc;
}
示例#16
0
DECLHIDDEN(int) VUSBSnifferCreate(PVUSBSNIFFER phSniffer, uint32_t fFlags,
                                  const char *pszCaptureFilename, const char *pszDesc)
{
    int rc = VINF_SUCCESS;
    PVUSBSNIFFERINT pThis = NULL;

    pThis = (PVUSBSNIFFERINT)RTMemAllocZ(sizeof(VUSBSNIFFERINT));
    if (pThis)
    {
        pThis->hFile       = NIL_RTFILE;
        pThis->cbBlockCur  = 0;
        pThis->cbBlockMax  = 0;
        pThis->pbBlockData = NULL;
        pThis->hMtx        = NIL_RTSEMFASTMUTEX;

        rc = RTSemFastMutexCreate(&pThis->hMtx);
        if (RT_SUCCESS(rc))
        {
            rc = RTFileOpen(&pThis->hFile, pszCaptureFilename, RTFILE_O_DENY_NONE | RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_READ);
            if (RT_SUCCESS(rc))
            {
                /* Write header and link type blocks. */
                DumpFileShb Shb;

                Shb.Hdr.u32BlockType        = DUMPFILE_SHB_BLOCK_TYPE;
                Shb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
                Shb.u32ByteOrderMagic       = DUMPFILE_SHB_BYTE_ORDER_MAGIC;
                Shb.u16VersionMajor         = DUMPFILE_SHB_VERSION_MAJOR;
                Shb.u16VersionMinor         = DUMPFILE_SHB_VERSION_MINOR;
                Shb.u64SectionLength        = UINT64_C(0xffffffffffffffff); /* -1 */

                /* Write the blocks. */
                rc = vusbSnifferBlockNew(pThis, &Shb.Hdr, sizeof(Shb));
                if (RT_SUCCESS(rc))
                {
                    const char *pszOpt = RTBldCfgTargetDotArch();
                    rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_HARDWARE, pszOpt, strlen(pszOpt) + 1);
                }

                if (RT_SUCCESS(rc))
                {
                    char szTmp[512];
                    size_t cbTmp = sizeof(szTmp);

                    RT_ZERO(szTmp);

                    /* Build the OS code. */
                    rc = RTSystemQueryOSInfo(RTSYSOSINFO_PRODUCT, szTmp, cbTmp);
                    if (RT_SUCCESS(rc))
                    {
                        size_t cb = strlen(szTmp);

                        szTmp[cb] = ' ';
                        rc = RTSystemQueryOSInfo(RTSYSOSINFO_RELEASE, &szTmp[cb + 1], cbTmp - (cb + 1));
                        if (RT_SUCCESS(rc))
                        {
                            cb = strlen(szTmp);
                            szTmp[cb] = ' ';
                            rc = RTSystemQueryOSInfo(RTSYSOSINFO_VERSION, &szTmp[cb + 1], cbTmp - (cb + 1));
                        }
                    }

                    if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
                        rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_OS, szTmp, strlen(szTmp) + 1);
                    else
                        rc = VINF_SUCCESS; /* Skip OS code if building the string failed. */
                }

                if (RT_SUCCESS(rc))
                {
                    /** @todo: Add product info. */
                }

                if (RT_SUCCESS(rc))
                    rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
                if (RT_SUCCESS(rc))
                    rc = vusbSnifferBlockCommit(pThis);

                /* Write Interface descriptor block. */
                if (RT_SUCCESS(rc))
                {
                    DumpFileIdb Idb;

                    Idb.Hdr.u32BlockType        = DUMPFILE_IDB_BLOCK_TYPE;
                    Idb.Hdr.u32BlockTotalLength = 0; /* Filled out by lower layer. */
                    Idb.u16LinkType             = DUMPFILE_IDB_LINK_TYPE_USB_LINUX_MMAPED;
                    Idb.u16Reserved             = 0;
                    Idb.u32SnapLen              = UINT32_C(0xffffffff);

                    rc = vusbSnifferBlockNew(pThis, &Idb.Hdr, sizeof(Idb));
                    if (RT_SUCCESS(rc))
                    {
                        uint8_t u8TsResolution = 9; /* Nano second resolution. */
                        /* Add timestamp resolution option. */
                        rc = vusbSnifferAddOption(pThis, DUMPFILE_IDB_OPTION_TS_RESOLUTION,
                                                  &u8TsResolution, sizeof(u8TsResolution));
                    }
                    if (RT_SUCCESS(rc))
                        rc = vusbSnifferAddOption(pThis, DUMPFILE_OPTION_CODE_END, NULL, 0);
                    if (RT_SUCCESS(rc))
                        rc = vusbSnifferBlockCommit(pThis);
                }

                if (RT_SUCCESS(rc))
                {
                    *phSniffer = pThis;
                    return VINF_SUCCESS;
                }

                RTFileClose(pThis->hFile);
                pThis->hFile = NIL_RTFILE;
                RTFileDelete(pszCaptureFilename);
            }
            RTSemFastMutexDestroy(pThis->hMtx);
            pThis->hMtx = NIL_RTSEMFASTMUTEX;
        }
        RTMemFree(pThis);
    }
    else
        rc = VERR_NO_MEMORY;

    return rc;
}