Example #1
0
RTDECL(int) RTPathUserDocuments(char *pszPath, size_t cchPath)
{
    /*
     * Validate input
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(cchPath, VERR_INVALID_PARAMETER);

    RTLDRMOD hShell32;
    int rc = RTLdrLoad("Shell32.dll", &hShell32);
    if (RT_SUCCESS(rc))
    {
        PFNSHGETFOLDERPATHW pfnSHGetFolderPathW;
        rc = RTLdrGetSymbol(hShell32, "SHGetFolderPathW", (void**)&pfnSHGetFolderPathW);
        if (RT_SUCCESS(rc))
        {
            RTUTF16 wszPath[RTPATH_MAX];
            HRESULT hrc = pfnSHGetFolderPathW(0, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, wszPath);
            if (   hrc == S_OK     /* Found */
                || hrc == S_FALSE) /* Found, but doesn't exist */
            {
                /*
                 * Convert and return.
                 */
                RTLdrClose(hShell32);
                return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
            }
        }
        RTLdrClose(hShell32);
    }
    return VERR_PATH_NOT_FOUND;
}
Example #2
0
bool VBoxLibDlpiFound(void)
{
    RTLDRMOD hLibDlpi;

    if (g_hLibDlpi && g_fCheckedForLibDlpi)
        return true;
    if (g_fCheckedForLibDlpi)
        return false;
    if (!RT_SUCCESS(RTLdrLoad(LIB_DLPI, &hLibDlpi)))
        return false;
    if (   RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_open", (void **)&g_pfnLibDlpiOpen))
        && RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_close", (void **)&g_pfnLibDlpiClose))
        && RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_info", (void **)&g_pfnLibDlpiInfo))
        && RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_bind", (void **)&g_pfnLibDlpiBind))
        && RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_promiscon", (void **)&g_pfnLibDlpiPromiscon))
        && RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_set_physaddr", (void **)&g_pfnLibDlpiSetPhysAddr))
        && RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_recv", (void **)&g_pfnLibDlpiRecv))
        && RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_fd", (void **)&g_pfnLibDlpiFd))
       )
    {
        g_hLibDlpi = hLibDlpi;
        g_fCheckedForLibDlpi = true;
        return true;
    }
    else
    {
        RTLdrClose(hLibDlpi);
        g_fCheckedForLibDlpi = true;
        return false;
    }
}
Example #3
0
bool VBoxSolarisLibDlpiFound(void)
{
    RTLDRMOD hLibDlpi;

    if (g_hLibDlpi && g_fCheckedForLibDlpi)
        return true;
    if (g_fCheckedForLibDlpi)
        return false;
    if (!RT_SUCCESS(RTLdrLoad(LIB_DLPI, &hLibDlpi)))
        return false;
    /*
     * Unfortunately; we cannot make use of dlpi_get_physaddr because it requires us to
     * open the VNIC/link which requires root permissions :/
     */
    if (RT_SUCCESS(RTLdrGetSymbol(hLibDlpi, "dlpi_walk", (void **)&g_pfnLibDlpiWalk)))
    {
        g_hLibDlpi = hLibDlpi;
        g_fCheckedForLibDlpi = true;
        return true;
    }
    else
    {
        RTLdrClose(hLibDlpi);
        g_fCheckedForLibDlpi = true;
        return false;
    }
}
bool VBoxSolarisLibDlpiFound(void)
{
    RTLDRMOD hLibDlpi;

    if (g_fCheckedForLibDlpi)
        return g_hLibDlpi != NIL_RTLDRMOD;
    g_fCheckedForLibDlpi = true;
    int rc = RTLdrLoad(LIB_DLPI, &hLibDlpi);
    if (RT_SUCCESS(rc))
    {
        /*
         * Unfortunately; we cannot make use of dlpi_get_physaddr because it requires us to
         * open the VNIC/link which requires root permissions :/
         */
        rc  = RTLdrGetSymbol(hLibDlpi, "dlpi_walk", (void **)&g_pfnLibDlpiWalk);
        rc |= RTLdrGetSymbol(hLibDlpi, "dlpi_close", (void **)&g_pfnLibDlpiClose);
        rc |= RTLdrGetSymbol(hLibDlpi, "dlpi_open", (void **)&g_pfnLibDlpiOpen);
        if (RT_SUCCESS(rc))
        {
            g_hLibDlpi = hLibDlpi;
            return true;
        }

        RTLdrClose(hLibDlpi);
    }
    hLibDlpi = NIL_RTLDRMOD;
    return false;
}
Example #5
0
static void vboxClipboardInitNewAPI(VBOXCLIPBOARDCONTEXT *pCtx)
{
    RTLDRMOD hUser32 = NIL_RTLDRMOD;
    int rc = RTLdrLoadSystem("User32.dll", /* fNoUnload = */ true, &hUser32);
    if (RT_SUCCESS(rc))
    {
        rc = RTLdrGetSymbol(hUser32, "AddClipboardFormatListener", (void**)&pCtx->pfnAddClipboardFormatListener);
        if (RT_SUCCESS(rc))
        {
            rc = RTLdrGetSymbol(hUser32, "RemoveClipboardFormatListener", (void**)&pCtx->pfnRemoveClipboardFormatListener);
        }

        RTLdrClose(hUser32);
    }

    if (RT_SUCCESS(rc))
    {
        Log(("New Clipboard API is enabled\n"));
    }
    else
    {
        pCtx->pfnAddClipboardFormatListener = NULL;
        pCtx->pfnRemoveClipboardFormatListener = NULL;
        Log(("New Clipboard API is not available. rc = %Rrc\n", rc));
    }
}
Example #6
0
/**
 * Builds and allocates the security descriptor required for securing the local pipe.
 *
 * @return  IPRT status code.
 * @param   ppDesc              Where to store the allocated security descriptor on success.
 *                              Must be free'd using LocalFree().
 */
