/**
 * @interface_method_impl{TXSTRANSPORT,pfnInit}
 */
static DECLCALLBACK(int) txsTcpInit(void)
{
    int rc = RTCritSectInit(&g_TcpCritSect);
    if (RT_SUCCESS(rc) && g_enmTcpMode != TXSTCPMODE_CLIENT)
    {
        rc = RTTcpServerCreateEx(g_szTcpBindAddr[0] ? g_szTcpBindAddr : NULL, g_uTcpBindPort, &g_pTcpServer);
        if (RT_FAILURE(rc))
        {
            if (rc == VERR_NET_DOWN)
            {
                RTMsgInfo("RTTcpServerCreateEx(%s, %u,) failed: %Rrc, retrying for 20 seconds...\n",
                          g_szTcpBindAddr[0] ? g_szTcpBindAddr : NULL, g_uTcpBindPort, rc);
                uint64_t StartMs = RTTimeMilliTS();
                do
                {
                    RTThreadSleep(1000);
                    rc = RTTcpServerCreateEx(g_szTcpBindAddr[0] ? g_szTcpBindAddr : NULL, g_uTcpBindPort, &g_pTcpServer);
                } while (   rc == VERR_NET_DOWN
                         && RTTimeMilliTS() - StartMs < 20000);
                if (RT_SUCCESS(rc))
                    RTMsgInfo("RTTcpServerCreateEx succceeded.\n");
            }
            if (RT_FAILURE(rc))
            {
                g_pTcpServer = NULL;
                RTCritSectDelete(&g_TcpCritSect);
                RTMsgError("RTTcpServerCreateEx(%s, %u,) failed: %Rrc\n",
                           g_szTcpBindAddr[0] ? g_szTcpBindAddr : NULL, g_uTcpBindPort, rc);
            }
        }
    }

    return rc;
}
/**
 * @interface_method_impl{TXSTRANSPORT,pfnTerm}
 */
static DECLCALLBACK(void) txsTcpTerm(void)
{
    /* Signal thread */
    if (RTCritSectIsInitialized(&g_TcpCritSect))
    {
        RTCritSectEnter(&g_TcpCritSect);
        g_fTcpStopConnecting = true;
        RTCritSectLeave(&g_TcpCritSect);
    }

    if (g_hThreadTcpConnect != NIL_RTTHREAD)
    {
        RTThreadUserSignal(g_hThreadTcpConnect);
        RTTcpClientCancelConnect(&g_pTcpConnectCancelCookie);
    }

    /* Shut down the server (will wake up thread). */
    if (g_pTcpServer)
    {
        Log(("txsTcpTerm: Destroying server...\n"));
        int rc = RTTcpServerDestroy(g_pTcpServer);
        if (RT_FAILURE(rc))
            RTMsgInfo("RTTcpServerDestroy failed in txsTcpTerm: %Rrc", rc);
        g_pTcpServer        = NULL;
    }

    /* Shut down client */
    if (g_hTcpClient != NIL_RTSOCKET)
    {
        if (g_fTcpClientFromServer)
        {
            Log(("txsTcpTerm: Disconnecting client...\n"));
            int rc = RTTcpServerDisconnectClient2(g_hTcpClient);
            if (RT_FAILURE(rc))
                RTMsgInfo("RTTcpServerDisconnectClient2(%RTsock) failed in txsTcpTerm: %Rrc", g_hTcpClient, rc);
        }
        else
        {
            int rc = RTTcpClientClose(g_hTcpClient);
            if (RT_FAILURE(rc))
                RTMsgInfo("RTTcpClientClose(%RTsock) failed in txsTcpTerm: %Rrc", g_hTcpClient, rc);
        }
        g_hTcpClient        = NIL_RTSOCKET;
    }

    /* Clean up stashing. */
    RTMemFree(g_pbTcpStashed);
    g_pbTcpStashed          = NULL;
    g_cbTcpStashed          = 0;
    g_cbTcpStashedAlloced   = 0;

    /* Wait for the thread (they should've had some time to quit by now). */
    txsTcpConnectWaitOnThreads(15000);

    /* Finally, clean up the critical section. */
    if (RTCritSectIsInitialized(&g_TcpCritSect))
        RTCritSectDelete(&g_TcpCritSect);

    Log(("txsTcpTerm: done\n"));
}
Пример #3
0
/**
 * Loads the modules.
 *
 * @returns RTEXITCODE_SUCCESS on success.
 */
static RTEXITCODE LoadModules(void)
{
    for (uint32_t i = 0; i < RT_ELEMENTS(g_aModules); i++)
    {
        if (g_aModules[i].fPreload)
        {
            char            szPath[RTPATH_MAX];
            int rc = RTPathAppPrivateArch(szPath, sizeof(szPath));
            if (RT_SUCCESS(rc))
                rc = RTPathAppend(szPath, sizeof(szPath), g_aModules[i].pszName);
            if (RT_FAILURE(rc))
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTPathAppPrivateArch or RTPathAppend returned %Rrc", rc);

            void           *pvImageBase;
            RTERRINFOSTATIC ErrInfo;
            RTErrInfoInitStatic(&ErrInfo);
            rc = SUPR3LoadModule(szPath, g_aModules[i].pszName, &g_aModules[i].pvImageBase, &ErrInfo.Core);
            if (RT_FAILURE(rc))
                return RTMsgErrorExit(RTEXITCODE_FAILURE, "SUPR3LoadModule failed for %s (%s): %s (rc=%Rrc)",
                                      g_aModules[i].pszName, szPath, ErrInfo.Core.pszMsg, rc);
            if (g_cVerbose >= 1)
                RTMsgInfo("Loaded '%s' ('%s') at %p\n", szPath, g_aModules[i].pszName, g_aModules[i].pvImageBase);
        }
    }

    RTStrmFlush(g_pStdOut);
    return RTEXITCODE_SUCCESS;
}
Пример #4
0
/**
 * Opens a certificate store.
 *
 * @returns true on success, false on failure (error message written).
 * @param   dwDst           The destination, like
 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
 *                          CERT_SYSTEM_STORE_CURRENT_USER.
 * @param   pszStoreNm      The store name.
 */
static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
{
    HCERTSTORE hStore = NULL;
    PRTUTF16   pwszStoreNm;
    int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
    if (RT_SUCCESS(rc))
    {
        if (g_cVerbosityLevel > 1)
            RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm);

        /*
         * Make sure CERT_STORE_OPEN_EXISTING_FLAG is not set. This causes Windows XP
         * to return ACCESS_DENIED when installing TrustedPublisher certificates via
         * CertAddCertificateContextToStore() if the TrustedPublisher store never has
         * been used (through certmgr.exe and friends) yet.
         *
         * According to MSDN, if neither CERT_STORE_OPEN_EXISTING_FLAG nor
         * CERT_STORE_CREATE_NEW_FLAG is set, the store will be either opened or
         * created accordingly.
         */
        dwDst &= ~CERT_STORE_OPEN_EXISTING_FLAG;

        hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
                               PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                               NULL /* hCryptProv = default */,
                               dwDst,
                               pwszStoreNm);
        if (hStore == NULL)
            RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
                       dwDst, pszStoreNm, errorToString(GetLastError()));

        RTUtf16Free(pwszStoreNm);
    }
    return hStore;
}
/**
 * @interface_method_impl{TXSTRANSPORT,txsTcpNotifyReboot}
 */
