Example #1
0
File: s3.cpp Project: mcenirm/vbox
static char* rtS3Canonicalize(const char* pszAction, const char* pszBucket, const char* pszKey, char** papszHeadEnts, size_t cHeadEnts)
{
    char* pszRes;
    /* Grep the necessary info out of the headers & put them in a string */
    char* pszHead = rtS3ParseHeaders(papszHeadEnts, cHeadEnts);
    /* Create the string which will be used as signature */
    RTStrAPrintf(&pszRes, "%s\n%s\n/",
                 pszAction,
                 pszHead);
    RTStrFree(pszHead);
    /* Add the bucket if the bucket isn't empty */
    if (pszBucket[0] != 0)
    {
        char* pszTmp = pszRes;
        RTStrAPrintf(&pszRes, "%s%s/", pszRes, pszBucket);
        RTStrFree(pszTmp);
    }
    /* Add the key if the key isn't empty. */
    if (pszKey[0] != 0)
    {
        char* pszTmp = pszRes;
        RTStrAPrintf(&pszRes, "%s%s", pszRes, pszKey);
        RTStrFree(pszTmp);
    }

    return pszRes;
}
Example #2
0
File: s3.cpp Project: mcenirm/vbox
static char* rtS3HostHeader(const char* pszBucket, const char* pszBaseUrl)
{
    char* pszUrl;
    /* Host header entry */
    if (pszBucket[0] != 0)
        RTStrAPrintf(&pszUrl, "Host: %s.%s", pszBucket, pszBaseUrl);
    else
        RTStrAPrintf(&pszUrl, "Host: %s", pszBaseUrl);
    return pszUrl;
}
Example #3
0
File: s3.cpp Project: mcenirm/vbox
static char* rtS3Host(const char* pszBucket, const char* pszKey, const char* pszBaseUrl)
{
    char* pszUrl;
    /* Host header entry */
    if (pszBucket[0] == 0)
        RTStrAPrintf(&pszUrl, "%s", pszBaseUrl);
    else if (pszKey[0] == 0)
        RTStrAPrintf(&pszUrl, "%s.%s", pszBucket, pszBaseUrl);
    else
        RTStrAPrintf(&pszUrl, "%s.%s/%s", pszBucket, pszBaseUrl, pszKey);
    return pszUrl;
}
Example #4
0
/**
 * Appends environment variables to the environment block.
 *
 * Each var=value pair is separated by the null character ('\\0').  The whole
 * block will be stored in one blob and disassembled on the guest side later to
 * fit into the HGCM param structure.
 *
 * @returns VBox status code.
 *
 * @param   pszEnvVar       The environment variable=value to append to the
 *                          environment block.
 * @param   ppvList         This is actually a pointer to a char pointer
 *                          variable which keeps track of the environment block
 *                          that we're constructing.
 * @param   pcbList         Pointer to the variable holding the current size of
 *                          the environment block.  (List is a misnomer, go
 *                          ahead a be confused.)
 * @param   pcEnvVars       Pointer to the variable holding count of variables
 *                          stored in the environment block.
 */