static int rtLocalIpcServerWinAllocSecurityDescriptior(PSECURITY_DESCRIPTOR *ppDesc, bool fServer)
{
    /** @todo Stuff this into RTInitOnce? Later. */
    PFNCONVERTSTRINGSECURITYDESCRIPTORTOSECURITYDESCRIPTOR
        pfnConvertStringSecurityDescriptorToSecurityDescriptor = NULL;

    RTLDRMOD hAdvApi32 = NIL_RTLDRMOD;
    int rc = RTLdrLoadSystem("Advapi32.dll", true /*fNoUnload*/, &hAdvApi32);
    if (RT_SUCCESS(rc))
        rc = RTLdrGetSymbol(hAdvApi32, "ConvertStringSecurityDescriptorToSecurityDescriptorW",
                            (void**)&pfnConvertStringSecurityDescriptorToSecurityDescriptor);

    PSECURITY_DESCRIPTOR pSecDesc = NULL;
    if (RT_SUCCESS(rc))
    {
        AssertPtr(pfnConvertStringSecurityDescriptorToSecurityDescriptor);

        /*
         * We'll create a security descriptor from a SDDL that denies
         * access to network clients (this is local IPC after all), it
         * makes some further restrictions to prevent non-authenticated
         * users from screwing around.
         */
        PRTUTF16 pwszSDDL;
        rc = RTStrToUtf16(fServer
                          ? RTLOCALIPC_WIN_SDDL_SERVER : RTLOCALIPC_WIN_SDDL_CLIENT, &pwszSDDL);
        if (RT_SUCCESS(rc))
        {
            if (!pfnConvertStringSecurityDescriptorToSecurityDescriptor((LPCTSTR)pwszSDDL,
                                                                        SDDL_REVISION_1,
                                                                        &pSecDesc,
                                                                        NULL))
            {
                rc = RTErrConvertFromWin32(GetLastError());
            }

            RTUtf16Free(pwszSDDL);
        }
    }
    else
    {
        /* Windows OSes < W2K SP2 not supported for now, bail out. */
        /** @todo Implement me! */
        rc = VERR_NOT_SUPPORTED;
    }

    if (hAdvApi32 != NIL_RTLDRMOD)
         RTLdrClose(hAdvApi32);

    if (RT_SUCCESS(rc))
    {
        AssertPtr(pSecDesc);
        *ppDesc = pSecDesc;
    }

    return rc;
}
/**
 * Gets the user home directory.
 *
 * @returns iprt status code.
 * @param   pszPath     Buffer where to store the path.
 * @param   cchPath     Buffer size in bytes.
 */
