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

    /*
     * Parse arguments up to the command and pass it on to the command handlers.
     */
    typedef enum
    {
        VCUACTION_ADD_TRUSTED_PUBLISHER = 1000,
        VCUACTION_REMOVE_TRUSTED_PUBLISHER,
        VCUACTION_DISPLAY_ALL,
        VCUACTION_END
    } VCUACTION;

    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--verbose",                  'v',                                RTGETOPT_REQ_NOTHING },
        { "--quiet",                    'q',                                RTGETOPT_REQ_NOTHING },
        { "add-trusted-publisher",      VCUACTION_ADD_TRUSTED_PUBLISHER,    RTGETOPT_REQ_NOTHING },
        { "remove-trusted-publisher",   VCUACTION_REMOVE_TRUSTED_PUBLISHER, RTGETOPT_REQ_NOTHING },
        { "display-all",                VCUACTION_DISPLAY_ALL,              RTGETOPT_REQ_NOTHING },
    };

    RTGETOPTUNION   ValueUnion;
    RTGETOPTSTATE   GetState;
    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
    {
        switch (rc)
        {
            case 'v':
                g_cVerbosityLevel++;
                break;

            case 'q':
                if (g_cVerbosityLevel > 0)
                    g_cVerbosityLevel--;
                break;

            case 'h':
                showUsage(argv[0]);
                return RTEXITCODE_SUCCESS;

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

            case VCUACTION_ADD_TRUSTED_PUBLISHER:
                return cmdAddTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);

            case VCUACTION_REMOVE_TRUSTED_PUBLISHER:
                return cmdRemoveTrustedPublisher(argc - GetState.iNext + 1, argv + GetState.iNext - 1);

            case VCUACTION_DISPLAY_ALL:
                return cmdDisplayAll(argc - GetState.iNext + 1, argv + GetState.iNext - 1);

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

    RTMsgError("Missing command...");
    showUsage(argv[0]);
    return RTEXITCODE_SYNTAX;
}
/**
 * Method that does the actual resize of the guest framebuffer and
 * then changes the SDL framebuffer setup.
 */
static void bench(unsigned long w, unsigned long h, unsigned long bpp)
{
    Uint32 Rmask,  Gmask,  Bmask, Amask = 0;
    Uint32 Rsize,  Gsize,  Bsize;
    Uint32 newWidth, newHeight;

    guGuestXRes = w;
    guGuestYRes = h;
    guGuestBpp  = bpp;

    RTPrintf("\n");

    /* a different format we support directly? */
    switch (guGuestBpp)
    {
        case 16:
        {
            Rmask = 0xF800;
            Gmask = 0x07E0;
            Bmask = 0x001F;
            Amask = 0x0000;
            Rsize  = 5;
            Gsize  = 6;
            Bsize  = 5;
            break;
        }

        case 24:
        {
            Rmask = 0x00FF0000;
            Gmask = 0x0000FF00;
            Bmask = 0x000000FF;
            Amask = 0x00000000;
            Rsize  = 8;
            Gsize  = 8;
            Bsize  = 8;
            break;
        }

        default:
            Rmask = 0x00FF0000;
            Gmask = 0x0000FF00;
            Bmask = 0x000000FF;
            Amask = 0x00000000;
            Rsize  = 8;
            Gsize  = 8;
            Bsize  = 8;
            break;
    }

    int sdlFlags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
#ifdef VBOX_OPENGL
    if (gfOpenGL)
        sdlFlags |= SDL_OPENGL;
#endif
    if (gfResizable)
        sdlFlags |= SDL_RESIZABLE;
    if (gfFullscreen)
        sdlFlags |= SDL_FULLSCREEN;

    /*
     * Now we have to check whether there are video mode restrictions
     */
    SDL_Rect **modes;
    /* Get available fullscreen/hardware modes */
    modes = SDL_ListModes(NULL, sdlFlags);
    if (modes == NULL)
    {
        RTPrintf("Error: SDL_ListModes failed with message '%s'\n", SDL_GetError());
        return;
    }

    /* -1 means that any mode is possible (usually non fullscreen) */
    if (modes != (SDL_Rect **)-1)
    {
        /*
         * according to the SDL documentation, the API guarantees that
         * the modes are sorted from larger to smaller, so we just
         * take the first entry as the maximum.
         */
        guMaxScreenWidth  = modes[0]->w;
        guMaxScreenHeight = modes[0]->h;
    }
    else
    {
        /* no restriction */
        guMaxScreenWidth  = ~0;
        guMaxScreenHeight = ~0;
    }

    newWidth  = RT_MIN(guMaxScreenWidth,  guGuestXRes);
    newHeight = RT_MIN(guMaxScreenHeight, guGuestYRes);

    /*
     * Now set the screen resolution and get the surface pointer
     * @todo BPP is not supported!
     */
#ifdef VBOX_OPENGL
    if (gfOpenGL)
    {
        checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_RED_SIZE,   Rsize));
        checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, Gsize));
        checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE,  Bsize));
        checkSDL("SDL_GL_SetAttribute", SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 0));
    }
#else
    NOREF(Rsize); NOREF(Gsize); NOREF(Bsize);
#endif

    RTPrintf("Testing "ESC_BOLD"%ldx%[email protected]%ld"ESC_NORM"\n", guGuestXRes, guGuestYRes, guGuestBpp);

    gScreen = SDL_SetVideoMode(newWidth, newHeight, 0, sdlFlags);
    if (!gScreen)
    {
        RTPrintf("SDL_SetVideoMode failed (%s)\n", SDL_GetError());
        return;
    }

    /* first free the current surface */
    if (gSurfVRAM)
    {
        SDL_FreeSurface(gSurfVRAM);
        gSurfVRAM = NULL;
    }
    if (gPtrVRAM)
    {
        free(gPtrVRAM);
        gPtrVRAM = NULL;
    }

    if (gScreen->format->BitsPerPixel != guGuestBpp)
    {
        /* Create a source surface from guest VRAM. */
        int bytes_per_pixel = (guGuestBpp + 7) / 8;
        gPtrVRAM  = malloc(guGuestXRes * guGuestYRes * bytes_per_pixel);
        gSurfVRAM = SDL_CreateRGBSurfaceFrom(gPtrVRAM, guGuestXRes, guGuestYRes, guGuestBpp,
                                             bytes_per_pixel * guGuestXRes,
                                             Rmask, Gmask, Bmask, Amask);
    }
    else
    {
        /* Create a software surface for which SDL allocates the RAM */
        gSurfVRAM = SDL_CreateRGBSurface(SDL_SWSURFACE, guGuestXRes, guGuestYRes, guGuestBpp,
                                         Rmask, Gmask, Bmask, Amask);
    }

    if (!gSurfVRAM)
    {
        RTPrintf("Failed to allocate surface %ldx%[email protected]%ld\n",
                guGuestXRes, guGuestYRes, guGuestBpp);
        return;
    }

    RTPrintf("  gScreen=%dx%[email protected]%d (surface: %s)\n",
            gScreen->w, gScreen->h, gScreen->format->BitsPerPixel,
             (gScreen->flags & SDL_HWSURFACE) == 0 ? "software" : "hardware");

    SDL_Rect rect = { 0, 0, (Uint16)guGuestXRes, (Uint16)guGuestYRes };
    checkSDL("SDL_FillRect",
              SDL_FillRect(gSurfVRAM, &rect,
                           SDL_MapRGB(gSurfVRAM->format, 0x5F, 0x6F, 0x1F)));

#ifdef VBOX_OPENGL
    if (gfOpenGL)
    {
        int r, g, b, d, o;
        SDL_GL_GetAttribute(SDL_GL_RED_SIZE,     &r);
        SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE,   &g);
        SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE,    &b);
        SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE,   &d);
        SDL_GL_GetAttribute(SDL_GL_DOUBLEBUFFER, &o);
        RTPrintf("  OpenGL ctxt red=%d, green=%d, blue=%d, depth=%d, dbl=%d", r, g, b, d, o);

        glEnable(GL_TEXTURE_2D);
        glDisable(GL_BLEND);
        glDisable(GL_DEPTH_TEST);
        glDepthMask(GL_FALSE);
        glGenTextures(1, &gTexture);
        glBindTexture(GL_TEXTURE_2D, gTexture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

        for (guTextureWidth  = 32; guTextureWidth  < newWidth;  guTextureWidth  <<= 1)
            ;
        for (guTextureHeight = 32; guTextureHeight < newHeight; guTextureHeight <<= 1)
            ;
        RTPrintf(", tex %ldx%ld\n", guTextureWidth, guTextureHeight);

        switch (guGuestBpp)
        {
            case 16: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB5, guTextureWidth, guTextureHeight, 0,
                                  GL_RGB,  GL_UNSIGNED_SHORT_5_6_5, 0);
                     break;
            case 24: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,  guTextureWidth, guTextureHeight, 0,
                                  GL_BGR,  GL_UNSIGNED_BYTE, 0);
                     break;
            case 32: glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, guTextureWidth, guTextureHeight, 0,
                                  GL_BGRA, GL_UNSIGNED_BYTE, 0);
                     break;
            default: RTPrintf("guGuestBpp=%d?\n", guGuestBpp);
                     return;
        }

        glViewport(0, 0, newWidth, newHeight);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0.0, newWidth, newHeight, 0.0, -1.0, 1.0);
    }
#endif

    checkEvents();
    benchExecute();

#ifdef VBOX_OPENGL
    if (gfOpenGL)
    {
        glDeleteTextures(1, &gTexture);
    }