int GuestEnvironment::appendToEnvBlock(const char *pszEnv, void **ppvList, size_t *pcbList, uint32_t *pcEnvVars)
{
    int rc = VINF_SUCCESS;
    size_t cchEnv = strlen(pszEnv); Assert(cchEnv >= 2);
    if (*ppvList)
    {
        size_t cbNewLen = *pcbList + cchEnv + 1; /* Include zero termination. */
        char *pvTmp = (char *)RTMemRealloc(*ppvList, cbNewLen);
        if (pvTmp == NULL)
            rc = VERR_NO_MEMORY;
        else
        {
            memcpy(pvTmp + *pcbList, pszEnv, cchEnv);
            pvTmp[cbNewLen - 1] = '\0'; /* Add zero termination. */
            *ppvList = (void **)pvTmp;
        }
    }
    else
    {
        char *pszTmp;
        if (RTStrAPrintf(&pszTmp, "%s", pszEnv) >= 0)
        {
            *ppvList = (void **)pszTmp;
            /* Reset counters. */
            *pcEnvVars = 0;
            *pcbList = 0;
        }
    }
    if (RT_SUCCESS(rc))
    {
        *pcbList += cchEnv + 1; /* Include zero termination. */
        *pcEnvVars += 1;        /* Increase env variable count. */
    }
    return rc;
}
Example #5
0
int CollectorSolaris::getProcessMemoryUsage(RTPROCESS process, ULONG *used)
{
    int rc = VINF_SUCCESS;
    char *pszName = NULL;
    psinfo_t psinfo;

    RTStrAPrintf(&pszName, "/proc/%d/psinfo", process);
    Log(("Opening %s...\n", pszName));
    int h = open(pszName, O_RDONLY);
    RTStrFree(pszName);

    if (h != -1)
    {
        if (read(h, &psinfo, sizeof(psinfo)) == sizeof(psinfo))
        {
            Assert((pid_t)process == psinfo.pr_pid);
            *used = psinfo.pr_rssize;
        }
        else
        {
            Log(("read() -> %d\n", errno));
            rc = VERR_FILE_IO_ERROR;
        }
        close(h);
    }
    else
    {
        Log(("open() -> %d\n", errno));
        rc = VERR_ACCESS_DENIED;
    }

    return rc;
}
Example #6
0
File: s3.cpp Project: mcenirm/vbox
static char* rtS3ParseHeaders(char** ppHeaders, size_t cHeadEnts)
{
    char pszEmpty[] = "";
    char *pszRes = NULL;
    char *pszDate = pszEmpty;
    char *pszType = pszEmpty;
    for(size_t i=0; i < cHeadEnts; ++i)
    {
        if(ppHeaders[i] != NULL)
        {
            if (RTStrStr(ppHeaders[i], "Date: ") == ppHeaders[i])
            {
                pszDate = &(ppHeaders[i][6]);
            }
            else if(RTStrStr(ppHeaders[i], "Content-Type: ") == ppHeaders[i])
            {
                pszType = &(ppHeaders[i][14]);
//                char *pszTmp = RTStrDup (&(ppHeaders[i][14]));
//                if (pszRes)
//                {
//                    char *pszTmp1 = pszRes;
//                    RTStrAPrintf(&pszRes, "%s\n%s", pszRes, pszTmp);
//                    RTStrFree(pszTmp);
//                    RTStrFree(pszTmp1);
//                }
//                else
//                    pszRes = pszTmp;
            }
        }
    }
    RTStrAPrintf(&pszRes, "\n%s\n%s", pszType, pszDate);
    return pszRes;
}
Example #7
0
File: s3.cpp Project: mcenirm/vbox
static char* rtS3CreateAuthHeader(PRTS3INTERNAL pS3Int, const char* pszAction, const char* pszBucket, const char* pszKey,
                                  char** papszHeadEnts, size_t cHeadEnts)
{
    char *pszAuth;
    /* Create a signature out of the header & the bucket/key info */
    char *pszSigBase64Enc = rtS3CreateSignature(pS3Int, pszAction, pszBucket, pszKey, papszHeadEnts, cHeadEnts);
    /* Create the authorization header entry */
    RTStrAPrintf(&pszAuth, "Authorization: AWS %s:%s",
                 pS3Int->pszAccessKey,
                 pszSigBase64Enc);
    RTStrFree(pszSigBase64Enc);
    return pszAuth;
}
Example #8
0
// static
char *XmlError::Format(xmlErrorPtr aErr)
{
    const char *msg = aErr->message ? aErr->message : "<none>";
    size_t msgLen = strlen(msg);
    /* strip spaces, trailing EOLs and dot-like char */
    while (msgLen && strchr(" \n.?!", msg [msgLen - 1]))
        --msgLen;

    char *finalMsg = NULL;
    RTStrAPrintf(&finalMsg, "%.*s.\nLocation: '%s', line %d (%d), column %d",
                 msgLen, msg, aErr->file, aErr->line, aErr->int1, aErr->int2);

    return finalMsg;
}
Example #9
0
EIPRTFailure::EIPRTFailure(int aRC, const char *pcszContext, ...)
    : RuntimeError(NULL),
      mRC(aRC)
{
    char *pszContext2;
    va_list args;
    va_start(args, pcszContext);
    RTStrAPrintfV(&pszContext2, pcszContext, args);
    char *newMsg;
    RTStrAPrintf(&newMsg, "%s: %d (%s)", pszContext2, aRC, RTErrGetShort(aRC));
    setWhat(newMsg);
    RTStrFree(newMsg);
    RTStrFree(pszContext2);
}
Example #10
0
int CollectorSolaris::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total)
{
    int rc = VINF_SUCCESS;
    char *pszName;
    prusage_t prusage;

    RTStrAPrintf(&pszName, "/proc/%d/usage", process);
    Log(("Opening %s...\n", pszName));
    int h = open(pszName, O_RDONLY);
    RTStrFree(pszName);

    if (h != -1)
    {
        if (read(h, &prusage, sizeof(prusage)) == sizeof(prusage))
        {
            //Assert((pid_t)process == pstatus.pr_pid);
            //Log(("user=%u kernel=%u total=%u\n", prusage.pr_utime.tv_sec, prusage.pr_stime.tv_sec, prusage.pr_tstamp.tv_sec));
            /*
             * The CPU time spent must be adjusted by the number of cores for compatibility with
             * other platforms (see @bugref{6345}).
             */
            Assert(mCpus);
            if (mCpus)
            {
                *user = ((uint64_t)prusage.pr_utime.tv_sec * 1000000000 + prusage.pr_utime.tv_nsec) / mCpus;
                *kernel = ((uint64_t)prusage.pr_stime.tv_sec * 1000000000 + prusage.pr_stime.tv_nsec) / mCpus;
            }
            else
                *user = *kernel = 0;
            *total = (uint64_t)prusage.pr_tstamp.tv_sec * 1000000000 + prusage.pr_tstamp.tv_nsec;
            //Log(("user=%llu kernel=%llu total=%llu\n", *user, *kernel, *total));
        }
        else
        {
            Log(("read() -> %d\n", errno));
            rc = VERR_FILE_IO_ERROR;
        }
        close(h);
    }
    else
    {
        Log(("open() -> %d\n", errno));
        rc = VERR_ACCESS_DENIED;
    }

    return rc;
}
Example #11
0
int CollectorLinux::getHostDiskSize(const char *pszFile, uint64_t *size)
{
    char *pszPath = NULL;

    RTStrAPrintf(&pszPath, "/sys/block/%s/size", pszFile);
    Assert(pszPath);

    int rc = VINF_SUCCESS;
    if (!RTLinuxSysFsExists(pszPath))
        rc = VERR_FILE_NOT_FOUND;
    else
    {
        int64_t cSize = RTLinuxSysFsReadIntFile(0, pszPath);
        if (cSize < 0)
            rc = VERR_ACCESS_DENIED;
        else
            *size = cSize * 512;
    }
    RTStrFree(pszPath);
    return rc;
}
Example #12
0
int CollectorLinux::getRawProcessStats(RTPROCESS process, uint64_t *cpuUser, uint64_t *cpuKernel, ULONG *memPagesUsed)
{
    int rc = VINF_SUCCESS;
    char *pszName;
    pid_t pid2;
    char c;
    int iTmp;
    long long unsigned int u64Tmp;
    unsigned uTmp;
    unsigned long ulTmp;
    signed long ilTmp;
    ULONG u32user, u32kernel;
    char buf[80]; /* @todo: this should be tied to max allowed proc name. */

    RTStrAPrintf(&pszName, "/proc/%d/stat", process);
    FILE *f = fopen(pszName, "r");
    RTStrFree(pszName);

    if (f)
    {
        if (fscanf(f, "%d %79s %c %d %d %d %d %d %u %lu %lu %lu %lu %u %u "
                      "%ld %ld %ld %ld %ld %ld %llu %lu %u",
                   &pid2, buf, &c, &iTmp, &iTmp, &iTmp, &iTmp, &iTmp, &uTmp,
                   &ulTmp, &ulTmp, &ulTmp, &ulTmp, &u32user, &u32kernel,
                   &ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &ilTmp, &u64Tmp,
                   &ulTmp, memPagesUsed) == 24)
        {
            Assert((pid_t)process == pid2);
            *cpuUser   = u32user;
            *cpuKernel = u32kernel;
        }
        else
            rc = VERR_FILE_IO_ERROR;
        fclose(f);
    }
    else
        rc = VERR_ACCESS_DENIED;

    return rc;
}
Example #13
0
File: s3.cpp Project: mcenirm/vbox
static char* rtS3DateHeader()
{
    /* Date header entry */
    RTTIMESPEC TimeSpec;
    RTTIME Time;
    RTTimeExplode(&Time, RTTimeNow(&TimeSpec));

    static const char s_apszDayNms[7][4] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
    static const char s_apszMonthNms[1+12][4] =
    { "???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
    char *pszDate;
    RTStrAPrintf(&pszDate, "Date: %s, %02u %s %04d %02u:%02u:%02u UTC",
                 s_apszDayNms[Time.u8WeekDay],
                 Time.u8MonthDay,
                 s_apszMonthNms[Time.u8Month],
                 Time.i32Year,
                 Time.u8Hour,
                 Time.u8Minute,
                 Time.u8Second);

    return pszDate;
}
int CollectorSolaris::getRawProcessCpuLoad(RTPROCESS process, uint64_t *user, uint64_t *kernel, uint64_t *total)
{
    int rc = VINF_SUCCESS;
    char *pszName;
    prusage_t prusage;

    RTStrAPrintf(&pszName, "/proc/%d/usage", process);
    Log(("Opening %s...\n", pszName));
    int h = open(pszName, O_RDONLY);
    RTStrFree(pszName);

    if (h != -1)
    {
        if (read(h, &prusage, sizeof(prusage)) == sizeof(prusage))
        {
            //Assert((pid_t)process == pstatus.pr_pid);
            //Log(("user=%u kernel=%u total=%u\n", prusage.pr_utime.tv_sec, prusage.pr_stime.tv_sec, prusage.pr_tstamp.tv_sec));
            *user = (uint64_t)prusage.pr_utime.tv_sec * 1000000000 + prusage.pr_utime.tv_nsec;
            *kernel = (uint64_t)prusage.pr_stime.tv_sec * 1000000000 + prusage.pr_stime.tv_nsec;
            *total = (uint64_t)prusage.pr_tstamp.tv_sec * 1000000000 + prusage.pr_tstamp.tv_nsec;
            //Log(("user=%llu kernel=%llu total=%llu\n", *user, *kernel, *total));
        }
        else
        {
            Log(("read() -> %d\n", errno));
            rc = VERR_FILE_IO_ERROR;
        }
        close(h);
    }
    else
    {
        Log(("open() -> %d\n", errno));
        rc = VERR_ACCESS_DENIED;
    }

    return rc;
}
Example #15
0
int GuestEnvironment::BuildEnvironmentBlock(void **ppvEnv, size_t *pcbEnv, uint32_t *pcEnvVars)
{
    AssertPtrReturn(ppvEnv, VERR_INVALID_POINTER);
    /* Rest is optional. */

    size_t cbEnv = 0;
    uint32_t cEnvVars = 0;

    int rc = VINF_SUCCESS;

    size_t cEnv = mEnvironment.size();
    if (cEnv)
    {
        std::map<Utf8Str, Utf8Str>::const_iterator itEnv = mEnvironment.begin();
        for (; itEnv != mEnvironment.end() && RT_SUCCESS(rc); itEnv++)
        {
            char *pszEnv;
            if (!RTStrAPrintf(&pszEnv, "%s=%s", itEnv->first.c_str(), itEnv->second.c_str()))
            {
                rc = VERR_NO_MEMORY;
                break;
            }
            AssertPtr(pszEnv);
            rc = appendToEnvBlock(pszEnv, ppvEnv, &cbEnv, &cEnvVars);
            RTStrFree(pszEnv);
        }
        Assert(cEnv == cEnvVars);
    }

    if (pcbEnv)
        *pcbEnv = cbEnv;
    if (pcEnvVars)
        *pcEnvVars = cEnvVars;

    return rc;
}
/**
 * Process the testcases found in the filter.
 *
 * @param   pszFilter   The filter (winnt) to pass to RTDirOpenFiltered for
 *                      selecting the testcases.
 * @param   pszDir      The directory we're processing.
 */
static void Process(const char *pszFilter, const char *pszDir)
{
    /*
     * Open and enumerate the directory.
     */
    PRTDIR pDir;
    int rc = RTDirOpenFiltered(&pDir, pszFilter, RTDIRFILTER_WINNT, 0);
    if (RT_SUCCESS(rc))
    {
        for (;;)
        {
            RTDIRENTRY DirEntry;
            rc = RTDirRead(pDir, &DirEntry, NULL);
            if (RT_FAILURE(rc))
            {
                if (rc == VERR_NO_MORE_FILES)
                    rc = VINF_SUCCESS;
                else
                    RTPrintf("tstRunTestcases: reading '%s' -> %Rrc\n", pszFilter, rc);
                break;
            }

            /*
             * Construct the testcase name.
             */
            char *pszTestcase;
            RTStrAPrintf(&pszTestcase, "%s/%s", pszDir, DirEntry.szName);
            if (!pszTestcase)
            {
                RTPrintf("tstRunTestcases: out of memory!\n");
                rc = VERR_NO_MEMORY;
                break;
            }
            if (IsTestcaseIncluded(pszTestcase))
            {
                /*
                 * Execute the testcase.
                 */
                RTPrintf("*** %s: Executing...\n", pszTestcase);  RTStrmFlush(g_pStdOut);
                const char *papszArgs[2];
                papszArgs[0] = pszTestcase;
                papszArgs[1] = NULL;
                RTPROCESS Process;
                rc = RTProcCreate(pszTestcase, papszArgs, RTENV_DEFAULT, 0, &Process);
                if (RT_SUCCESS(rc))
                {
                    /*
                     * Wait for the process and collect it's return code.
                     * If it takes too long, we'll terminate it and continue.
                     */
                    RTTIMESPEC Start;
                    RTTimeNow(&Start);
                    RTPROCSTATUS ProcStatus;
                    for (;;)
                    {
                        rc = RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus);
                        if (rc != VERR_PROCESS_RUNNING)
                            break;
                        RTTIMESPEC Now;
                        if (RTTimeSpecGetMilli(RTTimeSpecSub(RTTimeNow(&Now), &Start)) > 120*1000 /* 1 min */)
                        {
                            RTPrintf("*** %s: FAILED - timed out. killing it.\n", pszTestcase);
                            RTProcTerminate(Process);
                            RTThreadSleep(100);
                            RTProcWait(Process, RTPROCWAIT_FLAGS_NOBLOCK, &ProcStatus);
                            g_cFailures++;
                            break;
                        }
                        RTThreadSleep(100);
                    }

                    /*
                     * Examin the exit status.
                     */
                    if (RT_SUCCESS(rc))
                    {
                        if (    ProcStatus.enmReason == RTPROCEXITREASON_NORMAL
                            &&  ProcStatus.iStatus == 0)
                        {
                            RTPrintf("*** %s: PASSED\n", pszTestcase);
                            g_cPasses++;
                        }
                        else
                        {
                            RTPrintf("*** %s: FAILED\n", pszTestcase);
                            g_cFailures++;
                        }
                    }
                    else if (rc != VERR_PROCESS_RUNNING)
                    {
                        RTPrintf("tstRunTestcases: %s: RTProcWait failed -> %Rrc\n", pszTestcase, rc);
                        g_cFailures++;
                    }
                }
                else
                {
                    RTPrintf("tstRunTestcases: %s: failed to start -> %Rrc\n", pszTestcase, rc);
                    g_cFailures++;
                }

            }
            else
            {
                RTPrintf("tstRunTestcases: %s: SKIPPED\n", pszTestcase);
                g_cSkipped++;
            }
            RTStrFree(pszTestcase);
        } /* enumeration loop */

        RTDirClose(pDir);
    }
    else
        RTPrintf("tstRunTestcases: opening '%s' -> %Rrc\n", pszDir, rc);
}
Example #17
0
File: s3.cpp Project: mcenirm/vbox
RTR3DECL(int) RTS3PutKey(RTS3 hS3, const char *pszBucketName, const char *pszKeyName, const char *pszFilename)
{
    PRTS3INTERNAL pS3Int = hS3;
    RTS3_VALID_RETURN(pS3Int);

    /* Reset the CURL object to an defined state */
    rtS3ReinitCurl(pS3Int);

    /* Open the file */
    RTFILE hFile;
    int rc = RTFileOpen(&hFile, pszFilename, RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
    if (RT_FAILURE(rc))
        return rc;

    uint64_t cbFileSize;
    rc = RTFileGetSize(hFile, &cbFileSize);
    if (RT_FAILURE(rc))
    {
        RTFileClose(hFile);
        return rc;
    }

    char* pszUrl = rtS3Host(pszBucketName, pszKeyName, pS3Int->pszBaseUrl);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_URL, pszUrl);
    RTStrFree(pszUrl);

    char* pszContentLength;
    RTStrAPrintf(&pszContentLength, "Content-Length: %lu", cbFileSize);
    /* Create the three basic header entries */
    char *apszHead[5] =
    {
        /* todo: For now we use octet-stream for all types. Later we should try
         * to set the right one (libmagic from the file packet could be a
         * candidate for finding the right type). */
        RTStrDup("Content-Type: octet-stream"),            /* Content type entry */
        pszContentLength,                                  /* Content length entry */
        rtS3HostHeader(pszBucketName, pS3Int->pszBaseUrl), /* Host entry */
        rtS3DateHeader(),                                  /* Date entry */
        NULL                                               /* Authorization entry */
    };
    /* Create the authorization header entry */
    apszHead[RT_ELEMENTS(apszHead)-1] = rtS3CreateAuthHeader(pS3Int, "PUT", pszBucketName, pszKeyName, apszHead, RT_ELEMENTS(apszHead));

    /* Add all headers to curl */
    struct curl_slist* pHeaders = NULL; /* Init to NULL is important */
    for(size_t i=0; i < RT_ELEMENTS(apszHead); ++i)
        pHeaders = curl_slist_append(pHeaders, apszHead[i]);

    /* Pass our list of custom made headers */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_HTTPHEADER, pHeaders);

    /* Set CURL in upload mode */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_PUT, 1);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_UPLOAD, 1);

    /* Set the size of the file we like to transfer */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_INFILESIZE_LARGE, cbFileSize);

    /* Set the callback which send the content */
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_READFUNCTION, rtS3ReadFileCallback);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_READDATA, &hFile);
    curl_easy_setopt(pS3Int->pCurl, CURLOPT_SSLVERSION, (long)CURL_SSLVERSION_TLSv1);

    /* Start the request */
    rc = rtS3Perform(pS3Int);

    /* Regardless of the result, free all used resources first*/
    curl_slist_free_all(pHeaders);
    for(size_t i=0; i < RT_ELEMENTS(apszHead); ++i)
        RTStrFree(apszHead[i]);

    /* Close the open file */
    RTFileClose(hFile);

    return rc;
}
/**
 * Modifies the autostart database.
 *
 * @returns VBox status code.
 * @param   fAutostart    Flag whether the autostart or autostop database is modified.
 * @param   fAddVM        Flag whether a VM is added or removed from the database.
 */