RTDECL(int) RTPathUserHome(char *pszPath, size_t cchPath)
{
    /*
     * Validate input
     */
    AssertPtrReturn(pszPath, VERR_INVALID_POINTER);
    AssertReturn(cchPath, VERR_INVALID_PARAMETER);

    RTUTF16 wszPath[RTPATH_MAX];
    bool    fValidFolderPath = false;

    /*
     * Try with Windows XP+ functionality first.
     */
    RTLDRMOD hShell32;
    int rc = RTLdrLoadSystem("Shell32.dll", true /*fNoUnload*/, &hShell32);
    if (RT_SUCCESS(rc))
    {
        PFNSHGETFOLDERPATHW pfnSHGetFolderPathW;
        rc = RTLdrGetSymbol(hShell32, "SHGetFolderPathW", (void**)&pfnSHGetFolderPathW);
        if (RT_SUCCESS(rc))
        {
            HRESULT hrc = pfnSHGetFolderPathW(0, CSIDL_PROFILE, NULL, SHGFP_TYPE_CURRENT, wszPath);
            fValidFolderPath = (hrc == S_OK);
        }
        RTLdrClose(hShell32);
    }

    DWORD   dwAttr;
    if (    !fValidFolderPath
        ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
        ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
    {
        /*
         * Fall back to Windows specific environment variables. HOME is not used.
         */
        if (    !GetEnvironmentVariableW(L"USERPROFILE", &wszPath[0], RTPATH_MAX)
            ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
            ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
        {
            /* %HOMEDRIVE%%HOMEPATH% */
            if (!GetEnvironmentVariableW(L"HOMEDRIVE", &wszPath[0], RTPATH_MAX))
                return VERR_PATH_NOT_FOUND;
            size_t const cwc = RTUtf16Len(&wszPath[0]);
            if (    !GetEnvironmentVariableW(L"HOMEPATH", &wszPath[cwc], RTPATH_MAX - (DWORD)cwc)
                ||  (dwAttr = GetFileAttributesW(&wszPath[0])) == INVALID_FILE_ATTRIBUTES
                ||  !(dwAttr & FILE_ATTRIBUTE_DIRECTORY))
                return VERR_PATH_NOT_FOUND;
        }
    }

    /*
     * Convert and return.
     */
    return RTUtf16ToUtf8Ex(&wszPath[0], RTSTR_MAX, &pszPath, cchPath, NULL);
}
Example #8
0
void VBoxVRDPDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
{
    Log(("VBoxTray: VBoxVRDPDestroy\n"));
    VBOXVRDPCONTEXT *pCtx = (VBOXVRDPCONTEXT *)pInstance;
    vboxExperienceRestore (pCtx->level);
    if (gCtx.hModUxTheme != NIL_RTLDRMOD)
    {
        RTLdrClose(gCtx.hModUxTheme);
        gCtx.hModUxTheme = NIL_RTLDRMOD;
    }
    return;
}
Example #9
0
RTDECL(bool) RTLdrIsLoadable(const char *pszFilename)
{
    /*
     * Try to load the library.
     */
    RTLDRMOD hLib;
    int rc = RTLdrLoad(pszFilename, &hLib);
    if (RT_SUCCESS(rc))
    {
        RTLdrClose(hLib);
        return true;
    }
    return false;
}
Example #10
0
RTDECL(void *) RTLdrGetSystemSymbol(const char *pszFilename, const char *pszSymbol)
{
    void    *pvRet = NULL;
    RTLDRMOD hLdrMod;
    int rc = RTLdrLoadSystem(pszFilename, true /*fNoUnload*/, &hLdrMod);
    if (RT_SUCCESS(rc))
    {
        rc = RTLdrGetSymbol(hLdrMod, pszSymbol, &pvRet);
        if (RT_FAILURE(rc))
            pvRet = NULL; /* paranoia */
        RTLdrClose(hLdrMod);
    }
    return pvRet;
}
Example #11
0
void VBoxMMRCleanup(VBOXMMRCONTEXT *pCtx)
{
    if (pCtx->hHook)
    {
        UnhookWindowsHookEx(pCtx->hHook);
        pCtx->hHook = NULL;
    }

    if (pCtx->hModHook != NIL_RTLDRMOD)
    {
        RTLdrClose(pCtx->hModHook);
        pCtx->hModHook = NIL_RTLDRMOD;
    }
}
Example #12
0
int main(int argc, char **argv)
{
    int rcRet = 0;
    RTR3InitExe(argc, &argv, 0);

    /*
     * If no args, display usage.
     */
    if (argc <= 1)
    {
        RTPrintf("Syntax: %s [so/dll [so/dll [..]]\n", argv[0]);
        return 1;
    }

    /*
     * Iterate the arguments and treat all of them as so/dll paths.
     */
    for (int i = 1; i < argc; i++)
    {
        RTLDRMOD hLdrMod = (RTLDRMOD)0xbaadffaa;
        int rc = RTLdrLoad(argv[i], &hLdrMod);
        if (RT_SUCCESS(rc))
        {
            RTPrintf("tstLdrLoad: %d - %s\n", i, argv[i]);
            rc = RTLdrClose(hLdrMod);
            if (RT_FAILURE(rc))
            {
                RTPrintf("tstLdrLoad: rc=%Rrc RTLdrClose()\n", rc);
                rcRet++;
            }
        }
        else
        {
            RTPrintf("tstLdrLoad: rc=%Rrc RTLdrOpen('%s')\n", rc, argv[i]);
            rcRet++;
        }
    }

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

    return !!rcRet;
}
Example #13
0
void VBoxSeamlessDestroy(const VBOXSERVICEENV *pEnv, void *pInstance)
{
    Log(("VBoxTray: VBoxSeamlessDestroy\n"));

    VBoxSeamlessSetSupported(FALSE);

    /* Inform the host that we no longer support the seamless window mode. */
    if (gCtx.pfnVBoxHookRemoveWindowTracker)
        gCtx.pfnVBoxHookRemoveWindowTracker();
    if (gCtx.hModHook != NIL_RTLDRMOD)
    {
        RTLdrClose(gCtx.hModHook);
        gCtx.hModHook = NIL_RTLDRMOD;
    }
    return;
}
Example #14
0
void VBoxSeamlessDestroy(void *pInstance)
{
    LogFlowFuncEnter();

    PVBOXSEAMLESSCONTEXT pCtx = (PVBOXSEAMLESSCONTEXT)pInstance;
    AssertPtr(pCtx);

    VBoxSeamlessSetSupported(FALSE);

    /* Inform the host that we no longer support the seamless window mode. */
    if (pCtx->pfnVBoxHookRemoveWindowTracker)
        pCtx->pfnVBoxHookRemoveWindowTracker();
    if (pCtx->hModHook != NIL_RTLDRMOD)
    {
        RTLdrClose(pCtx->hModHook);
        pCtx->hModHook = NIL_RTLDRMOD;
    }
    return;
}
bool gLibHalCheckPresence(void)
{
    RTLDRMOD hLibHal;

    if (ghLibHal != 0 && gCheckedForLibHal == true)
        return true;
    if (gCheckedForLibHal == true)
        return false;
    if (!RT_SUCCESS(RTLdrLoad(LIB_HAL, &hLibHal)))
    {
        return false;
    }
    if (   RT_SUCCESS(RTLdrGetSymbol(hLibHal, "dbus_error_init", (void **) &gDBusErrorInit))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "dbus_bus_get", (void **) &gDBusBusGet))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "dbus_error_free", (void **) &gDBusErrorFree))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "dbus_connection_unref",
                                     (void **) &gDBusConnectionUnref))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_ctx_new", (void **) &gLibHalCtxNew))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_ctx_set_dbus_connection",
                                     (void **) &gLibHalCtxSetDBusConnection))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_ctx_init", (void **) &gLibHalCtxInit))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_manager_find_device_string_match",
                                     (void **) &gLibHalFindDeviceStringMatch))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_device_get_property_string",
                                     (void **) &gLibHalDeviceGetPropertyString))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_free_string", (void **) &gLibHalFreeString))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_free_string_array",
                                     (void **) &gLibHalFreeStringArray))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_ctx_shutdown", (void **) &gLibHalCtxShutdown))
        && RT_SUCCESS(RTLdrGetSymbol(hLibHal, "libhal_ctx_free", (void **) &gLibHalCtxFree))
       )
    {
        ghLibHal = hLibHal;
        gCheckedForLibHal = true;
        return true;
    }
    else
    {
        RTLdrClose(hLibHal);
        gCheckedForLibHal = true;
        return false;
    }
}
Example #16
0
int VBoxMMRInit(const VBOXSERVICEENV *pEnv, void **ppInstance, bool *pfStartThread)
{
    LogFlowFuncEnter();

    int rc = RTLdrLoadAppPriv(g_pszMMRDLL, &gCtx.hModHook);
    if (RT_SUCCESS(rc))
    {
        HOOKPROC pHook = (HOOKPROC)RTLdrGetFunction(gCtx.hModHook, g_pszMMRPROC);
        if (pHook)
        {
            HMODULE hMod = (HMODULE)RTLdrGetNativeHandle(gCtx.hModHook);
            Assert(hMod != (HMODULE)~(uintptr_t)0);
            gCtx.hHook = SetWindowsHookEx(WH_CBT, pHook, hMod, 0);
            if (gCtx.hHook)
            {
                *ppInstance = &gCtx;
                return VINF_SUCCESS;
            }

            rc = RTErrConvertFromWin32(GetLastError());
            LogFlowFunc(("Error installing hooking proc: %Rrc\n", rc));
        }
        else
        {
            LogFlowFunc(("Hooking proc not found\n"));
            rc = VERR_NOT_FOUND;
        }

        RTLdrClose(gCtx.hModHook);
        gCtx.hModHook = NIL_RTLDRMOD;
    }
    else
        LogFlowFunc(("Hooking library not found (%Rrc)\n", rc));

    return rc;
}
Example #17
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;
}
RTDECL(int) RTCrStoreCreateSnapshotById(PRTCRSTORE phStore, RTCRSTOREID enmStoreId, PRTERRINFO pErrInfo)
{
    AssertReturn(enmStoreId > RTCRSTOREID_INVALID && enmStoreId < RTCRSTOREID_END, VERR_INVALID_PARAMETER);

    /*
     * Create an empty in-memory store.
     */
    RTCRSTORE hStore;
    int rc = RTCrStoreCreateInMem(&hStore, 128);
    if (RT_SUCCESS(rc))
    {
        *phStore = hStore;

        /*
         * Resolve the APIs we need to do this job.
         */
        RTLDRMOD hLdrMod;
        int rc2 = RTLdrLoadSystem("crypt32.dll", false /*NoUnload*/, &hLdrMod);
        if (RT_SUCCESS(rc2))
        {
            PFNCERTOPENSTORE                pfnOpenStore  = NULL;
            rc2 = RTLdrGetSymbol(hLdrMod, "CertOpenStore", (void **)&pfnOpenStore);

            PFNCERTCLOSESTORE               pfnCloseStore = NULL;
            if (RT_SUCCESS(rc2))
                rc2 = RTLdrGetSymbol(hLdrMod, "CertCloseStore", (void **)&pfnCloseStore);

            PFNCERTENUMCERTIFICATESINSTORE  pfnEnumCerts  = NULL;
            if (RT_SUCCESS(rc2))
                rc2 = RTLdrGetSymbol(hLdrMod, "CertEnumCertificatesInStore", (void **)&pfnEnumCerts);
            if (RT_SUCCESS(rc2))
            {
                /*
                 * Do the work.
                 */
                switch (enmStoreId)
                {
                case RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES:
                case RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES:
                {
                    DWORD fStore = enmStoreId == RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES
                                   ? CERT_SYSTEM_STORE_CURRENT_USER : CERT_SYSTEM_STORE_LOCAL_MACHINE;
                    static PCRTUTF16 const s_apwszStores[] =  { L"AuthRoot", L"CA", L"MY", L"Root" };
                    for (uint32_t i = 0; i < RT_ELEMENTS(s_apwszStores); i++)
                        rc = rtCrStoreAddCertsFromNative(hStore, fStore, s_apwszStores[i], pfnOpenStore, pfnCloseStore,
                                                         pfnEnumCerts, rc, pErrInfo);
                    break;
                }

                default:
                    AssertFailed(); /* implement me */
                }
            }
            else
                rc = RTErrInfoSetF(pErrInfo, -rc2, "Error resolving crypt32.dll APIs");
            RTLdrClose(hLdrMod);
        }
        else
            rc = RTErrInfoSetF(pErrInfo, -rc2, "Error loading crypt32.dll");
    }
    else
        RTErrInfoSet(pErrInfo, rc, "RTCrStoreCreateInMem failed");
    return rc;
}
Example #19
0
/**
 * Resolve APIs not present on older windows versions.
 */