#endif
}
int main()
{
    int cErrors = 0;

#define CHECK_EXPR(expr) \
    do { bool const f = !!(expr); if (RT_UNLIKELY(!f)) { RTPrintf("tstStrSimplePattern(%d): %s!\n", __LINE__, #expr); cErrors++; } } while (0)
#define CHECK_EXPR_MSG(expr, msg) \
    do { \
        bool const f = !!(expr); \
        if (RT_UNLIKELY(!f)) { \
            RTPrintf("tstStrSimplePattern(%d): %s!\n", __LINE__, #expr); \
            RTPrintf("tstStrSimplePattern: "); \
            RTPrintf msg; \
            ++cErrors; \
        } \
    } while (0)

    CHECK_EXPR(RTStrSimplePatternMatch("*", ""));
    CHECK_EXPR(RTStrSimplePatternMatch("*", "asdfasdflkjasdlfkj"));
    CHECK_EXPR(RTStrSimplePatternMatch("*?*?*?*?*", "asdfasdflkjasdlfkj"));
    CHECK_EXPR(RTStrSimplePatternMatch("asdf??df", "asdfasdf"));
    CHECK_EXPR(!RTStrSimplePatternMatch("asdf??dq", "asdfasdf"));
    CHECK_EXPR(RTStrSimplePatternMatch("asdf*df", "asdfasdf"));
    CHECK_EXPR(!RTStrSimplePatternMatch("asdf*dq", "asdfasdf"));
    CHECK_EXPR(RTStrSimplePatternMatch("a*", "asdfasdf"));
    CHECK_EXPR(RTStrSimplePatternMatch("a*f", "asdfasdf"));
    CHECK_EXPR(!RTStrSimplePatternMatch("a*q", "asdfasdf"));
    CHECK_EXPR(!RTStrSimplePatternMatch("a*q?", "asdfasdf"));
    CHECK_EXPR(RTStrSimplePatternMatch("?*df", "asdfasdf"));

    CHECK_EXPR(RTStrSimplePatternNMatch("*", 1, "", 0));
    CHECK_EXPR(RTStrSimplePatternNMatch("*", ~(size_t)0, "", 0));
    CHECK_EXPR(RTStrSimplePatternNMatch("*", ~(size_t)0, "", ~(size_t)0));
    CHECK_EXPR(RTStrSimplePatternNMatch("*", 1, "asdfasdflkjasdlfkj", ~(size_t)0));
    CHECK_EXPR(RTStrSimplePatternNMatch("*", ~(size_t)0, "asdfasdflkjasdlfkj", ~(size_t)0));
    CHECK_EXPR(RTStrSimplePatternNMatch("*", 1, "asdfasdflkjasdlfkj", 3));
    CHECK_EXPR(RTStrSimplePatternNMatch("*", 2, "asdfasdflkjasdlfkj", 10));
    CHECK_EXPR(RTStrSimplePatternNMatch("*", 15, "asdfasdflkjasdlfkj", 10));
    CHECK_EXPR(RTStrSimplePatternNMatch("*?*?*?*?*", 1, "asdfasdflkjasdlfkj", 128));
    CHECK_EXPR(RTStrSimplePatternNMatch("*?*?*?*?*", 5, "asdfasdflkjasdlfkj", 0));
    CHECK_EXPR(RTStrSimplePatternNMatch("*?*?*?*?*", 5, "asdfasdflkjasdlfkj", ~(size_t)0));
    CHECK_EXPR(RTStrSimplePatternNMatch("*?*?*?*?*", ~(size_t)0, "asdfasdflkjasdlfkj", ~(size_t)0));
    CHECK_EXPR(RTStrSimplePatternNMatch("asdf??df", 8, "asdfasdf", 8));
    CHECK_EXPR(RTStrSimplePatternNMatch("asdf??df", ~(size_t)0, "asdfasdf", 8));
    CHECK_EXPR(RTStrSimplePatternNMatch("asdf??df", ~(size_t)0, "asdfasdf", ~(size_t)0));
    CHECK_EXPR(RTStrSimplePatternNMatch("asdf??df", 7, "asdfasdf", 7));
    CHECK_EXPR(!RTStrSimplePatternNMatch("asdf??df", 7, "asdfasdf", 8));
    CHECK_EXPR(!RTStrSimplePatternNMatch("asdf??dq", 8, "asdfasdf", 8));
    CHECK_EXPR(RTStrSimplePatternNMatch("asdf??dq", 7, "asdfasdf", 7));
    CHECK_EXPR(RTStrSimplePatternNMatch("asdf*df", 8, "asdfasdf", 8));
    CHECK_EXPR(!RTStrSimplePatternNMatch("asdf*dq", 8, "asdfasdf", 8));
    CHECK_EXPR(RTStrSimplePatternNMatch("a*", 10, "asdfasdf", 8));
    CHECK_EXPR(RTStrSimplePatternNMatch("a*f", 3, "asdfasdf", ~(size_t)0));
    CHECK_EXPR(!RTStrSimplePatternNMatch("a*q", 3, "asdfasdf", ~(size_t)0));
    CHECK_EXPR(!RTStrSimplePatternNMatch("a*q?", 4, "asdfasdf", 9));
    CHECK_EXPR(RTStrSimplePatternNMatch("?*df", 4, "asdfasdf", 8));

    size_t offPattern;
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdq|a*f|a??t", ~(size_t)0, "asdf", 4, NULL));
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdq|a*f|a??t", ~(size_t)0, "asdf", 4, &offPattern));
    CHECK_EXPR(offPattern == 5);
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdq|a??t|a??f", ~(size_t)0, "asdf", 4, NULL));
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdq|a??t|a??f", ~(size_t)0, "asdf", 4, &offPattern));
    CHECK_EXPR(offPattern == 10);
    CHECK_EXPR(RTStrSimplePatternMultiMatch("a*f|a??t|a??f", ~(size_t)0, "asdf", 4, NULL));
    CHECK_EXPR(RTStrSimplePatternMultiMatch("a*f|a??t|a??f", ~(size_t)0, "asdf", 4, &offPattern));
    CHECK_EXPR(offPattern == 0);
    CHECK_EXPR(!RTStrSimplePatternMultiMatch("asdq|a??y|a??x", ~(size_t)0, "asdf", 4, NULL));
    CHECK_EXPR(!RTStrSimplePatternMultiMatch("asdq|a??y|a??x", ~(size_t)0, "asdf", 4, &offPattern));
    CHECK_EXPR(offPattern == ~(size_t)0);
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdq|a*f|a??t", 9, "asdf", 4, NULL));
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdq|a*f|a??t", 8, "asdf", 4, NULL));
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdq|a*f|a??t", 7, "asdf", 4, NULL));
    CHECK_EXPR(!RTStrSimplePatternMultiMatch("asdq|a*f|a??t", 6, "asdf", 4, NULL));
    CHECK_EXPR(!RTStrSimplePatternMultiMatch("asdq|a*f|a??t", 5, "asdf", 4, NULL));
    CHECK_EXPR(!RTStrSimplePatternMultiMatch("asdq|a*f|a??t", 4, "asdf", 4, NULL));
    CHECK_EXPR(!RTStrSimplePatternMultiMatch("asdq|a*f|a??t", 3, "asdf", 4, NULL));
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdf", 4, "asdf", 4, NULL));
    CHECK_EXPR(RTStrSimplePatternMultiMatch("asdf|", 5, "asdf", 4, NULL));


    /*
     * Summary.
     */
    if (!cErrors)
        RTPrintf("tstStrToNum: SUCCESS\n");
    else
        RTPrintf("tstStrToNum: FAILURE - %d errors\n", cErrors);
    return !!cErrors;
}
/**
 * Does one free space wipe, using the given filename.
 *
 * @returns RTEXITCODE_SUCCESS on success, RTEXITCODE_FAILURE on failure (fully
 *          bitched).
 * @param   pszFilename     The filename to use for wiping free space.  Will be
 *                          replaced and afterwards deleted.
 * @param   pvFiller        The filler block buffer.
 * @param   cbFiller        The size of the filler block buffer.
 * @param   cbMinLeftOpt    When to stop wiping.
 */
static RTEXITCODE doOneFreeSpaceWipe(const char *pszFilename, void const *pvFiller, size_t cbFiller, uint64_t cbMinLeftOpt)
{
    /*
     * Open the file.
     */
    RTEXITCODE  rcExit = RTEXITCODE_SUCCESS;
    RTFILE      hFile  = NIL_RTFILE;
    int rc = RTFileOpen(&hFile, pszFilename,
                        RTFILE_O_WRITE | RTFILE_O_DENY_NONE | RTFILE_O_CREATE_REPLACE | (0775 << RTFILE_O_CREATE_MODE_SHIFT));
    if (RT_SUCCESS(rc))
    {
        /*
         * Query the amount of available free space.  Figure out which API we should use.
         */
        RTFOFF cbTotal = 0;
        RTFOFF cbFree = 0;
        rc = RTFileQueryFsSizes(hFile, &cbTotal, &cbFree, NULL, NULL);
        bool const fFileHandleApiSupported = rc != VERR_NOT_SUPPORTED && rc != VERR_NOT_IMPLEMENTED;
        if (!fFileHandleApiSupported)
            rc = RTFsQuerySizes(pszFilename, &cbTotal, &cbFree, NULL, NULL);
        if (RT_SUCCESS(rc))
        {
            RTPrintf("%s: %'9RTfoff MiB out of %'9RTfoff are free\n", pszFilename, cbFree / _1M, cbTotal / _1M);

            /*
             * Start filling up the free space, down to the last 32MB.
             */
            uint64_t const  nsStart       = RTTimeNanoTS();     /* for speed calcs */
            uint64_t        nsStat        = nsStart;            /* for speed calcs */
            uint64_t        cbStatWritten = 0;                  /* for speed calcs */
            RTFOFF const    cbMinLeft     = RT_MAX(cbMinLeftOpt, cbFiller * 2);
            RTFOFF          cbLeftToWrite = cbFree - cbMinLeft;
            uint64_t        cbWritten     = 0;
            uint32_t        iLoop         = 0;
            while (cbLeftToWrite >= (RTFOFF)cbFiller)
            {
                rc = RTFileWrite(hFile, pvFiller, cbFiller, NULL);
                if (RT_FAILURE(rc))
                {
                    if (rc == VERR_DISK_FULL)
                        RTPrintf("%s: Disk full after writing %'9RU64 MiB\n", pszFilename, cbWritten / _1M);
                    else
                        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Write error after %'RU64 bytes: %Rrc\n",
                                                pszFilename, cbWritten, rc);
                    break;
                }

                /* Flush every now and then as we approach a completely full disk. */
                if (cbLeftToWrite <= _1G && (iLoop & (cbLeftToWrite  > _128M ? 15 : 3)) == 0)
                    RTFileFlush(hFile);

                /*
                 * Advance and maybe recheck the amount of free space.
                 */
                cbWritten     += cbFiller;
                cbLeftToWrite -= (ssize_t)cbFiller;
                iLoop++;
                if ((iLoop & (16 - 1)) == 0 || cbLeftToWrite < _256M)
                {
                    RTFOFF cbFreeUpdated;
                    if (fFileHandleApiSupported)
                        rc = RTFileQueryFsSizes(hFile, NULL, &cbFreeUpdated, NULL, NULL);
                    else
                        rc = RTFsQuerySizes(pszFilename, NULL, &cbFreeUpdated, NULL, NULL);
                    if (RT_SUCCESS(rc))
                    {
                        cbFree = cbFreeUpdated;
                        cbLeftToWrite = cbFree - cbMinLeft;
                    }
                    else
                    {
                        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Failed to query free space after %'RU64 bytes: %Rrc\n",
                                                pszFilename, cbWritten, rc);
                        break;
                    }
                    if ((iLoop & (512 - 1)) == 0)
                    {
                        uint64_t const nsNow = RTTimeNanoTS();
                        uint64_t cNsInterval = nsNow - nsStat;
                        uint64_t cbInterval  = cbWritten - cbStatWritten;
                        uint64_t cbIntervalPerSec = cbInterval ? (uint64_t)(cbInterval / (cNsInterval / (double)RT_NS_1SEC)) : 0;

                        RTPrintf("%s: %'9RTfoff MiB out of %'9RTfoff are free after writing %'9RU64 MiB (%'5RU64 MiB/s)\n",
                                 pszFilename, cbFree / _1M, cbTotal  / _1M, cbWritten  / _1M, cbIntervalPerSec / _1M);
                        nsStat        = nsNow;
                        cbStatWritten = cbWritten;
                    }
                }
            }

            /*
             * Now flush the file and then reduce the size a little before closing
             * it so the system won't entirely run out of space.  The flush should
             * ensure the data has actually hit the disk.
             */
            rc = RTFileFlush(hFile);
            if (RT_FAILURE(rc))
                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Flush failed at %'RU64 bytes: %Rrc\n", pszFilename, cbWritten, rc);

            uint64_t cbReduced = cbWritten > _512M ? cbWritten - _512M : cbWritten / 2;
            rc = RTFileSetSize(hFile, cbReduced);
            if (RT_FAILURE(rc))
                rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Failed to reduce file size from %'RU64 to %'RU64 bytes: %Rrc\n",
                                        pszFilename, cbWritten, cbReduced, rc);

            /* Issue a summary statements. */
            uint64_t cNsElapsed = RTTimeNanoTS() - nsStart;
            uint64_t cbPerSec   = cbWritten ? (uint64_t)(cbWritten / (cNsElapsed / (double)RT_NS_1SEC)) : 0;
            RTPrintf("%s: Wrote %'RU64 MiB in %'RU64 s, avg %'RU64 MiB/s.\n",
                     pszFilename, cbWritten / _1M, cNsElapsed / RT_NS_1SEC, cbPerSec / _1M);
        }
        else
            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Initial free space query failed: %Rrc \n", pszFilename, rc);

        RTFileClose(hFile);

        /*
         * Delete the file.
         */
        rc = RTFileDelete(pszFilename);
        if (RT_FAILURE(rc))
            rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Delete failed: %Rrc !!\n", pszFilename, rc);
    }
    else
        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "%s: Open failed: %Rrc\n", pszFilename, rc);
    return rcExit;
}
Exemple #5
0
void PrintResult(uint64_t u64Ticks, uint64_t u64MaxTicks, uint64_t u64MinTicks, unsigned cTimes, const char *pszOperation)
{
    RTPrintf("tstPrfRT: %-32s %5lld / %5lld / %5lld ticks per call (%u calls %lld ticks)\n",
             pszOperation, u64MinTicks, u64Ticks / (uint64_t)cTimes, u64MaxTicks, cTimes, u64Ticks);
}
/**
 * Wipes free space on one or more volumes by creating large files.
 */
static RTEXITCODE handlerWipeFreeSpace(int argc, char **argv)
{
    /*
     * Parse arguments.
     */
    const char *apszDefFiles[2] = { "./wipefree.spc", NULL };
    bool        fAll            = false;
    uint32_t    u32Filler       = UINT32_C(0xf6f6f6f6);
    uint64_t    cbMinLeftOpt    = _32M;

    static RTGETOPTDEF const s_aOptions[] =
    {
        { "--all",      'a', RTGETOPT_REQ_NOTHING },
        { "--filler",   'f', RTGETOPT_REQ_UINT32 },
        { "--min-free", 'm', RTGETOPT_REQ_UINT64 },
    };
    RTGETOPTSTATE State;
    RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    RTGETOPTUNION ValueUnion;
    int chOpt;
    while (  (chOpt = RTGetOpt(&State, &ValueUnion)) != 0
           && chOpt != VINF_GETOPT_NOT_OPTION)
    {
        switch (chOpt)
        {
            case 'a':
                fAll = true;
                break;
            case 'f':
                u32Filler = ValueUnion.u32;
                break;
            case 'm':
                cbMinLeftOpt = ValueUnion.u64;
                break;
            case 'h':
                RTPrintf("usage: wipefrespace [options] [filename1 [..]]\n"
                         "\n"
                         "Options:\n"
                         "  -a, --all\n"
                         "    Try do the free space wiping on all seemingly relevant file systems.\n"
                         "    Changes the meaning of the filenames  "
                         "    This is not yet implemented\n"
                         "  -p, --filler <32-bit value>\n"
                         "    What to fill the blocks we write with.\n"
                         "    Default: 0xf6f6f6f6\n"
                         "  -m, --min-free <64-bit byte count>\n"
                         "    Specifies when to stop in terms of free disk space (in bytes).\n"
                         "    Default: 32MB\n"
                         "\n"
                         "Zero or more names of files to do the free space wiping thru can be given.\n"
                         "When --all is NOT used, each of the files are used to do free space wiping on\n"
                         "the volume they will live on.  However, when --all is in effect the files are\n"
                         "appended to the volume mountpoints and only the first that can be created will\n"
                         "be used.  Files (used ones) will be removed when done.\n"
                         "\n"
                         "If no filename is given, the default is: %s\n"
                         , apszDefFiles[0]);
                return RTEXITCODE_SUCCESS;

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

    char **papszFiles;
    if (chOpt == 0)
        papszFiles = (char **)apszDefFiles;
    else
        papszFiles = RTGetOptNonOptionArrayPtr(&State);

    /*
     * Allocate and prep a memory which we'll write over and over again.
     */
    uint32_t  cbFiller   = _2M;
    uint32_t *pu32Filler = (uint32_t *)RTMemPageAlloc(cbFiller);
    while (!pu32Filler)
    {
        cbFiller <<= 1;
        if (cbFiller >= _4K)
            pu32Filler = (uint32_t *)RTMemPageAlloc(cbFiller);
        else
            return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTMemPageAlloc failed for sizes between 4KB and 2MB!\n");
    }
    for (uint32_t i = 0; i < cbFiller / sizeof(pu32Filler[0]); i++)
        pu32Filler[i] = u32Filler;

    /*
     * Do the requested work.
     */
    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    if (!fAll)
    {
        for (uint32_t iFile = 0; papszFiles[iFile] != NULL; iFile++)
        {
            RTEXITCODE rcExit2 = doOneFreeSpaceWipe(papszFiles[iFile], pu32Filler, cbFiller, cbMinLeftOpt);
            if (rcExit2 != RTEXITCODE_SUCCESS && rcExit == RTEXITCODE_SUCCESS)
                rcExit = rcExit2;
        }
    }
    else
    {
        /*
         * Reject --all for now.
         */
        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE,  "The --all option is not yet implemented!\n");
    }

    RTMemPageFree(pu32Filler, cbFiller);
    return rcExit;
}
/** Print the 'true' if VT-x or AMD-v is supported, 'false' it not. */
static RTEXITCODE handlerCpuHwVirt(int argc, char **argv)
{
    NOREF(argc); NOREF(argv);
    int cch = RTPrintf(isHwVirtSupported() != HWVIRTTYPE_NONE ? "true\n" : "false\n");
    return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}
Exemple #8
0
int main(int argc, char **argv)
{
    RTR3InitExe(argc, &argv, 0);

    /*
     * Parse args
     */
    static const RTGETOPTDEF g_aOptions[] =
    {
        { "--iterations",       'i', RTGETOPT_REQ_INT32 },
        { "--hex",              'h', RTGETOPT_REQ_NOTHING },
        { "--decimal",          'd', RTGETOPT_REQ_NOTHING },
        { "--spin",             's', RTGETOPT_REQ_NOTHING }
    };

    uint32_t cIterations = 40;
    bool fHex = true;
    bool fSpin = false;
    int ch;
    RTGETOPTUNION ValueUnion;
    RTGETOPTSTATE GetState;
    RTGetOptInit(&GetState, argc, argv, g_aOptions, RT_ELEMENTS(g_aOptions), 1, RTGETOPTINIT_FLAGS_NO_STD_OPTS);
    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
    {
        switch (ch)
        {
            case 'i':
                cIterations = ValueUnion.u32;
                break;

            case 'd':
                fHex = false;
                break;

            case 'h':
                fHex = true;
                break;

            case 's':
                fSpin = true;
                break;

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

    /*
     * Init
     */
    PSUPDRVSESSION pSession = NIL_RTR0PTR;
    int rc = SUPR3Init(&pSession);
    if (RT_SUCCESS(rc))
    {
        if (g_pSUPGlobalInfoPage)
        {
            RTPrintf("tstGIP-2: cCpus=%d  u32UpdateHz=%RU32  u32UpdateIntervalNS=%RU32  u64NanoTSLastUpdateHz=%RX64  u32Mode=%d (%s) u32Version=%#x\n",
                     g_pSUPGlobalInfoPage->cCpus,
                     g_pSUPGlobalInfoPage->u32UpdateHz,
                     g_pSUPGlobalInfoPage->u32UpdateIntervalNS,
                     g_pSUPGlobalInfoPage->u64NanoTSLastUpdateHz,
                     g_pSUPGlobalInfoPage->u32Mode,
                     g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_SYNC_TSC       ? "sync"
                     : g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_ASYNC_TSC    ? "async"
                     :                                                            "???",
                     g_pSUPGlobalInfoPage->u32Version);
            RTPrintf(fHex
                     ? "tstGIP-2:     it: u64NanoTS        delta     u64TSC           UpIntTSC H  TransId           CpuHz TSC Interval History...\n"
                     : "tstGIP-2:     it: u64NanoTS        delta     u64TSC             UpIntTSC H    TransId           CpuHz TSC Interval History...\n");
            static SUPGIPCPU s_aaCPUs[2][256];
            for (uint32_t i = 0; i < cIterations; i++)
            {
                /* copy the data */
                memcpy(&s_aaCPUs[i & 1][0], &g_pSUPGlobalInfoPage->aCPUs[0], g_pSUPGlobalInfoPage->cCpus * sizeof(g_pSUPGlobalInfoPage->aCPUs[0]));

                /* display it & find something to spin on. */
                uint32_t u32TransactionId = 0;
                uint32_t volatile *pu32TransactionId = NULL;
                for (unsigned iCpu = 0; iCpu < g_pSUPGlobalInfoPage->cCpus; iCpu++)
                    if (    g_pSUPGlobalInfoPage->aCPUs[iCpu].u64CpuHz > 0
                        &&  g_pSUPGlobalInfoPage->aCPUs[iCpu].u64CpuHz != _4G + 1)
                    {
                        PSUPGIPCPU pPrevCpu = &s_aaCPUs[!(i & 1)][iCpu];
                        PSUPGIPCPU pCpu = &s_aaCPUs[i & 1][iCpu];
                        RTPrintf(fHex
                                 ? "tstGIP-2: %4d/%d: %016llx %09llx %016llx %08x %d %08x %15llu %08x %08x %08x %08x %08x %08x %08x %08x (%d)\n"
                                 : "tstGIP-2: %4d/%d: %016llu %09llu %016llu %010u %d %010u %15llu %08x %08x %08x %08x %08x %08x %08x %08x (%d)\n",
                                 i, iCpu,
                                 pCpu->u64NanoTS,
                                 i ? pCpu->u64NanoTS - pPrevCpu->u64NanoTS : 0,
                                 pCpu->u64TSC,
                                 pCpu->u32UpdateIntervalTSC,
                                 pCpu->iTSCHistoryHead,
                                 pCpu->u32TransactionId,
                                 pCpu->u64CpuHz,
                                 pCpu->au32TSCHistory[0],
                                 pCpu->au32TSCHistory[1],
                                 pCpu->au32TSCHistory[2],
                                 pCpu->au32TSCHistory[3],
                                 pCpu->au32TSCHistory[4],
                                 pCpu->au32TSCHistory[5],
                                 pCpu->au32TSCHistory[6],
                                 pCpu->au32TSCHistory[7],
                                 pCpu->cErrors);
                        if (!pu32TransactionId)
                        {
                            pu32TransactionId = &g_pSUPGlobalInfoPage->aCPUs[iCpu].u32TransactionId;
                            u32TransactionId = pCpu->u32TransactionId;
                        }
                    }

                /* wait a bit / spin */
                if (!fSpin)
                    RTThreadSleep(9);
                else
                    while (u32TransactionId == *pu32TransactionId)
                        /* nop */;
            }
        }
        else
        {
            RTPrintf("tstGIP-2: g_pSUPGlobalInfoPage is NULL\n");
            rc = -1;
        }

        SUPR3Term(false /*fForced*/);
    }
    else
        RTPrintf("tstGIP-2: SUPR3Init failed: %Rrc\n", rc);
    return !!rc;
}
static RTEXITCODE RTCmdRmDir(unsigned cArgs,  char **papszArgs)
{
    /*
     * Parse the command line.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        /* operations */
        { "--parents",                  'p', RTGETOPT_REQ_NOTHING },
        { "--ignore-fail-on-non-empty", 'F', RTGETOPT_REQ_NOTHING },
        { "--ignore-non-existing",      'E', RTGETOPT_REQ_NOTHING },
        { "--always-use-vfs-chain-api", 'A', RTGETOPT_REQ_NOTHING },
        { "--verbose",                  'v', RTGETOPT_REQ_NOTHING },
    };

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

    RTCMDRMDIROPTS Opts;
    Opts.fVerbose               = false;
    Opts.fParents               = false;
    Opts.fIgnoreNotEmpty        = false;
    Opts.fIgnoreNonExisting     = false;
    Opts.fAlwaysUseChainApi     = false;

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

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

            case 'A':
                Opts.fAlwaysUseChainApi = true;
                break;

            case 'E':
                Opts.fIgnoreNonExisting = true;
                break;

            case 'F':
                Opts.fIgnoreNotEmpty = true;
                break;

            case 'h':
                RTPrintf("Usage: %s [options] <dir> [..]\n"
                         "\n"
                         "Removes empty directories.\n"
                         "\n"
                         "Options:\n"
                         "  -p, --parent\n"
                         "      Remove specified parent directories too.\n"
                         "  -F, --ignore-fail-on-non-empty\n"
                         "      Do not fail if a directory is not empty, just ignore it.\n"
                         "      This is really handy with the -p option.\n"
                         "  -E, --ignore-non-existing\n"
                         "      Do not fail if a specified directory is not there.\n"
                         "  -v, --verbose\n"
                         "      Tell which directories get remove.\n"
                         "  -A, --always-use-vfs-chain-api\n"
                         "      Always use the VFS API.\n"
                         , papszArgs[0]);
                return RTEXITCODE_SUCCESS;

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

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


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

    /*
     * Work thru the specified dirs.
     */
    RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
    while (rc == VINF_GETOPT_NOT_OPTION)
    {
        if (Opts.fParents)
            rc = rtCmdRmDirOneWithParents(&Opts, ValueUnion.psz);
        else
            rc = rtCmdRmDirOne(&Opts, ValueUnion.psz);
        if (RT_FAILURE(rc))
            rcExit = RTEXITCODE_FAILURE;

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

    return rcExit;
}
int VbglR3SeamlessSetCap(bool bState)
{
    RTPrintf("%s\n", bState ? "Seamless capability set"
                            : "Seamless capability unset");
    return true;
}
int VbglR3CtlFilterMask(uint32_t u32OrMask, uint32_t u32NotMask)
{
    RTPrintf("IRQ filter mask changed.  Or mask: 0x%x.  Not mask: 0x%x\n",
             u32OrMask, u32NotMask);
    return true;
}
Exemple #12
0
int main(int argc, char* argv[])
{
    int rcErrors = 0;

    /*
     * Initialize the runtime.
     */
    RTR3InitAndSUPLib();

#ifndef AUTO_TEST_ARGS
    if (argc < 2)
    {
        RTPrintf("syntax: %s command [args]\n"
                    "\n"
                    "command    Command to run under child process in fork.\n"
                    "[args]     Arguments to command.\n", argv[0]);
        return 1;
    }
#endif

    /*
     * Create empty VM.
     */
    RTPrintf(TESTCASE ": Initializing...\n");
    PVM pVM;
    int rc = VMR3Create(1, NULL, NULL, NULL, NULL, NULL, &pVM);
    if (RT_SUCCESS(rc))
    {
        /*
         * Do testing.
         */
        int iCowTester = 0;
        char cCowTester = 'a';

#ifndef AUTO_TEST_ARGS
        int cArgs = argc - 1;
        char **ppszArgs = &argv[1];
#else
        int cArgs = 2;
        char *ppszArgs[3];
        ppszArgs[0] = (char *)"/bin/sleep";
        ppszArgs[1] = (char *)"3";
        ppszArgs[2] = NULL;
#endif

        RTPrintf(TESTCASE ": forking current process...\n");
        pid_t pid = fork();
        if (pid < 0)
        {
            /* Bad. fork() failed! */
            RTPrintf(TESTCASE ": error: fork() failed.\n");
            rcErrors++;
        }
        else if (pid == 0)
        {
            /*
             * The child process.
             * Write to some local variables to trigger copy-on-write if it's used.
             */
            RTPrintf(TESTCASE ": running child process...\n");
            RTPrintf(TESTCASE ": writing local variables...\n");
            iCowTester = 2;
            cCowTester = 'z';

            RTPrintf(TESTCASE ": calling execv() with command-line:\n");
            for (int i = 0; i < cArgs; i++)
                RTPrintf(TESTCASE ": ppszArgs[%d]=%s\n", i, ppszArgs[i]);
            execv(ppszArgs[0], ppszArgs);
            RTPrintf(TESTCASE ": error: execv() returned to caller. errno=%d.\n", errno);
            _exit(-1);
        }
        else
        {
            /*
             * The parent process.
             * Wait for child & run VMM test to ensure things are fine.
             */
            int result;
            while (waitpid(pid, &result, 0) < 0)
                ;
            if (!WIFEXITED(result) || WEXITSTATUS(result) != 0)
            {
                RTPrintf(TESTCASE ": error: failed to run child process. errno=%d\n", errno);
                rcErrors++;
            }

            if (rcErrors == 0)
            {
                RTPrintf(TESTCASE ": fork() returned fine.\n");
                RTPrintf(TESTCASE ": testing VM after fork.\n");
                VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM);

                STAMR3Dump(pVM, "*");
            }
        }

        if (rcErrors > 0)
            RTPrintf(TESTCASE ": error: %d error(s) during fork(). Cannot proceed to test the VM.\n");
        else
            RTPrintf(TESTCASE ": fork() and VM test, SUCCESS.\n");

        /*
         * Cleanup.
         */
        rc = VMR3Destroy(pVM);
        if (!RT_SUCCESS(rc))
        {
            RTPrintf(TESTCASE ": error: failed to destroy vm! rc=%d\n", rc);
            rcErrors++;
        }
    }
    else
    {
        RTPrintf(TESTCASE ": fatal error: failed to create vm! rc=%d\n", rc);
        rcErrors++;
    }

    return rcErrors;
}
int main()
{
    RTR3InitExeNoArguments(0);

    /*
     * Just a simple testcase.
     */
    RTPrintf("tstOnce: TESTING - smoke...\n");
    RTONCE Once1 = RTONCE_INITIALIZER;
    g_fOnceCB1 = false;
    int rc = RTOnce(&Once1, Once1CB, (void *)1);
    if (rc != VINF_SUCCESS)
        RTPrintf("tstOnce: ERROR - Once1, 1 failed, rc=%Rrc\n", rc);
    g_fOnceCB1 = false;
    rc = RTOnce(&Once1, Once1CB, (void *)1);
    if (rc != VINF_SUCCESS)
        RTPrintf("tstOnce: ERROR - Once1, 2 failed, rc=%Rrc\n", rc);

    /*
     * Throw a bunch of threads up against a init once thing.
     */
    RTPrintf("tstOnce: TESTING - bunch of threads...\n");
    /* create the semaphore they'll be waiting on. */
    rc = RTSemEventMultiCreate(&g_hEventMulti);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiCreate returned %Rrc\n", rc);
        return 1;
    }

    /* create the threads */
    RTTHREAD aThreads[32];
    for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++)
    {
        char szName[16];
        RTStrPrintf(szName, sizeof(szName), "ONCE2-%d\n", i);
        rc = RTThreadCreate(&aThreads[i], Once2Thread, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, szName);
        if (RT_FAILURE(rc))
        {
            RTPrintf("tstOnce: ERROR - failed to create thread #%d\n", i);
            g_cErrors++;
        }
    }

    /* kick them off and yield */
    rc = RTSemEventMultiSignal(g_hEventMulti);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstOnce: FATAL ERROR - RTSemEventMultiSignal returned %Rrc\n", rc);
        return 1;
    }
    RTThreadYield();

    /* wait for all of them to finish up, 30 seconds each. */
    for (unsigned i = 0; i < RT_ELEMENTS(aThreads); i++)
        if (aThreads[i] != NIL_RTTHREAD)
        {
            int rc2;
            rc = RTThreadWait(aThreads[i], 30*1000, &rc2);
            if (RT_FAILURE(rc))
            {
                RTPrintf("tstOnce: ERROR - RTThreadWait on thread #%u returned %Rrc\n", i, rc);
                g_cErrors++;
            }
            else if (RT_FAILURE(rc2))
            {
                RTPrintf("tstOnce: ERROR - Thread #%u returned %Rrc\n", i, rc2);
                g_cErrors++;
            }
        }

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

    return !!g_cErrors;
}
int main()
{
    unsigned cErrors = 0;
    RTR3InitExeNoArguments(0);

    /*
     * Basic property setting and simple matching.
     */
    USBFILTER Flt1;
    USBFilterInit(&Flt1, USBFILTERTYPE_CAPTURE);
    /* numbers */
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_VENDOR_ID, 0x1111, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_PRODUCT_ID, 0x2222, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_DEVICE, 0, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_DEVICE_CLASS, 0, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_DEVICE_SUB_CLASS, 0, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_DEVICE_PROTOCOL, 0xff, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_BUS, 1, true));
    TST_CHECK_RC(USBFilterSetIgnore(&Flt1, USBFILTERIDX_BUS));
    TST_CHECK_RC(USBFilterSetPresentOnly(&Flt1, USBFILTERIDX_BUS));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_BUS, 1, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_BUS, 1, false));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_PORT, 1, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_PORT, 1, false));
    TST_CHECK_RC(USBFilterSetIgnore(&Flt1, USBFILTERIDX_PORT));
    /* strings */
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR, "foobar", true, false ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR, "foobar", true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString128, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString128, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString128, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString128, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString128, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_PRODUCT_STR,       "barbar", true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_PRODUCT_STR,       g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_PRODUCT_STR,       g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_SERIAL_NUMBER_STR, g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_SERIAL_NUMBER_STR, g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_SERIAL_NUMBER_STR, g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_SERIAL_NUMBER_STR, g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_SERIAL_NUMBER_STR, g_szString64, true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_MANUFACTURER_STR,  "vendor", true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_PRODUCT_STR,       "product", true, false  ));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_SERIAL_NUMBER_STR, "serial", true, false  ));

    /* cloning */
    USBFILTER Dev;
    USBFilterClone(&Dev, &Flt1);

    TST_CHECK_EXPR(USBFilterIsIdentical(&Dev, &Flt1));
    TST_CHECK_EXPR(USBFilterMatch(&Dev, &Flt1));

    USBFilterDelete(&Flt1);
    USBFilterDelete(&Dev);

    /* make a sample device */
    USBFilterInit(&Dev, USBFILTERTYPE_CAPTURE);
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_VENDOR_ID,         0x1111, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_PRODUCT_ID,        0x2222, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_DEVICE,            0, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_DEVICE_CLASS,      0, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_DEVICE_SUB_CLASS,  0, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_DEVICE_PROTOCOL,   0xff, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_BUS,               1, true));
    TST_CHECK_RC(USBFilterSetNumExact(&Dev,     USBFILTERIDX_PORT,              2, true));
    TST_CHECK_RC(USBFilterSetStringExact(&Dev,  USBFILTERIDX_MANUFACTURER_STR,  "vendor", true, false ));
    TST_CHECK_RC(USBFilterSetStringExact(&Dev,  USBFILTERIDX_PRODUCT_STR,       "product", true, false ));
    TST_CHECK_RC(USBFilterSetStringExact(&Dev,  USBFILTERIDX_SERIAL_NUMBER_STR, "serial", true, false ));

    /* do some basic matching tests */
    USBFilterInit(&Flt1, USBFILTERTYPE_CAPTURE);
    TST_CHECK_EXPR(!USBFilterHasAnySubstatialCriteria(&Flt1));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev) /* 100% ignore filter */);

    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_PORT, 3, true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_PORT, 2, true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_BUS, 2, true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExact(&Flt1, USBFILTERIDX_BUS, 1, true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_PRODUCT_STR, "no match", true, false ));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringExact(&Flt1, USBFILTERIDX_PRODUCT_STR, "product", true, false ));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    /* string patterns */
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "p*", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "*product", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "product*", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "pro*t", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "pro*uct", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "pro*uct", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "pro*duct", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "pro*x", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "*product*", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "*oduct*", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "*produc*", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "?r??u*?t", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "?r??u*?*?*?***??t", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "?r??u*?*?*?***??", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "p*d*t", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetStringPattern(&Flt1, USBFILTERIDX_PRODUCT_STR, "p*x*t", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetIgnore(&Flt1, USBFILTERIDX_PRODUCT_STR));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    /* numeric patterns */
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x1111", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0X1111", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "4369", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "010421", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x1111-0x1111", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "4369-4369", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "010421-010421", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x1110-0x1112", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "4360-4370", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "010420-010422", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x1112-0x1110", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x0-0x1f", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0-19", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0-017", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x0-0xffff", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0-65535", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0-177777", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x0-0XABCD", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x0EF-0XABCD", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0X0ef-0Xabcd", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "42|1|0x1111", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "42|0x1111|1", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x1111|42|1", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x1112|42|1", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));

    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "39-59|0x256-0x101f|0xfffff-0xf000|0x1000-0x2000", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "0x000256-0x0101f|0xf000-0xfffff|0x000008000-0x2000|39-59", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "| | \t \t\t| 0x256 - 0x101f   | 0xf000 - 0xfeff\t| 0x1000 -\t0x6000 | 1- 0512", true));
    TST_CHECK_EXPR(USBFilterMatch(&Flt1, &Dev));
    TST_CHECK_RC(USBFilterSetNumExpression(&Flt1, USBFILTERIDX_VENDOR_ID, "| | \t \t\t| 0x256 - 0x101f   | 0xf000 - 0xfeff\t| 0x1112 -\t0x6000 | 1- 0512", true));
    TST_CHECK_EXPR(!USBFilterMatch(&Flt1, &Dev));


    USBFilterDelete(&Flt1);

    /*
     * string overflow
     */
    struct
    {
        uint64_t  u64Pre;
        USBFILTER Flt;
        uint64_t  u64Post;
    } sOf;
    sOf.u64Pre = sOf.u64Post = UINT64_C(0x1234567887654321);

    USBFilterInit(&sOf.Flt, USBFILTERTYPE_CAPTURE);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));

    AssertCompileMemberSize(USBFILTER, achStrTab, 256);
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_SERIAL_NUMBER_STR,   &g_szString256[0],  true, false  ) == VERR_BUFFER_OVERFLOW);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_SERIAL_NUMBER_STR,   &g_szString256[1],  true, false  ) == VERR_BUFFER_OVERFLOW);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_SERIAL_NUMBER_STR,   &g_szString256[2],  true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_SERIAL_NUMBER_STR,   &g_szString256[3],  true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    /* 0 + 1 */
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_SERIAL_NUMBER_STR,   "",                 true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_PRODUCT_STR,         &g_szString256[2],  true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_PRODUCT_STR,         &g_szString256[1],  true, false  ) == VERR_BUFFER_OVERFLOW);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    /* 0 + 2 */
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_PRODUCT_STR,         &g_szString128[2],  true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_SERIAL_NUMBER_STR,   &g_szString128[1],  true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    /* 3 */
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_SERIAL_NUMBER_STR,   &g_szString64[0],   true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_PRODUCT_STR,         &g_szString64[0],   true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_MANUFACTURER_STR,    &g_szString128[4],  true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_MANUFACTURER_STR,    &g_szString128[4],  true, false  ) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetStringExact(&sOf.Flt, USBFILTERIDX_MANUFACTURER_STR,    &g_szString128[3],  true, false  ) == VERR_BUFFER_OVERFLOW);
    TST_CHECK_EXPR(sOf.u64Pre == UINT64_C(0x1234567887654321)); TST_CHECK_EXPR(sOf.u64Post == UINT64_C(0x1234567887654321));

    /*
     * Check for a string replacement bug.
     */
    USBFILTER Dev2;
    USBFilterInit(&Dev2, USBFILTERTYPE_CAPTURE);
    TST_CHECK_EXPR(USBFilterSetNumExact(&Dev2,      USBFILTERIDX_VENDOR_ID,         0x19b6, true) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetNumExact(&Dev2,      USBFILTERIDX_PRODUCT_ID,        0x1024, true) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetNumExact(&Dev2,      USBFILTERIDX_DEVICE_REV,        0x0141, true) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetNumExact(&Dev2,      USBFILTERIDX_DEVICE_CLASS,      0,      true) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetNumExact(&Dev2,      USBFILTERIDX_DEVICE_SUB_CLASS,  0,      true) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetNumExact(&Dev2,      USBFILTERIDX_DEVICE_PROTOCOL,   0,      true) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetNumExact(&Dev2,      USBFILTERIDX_PORT,              0x1,    true) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetStringExact(&Dev2,   USBFILTERIDX_MANUFACTURER_STR, "Generic", true, false ) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetStringExact(&Dev2,   USBFILTERIDX_PRODUCT_STR, "Mass Storage Device", true, false ) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterSetStringExact(&Dev2,   USBFILTERIDX_MANUFACTURER_STR, "YBU1PPRS", true, false ) == VINF_SUCCESS);
    TST_CHECK_EXPR(USBFilterGetNum(&Dev2, USBFILTERIDX_VENDOR_ID) == 0x19b6);
    TST_CHECK_EXPR(USBFilterGetNum(&Dev2, USBFILTERIDX_PRODUCT_ID) == 0x1024);
    TST_CHECK_EXPR(USBFilterGetNum(&Dev2, USBFILTERIDX_DEVICE_REV) == 0x0141);
    TST_CHECK_EXPR(USBFilterGetNum(&Dev2, USBFILTERIDX_DEVICE_CLASS) == 0);
    TST_CHECK_EXPR(USBFilterGetNum(&Dev2, USBFILTERIDX_DEVICE_SUB_CLASS) == 0);
    TST_CHECK_EXPR(USBFilterGetNum(&Dev2, USBFILTERIDX_DEVICE_PROTOCOL) == 0);
    TST_CHECK_EXPR(USBFilterGetNum(&Dev2, USBFILTERIDX_PORT) == 1);


    /*
     * Summary.
     */
    if (!cErrors)
        RTPrintf(TESTCASE ": SUCCESS\n");
    else
        RTPrintf(TESTCASE ": FAILURE - %d errors\n", cErrors);
    return !!cErrors;
}
Exemple #15
0
/**
 * Handle the 'create' action.
 *
 * @returns 0 or 1.
 * @param   argc    The action argument count.
 * @param   argv    The action argument vector.
 */
static int supSvcWinCreate(int argc, char **argv)
{
    /*
     * Parse the arguments.
     */
    bool fVerbose = false;
    static const RTOPTIONDEF s_aOptions[] =
    {
        { "--verbose", 'v', RTGETOPT_REQ_NOTHING }
    };
    int iArg = 0;
    int ch;
    RTGETOPTUNION Value;
    while ((ch = RTGetOpt(argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), &iArg, &Value)))
        switch (ch)
        {
            case 'v':   fVerbose = true;  break;
            default:    return supSvcDisplayGetOptError("create", ch, argc, argv, iArg, &Value);
        }
    if (iArg != argc)
        return supSvcDisplayTooManyArgsError("create", argc, argv, iArg);

    /*
     * Create the service.
     */
    int rc = 1;
    SC_HANDLE hSCM = supSvcWinOpenSCManager("create", SC_MANAGER_CREATE_SERVICE); /*SC_MANAGER_ALL_ACCESS*/
    if (hSCM)
    {
        char szExecPath[MAX_PATH];
        if (GetModuleFileName(NULL /* the executable */, szExecPath, sizeof(szExecPath)))
        {
            if (fVerbose)
                RTPrintf("Creating the %s service, binary \"%s\"...\n",
                         SUPSVC_SERVICE_NAME, szExecPath); /* yea, the binary name isn't UTF-8, but wtf. */

            SC_HANDLE hSvc = CreateService(hSCM,                            /* hSCManager */
                                           SUPSVC_SERVICE_NAME,             /* lpServiceName */
                                           SUPSVC_SERVICE_DISPLAY_NAME,     /* lpDisplayName */
                                           SERVICE_CHANGE_CONFIG | SERVICE_QUERY_STATUS | SERVICE_QUERY_CONFIG, /* dwDesiredAccess */
                                           SERVICE_WIN32_OWN_PROCESS,       /* dwServiceType ( | SERVICE_INTERACTIVE_PROCESS? ) */
                                           SERVICE_DEMAND_START/*_AUTO*/,   /* dwStartType */
                                           SERVICE_ERROR_NORMAL,            /* dwErrorControl */
                                           szExecPath,                      /* lpBinaryPathName */
                                           NULL,                            /* lpLoadOrderGroup */
                                           NULL,                            /* lpdwTagId */
                                           NULL,                            /* lpDependencies */
                                           NULL,                            /* lpServiceStartName (=> LocalSystem) */
                                           NULL);                           /* lpPassword */
            if (hSvc)
            {
                RTPrintf("Successfully created the %s service.\n", SUPSVC_SERVICE_NAME);
                /** @todo Set the service description or it'll look weird in the vista service manager.
                 *  Anything else that should be configured? Start access or something? */
                rc = 0;
                CloseServiceHandle(hSvc);
            }
            else
            {
                DWORD err = GetLastError();
                switch (err)
                {
                    case ERROR_SERVICE_EXISTS:
                        supSvcDisplayError("create - The service already exists.\n");
                        break;
                    default:
                        supSvcDisplayError("create - CreateService failed, err=%d.\n", GetLastError());
                        break;
                }
            }
            CloseServiceHandle(hSvc);
        }
        else
            supSvcDisplayError("create - Failed to obtain the executable path: %d\n", GetLastError());
    }
    return rc;
}
/**
 * Create one directory and any missing parent directories.
 *
 * @returns exit code
 * @param   pOpts               The mkdir option.
 * @param   pszDir              The path to the new directory.
 */
static int rtCmdRmDirOneWithParents(RTCMDRMDIROPTS const *pOpts, const char *pszDir)
{
    /* We need a copy we can work with here. */
    char *pszCopy = RTStrDup(pszDir);
    if (!pszCopy)
        return RTMsgErrorExitFailure("Out of string memory!");

    int rc;
    if (!pOpts->fAlwaysUseChainApi && !RTVfsChainIsSpec(pszDir) )
    {
        size_t cchCopy = strlen(pszCopy);
        do
        {
            rc = RTDirRemove(pszCopy);
            if (RT_SUCCESS(rc))
            {
                if (pOpts->fVerbose)
                    RTPrintf("%s\n", pszCopy);
            }
            else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting)
                rc = VINF_SUCCESS;
            else
            {
                if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty)
                    rc = VINF_SUCCESS;
                else
                    RTMsgError("Failed to remove directory '%s': %Rrc", pszCopy, rc);
                break;
            }

            /* Strip off a component. */
            while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
                cchCopy--;
            while (cchCopy > 0 && !RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
                cchCopy--;
            while (cchCopy > 0 && RTPATH_IS_SLASH(pszCopy[cchCopy - 1]))
                cchCopy--;
            pszCopy[cchCopy] = '\0';
        } while (cchCopy > 0);
    }
    else
    {
        /*
         * Strip the final path element from the pszDir spec.
         */
        char       *pszFinalPath;
        char       *pszSpec;
        uint32_t    offError;
        rc = RTVfsChainSplitOffFinalPath(pszCopy, &pszSpec, &pszFinalPath, &offError);
        if (RT_SUCCESS(rc))
        {
            /*
             * Open the root director/whatever.
             */
            RTERRINFOSTATIC ErrInfo;
            RTVFSDIR hVfsBaseDir;
            if (pszSpec)
            {
                rc = RTVfsChainOpenDir(pszSpec, 0 /*fOpen*/, &hVfsBaseDir, &offError, RTErrInfoInitStatic(&ErrInfo));
                if (RT_FAILURE(rc))
                    RTVfsChainMsgError("RTVfsChainOpenDir", pszSpec, rc, offError, &ErrInfo.Core);
                else if (!pszFinalPath)
                    pszFinalPath = RTStrEnd(pszSpec, RTSTR_MAX);
            }
            else if (!RTPathStartsWithRoot(pszFinalPath))
            {
                rc = RTVfsDirOpenNormal(".", 0 /*fOpen*/, &hVfsBaseDir);
                if (RT_FAILURE(rc))
                    RTMsgError("Failed to open '.' (for %s): %Rrc", rc, pszFinalPath);
            }
            else
            {
                char *pszRoot = pszFinalPath;
                pszFinalPath = RTPathSkipRootSpec(pszFinalPath);
                char const chSaved = *pszFinalPath;
                *pszFinalPath = '\0';
                rc = RTVfsDirOpenNormal(pszRoot, 0 /*fOpen*/, &hVfsBaseDir);
                *pszFinalPath = chSaved;
                if (RT_FAILURE(rc))
                    RTMsgError("Failed to open root dir for '%s': %Rrc", rc, pszRoot);
            }

            /*
             * Walk the path component by component, starting at the end.
             */
            if (RT_SUCCESS(rc))
            {
                size_t cchFinalPath = strlen(pszFinalPath);
                while (RT_SUCCESS(rc) && cchFinalPath > 0)
                {
                    rc = RTVfsDirRemoveDir(hVfsBaseDir, pszFinalPath, 0 /*fFlags*/);
                    if (RT_SUCCESS(rc))
                    {
                        if (pOpts->fVerbose)
                            RTPrintf("%s\n", pszCopy);
                    }
                    else if ((rc == VERR_PATH_NOT_FOUND || rc == VERR_FILE_NOT_FOUND) && pOpts->fIgnoreNonExisting)
                        rc = VINF_SUCCESS;
                    else
                    {
                        if ((rc == VERR_DIR_NOT_EMPTY || rc == VERR_SHARING_VIOLATION) && pOpts->fIgnoreNotEmpty)
                            rc = VINF_SUCCESS;
                        else if (pszSpec)
                            RTMsgError("Failed to remove directory '%s:%s': %Rrc", pszSpec, pszFinalPath, rc);
                        else
                            RTMsgError("Failed to remove directory '%s': %Rrc", pszFinalPath, rc);
                        break;
                    }

                    /* Strip off a component. */
                    while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
                        cchFinalPath--;
                    while (cchFinalPath > 0 && !RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
                        cchFinalPath--;
                    while (cchFinalPath > 0 && RTPATH_IS_SLASH(pszFinalPath[cchFinalPath - 1]))
                        cchFinalPath--;
                    pszFinalPath[cchFinalPath] = '\0';
                }

                RTVfsDirRelease(hVfsBaseDir);
            }
        }
        else
            RTVfsChainMsgError("RTVfsChainOpenParentDir", pszCopy, rc, offError, NULL);
    }
    RTStrFree(pszCopy);
    return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}
/**
 * The main loop for the VBoxClient daemon.
 * @todo Clean up for readability.
 */
int main(int argc, char *argv[])
{
    bool fDaemonise = true, fRespawn = true;
    int rc;
    const char *pcszFileName, *pcszStage;

    /* Initialise our runtime before all else. */
    rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);
    /* This should never be called twice in one process - in fact one Display
     * object should probably never be used from multiple threads anyway. */
    if (!XInitThreads())
        VBClFatalError(("Failed to initialize X11 threads\n"));
    /* Get our file name for error output. */
    pcszFileName = RTPathFilename(argv[0]);
    if (!pcszFileName)
        pcszFileName = "VBoxClient";

    /* Parse our option(s) */
    /** @todo Use RTGetOpt() if the arguments become more complex. */
    for (int i = 1; i < argc; ++i)
    {
        rc = VERR_INVALID_PARAMETER;
        if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--nodaemon"))
        {
            /* If the user is running in "no daemon" mode anyway, send critical
             * logging to stdout as well. */
            PRTLOGGER pReleaseLog = RTLogRelDefaultInstance();

            if (pReleaseLog)
                rc = RTLogDestinations(pReleaseLog, "stdout");
            if (pReleaseLog && RT_FAILURE(rc))
                RTPrintf("%s: failed to redivert error output, rc=%Rrc\n",
                         pcszFileName, rc);
            fDaemonise = false;
        }
        else if (!strcmp(argv[i], "--no-respawn"))
        {
            fRespawn = false;
        }
        else if (!strcmp(argv[i], "--clipboard"))
        {
            if (g_pService)
                break;
            g_pService = VBClGetClipboardService();
        }
        else if (!strcmp(argv[i], "--display"))
        {
            if (g_pService)
                break;
            g_pService = VBClGetDisplayService();
        }
        else if (!strcmp(argv[i], "--seamless"))
        {
            if (g_pService)
                break;
            g_pService = VBClGetSeamlessService();
        }
        else if (!strcmp(argv[i], "--checkhostversion"))
        {
            if (g_pService)
                break;
            g_pService = VBClGetHostVersionService();
        }
#ifdef VBOX_WITH_DRAG_AND_DROP
        else if (!strcmp(argv[i], "--draganddrop"))
        {
            if (g_pService)
                break;
            g_pService = VBClGetDragAndDropService();
        }
#endif /* VBOX_WITH_DRAG_AND_DROP */
        else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help"))
        {
            vboxClientUsage(pcszFileName);
            return 0;
        }
        else
        {
            RTPrintf("%s: unrecognized option `%s'\n", pcszFileName, argv[i]);
            RTPrintf("Try `%s --help' for more information\n", pcszFileName);
            return 1;
        }
        rc = VINF_SUCCESS;
    }
    if (RT_FAILURE(rc) || !g_pService)
    {
        vboxClientUsage(pcszFileName);
        return 1;
    }

    rc = RTCritSectInit(&g_critSect);
    if (RT_FAILURE(rc))
        VBClFatalError(("Initialising critical section: %Rrc\n", rc));
    rc = RTPathUserHome(g_szPidFile, sizeof(g_szPidFile));
    if (RT_FAILURE(rc))
        VBClFatalError(("Getting home directory for pid-file: %Rrc\n", rc));
    rc = RTPathAppend(g_szPidFile, sizeof(g_szPidFile),
                      (*g_pService)->getPidFilePath());
    if (RT_FAILURE(rc))
        VBClFatalError(("Creating pid-file path: %Rrc\n", rc));
    if (fDaemonise)
        rc = VbglR3Daemonize(false /* fNoChDir */, false /* fNoClose */, fRespawn, &cRespawn);
    if (RT_FAILURE(rc))
        VBClFatalError(("Daemonizing: %Rrc\n", rc));
    if (g_szPidFile[0])
        rc = VbglR3PidFile(g_szPidFile, &g_hPidFile);
    if (rc == VERR_FILE_LOCK_VIOLATION)  /* Already running. */
        return 0;
    if (RT_FAILURE(rc))
        VBClFatalError(("Creating pid-file: %Rrc\n", rc));
    /* Set signal handlers to clean up on exit. */
    vboxClientSetSignalHandlers();
#ifndef VBOXCLIENT_WITHOUT_X11
    /* Set an X11 error handler, so that we don't die when we get unavoidable
     * errors. */
    XSetErrorHandler(vboxClientXLibErrorHandler);
    /* Set an X11 I/O error handler, so that we can shutdown properly on
     * fatal errors. */
    XSetIOErrorHandler(vboxClientXLibIOErrorHandler);
#endif
    rc = (*g_pService)->init(g_pService);
    if (RT_FAILURE(rc))
        VBClFatalError(("Initialising service: %Rrc\n", rc));
    rc = (*g_pService)->run(g_pService, fDaemonise);
    if (RT_FAILURE(rc))
        VBClFatalError(("Service main loop failed: %Rrc\n", rc));
    VBClCleanUp();
    return 0;
}
Exemple #18
0
int main(int argc, char **argv)
{
    unsigned cErrors = 0;

    RTR3InitExe(argc, &argv, 0);

    if (argc <= 1)
    {
        RTPrintf("usage: %s default\n", argv[0]);
        return 1;
    }

    for (int i = 1; i < argc; i++)
    {
        if (!strcmp(argv[i], "default"))
            ;
        else
        {
            RTPrintf("Unknown parameter '%s'\n", argv[i]);
            return 1;
        }
    }

    RTHTTP hHttp;
    char *pszBuf = NULL;
    PRTSTREAM CAFile = NULL;

    int rc = RTHttpCreate(&hHttp);

    // create certificate file
    if (RT_SUCCESS(rc))
        rc = RTStrmOpen(CAFILE_NAME, "w+b", &CAFile);

    // fetch root CA certificate (new one, often avoided in cert chains by
    // using an intermediate cert which is signed by old root)
    if (RT_SUCCESS(rc))
        rc = RTHttpGet(hHttp,
                       "http://www.verisign.com/repository/roots/root-certificates/PCA-3G5.pem",
                       &pszBuf);
    if (RT_SUCCESS(rc) && pszBuf)
    {
        uint8_t *abSha1;
        size_t  cbSha1;
        uint8_t *abSha512;
        size_t  cbSha512;
        size_t cbBuf = strlen(pszBuf);
        const uint8_t abSha1PCA3G5[] =
        {
            0x4e, 0xb6, 0xd5, 0x78, 0x49, 0x9b, 0x1c, 0xcf, 0x5f, 0x58,
            0x1e, 0xad, 0x56, 0xbe, 0x3d, 0x9b, 0x67, 0x44, 0xa5, 0xe5
        };
        const uint8_t abSha512PCA3G5[] =
        {
            0xd4, 0xf8, 0x10, 0x54, 0x72, 0x77, 0x0a, 0x2d,
            0xe3, 0x17, 0xb3, 0xcf, 0xed, 0x61, 0xae, 0x5c,
            0x5d, 0x3e, 0xde, 0xa1, 0x41, 0x35, 0xb2, 0xdf,
            0x60, 0xe2, 0x61, 0xfe, 0x3a, 0xc1, 0x66, 0xa3,
            0x3c, 0x88, 0x54, 0x04, 0x4f, 0x1d, 0x13, 0x46,
            0xe3, 0x8c, 0x06, 0x92, 0x9d, 0x70, 0x54, 0xc3,
            0x44, 0xeb, 0x2c, 0x74, 0x25, 0x9e, 0x5d, 0xfb,
            0xd2, 0x6b, 0xa8, 0x9a, 0xf0, 0xb3, 0x6a, 0x01
        };
        rc = RTHttpCertDigest(hHttp, pszBuf, cbBuf,
                              &abSha1, &cbSha1, &abSha512, &cbSha512);
        if (RT_SUCCESS(rc))
        {
            if (cbSha1 != sizeof(abSha1PCA3G5))
            {
                RTPrintf("Wrong SHA1 digest size of PCA-3G5\n");
                rc = VERR_INTERNAL_ERROR;
            }
            else if (memcmp(abSha1PCA3G5, abSha1, cbSha1))
            {
                RTPrintf("Wrong SHA1 digest for PCA-3G5:\n"
                        "Got:      %.*Rhxs\n"
                        "Expected: %.*Rhxs\n",
                        cbSha1, abSha1, sizeof(abSha1PCA3G5), abSha1PCA3G5);
                rc = VERR_INTERNAL_ERROR;
            }
            if (cbSha512 != sizeof(abSha512PCA3G5))
            {
                RTPrintf("Wrong SHA512 digest size of PCA-3G5\n");
                rc = VERR_INTERNAL_ERROR;
            }
            else if (memcmp(abSha512PCA3G5, abSha512, cbSha512))
            {
                RTPrintf("Wrong SHA512 digest for PCA-3G5:\n"
                        "Got:      %.*Rhxs\n"
                        "Expected: %.*Rhxs\n",
                        cbSha512, abSha512, sizeof(abSha512PCA3G5), abSha512PCA3G5);
                rc = VERR_INTERNAL_ERROR;
            }
            RTMemFree(abSha1);
            RTMemFree(abSha512);
            if (RT_SUCCESS(rc))
                rc = RTStrmWrite(CAFile, pszBuf, cbBuf);
            if (RT_SUCCESS(rc))
                rc = RTStrmWrite(CAFile, RTFILE_LINEFEED, strlen(RTFILE_LINEFEED));
        }
    }
    if (pszBuf)
    {
        RTMemFree(pszBuf);
        pszBuf = NULL;
    }

    // fetch root CA certificate (old one, but still very widely used)
    if (RT_SUCCESS(rc))
        rc = RTHttpGet(hHttp,
                       "http://www.verisign.com/repository/roots/root-certificates/PCA-3.pem",
                       &pszBuf);
    if (RT_SUCCESS(rc) && pszBuf)
    {
        uint8_t *abSha1;
        size_t  cbSha1;
        uint8_t *abSha512;
        size_t  cbSha512;
        size_t  cbBuf = strlen(pszBuf);
        const uint8_t abSha1PCA3[] =
        {
            0xa1, 0xdb, 0x63, 0x93, 0x91, 0x6f, 0x17, 0xe4, 0x18, 0x55,
            0x09, 0x40, 0x04, 0x15, 0xc7, 0x02, 0x40, 0xb0, 0xae, 0x6b
        };
        const uint8_t abSha512PCA3[] =
        {
            0xbb, 0xf7, 0x8a, 0x19, 0x9f, 0x37, 0xee, 0xa2,
            0xce, 0xc8, 0xaf, 0xe3, 0xd6, 0x22, 0x54, 0x20,
            0x74, 0x67, 0x6e, 0xa5, 0x19, 0xb7, 0x62, 0x1e,
            0xc1, 0x2f, 0xd5, 0x08, 0xf4, 0x64, 0xc4, 0xc6,
            0xbb, 0xc2, 0xf2, 0x35, 0xe7, 0xbe, 0x32, 0x0b,
            0xde, 0xb2, 0xfc, 0x44, 0x92, 0x5b, 0x8b, 0x9b,
            0x77, 0xa5, 0x40, 0x22, 0x18, 0x12, 0xcb, 0x3d,
            0x0a, 0x67, 0x83, 0x87, 0xc5, 0x45, 0xc4, 0x99
        };
        rc = RTHttpCertDigest(hHttp, pszBuf, cbBuf,
                              &abSha1, &cbSha1, &abSha512, &cbSha512);
        if (RT_SUCCESS(rc))
        {
            if (cbSha1 != sizeof(abSha1PCA3))
            {
                RTPrintf("Wrong SHA1 digest size of PCA-3\n");
                rc = VERR_INTERNAL_ERROR;
            }
            else if (memcmp(abSha1PCA3, abSha1, cbSha1))
            {
                RTPrintf("Wrong SHA1 digest for PCA-3:\n"
                        "Got:      %.*Rhxs\n"
                        "Expected: %.*Rhxs\n",
                        cbSha1, abSha1, sizeof(abSha1PCA3), abSha1PCA3);
                rc = VERR_INTERNAL_ERROR;
            }
            if (cbSha512 != sizeof(abSha512PCA3))
            {
                RTPrintf("Wrong SHA512 digest size of PCA-3\n");
                rc = VERR_INTERNAL_ERROR;
            }
            else if (memcmp(abSha512PCA3, abSha512, cbSha512))
            {
                RTPrintf("Wrong SHA512 digest for PCA-3:\n"
                        "Got:      %.*Rhxs\n"
                        "Expected: %.*Rhxs\n",
                        cbSha512, abSha512, sizeof(abSha512PCA3), abSha512PCA3);
                rc = VERR_INTERNAL_ERROR;
            }
            RTMemFree(abSha1);
            RTMemFree(abSha512);
            if (RT_SUCCESS(rc))
                rc = RTStrmWrite(CAFile, pszBuf, cbBuf);
            if (RT_SUCCESS(rc))
                rc = RTStrmWrite(CAFile, RTFILE_LINEFEED, strlen(RTFILE_LINEFEED));
        }
    }
    if (pszBuf)
    {
        RTMemFree(pszBuf);
        pszBuf = NULL;
    }

    // close certificate file
    if (CAFile)
    {
        RTStrmClose(CAFile);
        CAFile = NULL;
    }

    if (RT_SUCCESS(rc))
        rc = RTHttpSetCAFile(hHttp, CAFILE_NAME);

    if (RT_SUCCESS(rc))
        rc = RTHttpGet(hHttp,
                       "https://update.virtualbox.org/query.php?platform=LINUX_32BITS_UBUNTU_12_04&version=4.1.18",
                       &pszBuf);

    if (   RT_FAILURE(rc)
        && rc != VERR_HTTP_COULDNT_CONNECT)
        cErrors++;

    if (RT_FAILURE(rc))
        RTPrintf("Error code: %Rrc\n", rc);
    else
        RTPrintf("Success!\n");
    RTPrintf("Got: %s\n", pszBuf);
    if (pszBuf)
    {
        RTMemFree(pszBuf);
        pszBuf = NULL;
    }

    RTHttpDestroy(hHttp);

//    RTFileDelete(CAFILE_NAME);

    return !!cErrors;
}
/**
 * Generates a kind of report of the hardware, software and whatever else we
 * think might be useful to know about the testbox.
 */