static DECLCALLBACK(void) txsTcpNotifyReboot(void)
{
    Log(("txsTcpNotifyReboot: RTTcpServerDestroy(%p)\n", g_pTcpServer));
    if (g_pTcpServer)
    {
        int rc = RTTcpServerDestroy(g_pTcpServer);
        if (RT_FAILURE(rc))
            RTMsgInfo("RTTcpServerDestroy failed in txsTcpNotifyReboot: %Rrc", rc);
        g_pTcpServer = NULL;
    }
}
Пример #6
0
int main(int argc, char **argv)
{
    RTR3InitExeNoArguments(0);
    if (argc != 1)
        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "This utility takes no arguments");
    NOREF(argv);

    int rc = SUPR3Install();
    if (RT_SUCCESS(rc))
    {
        if (rc == VINF_SUCCESS)
            RTMsgInfo("Installed successfully!");
        else if (rc == VINF_ALREADY_INITIALIZED)
            RTMsgInfo("Already loaded.");
        else if (rc == VWRN_ALREADY_EXISTS)
            RTMsgInfo("Service already existed; started successfully.");
        else
            RTMsgInfo("Unexpected status: %Rrc", rc);
        return RTEXITCODE_SUCCESS;
    }
    return RTMsgErrorExit(RTEXITCODE_FAILURE, "installation failed. rc=%Rrc", rc);
}
Пример #7
0
int main(int argc, char **argv)
{
    RTR3InitExeNoArguments(0);
    if (argc != 1)
        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "This utility takes no arguments\n");
    NOREF(argv);

    int rc = SUPR3Uninstall();
    if (RT_SUCCESS(rc))
    {
        RTMsgInfo("uninstalled successfully");
        return RTEXITCODE_SUCCESS;
    }
    return RTMsgErrorExit(RTEXITCODE_FAILURE, "uninstallation failed. rc=%Rrc", rc);
}
Пример #8
0
/**
 * Adds a certificate to a store.
 *
 * @returns true on success, false on failure (error message written).
 * @param   dwDst           The destination, like
 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
 *                          ERT_SYSTEM_STORE_CURRENT_USER.
 * @param   pszStoreNm      The store name.
 * @param   pszCertFile     The file containing the certificate to add.
 * @param   dwDisposition   The disposition towards existing certificates when
 *                          adding it.  CERT_STORE_ADD_NEW is a safe one.
 */
static bool addCertToStore(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile, DWORD dwDisposition)
{
    /*
     * Read the certificate file first.
     */
    PCCERT_CONTEXT  pSrcCtx   = NULL;
    HCERTSTORE      hSrcStore = NULL;
    if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
        return false;

    /*
     * Open the destination store.
     */
    bool fRc = false;
    HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
    if (hDstStore)
    {
        if (pSrcCtx)
        {
            if (g_cVerbosityLevel > 1)
                RTMsgInfo("Adding '%s' to %#x:'%s'... (disp %d)", pszCertFile, dwDst, pszStoreNm, dwDisposition);

            if (CertAddCertificateContextToStore(hDstStore, pSrcCtx, dwDisposition, NULL))
                fRc = true;
            else
                RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
        }
        else
        {
            RTMsgError("Path not implemented at line %d\n",  __LINE__);
        }

        CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
    }
    if (pSrcCtx)
        CertFreeCertificateContext(pSrcCtx);
    if (hSrcStore)
        CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
    return fRc;
}
Пример #9
0
/**
 * Opens a certificate store.
 *
 * @returns true on success, false on failure (error message written).
 * @param   dwDst           The destination, like
 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
 *                          ERT_SYSTEM_STORE_CURRENT_USER.
 * @param   pszStoreNm      The store name.
 */
static HCERTSTORE openCertStore(DWORD dwDst, const char *pszStoreNm)
{
    HCERTSTORE hStore = NULL;
    PRTUTF16   pwszStoreNm;
    int rc = RTStrToUtf16(pszStoreNm, &pwszStoreNm);
    if (RT_SUCCESS(rc))
    {
        if (g_cVerbosityLevel > 1)
            RTMsgInfo("Opening store %#x:'%s'", dwDst, pszStoreNm);

        hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
                               PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                               NULL /* hCryptProv = default */,
                               dwDst | CERT_STORE_OPEN_EXISTING_FLAG,
                               pwszStoreNm);
        if (hStore == NULL)
            RTMsgError("CertOpenStore failed opening %#x:'%s': %s",
                       dwDst, pszStoreNm, errorToString(GetLastError()));

        RTUtf16Free(pwszStoreNm);
    }
    return hStore;
}
Пример #10
0
/**
 * 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.",
                                          pszRootCert);
                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;
}
Пример #11
0
/**
 * Removes a certificate, given by file, from a store
 *
 * @returns true on success, false on failure (error message written).
 * @param   dwDst           The destination, like
 *                          CERT_SYSTEM_STORE_LOCAL_MACHINE or
 *                          ERT_SYSTEM_STORE_CURRENT_USER.
 * @param   pszStoreNm      The store name.
 * @param   pszCertFile     The file containing the certificate to add.
 */
static bool removeCertFromStoreByFile(DWORD dwDst, const char *pszStoreNm, const char *pszCertFile)
{
    /*
     * Read the certificate file first.
     */
    PCCERT_CONTEXT  pSrcCtx   = NULL;
    HCERTSTORE      hSrcStore = NULL;
    if (!readCertFile(pszCertFile, &pSrcCtx, &hSrcStore))
        return false;

    WCHAR wszName[1024];
    if (!CertGetNameStringW(pSrcCtx, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0 /*dwFlags*/, NULL /*pvTypePara*/,
                            wszName, sizeof(wszName)))
    {
        RTMsgError("CertGetNameStringW(Subject) failed: %s\n", errorToString(GetLastError()));
        wszName[0] = '\0';
    }

    /*
     * Open the destination store.
     */
    bool fRc = false;
    HCERTSTORE hDstStore = openCertStore(dwDst, pszStoreNm);
    if (hDstStore)
    {
        if (pSrcCtx)
        {
            fRc = true;
            unsigned        cDeleted = 0;
            PCCERT_CONTEXT  pCurCtx  = NULL;
            while ((pCurCtx = CertEnumCertificatesInStore(hDstStore, pCurCtx)) != NULL)
            {
                if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, pCurCtx->pCertInfo, pSrcCtx->pCertInfo))
                {
                    if (g_cVerbosityLevel > 1)
                        RTMsgInfo("Removing '%ls'...", wszName);
                    PCCERT_CONTEXT pDeleteCtx = CertDuplicateCertificateContext(pCurCtx);
                    if (pDeleteCtx)
                    {
                        if (CertDeleteCertificateFromStore(pDeleteCtx))
                            cDeleted++;
                        else
                            RTMsgError("CertDeleteFromStore('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
                    }
                    else
                        RTMsgError("CertDuplicateCertificateContext('%ls') failed: %s\n", wszName, errorToString(GetLastError()));
                }
            }

            if (!cDeleted)
                RTMsgInfo("Found no matching certificates to remove.");
        }
        else
        {
            RTMsgError("Path not implemented at line %d\n",  __LINE__);
        }

        CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
    }
    if (pSrcCtx)
        CertFreeCertificateContext(pSrcCtx);
    if (hSrcStore)
        CertCloseStore(hSrcStore, CERT_CLOSE_STORE_CHECK_FLAG);
    return fRc;
}
Пример #12
0
/**
 * Adds what we think is an image file to the cache.
 *
 * @returns IPRT status code.
 * @param   pszPath         Path to the image file.
 * @param   pszExtraSuff    Optional extra suffix. Mach-O dSYM hack.
 * @param   pszUuidMapDir   The UUID map subdirectory in the cache, if this is
 *                          wanted, otherwise NULL.
 * @param   pCfg            Configuration data.
 */