void VGSvcWinResolveApis(void)
{
    RTLDRMOD hLdrMod;
#define RESOLVE_SYMBOL(a_fn) do { RT_CONCAT(g_pfn, a_fn) = (decltype(a_fn) *)RTLdrGetFunction(hLdrMod, #a_fn); } while (0)

    /* From ADVAPI32.DLL: */
    int rc = RTLdrLoadSystem("advapi32.dll", true /*fNoUnload*/, &hLdrMod);
    AssertRC(rc);
    if (RT_SUCCESS(rc))
    {
        RESOLVE_SYMBOL(RegisterServiceCtrlHandlerExA);
        RESOLVE_SYMBOL(ChangeServiceConfig2A);
        RESOLVE_SYMBOL(GetNamedSecurityInfoA);
        RESOLVE_SYMBOL(SetEntriesInAclA);
        RESOLVE_SYMBOL(SetNamedSecurityInfoA);
        RESOLVE_SYMBOL(LsaNtStatusToWinError);
        RTLdrClose(hLdrMod);
    }

    /* From KERNEL32.DLL: */
    rc = RTLdrLoadSystem("kernel32.dll", true /*fNoUnload*/, &hLdrMod);
    AssertRC(rc);
    if (RT_SUCCESS(rc))
    {
        RESOLVE_SYMBOL(CreateToolhelp32Snapshot);
        RESOLVE_SYMBOL(Process32First);
        RESOLVE_SYMBOL(Process32Next);
        RESOLVE_SYMBOL(Module32First);
        RESOLVE_SYMBOL(Module32Next);
        RESOLVE_SYMBOL(GetSystemTimeAdjustment);
        RESOLVE_SYMBOL(SetSystemTimeAdjustment);
        RTLdrClose(hLdrMod);
    }

    /* From NTDLL.DLL: */
    rc = RTLdrLoadSystem("ntdll.dll", true /*fNoUnload*/, &hLdrMod);
    AssertRC(rc);
    if (RT_SUCCESS(rc))
    {
        RESOLVE_SYMBOL(ZwQuerySystemInformation);
        RTLdrClose(hLdrMod);
    }

    /* From IPHLPAPI.DLL: */
    rc = RTLdrLoadSystem("iphlpapi.dll", true /*fNoUnload*/, &hLdrMod);
    if (RT_SUCCESS(rc))
    {
        RESOLVE_SYMBOL(GetAdaptersInfo);
        RTLdrClose(hLdrMod);
    }

    /* From WS2_32.DLL: */
    rc = RTLdrLoadSystem("ws2_32.dll", true /*fNoUnload*/, &hLdrMod);
    if (RT_SUCCESS(rc))
    {
        RESOLVE_SYMBOL(WSAStartup);
        RESOLVE_SYMBOL(WSACleanup);
        RESOLVE_SYMBOL(WSASocketA);
        RESOLVE_SYMBOL(WSAIoctl);
        RESOLVE_SYMBOL(WSAGetLastError);
        RESOLVE_SYMBOL(closesocket);
        RESOLVE_SYMBOL(inet_ntoa);
        RTLdrClose(hLdrMod);
    }
}
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;
}
/**
 * One test iteration with one file.
 *
 * The test is very simple, we load the file three times
 * into two different regions. The first two into each of the
 * regions the for compare usage. The third is loaded into one
 * and then relocated between the two and other locations a few times.
 *
 * @returns number of errors.
 * @param   pszFilename     The file to load the mess with.
 */