static RTEXITCODE handlerReport(int argc, char **argv)
{
    NOREF(argc); NOREF(argv);

#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    /*
     * For now, a simple CPUID dump.  Need to figure out how to share code
     * like this with other bits, putting it in IPRT.
     */
    RTPrintf("CPUID Dump\n"
             "Leaf      eax      ebx      ecx      edx\n"
             "---------------------------------------------\n");
    static uint32_t const s_auRanges[] =
    {
        UINT32_C(0x00000000),
        UINT32_C(0x80000000),
        UINT32_C(0x80860000),
        UINT32_C(0xc0000000),
        UINT32_C(0x40000000),
    };
    for (uint32_t iRange = 0; iRange < RT_ELEMENTS(s_auRanges); iRange++)
    {
        uint32_t const uFirst = s_auRanges[iRange];

        uint32_t uEax, uEbx, uEcx, uEdx;
        ASMCpuIdExSlow(uFirst, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
        if (uEax >= uFirst && uEax < uFirst + 100)
        {
            uint32_t const cLeafs = RT_MIN(uEax - uFirst + 1, 32);
            for (uint32_t iLeaf = 0; iLeaf < cLeafs; iLeaf++)
            {
                uint32_t uLeaf = uFirst + iLeaf;
                ASMCpuIdExSlow(uLeaf, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);

                /* Clear APIC IDs to avoid submitting new reports all the time. */
                if (uLeaf == 1)
                    uEbx &= UINT32_C(0x00ffffff);
                if (uLeaf == 0xb)
                    uEdx  = 0;
                if (uLeaf == 0x8000001e)
                    uEax  = 0;

                /* Clear some other node/cpu/core/thread ids. */
                if (uLeaf == 0x8000001e)
                {
                    uEbx &= UINT32_C(0xffffff00);
                    uEcx &= UINT32_C(0xffffff00);
                }

                RTPrintf("%08x: %08x %08x %08x %08x\n", uLeaf, uEax, uEbx, uEcx, uEdx);
            }
        }
    }
    RTPrintf("\n");

    /*
     * DMI info.
     */
    RTPrintf("DMI Info\n"
             "--------\n");
    static const struct { const char *pszName; RTSYSDMISTR enmDmiStr; } s_aDmiStrings[] =
    {
        { "Product Name",           RTSYSDMISTR_PRODUCT_NAME },
        { "Product version",        RTSYSDMISTR_PRODUCT_VERSION },
        { "Product UUID",           RTSYSDMISTR_PRODUCT_UUID },
        { "Product Serial",         RTSYSDMISTR_PRODUCT_SERIAL },
        { "System Manufacturer",    RTSYSDMISTR_MANUFACTURER },
    };
    for (uint32_t iDmiString = 0; iDmiString < RT_ELEMENTS(s_aDmiStrings); iDmiString++)
    {
        char szTmp[4096];
        RT_ZERO(szTmp);
        int rc = RTSystemQueryDmiString(s_aDmiStrings[iDmiString].enmDmiStr, szTmp, sizeof(szTmp) - 1);
        if (RT_SUCCESS(rc))
            RTPrintf("%25s: %s\n", s_aDmiStrings[iDmiString].pszName, RTStrStrip(szTmp));
        else
            RTPrintf("%25s: %s [rc=%Rrc]\n", s_aDmiStrings[iDmiString].pszName, RTStrStrip(szTmp), rc);
    }
    RTPrintf("\n");

#else
#endif

    /*
     * Dump the environment.
     */
    RTPrintf("Environment\n"
             "-----------\n");
    RTENV hEnv;
    int rc = RTEnvClone(&hEnv, RTENV_DEFAULT);
    if (RT_SUCCESS(rc))
    {
        uint32_t cVars = RTEnvCountEx(hEnv);
        for (uint32_t iVar = 0; iVar < cVars; iVar++)
        {
            char szVar[1024];
            char szValue[16384];
            rc = RTEnvGetByIndexEx(hEnv, iVar, szVar, sizeof(szVar), szValue, sizeof(szValue));

            /* zap the value of variables that are subject to change. */
            if (   (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW)
                && (   !strcmp(szVar, "TESTBOX_SCRIPT_REV")
                    || !strcmp(szVar, "TESTBOX_ID")
                    || !strcmp(szVar, "TESTBOX_SCRATCH_SIZE")
                    || !strcmp(szVar, "TESTBOX_TIMEOUT")
                    || !strcmp(szVar, "TESTBOX_TIMEOUT_ABS")
                    || !strcmp(szVar, "TESTBOX_TEST_SET_ID")
                   )
               )
               strcpy(szValue, "<volatile>");

            if (RT_SUCCESS(rc))
                RTPrintf("%25s=%s\n", szVar, szValue);
            else if (rc == VERR_BUFFER_OVERFLOW)
                RTPrintf("%25s=%s [VERR_BUFFER_OVERFLOW]\n", szVar, szValue);
            else
                RTPrintf("rc=%Rrc\n", rc);
        }
        RTEnvDestroy(hEnv);
    }

    /** @todo enumerate volumes and whatnot.  */

    int cch = RTPrintf("\n");
    return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}
Exemple #20
0
static int supSvcWinInterrogate(int argc, char **argv)
{
    RTPrintf("VBoxSupSvc: The \"interrogate\" action is not implemented.\n");
    return 1;
}
/** Print the 'true' if nested paging is supported, 'false' if not and
 * 'dunno' if we cannot tell. */
static RTEXITCODE handlerCpuNestedPaging(int argc, char **argv)
{
    NOREF(argc); NOREF(argv);
    HWVIRTTYPE  enmHwVirt  = isHwVirtSupported();
    int         fSupported = -1;

#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    if (enmHwVirt == HWVIRTTYPE_AMDV)
    {
        uint32_t uEax, uEbx, uEcx, uEdx;
        ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx);
        if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a)
        {
            ASMCpuId(0x8000000a, &uEax, &uEbx, &uEcx, &uEdx);
            if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */)
                fSupported = 1;
            else
                fSupported = 0;
        }
    }
# if defined(RT_OS_LINUX)
    else if (enmHwVirt == HWVIRTTYPE_VTX)
    {
        /*
         * For Intel there is no generic way to query EPT support but on
         * Linux we can resort to checking for the EPT flag in /proc/cpuinfo
         */
        RTFILE hFileCpu;
        int rc = RTFileOpen(&hFileCpu, "/proc/cpuinfo", RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE);
        if (RT_SUCCESS(rc))
        {
            /*
             * Read enough to fit the first CPU entry in, we only check the first
             * CPU as all the others should have the same features.
             */
            char szBuf[_4K];
            size_t cbRead = 0;

            RT_ZERO(szBuf); /* Ensure proper termination. */
            rc = RTFileRead(hFileCpu, &szBuf[0], sizeof(szBuf) - 1, &cbRead);
            if (RT_SUCCESS(rc))
            {
                /* Look for the start of the flags section. */
                char *pszStrFlags = RTStrStr(&szBuf[0], "flags");
                if (pszStrFlags)
                {
                    /* Look for the end as indicated by new line. */
                    char *pszEnd = pszStrFlags;
                    while (   *pszEnd != '\0'
                           && *pszEnd != '\n')
                        pszEnd++;
                    *pszEnd = '\0'; /* Cut off everything after the flags section. */

                    /*
                     * Search for the ept flag indicating support and the absence meaning
                     * not supported.
                     */
                    if (RTStrStr(pszStrFlags, "ept"))
                        fSupported = 1;
                    else
                        fSupported = 0;
                }
            }
            RTFileClose(hFileCpu);
        }
    }
# endif
#endif

    int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n");
    return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
}
Exemple #22
0
static int supSvcWinContinue(int argc, char **argv)
{
    RTPrintf("VBoxSupSvc: The \"continue\" action is not implemented.\n");
    return 1;
}
int main(int argc, char **argv)
{
    int rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);

    /*
     * The first argument is a command.  Figure out which and call its handler.
     */
    static const struct
    {
        const char     *pszCommand;
        RTEXITCODE    (*pfnHandler)(int argc, char **argv);
        bool            fNoArgs;
    } s_aHandlers[] =
    {
        { "cpuvendor",      handlerCpuVendor,       true },
        { "cpuname",        handlerCpuName,         true },
        { "cpurevision",    handlerCpuRevision,     true },
        { "cpuhwvirt",      handlerCpuHwVirt,       true },
        { "nestedpaging",   handlerCpuNestedPaging, true },
        { "longmode",       handlerCpuLongMode,     true },
        { "memsize",        handlerMemSize,         true },
        { "report",         handlerReport,          true },
        { "wipefreespace",  handlerWipeFreeSpace,   false }
    };

    if (argc < 2)
        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "expected command as the first argument");

    for (unsigned i = 0; i < RT_ELEMENTS(s_aHandlers); i++)
    {
        if (!strcmp(argv[1], s_aHandlers[i].pszCommand))
        {
            if (   s_aHandlers[i].fNoArgs
                && argc != 2)
                return RTMsgErrorExit(RTEXITCODE_SYNTAX, "the command '%s' does not take any arguments", argv[1]);
            return s_aHandlers[i].pfnHandler(argc - 1, argv + 1);
        }
    }

    /*
     * Help or version query?
     */
    for (int i = 1; i < argc; i++)
        if (   !strcmp(argv[i], "--help")
            || !strcmp(argv[i], "-h")
            || !strcmp(argv[i], "-?")
            || !strcmp(argv[i], "help") )
        {
            RTPrintf("usage: %s <cmd> [cmd specific args]\n"
                     "\n"
                     "commands:\n", argv[0]);
            for (unsigned j = 0; j < RT_ELEMENTS(s_aHandlers); j++)
                RTPrintf("    %s\n", s_aHandlers[j].pszCommand);
            return RTEXITCODE_FAILURE;
        }
        else if (   !strcmp(argv[i], "--version")
                 || !strcmp(argv[i], "-V") )
        {
            RTPrintf("%sr%u", RTBldCfgVersion(),  RTBldCfgRevision());
            return argc == 2 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
        }

    /*
     * Syntax error.
     */
    return RTMsgErrorExit(RTEXITCODE_SYNTAX, "unknown command '%s'", argv[1]);
}
Exemple #24
0
static int supSvcWinQueryDescription(int argc, char **argv)
{
    RTPrintf("VBoxSupSvc: The \"qdescription\" action is not implemented.\n");
    return 1;
}
Exemple #25
0
void PrintResult(uint64_t cNs, uint64_t cNsMax, uint64_t cNsMin, unsigned cTimes, const char *pszOperation)
{
    RTPrintf("tstPrfRT: %-32s %5lld / %5lld / %5lld ns per call (%u calls %lld ns)\n",
             pszOperation, cNsMin, cNs / (uint64_t)cTimes, cNsMax, cTimes, cNs);
}
Exemple #26
0
static int supSvcWinQueryConfig(int argc, char **argv)
{
    RTPrintf("VBoxSupSvc: The \"qconfig\" action is not implemented.\n");
    return 1;
}
int
main(int argc, char **argv)
{
    int rc;
    RTR3InitExe(argc, &argv, 0);

    for (int i = 1; i < argc; i++)
    {
#ifdef VBOX_OPENGL
        if (strcmp(argv[i], "-gl") == 0)
        {
            gfOpenGL = 1;
            continue;
        }
#endif
        if (strcmp(argv[i], "-loop") == 0 && ++i < argc)
        {
            guLoop = atoi(argv[i]);
            continue;
        }
        RTPrintf("Unrecognized option '%s'\n", argv[i]);
        return -1;
    }

#ifdef RT_OS_WINDOWS
    /* Default to DirectX if nothing else set. "windib" would be possible.  */
    if (!RTEnvExist("SDL_VIDEODRIVER"))
    {
        _putenv("SDL_VIDEODRIVER=directx");
    }
#endif

#ifdef RT_OS_WINDOWS
    _putenv("SDL_VIDEO_WINDOW_POS=0,0");
#else
    RTEnvSet("SDL_VIDEO_WINDOW_POS", "0,0");
#endif

    rc = SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE);
    if (rc != 0)
    {
        RTPrintf("Error: SDL_InitSubSystem failed with message '%s'\n", SDL_GetError());
        return -1;
    }

    /* output what SDL is capable of */
    const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();

    if (!videoInfo)
    {
        RTPrintf("No SDL video info available!\n");
        return -1;
    }

    RTPrintf("SDL capabilities:\n");
    RTPrintf("  Hardware surface support:                    %s\n", videoInfo->hw_available ? "yes" : "no");
    RTPrintf("  Window manager available:                    %s\n", videoInfo->wm_available ? "yes" : "no");
    RTPrintf("  Screen to screen blits accelerated:          %s\n", videoInfo->blit_hw ? "yes" : "no");
    RTPrintf("  Screen to screen colorkey blits accelerated: %s\n", videoInfo->blit_hw_CC ? "yes" : "no");
    RTPrintf("  Screen to screen alpha blits accelerated:    %s\n", videoInfo->blit_hw_A ? "yes" : "no");
    RTPrintf("  Memory to screen blits accelerated:          %s\n", videoInfo->blit_sw ? "yes" : "no");
    RTPrintf("  Memory to screen colorkey blits accelerated: %s\n", videoInfo->blit_sw_CC ? "yes" : "no");
    RTPrintf("  Memory to screen alpha blits accelerated:    %s\n", videoInfo->blit_sw_A ? "yes" : "no");
    RTPrintf("  Color fills accelerated:                     %s\n", videoInfo->blit_fill ? "yes" : "no");
    RTPrintf("  Video memory in kilobytes:                   %d\n", videoInfo->video_mem);
    RTPrintf("  Optimal bpp mode:                            %d\n", videoInfo->vfmt->BitsPerPixel);
    char buf[256];
    RTPrintf("Video driver SDL_VIDEODRIVER / active:         %s/%s\n", RTEnvGet("SDL_VIDEODRIVER"),
                                                                       SDL_VideoDriverName(buf, sizeof(buf)));

    RTPrintf("\n"
             "Starting tests. Any key pressed inside the SDL window will abort this\n"
             "program at the end of the current test. Iterations = %u\n", guLoop);

#ifdef VBOX_OPENGL
    RTPrintf("\n========== "ESC_BOLD"OpenGL is %s"ESC_NORM" ==========\n",
             gfOpenGL ? "ON" : "OFF");
#endif
    bench( 640,  480, 16);  bench( 640,  480, 24);  bench( 640,  480, 32);
    bench(1024,  768, 16);  bench(1024,  768, 24);  bench(1024,  768, 32);
    bench(1280, 1024, 16);  bench(1280, 1024, 24);  bench(1280, 1024, 32);

    RTPrintf("\nSuccess!\n");
    return 0;
}
Exemple #28
0
static int supSvcWinEnable(int argc, char **argv)
{
    RTPrintf("VBoxSupSvc: The \"enable\" action is not implemented.\n");
    return 1;
}
Exemple #29
0
RTR3DECL(int) RTManifestVerifyFilesBuf(void *pvBuf, size_t cbSize, PRTMANIFESTTEST paTests, size_t cTests, size_t *piFailed)
{
    /* Validate input */
    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
    AssertReturn(cbSize > 0, VERR_INVALID_PARAMETER);
    AssertPtrReturn(paTests, VERR_INVALID_POINTER);
    AssertReturn(cTests > 0, VERR_INVALID_PARAMETER);
    AssertPtrNullReturn(piFailed, VERR_INVALID_POINTER);

    int rc = VINF_SUCCESS;

    PRTMANIFESTFILEENTRY paFiles = (PRTMANIFESTFILEENTRY)RTMemTmpAllocZ(sizeof(RTMANIFESTFILEENTRY) * cTests);
    if (!paFiles)
        return VERR_NO_MEMORY;

    /* Fill our compare list */
    for (size_t i = 0; i < cTests; ++i)
        paFiles[i].pTestPattern = &paTests[i];

    char *pcBuf = (char*)pvBuf;
    size_t cbRead = 0;
    /* Parse the manifest file line by line */
    for (;;)
    {
        if (cbRead >= cbSize)
            break;

        size_t cch = rtManifestIndexOfCharInBuf(pcBuf, cbSize - cbRead, '\n') + 1;

        /* Skip empty lines (UNIX/DOS format) */
        if (   (   cch == 1
                && pcBuf[0] == '\n')
            || (   cch == 2
                && pcBuf[0] == '\r'
                && pcBuf[1] == '\n'))
        {
            pcBuf += cch;
            cbRead += cch;
            continue;
        }

        /** @todo r=bird:
         *  -# Better deal with this EOF line platform dependency
         *  -# The SHA1 and SHA256 tests should probably include a blank space check.
         *  -# If there is a specific order to the elements in the string, it would be
         *     good if the delimiter searching checked for it.
         *  -# Deal with filenames containing delimiter characters.
         */

        /* Check for the digest algorithm */
        if (   cch < 4
            || (   !(   pcBuf[0] == 'S'
                     && pcBuf[1] == 'H'
                     && pcBuf[2] == 'A'
                     && pcBuf[3] == '1')
                &&
                   !(   pcBuf[0] == 'S'
                     && pcBuf[1] == 'H'
                     && pcBuf[2] == 'A'
                     && pcBuf[3] == '2'
                     && pcBuf[4] == '5'
                     && pcBuf[5] == '6')
               )
            )
        {
            /* Digest unsupported */
            rc = VERR_MANIFEST_UNSUPPORTED_DIGEST_TYPE;
            break;
        }

        /* Try to find the filename */
        char *pszNameStart = rtManifestPosOfCharInBuf(pcBuf, cch, '(');
        if (!pszNameStart)
        {
            rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
            break;
        }
        char *pszNameEnd = rtManifestPosOfCharInBuf(pcBuf, cch, ')');
        if (!pszNameEnd)
        {
            rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
            break;
        }

        /* Copy the filename part */
        size_t cchName = pszNameEnd - pszNameStart - 1;
        char *pszName = (char *)RTMemTmpAlloc(cchName + 1);
        if (!pszName)
        {
            rc = VERR_NO_MEMORY;
            break;
        }
        memcpy(pszName, pszNameStart + 1, cchName);
        pszName[cchName] = '\0';

        /* Try to find the digest sum */
        char *pszDigestStart = rtManifestPosOfCharInBuf(pcBuf, cch, '=') + 1;
        if (!pszDigestStart)
        {
            RTMemTmpFree(pszName);
            rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
            break;
        }
        char *pszDigestEnd = rtManifestPosOfCharInBuf(pcBuf, cch, '\r');
        if (!pszDigestEnd)
            pszDigestEnd = rtManifestPosOfCharInBuf(pcBuf, cch, '\n');
        if (!pszDigestEnd)
        {
            RTMemTmpFree(pszName);
            rc = VERR_MANIFEST_WRONG_FILE_FORMAT;
            break;
        }
        /* Copy the digest part */
        size_t cchDigest = pszDigestEnd - pszDigestStart - 1;
        char *pszDigest = (char *)RTMemTmpAlloc(cchDigest + 1);
        if (!pszDigest)
        {
            RTMemTmpFree(pszName);
            rc = VERR_NO_MEMORY;
            break;
        }
        memcpy(pszDigest, pszDigestStart + 1, cchDigest);
        pszDigest[cchDigest] = '\0';

        /* Check our file list against the extracted data */
        bool fFound = false;
        for (size_t i = 0; i < cTests; ++i)
        {
            /** @todo r=bird: Using RTStrStr here looks bogus. */
            if (RTStrStr(paFiles[i].pTestPattern->pszTestFile, RTStrStrip(pszName)) != NULL)
            {
                /* Add the data of the manifest file to the file list */
                paFiles[i].pszManifestFile = RTStrDup(RTStrStrip(pszName));
                paFiles[i].pszManifestDigest = RTStrDup(RTStrStrip(pszDigest));
                fFound = true;
                break;
            }
        }
        RTMemTmpFree(pszName);
        RTMemTmpFree(pszDigest);
        if (!fFound)
        {
            /* There have to be an entry in the file list */
            rc = VERR_MANIFEST_FILE_MISMATCH;
            break;
        }

        pcBuf += cch;
        cbRead += cch;
    }

    if (   rc == VINF_SUCCESS
        || rc == VERR_EOF)
    {
        rc = VINF_SUCCESS;
        for (size_t i = 0; i < cTests; ++i)
        {
            /* If there is an entry in the file list, which hasn't an
             * equivalent in the manifest file, its an error. */
            if (   !paFiles[i].pszManifestFile
                || !paFiles[i].pszManifestDigest)
            {
                rc = VERR_MANIFEST_FILE_MISMATCH;
                break;
            }

            /* Do the manifest SHA digest match against the actual digest? */
            if (RTStrICmp(paFiles[i].pszManifestDigest, paFiles[i].pTestPattern->pszTestDigest))
            {
                if (piFailed)
                    *piFailed = i;
                rc = VERR_MANIFEST_DIGEST_MISMATCH;
                break;
            }
        }
    }

    /* Cleanup */
    for (size_t i = 0; i < cTests; ++i)
    {
        if (paFiles[i].pszManifestFile)
            RTStrFree(paFiles[i].pszManifestFile);
        if (paFiles[i].pszManifestDigest)
            RTStrFree(paFiles[i].pszManifestDigest);
    }
    RTMemTmpFree(paFiles);

    RTPrintf("rc = %Rrc\n", rc);
    return rc;
}
/**
 * Handler for the 'add-trusted-publisher' command.
 */
static RTEXITCODE cmdAddTrustedPublisher(int argc, char **argv)
{
    /*
     * Parse arguments.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--root",     'r',    RTGETOPT_REQ_STRING },
    };

    const char *pszRootCert    = NULL;
    const char *pszTrustedCert = NULL;

    int             rc;
    RTGETOPTUNION   ValueUnion;
    RTGETOPTSTATE   GetState;
    RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
    while ((rc = RTGetOpt(&GetState, &ValueUnion)))
    {
        switch (rc)
        {
            case 'h':
                RTPrintf("Usage: VBoxCertUtil add-trusted-publisher [--root <root-cert>] <trusted-cert>\n");
                break;

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

            case 'r':
                if (pszRootCert)
                    return RTMsgErrorExit(RTEXITCODE_SUCCESS,
                                          "You've already specified '%s' as root certificate.",
                                          pszRootCert);
                pszRootCert = ValueUnion.psz;
                break;

            case VINF_GETOPT_NOT_OPTION:
                if (pszTrustedCert)
                    return RTMsgErrorExit(RTEXITCODE_SUCCESS,
                                          "You've already specified '%s' as trusted certificate.",
                                          pszTrustedCert);
                pszTrustedCert = ValueUnion.psz;
                break;

            default:
                return RTGetOptPrintError(rc, &ValueUnion);
        }
    }
    if (!pszTrustedCert)
        return RTMsgErrorExit(RTEXITCODE_SUCCESS, "No trusted certificate specified.");

    /*
     * Do the job.
     */
    /** @todo The root-cert part needs to be made more flexible. */
    if (   pszRootCert
        && !addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "Root", pszRootCert, CERT_STORE_ADD_NEW))
        return RTEXITCODE_FAILURE;

    if (!addCertToStore(CERT_SYSTEM_STORE_LOCAL_MACHINE, "TrustedPublisher", pszTrustedCert, CERT_STORE_ADD_NEW))
        return RTEXITCODE_FAILURE;

    if (g_cVerbosityLevel > 0)
    {
        if (pszRootCert)
            RTMsgInfo("Successfully added '%s' as root and '%s' as trusted publisher", pszRootCert, pszTrustedCert);
        else
            RTMsgInfo("Successfully added '%s' as trusted publisher", pszTrustedCert);
    }
    return RTEXITCODE_SUCCESS;
}