int AutostartDb::autostartModifyDb(bool fAutostart, bool fAddVM)
{
    int rc = VINF_SUCCESS;
    char *pszUser = NULL;

    /* Check if the path is set. */
    if (!m_pszAutostartDbPath)
        return VERR_PATH_NOT_FOUND;

    rc = RTProcQueryUsernameA(RTProcSelf(), &pszUser);
    if (RT_SUCCESS(rc))
    {
        char *pszFile;
        uint64_t fOpen = RTFILE_O_DENY_ALL | RTFILE_O_READWRITE;
        RTFILE hAutostartFile;

        AssertPtr(pszUser);

        if (fAddVM)
            fOpen |= RTFILE_O_OPEN_CREATE;
        else
            fOpen |= RTFILE_O_OPEN;

        rc = RTStrAPrintf(&pszFile, "%s/%s.%s",
                          m_pszAutostartDbPath, pszUser, fAutostart ? "start" : "stop");
        if (RT_SUCCESS(rc))
        {
            rc = RTFileOpen(&hAutostartFile, pszFile, fOpen);
            if (RT_SUCCESS(rc))
            {
                uint64_t cbFile;

                /*
                 * Files with more than 16 bytes are rejected because they just contain
                 * a number of the amount of VMs with autostart configured, so they
                 * should be really really small. Anything else is bogus.
                 */
                rc = RTFileGetSize(hAutostartFile, &cbFile);
                if (   RT_SUCCESS(rc)
                    && cbFile <= 16)
                {
                    char abBuf[16 + 1]; /* trailing \0 */
                    uint32_t cAutostartVms = 0;

                    RT_ZERO(abBuf);

                    /* Check if the file was just created. */
                    if (cbFile)
                    {
                        rc = RTFileRead(hAutostartFile, abBuf, cbFile, NULL);
                        if (RT_SUCCESS(rc))
                        {
                            rc = RTStrToUInt32Ex(abBuf, NULL, 10 /* uBase */, &cAutostartVms);
                            if (   rc == VWRN_TRAILING_CHARS
                                || rc == VWRN_TRAILING_SPACES)
                                rc = VINF_SUCCESS;
                        }
                    }

                    if (RT_SUCCESS(rc))
                    {
                        size_t cbBuf;

                        /* Modify VM counter and write back. */
                        if (fAddVM)
                            cAutostartVms++;
                        else
                            cAutostartVms--;

                        if (cAutostartVms > 0)
                        {
                            cbBuf = RTStrPrintf(abBuf, sizeof(abBuf), "%u", cAutostartVms);
                            rc = RTFileSetSize(hAutostartFile, cbBuf);
                            if (RT_SUCCESS(rc))
                                rc = RTFileWriteAt(hAutostartFile, 0, abBuf, cbBuf, NULL);
                        }
                        else
                        {
                            /* Just delete the file if there are no VMs left. */
                            RTFileClose(hAutostartFile);
                            RTFileDelete(pszFile);
                            hAutostartFile = NIL_RTFILE;
                        }
                    }
                }
                else if (RT_SUCCESS(rc))
                    rc = VERR_FILE_TOO_BIG;

                if (hAutostartFile != NIL_RTFILE)
                    RTFileClose(hAutostartFile);
            }
            RTStrFree(pszFile);
        }

        RTStrFree(pszUser);
    }

    return rc;
}
Example #19
0
PUSBDEVICE USBProxyBackendFreeBSD::getDevices(void)
{
    PUSBDEVICE pDevices = NULL;
    int FileUsb = 0;
    int iBus  = 0;
    int iAddr = 1;
    int rc = VINF_SUCCESS;
    char *pszDevicePath = NULL;
    uint32_t PlugTime = 0;

    for (;;)
    {
        rc = RTStrAPrintf(&pszDevicePath, "/dev/%s%d.%d", USB_GENERIC_NAME, iBus, iAddr);
        if (RT_FAILURE(rc))
        {
            mLastError = rc;
            break;
        }

        LogFlowFunc((": Opening %s\n", pszDevicePath));

        FileUsb = open(pszDevicePath, O_RDONLY);
        if (FileUsb < 0)
        {
            if (   (errno != ENOENT)
                && (errno != EACCES))
                mLastError = RTErrConvertFromErrno(errno);

            RTStrFree(pszDevicePath);

            if ((errno == ENOENT) && (iAddr > 1))
            {
                iAddr = 1;
                iBus++;
                continue;
            }
            else if (errno == EACCES)
            {
                /* Skip devices without the right permission. */
                iAddr++;
                continue;
            }
            else
                break;
        }

        LogFlowFunc((": %s opened successfully\n", pszDevicePath));

        struct usb_device_info UsbDevInfo;
        RT_ZERO(UsbDevInfo);

        rc = ioctl(FileUsb, USB_GET_DEVICEINFO, &UsbDevInfo);
        if (rc < 0)
        {
            LogFlowFunc((": Error querying device info rc=%Rrc\n", RTErrConvertFromErrno(errno)));
            mLastError = RTErrConvertFromErrno(errno);
            close(FileUsb);
            RTStrFree(pszDevicePath);
            break;
        }

        /* Filter out hubs */
        if (UsbDevInfo.udi_class != 0x09)
        {
            PUSBDEVICE pDevice = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE));
            if (!pDevice)
            {
                mLastError = VERR_NO_MEMORY;
                close(FileUsb);
                RTStrFree(pszDevicePath);
                break;
            }

            pDevice->enmState           = USBDEVICESTATE_UNUSED;
            pDevice->bBus               = UsbDevInfo.udi_bus;
            pDevice->bDeviceClass       = UsbDevInfo.udi_class;
            pDevice->bDeviceSubClass    = UsbDevInfo.udi_subclass;
            pDevice->bDeviceProtocol    = UsbDevInfo.udi_protocol;
            pDevice->bNumConfigurations = UsbDevInfo.udi_config_no;
            pDevice->idVendor           = UsbDevInfo.udi_vendorNo;
            pDevice->idProduct          = UsbDevInfo.udi_productNo;
            pDevice->bDevNum            = UsbDevInfo.udi_index;

            switch (UsbDevInfo.udi_speed)
            {
                case USB_SPEED_LOW:
                    pDevice->enmSpeed = USBDEVICESPEED_LOW;
                    break;
                case USB_SPEED_FULL:
                    pDevice->enmSpeed = USBDEVICESPEED_FULL;
                    break;
                case USB_SPEED_HIGH:
                    pDevice->enmSpeed = USBDEVICESPEED_HIGH;
                    break;
                case USB_SPEED_SUPER:
                case USB_SPEED_VARIABLE:
                default:
                    pDevice->enmSpeed = USBDEVICESPEED_UNKNOWN;
            }

            if (UsbDevInfo.udi_vendor[0] != '\0')
                pDevice->pszManufacturer = RTStrDupN(UsbDevInfo.udi_vendor, sizeof(UsbDevInfo.udi_vendor));

            if (UsbDevInfo.udi_product[0] != '\0')
                pDevice->pszProduct = RTStrDupN(UsbDevInfo.udi_product, sizeof(UsbDevInfo.udi_product));

            if (UsbDevInfo.udi_serial[0] != '\0')
            {
                pDevice->pszSerialNumber = RTStrDupN(UsbDevInfo.udi_serial, sizeof(UsbDevInfo.udi_serial));
                pDevice->u64SerialHash   = USBLibHashSerial(pDevice->pszSerialNumber);
            }
            rc = ioctl(FileUsb, USB_GET_PLUGTIME, &PlugTime);
            if (rc == 0)
                pDevice->u64SerialHash  += PlugTime;

            pDevice->pszAddress = RTStrDup(pszDevicePath);
            pDevice->pszBackend = RTStrDup("host");
            pDevice->enmState   = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;

            usbLogDevice(pDevice);

            pDevice->pNext = pDevices;
            if (pDevices)
                pDevices->pPrev = pDevice;
            pDevices = pDevice;
        }
        close(FileUsb);
        RTStrFree(pszDevicePath);
        iAddr++;
    }

    return pDevices;
}
Example #20
0
/**
 * Creates a new USB device and adds it to the list.
 *
 * @returns VBox status code.
 * @param   pDev    Pointer to the USB/IP exported device structure to take
 *                  the information for the new device from.
 */