static int testLdrOne(const char *pszFilename)
{
    RTLDRMOD hLdrMod;
    int rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_WHATEVER, &hLdrMod);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstLdr: Failed to open '%s', rc=%Rrc. aborting test.\n", pszFilename, rc);
        Assert(hLdrMod == NIL_RTLDRMOD);
        return 1;
    }

    int rcRet = 1;
    size_t cb = RTLdrSize(hLdrMod);
    if (cb > 100)
    {
        void *pvBits = RTMemAlloc(cb);
        if (pvBits)
        {
            RTUINTPTR Addr = 0xc0000000;
            rc = RTLdrGetBits(hLdrMod, pvBits, Addr, testGetImport, NULL);
            if (RT_SUCCESS(rc))
            {
                RTUINTPTR Value;
                rc = RTLdrGetSymbolEx(hLdrMod, pvBits, Addr, "Entrypoint", &Value);
                if (RT_SUCCESS(rc))
                {
                    unsigned off = Value - Addr;
                    if (off < cb)
                    {
                        DISCPUSTATE Cpu;

                        memset(&Cpu, 0, sizeof(Cpu));
                        Cpu.mode = CPUMODE_32BIT;
                        if (MyDisBlock(&Cpu, (uintptr_t)pvBits + off, 200, Addr - (uintptr_t)pvBits))
                        {
                            RTUINTPTR Addr2 = 0xd0000000;
                            rc = RTLdrRelocate(hLdrMod, pvBits, Addr2, Addr, testGetImport, NULL);
                            if (RT_SUCCESS(rc))
                            {
                                if (MyDisBlock(&Cpu, (uintptr_t)pvBits + off, 200, Addr2 - (uintptr_t)pvBits))
                                    rcRet = 0;
                                else
                                    RTPrintf("tstLdr: Disassembly failed!\n");
                            }
                            else
                                RTPrintf("tstLdr: Relocate of '%s' from %#x to %#x failed, rc=%Rrc. Aborting test.\n",
                                         pszFilename, Addr2, Addr, rc);
                        }
                        else
                            RTPrintf("tstLdr: Disassembly failed!\n");
                    }
                    else
                        RTPrintf("tstLdr: Invalid value for symbol '%s' in '%s'. off=%#x Value=%#x\n",
                                 "Entrypoint", pszFilename, off, Value);
                }
                else
                    RTPrintf("tstLdr: Failed to resolve symbol '%s' in '%s', rc=%Rrc.\n", "Entrypoint", pszFilename, rc);
            }
            else
                RTPrintf("tstLdr: Failed to get bits for '%s', rc=%Rrc. aborting test\n", pszFilename, rc);
            RTMemFree(pvBits);
        }
        else
            RTPrintf("tstLdr: Out of memory '%s' cb=%d. aborting test.\n", pszFilename, cb);
    }
    else
        RTPrintf("tstLdr: Size is odd, '%s'. aborting test.\n", pszFilename);


    /* cleanup */
    rc = RTLdrClose(hLdrMod);
    if (RT_FAILURE(rc))
    {
        RTPrintf("tstLdr: Failed to close '%s', rc=%Rrc.\n", pszFilename, rc);
        rcRet++;
    }

    return rcRet;
}
Example #22
0
/**
 * One test iteration with one file.
 *
 * The test is very simple, we load the file three times
 * into two different regions. The first two into each of the
 * regions the for compare usage. The third is loaded into one
 * and then relocated between the two and other locations a few times.
 *
 * @returns number of errors.
 * @param   pszFilename     The file to load the mess with.
 */