static int rtDbgSymCacheAddImageFile(const char *pszPath, const char *pszExtraSuff, const char *pszUuidMapDir,
                                     PCRTDBGSYMCACHEADDCFG pCfg)
{
    /*
     * Use the loader to open the alleged image file.  We need to open it with
     * arch set to amd64 and x86_32 in order to handle FAT images from the mac
     * guys (we should actually enumerate archs, but that's currently not
     * implemented nor necessary for our current use).
     */
    /* Open it as AMD64. */
    RTLDRMOD hLdrMod64;
    int rc = RTLdrOpen(pszPath, RTLDR_O_FOR_DEBUG, RTLDRARCH_AMD64, &hLdrMod64);
    if (RT_FAILURE(rc))
    {
        if (rc != VERR_LDR_ARCH_MISMATCH)
        {
            if (rc != VERR_INVALID_EXE_SIGNATURE)
                return RTMsgErrorRc(rc, "RTLdrOpen failed opening '%s' [arch=amd64]: %Rrc", pszPath, rc);
            RTMsgInfo("Skipping '%s', no a recognizable image file...", pszPath);
            return VINF_SUCCESS;
        }
        hLdrMod64 = NIL_RTLDRMOD;
    }

    /* Open it as X86. */
    RTLDRMOD hLdrMod32;
    rc = RTLdrOpen(pszPath, RTLDR_O_FOR_DEBUG, RTLDRARCH_X86_32, &hLdrMod32);
    if (RT_FAILURE(rc))
    {
        if (rc != VERR_LDR_ARCH_MISMATCH)
        {
            RTLdrClose(hLdrMod32);
            return RTMsgErrorRc(rc, "RTLdrOpen failed opening '%s' [arch=x86]: %Rrc", pszPath, rc);
        }
        hLdrMod32 = NIL_RTLDRMOD;
    }

    /*
     * Add the file.
     */
    if (hLdrMod32 == NIL_RTLDRMOD)
        rc = rtDbgSymCacheAddImageFileWorker(pszPath, pCfg, hLdrMod64, pszExtraSuff, pszUuidMapDir);
    else if (hLdrMod64 == NIL_RTLDRMOD)
        rc = rtDbgSymCacheAddImageFileWorker(pszPath, pCfg, hLdrMod32, pszExtraSuff, pszUuidMapDir);
    else
    {
        /*
         * Do we need to add it once or twice?
         */
        RTLDRFMT enmFmt = RTLdrGetFormat(hLdrMod32);
        bool     fSame  = enmFmt == RTLdrGetFormat(hLdrMod64);
        if (fSame && enmFmt == RTLDRFMT_MACHO)
        {
            RTUUID Uuid32, Uuid64;
            int rc32 = RTLdrQueryProp(hLdrMod32, RTLDRPROP_UUID, &Uuid32, sizeof(Uuid32));
            int rc64 = RTLdrQueryProp(hLdrMod64, RTLDRPROP_UUID, &Uuid64, sizeof(Uuid64));
            fSame = RT_SUCCESS(rc32) == RT_SUCCESS(rc64);
            if (fSame && RT_SUCCESS(rc32))
                fSame = RTUuidCompare(&Uuid32, &Uuid64) == 0;
        }
        else if (fSame && enmFmt == RTLDRFMT_PE)
        {
            fSame = RTLdrSize(hLdrMod32) == RTLdrSize(hLdrMod64);
            if (fSame)
            {
                uint32_t uTimestamp32, uTimestamp64;
                int rc32 = RTLdrQueryProp(hLdrMod32, RTLDRPROP_TIMESTAMP_SECONDS, &uTimestamp32, sizeof(uTimestamp32));
                int rc64 = RTLdrQueryProp(hLdrMod64, RTLDRPROP_TIMESTAMP_SECONDS, &uTimestamp64, sizeof(uTimestamp64));
                fSame = RT_SUCCESS(rc32) == RT_SUCCESS(rc64);
                if (fSame && RT_SUCCESS(rc32))
                    fSame = uTimestamp32 == uTimestamp64;
            }
        }

        rc = rtDbgSymCacheAddImageFileWorker(pszPath, pCfg, hLdrMod64, pszExtraSuff, pszUuidMapDir);
        if (!fSame)
        {
            /** @todo should symlink or hardlink this second copy. */
            int rc2 = rtDbgSymCacheAddImageFileWorker(pszPath, pCfg, hLdrMod32, pszExtraSuff, pszUuidMapDir);
            if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
                rc = rc2;
        }
    }

    RTLdrClose(hLdrMod32);
    RTLdrClose(hLdrMod64);
    return VINF_SUCCESS;
}
Пример #13
0
RT_C_DECLS_END



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

    /*
     * Parse arguments.
     */
    bool        fVerbose   = true;
    uint32_t    u32NewRes  = 0;
    uint32_t    cSecsSleep = UINT32_MAX;

    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--resolution",  'r', RTGETOPT_REQ_UINT32 },
        { "--sleep",       's', RTGETOPT_REQ_UINT32 },
        { "--quiet",       'q', RTGETOPT_REQ_NOTHING },
        { "--verbose",     'v', 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 'r':
                u32NewRes = ValueUnion.u32;
                if (u32NewRes > 16*10000 /* 16 ms */ || u32NewRes < 1000 /* 100 microsec */)
                    return RTMsgErrorExit(RTEXITCODE_SYNTAX,
                                          "syntax error: the new timer resolution (%RU32) is out of range\n",
                                          u32NewRes);
                break;

            case 's':
                cSecsSleep = ValueUnion.u32;
                break;

            case 'q':
                fVerbose = false;
                break;

            case 'v':
                fVerbose = true;
                break;

            case 'h':
                RTPrintf("Usage: ntsetfreq [-q|--quiet] [-v|--verbose] [-r|--resolution <100ns>] [-s|--sleep <1s>]\n");
                return RTEXITCODE_SUCCESS;

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


    /*
     * Query the current resolution.
     */
    ULONG   Cur = ~0;
    ULONG   Min = ~0;
    ULONG   Max = ~0;
    LONG    Status;
    if (fVerbose || !u32NewRes)
    {
        Status = NtQueryTimerResolution(&Min, &Max, &Cur);
        if (Status >= 0)
            RTMsgInfo("cur: %u (%u.%02u Hz)  min: %u (%u.%02u Hz)  max: %u (%u.%02u Hz)\n",
                      Cur, 10000000 / Cur, (10000000 / (Cur * 100)) % 100,
                      Min, 10000000 / Min, (10000000 / (Min * 100)) % 100,
                      Max, 10000000 / Max, (10000000 / (Max * 100)) % 100);
        else
            RTMsgError("NTQueryTimerResolution failed with status %#x\n", Status);
    }

    if (u32NewRes)
    {
        Status = NtSetTimerResolution(u32NewRes, TRUE, &Cur);
        if (Status < 0)
            RTMsgError("NTSetTimerResolution(%RU32,,) failed with status %#x\n", u32NewRes, Status);
        else if (fVerbose)
        {
            Cur = Min = Max = ~0;
            Status = NtQueryTimerResolution(&Min, &Max, &Cur);
            if (Status >= 0)
                RTMsgInfo("new: %u (%u.%02u Hz) requested %RU32 (%u.%02u Hz)\n",
                          Cur, 10000000 / Cur, (10000000 / (Cur * 100)) % 100,
                          u32NewRes, 10000000 / u32NewRes, (10000000 / (u32NewRes * 100)) % 100);
            else
                RTMsgError("NTSetTimerResolution succeeded but the NTQueryTimerResolution call failed with status %#x (ignored)\n", Status);
            Status = 0;
        }
    }

    if (u32NewRes && Status >= 0)
    {
        if (cSecsSleep == UINT32_MAX)
            for (;;)
                RTThreadSleep(RT_INDEFINITE_WAIT);
        else
            while (cSecsSleep-- > 0)
                RTThreadSleep(1000);
    }

    return Status >= 0 ? 0 : 1;
}
Пример #14
0
/**
 * Creates a UUID mapping for the file.
 *
 * @returns IPRT status code.
 * @param   pszCacheFile    The path to the file in the cache.
 * @param   pFileUuid       The UUID of the file.
 * @param   pszUuidMapDir   The UUID map subdirectory in the cache, if this is
 *                          wanted, otherwise NULL.
 * @param   pCfg            The configuration.
 */