int USBProxyBackendUsbIp::addDeviceToList(PUsbIpExportedDevice pDev)
{
    PUSBDEVICE pNew = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE));
    if (!pNew)
        return VERR_NO_MEMORY;

    pNew->pszManufacturer = RTStrDup("");
    pNew->pszProduct      = RTStrDup("");
    pNew->pszSerialNumber = NULL;
    pNew->pszBackend      = RTStrDup("usbip");

    /* Make sure the Bus id is 0 terminated. */
    pDev->szBusId[31] = '\0';
    RTStrAPrintf((char **)&pNew->pszAddress, "usbip://%s:%u:%s", m->pszHost, m->uPort, &pDev->szBusId[0]);

    pNew->idVendor           = pDev->u16VendorId;
    pNew->idProduct          = pDev->u16ProductId;
    pNew->bcdDevice          = pDev->u16BcdDevice;
    pNew->bDeviceClass       = pDev->bDeviceClass;
    pNew->bDeviceSubClass    = pDev->bDeviceSubClass;
    pNew->bDeviceProtocol    = pDev->bDeviceProtocol;
    pNew->bNumConfigurations = pDev->bNumConfigurations;
    pNew->enmState           = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
    pNew->u64SerialHash      = 0;
    pNew->bBus               = (uint8_t)pDev->u32BusNum;
    pNew->bPort              = (uint8_t)pDev->u32DevNum;

    switch (pDev->u32Speed)
    {
        case USBIP_SPEED_LOW:
            pNew->enmSpeed = USBDEVICESPEED_LOW;
            pNew->bcdUSB = 1 << 8;
            break;
        case USBIP_SPEED_FULL:
            pNew->enmSpeed = USBDEVICESPEED_FULL;
            pNew->bcdUSB = 1 << 8;
            break;
        case USBIP_SPEED_HIGH:
            pNew->enmSpeed = USBDEVICESPEED_HIGH;
            pNew->bcdUSB = 2 << 8;
            break;
        case USBIP_SPEED_WIRELESS:
            pNew->enmSpeed = USBDEVICESPEED_VARIABLE;
            pNew->bcdUSB = 1 << 8;
            break;
        case USBIP_SPEED_SUPER:
            pNew->enmSpeed = USBDEVICESPEED_SUPER;
            pNew->bcdUSB = 3 << 8;
            break;
        case USBIP_SPEED_UNKNOWN:
        default:
            pNew->bcdUSB = 1 << 8;
            pNew->enmSpeed = USBDEVICESPEED_UNKNOWN;
    }

    /* link it */
    pNew->pNext = NULL;
    pNew->pPrev = *m->ppNext;
    *m->ppNext = pNew;
    m->ppNext = &pNew->pNext;
    m->cDevicesCur++;

    return VINF_SUCCESS;
}
static int tstVDOpenCreateWriteMerge(PVDSNAPTEST pTest)
{
    int rc;
    PVBOXHDD pVD = NULL;
    VDGEOMETRY       PCHS = { 0, 0, 0 };
    VDGEOMETRY       LCHS = { 0, 0, 0 };
    PVDINTERFACE     pVDIfs = NULL;
    VDINTERFACEERROR VDIfError;

    /** Buffer storing the random test pattern. */
    uint8_t *pbTestPattern = NULL;
    /** Number of disk segments */
    uint32_t cDiskSegments;
    /** Array of disk segments */
    PVDDISKSEG paDiskSeg = NULL;
    unsigned   cDiffs = 0;
    unsigned   idDiff = 0; /* Diff ID counter for the filename */

    /* Delete all images from a previous run. */
    RTFileDelete(pTest->pcszBaseImage);
    for (unsigned i = 0; i < pTest->cIterations; i++)
    {
        char *pszDiffFilename = NULL;

        rc = RTStrAPrintf(&pszDiffFilename, "tstVDSnapDiff%u.%s", i, pTest->pcszDiffSuff);
        if (RT_SUCCESS(rc))
        {
            if (RTFileExists(pszDiffFilename))
                RTFileDelete(pszDiffFilename);
            RTStrFree(pszDiffFilename);
        }
    }

    /* Create the virtual disk test data */
    pbTestPattern = (uint8_t *)RTMemAlloc(pTest->cbTestPattern);

    RTRandAdvBytes(g_hRand, pbTestPattern, pTest->cbTestPattern);
    cDiskSegments = RTRandAdvU32Ex(g_hRand, pTest->cDiskSegsMin, pTest->cDiskSegsMax);

    uint64_t cbDisk = 0;

    paDiskSeg = (PVDDISKSEG)RTMemAllocZ(cDiskSegments * sizeof(VDDISKSEG));
    if (!paDiskSeg)
    {
        RTPrintf("Failed to allocate memory for random disk segments\n");
        g_cErrors++;
        return VERR_NO_MEMORY;
    }

    for (unsigned i = 0; i < cDiskSegments; i++)
    {
        paDiskSeg[i].off    = cbDisk;
        paDiskSeg[i].cbSeg  = RT_ALIGN_64(RTRandAdvU64Ex(g_hRand, 512, pTest->cbTestPattern), 512);
        if (tstVDSnapIsTrue(pTest->uAllocatedBlocks))
            paDiskSeg[i].pbData = pbTestPattern + RT_ALIGN_64(RTRandAdvU64Ex(g_hRand, 0, pTest->cbTestPattern - paDiskSeg[i].cbSeg - 512), 512);
        else
            paDiskSeg[i].pbData = NULL; /* Not allocated initially */
        cbDisk += paDiskSeg[i].cbSeg;
    }

    RTPrintf("Disk size is %llu bytes\n", cbDisk);

#define CHECK(str) \
    do \
    { \
        RTPrintf("%s rc=%Rrc\n", str, rc); \
        if (RT_FAILURE(rc)) \
        { \
            if (pbTestPattern) \
                RTMemFree(pbTestPattern); \
            if (paDiskSeg) \
                RTMemFree(paDiskSeg); \
            VDDestroy(pVD); \
            g_cErrors++; \
            return rc; \
        } \
    } while (0)

#define CHECK_BREAK(str) \
    do \
    { \
        RTPrintf("%s rc=%Rrc\n", str, rc); \
        if (RT_FAILURE(rc)) \
        { \
            g_cErrors++; \
            break; \
        } \
    } while (0)

    /* Create error interface. */
    /* Create error interface. */
    VDIfError.pfnError = tstVDError;
    VDIfError.pfnMessage = tstVDMessage;

    rc = VDInterfaceAdd(&VDIfError.Core, "tstVD_Error", VDINTERFACETYPE_ERROR,
                        NULL, sizeof(VDINTERFACEERROR), &pVDIfs);
    AssertRC(rc);


    rc = VDCreate(pVDIfs, VDTYPE_HDD, &pVD);
    CHECK("VDCreate()");

    rc = VDCreateBase(pVD, pTest->pcszBackend, pTest->pcszBaseImage, cbDisk,
                      VD_IMAGE_FLAGS_NONE, "Test image",
                      &PCHS, &LCHS, NULL, VD_OPEN_FLAGS_NORMAL,
                      NULL, NULL);
    CHECK("VDCreateBase()");

    bool fInit = true;
    uint32_t cIteration = 0;

    /* Do the real work now */
    while (   RT_SUCCESS(rc)
           && cIteration < pTest->cIterations)
    {
        /* Write */
        rc = tstVDSnapWrite(pVD, paDiskSeg, cDiskSegments, cbDisk, fInit);
        CHECK_BREAK("tstVDSnapWrite()");

        fInit = false;

        /* Write returned, do we want to create a new diff or merge them? */
        bool fCreate =   cDiffs < pTest->cDiffsMinBeforeMerge
                       ? true
                       : tstVDSnapIsTrue(pTest->uCreateDiffChance);

        if (fCreate)
        {
            char *pszDiffFilename = NULL;

            RTStrAPrintf(&pszDiffFilename, "tstVDSnapDiff%u.%s", idDiff, pTest->pcszDiffSuff);
            CHECK("RTStrAPrintf()");
            idDiff++;
            cDiffs++;

            rc = VDCreateDiff(pVD, pTest->pcszBackend, pszDiffFilename,
                              VD_IMAGE_FLAGS_NONE, "Test diff image", NULL, NULL,
                              VD_OPEN_FLAGS_NORMAL, NULL, NULL);
            CHECK_BREAK("VDCreateDiff()");

            RTStrFree(pszDiffFilename);
            VDDumpImages(pVD);

            /* Change data */
            tstVDSnapSegmentsDice(pTest, paDiskSeg, cDiskSegments, pbTestPattern, pTest->cbTestPattern);
        }
        else
        {
            uint32_t uStartMerge = RTRandAdvU32Ex(g_hRand, 1, cDiffs - 1);
            uint32_t uEndMerge   = RTRandAdvU32Ex(g_hRand, uStartMerge + 1, cDiffs);
            RTPrintf("Merging %u diffs from %u to %u...\n",
                     uEndMerge - uStartMerge,
                     uStartMerge,
                     uEndMerge);
            if (pTest->fForward)
                rc = VDMerge(pVD, uStartMerge, uEndMerge, NULL);
            else
                rc = VDMerge(pVD, uEndMerge, uStartMerge, NULL);
            CHECK_BREAK("VDMerge()");

            cDiffs -= uEndMerge - uStartMerge;

            VDDumpImages(pVD);

            /* Go through the disk segments and reset pointers. */
            for (uint32_t i = 0; i < cDiskSegments; i++)
            {
                if (paDiskSeg[i].pbDataDiff)
                {
                    paDiskSeg[i].pbData     = paDiskSeg[i].pbDataDiff;
                    paDiskSeg[i].pbDataDiff = NULL;
                }
            }

            /* Now compare the result with our test pattern */
            rc = tstVDSnapReadVerify(pVD, paDiskSeg, cDiskSegments, cbDisk);
            CHECK_BREAK("tstVDSnapReadVerify()");
        }
        cIteration++;
    }

    VDDumpImages(pVD);

    VDDestroy(pVD);
    if (paDiskSeg)
        RTMemFree(paDiskSeg);
    if (pbTestPattern)
        RTMemFree(pbTestPattern);

    RTFileDelete(pTest->pcszBaseImage);
    for (unsigned i = 0; i < idDiff; i++)
    {
        char *pszDiffFilename = NULL;

        RTStrAPrintf(&pszDiffFilename, "tstVDSnapDiff%u.%s", i, pTest->pcszDiffSuff);
        RTFileDelete(pszDiffFilename);
        RTStrFree(pszDiffFilename);
    }
#undef CHECK
    return rc;
}
static int VBoxServiceAutoMountProcessMappings(PVBGLR3SHAREDFOLDERMAPPING paMappings, uint32_t cMappings,
                                               const char *pszMountDir, const char *pszSharePrefix, uint32_t uClientID)
{
    if (cMappings == 0)
        return VINF_SUCCESS;
    AssertPtrReturn(paMappings, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszMountDir, VERR_INVALID_PARAMETER);
    AssertPtrReturn(pszSharePrefix, VERR_INVALID_PARAMETER);
    AssertReturn(uClientID > 0, VERR_INVALID_PARAMETER);

    int rc = VINF_SUCCESS;
    for (uint32_t i = 0; i < cMappings && RT_SUCCESS(rc); i++)
    {
        char *pszShareName = NULL;
        rc = VbglR3SharedFolderGetName(uClientID, paMappings[i].u32Root, &pszShareName);
        if (   RT_SUCCESS(rc)
            && *pszShareName)
        {
            VBoxServiceVerbose(3, "VBoxServiceAutoMountWorker: Connecting share %u (%s) ...\n", i+1, pszShareName);

            char *pszShareNameFull = NULL;
            if (RTStrAPrintf(&pszShareNameFull, "%s%s", pszSharePrefix, pszShareName) > 0)
            {
                char szMountPoint[RTPATH_MAX];
                rc = RTPathJoin(szMountPoint, sizeof(szMountPoint), pszMountDir, pszShareNameFull);
                if (RT_SUCCESS(rc))
                {
                    VBoxServiceVerbose(4, "VBoxServiceAutoMountWorker: Processing mount point \"%s\"\n", szMountPoint);

                    struct group *grp_vboxsf = getgrnam("vboxsf");
                    if (grp_vboxsf)
                    {
                        struct vbsf_mount_opts mount_opts =
                        {
                            0,                     /* uid */
                            (int)grp_vboxsf->gr_gid, /* gid */
                            0,                     /* ttl */
                            0770,                  /* dmode, owner and group "vboxsf" have full access */
                            0770,                  /* fmode, owner and group "vboxsf" have full access */
                            0,                     /* dmask */
                            0,                     /* fmask */
                            0,                     /* ronly */
                            0,                     /* noexec */
                            0,                     /* nodev */
                            0,                     /* nosuid */
                            0,                     /* remount */
                            "\0",                  /* nls_name */
                            NULL,                  /* convertcp */
                        };

                        rc = VBoxServiceAutoMountSharedFolder(pszShareName, szMountPoint, &mount_opts);
                    }
                    else
                        VBoxServiceError("VBoxServiceAutoMountWorker: Group \"vboxsf\" does not exist\n");
                }
                else
                    VBoxServiceError("VBoxServiceAutoMountWorker: Unable to join mount point/prefix/shrae, rc = %Rrc\n", rc);
                RTStrFree(pszShareNameFull);
            }
            else
                VBoxServiceError("VBoxServiceAutoMountWorker: Unable to allocate full share name\n");
            RTStrFree(pszShareName);
        }
        else
            VBoxServiceError("VBoxServiceAutoMountWorker: Error while getting the shared folder name for root node = %u, rc = %Rrc\n",
                             paMappings[i].u32Root, rc);
    } /* for cMappings. */
    return rc;
}
Example #23
0
int main()
{
    RTTEST hTest;
    int rc = RTTestInitAndCreate("tstRTStrFormat", &hTest);
    if (rc)
        return rc;
    RTTestBanner(hTest);

    uint32_t    u32 = 0x010;
    uint64_t    u64 = 0x100;
#define BUF_SIZE    120
    char       *pszBuf  = (char *)RTTestGuardedAllocHead(hTest, BUF_SIZE);
    char       *pszBuf2 = (char *)RTTestGuardedAllocHead(hTest, BUF_SIZE);

    RTTestSub(hTest, "Basics");

    /* simple */
    size_t cch = RTStrPrintf(pszBuf, BUF_SIZE, "u32=%d u64=%lld u64=%#llx", u32, u64, u64);
    if (strcmp(pszBuf, "u32=16 u64=256 u64=0x100"))
    {
        RTTestIFailed("error: '%s'\n"
                      "wanted 'u32=16 u64=256 u64=0x100'\n", pszBuf);
    }

    /* just big. */
    u64 = UINT64_C(0x7070605040302010);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "u64=%#llx 42=%d u64=%lld 42=%d", u64, 42, u64, 42);
    if (strcmp(pszBuf, "u64=0x7070605040302010 42=42 u64=8102081627430068240 42=42"))
    {
        RTTestIFailed("error: '%s'\n"
                      "wanted 'u64=0x8070605040302010 42=42 u64=8102081627430068240 42=42'\n", pszBuf);
        RTTestIPrintf(RTTESTLVL_FAILURE, "%d\n", (int)(u64 % 10));
    }

    /* huge and negative. */
    u64 = UINT64_C(0x8070605040302010);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "u64=%#llx 42=%d u64=%llu 42=%d u64=%lld 42=%d", u64, 42, u64, 42, u64, 42);
    /* Not sure if this is the correct decimal representation... But both */
    if (strcmp(pszBuf, "u64=0x8070605040302010 42=42 u64=9255003132036915216 42=42 u64=-9191740941672636400 42=42"))
    {
        RTTestIFailed("error: '%s'\n"
                      "wanted 'u64=0x8070605040302010 42=42 u64=9255003132036915216 42=42 u64=-9191740941672636400 42=42'\n", pszBuf);
        RTTestIPrintf(RTTESTLVL_FAILURE, "%d\n", (int)(u64 % 10));
    }

    /* 64-bit value bug. */
    u64 = 0xa0000000;
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "u64=%#llx 42=%d u64=%lld 42=%d", u64, 42, u64, 42);
    if (strcmp(pszBuf, "u64=0xa0000000 42=42 u64=2684354560 42=42"))
        RTTestIFailed("error: '%s'\n"
                      "wanted 'u64=0xa0000000 42=42 u64=2684354560 42=42'\n", pszBuf);

    /* uuid */
    RTUUID Uuid;
    RTUuidCreate(&Uuid);
    char szCorrect[RTUUID_STR_LENGTH];
    RTUuidToStr(&Uuid, szCorrect, sizeof(szCorrect));
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%RTuuid", &Uuid);
    if (strcmp(pszBuf, szCorrect))
        RTTestIFailed("error:    '%s'\n"
                      "expected: '%s'\n",
                      pszBuf, szCorrect);

    /*
     * Nested
     */
    RTTestSub(hTest, "Nested (%N)");
    testNested(__LINE__, "42 2684354560 42 asdf 42", "42 %u 42 %s 42", 2684354560U, "asdf");
    testNested(__LINE__, "", "");

    /*
     * allocation
     */
    RTTestSub(hTest, "RTStrAPrintf");
    char *psz = (char *)~0;
    int cch2 = RTStrAPrintf(&psz, "Hey there! %s%s", "This is a test", "!");
    if (cch2 < 0)
        RTTestIFailed("RTStrAPrintf failed, cch2=%d\n", cch2);
    else if (strcmp(psz, "Hey there! This is a test!"))
        RTTestIFailed("RTStrAPrintf failed\n"
                      "got   : '%s'\n"
                      "wanted: 'Hey there! This is a test!'\n",
                      psz);
    else if ((int)strlen(psz) != cch2)
        RTTestIFailed("RTStrAPrintf failed, cch2 == %d expected %u\n", cch2, strlen(psz));
    RTStrFree(psz);

#define CHECK42(fmt, arg, out) \
    do { \
        cch = RTStrPrintf(pszBuf, BUF_SIZE, fmt " 42=%d " fmt " 42=%d", arg, 42, arg, 42); \
        if (strcmp(pszBuf, out " 42=42 " out " 42=42")) \
            RTTestIFailed("at line %d: format '%s'\n" \
                          "    output: '%s'\n"  \
                          "    wanted: '%s'\n", \
                          __LINE__, fmt, pszBuf, out " 42=42 " out " 42=42"); \
        else if (cch != sizeof(out " 42=42 " out " 42=42") - 1) \
            RTTestIFailed("at line %d: Invalid length %d returned, expected %u!\n", \
                          __LINE__, cch, sizeof(out " 42=42 " out " 42=42") - 1); \
    } while (0)

#define CHECKSTR(Correct) \
    if (strcmp(pszBuf, Correct)) \
        RTTestIFailed("error:    '%s'\n" \
                      "expected: '%s'\n", pszBuf, Correct); \

    /*
     * Runtime extensions.
     */
    RTTestSub(hTest, "Runtime format types (%R*)");
    CHECK42("%RGi", (RTGCINT)127, "127");
    CHECK42("%RGi", (RTGCINT)-586589, "-586589");

    CHECK42("%RGp", (RTGCPHYS)0x0000000044505045, "0000000044505045");
    CHECK42("%RGp", ~(RTGCPHYS)0, "ffffffffffffffff");

    CHECK42("%RGu", (RTGCUINT)586589, "586589");
    CHECK42("%RGu", (RTGCUINT)1, "1");
    CHECK42("%RGu", (RTGCUINT)3000000000U, "3000000000");

#if GC_ARCH_BITS == 32
    CHECK42("%RGv", (RTGCUINTPTR)0, "00000000");
    CHECK42("%RGv", ~(RTGCUINTPTR)0, "ffffffff");
    CHECK42("%RGv", (RTGCUINTPTR)0x84342134, "84342134");
#else
    CHECK42("%RGv", (RTGCUINTPTR)0, "0000000000000000");
    CHECK42("%RGv", ~(RTGCUINTPTR)0, "ffffffffffffffff");
    CHECK42("%RGv", (RTGCUINTPTR)0x84342134, "0000000084342134");