static int testLdrOne(const char *pszFilename)
{
    int             cErrors = 0;
    size_t          cbImage = 0;
    struct Load
    {
        RTLDRMOD    hLdrMod;
        void       *pvBits;
        size_t      cbBits;
        const char *pszName;
    }   aLoads[6] =
    {
        { NULL, NULL, 0, "foo" },
        { NULL, NULL, 0, "bar" },
        { NULL, NULL, 0, "foobar" },
        { NULL, NULL, 0, "kLdr-foo" },
        { NULL, NULL, 0, "kLdr-bar" },
        { NULL, NULL, 0, "kLdr-foobar" }
    };
    unsigned i;
    int rc;

    /*
     * Load them.
     */
    for (i = 0; i < RT_ELEMENTS(aLoads); i++)
    {
        if (!strncmp(aLoads[i].pszName, RT_STR_TUPLE("kLdr-")))
            rc = RTLdrOpenkLdr(pszFilename, 0, RTLDRARCH_WHATEVER, &aLoads[i].hLdrMod);
        else
            rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_WHATEVER, &aLoads[i].hLdrMod);
        if (RT_FAILURE(rc))
        {
            RTPrintf("tstLdr-4: Failed to open '%s'/%d, rc=%Rrc. aborting test.\n", pszFilename, i, rc);
            Assert(aLoads[i].hLdrMod == NIL_RTLDRMOD);
            cErrors++;
            break;
        }

        /* size it */
        size_t cb = RTLdrSize(aLoads[i].hLdrMod);
        if (cbImage && cb != cbImage)
        {
            RTPrintf("tstLdr-4: Size mismatch '%s'/%d. aborting test.\n", pszFilename, i);
            cErrors++;
            break;
        }
        aLoads[i].cbBits = cbImage = cb;

        /* Allocate bits. */
        aLoads[i].pvBits = RTMemExecAlloc(cb);
        if (!aLoads[i].pvBits)
        {
            RTPrintf("tstLdr-4: Out of memory '%s'/%d cbImage=%d. aborting test.\n", pszFilename, i, cbImage);
            cErrors++;
            break;
        }

        /* Get the bits. */
        rc = RTLdrGetBits(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits, testGetImport, NULL);
        if (RT_FAILURE(rc))
        {
            RTPrintf("tstLdr-4: Failed to get bits for '%s'/%d, rc=%Rrc. aborting test\n", pszFilename, i, rc);
            cErrors++;
            break;
        }
    }

    /*
     * Execute the code.
     */
    if (!cErrors)
    {
        for (i = 0; i < RT_ELEMENTS(aLoads); i += 1)
        {
            /* get the pointer. */
            RTUINTPTR Value;
            rc = RTLdrGetSymbolEx(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits,
                                  UINT32_MAX, "DisasmTest1", &Value);
            if (rc == VERR_SYMBOL_NOT_FOUND)
                rc = RTLdrGetSymbolEx(aLoads[i].hLdrMod, aLoads[i].pvBits, (uintptr_t)aLoads[i].pvBits,
                                      UINT32_MAX, "_DisasmTest1", &Value);
            if (RT_FAILURE(rc))
            {
                RTPrintf("tstLdr-4: Failed to get symbol \"DisasmTest1\" from load #%d: %Rrc\n", i, rc);
                cErrors++;
                break;
            }
            DECLCALLBACKPTR(int, pfnDisasmTest1)(void) = (DECLCALLBACKPTR(int, RT_NOTHING)(void))(uintptr_t)Value; /* eeeh. */
            RTPrintf("tstLdr-4: pfnDisasmTest1=%p / add-symbol-file %s %#x\n", pfnDisasmTest1, pszFilename, aLoads[i].pvBits);

            /* call the test function. */
            rc = pfnDisasmTest1();
            if (rc)
            {
                RTPrintf("tstLdr-4: load #%d Test1 -> %#x\n", i, rc);
                cErrors++;
            }
        }
    }


    /*
     * Clean up.
     */
    for (i = 0; i < RT_ELEMENTS(aLoads); i++)
    {
        if (aLoads[i].pvBits)
            RTMemExecFree(aLoads[i].pvBits, aLoads[i].cbBits);
        if (aLoads[i].hLdrMod)
        {
            rc = RTLdrClose(aLoads[i].hLdrMod);
            if (RT_FAILURE(rc))
            {
                RTPrintf("tstLdr-4: Failed to close '%s' i=%d, rc=%Rrc.\n", pszFilename, i, rc);
                cErrors++;
            }
        }
    }

    return cErrors;
}
/**
 * Retrieves the module name of a given process.
 *
 * @return  IPRT status code.
 * @param   pProc
 * @param   pszBuf
 * @param   cbBuf
 */