static int rtDbgSymCacheAddCreateUuidMapping(const char *pszCacheFile, PRTUUID pFileUuid,
                                             const char *pszUuidMapDir, PCRTDBGSYMCACHEADDCFG pCfg)
{
    /*
     * Create the UUID map entry first, deep.
     */
    char szMapPath[RTPATH_MAX];
    int rc = RTPathJoin(szMapPath, sizeof(szMapPath) - sizeof("/xxxx/yyyy/xxxx/yyyy/xxxx/zzzzzzzzzzzz") + 1,
                        pCfg->pszCache, pszUuidMapDir);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error constructing UUID map path (RTPathJoin): %Rrc", rc);

    size_t cch = strlen(szMapPath);
    szMapPath[cch] = '-';

    rc = RTUuidToStr(pFileUuid, &szMapPath[cch + 2], sizeof(szMapPath) - cch);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error constructing UUID map path (RTUuidToStr): %Rrc", rc);

    /* Uppercase the whole lot. */
    RTStrToUpper(&szMapPath[cch + 2]);

    /* Split the first dword in two. */
    szMapPath[cch + 1] = szMapPath[cch + 2];
    szMapPath[cch + 2] = szMapPath[cch + 3];
    szMapPath[cch + 3] = szMapPath[cch + 4];
    szMapPath[cch + 4] = szMapPath[cch + 5];
    szMapPath[cch + 5] = '-';

    /*
     * Create the directories in the path.
     */
    char chSaved = RTPATH_SLASH;
    for (unsigned i = 0; i < 6; i++, cch += 5)
    {
        Assert(szMapPath[cch] == '-');
        szMapPath[cch] = '\0';
        if (!RTDirExists(szMapPath))
        {
            rc = RTDirCreate(szMapPath, 0755, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
            if (RT_FAILURE(rc))
                return RTMsgErrorRc(rc, "RTDirCreate failed on '%s' (UUID map path): %Rrc", szMapPath, rc);
        }
        szMapPath[cch] = RTPATH_SLASH;
    }
    cch -= 5;

    /*
     * Calculate a relative path from there to the actual file.
     */
    char szLinkTarget[RTPATH_MAX];
    //szMapPath[cch] = '\0';
    rc = RTPathCalcRelative(szLinkTarget, sizeof(szLinkTarget), szMapPath, pszCacheFile);
    //szMapPath[cch] = RTPATH_SLASH;
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Failed to calculate relative path from '%s' to '%s': %Rrc", szMapPath, pszCacheFile, rc);

    /*
     * If there is already a link there, check if it matches or whether
     * perhaps it's target doesn't exist.
     */
    RTFSOBJINFO ObjInfo;
    rc = RTPathQueryInfoEx(szMapPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_ON_LINK);
    if (RT_SUCCESS(rc))
    {
        if (RTFS_IS_SYMLINK(ObjInfo.Attr.fMode))
        {
            rc = RTPathQueryInfoEx(szMapPath, &ObjInfo, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
            if (RT_SUCCESS(rc))
            {
                char *pszCurTarget = NULL;
                rc = RTSymlinkReadA(szMapPath, &pszCurTarget);
                if (RT_FAILURE(rc))
                    return RTMsgErrorRc(rc, "UUID map: failed to read existing symlink '%s': %Rrc", szMapPath, rc);
                if (RTPathCompare(pszCurTarget, szLinkTarget) == 0)
                    RTMsgInfo("UUID map: existing link '%s' has the same target ('%s').", szMapPath, pszCurTarget);
                else
                {
                    RTMsgError("UUID map: Existing mapping '%s' pointing to '%s' insted of '%s'",
                               szMapPath, pszCurTarget, szLinkTarget);
                    rc = VERR_ALREADY_EXISTS;
                }
                RTStrFree(pszCurTarget);
                return rc;
            }
            else
                RTMsgInfo("UUID map: replacing dangling link '%s'", szMapPath);
            RTSymlinkDelete(szMapPath, 0 /*fFlags*/);
        }
        else if (RTFS_IS_FILE(ObjInfo.Attr.fMode))
            return RTMsgErrorRc(VERR_IS_A_FILE,
                                "UUID map: found file at '%s', expect symbolic link or nothing.", szMapPath);
        else if (RTFS_IS_DIRECTORY(ObjInfo.Attr.fMode))
            return RTMsgErrorRc(VERR_IS_A_DIRECTORY,
                                "UUID map: found directory at '%s', expect symbolic link or nothing.", szMapPath);
        else
            return RTMsgErrorRc(VERR_NOT_SYMLINK,
                                "UUID map: Expected symbolic link or nothing at '%s', found: fMode=%#x",
                                szMapPath, ObjInfo.Attr.fMode);
    }

    /*
     * Create the symbolic link.
     */
    rc = RTSymlinkCreate(szMapPath, szLinkTarget, RTSYMLINKTYPE_FILE, 0);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Failed to create UUID map symlink '%s' to '%s': %Rrc", szMapPath, szLinkTarget, rc);
    RTMsgInfo("UUID map: %s  =>  %s", szMapPath, szLinkTarget);
    return VINF_SUCCESS;
}
int main(int argc, char *argv[])
{
    /*
     * Initialize IPRT and convert argv to UTF-8.
     */
    int rc = RTR3InitExe(argc, &argv, 0);
    if (RT_FAILURE(rc))
        return RTMsgInitFailure(rc);

    /*
     * Parse arguments and read input files.
     */
    if (argc < 4)
    {
        usage(stderr, argv[0]);
        return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Insufficient arguments.");
    }
    g_products.reserve(20000);
    g_vendors.reserve(3500);

    const char *pszOutFile = NULL;
    for (int i = 1; i < argc; i++)
    {
        if (strcmp(argv[i], "-o") == 0)
        {
            pszOutFile = argv[++i];
            continue;
        }
        if (   strcmp(argv[i], "-h") == 0
            || strcmp(argv[i], "-?") == 0
            || strcmp(argv[i], "--help") == 0)
        {
            usage(stdout, argv[0]);
            return RTEXITCODE_SUCCESS;
        }

        PRTSTREAM pInStrm;
        rc = RTStrmOpen(argv[i], "r", &pInStrm);
        if (RT_FAILURE(rc))
            return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE,
                                  "Failed to open file '%s' for reading: %Rrc", argv[i], rc);

        rc = ParseUsbIds(pInStrm, argv[i]);
        RTStrmClose(pInStrm);
        if (rc != 0)
        {
            RTMsgError("Failed parsing USB devices file '%s'", argv[i]);
            return rc;
        }
    }

    /*
     * Due to USBIDDBVENDOR::iProduct, there is currently a max of 64KB products.
     * (Not a problem as we've only have less that 54K products currently.)
     */
    if (g_products.size() > _64K)
        return RTMsgErrorExit((RTEXITCODE)ERROR_TOO_MANY_PRODUCTS,
                              "More than 64K products is not supported: %u products", g_products.size());

    /*
     * Sort the IDs and fill in the iProduct and cProduct members.
     */
    sort(g_products.begin(), g_products.end());
    sort(g_vendors.begin(), g_vendors.end());

    size_t iProduct = 0;
    for (size_t iVendor = 0; iVendor < g_vendors.size(); iVendor++)
    {
        size_t const idVendor = g_vendors[iVendor].vendorID;
        g_vendors[iVendor].iProduct = iProduct;
        if (   iProduct < g_products.size()
            && g_products[iProduct].vendorID <= idVendor)
        {
            if (g_products[iProduct].vendorID == idVendor)
                do
                    iProduct++;
                while (   iProduct < g_products.size()
                       && g_products[iProduct].vendorID == idVendor);
            else
                return RTMsgErrorExit((RTEXITCODE)ERROR_IN_PARSE_LINE, "product without vendor after sorting. impossible!");
        }
        g_vendors[iVendor].cProducts = iProduct - g_vendors[iVendor].iProduct;
    }

    /*
     * Verify that all IDs are unique.
     */
    ProductsSet::iterator ita = adjacent_find(g_products.begin(), g_products.end());
    if (ita != g_products.end())
        return RTMsgErrorExit((RTEXITCODE)ERROR_DUPLICATE_ENTRY, "Duplicate alias detected: idProduct=%#06x", ita->productID);

    /*
     * Build the string table.
     * Do string compression and create the string table.
     */
    BLDPROGSTRTAB StrTab;
    if (!BldProgStrTab_Init(&StrTab, g_products.size() + g_vendors.size()))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Out of memory!");

    for (ProductsSet::iterator it = g_products.begin(); it != g_products.end(); ++it)
    {
        it->StrRef.pszString = (char *)it->str.c_str();
        BldProgStrTab_AddString(&StrTab, &it->StrRef);
    }
    for (VendorsSet::iterator it = g_vendors.begin(); it != g_vendors.end(); ++it)
    {
        it->StrRef.pszString = (char *)it->str.c_str();
        BldProgStrTab_AddString(&StrTab, &it->StrRef);
    }

    if (!BldProgStrTab_CompileIt(&StrTab, g_fVerbose))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "BldProgStrTab_CompileIt failed!\n");

    /*
     * Print stats.  Making a little extra effort to get it all on one line.
     */
    size_t const cbVendorEntry  = sizeof(USBIdDatabase::s_aVendors[0]) + sizeof(USBIdDatabase::s_aVendorNames[0]);
    size_t const cbProductEntry = sizeof(USBIdDatabase::s_aProducts[0]) + sizeof(USBIdDatabase::s_aProductNames[0]);

    size_t cbOldRaw = (g_products.size() + g_vendors.size()) * sizeof(const char *) * 2 + g_cbRawStrings;
    size_t cbRaw    = g_vendors.size() * cbVendorEntry + g_products.size() * cbProductEntry + g_cbRawStrings;
    size_t cbActual = g_vendors.size() * cbVendorEntry + g_products.size() * cbProductEntry + StrTab.cchStrTab;
#ifdef USB_ID_DATABASE_WITH_COMPRESSION
    cbActual += sizeof(StrTab.aCompDict);
#endif

    char szMsg1[32];
    RTStrPrintf(szMsg1, sizeof(szMsg1),"Total %zu bytes", cbActual);
    char szMsg2[64];
    RTStrPrintf(szMsg2, sizeof(szMsg2)," old version %zu bytes + relocs (%zu%% save)",
                cbOldRaw, (cbOldRaw - cbActual) * 100 / cbOldRaw);
    if (cbActual < cbRaw)
        RTMsgInfo("%s - saving %zu%% (%zu bytes);%s", szMsg1, (cbRaw - cbActual) * 100 / cbRaw, cbRaw - cbActual, szMsg2);
    else
        RTMsgInfo("%s - wasting %zu bytes;%s", szMsg1, cbActual - cbRaw, szMsg2);

    /*
     * Produce the source file.
     */
    if (!pszOutFile)
        return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Output file is not specified.");

    FILE *pOut = fopen(pszOutFile, "w");
    if (!pOut)
        return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Error opening '%s' for writing", pszOutFile);

    WriteSourceFile(pOut, argv[0], &StrTab);

    if (ferror(pOut))
        return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Error writing '%s'!", pszOutFile);
    if (fclose(pOut) != 0)
        return RTMsgErrorExit((RTEXITCODE)ERROR_OPEN_FILE, "Error closing '%s'!", pszOutFile);

    return RTEXITCODE_SUCCESS;
}
Пример #16
0
/**
 * Adds a file to the cache.
 *
 * @returns IPRT status code.
 * @param   pszSrcPath      Path to the source file.
 * @param   pszDstName      The name of the destionation file (no path stuff).
 * @param   pszExtraSuff    Optional extra suffix. Mach-O dSYM hack.
 * @param   pszDstSubDir    The subdirectory to file it under.  This is the
 *                          stringification of a relatively unique identifier of
 *                          the file in question.
 * @param   pAddToUuidMap   Optional file UUID that is used to create a UUID map
 *                          entry.
 * @param   pszUuidMapDir   The UUID map subdirectory in the cache, if this is
 *                          wanted, otherwise NULL.
 * @param   pCfg            The configuration.
 */
static int rtDbgSymCacheAddOneFile(const char *pszSrcPath, const char *pszDstName, const char *pszExtraStuff,
                                   const char *pszDstSubDir, PRTUUID pAddToUuidMap, const char *pszUuidMapDir,
                                   PCRTDBGSYMCACHEADDCFG pCfg)
{
    /*
     * Build and create the destination path, step by step.
     */
    char szDstPath[RTPATH_MAX];
    int rc = RTPathJoin(szDstPath, sizeof(szDstPath), pCfg->pszCache, pszDstName);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error constructing cache path for '%s': %Rrc", pszSrcPath, rc);

    if (!RTDirExists(szDstPath))
    {
        rc = RTDirCreate(szDstPath, 0755, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
        if (RT_FAILURE(rc))
            return RTMsgErrorRc(rc, "Error creating '%s': %Rrc", szDstPath, rc);
    }

    rc = RTPathAppend(szDstPath, sizeof(szDstPath), pszDstSubDir);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error constructing cache path for '%s': %Rrc", pszSrcPath, rc);

    if (!RTDirExists(szDstPath))
    {
        rc = RTDirCreate(szDstPath, 0755, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_NOT_CRITICAL);
        if (RT_FAILURE(rc))
            return RTMsgErrorRc(rc, "Error creating '%s': %Rrc", szDstPath, rc);
    }

    rc = RTPathAppend(szDstPath, sizeof(szDstPath), pszDstName);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error constructing cache path for '%s': %Rrc", pszSrcPath, rc);
    if (pszExtraStuff)
    {
        rc = RTStrCat(szDstPath, sizeof(szDstPath), pszExtraStuff);
        if (RT_FAILURE(rc))
            return RTMsgErrorRc(rc, "Error constructing cache path for '%s': %Rrc", pszSrcPath, rc);
    }

    /*
     * If the file exists, we compare the two and throws an error if the doesn't match.
     */
    if (RTPathExists(szDstPath))
    {
        rc = RTFileCompare(pszSrcPath, szDstPath);
        if (RT_SUCCESS(rc))
        {
            RTMsgInfo("%s is already in the cache.", pszSrcPath);
            if (pAddToUuidMap && pszUuidMapDir)
                return rtDbgSymCacheAddCreateUuidMapping(szDstPath, pAddToUuidMap, pszUuidMapDir, pCfg);
            return VINF_SUCCESS;
        }
        if (rc == VERR_NOT_EQUAL)
            RTMsgInfo("Cache conflict with existing entry '%s' when inserting '%s'.", szDstPath, pszSrcPath);
        else
            RTMsgInfo("Error comparing '%s' with '%s': %Rrc", pszSrcPath, szDstPath, rc);
        if (!pCfg->fOverwriteOnConflict)
            return rc;
    }

    /*
     * The file doesn't exist or we should overwrite it,
     */
    RTMsgInfo("Copying '%s' to '%s'...", pszSrcPath, szDstPath);
    rc = RTFileCopy(pszSrcPath, szDstPath);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "Error copying '%s' to '%s': %Rrc", pszSrcPath, szDstPath, rc);
    if (pAddToUuidMap && pszUuidMapDir)
        return rtDbgSymCacheAddCreateUuidMapping(szDstPath, pAddToUuidMap, pszUuidMapDir, pCfg);
    return VINF_SUCCESS;
}
Пример #17
0
/** The verbosity level. */
static unsigned  g_cVerbosityLevel = 1;


static const char *errorToString(DWORD dwErr)
{
    switch (dwErr)
    {
#define MY_CASE(a_uConst)       case a_uConst: return #a_uConst;
        MY_CASE(CRYPT_E_MSG_ERROR);
        MY_CASE(CRYPT_E_UNKNOWN_ALGO);
        MY_CASE(CRYPT_E_OID_FORMAT);
        MY_CASE(CRYPT_E_INVALID_MSG_TYPE);
        MY_CASE(CRYPT_E_UNEXPECTED_ENCODING);
        MY_CASE(CRYPT_E_AUTH_ATTR_MISSING);
        MY_CASE(CRYPT_E_HASH_VALUE);
        MY_CASE(CRYPT_E_INVALID_INDEX);
        MY_CASE(CRYPT_E_ALREADY_DECRYPTED);
        MY_CASE(CRYPT_E_NOT_DECRYPTED);
        MY_CASE(CRYPT_E_RECIPIENT_NOT_FOUND);
        MY_CASE(CRYPT_E_CONTROL_TYPE);
        MY_CASE(CRYPT_E_ISSUER_SERIALNUMBER);
        MY_CASE(CRYPT_E_SIGNER_NOT_FOUND);
        MY_CASE(CRYPT_E_ATTRIBUTES_MISSING);
        MY_CASE(CRYPT_E_STREAM_MSG_NOT_READY);
        MY_CASE(CRYPT_E_STREAM_INSUFFICIENT_DATA);
        MY_CASE(CRYPT_I_NEW_PROTECTION_REQUIRED);
        MY_CASE(CRYPT_E_BAD_LEN);
        MY_CASE(CRYPT_E_BAD_ENCODE);
        MY_CASE(CRYPT_E_FILE_ERROR);
        MY_CASE(CRYPT_E_NOT_FOUND);
        MY_CASE(CRYPT_E_EXISTS);
        MY_CASE(CRYPT_E_NO_PROVIDER);
        MY_CASE(CRYPT_E_SELF_SIGNED);
        MY_CASE(CRYPT_E_DELETED_PREV);
        MY_CASE(CRYPT_E_NO_MATCH);
        MY_CASE(CRYPT_E_UNEXPECTED_MSG_TYPE);
        MY_CASE(CRYPT_E_NO_KEY_PROPERTY);
        MY_CASE(CRYPT_E_NO_DECRYPT_CERT);
        MY_CASE(CRYPT_E_BAD_MSG);
        MY_CASE(CRYPT_E_NO_SIGNER);
        MY_CASE(CRYPT_E_PENDING_CLOSE);
        MY_CASE(CRYPT_E_REVOKED);
        MY_CASE(CRYPT_E_NO_REVOCATION_DLL);
        MY_CASE(CRYPT_E_NO_REVOCATION_CHECK);
        MY_CASE(CRYPT_E_REVOCATION_OFFLINE);
        MY_CASE(CRYPT_E_NOT_IN_REVOCATION_DATABASE);
        MY_CASE(CRYPT_E_INVALID_NUMERIC_STRING);
        MY_CASE(CRYPT_E_INVALID_PRINTABLE_STRING);
        MY_CASE(CRYPT_E_INVALID_IA5_STRING);
        MY_CASE(CRYPT_E_INVALID_X500_STRING);
        MY_CASE(CRYPT_E_NOT_CHAR_STRING);
        MY_CASE(CRYPT_E_FILERESIZED);
        MY_CASE(CRYPT_E_SECURITY_SETTINGS);
        MY_CASE(CRYPT_E_NO_VERIFY_USAGE_DLL);
        MY_CASE(CRYPT_E_NO_VERIFY_USAGE_CHECK);
        MY_CASE(CRYPT_E_VERIFY_USAGE_OFFLINE);
        MY_CASE(CRYPT_E_NOT_IN_CTL);
        MY_CASE(CRYPT_E_NO_TRUSTED_SIGNER);
        MY_CASE(CRYPT_E_MISSING_PUBKEY_PARA);
        MY_CASE(CRYPT_E_OSS_ERROR);
        default:
        {
            PCRTCOMERRMSG pWinComMsg = RTErrCOMGet(dwErr);
            if (pWinComMsg)
                return pWinComMsg->pszDefine;

            static char s_szErr[32];
            RTStrPrintf(s_szErr, sizeof(s_szErr), "%#x (%d)", dwErr, dwErr);
            return s_szErr;
        }
    }
}

#if 0 /* hacking */
static RTEXITCODE addToStore(const char *pszFilename, PCRTUTF16 pwszStore)
{
    /*
     * Open the source.
     */
    void   *pvFile;
    size_t  cbFile;
    int rc = RTFileReadAll(pszFilename, &pvFile, &cbFile);
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "RTFileReadAll failed on '%s': %Rrc", pszFilename, rc);

    RTEXITCODE rcExit = RTEXITCODE_FAILURE;

    PCCERT_CONTEXT pCertCtx = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
                                                           (PBYTE)pvFile,
                                                           (DWORD)cbFile);
    if (pCertCtx)
    {
        /*
         * Open the destination.
         */
        HCERTSTORE hDstStore = CertOpenStore(CERT_STORE_PROV_SYSTEM_W,
                                             PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                                             NULL /* hCryptProv = default */,
                                             /*CERT_SYSTEM_STORE_LOCAL_MACHINE*/ CERT_SYSTEM_STORE_CURRENT_USER | CERT_STORE_OPEN_EXISTING_FLAG,
                                             pwszStore);
        if (hDstStore != NULL)
        {
#if 0
            DWORD dwContextType;
            if (CertAddSerializedElementToStore(hDstStore,
                                                pCertCtx->pbCertEncoded,
                                                pCertCtx->cbCertEncoded,
                                                CERT_STORE_ADD_NEW,
                                                0 /* dwFlags (reserved) */,
                                                CERT_STORE_ALL_CONTEXT_FLAG,
                                                &dwContextType,
                                                NULL))
            {
                RTMsgInfo("Successfully added '%s' to the '%ls' store (ctx type %u)", pszFilename, pwszStore, dwContextType);
                rcExit = RTEXITCODE_SUCCESS;
            }
            else
                RTMsgError("CertAddSerializedElementToStore returned %s", errorToString(GetLastError()));
#else
            if (CertAddCertificateContextToStore(hDstStore, pCertCtx, CERT_STORE_ADD_NEW, NULL))
            {
                RTMsgInfo("Successfully added '%s' to the '%ls' store", pszFilename, pwszStore);
                rcExit = RTEXITCODE_SUCCESS;
            }
            else
                RTMsgError("CertAddCertificateContextToStore returned %s", errorToString(GetLastError()));
#endif

            CertCloseStore(hDstStore, CERT_CLOSE_STORE_CHECK_FLAG);
        }
        else
            RTMsgError("CertOpenStore returned %s", errorToString(GetLastError()));
        CertFreeCertificateContext(pCertCtx);
    }
    else
        RTMsgError("CertCreateCertificateContext returned %s", errorToString(GetLastError()));
    RTFileReadAllFree(pvFile, cbFile);
    return rcExit;

#if 0

    CRYPT_DATA_BLOB Blob;
    Blob.cbData = (DWORD)cbData;
    Blob.pbData = (PBYTE)pvData;
    HCERTSTORE hSrcStore = PFXImportCertStore(&Blob, L"", )

#endif
}
Пример #18
0
/**
 * Recursive worker for rtDbgSymCacheAddDir, for minimal stack wasting.
 *
 * @returns IPRT status code (fully bitched).
 * @param   pszPath             Pointer to a RTPATH_MAX size buffer containing
 *                              the path to the current directory ending with a
 *                              slash.
 * @param   cchPath             The size of the current directory path.
 * @param   pDirEntry           Pointer to the RTDIRENTRYEX structure to use.
 * @param   pCfg                The configuration.
 */
static int rtDbgSymCacheAddDirWorker(char *pszPath, size_t cchPath, PRTDIRENTRYEX pDirEntry, PCRTDBGSYMCACHEADDCFG pCfg)
{
    /*
     * Open the directory.
     */
    PRTDIR pDir;
    int rc, rc2;
    if (pCfg->pszFilter)
    {
        rc = RTStrCopy(&pszPath[cchPath], RTPATH_MAX - cchPath, pCfg->pszFilter);
        if (RT_FAILURE(rc))
        {
            pszPath[cchPath] = '\0';
            return RTMsgErrorRc(rc, "Filename too long (%Rrc): '%s" RTPATH_SLASH_STR "%s'", rc, pszPath, pCfg->pszFilter);
        }
        rc = RTDirOpenFiltered(&pDir, pszPath, RTDIRFILTER_WINNT, 0 /*fFlags*/);
    }
    else
        rc = RTDirOpen(&pDir, pszPath);
    if (RT_FAILURE(rc))
        return RTMsgErrorRc(rc, "RTDirOpen%s failed on '%s': %Rrc", pCfg->pszFilter ? "Filtered" : "", pszPath, rc);

    /*
     * Enumerate the files.
     */
    for (;;)
    {
        rc2 = RTDirReadEx(pDir, pDirEntry, NULL, RTFSOBJATTRADD_NOTHING, RTPATH_F_FOLLOW_LINK);
        if (RT_FAILURE(rc2))
        {
            pszPath[cchPath] = '\0';
            if (rc2 != VERR_NO_MORE_FILES)
            {
                RTMsgError("RTDirReadEx failed in '%s': %Rrc\n", pszPath, rc2);
                rc = rc2;
            }
            break;
        }

        /* Skip dot and dot-dot. */
        if (RTDirEntryExIsStdDotLink(pDirEntry))
            continue;

        /* Construct a full path. */
        rc = RTStrCopy(&pszPath[cchPath], RTPATH_MAX, pDirEntry->szName);
        if (RT_FAILURE(rc))
        {
            pszPath[cchPath] = '\0';
            RTMsgError("File name too long in '%s': '%s' (%Rrc)", pszPath, pDirEntry->szName, rc);
            break;
        }

        switch (rtDbgSymCacheFigureType2(pszPath, &pDirEntry->Info))
        {
            case RTDBGSYMCACHEFILETYPE_DIR:
                if (!pCfg->fRecursive)
                    RTMsgInfo("Skipping directory '%s'...", pszPath);
                else
                {
                    if (cchPath + pDirEntry->cbName + 3 <= RTPATH_MAX)
                    {
                        pszPath[cchPath + pDirEntry->cbName] = RTPATH_SLASH;
                        pszPath[cchPath + pDirEntry->cbName + 1] = '\0';
                        rc2 = rtDbgSymCacheAddDirWorker(pszPath, cchPath + pDirEntry->cbName + 1, pDirEntry, pCfg);
                    }
                    else
                    {
                        RTMsgError("File name too long in '%s': '%s' (%Rrc)", pszPath, pDirEntry->szName, rc);
                        rc2 = VERR_FILENAME_TOO_LONG;
                    }
                }
                break;

            case RTDBGSYMCACHEFILETYPE_DEBUG_FILE:
                rc2 = rtDbgSymCacheAddDebugFile(pszPath, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_IMAGE_FILE:
                rc2 = rtDbgSymCacheAddImageFile(pszPath, NULL /*pszExtraSuff*/, RTDBG_CACHE_UUID_MAP_DIR_IMAGES, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_DEBUG_BUNDLE:
                rc2 = rtDbgSymCacheAddDebugBundle(pszPath, cchPath, pDirEntry->cbName, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_IMAGE_BUNDLE:
                rc2 = rtDbgSymCacheAddImageBundle(pszPath, cchPath, pDirEntry->cbName, pDirEntry, pCfg);
                break;

            case RTDBGSYMCACHEFILETYPE_DIR_FILTER:
            case RTDBGSYMCACHEFILETYPE_INVALID:
                rc2 = RTMsgErrorRc(VERR_INTERNAL_ERROR_2, "Invalid: '%s'", pszPath);
                break;

            case RTDBGSYMCACHEFILETYPE_IGNORE:
                rc2 = VINF_SUCCESS;
                break;
        }

        if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
            rc = rc2;
    }

    /*
     * Clean up.
     */
    rc2 = RTDirClose(pDir);
    if (RT_FAILURE(rc2))
    {
        RTMsgError("RTDirClose failed in '%s': %Rrc", pszPath, rc);
        rc = rc2;
    }
    return rc;
}
static RTEXITCODE HandleExtractExeSignerCert(int cArgs, char **papszArgs)
{
    /*
     * Parse arguments.
     */
    static const RTGETOPTDEF s_aOptions[] =
    {
        { "--ber",    'b', RTGETOPT_REQ_NOTHING },
        { "--cer",    'c', RTGETOPT_REQ_NOTHING },
        { "--der",    'd', RTGETOPT_REQ_NOTHING },
        { "--exe",    'e', RTGETOPT_REQ_STRING },
        { "--output", 'o', RTGETOPT_REQ_STRING },
    };

    const char *pszExe = NULL;
    const char *pszOut = NULL;
    RTLDRARCH   enmLdrArch   = RTLDRARCH_WHATEVER;
    uint32_t    fCursorFlags = RTASN1CURSOR_FLAGS_DER;

    RTGETOPTSTATE GetState;
    int rc = RTGetOptInit(&GetState, cArgs, papszArgs, s_aOptions, RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    AssertRCReturn(rc, RTEXITCODE_FAILURE);
    RTGETOPTUNION ValueUnion;
    int ch;
    while ((ch = RTGetOpt(&GetState, &ValueUnion)))
    {
        switch (ch)
        {
            case 'e':   pszExe = ValueUnion.psz; break;
            case 'o':   pszOut = ValueUnion.psz; break;
            case 'b':   fCursorFlags = 0; break;
            case 'c':   fCursorFlags = RTASN1CURSOR_FLAGS_CER; break;
            case 'd':   fCursorFlags = RTASN1CURSOR_FLAGS_DER; break;
            case 'V':   return HandleVersion(cArgs, papszArgs);
            case 'h':   return HelpExtractExeSignerCert(g_pStdOut, RTSIGNTOOLHELP_FULL);

            case VINF_GETOPT_NOT_OPTION:
                if (!pszExe)
                    pszExe = ValueUnion.psz;
                else if (!pszOut)
                    pszOut = ValueUnion.psz;
                else
                    return RTMsgErrorExit(RTEXITCODE_FAILURE, "Too many file arguments: %s", ValueUnion.psz);
                break;

            default:
                return RTGetOptPrintError(ch, &ValueUnion);
        }
    }
    if (!pszExe)
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No executable given.");
    if (!pszOut)
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "No output file given.");
    if (RTPathExists(pszOut))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "The output file '%s' exists.", pszOut);

    /*
     * Do it.
     */

    /* Open the executable image and query the PKCS7 info. */
    RTLDRMOD hLdrMod;
    rc = RTLdrOpen(pszExe, RTLDR_O_FOR_VALIDATION, enmLdrArch, &hLdrMod);
    if (RT_FAILURE(rc))
        return RTMsgErrorExit(RTEXITCODE_FAILURE, "Error opening executable image '%s': %Rrc", pszExe, rc);

    RTEXITCODE rcExit = RTEXITCODE_FAILURE;
#ifdef DEBUG
    size_t     cbBuf = 64;
#else
    size_t     cbBuf = _512K;
#endif
    void      *pvBuf = RTMemAlloc(cbBuf);
    size_t     cbRet = 0;
    rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbRet);
    if (rc == VERR_BUFFER_OVERFLOW && cbRet < _4M && cbRet > 0)
    {
        RTMemFree(pvBuf);
        cbBuf = cbRet;
        pvBuf = RTMemAlloc(cbBuf);
        rc = RTLdrQueryPropEx(hLdrMod, RTLDRPROP_PKCS7_SIGNED_DATA, NULL /*pvBits*/, pvBuf, cbBuf, &cbRet);
    }
    if (RT_SUCCESS(rc))
    {
        static RTERRINFOSTATIC s_StaticErrInfo;
        RTErrInfoInitStatic(&s_StaticErrInfo);

        /*
         * Decode the output.
         */
        RTASN1CURSORPRIMARY PrimaryCursor;
        RTAsn1CursorInitPrimary(&PrimaryCursor, pvBuf, (uint32_t)cbRet, &s_StaticErrInfo.Core,
                                &g_RTAsn1DefaultAllocator, fCursorFlags, "exe");
        RTCRPKCS7CONTENTINFO Pkcs7Ci;
        rc = RTCrPkcs7ContentInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &Pkcs7Ci, "pkcs7");
        if (RT_SUCCESS(rc))
        {
            if (RTCrPkcs7ContentInfo_IsSignedData(&Pkcs7Ci))
            {
                PCRTCRPKCS7SIGNEDDATA pSd = Pkcs7Ci.u.pSignedData;
                if (pSd->SignerInfos.cItems == 1)
                {
                    PCRTCRPKCS7ISSUERANDSERIALNUMBER pISN = &pSd->SignerInfos.paItems[0].IssuerAndSerialNumber;
                    PCRTCRX509CERTIFICATE pCert;
                    pCert = RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(&pSd->Certificates,
                                                                                &pISN->Name, &pISN->SerialNumber);
                    if (pCert)
                    {
                        /*
                         * Write it out.
                         */
                        RTFILE hFile;
                        rc = RTFileOpen(&hFile, pszOut, RTFILE_O_WRITE | RTFILE_O_DENY_WRITE | RTFILE_O_CREATE);
                        if (RT_SUCCESS(rc))
                        {
                            uint32_t cbCert = pCert->SeqCore.Asn1Core.cbHdr + pCert->SeqCore.Asn1Core.cb;
                            rc = RTFileWrite(hFile, pCert->SeqCore.Asn1Core.uData.pu8 - pCert->SeqCore.Asn1Core.cbHdr,
                                             cbCert, NULL);
                            if (RT_SUCCESS(rc))
                            {
                                rc = RTFileClose(hFile);
                                if (RT_SUCCESS(rc))
                                {
                                    hFile  = NIL_RTFILE;
                                    rcExit = RTEXITCODE_SUCCESS;
                                    RTMsgInfo("Successfully wrote %u bytes to '%s'", cbCert, pszOut);
                                }
                                else
                                    RTMsgError("RTFileClose failed: %Rrc", rc);
                            }
                            else
                                RTMsgError("RTFileWrite failed: %Rrc", rc);
                            RTFileClose(hFile);
                        }
                        else
                            RTMsgError("Error opening '%s': %Rrc", pszOut, rc);
                    }
                    else
                        RTMsgError("Certificate not found.");
                }
                else
                    RTMsgError("SignerInfo count: %u", pSd->SignerInfos.cItems);
            }
            else
                RTMsgError("No PKCS7 content: ContentType=%s", Pkcs7Ci.ContentType.szObjId);
            RTAsn1VtDelete(&Pkcs7Ci.SeqCore.Asn1Core);
        }
        else
            RTMsgError("RTPkcs7ContentInfoDecodeAsn1 failed: %Rrc - %s", rc, s_StaticErrInfo.szMsg);
    }
    else
        RTMsgError("RTLDRPROP_PKCS7_SIGNED_DATA failed on '%s': %Rrc", pszExe, rc);
    RTMemFree(pvBuf);
    rc = RTLdrClose(hLdrMod);
    if (RT_FAILURE(rc))
        rcExit = RTMsgErrorExit(RTEXITCODE_FAILURE, "RTLdrClose failed: %Rrc\n", rc);
    return rcExit;
}