#endif

    CHECK42("%RGx", (RTGCUINT)0x234, "234");
    CHECK42("%RGx", (RTGCUINT)0xffffffff, "ffffffff");

    CHECK42("%RRv", (RTRCUINTPTR)0, "00000000");
    CHECK42("%RRv", ~(RTRCUINTPTR)0, "ffffffff");
    CHECK42("%RRv", (RTRCUINTPTR)0x84342134, "84342134");

    CHECK42("%RHi", (RTHCINT)127, "127");
    CHECK42("%RHi", (RTHCINT)-586589, "-586589");

    CHECK42("%RHp", (RTHCPHYS)0x0000000044505045, "0000000044505045");
    CHECK42("%RHp", ~(RTHCPHYS)0, "ffffffffffffffff");

    CHECK42("%RHu", (RTHCUINT)586589, "586589");
    CHECK42("%RHu", (RTHCUINT)1, "1");
    CHECK42("%RHu", (RTHCUINT)3000000000U, "3000000000");

    if (sizeof(void*) == 8)
    {
        CHECK42("%RHv", (RTHCUINTPTR)0, "0000000000000000");
        CHECK42("%RHv", ~(RTHCUINTPTR)0, "ffffffffffffffff");
        CHECK42("%RHv", (RTHCUINTPTR)0x84342134, "0000000084342134");
    }
    else
    {
        CHECK42("%RHv", (RTHCUINTPTR)0, "00000000");
        CHECK42("%RHv", ~(RTHCUINTPTR)0, "ffffffff");
        CHECK42("%RHv", (RTHCUINTPTR)0x84342134, "84342134");
    }

    CHECK42("%RHx", (RTHCUINT)0x234, "234");
    CHECK42("%RHx", (RTHCUINT)0xffffffff, "ffffffff");

    CHECK42("%RI16", (int16_t)1, "1");
    CHECK42("%RI16", (int16_t)-16384, "-16384");

    CHECK42("%RI32", (int32_t)1123, "1123");
    CHECK42("%RI32", (int32_t)-86596, "-86596");

    CHECK42("%RI64", (int64_t)112345987345LL, "112345987345");
    CHECK42("%RI64", (int64_t)-8659643985723459LL, "-8659643985723459");

    CHECK42("%RI8", (int8_t)1, "1");
    CHECK42("%RI8", (int8_t)-128, "-128");

    CHECK42("%Rbn", "file.c", "file.c");
    CHECK42("%Rbn", "foo/file.c", "file.c");
    CHECK42("%Rbn", "/foo/file.c", "file.c");
    CHECK42("%Rbn", "/dir/subdir/", "subdir/");

    CHECK42("%Rfn", "function", "function");
    CHECK42("%Rfn", "void function(void)", "function");

    CHECK42("%RTfile", (RTFILE)127, "127");
    CHECK42("%RTfile", (RTFILE)12341234, "12341234");

    CHECK42("%RTfmode", (RTFMODE)0x123403, "00123403");

    CHECK42("%RTfoff", (RTFOFF)12342312, "12342312");
    CHECK42("%RTfoff", (RTFOFF)-123123123, "-123123123");
    CHECK42("%RTfoff", (RTFOFF)858694596874568LL, "858694596874568");

    RTFAR16 fp16;
    fp16.off = 0x34ff;
    fp16.sel = 0x0160;
    CHECK42("%RTfp16", fp16, "0160:34ff");

    RTFAR32 fp32;
    fp32.off = 0xff094030;
    fp32.sel = 0x0168;
    CHECK42("%RTfp32", fp32, "0168:ff094030");

    RTFAR64 fp64;
    fp64.off = 0xffff003401293487ULL;
    fp64.sel = 0x0ff8;
    CHECK42("%RTfp64", fp64, "0ff8:ffff003401293487");
    fp64.off = 0x0;
    fp64.sel = 0x0;
    CHECK42("%RTfp64", fp64, "0000:0000000000000000");

    CHECK42("%RTgid", (RTGID)-1, "-1");
    CHECK42("%RTgid", (RTGID)1004, "1004");

    CHECK42("%RTino", (RTINODE)0, "0000000000000000");
    CHECK42("%RTino", (RTINODE)0x123412341324ULL, "0000123412341324");

    CHECK42("%RTint", (RTINT)127, "127");
    CHECK42("%RTint", (RTINT)-586589, "-586589");
    CHECK42("%RTint", (RTINT)-23498723, "-23498723");

    CHECK42("%RTiop", (RTIOPORT)0x3c4, "03c4");
    CHECK42("%RTiop", (RTIOPORT)0xffff, "ffff");

    RTMAC Mac;
    Mac.au8[0] = 0;
    Mac.au8[1] = 0x1b;
    Mac.au8[2] = 0x21;
    Mac.au8[3] = 0x0a;
    Mac.au8[4] = 0x1d;
    Mac.au8[5] = 0xd9;
    CHECK42("%RTmac", &Mac, "00:1b:21:0a:1d:d9");
    Mac.au16[0] = 0xffff;
    Mac.au16[1] = 0xffff;
    Mac.au16[2] = 0xffff;
    CHECK42("%RTmac", &Mac, "ff:ff:ff:ff:ff:ff");

    RTNETADDRIPV4 Ipv4Addr;
    Ipv4Addr.u = RT_H2N_U32_C(0xf040d003);
    CHECK42("%RTnaipv4", Ipv4Addr.u, "240.64.208.3");
    Ipv4Addr.u = RT_H2N_U32_C(0xffffffff);
    CHECK42("%RTnaipv4", Ipv4Addr.u, "255.255.255.255");

    RTNETADDRIPV6 Ipv6Addr;

    /* any */
    memset(&Ipv6Addr, 0, sizeof(Ipv6Addr));
    CHECK42("%RTnaipv6", &Ipv6Addr, "::");

    /* loopback */
    Ipv6Addr.au8[15] = 1;
    CHECK42("%RTnaipv6", &Ipv6Addr, "::1");

    /* IPv4-compatible */
    Ipv6Addr.au8[12] = 1;
    Ipv6Addr.au8[13] = 1;
    Ipv6Addr.au8[14] = 1;
    Ipv6Addr.au8[15] = 1;
    CHECK42("%RTnaipv6", &Ipv6Addr, "::1.1.1.1");

    /* IPv4-mapped */
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0xffff);
    CHECK42("%RTnaipv6", &Ipv6Addr, "::ffff:1.1.1.1");

    /* IPv4-translated */
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0xffff);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x0000);
    CHECK42("%RTnaipv6", &Ipv6Addr, "::ffff:0:1.1.1.1");

    /* single zero word is not abbreviated, leading zeroes are not printed */
    Ipv6Addr.au16[0] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[1] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[2] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[3] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[6] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[7] = RT_H2N_U16_C(0x0001);
    CHECK42("%RTnaipv6", &Ipv6Addr, "0:1:0:1:0:1:0:1");

    /* longest run is abbreviated (here: at the beginning) */
    Ipv6Addr.au16[0] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[1] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[2] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[3] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[6] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[7] = RT_H2N_U16_C(0x0000);
    CHECK42("%RTnaipv6", &Ipv6Addr, "::1:0:0:1:0");

    /* longest run is abbreviated (here: first) */
    Ipv6Addr.au16[0] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[1] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[2] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[3] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[6] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[7] = RT_H2N_U16_C(0x0001);
    CHECK42("%RTnaipv6", &Ipv6Addr, "1::1:0:0:1");

    /* longest run is abbreviated (here: second) */
    Ipv6Addr.au16[0] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[1] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[2] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[3] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[6] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[7] = RT_H2N_U16_C(0x0001);
    CHECK42("%RTnaipv6", &Ipv6Addr, "1:0:0:1::1");

    /* longest run is abbreviated (here: at the end) */
    Ipv6Addr.au16[0] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[1] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[2] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[3] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[6] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[7] = RT_H2N_U16_C(0x0000);
    CHECK42("%RTnaipv6", &Ipv6Addr, "1:0:0:1::");

    /* first of the two runs of equal length is abbreviated */
    Ipv6Addr.au16[0] = RT_H2N_U16_C(0x2001);
    Ipv6Addr.au16[1] = RT_H2N_U16_C(0x0db8);
    Ipv6Addr.au16[2] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[3] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0x0001);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[6] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[7] = RT_H2N_U16_C(0x0001);
    CHECK42("%RTnaipv6", &Ipv6Addr, "2001:db8::1:0:0:1");

    Ipv6Addr.au16[0] = RT_H2N_U16_C(0x2001);
    Ipv6Addr.au16[1] = RT_H2N_U16_C(0x0db8);
    Ipv6Addr.au16[2] = RT_H2N_U16_C(0x85a3);
    Ipv6Addr.au16[3] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[4] = RT_H2N_U16_C(0x0000);
    Ipv6Addr.au16[5] = RT_H2N_U16_C(0x8a2e);
    Ipv6Addr.au16[6] = RT_H2N_U16_C(0x0370);
    Ipv6Addr.au16[7] = RT_H2N_U16_C(0x7334);
    CHECK42("%RTnaipv6", &Ipv6Addr, "2001:db8:85a3::8a2e:370:7334");

    Ipv6Addr.au64[0] = UINT64_MAX;
    Ipv6Addr.au64[1] = UINT64_MAX;
    CHECK42("%RTnaipv6", &Ipv6Addr, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff");

    RTNETADDR NetAddr;
    memset(&NetAddr, 0, sizeof(NetAddr));

    /* plain IPv6 address if port is not specified */
    NetAddr.enmType = RTNETADDRTYPE_IPV6;
    NetAddr.uAddr.au16[0] = RT_H2N_U16_C(0x0001);
    NetAddr.uAddr.au16[7] = RT_H2N_U16_C(0x0001);
    NetAddr.uPort = RTNETADDR_PORT_NA;
    CHECK42("%RTnaddr", &NetAddr, "1::1");

    /* square brackets around IPv6 address if port is specified */
    NetAddr.uPort = 1;
    CHECK42("%RTnaddr", &NetAddr, "[1::1]:1");

    CHECK42("%RTproc", (RTPROCESS)0xffffff, "00ffffff");
    CHECK42("%RTproc", (RTPROCESS)0x43455443, "43455443");

    if (sizeof(RTUINTPTR) == 8)
    {
        CHECK42("%RTptr", (RTUINTPTR)0, "0000000000000000");
        CHECK42("%RTptr", ~(RTUINTPTR)0, "ffffffffffffffff");
        CHECK42("%RTptr", (RTUINTPTR)0x84342134, "0000000084342134");
    }
    else
    {
        CHECK42("%RTptr", (RTUINTPTR)0, "00000000");
        CHECK42("%RTptr", ~(RTUINTPTR)0, "ffffffff");
        CHECK42("%RTptr", (RTUINTPTR)0x84342134, "84342134");
    }

    if (sizeof(RTCCUINTREG) == 8)
    {
        CHECK42("%RTreg", (RTCCUINTREG)0, "0000000000000000");
        CHECK42("%RTreg", ~(RTCCUINTREG)0, "ffffffffffffffff");
        CHECK42("%RTreg", (RTCCUINTREG)0x84342134, "0000000084342134");
        CHECK42("%RTreg", (RTCCUINTREG)0x23484342134ULL, "0000023484342134");
    }
    else
    {
        CHECK42("%RTreg", (RTCCUINTREG)0, "00000000");
        CHECK42("%RTreg", ~(RTCCUINTREG)0, "ffffffff");
        CHECK42("%RTreg", (RTCCUINTREG)0x84342134, "84342134");
    }

    CHECK42("%RTsel", (RTSEL)0x543, "0543");
    CHECK42("%RTsel", (RTSEL)0xf8f8, "f8f8");

    if (sizeof(RTSEMEVENT) == 8)
    {
        CHECK42("%RTsem", (RTSEMEVENT)0, "0000000000000000");
        CHECK42("%RTsem", (RTSEMEVENT)0x23484342134ULL, "0000023484342134");
    }
    else
    {
        CHECK42("%RTsem", (RTSEMEVENT)0, "00000000");
        CHECK42("%RTsem", (RTSEMEVENT)0x84342134, "84342134");
    }

    CHECK42("%RTsock", (RTSOCKET)12234, "12234");
    CHECK42("%RTsock", (RTSOCKET)584854543, "584854543");

    if (sizeof(RTTHREAD) == 8)
    {
        CHECK42("%RTthrd", (RTTHREAD)0, "0000000000000000");
        CHECK42("%RTthrd", (RTTHREAD)~(uintptr_t)0, "ffffffffffffffff");
        CHECK42("%RTthrd", (RTTHREAD)0x63484342134ULL, "0000063484342134");
    }
    else
    {
        CHECK42("%RTthrd", (RTTHREAD)0, "00000000");
        CHECK42("%RTthrd", (RTTHREAD)~(uintptr_t)0, "ffffffff");
        CHECK42("%RTthrd", (RTTHREAD)0x54342134, "54342134");
    }

    CHECK42("%RTuid", (RTUID)-2, "-2");
    CHECK42("%RTuid", (RTUID)90344, "90344");

    CHECK42("%RTuint", (RTUINT)584589, "584589");
    CHECK42("%RTuint", (RTUINT)3, "3");
    CHECK42("%RTuint", (RTUINT)2400000000U, "2400000000");

    RTUuidCreate(&Uuid);
    RTUuidToStr(&Uuid, szCorrect, sizeof(szCorrect));
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%RTuuid", &Uuid);
    if (strcmp(pszBuf, szCorrect))
        RTTestIFailed("error:    '%s'\n"
                      "expected: '%s'\n",
                      pszBuf, szCorrect);

    CHECK42("%RTxint", (RTUINT)0x2345, "2345");
    CHECK42("%RTxint", (RTUINT)0xffff8fff, "ffff8fff");

    CHECK42("%RU16", (uint16_t)7, "7");
    CHECK42("%RU16", (uint16_t)46384, "46384");

    CHECK42("%RU32", (uint32_t)1123, "1123");
    CHECK42("%RU32", (uint32_t)86596, "86596");
    CHECK42("%4RU32",  (uint32_t)42, "  42");
    CHECK42("%04RU32", (uint32_t)42, "0042");
    CHECK42("%.4RU32", (uint32_t)42, "0042");

    CHECK42("%RU64", (uint64_t)112345987345ULL, "112345987345");
    CHECK42("%RU64", (uint64_t)8659643985723459ULL, "8659643985723459");
    CHECK42("%14RU64",  (uint64_t)4, "             4");
    CHECK42("%014RU64", (uint64_t)4, "00000000000004");
    CHECK42("%.14RU64", (uint64_t)4, "00000000000004");

    CHECK42("%RU8", (uint8_t)1, "1");
    CHECK42("%RU8", (uint8_t)254, "254");
    CHECK42("%RU8", 256, "0");

    CHECK42("%RX16", (uint16_t)0x7, "7");
    CHECK42("%RX16", 0x46384, "6384");

    CHECK42("%RX32", (uint32_t)0x1123, "1123");
    CHECK42("%RX32", (uint32_t)0x49939493, "49939493");

    CHECK42("%RX64", UINT64_C(0x348734), "348734");
    CHECK42("%RX64", UINT64_C(0x12312312312343f), "12312312312343f");
    CHECK42("%5RX64",   UINT64_C(0x42), "   42");
    CHECK42("%05RX64",  UINT64_C(0x42), "00042");
    CHECK42("%.5RX64",  UINT64_C(0x42), "00042");
    CHECK42("%.05RX64", UINT64_C(0x42), "00042"); /* '0' is ignored */

    CHECK42("%RX8", (uint8_t)1, "1");
    CHECK42("%RX8", (uint8_t)0xff, "ff");
    CHECK42("%RX8", 0x100, "0");

    /*
     * Thousand separators.
     */
    RTTestSub(hTest, "Thousand Separators (%'*)");

    RTStrFormatNumber(pszBuf,       1, 10, 0, 0, RTSTR_F_THOUSAND_SEP); CHECKSTR("1");              memset(pszBuf, '!', BUF_SIZE);
    RTStrFormatNumber(pszBuf,      10, 10, 0, 0, RTSTR_F_THOUSAND_SEP); CHECKSTR("10");             memset(pszBuf, '!', BUF_SIZE);
    RTStrFormatNumber(pszBuf,     100, 10, 0, 0, RTSTR_F_THOUSAND_SEP); CHECKSTR("100");            memset(pszBuf, '!', BUF_SIZE);
    RTStrFormatNumber(pszBuf,    1000, 10, 0, 0, RTSTR_F_THOUSAND_SEP); CHECKSTR("1 000");          memset(pszBuf, '!', BUF_SIZE);
    RTStrFormatNumber(pszBuf,   10000, 10, 0, 0, RTSTR_F_THOUSAND_SEP); CHECKSTR("10 000");         memset(pszBuf, '!', BUF_SIZE);
    RTStrFormatNumber(pszBuf,  100000, 10, 0, 0, RTSTR_F_THOUSAND_SEP); CHECKSTR("100 000");        memset(pszBuf, '!', BUF_SIZE);
    RTStrFormatNumber(pszBuf, 1000000, 10, 0, 0, RTSTR_F_THOUSAND_SEP); CHECKSTR("1 000 000");      memset(pszBuf, '!', BUF_SIZE);

    CHECK42("%'u", 1,                              "1");
    CHECK42("%'u", 10,                            "10");
    CHECK42("%'u", 100,                          "100");
    CHECK42("%'u", 1000,                       "1 000");
    CHECK42("%'u", 10000,                     "10 000");
    CHECK42("%'u", 100000,                   "100 000");
    CHECK42("%'u", 1000000,                "1 000 000");
    CHECK42("%'RU64", _1T,         "1 099 511 627 776");
    CHECK42("%'RU64", _1E, "1 152 921 504 606 846 976");

    /*
     * String formatting.
     */
    RTTestSub(hTest, "String formatting (%s)");

//            0         1         2         3         4         5         6         7
//            0....5....0....5....0....5....0....5....0....5....0....5....0....5....0
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%-10s %-30s %s", "cmd", "args", "description");
    CHECKSTR("cmd        args                           description");

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%-10s %-30s %s", "cmd", "", "description");
    CHECKSTR("cmd                                       description");


    cch = RTStrPrintf(pszBuf, BUF_SIZE,  "%*s", 0, "");
    CHECKSTR("");

    /* automatic conversions. */
    static RTUNICP s_usz1[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0 }; //assumes ascii.
    static RTUTF16 s_wsz1[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0 }; //assumes ascii.

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%ls", s_wsz1);
    CHECKSTR("hello world");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%Ls", s_usz1);
    CHECKSTR("hello world");

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%.5ls", s_wsz1);
    CHECKSTR("hello");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%.5Ls", s_usz1);
    CHECKSTR("hello");

    /*
     * Unicode string formatting.
     */
    RTTestSub(hTest, "Unicode string formatting (%ls)");
    static RTUTF16 s_wszEmpty[]  = { 0 }; //assumes ascii.
    static RTUTF16 s_wszCmd[]    = { 'c', 'm', 'd', 0 }; //assumes ascii.
    static RTUTF16 s_wszArgs[]   = { 'a', 'r', 'g', 's', 0 }; //assumes ascii.
    static RTUTF16 s_wszDesc[]   = { 'd', 'e', 's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', 0 }; //assumes ascii.

//            0         1         2         3         4         5         6         7
//            0....5....0....5....0....5....0....5....0....5....0....5....0....5....0
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%-10ls %-30ls %ls", s_wszCmd, s_wszArgs, s_wszDesc);
    CHECKSTR("cmd        args                           description");

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%-10ls %-30ls %ls", s_wszCmd, s_wszEmpty, s_wszDesc);
    CHECKSTR("cmd                                       description");


#if 0
    static RTUNICP s_usz2[] = { 0xc5, 0xc6, 0xf8, 0 };
    static RTUTF16 s_wsz2[] = { 0xc5, 0xc6, 0xf8, 0 };
    static char    s_sz2[]  = { 0xc5, 0xc6, 0xf8, 0 };///@todo multibyte tests.

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%ls", s_wsz2);
    CHECKSTR(s_sz2);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%Ls", s_usz2);
    CHECKSTR(s_sz2);
#endif

    /*
     * Hex formatting.
     */
    RTTestSub(hTest, "Hex dump formatting (%Rhx*)");
    static uint8_t const s_abHex1[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 };
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%.1Rhxs", s_abHex1);
    CHECKSTR("00");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%.2Rhxs", s_abHex1);
    CHECKSTR("00 01");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%Rhxs", s_abHex1);
    CHECKSTR("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%.*Rhxs", sizeof(s_abHex1), s_abHex1);
    CHECKSTR("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%4.*Rhxs", sizeof(s_abHex1), s_abHex1);
    CHECKSTR("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%1.*Rhxs", sizeof(s_abHex1), s_abHex1);
    CHECKSTR("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14");
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%256.*Rhxs", sizeof(s_abHex1), s_abHex1);
    CHECKSTR("00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14");

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%4.8Rhxd", s_abHex1);
    RTStrPrintf(pszBuf2, BUF_SIZE,
                "%p 0000: 00 01 02 03 ....\n"
                "%p 0004: 04 05 06 07 ....",
                &s_abHex1[0], &s_abHex1[4]);
    CHECKSTR(pszBuf2);

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%4.6Rhxd", s_abHex1);
    RTStrPrintf(pszBuf2, BUF_SIZE,
                "%p 0000: 00 01 02 03 ....\n"
                "%p 0004: 04 05       ..",
                &s_abHex1[0], &s_abHex1[4]);
    CHECKSTR(pszBuf2);

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%.*Rhxd", sizeof(s_abHex1), s_abHex1);
    RTStrPrintf(pszBuf2, BUF_SIZE,
                "%p 0000: 00 01 02 03 04 05 06 07-08 09 0a 0b 0c 0d 0e 0f ................\n"
                "%p 0010: 10 11 12 13 14                                  ....."
                ,
                &s_abHex1[0], &s_abHex1[0x10]);
    CHECKSTR(pszBuf2);

    /*
     * x86 register formatting.
     */
    RTTestSub(hTest, "x86 register format types (%RAx86[*])");
    CHECK42("%RAx86[cr0]", UINT64_C(0x80000011),    "80000011{PE,ET,PG}");
    CHECK42("%RAx86[cr0]", UINT64_C(0x80000001),    "80000001{PE,PG}");
    CHECK42("%RAx86[cr0]", UINT64_C(0x00000001),    "00000001{PE}");
    CHECK42("%RAx86[cr0]", UINT64_C(0x80000000),    "80000000{PG}");
    CHECK42("%RAx86[cr4]", UINT64_C(0x80000001),    "80000001{VME,unkn=80000000}");
    CHECK42("%#RAx86[cr4]", UINT64_C(0x80000001),    "0x80000001{VME,unkn=0x80000000}");

    /*
     * Custom types.
     */
    RTTestSub(hTest, "Custom format types (%R[*])");
    RTTESTI_CHECK_RC(RTStrFormatTypeRegister("type3", TstType, (void *)((uintptr_t)TstType)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type3",           (void *)((uintptr_t)TstType + 3)), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3]", (void *)1);
    CHECKSTR("type3=1");

    RTTESTI_CHECK_RC(RTStrFormatTypeRegister("type1", TstType, (void *)((uintptr_t)TstType)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type1",           (void *)((uintptr_t)TstType + 1)), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1]", (void *)1, (void *)2);
    CHECKSTR("type3=1 type1=2");

    RTTESTI_CHECK_RC(RTStrFormatTypeRegister("type4", TstType, (void *)((uintptr_t)TstType)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type4",           (void *)((uintptr_t)TstType + 4)), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1] %R[type4]", (void *)1, (void *)2, (void *)3);
    CHECKSTR("type3=1 type1=2 type4=3");

    RTTESTI_CHECK_RC(RTStrFormatTypeRegister("type2", TstType, (void *)((uintptr_t)TstType)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type2",           (void *)((uintptr_t)TstType + 2)), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1] %R[type4] %R[type2]", (void *)1, (void *)2, (void *)3, (void *)4);
    CHECKSTR("type3=1 type1=2 type4=3 type2=4");

    RTTESTI_CHECK_RC(RTStrFormatTypeRegister("type5", TstType, (void *)((uintptr_t)TstType)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type5",           (void *)((uintptr_t)TstType + 5)), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1] %R[type4] %R[type2] %R[type5]", (void *)1, (void *)2, (void *)3, (void *)4, (void *)5);
    CHECKSTR("type3=1 type1=2 type4=3 type2=4 type5=5");

    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type1",           (void *)((uintptr_t)TstType + 1)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type2",           (void *)((uintptr_t)TstType + 2)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type3",           (void *)((uintptr_t)TstType + 3)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type4",           (void *)((uintptr_t)TstType + 4)), VINF_SUCCESS);
    RTTESTI_CHECK_RC(RTStrFormatTypeSetUser("type5",           (void *)((uintptr_t)TstType + 5)), VINF_SUCCESS);

    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1] %R[type4] %R[type2] %R[type5]", (void *)10, (void *)20, (void *)30, (void *)40, (void *)50);
    CHECKSTR("type3=10 type1=20 type4=30 type2=40 type5=50");

    RTTESTI_CHECK_RC(RTStrFormatTypeDeregister("type2"), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1] %R[type4] %R[type5]", (void *)10, (void *)20, (void *)30, (void *)40);
    CHECKSTR("type3=10 type1=20 type4=30 type5=40");

    RTTESTI_CHECK_RC(RTStrFormatTypeDeregister("type5"), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1] %R[type4]", (void *)10, (void *)20, (void *)30);
    CHECKSTR("type3=10 type1=20 type4=30");

    RTTESTI_CHECK_RC(RTStrFormatTypeDeregister("type4"), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3] %R[type1]", (void *)10, (void *)20);
    CHECKSTR("type3=10 type1=20");

    RTTESTI_CHECK_RC(RTStrFormatTypeDeregister("type1"), VINF_SUCCESS);
    cch = RTStrPrintf(pszBuf, BUF_SIZE, "%R[type3]", (void *)10);
    CHECKSTR("type3=10");

    RTTESTI_CHECK_RC(RTStrFormatTypeDeregister("type3"), VINF_SUCCESS);

    /*
     * Summarize and exit.
     */
    return RTTestSummaryAndDestroy(hTest);
}
Example #24
0
RTDECL(int) RTLocalIpcSessionConnect(PRTLOCALIPCSESSION phSession, const char *pszName, uint32_t fFlags)
{
    AssertPtrReturn(phSession, VERR_INVALID_POINTER);
    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    AssertReturn(*pszName, VERR_INVALID_PARAMETER);
    AssertReturn(!fFlags, VERR_INVALID_PARAMETER); /* Flags currently unused, must be 0. */

    PRTLOCALIPCSESSIONINT pThis = (PRTLOCALIPCSESSIONINT)RTMemAlloc(sizeof(*pThis));
    if (!pThis)
        return VERR_NO_MEMORY;

    pThis->u32Magic = RTLOCALIPCSESSION_MAGIC;
    pThis->cRefs = 1; /* The one we return. */
    pThis->fIOPending = false;
    pThis->fZeroByteRead = false;
    pThis->fCancelled = false;
    pThis->pbBounceBuf = NULL;
    pThis->cbBounceBufAlloc = 0;
    pThis->cbBounceBufUsed = 0;

    int rc = RTCritSectInit(&pThis->CritSect);
    if (RT_SUCCESS(rc))
    {
        pThis->hEvent = CreateEvent(NULL /*lpEventAttributes*/, TRUE /*bManualReset*/,
                                    FALSE /*bInitialState*/, NULL /*lpName*/);
        if (pThis->hEvent != NULL)
        {
            RT_ZERO(pThis->OverlappedIO);
            pThis->OverlappedIO.Internal = STATUS_PENDING;
            pThis->OverlappedIO.hEvent = pThis->hEvent;

            PSECURITY_DESCRIPTOR pSecDesc;
            rc = rtLocalIpcServerWinAllocSecurityDescriptior(&pSecDesc, false /* Client */);
            if (RT_SUCCESS(rc))
            {
                char *pszPipe;
                if (RTStrAPrintf(&pszPipe, "%s%s", RTLOCALIPC_WIN_PREFIX, pszName))
                {
                    SECURITY_ATTRIBUTES SecAttrs;
                    SecAttrs.nLength = sizeof(SECURITY_ATTRIBUTES);
                    SecAttrs.lpSecurityDescriptor = pSecDesc;
                    SecAttrs.bInheritHandle = FALSE;

                    HANDLE hPipe = CreateFile(pszPipe,                  /* pipe name */
                                                GENERIC_READ            /* read and write access */
                                              | GENERIC_WRITE,
                                              0,                        /* no sharing */
                                              &SecAttrs,                /* lpSecurityAttributes */
                                              OPEN_EXISTING,            /* opens existing pipe */
                                              FILE_FLAG_OVERLAPPED,     /* default attributes */
                                              NULL);                    /* no template file */
                    RTStrFree(pszPipe);

                    if (hPipe != INVALID_HANDLE_VALUE)
                    {
                        LocalFree(pSecDesc);

                        pThis->hNmPipe = hPipe;
                        *phSession = pThis;
                        return VINF_SUCCESS;
                    }
                    else
                        rc = RTErrConvertFromWin32(GetLastError());
                }
                else
                    rc = VERR_NO_MEMORY;

                LocalFree(pSecDesc);
            }

            BOOL fRc = CloseHandle(pThis->hEvent);
            AssertMsg(fRc, ("%d\n", GetLastError())); NOREF(fRc);
        }
        else
            rc = RTErrConvertFromWin32(GetLastError());

        int rc2 = RTCritSectDelete(&pThis->CritSect);
        AssertRC(rc2);
    }

    RTMemFree(pThis);
    return rc;
}
PUSBDEVICE USBProxyServiceOs2::getDevices(void)
{
    /*
     * Count the devices.
     */
    ULONG cDevices = 0;
    int rc = mpfnUsbQueryNumberDevices((PULONG)&cDevices); /* Thanks to com/xpcom, PULONG and ULONG * aren't the same. */
    if (rc)
        return NULL;

    /*
     * Retrieve information about each device.
     */
    PUSBDEVICE pFirst = NULL;
    PUSBDEVICE *ppNext = &pFirst;
    for (ULONG i = 0; i < cDevices; i++)
    {
        /*
         * Query the device and config descriptors.
         */
        uint8_t abBuf[1024];
        ULONG cb = sizeof(abBuf);
        rc = mpfnUsbQueryDeviceReport(i + 1, (PULONG)&cb, &abBuf[0]); /* see above (PULONG) */
        if (rc)
            continue;
        PUSBDEVICEDESC pDevDesc = (PUSBDEVICEDESC)&abBuf[0];
        if (    cb < sizeof(*pDevDesc)
            ||  pDevDesc->bDescriptorType != USB_DT_DEVICE
            ||  pDevDesc->bLength < sizeof(*pDevDesc)
            ||  pDevDesc->bLength > sizeof(*pDevDesc) * 2)
            continue;
        PUSBCONFIGDESC pCfgDesc = (PUSBCONFIGDESC)&abBuf[pDevDesc->bLength];
        if (    pCfgDesc->bDescriptorType != USB_DT_CONFIG
            ||  pCfgDesc->bLength >= sizeof(*pCfgDesc))
            pCfgDesc = NULL;

        /*
         * Skip it if it's some kind of hub.
         */
        if (pDevDesc->bDeviceClass == USB_HUB_CLASSCODE)
            continue;

        /*
         * Allocate a new device node and initialize it with the basic stuff.
         */
        PUSBDEVICE pCur = (PUSBDEVICE)RTMemAlloc(sizeof(*pCur));
        pCur->bcdUSB = pDevDesc->bcdUSB;
        pCur->bDeviceClass = pDevDesc->bDeviceClass;
        pCur->bDeviceSubClass = pDevDesc->bDeviceSubClass;
        pCur->bDeviceProtocol = pDevDesc->bDeviceProtocol;
        pCur->idVendor = pDevDesc->idVendor;
        pCur->idProduct = pDevDesc->idProduct;
        pCur->bcdDevice = pDevDesc->bcdDevice;
        pCur->pszManufacturer = RTStrDup("");
        pCur->pszProduct = RTStrDup("");
        pCur->pszSerialNumber = NULL;
        pCur->u64SerialHash = 0;
        //pCur->bNumConfigurations = pDevDesc->bNumConfigurations;
        pCur->bNumConfigurations = 0;
        pCur->paConfigurations = NULL;
        pCur->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
        pCur->enmSpeed = USBDEVICESPEED_UNKNOWN;
        pCur->pszAddress = NULL;
        RTStrAPrintf((char **)&pCur->pszAddress, "p=0x%04RX16;v=0x%04RX16;r=0x%04RX16;e=0x%08RX32",
                     pDevDesc->idProduct, pDevDesc->idVendor, pDevDesc->bcdDevice, i);

        pCur->bBus = 0;
        pCur->bLevel = 0;
        pCur->bDevNum = 0;
        pCur->bDevNumParent = 0;
        pCur->bPort = 0;
        pCur->bNumDevices = 0;
        pCur->bMaxChildren = 0;

        /* link it */
        pCur->pNext = NULL;
        pCur->pPrev = *ppNext;
        *ppNext = pCur;
        ppNext = &pCur->pNext;
    }

    return pFirst;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPSTR /*lpCmdLine*/, int /*nShowCmd*/)
{
    LPCTSTR lpCmdLine = GetCommandLine(); /* this line necessary for _ATL_MIN_CRT */

    /*
     * Need to parse the command line before initializing the VBox runtime.
     */
    TCHAR szTokens[] = _T("-/");
    LPCTSTR lpszToken = FindOneOf(lpCmdLine, szTokens);
    while (lpszToken != NULL)
    {
        if (WordCmpI(lpszToken, _T("Embedding")) == 0)
        {
            /* %HOMEDRIVE%%HOMEPATH% */
            wchar_t wszHome[RTPATH_MAX];
            DWORD cEnv = GetEnvironmentVariable(L"HOMEDRIVE", &wszHome[0], RTPATH_MAX);
            if (cEnv && cEnv < RTPATH_MAX)
            {
                DWORD cwc = cEnv; /* doesn't include NUL */
                cEnv = GetEnvironmentVariable(L"HOMEPATH", &wszHome[cEnv], RTPATH_MAX - cwc);
                if (cEnv && cEnv < RTPATH_MAX - cwc)
                {
                    /* If this fails there is nothing we can do. Ignore. */
                    SetCurrentDirectory(wszHome);
                }
            }
        }

        lpszToken = FindOneOf(lpszToken, szTokens);
    }

    /*
     * Initialize the VBox runtime without loading
     * the support driver.
     */
    int    argc = __argc;
    char **argv = __argv;
    RTR3InitExe(argc, &argv, 0);

    /* Note that all options are given lowercase/camel case/uppercase to
     * approximate case insensitive matching, which RTGetOpt doesn't offer. */
    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--embedding",    'e',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "-embedding",     'e',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "/embedding",     'e',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "--unregserver",  'u',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "-unregserver",   'u',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "/unregserver",   'u',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "--regserver",    'r',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "-regserver",     'r',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "/regserver",     'r',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "--reregserver",  'f',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "-reregserver",   'f',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "/reregserver",   'f',    RTGETOPT_REQ_NOTHING | RTGETOPT_FLAG_ICASE },
        { "--helper",       'H',    RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE },
        { "-helper",        'H',    RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE },
        { "/helper",        'H',    RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE },
        { "--logfile",      'F',    RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE },
        { "-logfile",       'F',    RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE },
        { "/logfile",       'F',    RTGETOPT_REQ_STRING | RTGETOPT_FLAG_ICASE },
        { "--logrotate",    'R',    RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE },
        { "-logrotate",     'R',    RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE },
        { "/logrotate",     'R',    RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE },
        { "--logsize",      'S',    RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_ICASE },
        { "-logsize",       'S',    RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_ICASE },
        { "/logsize",       'S',    RTGETOPT_REQ_UINT64 | RTGETOPT_FLAG_ICASE },
        { "--loginterval",  'I',    RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE },
        { "-loginterval",   'I',    RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE },
        { "/loginterval",   'I',    RTGETOPT_REQ_UINT32 | RTGETOPT_FLAG_ICASE },
    };

    bool            fRun = true;
    bool            fRegister = false;
    bool            fUnregister = false;
    const char      *pszPipeName = NULL;
    const char      *pszLogFile = NULL;
    uint32_t        cHistory = 10;                  // enable log rotation, 10 files
    uint32_t        uHistoryFileTime = RT_SEC_1DAY; // max 1 day per file
    uint64_t        uHistoryFileSize = 100 * _1M;   // max 100MB per file

    RTGETOPTSTATE   GetOptState;
    int vrc = RTGetOptInit(&GetOptState, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, 0 /*fFlags*/);
    AssertRC(vrc);

    RTGETOPTUNION   ValueUnion;
    while ((vrc = RTGetOpt(&GetOptState, &ValueUnion)))
    {
        switch (vrc)
        {
            case 'e':
                /* already handled above */
                break;

            case 'u':
                fUnregister = true;
                fRun = false;
                break;

            case 'r':
                fRegister = true;
                fRun = false;
                break;

            case 'f':
                fUnregister = true;
                fRegister = true;
                fRun = false;
                break;

            case 'H':
                pszPipeName = ValueUnion.psz;
                if (!pszPipeName)
                    pszPipeName = "";
                fRun = false;
                break;

            case 'F':
                pszLogFile = ValueUnion.psz;
                break;

            case 'R':
                cHistory = ValueUnion.u32;
                break;

            case 'S':
                uHistoryFileSize = ValueUnion.u64;
                break;

            case 'I':
                uHistoryFileTime = ValueUnion.u32;
                break;

            case 'h':
            {
                TCHAR txt[]= L"Options:\n\n"
                             L"/RegServer:\tregister COM out-of-proc server\n"
                             L"/UnregServer:\tunregister COM out-of-proc server\n"
                             L"/ReregServer:\tunregister and register COM server\n"
                             L"no options:\trun the server";
                TCHAR title[]=_T("Usage");
                fRun = false;
                MessageBox(NULL, txt, title, MB_OK);
                return 0;
            }

            case 'V':
            {
                char *psz = NULL;
                RTStrAPrintf(&psz, "%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
                PRTUTF16 txt = NULL;
                RTStrToUtf16(psz, &txt);
                TCHAR title[]=_T("Version");
                fRun = false;
                MessageBox(NULL, txt, title, MB_OK);
                RTStrFree(psz);
                RTUtf16Free(txt);
                return 0;
            }

            default:
                /** @todo this assumes that stderr is visible, which is not
                 * true for standard Windows applications. */
                /* continue on command line errors... */
                RTGetOptPrintError(vrc, &ValueUnion);
        }
    }

    /* Only create the log file when running VBoxSVC normally, but not when
     * registering/unregistering or calling the helper functionality. */
    if (fRun)
    {
        if (!pszLogFile)
        {
            char szLogFile[RTPATH_MAX];
            vrc = com::GetVBoxUserHomeDirectory(szLogFile, sizeof(szLogFile));
            if (RT_SUCCESS(vrc))
                vrc = RTPathAppend(szLogFile, sizeof(szLogFile), "VBoxSVC.log");
            if (RT_SUCCESS(vrc))
                pszLogFile = RTStrDup(szLogFile);
        }
        char szError[RTPATH_MAX + 128];
        vrc = com::VBoxLogRelCreate("COM Server", pszLogFile,
                                    RTLOGFLAGS_PREFIX_THREAD | RTLOGFLAGS_PREFIX_TIME_PROG,
                                    "all", "VBOXSVC_RELEASE_LOG",
                                    RTLOGDEST_FILE, UINT32_MAX /* cMaxEntriesPerGroup */,
                                    cHistory, uHistoryFileTime, uHistoryFileSize,
                                    szError, sizeof(szError));
        if (RT_FAILURE(vrc))
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "failed to open release log (%s, %Rrc)", szError, vrc);
    }

    int nRet = 0;
    HRESULT hRes = com::Initialize();

    _ASSERTE(SUCCEEDED(hRes));
    _Module.Init(ObjectMap, hInstance, &LIBID_VirtualBox);
    _Module.dwThreadID = GetCurrentThreadId();

    if (!fRun)
    {
        if (fUnregister)
        {
            _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, FALSE);
            nRet = _Module.UnregisterServer(TRUE);
        }
        if (fRegister)
        {
            _Module.UpdateRegistryFromResource(IDR_VIRTUALBOX, TRUE);
            nRet = _Module.RegisterServer(TRUE);
        }
        if (pszPipeName)
        {
            Log(("SVCMAIN: Processing Helper request (cmdline=\"%s\")...\n", pszPipeName));

            if (!*pszPipeName)
                vrc = VERR_INVALID_PARAMETER;

            if (RT_SUCCESS(vrc))
            {
                /* do the helper job */
                SVCHlpServer server;
                vrc = server.open(pszPipeName);
                if (RT_SUCCESS(vrc))
                    vrc = server.run();
            }
            if (RT_FAILURE(vrc))
            {
                Log(("SVCMAIN: Failed to process Helper request (%Rrc).", vrc));
                nRet = 1;
            }
        }
    }
    else
    {
        _Module.StartMonitor();
#if _WIN32_WINNT >= 0x0400 & defined(_ATL_FREE_THREADED)
        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED);
        _ASSERTE(SUCCEEDED(hRes));
        hRes = CoResumeClassObjects();
#else
        hRes = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE);