static int VBoxServiceVMInfoWinProcessesGetModuleName(PVBOXSERVICEVMINFOPROC const pProc,
                                                      TCHAR *pszName, size_t cbName)
{
    AssertPtrReturn(pProc, VERR_INVALID_POINTER);
    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
    AssertReturn(cbName, VERR_INVALID_PARAMETER);

    OSVERSIONINFOEX OSInfoEx;
    RT_ZERO(OSInfoEx);
    OSInfoEx.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
    if (   !GetVersionEx((LPOSVERSIONINFO) &OSInfoEx)
        || OSInfoEx.dwPlatformId != VER_PLATFORM_WIN32_NT)
    {
        /* Platform other than NT (e.g. Win9x) not supported. */
        return VERR_NOT_SUPPORTED;
    }

    int rc = VINF_SUCCESS;

    DWORD dwFlags = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
    if (OSInfoEx.dwMajorVersion >= 6 /* Vista or later */)
        dwFlags = 0x1000; /* = PROCESS_QUERY_LIMITED_INFORMATION; less privileges needed. */

    HANDLE h = OpenProcess(dwFlags, FALSE, pProc->id);
    if (h == NULL)
    {
        DWORD dwErr = GetLastError();
        if (g_cVerbosity)
            VBoxServiceError("Unable to open process with PID=%ld, error=%ld\n",
                             pProc->id, dwErr);
        rc = RTErrConvertFromWin32(dwErr);
    }
    else
    {
        /* Since GetModuleFileNameEx has trouble with cross-bitness stuff (32-bit apps cannot query 64-bit
           apps and vice verse) we have to use a different code path for Vista and up. */

        /* Note: For 2000 + NT4 we might just use GetModuleFileName() instead. */
        if (OSInfoEx.dwMajorVersion >= 6 /* Vista or later */)
        {
            /* Loading the module and getting the symbol for each and every process is expensive
             * -- since this function (at the moment) only is used for debugging purposes it's okay. */
            RTLDRMOD hMod;
            rc = RTLdrLoad("kernel32.dll", &hMod);
            if (RT_SUCCESS(rc))
            {
                PFNQUERYFULLPROCESSIMAGENAME pfnQueryFullProcessImageName;
                rc = RTLdrGetSymbol(hMod, "QueryFullProcessImageNameA", (void **)&pfnQueryFullProcessImageName);
                if (RT_SUCCESS(rc))
                {
                    DWORD dwLen = cbName / sizeof(TCHAR);
                    if (!pfnQueryFullProcessImageName(h, 0 /*PROCESS_NAME_NATIVE*/, pszName, &dwLen))
                        rc = VERR_ACCESS_DENIED;
                }

                RTLdrClose(hMod);
            }
        }
        else
        {
            if (!GetModuleFileNameEx(h, NULL /* Get main executable */, pszName, cbName / sizeof(TCHAR)))
                rc = VERR_ACCESS_DENIED;
        }

        CloseHandle(h);
    }

    return rc;
}