VirtualBox

Changeset 59396 in vbox for trunk/src/VBox/Runtime/r3/win


Ignore:
Timestamp:
Jan 19, 2016 3:32:03 AM (9 years ago)
Author:
vboxsync
Message:

ldrNative-win.cpp: Implemented loading system dlls from WinSxS.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/ldrNative-win.cpp

    r59394 r59396  
    3030*********************************************************************************************************************************/
    3131#define LOG_GROUP RTLOGGROUP_LDR
    32 #include <Windows.h>
     32#include <iprt/nt/nt-and-windows.h>
    3333
    3434#include <iprt/ldr.h>
     
    3737#include <iprt/alloca.h>
    3838#include <iprt/assert.h>
     39#include <iprt/ctype.h>
    3940#include <iprt/err.h>
    4041#include <iprt/file.h>
     
    170171
    171172    /*
    172      * We only try the System32 directory.
     173     * Resolve side-by-side resolver API.
    173174     */
     175    static bool volatile s_fInitialized = false;
     176    static decltype(RtlDosApplyFileIsolationRedirection_Ustr) *s_pfnApplyRedir = NULL;
     177    if (!s_fInitialized)
     178    {
     179        s_pfnApplyRedir = (decltype(s_pfnApplyRedir))GetProcAddress(g_hModNtDll,
     180                                                                    "RtlDosApplyFileIsolationRedirection_Ustr");
     181        ASMCompilerBarrier();
     182        s_fInitialized = true;
     183    }
     184
     185    /*
     186     * We try WinSxS via undocumented NTDLL API and flal back on the System32
     187     * directory. No other locations are supported.
     188     */
     189    int rc = VERR_TRY_AGAIN;
     190    char  szPath[RTPATH_MAX];
     191    char *pszPath = szPath;
     192
     193    /* Get the windows system32 directory so we can sanity check the WinSxS result. */
    174194    WCHAR wszSysDir[MAX_PATH];
    175195    UINT cwcSysDir = GetSystemDirectoryW(wszSysDir, MAX_PATH);
     
    177197        return VERR_FILENAME_TOO_LONG;
    178198
    179 /** @todo On w2k3r1/64 winhttp.dll is only found under WinSxS. Try use
    180  *        RtlDosApplyFileIsolationRedirection_Ustr to resolve this issue
    181  *        (see http-curl.cpp). */
    182 
    183     char szPath[RTPATH_MAX];
    184     char *pszPath = szPath;
    185     int rc = RTUtf16ToUtf8Ex(wszSysDir, RTSTR_MAX, &pszPath, sizeof(szPath), NULL);
     199    /* Try side-by-side first (see COMCTL32.DLL). */
     200    if (s_pfnApplyRedir)
     201    {
     202        size_t   cwcName = 0;
     203        RTUTF16  wszName[MAX_PATH];
     204        PRTUTF16 pwszName = wszName;
     205        int rc2 = RTStrToUtf16Ex(pszFilename, RTSTR_MAX, &pwszName, RT_ELEMENTS(wszName), &cwcName);
     206        if (RT_SUCCESS(rc2))
     207        {
     208            static UNICODE_STRING const s_DefaultSuffix = RTNT_CONSTANT_UNISTR(L".dll");
     209            WCHAR           wszPath[MAX_PATH];
     210            UNICODE_STRING  UniStrStatic   = { 0, (USHORT)sizeof(wszPath) - sizeof(WCHAR), wszPath };
     211            UNICODE_STRING  UniStrDynamic  = { 0, 0, NULL };
     212            PUNICODE_STRING pUniStrResult  = NULL;
     213            UNICODE_STRING  UniStrName     =
     214            { (USHORT)(cwcName * sizeof(RTUTF16)), (USHORT)((cwcName + 1) * sizeof(RTUTF16)), wszName };
     215
     216            NTSTATUS rcNt = s_pfnApplyRedir(1 /*fFlags*/,
     217                                            &UniStrName,
     218                                            (PUNICODE_STRING)&s_DefaultSuffix,
     219                                            &UniStrStatic,
     220                                            &UniStrDynamic,
     221                                            &pUniStrResult,
     222                                            NULL /*pNewFlags*/,
     223                                            NULL /*pcbFilename*/,
     224                                            NULL /*pcbNeeded*/);
     225            if (NT_SUCCESS(rcNt))
     226            {
     227                /*
     228                 * Check that the resolved path has similarities to the
     229                 * system directory.
     230                 *
     231                 * ASSUMES the windows directory is a root directory and
     232                 * that both System32 and are on the same level.  So, we'll
     233                 * have 2 matching components (or more if the resolver
     234                 * returns a system32 path for some reason).
     235                 */
     236                unsigned cMatchingComponents = 0;
     237                unsigned cSlashes = 0;
     238                size_t   off = 0;
     239                while (off < pUniStrResult->Length)
     240                {
     241                    RTUTF16 wc1 = wszSysDir[off];
     242                    RTUTF16 wc2 = pUniStrResult->Buffer[off];
     243                    if (!RTPATH_IS_SLASH(wc1))
     244                    {
     245                        if (wc1 == wc2)
     246                            off++;
     247                        else if (   wc1 < 127
     248                                 && wc2 < 127
     249                                 && RT_C_TO_LOWER(wc1) == RT_C_TO_LOWER(wc2) )
     250                            off++;
     251                        else
     252                            break;
     253                    }
     254                    else if (RTPATH_IS_SLASH(wc2))
     255                    {
     256                        cMatchingComponents += off > 0;
     257                        do
     258                            off++;
     259                        while (   off < pUniStrResult->Length
     260                               && RTPATH_IS_SLASH(wszSysDir[off])
     261                               && RTPATH_IS_SLASH(pUniStrResult->Buffer[off]));
     262                    }
     263                    else
     264                        break;
     265                }
     266                if (cMatchingComponents >= 2)
     267                {
     268                    pszPath = szPath;
     269                    rc2 = RTUtf16ToUtf8Ex(pUniStrResult->Buffer, pUniStrResult->Length / sizeof(RTUTF16),
     270                                          &pszPath, sizeof(szPath), NULL);
     271                    if (RT_SUCCESS(rc2))
     272                        rc = VINF_SUCCESS;
     273                }
     274                else
     275                    AssertMsgFailed(("%s -> '%*.ls'\n", pszFilename, pUniStrResult->Length, pUniStrResult->Buffer));
     276                RtlFreeUnicodeString(&UniStrDynamic);
     277            }
     278        }
     279        else
     280            AssertMsgFailed(("%Rrc\n", rc));
     281    }
     282
     283    /* If the above didn't succeed, create a system32 path. */
     284    if (RT_FAILURE(rc))
     285    {
     286        rc = RTUtf16ToUtf8Ex(wszSysDir, RTSTR_MAX, &pszPath, sizeof(szPath), NULL);
     287        if (RT_SUCCESS(rc))
     288        {
     289            rc = RTPathAppend(szPath, sizeof(szPath), pszFilename);
     290            if (pszExt && RT_SUCCESS(rc))
     291                rc = RTStrCat(szPath, sizeof(szPath), pszExt);
     292        }
     293    }
     294
     295    /* Do the actual loading, if we were successful constructing a name. */
    186296    if (RT_SUCCESS(rc))
    187297    {
    188         rc = RTPathAppend(szPath, sizeof(szPath), pszFilename);
    189         if (pszExt && RT_SUCCESS(rc))
    190             rc = RTStrCat(szPath, sizeof(szPath), pszExt);
    191         if (RT_SUCCESS(rc))
    192         {
    193             if (RTFileExists(szPath))
    194                 rc = RTLdrLoadEx(szPath, phLdrMod, fFlags, NULL);
    195             else
    196                 rc = VERR_MODULE_NOT_FOUND;
    197         }
     298        if (RTFileExists(szPath))
     299            rc = RTLdrLoadEx(szPath, phLdrMod, fFlags, NULL);
     300        else
     301            rc = VERR_MODULE_NOT_FOUND;
    198302    }
    199303
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette