int NetIfCreateHostOnlyNetworkInterface(VirtualBox *pVBox,
                                        IHostNetworkInterface **aHostNetworkInterface,
                                        IProgress **aProgress,
                                        const char *pcszName)
{
#if defined(RT_OS_LINUX) || defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD)
    /* create a progress object */
    ComObjPtr<Progress> progress;
    progress.createObject();

    ComPtr<IHost> host;
    HRESULT hrc = pVBox->COMGETTER(Host)(host.asOutParam());
    if (SUCCEEDED(hrc))
    {
        hrc = progress->init(pVBox, host,
                             Bstr("Creating host only network interface").raw(),
                             FALSE /* aCancelable */);
        if (SUCCEEDED(hrc))
        {
            progress.queryInterfaceTo(aProgress);

            char szAdpCtl[RTPATH_MAX];
            int rc = RTPathExecDir(szAdpCtl, sizeof(szAdpCtl) - sizeof("/" VBOXNETADPCTL_NAME " add"));
            if (RT_FAILURE(rc))
            {
                progress->notifyComplete(E_FAIL,
                                         COM_IIDOF(IHostNetworkInterface),
                                         HostNetworkInterface::getStaticComponentName(),
                                         "Failed to get program path, rc=%Rrc\n", rc);
                return rc;
            }
            strcat(szAdpCtl, "/" VBOXNETADPCTL_NAME " ");
            if (pcszName && strlen(pcszName) <= RTPATH_MAX - strlen(szAdpCtl) - sizeof(" add"))
            {
                strcat(szAdpCtl, pcszName);
                strcat(szAdpCtl, " add");
            }
            else
                strcat(szAdpCtl, "add");
            FILE *fp = popen(szAdpCtl, "r");

            if (fp)
            {
                char szBuf[VBOXNET_MAX_SHORT_NAME];
                if (fgets(szBuf, sizeof(szBuf), fp))
                {
                    char *pLast = szBuf + strlen(szBuf) - 1;
                    if (pLast >= szBuf && *pLast == '\n')
                        *pLast = 0;

                    size_t cbNameLen = strlen(szBuf) + 1;
                    PNETIFINFO pInfo = (PNETIFINFO)RTMemAllocZ(RT_OFFSETOF(NETIFINFO, szName[cbNameLen]));
                    if (!pInfo)
                        rc = VERR_NO_MEMORY;
                    else
                    {
                        strcpy(pInfo->szShortName, szBuf);
                        strcpy(pInfo->szName, szBuf);
                        rc = NetIfGetConfigByName(pInfo);
                        if (RT_FAILURE(rc))
                        {
                            progress->notifyComplete(E_FAIL,
                                                     COM_IIDOF(IHostNetworkInterface),
                                                     HostNetworkInterface::getStaticComponentName(),
                                                     "Failed to get config info for %s (as reported by '" VBOXNETADPCTL_NAME " add')\n", szBuf);
                        }
                        else
                        {
                            Bstr IfName(szBuf);
                            /* create a new uninitialized host interface object */
                            ComObjPtr<HostNetworkInterface> iface;
                            iface.createObject();
                            iface->init(IfName, HostNetworkInterfaceType_HostOnly, pInfo);
                            iface->setVirtualBox(pVBox);
                            iface.queryInterfaceTo(aHostNetworkInterface);
                        }
                        RTMemFree(pInfo);
                    }
                }
                if ((rc = pclose(fp)) != 0)
                {
                    progress->notifyComplete(E_FAIL,
                                             COM_IIDOF(IHostNetworkInterface),
                                             HostNetworkInterface::getStaticComponentName(),
                                             "Failed to execute '"VBOXNETADPCTL_NAME " add' (exit status: %d)", rc);
                    rc = VERR_INTERNAL_ERROR;
                }
            }
            if (RT_SUCCESS(rc))
                progress->notifyComplete(rc);
        }
    }

    return hrc;

#else
    NOREF(pVBox);
    NOREF(aHostNetworkInterface);
    NOREF(aProgress);
    return VERR_NOT_IMPLEMENTED;
#endif
}
Example #2
0
/**
 * Verifies the manifest and its signature.
 *
 * @returns VBox status code, failures with message.
 * @param   hOurManifest    The manifest we compiled.
 * @param   hManifestFile   The manifest file in the extension pack.
 * @param   hSignatureFile  The manifest signature file.
 * @param   pszError            Where to store an error message on failure.
 * @param   cbError             The size of the buffer @a pszError points to.
 */
static int vboxExtPackVerifyManifestAndSignature(RTMANIFEST hOurManifest, RTVFSFILE hManifestFile, RTVFSFILE hSignatureFile,
                                                 char *pszError, size_t cbError)
{
    /*
     * Read the manifest from the extension pack.
     */
    int rc = RTVfsFileSeek(hManifestFile, 0, RTFILE_SEEK_BEGIN, NULL);
    if (RT_FAILURE(rc))
        return vboxExtPackReturnError(rc, pszError, cbError, "RTVfsFileSeek failed: %Rrc", rc);

    RTMANIFEST hTheirManifest;
    rc = RTManifestCreate(0 /*fFlags*/, &hTheirManifest);
    if (RT_FAILURE(rc))
        return vboxExtPackReturnError(rc, pszError, cbError, "RTManifestCreate failed: %Rrc", rc);

    RTVFSIOSTREAM hVfsIos = RTVfsFileToIoStream(hManifestFile);
    rc = RTManifestReadStandard(hTheirManifest, hVfsIos);
    RTVfsIoStrmRelease(hVfsIos);
    if (RT_SUCCESS(rc))
    {
        /*
         * Compare the manifests.
         */
        static const char *s_apszIgnoreEntries[] =
        {
            VBOX_EXTPACK_MANIFEST_NAME,
            VBOX_EXTPACK_SIGNATURE_NAME,
            "./" VBOX_EXTPACK_MANIFEST_NAME,
            "./" VBOX_EXTPACK_SIGNATURE_NAME,
            NULL
        };
        char szError[RTPATH_MAX];
        rc = RTManifestEqualsEx(hOurManifest, hTheirManifest, &s_apszIgnoreEntries[0], NULL,
                                RTMANIFEST_EQUALS_IGN_MISSING_ATTRS /*fFlags*/,
                                szError, sizeof(szError));
        if (RT_SUCCESS(rc))
        {
            /*
             * Validate the manifest file signature.
             */
            /** @todo implement signature stuff */
            NOREF(hSignatureFile);

        }
        else if (rc == VERR_NOT_EQUAL && szError[0])
            vboxExtPackSetError(pszError, cbError, "Manifest mismatch: %s", szError);
        else
            vboxExtPackSetError(pszError, cbError, "RTManifestEqualsEx failed: %Rrc", rc);
#if 0
        RTVFSIOSTREAM hVfsIosStdOut = NIL_RTVFSIOSTREAM;
        RTVfsIoStrmFromStdHandle(RTHANDLESTD_OUTPUT, RTFILE_O_WRITE, true, &hVfsIosStdOut);
        RTVfsIoStrmWrite(hVfsIosStdOut, "Our:\n", sizeof("Our:\n") - 1, true, NULL);
        RTManifestWriteStandard(hOurManifest, hVfsIosStdOut);
        RTVfsIoStrmWrite(hVfsIosStdOut, "Their:\n", sizeof("Their:\n") - 1, true, NULL);
        RTManifestWriteStandard(hTheirManifest, hVfsIosStdOut);
#endif
    }
    else
        vboxExtPackSetError(pszError, cbError, "Error parsing '%s': %Rrc", VBOX_EXTPACK_MANIFEST_NAME, rc);

    RTManifestRelease(hTheirManifest);
    return rc;
}
RTR3DECL(int) RTPathQueryInfoEx(const char *pszPath, PRTFSOBJINFO pObjInfo, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
{
    /*
     * Validate input.
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(*pszPath, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pObjInfo, VERR_INVALID_POINTER);
    AssertMsgReturn(    enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING
                    &&  enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
                    ("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs),
                    VERR_INVALID_PARAMETER);
    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);

    /*
     * Query file info.
     */
    WIN32_FILE_ATTRIBUTE_DATA Data;
    PRTUTF16 pwszPath;
    int rc = RTStrToUtf16(pszPath, &pwszPath);
    if (RT_FAILURE(rc))
        return rc;
    if (!GetFileAttributesExW(pwszPath, GetFileExInfoStandard, &Data))
    {
        /* Fallback to FindFileFirst in case of sharing violation. */
        if (GetLastError() == ERROR_SHARING_VIOLATION)
        {
            WIN32_FIND_DATAW FindData;
            HANDLE hDir = FindFirstFileW(pwszPath, &FindData);
            if (hDir == INVALID_HANDLE_VALUE)
            {
                rc = RTErrConvertFromWin32(GetLastError());
                RTUtf16Free(pwszPath);
                return rc;
            }
            FindClose(hDir);

            Data.dwFileAttributes   = FindData.dwFileAttributes;
            Data.ftCreationTime     = FindData.ftCreationTime;
            Data.ftLastAccessTime   = FindData.ftLastAccessTime;
            Data.ftLastWriteTime    = FindData.ftLastWriteTime;
            Data.nFileSizeHigh      = FindData.nFileSizeHigh;
            Data.nFileSizeLow       = FindData.nFileSizeLow;
        }
        else
        {
            rc = RTErrConvertFromWin32(GetLastError());
            RTUtf16Free(pwszPath);
            return rc;
        }
    }

    /*
     * Getting the information for the link target is a bit annoying and
     * subject to the same access violation mess as above.. :/
     */
    /** @todo we're too lazy wrt to error paths here... */
    if (   (fFlags & RTPATH_F_FOLLOW_LINK)
        && (Data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
    {
        HANDLE hFinal = CreateFileW(pwszPath,
                                    GENERIC_READ,
                                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                                    NULL,
                                    OPEN_EXISTING,
                                    FILE_FLAG_BACKUP_SEMANTICS,
                                    NULL);
        if (hFinal != INVALID_HANDLE_VALUE)
        {
            BY_HANDLE_FILE_INFORMATION FileData;
            if (GetFileInformationByHandle(hFinal, &FileData))
            {
                Data.dwFileAttributes   = FileData.dwFileAttributes;
                Data.ftCreationTime     = FileData.ftCreationTime;
                Data.ftLastAccessTime   = FileData.ftLastAccessTime;
                Data.ftLastWriteTime    = FileData.ftLastWriteTime;
                Data.nFileSizeHigh      = FileData.nFileSizeHigh;
                Data.nFileSizeLow       = FileData.nFileSizeLow;
            }
            CloseHandle(hFinal);
        }
        else if (GetLastError() != ERROR_SHARING_VIOLATION)
        {
            rc = RTErrConvertFromWin32(GetLastError());
            RTUtf16Free(pwszPath);
            return rc;
        }
    }

    RTUtf16Free(pwszPath);

    /*
     * Setup the returned data.
     */
    pObjInfo->cbObject    = ((uint64_t)Data.nFileSizeHigh << 32)
                          |  (uint64_t)Data.nFileSizeLow;
    pObjInfo->cbAllocated = pObjInfo->cbObject;

    Assert(sizeof(uint64_t) == sizeof(Data.ftCreationTime));
    RTTimeSpecSetNtTime(&pObjInfo->BirthTime,         *(uint64_t *)&Data.ftCreationTime);
    RTTimeSpecSetNtTime(&pObjInfo->AccessTime,        *(uint64_t *)&Data.ftLastAccessTime);
    RTTimeSpecSetNtTime(&pObjInfo->ModificationTime,  *(uint64_t *)&Data.ftLastWriteTime);
    pObjInfo->ChangeTime  = pObjInfo->ModificationTime;

    pObjInfo->Attr.fMode  = rtFsModeFromDos((Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
                                            pszPath, strlen(pszPath));

    /*
     * Requested attributes (we cannot provide anything actually).
     */
    switch (enmAdditionalAttribs)
    {
        case RTFSOBJATTRADD_NOTHING:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_NOTHING;
            break;

        case RTFSOBJATTRADD_UNIX:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_UNIX;
            pObjInfo->Attr.u.Unix.uid             = ~0U;
            pObjInfo->Attr.u.Unix.gid             = ~0U;
            pObjInfo->Attr.u.Unix.cHardlinks      = 1;
            pObjInfo->Attr.u.Unix.INodeIdDevice   = 0; /** @todo use volume serial number */
            pObjInfo->Attr.u.Unix.INodeId         = 0; /** @todo use fileid (see GetFileInformationByHandle). */
            pObjInfo->Attr.u.Unix.fFlags          = 0;
            pObjInfo->Attr.u.Unix.GenerationId    = 0;
            pObjInfo->Attr.u.Unix.Device          = 0;
            break;

        case RTFSOBJATTRADD_UNIX_OWNER:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_UNIX_OWNER;
            pObjInfo->Attr.u.UnixOwner.uid        = ~0U;
            pObjInfo->Attr.u.UnixOwner.szName[0]  = '\0'; /** @todo return something sensible here. */
            break;

        case RTFSOBJATTRADD_UNIX_GROUP:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_UNIX_GROUP;
            pObjInfo->Attr.u.UnixGroup.gid        = ~0U;
            pObjInfo->Attr.u.UnixGroup.szName[0]  = '\0';
            break;

        case RTFSOBJATTRADD_EASIZE:
            pObjInfo->Attr.enmAdditional          = RTFSOBJATTRADD_EASIZE;
            pObjInfo->Attr.u.EASize.cb            = 0;
            break;

        default:
            AssertMsgFailed(("Impossible!\n"));
            return VERR_INTERNAL_ERROR;
    }

    return VINF_SUCCESS;
}
Example #4
0
static int rtCrPkcs7SignedData_CheckSanityExtra(PCRTCRPKCS7SIGNEDDATA pSignedData, uint32_t fFlags,
                                                PRTERRINFO pErrInfo, const char *pszErrorTag)
{
    bool const fAuthenticode = RT_BOOL(fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE);

    //RTAsn1Dump(&pSignedData->SeqCore.Asn1Core, 0, 0, RTAsn1DumpStrmPrintfV, g_pStdOut);

    if (   RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V1) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V3) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V4) != 0
        && RTAsn1Integer_UnsignedCompareWithU32(&pSignedData->Version, RTCRPKCS7SIGNEDDATA_V5) != 0)
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_VERSION, "SignedData version is %llu, expected %u",
                             pSignedData->Version.uValue.u, RTCRPKCS7SIGNEDDATA_V1);

    /*
     * DigestAlgorithms.
     */
    if (pSignedData->DigestAlgorithms.cItems == 0) /** @todo this might be too strict */
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_SIGNED_DATA_NO_DIGEST_ALGOS, "SignedData.DigestAlgorithms is empty");
    if (pSignedData->DigestAlgorithms.cItems != 1 && fAuthenticode)
        return RTErrInfoSetF(pErrInfo, VERR_CR_SPC_NOT_EXACTLY_ONE_DIGEST_ALGO,
                             "SignedData.DigestAlgorithms has more than one algorithm (%u)",
                             pSignedData->DigestAlgorithms.cItems);

    if (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH)
        for (uint32_t i = 0; i < pSignedData->DigestAlgorithms.cItems; i++)
        {
            if (RTCrX509AlgorithmIdentifier_QueryDigestType(&pSignedData->DigestAlgorithms.paItems[i]) == RTDIGESTTYPE_INVALID)
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_UNKNOWN_DIGEST_ALGORITHM,
                                     "SignedData.DigestAlgorithms[%i] is not known: %s",
                                     i, pSignedData->DigestAlgorithms.paItems[i].Algorithm.szObjId);
            if (pSignedData->DigestAlgorithms.paItems[i].Parameters.enmType != RTASN1TYPE_NULL)
                return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_PARAMS_NOT_IMPL,
                                     "SignedData.DigestAlgorithms[%i] has parameters: tag=%u",
                                     i, pSignedData->DigestAlgorithms.paItems[i].Parameters.u.Core.uTag);
        }

    /*
     * Certificates.
     */
    if (   (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT)
        && pSignedData->Certificates.cItems == 0)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NO_CERTIFICATES,
                            "SignedData.Certifcates is empty, expected at least one certificate");

    /*
     * Crls.
     */
    if (fAuthenticode && RTAsn1Core_IsPresent(&pSignedData->Crls))
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_EXPECTED_NO_CRLS,
                            "SignedData.Crls is not empty as expected for authenticode.");
    /** @todo check Crls when they become important. */

    /*
     * SignerInfos.
     */
    if (pSignedData->SignerInfos.cItems == 0)
        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_NO_SIGNER_INFOS, "SignedData.SignerInfos is empty?");
    if (fAuthenticode && pSignedData->SignerInfos.cItems != 1)
        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_EXPECTED_ONE_SIGNER_INFO,
                             "SignedData.SignerInfos should have one entry for authenticode: %u",
                             pSignedData->SignerInfos.cItems);

    for (uint32_t i = 0; i < pSignedData->SignerInfos.cItems; i++)
    {
        PCRTCRPKCS7SIGNERINFO pSignerInfo = &pSignedData->SignerInfos.paItems[i];

        if (RTAsn1Integer_UnsignedCompareWithU32(&pSignerInfo->Version, RTCRPKCS7SIGNERINFO_V1) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_VERSION,
                                 "SignedData.SignerInfos[%u] version is %llu, expected %u",
                                 i, pSignerInfo->Version.uValue.u, RTCRPKCS7SIGNERINFO_V1);

        /* IssuerAndSerialNumber. */
        int rc = RTCrX509Name_CheckSanity(&pSignerInfo->IssuerAndSerialNumber.Name, 0, pErrInfo,
                                          "SignedData.SignerInfos[#].IssuerAndSerialNumber.Name");
        if (RT_FAILURE(rc))
            return rc;

        if (pSignerInfo->IssuerAndSerialNumber.SerialNumber.Asn1Core.cb == 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_NO_ISSUER_SERIAL_NO,
                                 "SignedData.SignerInfos[%u].IssuerAndSerialNumber.SerialNumber is missing (zero length)", i);

        PCRTCRX509CERTIFICATE pCert;
        pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSignedData->Certificates,
                                                                    &pSignerInfo->IssuerAndSerialNumber.Name,
                                                                    &pSignerInfo->IssuerAndSerialNumber.SerialNumber);
        if (!pCert && (fFlags & RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT))
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_CERT_NOT_SHIPPED,
                                 "SignedData.SignerInfos[%u].IssuerAndSerialNumber not found in T0.Certificates", i);

        /* DigestAlgorithm */
        uint32_t j = 0;
        while (   j < pSignedData->DigestAlgorithms.cItems
               && RTCrX509AlgorithmIdentifier_Compare(&pSignedData->DigestAlgorithms.paItems[j],
                                                      &pSignerInfo->DigestAlgorithm) != 0)
            j++;
        if (j >= pSignedData->DigestAlgorithms.cItems)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_DIGEST_ALGO_NOT_FOUND_IN_LIST,
                                 "SignedData.SignerInfos[%u].DigestAlgorithm (%s) not found in SignedData.DigestAlgorithms",
                                 i, pSignerInfo->DigestAlgorithm.Algorithm.szObjId);

        /* Digest encryption algorithm. */
#if 0  /** @todo Unimportant: Seen timestamp signatures specifying pkcs1-Sha256WithRsaEncryption in SignerInfo and just RSA in the certificate.  Figure out how to compare the two. */
        if (   pCert
            && RTCrX509AlgorithmIdentifier_Compare(&pSignerInfo->DigestEncryptionAlgorithm,
                                                   &pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm) != 0)
            return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNER_INFO_DIGEST_ENCRYPT_MISMATCH,
                                 "SignedData.SignerInfos[%u].DigestEncryptionAlgorithm (%s) mismatch with certificate (%s)",
                                 i, pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId,
                                 pCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId);
#endif

        /* Authenticated attributes we know. */
        if (RTCrPkcs7Attributes_IsPresent(&pSignerInfo->AuthenticatedAttributes))
        {
            bool fFoundContentInfo   = false;
            bool fFoundMessageDigest = false;
            for (j = 0; j < pSignerInfo->AuthenticatedAttributes.cItems; j++)
            {
                PCRTCRPKCS7ATTRIBUTE pAttrib = &pSignerInfo->AuthenticatedAttributes.paItems[j];
                if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_CONTENT_TYPE_OID) == 0)
                {
                    if (fFoundContentInfo)
                        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
                                            "Multiple authenticated content-type attributes.");
                    fFoundContentInfo = true;
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS, VERR_INTERNAL_ERROR_3);
                    if (pAttrib->uValues.pObjIds->cItems != 1)
                        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
                                             "Expected exactly one value for content-type attrib, found: %u",
                                             pAttrib->uValues.pObjIds->cItems);
                }
                else if (RTAsn1ObjId_CompareWithString(&pAttrib->Type, RTCR_PKCS9_ID_MESSAGE_DIGEST_OID) == 0)
                {
                    if (fFoundMessageDigest)
                        return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
                                            "Multiple authenticated message-digest attributes.");
                    fFoundMessageDigest = true;
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS, VERR_INTERNAL_ERROR_3);
                    if (pAttrib->uValues.pOctetStrings->cItems != 1)
                        return RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_BAD_CONTENT_TYPE_ATTRIB,
                                             "Expected exactly one value for message-digest attrib, found: %u",
                                             pAttrib->uValues.pOctetStrings->cItems);
                }
                else
                    AssertReturn(pAttrib->enmType == RTCRPKCS7ATTRIBUTETYPE_UNKNOWN, VERR_INTERNAL_ERROR_3);
            }

            if (!fFoundContentInfo)
                return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_CONTENT_TYPE_ATTRIB,
                                    "Missing authenticated content-type attribute.");
            if (!fFoundMessageDigest)
                return RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_MISSING_MESSAGE_DIGEST_ATTRIB,
                                    "Missing authenticated message-digest attribute.");
        }
    }

    return VINF_SUCCESS;
}
Example #5
0
/**
 * Validates the extension pack tarball prior to unpacking.
 *
 * Operations performed:
 *      - Mandatory files.
 *      - Manifest check.
 *      - Manifest seal check.
 *      - XML check, match name.
 *
 * @returns VBox status code, failures with message.
 * @param   hTarballFile        The handle to open the @a pszTarball file.
 * @param   pszExtPackName      The name of the extension pack name.  NULL if
 *                              the name is not fixed.
 * @param   pszTarball          The name of the tarball in case we have to
 *                              complain about something.
 * @param   pszTarballDigest    The SHA-256 digest of the tarball.  Empty string
 *                              if no digest available.
 * @param   pszError            Where to store an error message on failure.
 * @param   cbError             The size of the buffer @a pszError points to.
 * @param   phValidManifest     Where to optionally return the handle to fully
 *                              validated the manifest for the extension pack.
 *                              This includes all files.
 * @param   phXmlFile           Where to optionally return the memorized XML
 *                              file.
 * @param   pStrDigest          Where to return the digest of the file.
 *                              Optional.
 */
int VBoxExtPackValidateTarball(RTFILE hTarballFile, const char *pszExtPackName,
                               const char *pszTarball, const char *pszTarballDigest,
                               char *pszError, size_t cbError,
                               PRTMANIFEST phValidManifest, PRTVFSFILE phXmlFile, RTCString *pStrDigest)
{
    /*
     * Clear return values.
     */
    if (phValidManifest)
        *phValidManifest = NIL_RTMANIFEST;
    if (phXmlFile)
        *phXmlFile = NIL_RTVFSFILE;
    Assert(cbError > 1);
    *pszError = '\0';
    NOREF(pszTarball);

    /*
     * Open the tar.gz filesystem stream and set up an manifest in-memory file.
     */
    RTMANIFEST      hFileManifest;
    RTVFSFSSTREAM   hTarFss;
    int rc = VBoxExtPackOpenTarFss(hTarballFile, pszError, cbError, &hTarFss, &hFileManifest);
    if (RT_FAILURE(rc))
        return rc;

    RTMANIFEST hOurManifest;
    rc = RTManifestCreate(0 /*fFlags*/, &hOurManifest);
    if (RT_SUCCESS(rc))
    {
        /*
         * Process the tarball (would be nice to move this to a function).
         */
        RTVFSFILE hXmlFile       = NIL_RTVFSFILE;
        RTVFSFILE hManifestFile  = NIL_RTVFSFILE;
        RTVFSFILE hSignatureFile = NIL_RTVFSFILE;
        for (;;)
        {
            /*
             * Get the next stream object.
             */
            char           *pszName;
            RTVFSOBJ        hVfsObj;
            RTVFSOBJTYPE    enmType;
            rc = RTVfsFsStrmNext(hTarFss, &pszName, &enmType, &hVfsObj);
            if (RT_FAILURE(rc))
            {
                if (rc != VERR_EOF)
                    vboxExtPackSetError(pszError, cbError, "RTVfsFsStrmNext failed: %Rrc", rc);
                else
                    rc = VINF_SUCCESS;
                break;
            }
            const char     *pszAdjName = pszName[0] == '.' && pszName[1] == '/' ? &pszName[2] : pszName;

            /*
             * Check the type & name validity, performing special tests on
             * standard extension pack member files.
             *
             * N.B. We will always reach the end of the loop before breaking on
             *      failure - cleanup reasons.
             */
            rc = VBoxExtPackValidateMember(pszName, enmType, hVfsObj, pszError, cbError);
            if (RT_SUCCESS(rc))
            {
                PRTVFSFILE phVfsFile = NULL;
                if (!strcmp(pszAdjName, VBOX_EXTPACK_DESCRIPTION_NAME))
                    phVfsFile = &hXmlFile;
                else if (!strcmp(pszAdjName, VBOX_EXTPACK_MANIFEST_NAME))
                    phVfsFile = &hManifestFile;
                else if (!strcmp(pszAdjName, VBOX_EXTPACK_SIGNATURE_NAME))
                    phVfsFile = &hSignatureFile;
                else if (!strncmp(pszAdjName, VBOX_EXTPACK_LICENSE_NAME_PREFIX, sizeof(VBOX_EXTPACK_LICENSE_NAME_PREFIX) - 1))
                    rc = VBoxExtPackValidateStandardFile(pszAdjName, enmType, &hVfsObj, NULL, pszError, cbError);
                if (phVfsFile)
                    rc = VBoxExtPackValidateStandardFile(pszAdjName, enmType, &hVfsObj, phVfsFile, pszError, cbError);
            }

            /*
             * Add any I/O stream to the manifest
             */
            if (   RT_SUCCESS(rc)
                && (   enmType == RTVFSOBJTYPE_FILE
                    || enmType == RTVFSOBJTYPE_IO_STREAM))
            {
                RTVFSIOSTREAM hVfsIos = RTVfsObjToIoStream(hVfsObj);
                rc = RTManifestEntryAddIoStream(hOurManifest, hVfsIos, pszAdjName, RTMANIFEST_ATTR_SIZE | RTMANIFEST_ATTR_SHA256);
                if (RT_FAILURE(rc))
                    vboxExtPackSetError(pszError, cbError, "RTManifestEntryAddIoStream failed on '%s': %Rrc", pszAdjName, rc);
                RTVfsIoStrmRelease(hVfsIos);
            }

            /*
             * Clean up and break out on failure.
             */
            RTVfsObjRelease(hVfsObj);
            RTStrFree(pszName);
            if (RT_FAILURE(rc))
                break;
        }

        /*
         * Check the integrity of the tarball file.
         */
        if (RT_SUCCESS(rc))
        {
            RTVfsFsStrmRelease(hTarFss);
            hTarFss = NIL_RTVFSFSSTREAM;
            rc = vboxExtPackVerifyFileDigest(hFileManifest, pszTarballDigest, pStrDigest, pszError, cbError);
        }

        /*
         * If we've successfully processed the tarball, verify that the
         * mandatory files are present.
         */
        if (RT_SUCCESS(rc))
        {
            if (hXmlFile == NIL_RTVFSFILE)
                rc = vboxExtPackReturnError(VERR_MISSING, pszError, cbError, "Mandator file '%s' is missing",
                                            VBOX_EXTPACK_DESCRIPTION_NAME);
            if (hManifestFile == NIL_RTVFSFILE)
                rc = vboxExtPackReturnError(VERR_MISSING, pszError, cbError, "Mandator file '%s' is missing",
                                            VBOX_EXTPACK_MANIFEST_NAME);
            if (hSignatureFile == NIL_RTVFSFILE)
                rc = vboxExtPackReturnError(VERR_MISSING, pszError, cbError, "Mandator file '%s' is missing",
                                            VBOX_EXTPACK_SIGNATURE_NAME);
        }

        /*
         * Check the manifest and it's signature.
         */
        if (RT_SUCCESS(rc))
            rc = vboxExtPackVerifyManifestAndSignature(hOurManifest, hManifestFile, hSignatureFile, pszError, cbError);

        /*
         * Check the XML.
         */
        if (RT_SUCCESS(rc))
            rc = vboxExtPackVerifyXml(hXmlFile, pszExtPackName, pszError, cbError);

        /*
         * Returns objects.
         */
        if (RT_SUCCESS(rc))
        {
            if (phValidManifest)
            {
                RTManifestRetain(hOurManifest);
                *phValidManifest = hOurManifest;
            }
            if (phXmlFile)
            {
                RTVfsFileRetain(hXmlFile);
                *phXmlFile = hXmlFile;
            }
        }

        /*
         * Release our object references.
         */
        RTManifestRelease(hOurManifest);
        RTVfsFileRelease(hXmlFile);
        RTVfsFileRelease(hManifestFile);
        RTVfsFileRelease(hSignatureFile);
    }
    else
        vboxExtPackSetError(pszError, cbError, "RTManifestCreate failed: %Rrc", rc);
    RTVfsFsStrmRelease(hTarFss);
    RTManifestRelease(hFileManifest);

    return rc;
}
/**
 * The PDM thread function.
 *
 * @returns return from pfnThread.
 *
 * @param   Thread  The thread handle.
 * @param   pvUser  Pointer to the PDMTHREAD structure.
 */
static DECLCALLBACK(int) pdmR3ThreadMain(RTTHREAD Thread, void *pvUser)
{
    PPDMTHREAD pThread = (PPDMTHREAD)pvUser;
    Log(("PDMThread: Initializing thread %RTthrd / %p / '%s'...\n", Thread, pThread, RTThreadGetName(Thread)));
    pThread->Thread = Thread;

    PUVM pUVM = pThread->Internal.s.pVM->pUVM;
    if (   pUVM->pVmm2UserMethods
        && pUVM->pVmm2UserMethods->pfnNotifyPdmtInit)
        pUVM->pVmm2UserMethods->pfnNotifyPdmtInit(pUVM->pVmm2UserMethods, pUVM);

    /*
     * The run loop.
     *
     * It handles simple thread functions which returns when they see a suspending
     * request and leaves the PDMR3ThreadIAmSuspending and PDMR3ThreadIAmRunning
     * parts to us.
     */
    int rc;
    for (;;)
    {
        switch (pThread->Internal.s.enmType)
        {
            case PDMTHREADTYPE_DEVICE:
                rc = pThread->u.Dev.pfnThread(pThread->u.Dev.pDevIns, pThread);
                break;

            case PDMTHREADTYPE_USB:
                rc = pThread->u.Usb.pfnThread(pThread->u.Usb.pUsbIns, pThread);
                break;

            case PDMTHREADTYPE_DRIVER:
                rc = pThread->u.Drv.pfnThread(pThread->u.Drv.pDrvIns, pThread);
                break;

            case PDMTHREADTYPE_INTERNAL:
                rc = pThread->u.Int.pfnThread(pThread->Internal.s.pVM, pThread);
                break;

            case PDMTHREADTYPE_EXTERNAL:
                rc = pThread->u.Ext.pfnThread(pThread);
                break;

            default:
                AssertMsgFailed(("%d\n", pThread->Internal.s.enmType));
                rc = VERR_PDM_THREAD_IPE_1;
                break;
        }
        if (RT_FAILURE(rc))
            break;

        /*
         * If this is a simple thread function, the state will be suspending
         * or initializing now. If it isn't we're supposed to terminate.
         */
        if (    pThread->enmState != PDMTHREADSTATE_SUSPENDING
            &&  pThread->enmState != PDMTHREADSTATE_INITIALIZING)
        {
            Assert(pThread->enmState == PDMTHREADSTATE_TERMINATING);
            break;
        }
        rc = PDMR3ThreadIAmSuspending(pThread);
        if (RT_FAILURE(rc))
            break;
        if (pThread->enmState != PDMTHREADSTATE_RESUMING)
        {
            Assert(pThread->enmState == PDMTHREADSTATE_TERMINATING);
            break;
        }

        rc = PDMR3ThreadIAmRunning(pThread);
        if (RT_FAILURE(rc))
            break;
    }

    if (RT_FAILURE(rc))
        LogRel(("PDMThread: Thread '%s' (%RTthrd) quit unexpectedly with rc=%Rrc.\n", RTThreadGetName(Thread), Thread, rc));

    /*
     * Advance the state to terminating and then on to terminated.
     */
    for (;;)
    {
        PDMTHREADSTATE enmState = pThread->enmState;
        if (    enmState == PDMTHREADSTATE_TERMINATING
            ||  pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
            break;
    }

    ASMAtomicXchgSize(&pThread->enmState, PDMTHREADSTATE_TERMINATED);
    int rc2 = RTThreadUserSignal(Thread); AssertRC(rc2);

    if (   pUVM->pVmm2UserMethods
        && pUVM->pVmm2UserMethods->pfnNotifyPdmtTerm)
        pUVM->pVmm2UserMethods->pfnNotifyPdmtTerm(pUVM->pVmm2UserMethods, pUVM);
    Log(("PDMThread: Terminating thread %RTthrd / %p / '%s': %Rrc\n", Thread, pThread, RTThreadGetName(Thread), rc));
    return rc;
}
Example #7
0
/**
 * Creates a diff of the changes between the streams @a pLeft and @a pRight.
 *
 * This currently only implements the simplest diff format, so no contexts.
 *
 * Also, note that we won't detect differences in the final newline of the
 * streams.
 *
 * @returns The number of differences.
 * @param   pszFilename         The filename.
 * @param   pLeft               The left side stream.
 * @param   pRight              The right side stream.
 * @param   fIgnoreEol          Whether to ignore end of line markers.
 * @param   fIgnoreLeadingWhite Set if leading white space should be ignored.
 * @param   fIgnoreTrailingWhite  Set if trailing white space should be ignored.
 * @param   fSpecialChars       Whether to print special chars in a human
 *                              readable form or not.
 * @param   cchTab              The tab size.
 * @param   pDiff               Where to write the diff.
 */
size_t ScmDiffStreams(const char *pszFilename, PSCMSTREAM pLeft, PSCMSTREAM pRight, bool fIgnoreEol,
                      bool fIgnoreLeadingWhite, bool fIgnoreTrailingWhite, bool fSpecialChars,
                      size_t cchTab, PRTSTREAM pDiff)
{
#ifdef RT_STRICT
    ScmStreamCheckItegrity(pLeft);
    ScmStreamCheckItegrity(pRight);
#endif

    /*
     * Set up the diff state.
     */
    SCMDIFFSTATE State;
    State.cDiffs                = 0;
    State.pszFilename           = pszFilename;
    State.pLeft                 = pLeft;
    State.pRight                = pRight;
    State.fIgnoreEol            = fIgnoreEol;
    State.fIgnoreLeadingWhite   = fIgnoreLeadingWhite;
    State.fIgnoreTrailingWhite  = fIgnoreTrailingWhite;
    State.fSpecialChars         = fSpecialChars;
    State.cchTab                = cchTab;
    State.pDiff                 = pDiff;

    /*
     * Compare them line by line.
     */
    ScmStreamRewindForReading(pLeft);
    ScmStreamRewindForReading(pRight);
    const char *pchLeft;
    const char *pchRight;

    for (;;)
    {
        SCMEOL  enmEolLeft;
        size_t  cchLeft;
        pchLeft  = ScmStreamGetLine(pLeft,  &cchLeft,  &enmEolLeft);

        SCMEOL  enmEolRight;
        size_t  cchRight;
        pchRight = ScmStreamGetLine(pRight, &cchRight, &enmEolRight);
        if (!pchLeft || !pchRight)
            break;

        if (!scmDiffCompare(&State, pchLeft, cchLeft, enmEolLeft, pchRight, cchRight, enmEolRight))
            scmDiffSynchronize(&State, 3);
    }

    /*
     * Deal with any remaining differences.
     */
    if (pchLeft)
        scmDiffReport(&State, 0, ScmStreamTellLine(pLeft) - 1, ~(size_t)0, ScmStreamTellLine(pRight), 0);
    else if (pchRight)
        scmDiffReport(&State, 0, ScmStreamTellLine(pLeft), 0, ScmStreamTellLine(pRight) - 1, ~(size_t)0);

    /*
     * Report any errors.
     */
    if (RT_FAILURE(ScmStreamGetStatus(pLeft)))
        RTMsgError("Left diff stream error: %Rrc\n", ScmStreamGetStatus(pLeft));
    if (RT_FAILURE(ScmStreamGetStatus(pRight)))
        RTMsgError("Right diff stream error: %Rrc\n", ScmStreamGetStatus(pRight));

    return State.cDiffs;
}
/**
 * Recursively delete a directory.
 *
 * @returns IPRT status code, errors go via rtPathRmError.
 * @param   pOpts               The RM options.
 * @param   pszPath             Pointer to a writable buffer holding the path to
 *                              the directory.
 * @param   cchPath             The length of the path (avoid strlen).
 * @param   pDirEntry           Pointer to a directory entry buffer that is
 *                              RTPATHRM_DIR_MAX_ENTRY_SIZE bytes big.
 */
static int rtPathRmRecursive(PRTPATHRMCMDOPTS pOpts, char *pszPath, size_t cchPath, PRTDIRENTRYEX pDirEntry)
{
    /*
     * Make sure the path ends with a slash.
     */
    if (!cchPath || !RTPATH_IS_SLASH(pszPath[cchPath - 1]))
    {
        if (cchPath + 1 >= RTPATH_MAX)
            return rtPathRmError(pOpts, pszPath, VERR_BUFFER_OVERFLOW, "Buffer overflow fixing up '%s'.\n", pszPath);
        pszPath[cchPath++] = RTPATH_SLASH;
        pszPath[cchPath]   = '\0';
    }

    /*
     * Traverse the directory.
     */
    PRTDIR hDir;
    int rc = RTDirOpen(&hDir, pszPath);
    if (RT_FAILURE(rc))
        return rtPathRmError(pOpts, pszPath, rc, "Error opening directory '%s': %Rrc", pszPath, rc);
    int rcRet = VINF_SUCCESS;
    for (;;)
    {
        /*
         * Read the next entry, constructing an full path for it.
         */
        size_t cbEntry = RTPATHRM_DIR_MAX_ENTRY_SIZE;
        rc = RTDirReadEx(hDir, pDirEntry, &cbEntry, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
        if (rc == VERR_NO_MORE_FILES)
        {
            /*
             * Reached the end of the directory.
             */
            pszPath[cchPath] = '\0';
            rc = RTDirClose(hDir);
            if (RT_FAILURE(rc))
                return rtPathRmError(pOpts, pszPath, rc, "Error closing directory '%s': %Rrc", pszPath, rc);

            /* Delete the directory. */
            int rc2 = rtPathRmOneDir(pOpts, pszPath);
            if (RT_FAILURE(rc2) && RT_SUCCESS(rcRet))
                return rc2;
            return rcRet;
        }

        if (RT_FAILURE(rc))
        {
            rc = rtPathRmError(pOpts, pszPath, rc, "Error reading directory '%s': %Rrc", pszPath, rc);
            break;
        }

        /* Skip '.' and '..'. */
        if (   pDirEntry->szName[0] == '.'
            && (   pDirEntry->cbName == 1
                || (   pDirEntry->cbName == 2
                    && pDirEntry->szName[1] == '.')))
            continue;

        /* Construct full path. */
        if (cchPath + pDirEntry->cbName >= RTPATH_MAX)
        {
            pszPath[cchPath] = '\0';
            rc = rtPathRmError(pOpts, pszPath, VERR_BUFFER_OVERFLOW, "Path buffer overflow in directory '%s'.", pszPath);
            break;
        }
        memcpy(pszPath + cchPath, pDirEntry->szName, pDirEntry->cbName + 1);

        /*
         * Take action according to the type.
         */
        switch (pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK)
        {
            case RTFS_TYPE_FILE:
                rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info);
                break;

            case RTFS_TYPE_DIRECTORY:
                rc = rtPathRmRecursive(pOpts, pszPath, cchPath + pDirEntry->cbName, pDirEntry);
                break;

            case RTFS_TYPE_SYMLINK:
                rc = rtPathRmOneSymlink(pOpts, pszPath);
                break;

            case RTFS_TYPE_FIFO:
            case RTFS_TYPE_DEV_CHAR:
            case RTFS_TYPE_DEV_BLOCK:
            case RTFS_TYPE_SOCKET:
                rc = rtPathRmOneFile(pOpts, pszPath, &pDirEntry->Info);
                break;

            case RTFS_TYPE_WHITEOUT:
            default:
                rc = rtPathRmError(pOpts, pszPath, VERR_UNEXPECTED_FS_OBJ_TYPE,
                                   "Object '%s' has an unknown file type: %o\n",
                                   pszPath, pDirEntry->Info.Attr.fMode & RTFS_TYPE_MASK);
                break;
        }
        if (RT_FAILURE(rc) && RT_SUCCESS(rcRet))
            rcRet = rc;
    }

    /*
     * Some error occured, close and return.
     */
    RTDirClose(hDir);
    return rc;
}
/**
 * Remove one user specified file or directory.
 *
 * @returns IPRT status code, errors go via rtPathRmError.
 * @param   pOpts               The RM options.
 * @param   pszPath             The path to the file, directory, whatever.
 */
static int rtPathRmOne(PRTPATHRMCMDOPTS pOpts, const char *pszPath)
{
    /*
     * RM refuses to delete some directories.
     */
    int rc = rtPathRmOneValidate(pOpts, pszPath);
    if (RT_FAILURE(rc))
        return rc;

    /*
     * Query file system object info.
     */
    RTFSOBJINFO ObjInfo;
    rc = RTPathQueryInfoEx(pszPath, &ObjInfo, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK);
    if (RT_FAILURE(rc))
    {
        if (pOpts->fForce && (rc == VERR_FILE_NOT_FOUND || rc == VERR_PATH_NOT_FOUND))
            return VINF_SUCCESS;
        return rtPathRmError(pOpts, pszPath, rc, "Error deleting '%s': %Rrc", pszPath, rc);
    }

    /*
     * Take type specific action.
     */
    switch (ObjInfo.Attr.fMode & RTFS_TYPE_MASK)
    {
        case RTFS_TYPE_FILE:
            return rtPathRmOneFile(pOpts, pszPath, &ObjInfo);

        case RTFS_TYPE_DIRECTORY:
            if (pOpts->fRecursive)
            {
                char szPath[RTPATH_MAX];
                rc = RTPathAbs(pszPath, szPath, sizeof(szPath));
                if (RT_FAILURE(rc))
                    return rtPathRmError(pOpts, pszPath, rc, "RTPathAbs failed on '%s': %Rrc\n", pszPath, rc);

                union
                {
                    RTDIRENTRYEX    Core;
                    uint8_t         abPadding[RTPATHRM_DIR_MAX_ENTRY_SIZE];
                } DirEntry;

                return rtPathRmRecursive(pOpts, szPath, strlen(szPath), &DirEntry.Core);
            }
            if (pOpts->fDirsAndOther)
                return rtPathRmOneDir(pOpts, pszPath);
            return rtPathRmError(pOpts, pszPath, VERR_IS_A_DIRECTORY, "Cannot remove '%s': %Rrc\n", pszPath, VERR_IS_A_DIRECTORY);

        case RTFS_TYPE_SYMLINK:
            return rtPathRmOneSymlink(pOpts, pszPath);

        case RTFS_TYPE_FIFO:
        case RTFS_TYPE_DEV_CHAR:
        case RTFS_TYPE_DEV_BLOCK:
        case RTFS_TYPE_SOCKET:
            return rtPathRmOneFile(pOpts, pszPath, &ObjInfo);

        case RTFS_TYPE_WHITEOUT:
        default:
            return rtPathRmError(pOpts, pszPath, VERR_UNEXPECTED_FS_OBJ_TYPE,
                                 "Object '%s' has an unknown file type: %o\n", pszPath, ObjInfo.Attr.fMode & RTFS_TYPE_MASK);

    }
}
/**
 * Device I/O Control entry point.
 *
 * @param   pFilp       Associated file pointer.
 * @param   uCmd        The function specified to ioctl().
 * @param   ulArg       The argument specified to ioctl().
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36)
static int VBoxNetAdpLinuxIOCtl(struct inode *pInode, struct file *pFilp,
                                unsigned int uCmd, unsigned long ulArg)
#else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */
static long VBoxNetAdpLinuxIOCtlUnlocked(struct file *pFilp,
                                         unsigned int uCmd, unsigned long ulArg)
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) */
{
    VBOXNETADPREQ Req;
    PVBOXNETADP pAdp;
    int rc;
    char *pszName = NULL;

    Log(("VBoxNetAdpLinuxIOCtl: param len %#x; uCmd=%#x; add=%#x\n", _IOC_SIZE(uCmd), uCmd, VBOXNETADP_CTL_ADD));
    if (RT_UNLIKELY(_IOC_SIZE(uCmd) != sizeof(Req))) /* paranoia */
    {
        Log(("VBoxNetAdpLinuxIOCtl: bad ioctl sizeof(Req)=%#x _IOC_SIZE=%#x; uCmd=%#x.\n", sizeof(Req), _IOC_SIZE(uCmd), uCmd));
        return -EINVAL;
    }

    switch (uCmd)
    {
        case VBOXNETADP_CTL_ADD:
            Log(("VBoxNetAdpLinuxIOCtl: _IOC_DIR(uCmd)=%#x; IOC_OUT=%#x\n", _IOC_DIR(uCmd), IOC_OUT));
            if (RT_UNLIKELY(copy_from_user(&Req, (void *)ulArg, sizeof(Req))))
            {
                Log(("VBoxNetAdpLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x.\n", ulArg, uCmd));
                return -EFAULT;
            }
            Log(("VBoxNetAdpLinuxIOCtl: Add %s\n", Req.szName));

            if (Req.szName[0])
            {
                pAdp = vboxNetAdpFindByName(Req.szName);
                if (pAdp)
                {
                    Log(("VBoxNetAdpLinuxIOCtl: '%s' already exists\n", Req.szName));
                    return -EINVAL;
                }
                pszName = Req.szName;
            }
            rc = vboxNetAdpCreate(&pAdp, pszName);
            if (RT_FAILURE(rc))
            {
                Log(("VBoxNetAdpLinuxIOCtl: vboxNetAdpCreate -> %Rrc\n", rc));
                return -(rc == VERR_OUT_OF_RESOURCES ? ENOMEM : EINVAL);
            }

            Assert(strlen(pAdp->szName) < sizeof(Req.szName));
            strncpy(Req.szName, pAdp->szName, sizeof(Req.szName) - 1);
            Req.szName[sizeof(Req.szName) - 1] = '\0';

            if (RT_UNLIKELY(copy_to_user((void *)ulArg, &Req, sizeof(Req))))
            {
                /* this is really bad! */
                /** @todo remove the adapter again? */
                printk(KERN_ERR "VBoxNetAdpLinuxIOCtl: copy_to_user(%#lx,,%#zx); uCmd=%#x!\n", ulArg, sizeof(Req), uCmd);
                return -EFAULT;
            }
            Log(("VBoxNetAdpLinuxIOCtl: Successfully added '%s'\n", Req.szName));
            break;

        case VBOXNETADP_CTL_REMOVE:
            if (RT_UNLIKELY(copy_from_user(&Req, (void *)ulArg, sizeof(Req))))
            {
                Log(("VBoxNetAdpLinuxIOCtl: copy_from_user(,%#lx,) failed; uCmd=%#x.\n", ulArg, uCmd));
                return -EFAULT;
            }
            Log(("VBoxNetAdpLinuxIOCtl: Remove %s\n", Req.szName));

            pAdp = vboxNetAdpFindByName(Req.szName);
            if (!pAdp)
            {
                Log(("VBoxNetAdpLinuxIOCtl: '%s' not found\n", Req.szName));
                return -EINVAL;
            }

            rc = vboxNetAdpDestroy(pAdp);
            if (RT_FAILURE(rc))
            {
                Log(("VBoxNetAdpLinuxIOCtl: vboxNetAdpDestroy('%s') -> %Rrc\n", Req.szName, rc));
                return -EINVAL;
            }
            Log(("VBoxNetAdpLinuxIOCtl: Successfully removed '%s'\n", Req.szName));
            break;

        default:
            printk(KERN_ERR "VBoxNetAdpLinuxIOCtl: unknown command %x.\n", uCmd);
            return -EINVAL;
    }

    return 0;
}
/**
 * Worker that removes a file.
 *
 * Currently used to delete both regular and special files.
 *
 * @returns IPRT status code, errors go via rtPathRmError.
 * @param   pOpts               The RM options.
 * @param   pszPath             The path to the file.
 * @param   pObjInfo            The FS object info for the file.
 */
static int rtPathRmOneFile(PRTPATHRMCMDOPTS pOpts, const char *pszPath, PRTFSOBJINFO pObjInfo)
{
    int rc;
    if (pOpts->fVerbose)
        rtPathRmVerbose(pOpts, pszPath);

    /*
     * Wipe the file if requested and possible.
     */
    if (pOpts->fSafeDelete && RTFS_IS_FILE(pObjInfo->Attr.fMode))
    {
        /* Lazy init of the 0xff buffer. */
        if (g_ab0xFF[0] != 0xff || g_ab0xFF[sizeof(g_ab0xFF) - 1] != 0xff)
            memset(g_ab0xFF, 0xff, sizeof(g_ab0xFF));

        RTFILE hFile;
        rc = RTFileOpen(&hFile, pszPath, RTFILE_O_WRITE);
        if (RT_FAILURE(rc))
            return rtPathRmError(pOpts, pszPath, rc, "Opening '%s' for overwriting: %Rrc\n", pszPath, rc);

        for (unsigned iPass = 0; iPass < 3; iPass++)
        {
            uint8_t const *pabFiller = iPass == 1 ? g_abZeros         : g_ab0xFF;
            size_t const   cbFiller  = iPass == 1 ? sizeof(g_abZeros) : sizeof(g_ab0xFF);

            rc = RTFileSeek(hFile, 0, RTFILE_SEEK_BEGIN, NULL);
            if (RT_FAILURE(rc))
            {
                rc = rtPathRmError(pOpts, pszPath, rc, "Error seeking to start of '%s': %Rrc\n", pszPath, rc);
                break;
            }
            for (RTFOFF cbLeft = pObjInfo->cbObject; cbLeft > 0; cbLeft -= cbFiller)
            {
                size_t cbToWrite = cbFiller;
                if (cbLeft < (RTFOFF)cbToWrite)
                    cbToWrite = (size_t)cbLeft;
                rc = RTFileWrite(hFile, pabFiller, cbToWrite, NULL);
                if (RT_FAILURE(rc))
                {
                    rc = rtPathRmError(pOpts, pszPath, rc, "Error writing to '%s': %Rrc\n", pszPath, rc);
                    break;
                }
            }
        }

        int rc2 = RTFileClose(hFile);
        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
            return rtPathRmError(pOpts, pszPath, rc2, "Closing '%s' failed: %Rrc\n", pszPath, rc);
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Remove the file.
     */
    rc = RTFileDelete(pszPath);
    if (RT_FAILURE(rc))
        return rtPathRmError(pOpts, pszPath, rc,
                             RTFS_IS_FILE(pObjInfo->Attr.fMode)
                             ? "Error removing regular file '%s': %Rrc\n"
                             : "Error removing special file '%s': %Rrc\n",
                             pszPath, rc);
    return rc;
}
Example #12
0
static int vboxvfs_mount(struct mount *mp, struct thread *td)
{
    int rc;
    char *pszShare;
    int  cbShare, cbOption;
    int uid = 0, gid = 0;
    struct sf_glob_info *pShFlGlobalInfo;
    SHFLSTRING *pShFlShareName = NULL;
    int cbShFlShareName;

    printf("%s: Enter\n", __FUNCTION__);

    if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS))
        return EOPNOTSUPP;

    if (vfs_filteropt(mp->mnt_optnew, vboxvfs_opts))
    {
        vfs_mount_error(mp, "%s", "Invalid option");
        return EINVAL;
    }

    rc = vfs_getopt(mp->mnt_optnew, "from", (void **)&pszShare, &cbShare);
    if (rc || pszShare[cbShare-1] != '\0' || cbShare > 0xfffe)
        return EINVAL;

    rc = vfs_getopt(mp->mnt_optnew, "gid", (void **)&gid, &cbOption);
    if ((rc != ENOENT) && (rc || cbOption != sizeof(gid)))
        return EINVAL;

    rc = vfs_getopt(mp->mnt_optnew, "uid", (void **)&uid, &cbOption);
    if ((rc != ENOENT) && (rc || cbOption != sizeof(uid)))
        return EINVAL;

    pShFlGlobalInfo = RTMemAllocZ(sizeof(struct sf_glob_info));
    if (!pShFlGlobalInfo)
        return ENOMEM;

    cbShFlShareName = offsetof (SHFLSTRING, String.utf8) + cbShare + 1;
    pShFlShareName  = RTMemAllocZ(cbShFlShareName);
    if (!pShFlShareName)
        return VERR_NO_MEMORY;

    pShFlShareName->u16Length = cbShare;
    pShFlShareName->u16Size   = cbShare + 1;
    memcpy (pShFlShareName->String.utf8, pszShare, cbShare + 1);

    rc = VbglR0SfMapFolder (&g_vboxSFClient, pShFlShareName, &pShFlGlobalInfo->map);
    RTMemFree(pShFlShareName);

    if (RT_FAILURE (rc))
    {
        RTMemFree(pShFlGlobalInfo);
        printf("VbglR0SfMapFolder failed rc=%d\n", rc);
        return EPROTO;
    }

    pShFlGlobalInfo->uid = uid;
    pShFlGlobalInfo->gid = gid;

    mp->mnt_data = pShFlGlobalInfo;

    /** @todo root vnode. */

    vfs_getnewfsid(mp);
    vfs_mountedfrom(mp, pszShare);

    printf("%s: Leave rc=0\n", __FUNCTION__);

    return 0;
}
/**
 * @copydoc USBPROXYBACK::pfnUrbQueue
 */
static DECLCALLBACK(int) usbProxyFreeBSDUrbQueue(PUSBPROXYDEV pProxyDev, PVUSBURB pUrb)
{
    PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD);
    PUSBENDPOINTFBSD pEndpointFBSD;
    struct usb_fs_endpoint *pXferEndpoint;
    struct usb_fs_start UsbFsStart;
    unsigned cFrames;
    uint8_t *pbData;
    int index;
    int ep_num;
    int rc;

    LogFlow(("usbProxyFreeBSDUrbQueue: pUrb=%p EndPt=%u Dir=%u\n",
             pUrb, (unsigned)pUrb->EndPt, (unsigned)pUrb->enmDir));

    ep_num = pUrb->EndPt;
    if ((pUrb->enmType != VUSBXFERTYPE_MSG) && (pUrb->enmDir == VUSBDIRECTION_IN)) {
        /* set IN-direction bit */
        ep_num |= 0x80;
    }

    index = 0;

retry:

    index = usbProxyFreeBSDEndpointOpen(pProxyDev, ep_num,
                                        (pUrb->enmType == VUSBXFERTYPE_ISOC),
                                        index);

    if (index < 0)
        return VERR_INVALID_PARAMETER;

    pEndpointFBSD = &pDevFBSD->aSwEndpoint[index];
    pXferEndpoint = &pDevFBSD->aHwEndpoint[index];

    pbData = pUrb->abData;

    switch (pUrb->enmType)
    {
        case VUSBXFERTYPE_MSG:
        {
            pEndpointFBSD->apvData[0] = pbData;
            pEndpointFBSD->acbData[0] = 8;

            /* check wLength */
            if (pbData[6] || pbData[7])
            {
                pEndpointFBSD->apvData[1] = pbData + 8;
                pEndpointFBSD->acbData[1] = pbData[6] | (pbData[7] << 8);
                cFrames = 2;
            }
            else
            {
                pEndpointFBSD->apvData[1] = NULL;
                pEndpointFBSD->acbData[1] = 0;
                cFrames = 1;
            }

            LogFlow(("usbProxyFreeBSDUrbQueue: pUrb->cbData=%u, 0x%02x, "
                     "0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
                     pUrb->cbData, pbData[0], pbData[1], pbData[2], pbData[3],
                     pbData[4], pbData[5], pbData[6], pbData[7]));

            pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE;
            pXferEndpoint->flags = USB_FS_FLAG_MULTI_SHORT_OK;
            break;
        }
        case VUSBXFERTYPE_ISOC:
        {
            unsigned i;

            for (i = 0; i < pUrb->cIsocPkts; i++)
            {
                if (i >= pEndpointFBSD->cMaxFrames)
                    break;
                pEndpointFBSD->apvData[i] = pbData + pUrb->aIsocPkts[i].off;
                pEndpointFBSD->acbData[i] = pUrb->aIsocPkts[i].cb;
            }
            /* Timeout handling will be done during reap. */
            pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE;
            pXferEndpoint->flags = USB_FS_FLAG_MULTI_SHORT_OK;
            cFrames = i;
            break;
        }
        default:
        {
            pEndpointFBSD->apvData[0] = pbData;
            pEndpointFBSD->cbData0 = pUrb->cbData;

            /* XXX maybe we have to loop */
            if (pUrb->cbData > pEndpointFBSD->cMaxIo)
                pEndpointFBSD->acbData[0] = pEndpointFBSD->cMaxIo;
            else
                pEndpointFBSD->acbData[0] = pUrb->cbData;

            /* Timeout handling will be done during reap. */
            pXferEndpoint->timeout = USB_FS_TIMEOUT_NONE;
            pXferEndpoint->flags = pUrb->fShortNotOk ? 0 : USB_FS_FLAG_MULTI_SHORT_OK;
            cFrames = 1;
            break;
        }
    }

    /* store number of frames */
    pXferEndpoint->nFrames = cFrames;

    /* zero-default */
    memset(&UsbFsStart, 0, sizeof(UsbFsStart));

    /* Start the transfer */
    UsbFsStart.ep_index = index;

    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_START, &UsbFsStart, true);

    LogFlow(("usbProxyFreeBSDUrbQueue: USB_FS_START returned rc=%d "
             "len[0]=%u len[1]=%u cbData=%u index=%u ep_num=%u\n", rc,
             (unsigned)pEndpointFBSD->acbData[0],
             (unsigned)pEndpointFBSD->acbData[1],
             (unsigned)pUrb->cbData,
             (unsigned)index, (unsigned)ep_num));

    if (RT_FAILURE(rc))
    {
        if (rc == VERR_RESOURCE_BUSY)
        {
            index++;
            goto retry;
        }
        return rc;
    }
    pUrb->Dev.pvPrivate = (void *)(long)(index + 1);
    pEndpointFBSD->pUrb = pUrb;

    return rc;
}
static int usbProxyFreeBSDEndpointOpen(PUSBPROXYDEV pProxyDev, int Endpoint, bool fIsoc, int index)
{
    PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD);
    PUSBENDPOINTFBSD pEndpointFBSD = NULL; /* shut up gcc */
    struct usb_fs_endpoint *pXferEndpoint;
    struct usb_fs_open UsbFsOpen;
    int rc;

    LogFlow(("usbProxyFreeBSDEndpointOpen: pProxyDev=%p Endpoint=%d\n",
             (void *)pProxyDev, Endpoint));

    for (; index < USBFBSD_MAXENDPOINTS; index++)
    {
        pEndpointFBSD = &pDevFBSD->aSwEndpoint[index];
        if (pEndpointFBSD->fCancelling)
            continue;
        if (   pEndpointFBSD->fOpen
            && !pEndpointFBSD->pUrb
            && (int)pEndpointFBSD->iEpNum == Endpoint)
            return index;
    }

    if (index == USBFBSD_MAXENDPOINTS)
    {
        for (index = 0; index != USBFBSD_MAXENDPOINTS; index++)
        {
            pEndpointFBSD = &pDevFBSD->aSwEndpoint[index];
            if (pEndpointFBSD->fCancelling)
                continue;
            if (!pEndpointFBSD->fOpen)
                break;
        }
        if (index == USBFBSD_MAXENDPOINTS)
            return -1;
    }
    /* set ppBuffer and pLength */

    pXferEndpoint = &pDevFBSD->aHwEndpoint[index];
    pXferEndpoint->ppBuffer = &pEndpointFBSD->apvData[0];
    pXferEndpoint->pLength = &pEndpointFBSD->acbData[0];

    LogFlow(("usbProxyFreeBSDEndpointOpen: ep_index=%d ep_num=%d\n",
             index, Endpoint));

    memset(&UsbFsOpen, 0, sizeof(UsbFsOpen));

    UsbFsOpen.ep_index = index;
    UsbFsOpen.ep_no = Endpoint;
    UsbFsOpen.max_bufsize = 256 * 1024;
    /* Hardcoded assumption about the URBs we get. */

    UsbFsOpen.max_frames = fIsoc ? USBFBSD_MAXFRAMES : 2;

    rc = usbProxyFreeBSDDoIoCtl(pProxyDev, USB_FS_OPEN, &UsbFsOpen, true);
    if (RT_FAILURE(rc))
    {
        if (rc == VERR_RESOURCE_BUSY)
            LogFlow(("usbProxyFreeBSDEndpointOpen: EBUSY\n"));

        return -1;
    }
    pEndpointFBSD->fOpen = true;
    pEndpointFBSD->pUrb = NULL;
    pEndpointFBSD->iEpNum = Endpoint;
    pEndpointFBSD->cMaxIo = UsbFsOpen.max_bufsize;
    pEndpointFBSD->cMaxFrames = UsbFsOpen.max_frames;

    return index;
}
Example #15
0
/**
 *  Entry point.
 */
extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
{
    RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_SUPLIB);
    RTPrintf(TESTCASE ": TESTING...\n");
    RTStrmFlush(g_pStdOut);

    /*
     * Create empty VM.
     */
    PUVM pUVM;
    int rc = VMR3Create(1, NULL, NULL, NULL, tstVMREQConfigConstructor, NULL, NULL, &pUVM);
    if (RT_SUCCESS(rc))
    {
        /*
         * Do testing.
         */
        uint64_t u64StartTS = RTTimeNanoTS();
        RTTHREAD Thread0;
        rc = RTThreadCreate(&Thread0, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
        if (RT_SUCCESS(rc))
        {
            RTTHREAD Thread1;
            rc = RTThreadCreate(&Thread1, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
            if (RT_SUCCESS(rc))
            {
                int rcThread1;
                rc = RTThreadWait(Thread1, RT_INDEFINITE_WAIT, &rcThread1);
                if (RT_FAILURE(rc))
                {
                    RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
                    g_cErrors++;
                }
                if (RT_FAILURE(rcThread1))
                    g_cErrors++;
            }
            else
            {
                RTPrintf(TESTCASE ": RTThreadCreate(&Thread1,,,,) failed, rc=%Rrc\n", rc);
                g_cErrors++;
            }

            int rcThread0;
            rc = RTThreadWait(Thread0, RT_INDEFINITE_WAIT, &rcThread0);
            if (RT_FAILURE(rc))
            {
                RTPrintf(TESTCASE ": RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
                g_cErrors++;
            }
            if (RT_FAILURE(rcThread0))
                g_cErrors++;
        }
        else
        {
            RTPrintf(TESTCASE ": RTThreadCreate(&Thread0,,,,) failed, rc=%Rrc\n", rc);
            g_cErrors++;
        }
        uint64_t u64ElapsedTS = RTTimeNanoTS() - u64StartTS;
        RTPrintf(TESTCASE  ": %llu ns elapsed\n", u64ElapsedTS);
        RTStrmFlush(g_pStdOut);

        /*
         * Print stats.
         */
        STAMR3Print(pUVM, "/VM/Req/*");

        /*
         * Testing va_list fun.
         */
        RTPrintf(TESTCASE ": va_list argument test...\n"); RTStrmFlush(g_pStdOut);
        PassVA(pUVM, "hello %s", "world");
        VMR3AtRuntimeErrorRegister(pUVM, MyAtRuntimeError, (void *)"user argument");
        VMSetRuntimeError(VMR3GetVM(pUVM), 0 /*fFlags*/, "enum", "some %s string", "error");

        /*
         * Cleanup.
         */
        rc = VMR3PowerOff(pUVM);
        if (!RT_SUCCESS(rc))
        {
            RTPrintf(TESTCASE ": error: failed to power off vm! rc=%Rrc\n", rc);
            g_cErrors++;
        }
        rc = VMR3Destroy(pUVM);
        if (!RT_SUCCESS(rc))
        {
            RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%Rrc\n", rc);
            g_cErrors++;
        }
        VMR3ReleaseUVM(pUVM);
    }
    else
    {
        RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%Rrc\n", rc);
        g_cErrors++;
    }

    /*
     * Summary and return.
     */
    if (!g_cErrors)
        RTPrintf(TESTCASE ": SUCCESS\n");
    else
        RTPrintf(TESTCASE ": FAILURE - %d errors\n", g_cErrors);

    return !!g_cErrors;
}
RTDECL(RTEXITCODE) RTPathRmCmd(unsigned cArgs, char **papszArgs)
{
    /*
     * Parse the command line.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        /* operations */
        { "--dirs-and-more",        'd', RTGETOPT_REQ_NOTHING },
        { "--force",                'f', RTGETOPT_REQ_NOTHING },
        { "--prompt",               'i', RTGETOPT_REQ_NOTHING },
        { "--prompt-once",          'I', RTGETOPT_REQ_NOTHING },
        { "--interactive",      RTPATHRMCMD_OPT_INTERACTIVE, RTGETOPT_REQ_STRING },
        { "--one-file-system",  RTPATHRMCMD_OPT_ONE_FILE_SYSTEM, RTGETOPT_REQ_NOTHING },
        { "--preserve-root",    RTPATHRMCMD_OPT_PRESERVE_ROOT, RTGETOPT_REQ_NOTHING },
        { "--no-preserve-root", RTPATHRMCMD_OPT_NO_PRESERVE_ROOT, RTGETOPT_REQ_NOTHING },
        { "--recursive",            'R', RTGETOPT_REQ_NOTHING },
        { "--recursive",            'r', RTGETOPT_REQ_NOTHING },
        { "--safe-delete",          'P', RTGETOPT_REQ_NOTHING },
        { "--verbose",              'v', RTGETOPT_REQ_NOTHING },

        /* IPRT extensions */
        { "--machine-readable", RTPATHRMCMD_OPT_MACHINE_READABLE, RTGETOPT_REQ_NOTHING },
        { "--machinereadable",  RTPATHRMCMD_OPT_MACHINE_READABLE, RTGETOPT_REQ_NOTHING }, /* bad long option style */
    };

    RTGETOPTSTATE GetState;
    int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1,
                          RTGETOPTINIT_FLAGS_OPTS_FIRST);
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTGetOpt failed: %Rrc", rc);

    RTPATHRMCMDOPTS Opts;
    RT_ZERO(Opts);
    Opts.fPreserveRoot  = true;
    Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_NONE;

    RTGETOPTUNION   ValueUnion;
    while (   (rc = RTGetOpt(&GetState, &ValueUnion)) != 0
           && rc != VINF_GETOPT_NOT_OPTION)
    {
        switch (rc)
        {
            case 'd':
                Opts.fDirsAndOther = true;
                break;

            case 'f':
                Opts.fForce = true;
                Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_NONE;
                break;

            case 'i':
                Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ALL;
                break;

            case 'I':
                Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ONCE;
                break;

            case RTPATHRMCMD_OPT_INTERACTIVE:
                if (!strcmp(ValueUnion.psz, "always"))
                    Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ALL;
                else if (!strcmp(ValueUnion.psz, "once"))
                    Opts.enmInteractive = RTPATHRMCMDINTERACTIVE_ONCE;
                else
                    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Unknown --interactive option value: '%s'\n", ValueUnion.psz);
                break;

            case RTPATHRMCMD_OPT_ONE_FILE_SYSTEM:
                Opts.fOneFileSystem = true;
                break;

            case RTPATHRMCMD_OPT_PRESERVE_ROOT:
                Opts.fPreserveRoot = true;
                break;

            case RTPATHRMCMD_OPT_NO_PRESERVE_ROOT:
                Opts.fPreserveRoot = false;
                break;

            case 'R':
            case 'r':
                Opts.fRecursive = true;
                Opts.fDirsAndOther = true;
                break;

            case 'P':
                Opts.fSafeDelete = true;
                break;

            case 'v':
                Opts.fVerbose = true;
                break;


            case RTPATHRMCMD_OPT_MACHINE_READABLE:
                Opts.fMachineReadable = true;
                break;

            case 'h':
                RTPrintf("Usage: to be written\nOption dump:\n");
                for (unsigned i = 0; i < RT_ELEMENTS(s_aOptions); i++)
                    if (RT_C_IS_PRINT(s_aOptions[i].iShort))
                        RTPrintf(" -%c,%s\n", s_aOptions[i].iShort, s_aOptions[i].pszLong);
                    else
                        RTPrintf(" %s\n", s_aOptions[i].pszLong);
                return RTEXITCODE_SUCCESS;

            case 'V':
                RTPrintf("%sr%d\n", RTBldCfgVersion(), RTBldCfgRevision());
                return RTEXITCODE_SUCCESS;

            default:
                return RTGetOptPrintError(rc, &ValueUnion);
        }
    }

    /*
     * Options we don't support.
     */
    if (Opts.fOneFileSystem)
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The --one-file-system option is not yet implemented.\n");
    if (Opts.enmInteractive != RTPATHRMCMDINTERACTIVE_NONE)
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The -i, -I and --interactive options are not implemented yet.\n");

    /*
     * No files means error.
     */
    if (rc != VINF_GETOPT_NOT_OPTION && !Opts.fForce)
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No files or directories specified.\n");

    /*
     * Machine readable init + header.
     */
    if (Opts.fMachineReadable)
    {
        rc = RTStrmSetMode(g_pStdOut, true /*fBinary*/, false /*fCurrentCodeSet*/);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTStrmSetMode failed: %Rrc.\n", rc);
        static const char s_achHeader[] = "hdr_id=rm\0hdr_ver=1";
        RTStrmWrite(g_pStdOut, s_achHeader, sizeof(s_achHeader));
    }

    /*
     * Delete the specified files/dirs/whatever.
     */
    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    while (rc == VINF_GETOPT_NOT_OPTION)
    {
        rc = rtPathRmOne(&Opts, ValueUnion.psz);
        if (RT_FAILURE(rc))
            rcExit = RTEXITCODE_FAILURE;

        /* next */
        rc = RTGetOpt(&GetState, &ValueUnion);
    }
    if (rc != 0)
        rcExit = RTGetOptPrintError(rc, &ValueUnion);

    /*
     * Terminate the machine readable stuff.
     */
    if (Opts.fMachineReadable)
    {
        RTStrmWrite(g_pStdOut, "\0\0\0", 4);
        rc = RTStrmFlush(g_pStdOut);
        if (RT_FAILURE(rc) && rcExit == RTEXITCODE_SUCCESS)
            rcExit = RTEXITCODE_FAILURE;
    }

    return rcExit;
}
Example #17
0
int CollectorWin::preCollect(const CollectorHints& hints, uint64_t /* iTick */)
{
    LogFlowThisFuncEnter();

    uint64_t user, kernel, idle, total;
    int rc = getRawHostCpuLoad(&user, &kernel, &idle);
    if (RT_FAILURE(rc))
        return rc;
    total = user + kernel + idle;

    DWORD dwError;
    const CollectorHints::ProcessList& processes = hints.getProcessFlags();
    CollectorHints::ProcessList::const_iterator it;

    mProcessStats.clear();

    for (it = processes.begin(); it != processes.end() && RT_SUCCESS(rc); ++it)
    {
        RTPROCESS process = it->first;
        HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
                               FALSE, process);

        if (!h)
        {
            dwError = GetLastError();
            Log (("OpenProcess() -> 0x%x\n", dwError));
            rc = RTErrConvertFromWin32(dwError);
            break;
        }

        VMProcessStats vmStats;
        RT_ZERO(vmStats);
        if ((it->second & COLLECT_CPU_LOAD) != 0)
        {
            FILETIME ftCreate, ftExit, ftKernel, ftUser;
            if (!GetProcessTimes(h, &ftCreate, &ftExit, &ftKernel, &ftUser))
            {
                dwError = GetLastError();
                Log (("GetProcessTimes() -> 0x%x\n", dwError));
                rc = RTErrConvertFromWin32(dwError);
            }
            else
            {
                vmStats.cpuKernel = FILETTIME_TO_100NS(ftKernel);
                vmStats.cpuUser   = FILETTIME_TO_100NS(ftUser);
                vmStats.cpuTotal  = total;
            }
        }
        if (RT_SUCCESS(rc) && (it->second & COLLECT_RAM_USAGE) != 0)
        {
            PROCESS_MEMORY_COUNTERS pmc;
            if (!GetProcessMemoryInfo(h, &pmc, sizeof(pmc)))
            {
                dwError = GetLastError();
                Log (("GetProcessMemoryInfo() -> 0x%x\n", dwError));
                rc = RTErrConvertFromWin32(dwError);
            }
            else
                vmStats.ramUsed = pmc.WorkingSetSize;
        }
        CloseHandle(h);
        mProcessStats[process] = vmStats;
    }

    LogFlowThisFuncLeave();

    return rc;
}
Example #18
0
RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine,
                                   uint32_t fFlags, const char *pszSeparators)
{
    /*
     * Some input validation.
     */
    AssertPtr(pszCmdLine);
    AssertPtr(pcArgs);
    AssertPtr(ppapszArgv);
    AssertReturn(   fFlags == RTGETOPTARGV_CNV_QUOTE_BOURNE_SH
                 || fFlags == RTGETOPTARGV_CNV_QUOTE_MS_CRT, VERR_INVALID_FLAGS);
    if (!pszSeparators)
        pszSeparators = " \t\n\r";
    else
        AssertPtr(pszSeparators);
    size_t const cchSeparators = strlen(pszSeparators);
    AssertReturn(cchSeparators > 0, VERR_INVALID_PARAMETER);

    /*
     * Parse the command line and chop off it into argv individual argv strings.
     */
    int         rc        = VINF_SUCCESS;
    const char *pszSrc    = pszCmdLine;
    char       *pszDup    = (char *)RTMemAlloc(strlen(pszSrc) + 1);
    char       *pszDst    = pszDup;
    if (!pszDup)
        return VERR_NO_STR_MEMORY;
    char      **papszArgs = NULL;
    unsigned    iArg      = 0;
    while (*pszSrc)
    {
        /* Skip stuff */
        rc = rtGetOptSkipDelimiters(&pszSrc, pszSeparators, cchSeparators);
        if (RT_FAILURE(rc))
            break;
        if (!*pszSrc)
            break;

        /* Start a new entry. */
        if ((iArg % 32) == 0)
        {
            void *pvNew = RTMemRealloc(papszArgs, (iArg + 33) * sizeof(char *));
            if (!pvNew)
            {
                rc = VERR_NO_MEMORY;
                break;
            }
            papszArgs = (char **)pvNew;
        }
        papszArgs[iArg++] = pszDst;

        /*
         * Parse and copy the string over.
         */
        RTUNICP Cp;
        if ((fFlags & RTGETOPTARGV_CNV_QUOTE_MASK) == RTGETOPTARGV_CNV_QUOTE_BOURNE_SH)
        {
            /*
             * Bourne shell style.
             */
            RTUNICP CpQuote = 0;
            for (;;)
            {
                rc = RTStrGetCpEx(&pszSrc, &Cp);
                if (RT_FAILURE(rc) || !Cp)
                    break;
                if (!CpQuote)
                {
                    if (Cp == '"' || Cp == '\'')
                        CpQuote = Cp;
                    else if (rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
                        break;
                    else if (Cp != '\\')
                        pszDst = RTStrPutCp(pszDst, Cp);
                    else
                    {
                        /* escaped char */
                        rc = RTStrGetCpEx(&pszSrc, &Cp);
                        if (RT_FAILURE(rc) || !Cp)
                            break;
                        pszDst = RTStrPutCp(pszDst, Cp);
                    }
                }
                else if (CpQuote != Cp)
                {
                    if (Cp != '\\' || CpQuote == '\'')
                        pszDst = RTStrPutCp(pszDst, Cp);
                    else
                    {
                        /* escaped char */
                        rc = RTStrGetCpEx(&pszSrc, &Cp);
                        if (RT_FAILURE(rc) || !Cp)
                            break;
                        pszDst = RTStrPutCp(pszDst, Cp);
                    }
                }
                else
                    CpQuote = 0;
            }
        }
        else
        {
            /*
             * Microsoft CRT style.
             */
            Assert((fFlags & RTGETOPTARGV_CNV_QUOTE_MASK) == RTGETOPTARGV_CNV_QUOTE_MS_CRT);
            bool fInQuote = false;
            for (;;)
            {
                rc = RTStrGetCpEx(&pszSrc, &Cp);
                if (RT_FAILURE(rc) || !Cp)
                    break;
                if (Cp == '"')
                    fInQuote = !fInQuote;
                else if (!fInQuote && rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
                    break;
                else if (Cp != '\\')
                    pszDst = RTStrPutCp(pszDst, Cp);
                else
                {
                    /* A backslash sequence is only relevant if followed by
                       a double quote, then it will work like an escape char. */
                    size_t cQuotes = 1;
                    while (*pszSrc == '\\')
                    {
                        cQuotes++;
                        pszSrc++;
                    }
                    if (*pszSrc != '"')
                        /* Not an escape sequence.  */
                        while (cQuotes-- > 0)
                            pszDst = RTStrPutCp(pszDst, '\\');
                    else
                    {
                        /* Escape sequence.  Output half of the slashes.  If odd
                           number, output the escaped double quote . */
                        while (cQuotes >= 2)
                        {
                            pszDst = RTStrPutCp(pszDst, '\\');
                            cQuotes -= 2;
                        }
                        if (!cQuotes)
                            fInQuote = !fInQuote;
                        else
                            pszDst = RTStrPutCp(pszDst, '"');
                        pszSrc++;
                    }
                }
            }
        }

        *pszDst++ = '\0';
        if (RT_FAILURE(rc) || !Cp)
            break;
    }

    if (RT_FAILURE(rc))
    {
        RTMemFree(pszDup);
        RTMemFree(papszArgs);
        return rc;
    }

    /*
     * Terminate the array.
     * Check for empty string to make sure we've got an array.
     */
    if (iArg == 0)
    {
        RTMemFree(pszDup);
        papszArgs = (char **)RTMemAlloc(1 * sizeof(char *));
        if (!papszArgs)
            return VERR_NO_MEMORY;
    }
    papszArgs[iArg] = NULL;

    *pcArgs     = iArg;
    *ppapszArgv = papszArgs;
    return VINF_SUCCESS;
}
int main(int argc, char **argv)
{
    /*
     * Init IPRT.
     */
    int rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);

    /*
     * Locate a native DTrace command binary.
     */
    bool fIsNativeDTrace = false;
    char szDTraceCmd[RTPATH_MAX];
    szDTraceCmd[0] = '\0';

#if defined(RT_OS_DARWIN) || defined(RT_OS_FREEBSD) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
    /*
     * 1. Try native first on platforms where it's applicable.
     */
    static const char * const s_apszNativeDTrace[] =
    {
        "/usr/sbin/dtrace",
        "/sbin/dtrace",
        "/usr/bin/dtrace",
        "/bin/dtrace",
        "/usr/local/sbin/dtrace",
        "/usr/local/bin/dtrace"
    };
    if (!RTEnvExist("VBOX_DTRACE_NO_NATIVE"))
        for (uint32_t i = 0; i < RT_ELEMENTS(s_apszNativeDTrace); i++)
            if (RTFileExists(s_apszNativeDTrace[i]))
            {
                fIsNativeDTrace = true;
                strcpy(szDTraceCmd, s_apszNativeDTrace[i]);
# ifdef RT_OS_LINUX
                /** @todo Warn if the dtrace modules haven't been loaded or vboxdrv isn't
                 *        compiled against them. */
# endif
                break;
            }
    if (szDTraceCmd[0] == '\0')
#endif
    {
        /*
         * 2. VBoxDTrace extension pack installed?
         *
         * Note! We cannot use the COM API here because this program is usually
         *       run thru sudo or directly as root, even if the target
         *       VirtualBox process is running as regular user.  This is due to
         *       the privileges required to run dtrace scripts on a host.
         */
        rc = RTPathAppPrivateArch(szDTraceCmd, sizeof(szDTraceCmd));
        if (RT_SUCCESS(rc))
            rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd),
                              VBOX_EXTPACK_INSTALL_DIR RTPATH_SLASH_STR VBOX_EXTPACK_VBOXDTRACE_MANGLED_NAME);
        if (RT_SUCCESS(rc))
            rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), RTBldCfgTargetDotArch());
        if (RT_SUCCESS(rc))
            rc = RTPathAppend(szDTraceCmd, sizeof(szDTraceCmd), "VBoxDTraceCmd");
        if (RT_SUCCESS(rc))
            rc = RTStrCat(szDTraceCmd, sizeof(szDTraceCmd), RTLdrGetSuff());
        if (RT_FAILURE(rc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing extension pack path: %Rrc", rc);
        if (!RTFileExists(szDTraceCmd))
            return RTMsgErrorExit(RTEXITCODE_FAILURE,
                                  "Unable to find a DTrace implementation. VBoxDTrace Extension Pack installed?");
        fIsNativeDTrace = false;
    }


    /*
     * Construct a new command line that includes our libary.
     */
    char szDTraceLibDir[RTPATH_MAX];
    rc = RTPathAppPrivateNoArch(szDTraceLibDir, sizeof(szDTraceLibDir));
    if (RT_SUCCESS(rc))
        rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), "dtrace" RTPATH_SLASH_STR "lib");
    if (RT_SUCCESS(rc))
        rc = RTPathAppend(szDTraceLibDir, sizeof(szDTraceLibDir), RTBldCfgTargetArch());
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error constructing dtrace library path for VBox: %Rrc", rc);

    char **papszArgs = (char **)RTMemAlloc((argc + 3) * sizeof(char *));
    if (!papszArgs)
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No memory for argument list.");

    int cArgs    = 1;
    papszArgs[0] = fIsNativeDTrace ? szDTraceCmd : argv[0];
    if (argc > 1)
    {
        papszArgs[cArgs++] = (char *)"-L";
        papszArgs[cArgs++] = szDTraceLibDir;
    }
    for (int i = 1; i < argc; i++)
        papszArgs[cArgs++] = argv[i];
    papszArgs[cArgs] = NULL;
    Assert(cArgs <= argc + 3);


    /*
     * The native DTrace we execute as a sub-process and wait for.
     */
    RTEXITCODE rcExit;
    if (fIsNativeDTrace)
    {
        RTPROCESS hProc;
        rc = RTProcCreate(szDTraceCmd, papszArgs, RTENV_DEFAULT, 0, &hProc);
        if (RT_SUCCESS(rc))
        {
            RTPROCSTATUS Status;
            rc = RTProcWait(hProc, RTPROCWAIT_FLAGS_BLOCK, &Status);
            if (RT_SUCCESS(rc))
            {
                if (Status.enmReason == RTPROCEXITREASON_NORMAL)
                    rcExit = (RTEXITCODE)Status.iStatus;
                else
                    rcExit = RTEXITCODE_FAILURE;
            }
            else
                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error waiting for child process: %Rrc", rc);
        }
        else
            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error executing '%s': %Rrc", szDTraceCmd, rc);
    }
    /*
     * While the VBoxDTrace we load and call the main function of.
     */
    else
    {
        RTERRINFOSTATIC ErrInfo;
        RTLDRMOD hMod;
        rc = SUPR3HardenedLdrLoadPlugIn(szDTraceCmd, &hMod, RTErrInfoInitStatic(&ErrInfo));
        if (RT_SUCCESS(rc))
        {
            PFNVBOXDTRACEMAIN pfnVBoxDTraceMain;
            rc = RTLdrGetSymbol(hMod, "VBoxDTraceMain", (void **)&pfnVBoxDTraceMain);
            if (RT_SUCCESS(rc))
                rcExit = (RTEXITCODE)pfnVBoxDTraceMain(cArgs, papszArgs);
            else
                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error locating 'VBoxDTraceMain' in '%s': %Rrc", szDTraceCmd, rc);
        }
        else
            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "Error loading '%s': %Rrc (%s)", szDTraceCmd, rc, ErrInfo.szMsg);
    }
    return rcExit;
}
Example #20
0
static LRESULT vboxClipboardProcessMsg(VBOXCLIPBOARDCONTEXT *pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    LRESULT rc = 0;

    switch (msg)
    {
        case WM_CHANGECBCHAIN:
        {
            HWND hwndRemoved = (HWND)wParam;
            HWND hwndNext    = (HWND)lParam;

            Log(("VBoxTray: vboxClipboardProcessMsg: WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));

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

        case WM_DRAWCLIPBOARD:
        {
            Log(("VBoxTray: vboxClipboardProcessMsg: WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->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. */
                int vboxrc = vboxClipboardChanged(pCtx);
                if (RT_FAILURE(vboxrc))
                    Log(("VBoxTray: vboxClipboardProcessMsg: vboxClipboardChanged failed, rc = %Rrc\n", vboxrc));
            }

            /* Pass the message to next windows in the clipboard chain. */
            SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);
        } break;

        case WM_TIMER:
        {
            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 || pCtx->fCBChainPingInProcess)
            {
                removeFromCBChain(pCtx);
                addToCBChain(pCtx);
            }
            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
             * processed by ourselves to the chain. */
            pCtx->fCBChainPingInProcess = TRUE;
            hViewer = GetClipboardViewer();
            if (hViewer)
                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, CBChainPingProc, (ULONG_PTR) pCtx);
        } break;

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

        case WM_RENDERFORMAT:
        {
            /* Insert the requested clipboard format data into the clipboard. */
            uint32_t u32Format = 0;
            UINT format = (UINT)wParam;

            Log(("VBoxTray: vboxClipboardProcessMsg: WM_RENDERFORMAT, format = %x\n", format));
            switch (format)
            {
                case CF_UNICODETEXT:
                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
                    break;

                case CF_DIB:
                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
                    break;

                default:
                    if (format >= 0xC000)
                    {
                        TCHAR szFormatName[256];

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

            if (u32Format == 0)
            {
                /* Unsupported clipboard format is requested. */
                Log(("VBoxTray: vboxClipboardProcessMsg: Unsupported clipboard format requested: %ld\n", u32Format));
                EmptyClipboard();
            }
            else
            {
                const uint32_t cbPrealloc = 4096; /* @todo r=andy Make it dynamic for supporting larger text buffers! */
                uint32_t cb = 0;

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

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

                    if (pMem)
                    {
                        /* Read the host data to the preallocated buffer. */
                        int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, u32Format, pMem, cbPrealloc, &cb);
                        Log(("VBoxTray: vboxClipboardProcessMsg: 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);
                                Log(("VBoxTray: vboxClipboardProcessMsg: Reallocated hMem = %p\n", hMem));

                                if (hMem)
                                {
                                    pMem = GlobalLock(hMem);
                                    Log(("VBoxTray: vboxClipboardProcessMsg: 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, u32Format, pMem, cb, &cbNew);
                                        Log(("VBoxTray: 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 (u32Format == 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);
                                Log(("VBoxTray: vboxClipboardProcessMsg: Reallocated hMem = %p\n", hMem));

                                if (hMem)
                                {
                                    /* 'hMem' contains the host clipboard data.
                                     * size is 'cb' and format is 'format'. */
                                    HANDLE hClip = SetClipboardData(format, hMem);
                                    Log(("VBoxTray: vboxClipboardProcessMsg: 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. */
                EmptyClipboard();
            }
        } 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.
             */
            if (OpenClipboard(hwnd))
            {
                EmptyClipboard();
                CloseClipboard();
            }
        } break;

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

            if (FALSE == OpenClipboard(hwnd))
            {
                Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER: Failed to open clipboard! Last error = %ld\n", GetLastError()));
            }
            else
            {
                EmptyClipboard();

                HANDLE hClip = NULL;

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                {
                    Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
                    hClip = SetClipboardData(CF_UNICODETEXT, NULL);
                }

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
                    Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
                    hClip = SetClipboardData(CF_DIB, NULL);
                }

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
                {
                    UINT format = RegisterClipboardFormat ("HTML Format");
                    Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));
                    if (format != 0)
                    {
                        hClip = SetClipboardData(format, NULL);
                    }
                }

                CloseClipboard();
                Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER: hClip = %p, err = %ld\n", hClip, GetLastError ()));
            }
        } break;

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

            if (FALSE == OpenClipboard(hwnd))
            {
                Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER: Failed to open clipboard! Last error = %ld\n", GetLastError()));
            }
            else
            {
                int vboxrc;
                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
                    hClip = GetClipboardData(CF_DIB);

                    if (hClip != NULL)
                    {
                        LPVOID lp = GlobalLock(hClip);
                        if (lp != NULL)
                        {
                            Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER + 1: CF_DIB\n"));
                            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)
                        {
                            Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER + 1: CF_UNICODETEXT\n"));
                            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)
                            {
                                Log(("VBoxTray: vboxClipboardProcessMsg: WM_USER + 1: CF_HTML\n"));
                                vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
                                                                  lp, GlobalSize(hClip));
                                GlobalUnlock(hClip);
                            }
                            else
                            {
                                hClip = NULL;
                            }
                        }
                    }
                }

                CloseClipboard();
            }

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

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

    Log(("VBoxTray: vboxClipboardProcessMsg returned with rc = %ld\n", rc));
    return rc;
}
Example #21
0
RTDECL(int) RTGetOptArgvFromString(char ***ppapszArgv, int *pcArgs, const char *pszCmdLine, const char *pszSeparators)
{
    /*
     * Some input validation.
     */
    AssertPtr(pszCmdLine);
    AssertPtr(pcArgs);
    AssertPtr(ppapszArgv);
    if (!pszSeparators)
        pszSeparators = " \t\n\r";
    else
        AssertPtr(pszSeparators);
    size_t const cchSeparators = strlen(pszSeparators);
    AssertReturn(cchSeparators > 0, VERR_INVALID_PARAMETER);

    /*
     * Parse the command line and chop off it into argv individual argv strings.
     */
    int         rc        = VINF_SUCCESS;
    const char *pszSrc    = pszCmdLine;
    char       *pszDup    = (char *)RTMemAlloc(strlen(pszSrc) + 1);
    char       *pszDst    = pszDup;
    if (!pszDup)
        return VERR_NO_STR_MEMORY;
    char      **papszArgs = NULL;
    unsigned    iArg      = 0;
    while (*pszSrc)
    {
        /* Skip stuff */
        rc = rtGetOptSkipDelimiters(&pszSrc, pszSeparators, cchSeparators);
        if (RT_FAILURE(rc))
            break;
        if (!*pszSrc)
            break;

        /* Start a new entry. */
        if ((iArg % 32) == 0)
        {
            void *pvNew = RTMemRealloc(papszArgs, (iArg + 33) * sizeof(char *));
            if (!pvNew)
            {
                rc = VERR_NO_MEMORY;
                break;
            }
            papszArgs = (char **)pvNew;
        }
        papszArgs[iArg++] = pszDst;

        /* Parse and copy the string over. */
        RTUNICP CpQuote = 0;
        RTUNICP Cp;
        for (;;)
        {
            rc = RTStrGetCpEx(&pszSrc, &Cp);
            if (RT_FAILURE(rc) || !Cp)
                break;
            if (!CpQuote)
            {
                if (Cp == '"' || Cp == '\'')
                    CpQuote = Cp;
                else if (rtGetOptIsCpInSet(Cp, pszSeparators, cchSeparators))
                    break;
                else
                    pszDst = RTStrPutCp(pszDst, Cp);
            }
            else if (CpQuote != Cp)
                pszDst = RTStrPutCp(pszDst, Cp);
            else
                CpQuote = 0;
        }
        *pszDst++ = '\0';
        if (RT_FAILURE(rc) || !Cp)
            break;
    }

    if (RT_FAILURE(rc))
    {
        RTMemFree(pszDup);
        RTMemFree(papszArgs);
        return rc;
    }

    /*
     * Terminate the array.
     * Check for empty string to make sure we've got an array.
     */
    if (iArg == 0)
    {
        RTMemFree(pszDup);
        papszArgs = (char **)RTMemAlloc(1 * sizeof(char *));
        if (!papszArgs)
            return VERR_NO_MEMORY;
    }
    papszArgs[iArg] = NULL;

    *pcArgs     = iArg;
    *ppapszArgv = papszArgs;
    return VINF_SUCCESS;
}
Example #22
0
unsigned __stdcall VBoxClipboardThread(void *pInstance)
{
    Log(("VBoxTray: VBoxClipboardThread\n"));

    VBOXCLIPBOARDCONTEXT *pCtx = (VBOXCLIPBOARDCONTEXT *)pInstance;
    AssertPtr(pCtx);

    /* The thread waits for incoming messages from the host. */
    for (;;)
    {
        uint32_t u32Msg;
        uint32_t u32Formats;
        int rc = VbglR3ClipboardGetHostMsg(pCtx->u32ClientID, &u32Msg, &u32Formats);
        if (RT_FAILURE(rc))
        {
            Log(("VBoxTray: VBoxClipboardThread: Failed to call the driver for host message! rc = %Rrc\n", rc));
            if (rc == VERR_INTERRUPTED)
            {
                /* Wait for termination event. */
                WaitForSingleObject(pCtx->pEnv->hStopEvent, INFINITE);
                break;
            }
            /* Wait a bit before retrying. */
            AssertPtr(pCtx->pEnv);
            if (WaitForSingleObject(pCtx->pEnv->hStopEvent, 1000) == WAIT_OBJECT_0)
            {
                break;
            }
            continue;
        }
        else
        {
            Log(("VBoxTray: VBoxClipboardThread: VbglR3ClipboardGetHostMsg u32Msg = %ld, u32Formats = %ld\n", u32Msg, u32Formats));
            switch (u32Msg)
            {
                case VBOX_SHARED_CLIPBOARD_HOST_MSG_FORMATS:
                {
                    /* The host has announced available clipboard formats.
                     * Forward the information to the window, so it can later
                     * respond to WM_RENDERFORMAT message. */
                    ::PostMessage (pCtx->hwnd, WM_USER, 0, u32Formats);
                } break;

                case VBOX_SHARED_CLIPBOARD_HOST_MSG_READ_DATA:
                {
                    /* The host needs data in the specified format. */
                    ::PostMessage (pCtx->hwnd, WM_USER + 1, 0, u32Formats);
                } break;

                case VBOX_SHARED_CLIPBOARD_HOST_MSG_QUIT:
                {
                    /* The host is terminating. */
                    rc = VERR_INTERRUPTED;
                } break;

                default:
                {
                    Log(("VBoxTray: VBoxClipboardThread: Unsupported message from host! Message = %ld\n", u32Msg));
                }
            }
        }
    }
    return 0;
}
Example #23
0
/**
 * Rewinds the tarball file handle and creates a gunzip | tar chain that
 * results in a filesystem stream.
 *
 * @returns VBox status code, failures with message.
 * @param   hTarballFile        The handle to the tarball file.
 * @param   pszError            Where to store an error message on failure.
 * @param   cbError             The size of the buffer @a pszError points to.
 * @param   phTarFss            Where to return the filesystem stream handle.
 * @param   phFileManifest      Where to return a manifest where the tarball is
 *                              gettting hashed.  The entry will be called
 *                              "extpack" and be ready when the file system
 *                              stream is at an end.  Optional.
 */
int VBoxExtPackOpenTarFss(RTFILE hTarballFile, char *pszError, size_t cbError, PRTVFSFSSTREAM phTarFss,
                          PRTMANIFEST phFileManifest)
{
    Assert(cbError > 0);
    *pszError = '\0';
    *phTarFss = NIL_RTVFSFSSTREAM;

    /*
     * Rewind the file and set up a VFS chain for it.
     */
    int rc = RTFileSeek(hTarballFile, 0, RTFILE_SEEK_BEGIN, NULL);
    if (RT_FAILURE(rc))
        return vboxExtPackReturnError(rc, pszError, cbError, "Failed seeking to the start of the tarball: %Rrc", rc);

    RTVFSIOSTREAM hTarballIos;
    rc = RTVfsIoStrmFromRTFile(hTarballFile, RTFILE_O_READ | RTFILE_O_DENY_WRITE | RTFILE_O_OPEN, true /*fLeaveOpen*/,
                               &hTarballIos);
    if (RT_FAILURE(rc))
        return vboxExtPackReturnError(rc, pszError, cbError, "RTVfsIoStrmFromRTFile failed: %Rrc", rc);

    RTMANIFEST hFileManifest = NIL_RTMANIFEST;
    rc = RTManifestCreate(0 /*fFlags*/, &hFileManifest);
    if (RT_SUCCESS(rc))
    {
        RTVFSIOSTREAM hPtIos;
        rc = RTManifestEntryAddPassthruIoStream(hFileManifest, hTarballIos, "extpack", RTMANIFEST_ATTR_SHA256,
                                                true /*read*/, &hPtIos);
        if (RT_SUCCESS(rc))
        {
            RTVFSIOSTREAM hGunzipIos;
            rc = RTZipGzipDecompressIoStream(hPtIos, 0 /*fFlags*/, &hGunzipIos);
            if (RT_SUCCESS(rc))
            {
                RTVFSFSSTREAM hTarFss;
                rc = RTZipTarFsStreamFromIoStream(hGunzipIos, 0 /*fFlags*/, &hTarFss);
                if (RT_SUCCESS(rc))
                {
                    RTVfsIoStrmRelease(hPtIos);
                    RTVfsIoStrmRelease(hGunzipIos);
                    RTVfsIoStrmRelease(hTarballIos);
                    *phTarFss = hTarFss;
                    if (phFileManifest)
                        *phFileManifest = hFileManifest;
                    else
                        RTManifestRelease(hFileManifest);
                    return VINF_SUCCESS;
                }

                vboxExtPackSetError(pszError, cbError, "RTZipTarFsStreamFromIoStream failed: %Rrc", rc);
                RTVfsIoStrmRelease(hGunzipIos);
            }
            else
                vboxExtPackSetError(pszError, cbError, "RTZipGzipDecompressIoStream failed: %Rrc", rc);
            RTVfsIoStrmRelease(hPtIos);
        }
        else
            vboxExtPackSetError(pszError, cbError, "RTManifestEntryAddPassthruIoStream failed: %Rrc", rc);
        RTManifestRelease(hFileManifest);
    }
    else
        vboxExtPackSetError(pszError, cbError, "RTManifestCreate failed: %Rrc", rc);

    RTVfsIoStrmRelease(hTarballIos);
    return rc;
}
int main(int argc, char **argv)
{
    int rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);

    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--samples-per-sec",        's',  RTGETOPT_REQ_UINT32 },
        { "--period-in-samples",      'p',  RTGETOPT_REQ_UINT32 },
        { "--bufsize-in-samples",     'b',  RTGETOPT_REQ_UINT32 },
        { "--total-duration-in-secs", 'd',  RTGETOPT_REQ_UINT32 }
    };

    RTGETOPTSTATE State;
    RTGetOptInit(&State, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
    RTGETOPTUNION ValueUnion;
    int chOpt;
    while ((chOpt = RTGetOpt(&State, &ValueUnion)) != 0)
    {
        switch (chOpt)
        {
            case 's': g_cSamplesPerSec    = ValueUnion.u32; break;
            case 'p': g_cSamplesPerPeriod = ValueUnion.u32; break;
            case 'b': g_cSamplesInBuffer  = ValueUnion.u32; break;
            case 'd': g_rdSecDuration     = ValueUnion.u32; break;
            case 'h':
                RTPrintf("usage: ntPlayToneWaveX.exe\n"
                "[-s|--samples-per-sec]\n"
                "[-p|--period-in-samples]\n"
                "[-b|--bufsize-in-samples]\n"
                "[-d|--total-duration-in-secs]\n"
                         "\n"
                         "Plays sine tone using ancient waveX API\n");
                return 0;

            default:
                return RTGetOptPrintError(chOpt, &ValueUnion);
        }
    }


    WAVEFORMATEX waveFormatEx = { 0 };
    MMRESULT mmresult;

    waveFormatEx.wFormatTag = WAVE_FORMAT_PCM;
    waveFormatEx.nChannels = 2;
    waveFormatEx.nSamplesPerSec = g_cSamplesPerSec;
    waveFormatEx.wBitsPerSample = 16;
    waveFormatEx.nBlockAlign = g_cbSample = waveFormatEx.nChannels * waveFormatEx.wBitsPerSample / 8;
    waveFormatEx.nAvgBytesPerSec = waveFormatEx.nBlockAlign * waveFormatEx.nSamplesPerSec;
    waveFormatEx.cbSize = 0;

    g_hWavEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    mmresult = waveOutOpen(&g_hWaveOut, WAVE_MAPPER, &waveFormatEx, (DWORD_PTR)g_hWavEvent, NULL, CALLBACK_EVENT);

    if (mmresult != MMSYSERR_NOERROR)
    {
        RTMsgError("waveOutOpen failed with 0x%X\n", mmresult);
        return -1;
    }


    uint32_t ui32SamplesToPlayTotal = (uint32_t)(g_rdSecDuration * g_cSamplesPerSec);
    uint32_t ui32SamplesToPlay = ui32SamplesToPlayTotal;
    uint32_t ui32SamplesPlayed = 0;
    uint32_t ui32SamplesForWavBuf;

    WAVEHDR waveHdr1 = {0}, waveHdr2 = {0}, *pWaveHdr, *pWaveHdrPlaying, *pWaveHdrWaiting;
    uint32_t i, k;
    DWORD res;

    int16_t *i16Samples1 = (int16_t *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, g_cSamplesInBuffer * g_cbSample);
    int16_t *i16Samples2 = (int16_t *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, g_cSamplesInBuffer * g_cbSample);

    k = 0; // This is discrete time really!!!

    for (i = 0; i < g_cSamplesInBuffer; i++, k++)
    {
        i16Samples1[2 * i] = (uint16_t)(10000.0 * sin(2.0 * M_PI * k / g_cSamplesPerPeriod));
        i16Samples1[2 * i + 1] = i16Samples1[2 * i];
    }

    ui32SamplesForWavBuf = min(ui32SamplesToPlay, g_cSamplesInBuffer);

    waveHdr1.lpData = (LPSTR)i16Samples1;
    waveHdr1.dwBufferLength = ui32SamplesForWavBuf * g_cbSample;
    waveHdr1.dwFlags = 0;
    waveHdr1.dwLoops = 0;

    ui32SamplesToPlay -= ui32SamplesForWavBuf;
    ui32SamplesPlayed += ui32SamplesForWavBuf;

    pWaveHdrPlaying = &waveHdr1;

    mmresult = waveOutPrepareHeader(g_hWaveOut, pWaveHdrPlaying, sizeof(WAVEHDR));
    mmresult = waveOutWrite(g_hWaveOut, pWaveHdrPlaying, sizeof(WAVEHDR));
    //RTMsgInfo("waveOutWrite completes with %d\n", mmresult);

    res = WaitForSingleObject(g_hWavEvent, INFINITE);
    //RTMsgInfo("WaitForSingleObject completes with %d\n\n", res);

    waveHdr2.lpData = (LPSTR)i16Samples2;
    waveHdr2.dwBufferLength = 0;
    waveHdr2.dwFlags = 0;
    waveHdr2.dwLoops = 0;

    pWaveHdrWaiting = &waveHdr2;

    while (ui32SamplesToPlay > 0)
    {
        int16_t *i16Samples = (int16_t *)pWaveHdrWaiting->lpData;

        for (i = 0; i < g_cSamplesInBuffer; i++, k++)
        {
            i16Samples[2 * i] = (uint16_t)(10000.0 * sin(2.0 * M_PI * k / g_cSamplesPerPeriod));
            i16Samples[2 * i + 1] = i16Samples[2 * i];
        }

        ui32SamplesForWavBuf = min(ui32SamplesToPlay, g_cSamplesInBuffer);

        pWaveHdrWaiting->dwBufferLength = ui32SamplesForWavBuf * g_cbSample;
        pWaveHdrWaiting->dwFlags = 0;
        pWaveHdrWaiting->dwLoops = 0;


        ui32SamplesToPlay -= ui32SamplesForWavBuf;
        ui32SamplesPlayed += ui32SamplesForWavBuf;

        mmresult = waveOutPrepareHeader(g_hWaveOut, pWaveHdrWaiting, sizeof(WAVEHDR));
        mmresult = waveOutWrite(g_hWaveOut, pWaveHdrWaiting, sizeof(WAVEHDR));
        //RTMsgInfo("waveOutWrite completes with %d\n", mmresult);

        res = WaitForSingleObject(g_hWavEvent, INFINITE);
        //RTMsgInfo("WaitForSingleObject completes with %d\n\n", res);

        mmresult = waveOutUnprepareHeader(g_hWaveOut, pWaveHdrPlaying, sizeof(WAVEHDR));
        //RTMsgInfo("waveOutUnprepareHeader completes with %d\n", mmresult);

        pWaveHdr = pWaveHdrWaiting;
        pWaveHdrWaiting = pWaveHdrPlaying;
        pWaveHdrPlaying = pWaveHdr;
    }

    while (mmresult = waveOutUnprepareHeader(g_hWaveOut, pWaveHdrPlaying, sizeof(WAVEHDR)))
    {
        //Expecting WAVERR_STILLPLAYING
        //RTMsgInfo("waveOutUnprepareHeader failed with 0x%X\n", mmresult);
        Sleep(100);
    }

    if (mmresult == MMSYSERR_NOERROR)
    {
        waveOutClose(g_hWaveOut);
    }

    HeapFree(GetProcessHeap(), 0, i16Samples1);
    HeapFree(GetProcessHeap(), 0, i16Samples2);
}
Example #25
0
/**
 * Reads the extension pack descriptor.
 *
 * @returns NULL on success, pointer to an error message on failure (caller
 *          deletes it).
 * @param   a_pszDir        The directory containing the description file.
 * @param   a_pExtPackDesc  Where to store the extension pack descriptor.
 * @param   a_pObjInfo      Where to store the object info for the file (unix
 *                          attribs). Optional.
 */
RTCString *VBoxExtPackLoadDescFromVfsFile(RTVFSFILE hVfsFile, PVBOXEXTPACKDESC a_pExtPackDesc, PRTFSOBJINFO a_pObjInfo)
{
    vboxExtPackClearDesc(a_pExtPackDesc);

    /*
     * Query the object info.
     */
    RTFSOBJINFO ObjInfo;
    int rc = RTVfsFileQueryInfo(hVfsFile, &ObjInfo, RTFSOBJATTRADD_UNIX);
    if (RT_FAILURE(rc))
        return &(new RTCString)->printf("RTVfsFileQueryInfo failed: %Rrc", rc);
    if (a_pObjInfo)
        *a_pObjInfo = ObjInfo;

    /*
     * The simple approach, read the whole thing into memory and pass this to
     * the XML parser.
     */

    /* Check the file size. */
    if (ObjInfo.cbObject > _1M || ObjInfo.cbObject < 0)
        return &(new RTCString)->printf("The XML file is too large (%'RU64 bytes)", ObjInfo.cbObject);
    size_t const cbFile = (size_t)ObjInfo.cbObject;

    /* Rewind to the start of the file. */
    rc = RTVfsFileSeek(hVfsFile, 0, RTFILE_SEEK_BEGIN, NULL);
    if (RT_FAILURE(rc))
        return &(new RTCString)->printf("RTVfsFileSeek(,0,BEGIN) failed: %Rrc", rc);

    /* Allocate memory and read the file content into it. */
    void *pvFile = RTMemTmpAlloc(cbFile);
    if (!pvFile)
        return &(new RTCString)->printf("RTMemTmpAlloc(%zu) failed", cbFile);

    RTCString *pstrErr = NULL;
    rc = RTVfsFileRead(hVfsFile, pvFile, cbFile, NULL);
    if (RT_FAILURE(rc))
        pstrErr = &(new RTCString)->printf("RTVfsFileRead failed: %Rrc", rc);

    /*
     * Parse the file.
     */
    xml::Document Doc;
    if (RT_SUCCESS(rc))
    {
        xml::XmlMemParser   Parser;
        RTCString           strFileName = VBOX_EXTPACK_DESCRIPTION_NAME;
        try
        {
            Parser.read(pvFile, cbFile, strFileName, Doc);
        }
        catch (xml::XmlError Err)
        {
            pstrErr = new RTCString(Err.what());
            rc = VERR_PARSE_ERROR;
        }
    }
    RTMemTmpFree(pvFile);

    /*
     * Hand the xml doc over to the common code.
     */
    if (RT_SUCCESS(rc))
        pstrErr = vboxExtPackLoadDescFromDoc(&Doc, a_pExtPackDesc);

    return pstrErr;
}
Example #26
0
RTDECL(int) RTEnvSetEx(RTENV Env, const char *pszVar, const char *pszValue)
{
    AssertPtrReturn(pszVar, VERR_INVALID_POINTER);
    AssertReturn(*pszVar, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszValue, VERR_INVALID_POINTER);

    int rc;
    if (Env == RTENV_DEFAULT)
    {
        /*
         * Since RTEnvPut isn't UTF-8 clean and actually expects the strings
         * to be in the current code page (codeset), we'll do the necessary
         * conversions here.
         */
        char *pszVarOtherCP;
        rc = RTStrUtf8ToCurrentCP(&pszVarOtherCP, pszVar);
        if (RT_SUCCESS(rc))
        {
            char *pszValueOtherCP;
            rc = RTStrUtf8ToCurrentCP(&pszValueOtherCP, pszValue);
            if (RT_SUCCESS(rc))
            {
                rc = RTEnvSet(pszVarOtherCP, pszValueOtherCP);
                RTStrFree(pszValueOtherCP);
            }
            RTStrFree(pszVarOtherCP);
        }
    }
    else
    {
        PRTENVINTERNAL pIntEnv = Env;
        AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
        AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);

        /*
         * Create the variable string.
         */
        const size_t cchVar = strlen(pszVar);
        const size_t cchValue = strlen(pszValue);
        char *pszEntry = (char *)RTMemAlloc(cchVar + cchValue + 2);
        if (pszEntry)
        {
            memcpy(pszEntry, pszVar, cchVar);
            pszEntry[cchVar] = '=';
            memcpy(&pszEntry[cchVar + 1], pszValue, cchValue + 1);

            RTENV_LOCK(pIntEnv);

            /*
             * Find the location of the variable. (iVar = cVars if new)
             */
            rc = VINF_SUCCESS;
            size_t iVar;
            for (iVar = 0; iVar < pIntEnv->cVars; iVar++)
                if (    !strncmp(pIntEnv->papszEnv[iVar], pszVar, cchVar)
                    &&  pIntEnv->papszEnv[iVar][cchVar] == '=')
                    break;
            if (iVar < pIntEnv->cVars)
            {
                /*
                 * Replace the current entry. Simple.
                 */
                RTMemFree(pIntEnv->papszEnv[iVar]);
                pIntEnv->papszEnv[iVar] = pszEntry;
            }
            else
            {
                /*
                 * Adding a new variable. Resize the array if required
                 * and then insert the new value at the end.
                 */
                if (pIntEnv->cVars + 2 > pIntEnv->cAllocated)
                {
                    void *pvNew = RTMemRealloc(pIntEnv->papszEnv, sizeof(char *) * (pIntEnv->cAllocated + RTENV_GROW_SIZE));
                    if (!pvNew)
                        rc = VERR_NO_MEMORY;
                    else
                    {
                        pIntEnv->papszEnv = (char **)pvNew;
                        pIntEnv->cAllocated += RTENV_GROW_SIZE;
                        for (size_t iNewVar = pIntEnv->cVars; iNewVar < pIntEnv->cAllocated; iNewVar++)
                            pIntEnv->papszEnv[iNewVar] = NULL;
                    }
                }
                if (RT_SUCCESS(rc))
                {
                    pIntEnv->papszEnv[iVar] = pszEntry;
                    pIntEnv->papszEnv[iVar + 1] = NULL; /* this isn't really necessary, but doesn't hurt. */
                    pIntEnv->cVars++;
                    Assert(pIntEnv->cVars == iVar + 1);
                }
            }

            RTENV_UNLOCK(pIntEnv);

            if (RT_FAILURE(rc))
                RTMemFree(pszEntry);
        }
        else
            rc = VERR_NO_MEMORY;
    }
    return rc;
}
Example #27
0
/**
 * Construct a host parallel driver instance.
 *
 * @copydoc FNPDMDRVCONSTRUCT
 */
static DECLCALLBACK(int) drvHostParallelConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
{
    PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL);
    LogFlowFunc(("iInstance=%d\n", pDrvIns->iInstance));

    PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);

    /*
     * Init basic data members and interfaces.
     *
     * Must be done before returning any failure because we've got a destructor.
     */
    pThis->hFileDevice  = NIL_RTFILE;
#ifndef VBOX_WITH_WIN_PARPORT_SUP
    pThis->hWakeupPipeR = NIL_RTPIPE;
    pThis->hWakeupPipeW = NIL_RTPIPE;
#else
    pThis->hWinFileDevice = NIL_RTFILE;
#endif

    pThis->pDrvInsR3                                = pDrvIns;
#ifdef VBOX_WITH_DRVINTNET_IN_R0
    pThis->pDrvInsR0                                = PDMDRVINS_2_R0PTR(pDrvIns);
#endif

    /* IBase. */
    pDrvIns->IBase.pfnQueryInterface                  = drvHostParallelQueryInterface;
    /* IHostParallelConnector. */
    pThis->IHostParallelConnectorR3.pfnWrite            = drvHostParallelWrite;
    pThis->IHostParallelConnectorR3.pfnRead             = drvHostParallelRead;
    pThis->IHostParallelConnectorR3.pfnSetPortDirection = drvHostParallelSetPortDirection;
    pThis->IHostParallelConnectorR3.pfnWriteControl     = drvHostParallelWriteControl;
    pThis->IHostParallelConnectorR3.pfnReadControl      = drvHostParallelReadControl;
    pThis->IHostParallelConnectorR3.pfnReadStatus       = drvHostParallelReadStatus;

    /*
     * Validate the config.
     */
    if (!CFGMR3AreValuesValid(pCfg, "DevicePath\0"))
        return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
                                N_("Unknown host parallel configuration option, only supports DevicePath"));

    /*
     * Query configuration.
     */
    /* Device */
    int rc = CFGMR3QueryStringAlloc(pCfg, "DevicePath", &pThis->pszDevicePath);
    if (RT_FAILURE(rc))
    {
        AssertMsgFailed(("Configuration error: query for \"DevicePath\" string returned %Rra.\n", rc));
        return rc;
    }

    /*
     * Open the device
     */
    rc = RTFileOpen(&pThis->hFileDevice, pThis->pszDevicePath, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    if (RT_FAILURE(rc))
        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Parallel#%d could not open '%s'"),
                                   pDrvIns->iInstance, pThis->pszDevicePath);

#ifndef VBOX_WITH_WIN_PARPORT_SUP
    /*
     * Try to get exclusive access to parallel port
     */
    rc = ioctl(RTFileToNative(pThis->hFileDevice), PPEXCL);
    if (rc < 0)
        return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS,
                                   N_("Parallel#%d could not get exclusive access for parallel port '%s'"
                                      "Be sure that no other process or driver accesses this port"),
                                   pDrvIns->iInstance, pThis->pszDevicePath);

    /*
     * Claim the parallel port
     */
    rc = ioctl(RTFileToNative(pThis->hFileDevice), PPCLAIM);
    if (rc < 0)
        return PDMDrvHlpVMSetError(pDrvIns, RTErrConvertFromErrno(errno), RT_SRC_POS,
                                   N_("Parallel#%d could not claim parallel port '%s'"
                                      "Be sure that no other process or driver accesses this port"),
                                   pDrvIns->iInstance, pThis->pszDevicePath);

    /*
     * Get the IHostParallelPort interface of the above driver/device.
     */
    pThis->pDrvHostParallelPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIHOSTPARALLELPORT);
    if (!pThis->pDrvHostParallelPort)
        return PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_MISSING_INTERFACE_ABOVE, RT_SRC_POS, N_("Parallel#%d has no parallel port interface above"),
                                   pDrvIns->iInstance);

    /*
     * Create wakeup pipe.
     */
    rc = RTPipeCreate(&pThis->hWakeupPipeR, &pThis->hWakeupPipeW, 0 /*fFlags*/);
    AssertRCReturn(rc, rc);

    /*
     * Start in SPP mode.
     */
    pThis->enmModeCur = PDM_PARALLEL_PORT_MODE_INVALID;
    rc = drvHostParallelSetMode(pThis, PDM_PARALLEL_PORT_MODE_SPP);
    if (RT_FAILURE(rc))
        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot change mode of parallel mode to SPP"), pDrvIns->iInstance);

    /*
     * Start waiting for interrupts.
     */
    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0,
                               RTTHREADTYPE_IO, "ParMon");
    if (RT_FAILURE(rc))
        return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot create monitor thread"), pDrvIns->iInstance);

#else /* VBOX_WITH_WIN_PARPORT_SUP */
    pThis->fParportAvail     = false;
    pThis->u32LptAddr        = 0;
    pThis->u32LptAddrControl = 0;
    pThis->u32LptAddrStatus  = 0;
    rc = drvWinHostGetparportAddr(pThis);

    /* If we have the char port availabe use it , else I am not getting exclusive access to parallel port.
       Read and write will be done only if addresses are available
    */
    if (pThis->szParportName)
    {
        rc = RTFileOpen(&pThis->hWinFileDevice, (char *)pThis->szParportName,
                        RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    }
#endif
    return VINF_SUCCESS;
}
Example #28
0
RTDECL(int) RTEnvQueryUtf16Block(RTENV hEnv, PRTUTF16 *ppwszzBlock)
{
    RTENV           hClone  = NIL_RTENV;
    PRTENVINTERNAL  pIntEnv;
    int             rc;

    /*
     * Validate / simplify input.
     */
    if (hEnv == RTENV_DEFAULT)
    {
        rc = RTEnvClone(&hClone, RTENV_DEFAULT);
        if (RT_FAILURE(rc))
            return rc;
        pIntEnv = hClone;
    }
    else
    {
        pIntEnv = hEnv;
        AssertPtrReturn(pIntEnv, VERR_INVALID_HANDLE);
        AssertReturn(pIntEnv->u32Magic == RTENV_MAGIC, VERR_INVALID_HANDLE);
        rc = VINF_SUCCESS;
    }

    RTENV_LOCK(pIntEnv);

    /*
     * Sort it first.
     */
    RTSortApvShell((void **)pIntEnv->papszEnv, pIntEnv->cVars, rtEnvSortCompare, pIntEnv);

    /*
     * Calculate the size.
     */
    size_t cwc;
    size_t cwcTotal = 2;
    for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
    {
        rc = RTStrCalcUtf16LenEx(pIntEnv->papszEnv[iVar], RTSTR_MAX, &cwc);
        AssertRCBreak(rc);
        cwcTotal += cwc + 1;
    }

    PRTUTF16 pwszzBlock = NULL;
    if (RT_SUCCESS(rc))
    {
        /*
         * Perform the conversion.
         */
        PRTUTF16 pwszz = pwszzBlock = (PRTUTF16)RTMemAlloc(cwcTotal * sizeof(RTUTF16));
        if (pwszz)
        {
            size_t cwcLeft = cwcTotal;
            for (size_t iVar = 0; iVar < pIntEnv->cVars; iVar++)
            {
                rc = RTStrToUtf16Ex(pIntEnv->papszEnv[iVar], RTSTR_MAX,
                                    &pwszz, cwcTotal - (pwszz - pwszzBlock), &cwc);
                AssertRCBreak(rc);
                pwszz   += cwc + 1;
                cwcLeft -= cwc + 1;
                AssertBreakStmt(cwcLeft >= 2, rc = VERR_INTERNAL_ERROR_3);
            }
            AssertStmt(cwcLeft == 2 || RT_FAILURE(rc), rc = VERR_INTERNAL_ERROR_2);
            if (RT_SUCCESS(rc))
            {
                pwszz[0] = '\0';
                pwszz[1] = '\0';
            }
            else
            {
                RTMemFree(pwszzBlock);
                pwszzBlock = NULL;
            }
        }
        else
            rc = VERR_NO_MEMORY;
    }

    RTENV_UNLOCK(pIntEnv);

    if (hClone != NIL_RTENV)
        RTEnvDestroy(hClone);
    if (RT_SUCCESS(rc))
        *ppwszzBlock = pwszzBlock;
    return rc;
}
int main()
{
    char szPath[RTPATH_MAX];

    /*
     * Init RT+Test.
     */
    RTTEST hTest;
    int rc = RTTestInitAndCreate("tstRTPath", &hTest);
    if (rc)
        return rc;
    RTTestBanner(hTest);

    RTTestSub(hTest, "Environment");
#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
    RTTESTI_CHECK(RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS);
# if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS
# else
    RTTestIFailed("#if RTPATH_STYLE == RTPATH_STR_F_STYLE_DOS");
# endif
    RTTESTI_CHECK(strcmp(RTPATH_SLASH_STR, "\\") == 0);
    RTTESTI_CHECK(RTPATH_SLASH == '\\');
    RTTESTI_CHECK(RTPATH_IS_SEP('/'));
    RTTESTI_CHECK(RTPATH_IS_SEP('\\'));
    RTTESTI_CHECK(RTPATH_IS_SEP(':'));

#else
    RTTESTI_CHECK(RTPATH_STYLE == RTPATH_STR_F_STYLE_UNIX);
# if RTPATH_STYLE == RTPATH_STR_F_STYLE_UNIX
# else
    RTTestIFailed("#if RTPATH_STYLE == RTPATH_STR_F_STYLE_UNIX");
# endif
    RTTESTI_CHECK(strcmp(RTPATH_SLASH_STR, "/") == 0);
    RTTESTI_CHECK(RTPATH_SLASH == '/');
    RTTESTI_CHECK(RTPATH_IS_SEP('/'));
    RTTESTI_CHECK(!RTPATH_IS_SEP('\\'));
    RTTESTI_CHECK(!RTPATH_IS_SEP(':'));
#endif

    /*
     * RTPathExecDir, RTPathUserHome and RTProcGetExecutablePath.
     */
    RTTestSub(hTest, "RTPathExecDir");
    RTTESTI_CHECK_RC(rc = RTPathExecDir(szPath, sizeof(szPath)), VINF_SUCCESS);
    if (RT_SUCCESS(rc))
        RTTestIPrintf(RTTESTLVL_INFO, "ExecDir={%s}\n", szPath);

    RTTestSub(hTest, "RTProcGetExecutablePath");
    if (RTProcGetExecutablePath(szPath, sizeof(szPath)) == szPath)
        RTTestIPrintf(RTTESTLVL_INFO, "ExecutableName={%s}\n", szPath);
    else
        RTTestIFailed("RTProcGetExecutablePath -> NULL");

    RTTestSub(hTest, "RTPathUserHome");
    RTTESTI_CHECK_RC(rc = RTPathUserHome(szPath, sizeof(szPath)), VINF_SUCCESS);
    if (RT_SUCCESS(rc))
        RTTestIPrintf(RTTESTLVL_INFO, "UserHome={%s}\n", szPath);

    RTTestSub(hTest, "RTPathUserDocuments");
    RTTESTI_CHECK_RC(rc = RTPathUserDocuments(szPath, sizeof(szPath)), VINF_SUCCESS);
    if (RT_SUCCESS(rc))
        RTTestIPrintf(RTTESTLVL_INFO, "UserDocuments={%s}\n", szPath);

    RTTestSub(hTest, "RTPathTemp");
    RTTESTI_CHECK_RC(rc = RTPathTemp(szPath, sizeof(szPath)), VINF_SUCCESS);
    if (RT_SUCCESS(rc))
        RTTestIPrintf(RTTESTLVL_INFO, "PathTemp={%s}\n", szPath);
    size_t cch = strlen(szPath);
    RTTESTI_CHECK_RC(RTPathTemp(szPath, cch), VERR_BUFFER_OVERFLOW);
    RTTESTI_CHECK_RC(RTPathTemp(szPath, cch+1), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTPathTemp(szPath, cch+2), VINF_SUCCESS);


    /*
     * RTPathAbsEx
     */
    RTTestSub(hTest, "RTPathAbsEx");
    static const struct
    {
        const char *pcszInputBase;
        const char *pcszInputPath;
        int rc;
        const char *pcszOutput;
    }
    s_aRTPathAbsExTests[] =
    {
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
        { NULL, "", VERR_INVALID_PARAMETER, NULL },
        { NULL, ".", VINF_SUCCESS, "%p" },
        { NULL, "\\", VINF_SUCCESS, "%d\\" },
        { NULL, "\\..", VINF_SUCCESS, "%d\\" },
        { NULL, "/absolute/..", VINF_SUCCESS, "%d\\" },
        { NULL, "/absolute\\\\../..", VINF_SUCCESS, "%d\\" },
        { NULL, "/absolute//../path\\", VINF_SUCCESS, "%d\\path" },
        { NULL, "/absolute/../../path", VINF_SUCCESS, "%d\\path" },
        { NULL, "relative/../dir\\.\\.\\.\\file.txt", VINF_SUCCESS, "%p\\dir\\file.txt" },
        { NULL, "\\data\\", VINF_SUCCESS, "%d\\data" },
        { "relative_base/dir\\", "\\from_root", VINF_SUCCESS, "%d\\from_root" },
        { "relative_base/dir/", "relative_also", VINF_SUCCESS, "%p\\relative_base\\dir\\relative_also" },
#else
        { NULL, "", VERR_INVALID_PARAMETER, NULL },
        { NULL, ".", VINF_SUCCESS, "%p" },
        { NULL, "/", VINF_SUCCESS, "/" },
        { NULL, "/..", VINF_SUCCESS, "/" },
        { NULL, "/absolute/..", VINF_SUCCESS, "/" },
        { NULL, "/absolute\\\\../..", VINF_SUCCESS, "/" },
        { NULL, "/absolute//../path/", VINF_SUCCESS, "/path" },
        { NULL, "/absolute/../../path", VINF_SUCCESS, "/path" },
        { NULL, "relative/../dir/./././file.txt", VINF_SUCCESS, "%p/dir/file.txt" },
        { NULL, "relative/../dir\\.\\.\\.\\file.txt", VINF_SUCCESS, "%p/dir\\.\\.\\.\\file.txt" },  /* linux-specific */
        { NULL, "/data/", VINF_SUCCESS, "/data" },
        { "relative_base/dir/", "/from_root", VINF_SUCCESS, "/from_root" },
        { "relative_base/dir/", "relative_also", VINF_SUCCESS, "%p/relative_base/dir/relative_also" },
#endif
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
        { NULL, "C:\\", VINF_SUCCESS, "C:\\" },
        { "C:\\", "..", VINF_SUCCESS, "C:\\" },
        { "C:\\temp", "..", VINF_SUCCESS, "C:\\" },
        { "C:\\VirtualBox/Machines", "..\\VirtualBox.xml", VINF_SUCCESS, "C:\\VirtualBox\\VirtualBox.xml" },
        { "C:\\MustDie", "\\from_root/dir/..", VINF_SUCCESS, "C:\\from_root" },
        { "C:\\temp", "D:\\data", VINF_SUCCESS, "D:\\data" },
        { NULL, "\\\\server\\..\\share", VINF_SUCCESS, "\\\\server\\..\\share" /* kind of strange */ },
        { NULL, "\\\\server/", VINF_SUCCESS, "\\\\server\\" },
        { NULL, "\\\\", VINF_SUCCESS, "\\\\" },
        { NULL, "\\\\\\something", VINF_SUCCESS, "\\\\\\something" /* kind of strange */ },
        { "\\\\server\\share_as_base", "/from_root", VINF_SUCCESS, "\\\\server\\from_root" },
        { "\\\\just_server", "/from_root", VINF_SUCCESS, "\\\\just_server\\from_root" },
        { "\\\\server\\share_as_base", "relative\\data", VINF_SUCCESS, "\\\\server\\share_as_base\\relative\\data" },
        { "base", "\\\\?\\UNC\\relative/edwef/..", VINF_SUCCESS, "\\\\?\\UNC\\relative" },
        { "\\\\?\\UNC\\base", "/from_root", VERR_INVALID_NAME, NULL },
#else
        { "/temp", "..", VINF_SUCCESS, "/" },
        { "/VirtualBox/Machines", "../VirtualBox.xml", VINF_SUCCESS, "/VirtualBox/VirtualBox.xml" },
        { "/MustDie", "/from_root/dir/..", VINF_SUCCESS, "/from_root" },
        { "\\temp", "\\data", VINF_SUCCESS, "%p/\\temp/\\data" },
#endif
    };

    for (unsigned i = 0; i < RT_ELEMENTS(s_aRTPathAbsExTests); ++ i)
    {
        rc = RTPathAbsEx(s_aRTPathAbsExTests[i].pcszInputBase,
                         s_aRTPathAbsExTests[i].pcszInputPath,
                         szPath, sizeof(szPath));
        if (rc != s_aRTPathAbsExTests[i].rc)
        {
            RTTestIFailed("unexpected result code!\n"
                          "   input base: '%s'\n"
                          "   input path: '%s'\n"
                          "       output: '%s'\n"
                          "           rc: %Rrc\n"
                          "  expected rc: %Rrc",
                          s_aRTPathAbsExTests[i].pcszInputBase,
                          s_aRTPathAbsExTests[i].pcszInputPath,
                          szPath, rc,
                          s_aRTPathAbsExTests[i].rc);
            continue;
        }

        char szTmp[RTPATH_MAX];
        char *pszExpected = NULL;
        if (s_aRTPathAbsExTests[i].pcszOutput != NULL)
        {
            if (s_aRTPathAbsExTests[i].pcszOutput[0] == '%')
            {
                RTTESTI_CHECK_RC(rc = RTPathGetCurrent(szTmp, sizeof(szTmp)), VINF_SUCCESS);
                if (RT_FAILURE(rc))
                    break;

                pszExpected = szTmp;

                if (s_aRTPathAbsExTests[i].pcszOutput[1] == 'p')
                {
                    cch = strlen(szTmp);
                    if (cch + strlen(s_aRTPathAbsExTests[i].pcszOutput) - 2 <= sizeof(szTmp))
                        strcpy(szTmp + cch, s_aRTPathAbsExTests[i].pcszOutput + 2);
                }
#if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS)
                else if (s_aRTPathAbsExTests[i].pcszOutput[1] == 'd')
                {
                    if (2 + strlen(s_aRTPathAbsExTests[i].pcszOutput) - 2 <= sizeof(szTmp))
                        strcpy(szTmp + 2, s_aRTPathAbsExTests[i].pcszOutput + 2);
                }
#endif
            }
            else
            {
                strcpy(szTmp, s_aRTPathAbsExTests[i].pcszOutput);
                pszExpected = szTmp;
            }

            if (strcmp(szPath, pszExpected))
            {
                RTTestIFailed("Unexpected result\n"
                              "   input base: '%s'\n"
                              "   input path: '%s'\n"
                              "       output: '%s'\n"
                              "     expected: '%s'",
                              s_aRTPathAbsExTests[i].pcszInputBase,
                              s_aRTPathAbsExTests[i].pcszInputPath,
                              szPath,
                              s_aRTPathAbsExTests[i].pcszOutput);
            }
        }
    }

    /*
     * RTPathStripFilename
     */
    RTTestSub(hTest, "RTPathStripFilename");
    static const char *s_apszStripFilenameTests[] =
    {
        "/usr/include///",              "/usr/include//",
        "/usr/include/",                "/usr/include",
        "/usr/include",                 "/usr",
        "/usr",                         "/",
        "usr",                          ".",
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
        "c:/windows",                   "c:/",
        "c:/",                          "c:/",
        "D:",                           "D:",
        "C:\\OS2\\DLLS",                "C:\\OS2",
#endif
    };
    for (unsigned i = 0; i < RT_ELEMENTS(s_apszStripFilenameTests); i += 2)
    {
        const char *pszInput  = s_apszStripFilenameTests[i];
        const char *pszExpect = s_apszStripFilenameTests[i + 1];
        strcpy(szPath, pszInput);
        RTPathStripFilename(szPath);
        if (strcmp(szPath, pszExpect))
        {
            RTTestIFailed("Unexpected result\n"
                          "   input: '%s'\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszInput, szPath, pszExpect);
        }
    }

    /*
     * RTPathAppend.
     */
    RTTestSub(hTest, "RTPathAppend");
    static const char *s_apszAppendTests[] =
    {
        /* base                 append                  result */
        "/",                    "",                     "/",
        "",                     "/",                    "/",
        "/",                    "/",                    "/",
        "/x",                   "",                     "/x",
        "/x",                   "/",                    "/x/",
        "/",                    "x",                    "/x",
        "dir",                  "file",                 "dir/file",
        "dir",                  "/file",                "dir/file",
        "dir",                  "//file",               "dir/file",
        "dir",                  "///file",              "dir/file",
        "dir/",                 "/file",                "dir/file",
        "dir/",                 "//file",               "dir/file",
        "dir/",                 "///file",              "dir/file",
        "dir//",                "file",                 "dir/file",
        "dir//",                "/file",                "dir/file",
        "dir//",                "//file",               "dir/file",
        "dir///",               "///file",              "dir/file",
        "/bin/testcase",        "foo.r0",               "/bin/testcase/foo.r0",
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
        "/",                    "\\",                   "/",
        "\\",                   "/",                    "\\",
        "\\\\srv\\shr",         "dir//",                "\\\\srv\\shr/dir//",
        "\\\\srv\\shr",         "dir//file",            "\\\\srv\\shr/dir//file",
        "\\\\srv\\shr",         "//dir//",              "\\\\srv\\shr/dir//",
        "\\\\srv\\shr",         "/\\dir//",             "\\\\srv\\shr\\dir//",
        "\\\\",                 "not-srv/not-shr/file", "\\not-srv/not-shr/file",
        "C:",                   "autoexec.bat",         "C:autoexec.bat",
        "C:",                   "/autoexec.bat",        "C:/autoexec.bat",
        "C:",                   "\\autoexec.bat",       "C:\\autoexec.bat",
        "C:\\",                 "/autoexec.bat",        "C:\\autoexec.bat",
        "C:\\\\",               "autoexec.bat",         "C:\\autoexec.bat",
        "E:\\bin\\testcase",    "foo.r0",               "E:\\bin\\testcase/foo.r0",
#endif
    };
    for (unsigned i = 0; i < RT_ELEMENTS(s_apszAppendTests); i += 3)
    {
        const char *pszInput  = s_apszAppendTests[i];
        const char *pszAppend = s_apszAppendTests[i + 1];
        const char *pszExpect = s_apszAppendTests[i + 2];
        strcpy(szPath, pszInput);
        RTTESTI_CHECK_RC(rc = RTPathAppend(szPath, sizeof(szPath), pszAppend), VINF_SUCCESS);
        if (RT_FAILURE(rc))
            continue;
        if (strcmp(szPath, pszExpect))
        {
            RTTestIFailed("Unexpected result\n"
                          "   input: '%s'\n"
                          "  append: '%s'\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszInput, pszAppend, szPath, pszExpect);
        }
        else
        {
            size_t const cchResult = strlen(szPath);

            strcpy(szPath, pszInput);
            RTTESTI_CHECK_RC(rc = RTPathAppend(szPath, cchResult + 2, pszAppend), VINF_SUCCESS);
            RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));

            strcpy(szPath, pszInput);
            RTTESTI_CHECK_RC(rc = RTPathAppend(szPath, cchResult + 1, pszAppend), VINF_SUCCESS);
            RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));

            if (strlen(pszInput) < cchResult)
            {
                strcpy(szPath, pszInput);
                RTTESTI_CHECK_RC(RTPathAppend(szPath, cchResult, pszAppend), VERR_BUFFER_OVERFLOW);
            }
        }
    }

    /*
     * RTPathJoin - reuse the append tests.
     */
    RTTestSub(hTest, "RTPathJoin");
    for (unsigned i = 0; i < RT_ELEMENTS(s_apszAppendTests); i += 3)
    {
        const char *pszInput  = s_apszAppendTests[i];
        const char *pszAppend = s_apszAppendTests[i + 1];
        const char *pszExpect = s_apszAppendTests[i + 2];

        memset(szPath, 'a', sizeof(szPath));
        szPath[sizeof(szPath) - 1] = '\0';

        RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, sizeof(szPath), pszInput, pszAppend), VINF_SUCCESS);
        if (RT_FAILURE(rc))
            continue;
        if (strcmp(szPath, pszExpect))
        {
            RTTestIFailed("Unexpected result\n"
                          "   input: '%s'\n"
                          "  append: '%s'\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszInput, pszAppend, szPath, pszExpect);
        }
        else
        {
            size_t const cchResult = strlen(szPath);

            memset(szPath, 'a', sizeof(szPath));
            szPath[sizeof(szPath) - 1] = '\0';
            RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, cchResult + 2, pszInput, pszAppend), VINF_SUCCESS);
            RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));

            memset(szPath, 'a', sizeof(szPath));
            szPath[sizeof(szPath) - 1] = '\0';
            RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, cchResult + 1, pszInput, pszAppend), VINF_SUCCESS);
            RTTESTI_CHECK(RT_FAILURE(rc) || !strcmp(szPath, pszExpect));

            RTTESTI_CHECK_RC(rc = RTPathJoin(szPath, cchResult, pszInput, pszAppend), VERR_BUFFER_OVERFLOW);
        }
    }

    /*
     * RTPathJoinA - reuse the append tests.
     */
    RTTestSub(hTest, "RTPathJoinA");
    for (unsigned i = 0; i < RT_ELEMENTS(s_apszAppendTests); i += 3)
    {
        const char *pszInput  = s_apszAppendTests[i];
        const char *pszAppend = s_apszAppendTests[i + 1];
        const char *pszExpect = s_apszAppendTests[i + 2];

        char *pszPathDst;
        RTTESTI_CHECK(pszPathDst = RTPathJoinA(pszInput, pszAppend));
        if (!pszPathDst)
            continue;
        if (strcmp(pszPathDst, pszExpect))
        {
            RTTestIFailed("Unexpected result\n"
                          "   input: '%s'\n"
                          "  append: '%s'\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszInput, pszAppend, pszPathDst, pszExpect);
        }
        RTStrFree(pszPathDst);
    }

    /*
     * RTPathStripTrailingSlash
     */
    static const char *s_apszStripTrailingSlash[] =
    {
        /* input                   result */
        "/",                    "/",
        "//",                   "/",
        "////////////////////", "/",
        "/tmp",                 "/tmp",
        "/tmp////////////////", "/tmp",
        "tmp",                  "tmp",
        "tmp////////////////",  "tmp",
        "./",                   ".",
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
        "////////////////////", "/",
        "D:",                   "D:",
        "D:/",                  "D:/",
        "D:\\",                 "D:\\",
        "D:\\/\\",              "D:\\",
        "D:/\\/\\",             "D:/",
        "C:/Temp",              "C:/Temp",
        "C:/Temp/",             "C:/Temp",
        "C:/Temp\\/",           "C:/Temp",
#endif
    };
    for (unsigned i = 0; i < RT_ELEMENTS(s_apszStripTrailingSlash); i += 2)
    {
        const char *pszInput  = s_apszStripTrailingSlash[i];
        const char *pszExpect = s_apszStripTrailingSlash[i + 1];

        strcpy(szPath, pszInput);
        cch = RTPathStripTrailingSlash(szPath);
        if (strcmp(szPath, pszExpect))
            RTTestIFailed("Unexpected result\n"
                          "   input: '%s'\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszInput, szPath, pszExpect);
        else
            RTTESTI_CHECK(cch == strlen(szPath));
    }

    /*
     * RTPathCountComponents
     */
    RTTestSub(hTest, "RTPathCountComponents");
    RTTESTI_CHECK(RTPathCountComponents("") == 0);
    RTTESTI_CHECK(RTPathCountComponents("/") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//////////////") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//////////////bin") == 2);
    RTTESTI_CHECK(RTPathCountComponents("//////////////bin/") == 2);
    RTTESTI_CHECK(RTPathCountComponents("//////////////bin/////") == 2);
    RTTESTI_CHECK(RTPathCountComponents("..") == 1);
    RTTESTI_CHECK(RTPathCountComponents("../") == 1);
    RTTESTI_CHECK(RTPathCountComponents("../..") == 2);
    RTTESTI_CHECK(RTPathCountComponents("../../") == 2);
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
    RTTESTI_CHECK(RTPathCountComponents("d:") == 1);
    RTTESTI_CHECK(RTPathCountComponents("d:/") == 1);
    RTTESTI_CHECK(RTPathCountComponents("d:/\\") == 1);
    RTTESTI_CHECK(RTPathCountComponents("d:\\") == 1);
    RTTESTI_CHECK(RTPathCountComponents("c:\\config.sys") == 2);
    RTTESTI_CHECK(RTPathCountComponents("c:\\windows") == 2);
    RTTESTI_CHECK(RTPathCountComponents("c:\\windows\\") == 2);
    RTTESTI_CHECK(RTPathCountComponents("c:\\windows\\system32") == 3);
    RTTESTI_CHECK(RTPathCountComponents("//./C$") == 1);
    RTTESTI_CHECK(RTPathCountComponents("\\\\.\\C$") == 1);
    RTTESTI_CHECK(RTPathCountComponents("/\\.\\C$") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//myserver") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//myserver/") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//myserver/share") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//myserver/share/") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\") == 1);
    RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\x") == 2);
    RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\x\\y") == 3);
    RTTESTI_CHECK(RTPathCountComponents("//myserver/share\\x\\y\\") == 3);
#endif

    /*
     * RTPathCopyComponents
     */
    struct
    {
        const char *pszSrc;
        size_t      cComponents;
        const char *pszResult;
    } s_aCopyComponents[] =
    {
        { "",                           0, "" },
        { "",                           5, "" },
        { "/",                          0, "" },
        { "/",                          1, "/" },
        { "/",                          2, "/" },
        { "/usr/bin/sed",               0, "" },
        { "/usr/bin/sed",               1, "/" },
        { "/usr/bin/sed",               2, "/usr/" },
        { "/usr/bin/sed",               3, "/usr/bin/" },
        { "/usr/bin/sed",               4, "/usr/bin/sed" },
        { "/usr/bin/sed",               5, "/usr/bin/sed" },
        { "/usr/bin/sed",               6, "/usr/bin/sed" },
        { "/usr///bin/sed",             2, "/usr///" },
    };
    for (unsigned i = 0; i < RT_ELEMENTS(s_aCopyComponents); i++)
    {
        const char *pszInput    = s_aCopyComponents[i].pszSrc;
        size_t      cComponents = s_aCopyComponents[i].cComponents;
        const char *pszResult   = s_aCopyComponents[i].pszResult;

        memset(szPath, 'a', sizeof(szPath));
        rc = RTPathCopyComponents(szPath, sizeof(szPath), pszInput, cComponents);
        RTTESTI_CHECK_RC(rc, VINF_SUCCESS);
        if (RT_SUCCESS(rc) && strcmp(szPath, pszResult))
            RTTestIFailed("Unexpected result\n"
                          "   input: '%s' cComponents=%u\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszInput, cComponents, szPath, pszResult);
        else if (RT_SUCCESS(rc))
        {
            RTTESTI_CHECK_RC(RTPathCopyComponents(szPath, strlen(pszResult) + 1, pszInput, cComponents), VINF_SUCCESS);
            RTTESTI_CHECK_RC(RTPathCopyComponents(szPath, strlen(pszResult), pszInput, cComponents), VERR_BUFFER_OVERFLOW);
        }
    }


    /*
     * RTPathStripSuffix
     */
    RTTestSub(hTest, "RTPathStripSuffix");
    struct
    {
        const char *pszSrc;
        const char *pszResult;
    } s_aStripExt[] =
    {
        { "filename.ext",               "filename" },
        { "filename.ext1.ext2.ext3",    "filename.ext1.ext2" },
        { "filename..ext",              "filename." },
        { "filename.ext.",              "filename.ext." },
    };
    for (unsigned i = 0; i < RT_ELEMENTS(s_aStripExt); i++)
    {
        const char *pszInput    = s_aStripExt[i].pszSrc;
        const char *pszResult   = s_aStripExt[i].pszResult;

        strcpy(szPath, pszInput);
        RTPathStripSuffix(szPath);
        if (strcmp(szPath, pszResult))
            RTTestIFailed("Unexpected result\n"
                          "   input: '%s'\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszInput, szPath, pszResult);
    }

    /*
     * RTPathCalcRelative
     */
    RTTestSub(hTest, "RTPathCalcRelative");
    struct
    {
        const char *pszFrom;
        const char *pszTo;
        int rc;
        const char *pszExpected;
    } s_aRelPath[] =
    {
        { "/home/test.ext", "/home/test2.ext", VINF_SUCCESS, "test2.ext"},
        { "/dir/test.ext", "/dir/dir2/test2.ext", VINF_SUCCESS, "dir2/test2.ext"},
        { "/dir/dir2/test.ext", "/dir/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "test2.ext"},
        { "/dir/dir2/test.ext", "/dir/dir3/test2.ext", VINF_SUCCESS, ".." RTPATH_SLASH_STR "dir3/test2.ext"},
#if defined (RT_OS_OS2) || defined (RT_OS_WINDOWS)
        { "\\\\server\\share\\test.ext", "\\\\server\\share2\\test2.ext", VERR_NOT_SUPPORTED, ""},
        { "c:\\dir\\test.ext", "f:\\dir\\test.ext", VERR_NOT_SUPPORTED, ""}
#endif
    };
    for (unsigned i = 0; i < RT_ELEMENTS(s_aRelPath); i++)
    {
        const char *pszFrom = s_aRelPath[i].pszFrom;
        const char *pszTo   = s_aRelPath[i].pszTo;

        rc = RTPathCalcRelative(szPath, sizeof(szPath), pszFrom, pszTo);
        if (rc != s_aRelPath[i].rc)
            RTTestIFailed("Unexpected return code\n"
                          "     got: %Rrc\n"
                          "expected: %Rrc",
                          rc, s_aRelPath[i].rc);
        else if (   RT_SUCCESS(rc)
                    && strcmp(szPath, s_aRelPath[i].pszExpected))
            RTTestIFailed("Unexpected result\n"
                          "    from: '%s'\n"
                          "      to: '%s'\n"
                          "  output: '%s'\n"
                          "expected: '%s'",
                          pszFrom, pszTo, szPath, s_aRelPath[i].pszExpected);
    }

    testParserAndSplitter(hTest);

    /*
     * Summary.
     */
    return RTTestSummaryAndDestroy(hTest);
}
Example #30
0
bool writeQuoted(enum ENMFORMAT enmFormat, const char *pcszQuoted)
{
    /* Was the last character seen a back slash? */
    bool fEscaped = false;
    /* Was the last character seen an argument separator (an unescaped space)?
     */
    bool fNextArgument = false;

    if (enmFormat == FORMAT_SHELL)
        if (!outputCharacter('\''))
            return false;
    for (; *pcszQuoted; ++pcszQuoted)
    {
        if (fEscaped)
        {
            bool fRc = true;
            const char (*pachEscapes)[2];
            fEscaped = false;
            /* One-letter escapes. */
            for (pachEscapes = aachEscapes; (*pachEscapes)[0]; ++pachEscapes)
                if (*pcszQuoted == (*pachEscapes)[0])
                {
                    if (!escapeAndOutputCharacter(enmFormat, (*pachEscapes)[1]))
                        return false;
                    break;
                }
            if ((*pachEscapes)[0])
                continue;
            /* Octal. */
            if (*pcszQuoted >= '0' && *pcszQuoted <= '7')
            {
                uint8_t cNum;
                char *pchNext;
                char achDigits[4];
                int rc;
                RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted);
                rc = RTStrToUInt8Ex(achDigits, &pchNext, 8, &cNum);
                if (rc == VWRN_NUMBER_TOO_BIG)
                {
                    RTStrmPrintf(g_pStdErr, "Invalid octal sequence at \"%.16s\"\n",
                                 pcszQuoted - 1);
                    return false;
                }
                if (!escapeAndOutputCharacter(enmFormat, cNum))
                    return false;
                pcszQuoted += pchNext - achDigits - 1;
                continue;
            }
            /* Hexadecimal. */
            if (*pcszQuoted == 'x')
            {
                uint8_t cNum;
                char *pchNext;
                char achDigits[3];
                int rc;
                RTStrCopy(achDigits, sizeof(achDigits), pcszQuoted + 1);
                rc = RTStrToUInt8Ex(achDigits, &pchNext, 16, &cNum);
                if (   rc == VWRN_NUMBER_TOO_BIG
                    || rc == VWRN_NEGATIVE_UNSIGNED
                    || RT_FAILURE(rc))
                {
                    RTStrmPrintf(g_pStdErr, "Invalid hexadecimal sequence at \"%.16s\"\n",
                                 pcszQuoted - 1);
                    return false;
                }
                if (!escapeAndOutputCharacter(enmFormat, cNum))
                    return false;
                pcszQuoted += pchNext - achDigits;
                continue;
            }
            /* Output anything else non-zero as is. */
            if (*pcszQuoted)
            {
                if (!escapeAndOutputCharacter(enmFormat, *pcszQuoted))
                    return false;
                continue;
            }
            RTStrmPrintf(g_pStdErr, "Trailing back slash in argument.\n");
            return false;
        }
        /* Argument separator. */
        if (*pcszQuoted == ' ')
        {
            if (!fNextArgument && !outputArgumentSeparator(enmFormat))
                return false;
            fNextArgument = true;
            continue;
        }
        else
            fNextArgument = false;
        /* Start of escape sequence. */
        if (*pcszQuoted == '\\')
        {
            fEscaped = true;
            continue;
        }
        /* Anything else. */
        if (!outputCharacter(*pcszQuoted))
            return false;
    }
    if (enmFormat == FORMAT_SHELL)
        if (!outputCharacter('\''))
            return false;
    return true;
}