VirtualBox

Changeset 70889 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Feb 7, 2018 12:33:10 PM (7 years ago)
Author:
vboxsync
Message:

IPRT/direnum-r3-nt.cpp: Implemented RTDIR_F_NO_FOLLOW.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp

    r70884 r70889  
    107107    bool fObjDir = false;
    108108#endif
    109     if (hRelativeDir == ~(uintptr_t)0 && pvNativeRelative == NULL)
    110     {
    111         AssertMsg(pDir->fFlags & RTDIR_F_NO_FOLLOW /* Add FILE_OPEN_REPARSE_POINT and see how that works out (it better!). Need fallbacks for pre Vista. */,
    112                   ("Implement RTDIR_F_NO_FOLLOW!\n"));
    113         rc = RTNtPathOpenDir(pszPathBuf,
    114                              FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE,
    115                              FILE_SHARE_READ | FILE_SHARE_WRITE,
    116                              FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
    117                              OBJ_CASE_INSENSITIVE,
    118                              &pDir->hDir,
    119 #ifdef IPRT_WITH_NT_PATH_PASSTHRU
    120                              &fObjDir
    121 #else
    122                              NULL
    123 #endif
    124                              );
    125     }
    126     else if (pvNativeRelative != NULL)
    127     {
    128         AssertMsg(pDir->fFlags & RTDIR_F_NO_FOLLOW /* Add FILE_OPEN_REPARSE_POINT and see how that works out (it better!). Need fallbacks for pre Vista. */,
    129                   ("Implement RTDIR_F_NO_FOLLOW!\n"));
    130         rc = RTNtPathOpenDirEx((HANDLE)hRelativeDir,
    131                                (struct _UNICODE_STRING *)pvNativeRelative,
    132                                FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE,
    133                                FILE_SHARE_READ | FILE_SHARE_WRITE,
    134                                FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
    135                                OBJ_CASE_INSENSITIVE,
    136                                &pDir->hDir,
    137 #ifdef IPRT_WITH_NT_PATH_PASSTHRU
    138                                &fObjDir
    139 #else
    140                                NULL
    141 #endif
    142 
    143                                );
    144     }
    145     else
    146     {
     109    if (hRelativeDir != ~(uintptr_t)0 && pvNativeRelative == NULL)
     110    {
     111        /* Caller already opened it, easy! */
    147112        pDir->hDir = (HANDLE)hRelativeDir;
    148113        rc = VINF_SUCCESS;
     114    }
     115    else
     116    {
     117        /*
     118         * If we have to check for reparse points, this gets complicated!
     119         */
     120        static int volatile g_fReparsePoints = -1;
     121        uint32_t            fOptions         = FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT;
     122        int fReparsePoints = g_fReparsePoints;
     123        if (fReparsePoints != 0 && (pDir->fFlags & RTDIR_F_NO_FOLLOW))
     124            fOptions |= FILE_OPEN_REPARSE_POINT;
     125
     126        for (;;)
     127        {
     128            if (pvNativeRelative == NULL)
     129                rc = RTNtPathOpenDir(pszPathBuf,
     130                                     FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE,
     131                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
     132                                     fOptions,
     133                                     OBJ_CASE_INSENSITIVE,
     134                                     &pDir->hDir,
     135#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     136                                     &fObjDir
     137#else
     138                                     NULL
     139#endif
     140                                     );
     141            else
     142                rc = RTNtPathOpenDirEx((HANDLE)hRelativeDir,
     143                                       (struct _UNICODE_STRING *)pvNativeRelative,
     144                                       FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | FILE_TRAVERSE | SYNCHRONIZE,
     145                                       FILE_SHARE_READ | FILE_SHARE_WRITE,
     146                                       fOptions,
     147                                       OBJ_CASE_INSENSITIVE,
     148                                       &pDir->hDir,
     149#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     150                                       &fObjDir
     151#else
     152                                       NULL
     153#endif
     154                                       );
     155            if (   !(fOptions & FILE_OPEN_REPARSE_POINT)
     156                || (rc != VINF_SUCCESS && rc != VERR_INVALID_PARAMETER) )
     157                break;
     158            if (rc == VINF_SUCCESS)
     159            {
     160                if (fReparsePoints == -1)
     161                    g_fReparsePoints = 1;
     162
     163                /*
     164                 * We now need to check if we opened a symbolic directory link.
     165                 * (These can be enumerated, but contains only '.' and '..'.)
     166                 */
     167                FILE_ATTRIBUTE_TAG_INFORMATION  TagInfo = { 0, 0 };
     168                IO_STATUS_BLOCK                 Ios = RTNT_IO_STATUS_BLOCK_INITIALIZER;
     169                NTSTATUS rcNt = NtQueryInformationFile(pDir->hDir, &Ios, &TagInfo, sizeof(TagInfo), FileAttributeTagInformation);
     170                AssertMsg(NT_SUCCESS(rcNt), ("%#x\n", rcNt));
     171                if (!NT_SUCCESS(rcNt))
     172                    TagInfo.FileAttributes = TagInfo.ReparseTag = 0;
     173                if (!(TagInfo.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT))
     174                    break;
     175
     176                NtClose(pDir->hDir);
     177                pDir->hDir = RTNT_INVALID_HANDLE_VALUE;
     178
     179                if (TagInfo.ReparseTag == IO_REPARSE_TAG_SYMLINK)
     180                {
     181                    rc = VERR_IS_A_SYMLINK;
     182                    break;
     183                }
     184
     185                /* Reparse point that isn't a symbolic link, try follow the reparsing. */
     186            }
     187            else if (fReparsePoints == -1)
     188                g_fReparsePoints = fReparsePoints = 0;
     189            fOptions &= ~FILE_OPEN_REPARSE_POINT;
     190        }
     191
    149192    }
    150193    if (RT_SUCCESS(rc))
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