#endif
        _ASSERTE(SUCCEEDED(hRes));

        MSG msg;
        while (GetMessage(&msg, 0, 0, 0))
            DispatchMessage(&msg);

        _Module.RevokeClassObjects();
        Sleep(dwPause); //wait for any threads to finish
    }

    _Module.Term();

    com::Shutdown();

    Log(("SVCMAIN: Returning, COM server process ends.\n"));
    return nRet;
}
int VBoxSharedFoldersAutoMount(void)
{
    uint32_t u32ClientId;
    int rc = VbglR3SharedFolderConnect(&u32ClientId);
    if (RT_FAILURE(rc))
        Log(("VBoxTray: Failed to connect to the shared folder service, error %Rrc\n", rc));
    else
    {
        uint32_t cMappings;
        VBGLR3SHAREDFOLDERMAPPING *paMappings;

        rc = VbglR3SharedFolderGetMappings(u32ClientId, true /* Only process auto-mounted folders */,
                                           &paMappings, &cMappings);
        if (RT_SUCCESS(rc))
        {
#if 0
            /* Check for a fixed/virtual auto-mount share. */
            if (VbglR3SharedFolderExists(u32ClientId, "vbsfAutoMount"))
            {
                Log(("VBoxTray: Hosts supports auto-mount root\n"));
            }
            else
            {
#endif
                Log(("VBoxTray: Got %u shared folder mappings\n", cMappings));
                for (uint32_t i = 0; i < cMappings && RT_SUCCESS(rc); i++)
                {
                    char *pszName = NULL;
                    rc = VbglR3SharedFolderGetName(u32ClientId, paMappings[i].u32Root, &pszName);
                    if (   RT_SUCCESS(rc)
                        && *pszName)
                    {
                        Log(("VBoxTray: Connecting share %u (%s) ...\n", i+1, pszName));

                        char *pszShareName;
                        if (RTStrAPrintf(&pszShareName, "\\\\vboxsrv\\%s", pszName) >= 0)
                        {
                            char chDrive = 'D'; /* Start probing whether drive D: is free to use. */
                            do
                            {
                                char szCurDrive[3];
                                RTStrPrintf(szCurDrive, sizeof(szCurDrive), "%c:", chDrive++);

                                NETRESOURCE resource;
                                RT_ZERO(resource);
                                resource.dwType = RESOURCETYPE_ANY;
                                resource.lpLocalName = TEXT(szCurDrive);
                                resource.lpRemoteName = TEXT(pszShareName);
                                /* Go straight to our network provider in order to get maximum lookup speed. */
                                resource.lpProvider = TEXT("VirtualBox Shared Folders");

                                /** @todo Figure out how to map the drives in a block (F,G,H, ...).
                                          Save the mapping for later use. */
                                DWORD dwErr = WNetAddConnection2A(&resource, NULL, NULL, 0);
                                if (dwErr == NO_ERROR)
                                {
                                    LogRel(("VBoxTray: Shared folder \"%s\" was mounted to drive \"%s\"\n", pszName, szCurDrive));
                                    break;
                                }
                                else
                                {
                                    LogRel(("VBoxTray: Mounting \"%s\" to \"%s\" resulted in dwErr = %ld\n", pszName, szCurDrive, dwErr));

                                    switch (dwErr)
                                    {
                                        /*
                                         * The local device specified by the lpLocalName member is already
                                         * connected to a network resource.  Try next drive ...
                                         */
                                        case ERROR_ALREADY_ASSIGNED:
                                            break;

                                        default:
                                            LogRel(("VBoxTray: Error while mounting shared folder \"%s\" to \"%s\", error = %ld\n",
                                                    pszName, szCurDrive, dwErr));
                                            break;
                                    }
                                }
                            } while (chDrive <= 'Z');

                            if (chDrive > 'Z')
                            {
                                LogRel(("VBoxTray: No free driver letter found to assign shared folder \"%s\", aborting\n", pszName));
                                break;
                            }

                            RTStrFree(pszShareName);
                        }
                        else
                            rc = VERR_NO_STR_MEMORY;
                        RTStrFree(pszName);
                    }
                    else
                        Log(("VBoxTray: Error while getting the shared folder name for root node = %u, rc = %Rrc\n",
                             paMappings[i].u32Root, rc));
                }
#if 0
            }
#endif
            RTMemFree(paMappings);
        }
        else
            Log(("VBoxTray: Error while getting the shared folder mappings, rc = %Rrc\n", rc));
        VbglR3SharedFolderDisconnect(u32ClientId);
    }
    return rc;
}
int VBoxSharedFoldersAutoUnmount(void)
{
    uint32_t u32ClientId;
    int rc = VbglR3SharedFolderConnect(&u32ClientId);
    if (!RT_SUCCESS(rc))
        Log(("VBoxTray: Failed to connect to the shared folder service, error %Rrc\n", rc));
    else
    {
        uint32_t cMappings;
        VBGLR3SHAREDFOLDERMAPPING *paMappings;

        rc = VbglR3SharedFolderGetMappings(u32ClientId, true /* Only process auto-mounted folders */,
                                           &paMappings, &cMappings);
        if (RT_SUCCESS(rc))
        {
            for (uint32_t i = 0; i < cMappings && RT_SUCCESS(rc); i++)
            {
                char *pszName = NULL;
                rc = VbglR3SharedFolderGetName(u32ClientId, paMappings[i].u32Root, &pszName);
                if (   RT_SUCCESS(rc)
                    && *pszName)
                {
                    Log(("VBoxTray: Disconnecting share %u (%s) ...\n", i+1, pszName));

                    char *pszShareName;
                    if (RTStrAPrintf(&pszShareName, "\\\\vboxsrv\\%s", pszName) >= 0)
                    {
                        DWORD dwErr = WNetCancelConnection2(pszShareName, 0, FALSE /* Force disconnect */);
                        if (dwErr == NO_ERROR)
                        {
                            LogRel(("VBoxTray: Share \"%s\" was disconnected\n", pszShareName));
                            RTStrFree(pszShareName);
                            RTStrFree(pszName);
                            break;
                        }

                        LogRel(("VBoxTray: Disconnecting \"%s\" failed, dwErr = %ld\n", pszShareName, dwErr));

                        switch (dwErr)
                        {
                            case ERROR_NOT_CONNECTED:
                                break;

                            default:
                                LogRel(("VBoxTray: Error while disconnecting shared folder \"%s\", error = %ld\n",
                                        pszShareName, dwErr));
                                break;
                        }

                        RTStrFree(pszShareName);
                    }
                    else
                        rc = VERR_NO_MEMORY;
                    RTStrFree(pszName);
                }
                else
                    Log(("VBoxTray: Error while getting the shared folder name for root node = %u, rc = %Rrc\n",
                         paMappings[i].u32Root, rc));
            }
            RTMemFree(paMappings);
        }
        else
            Log(("VBoxTray: Error while getting the shared folder mappings, rc = %Rrc\n", rc));
        VbglR3SharedFolderDisconnect(u32ClientId);
    }
    return rc;
}
DECLHIDDEN(int) drvHostBaseOpenOs(PDRVHOSTBASE pThis, bool fReadOnly)
{
    RT_NOREF(fReadOnly);
    RTFILE hFileDevice;
    int rc = RTFileOpen(&hFileDevice, pThis->pszDevice, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    if (RT_FAILURE(rc))
        return rc;

    /*
     * The current device handle can't passthrough SCSI commands.
     * We have to get he passthrough device path and open this.
     */
    union ccb DeviceCCB;
    memset(&DeviceCCB, 0, sizeof(DeviceCCB));

    DeviceCCB.ccb_h.func_code = XPT_GDEVLIST;
    int rcBSD = ioctl(RTFileToNative(hFileDevice), CAMGETPASSTHRU, &DeviceCCB);
    if (!rcBSD)
    {
        char *pszPassthroughDevice = NULL;
        rc = RTStrAPrintf(&pszPassthroughDevice, "/dev/%s%u",
                          DeviceCCB.cgdl.periph_name, DeviceCCB.cgdl.unit_number);
        if (rc >= 0)
        {
            RTFILE hPassthroughDevice;
            rc = RTFileOpen(&hPassthroughDevice, pszPassthroughDevice, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
            RTStrFree(pszPassthroughDevice);
            if (RT_SUCCESS(rc))
            {
                /* Get needed device parameters. */

                /*
                 * The device path, target id and lun id. Those are
                 * needed for the SCSI passthrough ioctl.
                 */
                memset(&DeviceCCB, 0, sizeof(DeviceCCB));
                DeviceCCB.ccb_h.func_code = XPT_GDEVLIST;

                rcBSD = ioctl(RTFileToNative(hPassthroughDevice), CAMGETPASSTHRU, &DeviceCCB);
                if (!rcBSD)
                {
                    if (DeviceCCB.cgdl.status != CAM_GDEVLIST_ERROR)
                    {
                        pThis->Os.ScsiBus      = DeviceCCB.ccb_h.path_id;
                        pThis->Os.ScsiTargetID = DeviceCCB.ccb_h.target_id;
                        pThis->Os.ScsiLunID    = DeviceCCB.ccb_h.target_lun;
                        pThis->Os.hFileDevice  = hPassthroughDevice;
                    }
                    else
                    {
                        /* The passthrough device wasn't found. */
                        rc = VERR_NOT_FOUND;
                    }
                }
                else
                    rc = RTErrConvertFromErrno(errno);

                if (RT_FAILURE(rc))
                    RTFileClose(hPassthroughDevice);
            }
        }
        else
            rc = VERR_NO_STR_MEMORY;
    }
    else
        rc = RTErrConvertFromErrno(errno);

    RTFileClose(hFileDevice);
    return rc;
}