VirtualBox

Changeset 47535 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 5, 2013 1:54:25 AM (11 years ago)
Author:
vboxsync
Message:

IPRT: Wrote native NT directory enumeration - not enabled by default. Provides ChangeTime and later file ID (inode no). Can also enumerate object directories, just for the fun of it.

Location:
trunk/src/VBox/Runtime
Files:
12 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r47534 r47535  
    595595        r3/win/allocex-win.cpp \
    596596        r3/win/dir-win.cpp \
    597         r3/win/direnum-win.cpp \
     597        $(if-expr defined(VBOX_WITH_NT_DIRENUM),r3/nt/direnum-r3-nt.cpp,r3/win/direnum-win.cpp) \
    598598        r3/win/errvars-win.cpp \
    599599        r3/win/fileio-win.cpp \
  • trunk/src/VBox/Runtime/include/internal/dir.h

    r44528 r47535  
    8484    /** The length of the converted filename. */
    8585    size_t              cchName;
     86    /** The size of this structure. */
     87    size_t              cbSelf;
    8688
    87 #ifdef RT_OS_WINDOWS
     89#ifndef RTDIR_AGNOSTIC
     90# ifdef RT_OS_WINDOWS
    8891    /** Handle to the opened directory search. */
    8992    HANDLE              hDir;
     93#  ifndef RT_USE_NATIVE_NT
    9094    /** Find data buffer.
    9195     * fDataUnread indicates valid data. */
    9296    WIN32_FIND_DATAW    Data;
    93 
    94 #else /* 'POSIX': */
     97#  else
     98    /** The size of the name buffer pszName points to. */
     99    size_t              cbNameAlloc;
     100    /** NT filter string. */
     101    UNICODE_STRING      NtFilterStr;
     102    /** Pointer to NtFilterStr if applicable, otherwise NULL. */
     103    PUNICODE_STRING     pNtFilterStr;
     104    /** The information class we're using. */
     105    FILE_INFORMATION_CLASS enmInfoClass;
     106    /** Object directory context data. */
     107    ULONG               uObjDirCtx;
     108    /** Pointer to the current data entry in the buffer. */
     109    union
     110    {
     111        /** Both file names, no file ID. */
     112        PFILE_BOTH_DIR_INFORMATION      pBoth;
     113        /** Both file names with file ID. */
     114        PFILE_ID_BOTH_DIR_INFORMATION   pBothId;
     115        /** Object directory info. */
     116        POBJECT_DIRECTORY_INFORMATION   pObjDir;
     117        /** Unsigned view. */
     118        uintptr_t                       u;
     119    }                   uCurData;
     120    /** The amount of valid data in the buffer. */
     121    uint32_t            cbBuffer;
     122    /** The allocate buffer size. */
     123    uint32_t            cbBufferAlloc;
     124    /** Find data buffer containing multiple directory entries.
     125     * fDataUnread indicates valid data. */
     126    uint8_t            *pabBuffer;
     127#  endif
     128# else /* 'POSIX': */
    95129    /** What opendir() returned. */
    96130    DIR                *pDir;
    97     /** The max size of the d_name member.
    98      * This includes the 0 terminator of course.*/
    99     size_t              cbMaxName;
    100131    /** Find data buffer.
    101132     * fDataUnread indicates valid data. */
    102133    struct dirent       Data;
     134# endif
    103135#endif
    104136} RTDIR;
     
    131163int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf);
    132164
     165/**
     166 * Returns the size of the directory structure.
     167 *
     168 * @returns The size in bytes.
     169 * @param   pszPath     The path to the directory we're about to open.
     170 */
     171size_t rtDirNativeGetStructSize(const char *pszPath);
     172
    133173#endif
  • trunk/src/VBox/Runtime/nt/RTErrConvertFromNtStatus.cpp

    r47533 r47535  
    4646        case STATUS_USER_APC:               return VERR_INTERRUPTED;
    4747
     48        case STATUS_DATATYPE_MISALIGNMENT:  return VERR_INVALID_POINTER;
     49        case STATUS_NO_MORE_FILES:          return VERR_NO_MORE_FILES;
     50        case STATUS_NO_MORE_ENTRIES:        return VERR_NO_MORE_FILES;
     51
    4852        case STATUS_INVALID_HANDLE:         return VERR_INVALID_HANDLE;
    4953        case STATUS_INVALID_PARAMETER:      return VERR_INVALID_PARAMETER;
    5054        case STATUS_INVALID_DEVICE_REQUEST: return VERR_IO_BAD_COMMAND;
    5155        case STATUS_ACCESS_DENIED:          return VERR_ACCESS_DENIED;
     56        case STATUS_OBJECT_TYPE_MISMATCH:   return VERR_UNEXPECTED_FS_OBJ_TYPE;
    5257        case STATUS_OBJECT_NAME_INVALID:    return VERR_INVALID_NAME;
    5358        case STATUS_OBJECT_NAME_NOT_FOUND:  return VERR_FILE_NOT_FOUND;
    5459        case STATUS_OBJECT_PATH_INVALID:    return VERR_INVALID_NAME;
    5560        case STATUS_OBJECT_PATH_NOT_FOUND:  return VERR_PATH_NOT_FOUND;
     61        case STATUS_BAD_NETWORK_PATH:       return VERR_NET_PATH_NOT_FOUND;
     62        case STATUS_NOT_A_DIRECTORY:        return VERR_NOT_A_DIRECTORY;
    5663    }
    5764
  • trunk/src/VBox/Runtime/r3/dir.cpp

    r46014 r47535  
    3030*******************************************************************************/
    3131#define LOG_GROUP RTLOGGROUP_DIR
    32 #ifdef RT_OS_WINDOWS /* PORTME: Assumes everyone else is using dir-posix.cpp */
    33 # include <Windows.h>
    34 #else
    35 # include <dirent.h>
    36 # include <unistd.h>
    37 # include <limits.h>
    38 #endif
    39 
    4032#include <iprt/dir.h>
    4133#include "internal/iprt.h"
     
    5042#include <iprt/string.h>
    5143#include <iprt/uni.h>
     44#define RTDIR_AGNOSTIC
    5245#include "internal/dir.h"
    5346#include "internal/path.h"
     
    571564     * thus the horrible ugliness here. Solaris uses d_name[1] for instance.
    572565     */
    573 #ifndef RT_OS_WINDOWS
    574     long cbNameMax = pathconf(szRealPath, _PC_NAME_MAX);
    575 # ifdef NAME_MAX
    576     if (cbNameMax < NAME_MAX)           /* This is plain paranoia, but it doesn't hurt. */
    577         cbNameMax = NAME_MAX;
    578 # endif
    579 # ifdef _XOPEN_NAME_MAX
    580     if (cbNameMax < _XOPEN_NAME_MAX)    /* Ditto. */
    581         cbNameMax = _XOPEN_NAME_MAX;
    582 # endif
    583     size_t cbDir = RT_OFFSETOF(RTDIR, Data.d_name[cbNameMax + 1]);
    584     if (cbDir < sizeof(RTDIR))          /* Ditto. */
    585         cbDir = sizeof(RTDIR);
    586     cbDir = RT_ALIGN_Z(cbDir, 8);
    587 #else
    588     size_t cbDir = sizeof(RTDIR);
    589 #endif
     566    size_t cbDir = rtDirNativeGetStructSize(szRealPath);
    590567    size_t const cbAllocated = cbDir
    591568                             + cucFilter0 * sizeof(RTUNICP)
    592569                             + cbFilter
    593570                             + cchRealPath + 1 + 4;
    594     PRTDIR pDir = (PRTDIR)RTMemAlloc(cbAllocated);
     571    PRTDIR pDir = (PRTDIR)RTMemAllocZ(cbAllocated);
    595572    if (!pDir)
    596573        return VERR_NO_MEMORY;
     
    599576    /* initialize it */
    600577    pDir->u32Magic = RTDIR_MAGIC;
     578    pDir->cbSelf   = cbDir;
    601579    if (cbFilter)
    602580    {
     
    639617    pDir->pszName = NULL;
    640618    pDir->cchName = 0;
    641 #ifndef RT_OS_WINDOWS
    642     pDir->cbMaxName = cbDir - RT_OFFSETOF(RTDIR, Data.d_name);
    643 #endif
    644619
    645620    /*
  • trunk/src/VBox/Runtime/r3/nt/direnum-r3-nt.cpp

    r47534 r47535  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Directory Enumeration, Windows.
     3 * IPRT - Directory Enumeration, Native NT.
    44 */
    55
     
    3030*******************************************************************************/
    3131#define LOG_GROUP RTLOGGROUP_DIR
    32 #include <Windows.h>
     32#include "internal-r3-nt.h"
    3333
    3434#include <iprt/dir.h>
     
    4444
    4545
     46/*******************************************************************************
     47*   Defined Constants And Macros                                               *
     48*******************************************************************************/
     49/** Whether to return a single record (TRUE) or multiple (FALSE)o. */
     50#define RTDIR_NT_SINGLE_RECORD  FALSE
     51
     52/** Go hard on record chaining (has slight performance impact). */
     53#ifdef RT_STRICT
     54# define RTDIR_NT_STRICT
     55#endif
     56
     57
     58/* ASSUMES FileID comes after ShortName and the structus are identical up to that point. */
     59AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, NextEntryOffset, FILE_ID_BOTH_DIR_INFORMATION, NextEntryOffset);
     60AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileIndex      , FILE_ID_BOTH_DIR_INFORMATION, FileIndex      );
     61AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, CreationTime   , FILE_ID_BOTH_DIR_INFORMATION, CreationTime   );
     62AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, LastAccessTime , FILE_ID_BOTH_DIR_INFORMATION, LastAccessTime );
     63AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, LastWriteTime  , FILE_ID_BOTH_DIR_INFORMATION, LastWriteTime  );
     64AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ChangeTime     , FILE_ID_BOTH_DIR_INFORMATION, ChangeTime     );
     65AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, EndOfFile      , FILE_ID_BOTH_DIR_INFORMATION, EndOfFile      );
     66AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, AllocationSize , FILE_ID_BOTH_DIR_INFORMATION, AllocationSize );
     67AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileAttributes , FILE_ID_BOTH_DIR_INFORMATION, FileAttributes );
     68AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, FileNameLength , FILE_ID_BOTH_DIR_INFORMATION, FileNameLength );
     69AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, EaSize         , FILE_ID_BOTH_DIR_INFORMATION, EaSize         );
     70AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ShortNameLength, FILE_ID_BOTH_DIR_INFORMATION, ShortNameLength);
     71AssertCompileMembersSameSizeAndOffset(FILE_BOTH_DIR_INFORMATION, ShortName      , FILE_ID_BOTH_DIR_INFORMATION, ShortName      );
     72
     73
     74
     75size_t rtDirNativeGetStructSize(const char *pszPath)
     76{
     77    NOREF(pszPath);
     78    return sizeof(RTDIR);
     79}
     80
     81
    4682int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
    4783{
    4884    /*
    49      * Setup the search expression.
    50      *
    51      * pszPathBuf is pointing to the return 4K return buffer for the RTPathReal()
    52      * call in rtDirOpenCommon(), so all we gota do is check that we don't overflow
    53      * it when adding the wildcard expression.
    54      */
    55     size_t cbExpr;
    56     const char *pszExpr;
    57     if (pDir->enmFilter == RTDIRFILTER_WINNT)
    58     {
    59         pszExpr = pDir->pszFilter;
    60         cbExpr  = pDir->cchFilter + 1;
    61     }
    62     else
    63     {
    64         pszExpr = "*";
    65         cbExpr  = sizeof("*");
    66     }
    67     if (pDir->cchPath + cbExpr > RTPATH_MAX)
    68         return VERR_FILENAME_TOO_LONG;
    69     memcpy(pszPathBuf + pDir->cchPath, pszExpr, cbExpr);
    70 
    71 
    72     /*
    73      * Attempt opening the search.
    74      */
    75     int rc = VINF_SUCCESS;
    76     PRTUTF16 pwszName;
    77     rc = RTStrToUtf16(pszPathBuf, &pwszName);
     85     * Convert the filter to UTF-16.
     86     */
     87    int rc;
     88    pDir->pNtFilterStr = NULL;
     89    if (   pDir->cchFilter > 0
     90        && pDir->enmFilter == RTDIRFILTER_WINNT)
     91    {
     92        PRTUTF16 pwszTmp;
     93        rc = RTStrToUtf16(pDir->pszFilter, &pwszTmp);
     94        if (RT_FAILURE(rc))
     95            return rc;
     96        pDir->NtFilterStr.Buffer = pwszTmp;
     97        pDir->NtFilterStr.Length = pDir->NtFilterStr.MaximumLength = (uint16_t)(RTUtf16Len(pwszTmp) * sizeof(RTUTF16));
     98        pDir->pNtFilterStr = &pDir->NtFilterStr;
     99    }
     100
     101    /*
     102     * Try open the directory
     103     */
     104#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     105    bool fObjDir;
     106#endif
     107    rc = rtNtPathOpenDir(pszPathBuf,
     108                         FILE_READ_DATA | SYNCHRONIZE,
     109                         FILE_SHARE_READ | FILE_SHARE_WRITE,
     110                         FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     111                         OBJ_CASE_INSENSITIVE,
     112                         &pDir->hDir,
     113#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     114                         &fObjDir
     115#else
     116                         NULL
     117#endif
     118                         );
    78119    if (RT_SUCCESS(rc))
    79120    {
    80         pDir->hDir    = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
    81         if (pDir->hDir != INVALID_HANDLE_VALUE)
    82             pDir->fDataUnread = true;
    83         else
    84         {
    85             DWORD dwErr = GetLastError();
    86             /* Theoretical case of an empty directory or more normal case of no matches. */
    87             if (   dwErr == ERROR_FILE_NOT_FOUND
    88                 || dwErr == ERROR_NO_MORE_FILES /* ???*/)
    89                 pDir->fDataUnread = false;
    90             else
    91                 rc = RTErrConvertFromWin32(GetLastError());
    92         }
    93         RTUtf16Free(pwszName);
    94     }
    95 
     121        /*
     122         * Init data.
     123         */
     124        pDir->fDataUnread = false; /* spelling it out */
     125#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     126        if (fObjDir)
     127            pDir->enmInfoClass = FileMaximumInformation; /* object directory. */
     128#endif
     129    }
    96130    return rc;
    97131}
     
    114148     * Close the handle.
    115149     */
    116     pDir->u32Magic++;
    117     if (pDir->hDir != INVALID_HANDLE_VALUE)
    118     {
    119         BOOL fRc = FindClose(pDir->hDir);
    120         Assert(fRc);
    121         pDir->hDir = INVALID_HANDLE_VALUE;
     150    pDir->u32Magic = ~RTDIR_MAGIC;
     151    if (pDir->hDir != MY_INVALID_HANDLE_VALUE)
     152    {
     153        int rc = rtNtPathClose(pDir->hDir);
     154        AssertRC(rc);
     155        pDir->hDir = MY_INVALID_HANDLE_VALUE;
    122156    }
    123157    RTStrFree(pDir->pszName);
    124158    pDir->pszName = NULL;
     159    RTUtf16Free(pDir->NtFilterStr.Buffer);
     160    pDir->NtFilterStr.Buffer = NULL;
     161    RTMemFree(pDir->pabBuffer);
     162    pDir->pabBuffer = NULL;
    125163    RTMemFree(pDir);
    126164
     
    129167
    130168
     169/**
     170 * Checks the validity of the current record.
     171 *
     172 * @returns IPRT status code
     173 * @param   pThis       The directory instance data.
     174 */
     175static int rtDirNtCheckRecord(PRTDIR pThis)
     176{
     177#ifdef RTDIR_NT_STRICT
     178# ifdef IPRT_WITH_NT_PATH_PASSTHRU
     179    if (pThis->enmInfoClass != FileMaximumInformation)
     180# endif
     181    {
     182        uintptr_t uEndAddr;
     183        if (pThis->enmInfoClass == FileIdBothDirectoryInformation)
     184            uEndAddr = (uintptr_t)&pThis->uCurData.pBothId->FileName[0];
     185        else
     186            uEndAddr = (uintptr_t)&pThis->uCurData.pBoth->FileName[0];
     187        AssertReturn(uEndAddr < (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE);
     188
     189        AssertReturn(pThis->uCurData.pBoth->FileNameLength < _64K, VERR_FILENAME_TOO_LONG);
     190        AssertReturn((pThis->uCurData.pBoth->FileNameLength & 1) == 0, VERR_IO_GEN_FAILURE);
     191
     192        uEndAddr += pThis->uCurData.pBoth->FileNameLength;
     193        AssertReturn(uEndAddr <= (uintptr_t)&pThis->pabBuffer[pThis->cbBuffer], VERR_IO_GEN_FAILURE);
     194
     195        AssertReturn((unsigned)pThis->uCurData.pBoth->ShortNameLength <= sizeof(pThis->uCurData.pBoth->ShortName),
     196                     VERR_IO_GEN_FAILURE);
     197    }
     198#endif
     199
     200    return VINF_SUCCESS;
     201}
     202
     203
     204/**
     205 * Advances the buffer pointer.
     206 *
     207 * @param   pThis       The directory instance data.
     208 */
     209static int rtDirNtAdvanceBuffer(PRTDIR pThis)
     210{
     211    int rc;
     212
     213#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     214    if (pThis->enmInfoClass == FileMaximumInformation)
     215    {
     216        pThis->uCurData.pObjDir++;
     217        pThis->fDataUnread = pThis->uCurData.pObjDir->Name.Length != 0;
     218        return VINF_SUCCESS;
     219    }
     220#endif
     221
     222    pThis->fDataUnread = false;
     223
     224    uint32_t const offNext = pThis->uCurData.pBoth->NextEntryOffset;
     225    if (offNext == 0)
     226        return VINF_SUCCESS;
     227
     228#ifdef RTDIR_NT_STRICT
     229    /* Make sure the next-record offset is beyond the current record. */
     230    size_t cbRec;
     231    if (pThis->enmInfoClass == FileIdBothDirectoryInformation)
     232        cbRec = RT_UOFFSETOF(FILE_ID_BOTH_DIR_INFORMATION, FileName);
     233    else
     234        cbRec = RT_UOFFSETOF(FILE_BOTH_DIR_INFORMATION, FileName);
     235    cbRec += pThis->uCurData.pBoth->FileNameLength;
     236    AssertReturn(offNext >= cbRec, VERR_IO_GEN_FAILURE);
     237#endif
     238    pThis->uCurData.u += offNext;
     239
     240    rc = rtDirNtCheckRecord(pThis);
     241    pThis->fDataUnread = RT_SUCCESS(rc);
     242    return rc;
     243}
     244
     245
     246/**
     247 * Fetches more data from the file system.
     248 *
     249 * @returns IPRT status code
     250 * @param   pThis       The directory instance data.
     251 */
     252static int rtDirNtFetchMore(PRTDIR pThis)
     253{
     254    Assert(!pThis->fDataUnread);
     255
     256    /*
     257     * Allocate the buffer the first time around.
     258     * We do this in lazy fashion as some users of RTDirOpen will not actually
     259     * list any files, just open it for various reasons.
     260     */
     261    bool fFirst = false;
     262    if (!pThis->pabBuffer)
     263    {
     264        fFirst = false;
     265        pThis->cbBufferAlloc = _256K;
     266        pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc);
     267        if (!pThis->pabBuffer)
     268        {
     269            do
     270            {
     271                pThis->cbBufferAlloc /= 4;
     272                pThis->pabBuffer = (uint8_t *)RTMemAlloc(pThis->cbBufferAlloc);
     273            } while (pThis->pabBuffer == NULL && pThis->cbBufferAlloc > _4K);
     274            if (!pThis->pabBuffer)
     275                return VERR_NO_MEMORY;
     276        }
     277    }
     278
     279    /*
     280     * Read more.
     281     */
     282    NTSTATUS rcNt;
     283    IO_STATUS_BLOCK Ios = MY_IO_STATUS_BLOCK_INITIALIZER;
     284    if (pThis->enmInfoClass != (FILE_INFORMATION_CLASS)0)
     285    {
     286#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     287        if (pThis->enmInfoClass == FileMaximumInformation)
     288        {
     289            Ios.Information = 0;
     290            Ios.Status = rcNt = NtQueryDirectoryObject(pThis->hDir,
     291                                                       pThis->pabBuffer,
     292                                                       pThis->cbBufferAlloc,
     293                                                       RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
     294                                                       FALSE /*RestartScan*/,
     295                                                       &pThis->uObjDirCtx,
     296                                                       (PULONG)&Ios.Information);
     297        }
     298        else
     299#endif
     300            rcNt = NtQueryDirectoryFile(pThis->hDir,
     301                                        NULL /* Event */,
     302                                        NULL /* ApcRoutine */,
     303                                        NULL /* ApcContext */,
     304                                        &Ios,
     305                                        pThis->pabBuffer,
     306                                        pThis->cbBufferAlloc,
     307                                        pThis->enmInfoClass,
     308                                        RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
     309                                        pThis->pNtFilterStr,
     310                                        FALSE /*RestartScan */);
     311    }
     312    else
     313    {
     314        /*
     315         * The first time around we have figure which info class we can use.
     316         * We prefer one which gives us file IDs, but we'll settle for less.
     317         */
     318        pThis->enmInfoClass = FileIdBothDirectoryInformation;
     319        rcNt = NtQueryDirectoryFile(pThis->hDir,
     320                                    NULL /* Event */,
     321                                    NULL /* ApcRoutine */,
     322                                    NULL /* ApcContext */,
     323                                    &Ios,
     324                                    pThis->pabBuffer,
     325                                    pThis->cbBufferAlloc,
     326                                    pThis->enmInfoClass,
     327                                    RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
     328                                    pThis->pNtFilterStr,
     329                                    FALSE /*RestartScan */);
     330        if (!NT_SUCCESS(rcNt))
     331        {
     332            pThis->enmInfoClass = FileBothDirectoryInformation;
     333            rcNt = NtQueryDirectoryFile(pThis->hDir,
     334                                        NULL /* Event */,
     335                                        NULL /* ApcRoutine */,
     336                                        NULL /* ApcContext */,
     337                                        &Ios,
     338                                        pThis->pabBuffer,
     339                                        pThis->cbBufferAlloc,
     340                                        pThis->enmInfoClass,
     341                                        RTDIR_NT_SINGLE_RECORD /*ReturnSingleEntry */,
     342                                        pThis->pNtFilterStr,
     343                                        FALSE /*RestartScan */);
     344        }
     345    }
     346    if (!NT_SUCCESS(rcNt))
     347    {
     348        if (rcNt == STATUS_NO_MORE_FILES || rcNt == STATUS_NO_MORE_ENTRIES)
     349            return VERR_NO_MORE_FILES;
     350        return RTErrConvertFromNtStatus(rcNt);
     351    }
     352    Assert(Ios.Information > sizeof(*pThis->uCurData.pBoth));
     353
     354    /*
     355     * Set up the data members.
     356     */
     357    pThis->uCurData.u  = (uintptr_t)pThis->pabBuffer;
     358    pThis->cbBuffer    = Ios.Information;
     359
     360    int rc = rtDirNtCheckRecord(pThis);
     361    pThis->fDataUnread = RT_SUCCESS(rc);
     362
     363    return rc;
     364}
     365
     366
     367/**
     368 * Converts the name from UTF-16 to UTF-8.
     369 *
     370 * Fortunately, the names are relative to the directory, so we won't have to do
     371 * any sweaty path style coversion. :-)
     372 *
     373 * @returns IPRT status code
     374 * @param   pThis       The directory instance data.
     375 * @param   cbName      The file name length in bytes.
     376 * @param   pwsName     The file name, not terminated.
     377 */
     378static int rtDirNtConvertName(PRTDIR pThis, uint32_t cbName, PCRTUTF16 pwsName)
     379{
     380    int rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName);
     381    if (RT_SUCCESS(rc))
     382    {
     383        if (!pThis->cbNameAlloc)
     384            pThis->cbNameAlloc = pThis->cchName + 1;
     385    }
     386    else if (rc == VERR_BUFFER_OVERFLOW)
     387    {
     388        RTStrFree(pThis->pszName);
     389        pThis->pszName = NULL;
     390        pThis->cbNameAlloc = 0;
     391
     392        rc = RTUtf16ToUtf8Ex(pwsName, cbName / 2, &pThis->pszName, pThis->cbNameAlloc, &pThis->cchName);
     393        if (RT_SUCCESS(rc))
     394            pThis->cbNameAlloc = pThis->cchName + 1;
     395    }
     396    Assert(RT_SUCCESS(rc) ? pThis->pszName != NULL : pThis->pszName == NULL);
     397    return rc;
     398}
     399
     400
     401/**
     402 * Converts the name of the current record.
     403 *
     404 * @returns IPRT status code.
     405 * @param   pThis       The directory instance data.
     406 */
     407static int rtDirNtConvertCurName(PRTDIR pThis)
     408{
     409    switch (pThis->enmInfoClass)
     410    {
     411        case FileIdBothDirectoryInformation:
     412            return rtDirNtConvertName(pThis, pThis->uCurData.pBothId->FileNameLength, pThis->uCurData.pBothId->FileName);
     413        case FileBothDirectoryInformation:
     414            return rtDirNtConvertName(pThis, pThis->uCurData.pBoth->FileNameLength, pThis->uCurData.pBoth->FileName);
     415#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     416        case FileMaximumInformation:
     417            return rtDirNtConvertName(pThis, pThis->uCurData.pObjDir->Name.Length, pThis->uCurData.pObjDir->Name.Buffer);
     418#endif
     419
     420        default:
     421            AssertFailedReturn(VERR_INTERNAL_ERROR_3);
     422    }
     423}
     424
     425
    131426RTDECL(int) RTDirRead(PRTDIR pDir, PRTDIRENTRY pDirEntry, size_t *pcbDirEntry)
    132427{
     428    int rc;
     429
    133430    /*
    134431     * Validate input.
    135432     */
    136     if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
    137     {
    138         AssertMsgFailed(("Invalid pDir=%p\n", pDir));
    139         return VERR_INVALID_PARAMETER;
    140     }
    141     if (!pDirEntry)
    142     {
    143         AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
    144         return VERR_INVALID_PARAMETER;
    145     }
     433    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
     434    AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
     435    AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER);
    146436    size_t cbDirEntry = sizeof(*pDirEntry);
    147437    if (pcbDirEntry)
    148438    {
    149439        cbDirEntry = *pcbDirEntry;
    150         if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRY, szName[2]))
    151         {
    152             AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])));
    153             return VERR_INVALID_PARAMETER;
    154         }
     440        AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRY, szName[2]),
     441                        ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRY, szName[2])),
     442                        VERR_INVALID_PARAMETER);
    155443    }
    156444
     
    160448    if (!pDir->fDataUnread)
    161449    {
    162         RTStrFree(pDir->pszName);
    163         pDir->pszName = NULL;
    164 
    165         BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
    166         if (!fRc)
    167         {
    168             int iErr = GetLastError();
    169             if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
    170                 return VERR_NO_MORE_FILES;
    171             return RTErrConvertFromWin32(iErr);
    172         }
     450        rc = rtDirNtFetchMore(pDir);
     451        if (RT_FAILURE(rc))
     452            return rc;
    173453    }
    174454
     
    176456     * Convert the filename to UTF-8.
    177457     */
    178     if (!pDir->pszName)
    179     {
    180         int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
    181         if (RT_FAILURE(rc))
    182         {
    183             pDir->pszName = NULL;
    184             return rc;
    185         }
    186         pDir->cchName = strlen(pDir->pszName);
    187     }
     458    rc = rtDirNtConvertCurName(pDir);
     459    if (RT_FAILURE(rc))
     460        return rc;
    188461
    189462    /*
     
    201474     * Setup the returned data.
    202475     */
    203     pDir->fDataUnread  = false;
    204     pDirEntry->INodeId = 0; /** @todo we can use the fileid here if we must (see GetFileInformationByHandle). */
    205     pDirEntry->enmType = pDir->Data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
    206                        ? RTDIRENTRYTYPE_DIRECTORY : RTDIRENTRYTYPE_FILE;
    207     pDirEntry->cbName  = (uint16_t)cchName;
    208     Assert(pDirEntry->cbName == cchName);
     476    pDirEntry->cbName = (uint16_t)cchName; Assert(pDirEntry->cbName == cchName);
    209477    memcpy(pDirEntry->szName, pszName, cchName + 1);
    210478
    211     return VINF_SUCCESS;
    212 }
    213 
    214 
    215 RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry, RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
    216 {
    217     /** @todo Symlinks: Find[First|Next]FileW will return info about
    218         the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
     479    pDirEntry->INodeId = pDir->enmInfoClass == FileIdBothDirectoryInformation
     480                       ? pDir->uCurData.pBothId->FileId.QuadPart : 0;
     481
     482#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     483    if (pDir->enmInfoClass != FileMaximumInformation)
     484#endif
     485    {
     486        switch (   pDir->uCurData.pBoth->FileAttributes
     487                & (FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY))
     488        {
     489            default:
     490                AssertFailed();
     491            case 0:
     492                pDirEntry->enmType = RTDIRENTRYTYPE_FILE;
     493                break;
     494
     495            case FILE_ATTRIBUTE_DIRECTORY:
     496                pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY;
     497                break;
     498
     499            case FILE_ATTRIBUTE_REPARSE_POINT:
     500            case FILE_ATTRIBUTE_REPARSE_POINT | FILE_ATTRIBUTE_DIRECTORY:
     501                pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK;
     502                break;
     503        }
     504    }
     505#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     506    else
     507    {
     508        pDirEntry->enmType = RTDIRENTRYTYPE_UNKNOWN;
     509        if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
     510                                    RT_STR_TUPLE("Directory")))
     511            pDirEntry->enmType = RTDIRENTRYTYPE_DIRECTORY;
     512        else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
     513                                         RT_STR_TUPLE("SymbolicLink")))
     514            pDirEntry->enmType = RTDIRENTRYTYPE_SYMLINK;
     515    }
     516#endif
     517
     518    return rtDirNtAdvanceBuffer(pDir);
     519}
     520
     521
     522RTDECL(int) RTDirReadEx(PRTDIR pDir, PRTDIRENTRYEX pDirEntry, size_t *pcbDirEntry,
     523                        RTFSOBJATTRADD enmAdditionalAttribs, uint32_t fFlags)
     524{
     525    int rc;
     526
    219527    /*
    220528     * Validate input.
    221529     */
    222     if (!pDir || pDir->u32Magic != RTDIR_MAGIC)
    223     {
    224         AssertMsgFailed(("Invalid pDir=%p\n", pDir));
    225         return VERR_INVALID_PARAMETER;
    226     }
    227     if (!pDirEntry)
    228     {
    229         AssertMsgFailed(("Invalid pDirEntry=%p\n", pDirEntry));
    230         return VERR_INVALID_PARAMETER;
    231     }
    232     if (    enmAdditionalAttribs < RTFSOBJATTRADD_NOTHING
    233         ||  enmAdditionalAttribs > RTFSOBJATTRADD_LAST)
    234     {
    235         AssertMsgFailed(("Invalid enmAdditionalAttribs=%p\n", enmAdditionalAttribs));
    236         return VERR_INVALID_PARAMETER;
    237     }
     530    AssertPtrReturn(pDir, VERR_INVALID_POINTER);
     531    AssertReturn(pDir->u32Magic == RTDIR_MAGIC, VERR_INVALID_HANDLE);
     532    AssertPtrReturn(pDirEntry, VERR_INVALID_POINTER);
     533
     534    AssertReturn(enmAdditionalAttribs >= RTFSOBJATTRADD_NOTHING && enmAdditionalAttribs <= RTFSOBJATTRADD_LAST,
     535                 VERR_INVALID_PARAMETER);
    238536    AssertMsgReturn(RTPATH_F_IS_VALID(fFlags, 0), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     537
    239538    size_t cbDirEntry = sizeof(*pDirEntry);
    240539    if (pcbDirEntry)
    241540    {
    242541        cbDirEntry = *pcbDirEntry;
    243         if (cbDirEntry < RT_UOFFSETOF(RTDIRENTRYEX, szName[2]))
    244         {
    245             AssertMsgFailed(("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])));
    246             return VERR_INVALID_PARAMETER;
    247         }
     542        AssertMsgReturn(cbDirEntry >= RT_UOFFSETOF(RTDIRENTRYEX, szName[2]),
     543                        ("Invalid *pcbDirEntry=%d (min %d)\n", *pcbDirEntry, RT_OFFSETOF(RTDIRENTRYEX, szName[2])),
     544                        VERR_INVALID_PARAMETER);
    248545    }
    249546
     
    253550    if (!pDir->fDataUnread)
    254551    {
    255         RTStrFree(pDir->pszName);
    256         pDir->pszName = NULL;
    257 
    258         BOOL fRc = FindNextFileW(pDir->hDir, &pDir->Data);
    259         if (!fRc)
    260         {
    261             int iErr = GetLastError();
    262             if (pDir->hDir == INVALID_HANDLE_VALUE || iErr == ERROR_NO_MORE_FILES)
    263                 return VERR_NO_MORE_FILES;
    264             return RTErrConvertFromWin32(iErr);
    265         }
     552        rc = rtDirNtFetchMore(pDir);
     553        if (RT_FAILURE(rc))
     554            return rc;
    266555    }
    267556
     
    269558     * Convert the filename to UTF-8.
    270559     */
    271     if (!pDir->pszName)
    272     {
    273         int rc = RTUtf16ToUtf8((PCRTUTF16)pDir->Data.cFileName, &pDir->pszName);
    274         if (RT_FAILURE(rc))
    275         {
    276             pDir->pszName = NULL;
    277             return rc;
    278         }
    279         pDir->cchName = strlen(pDir->pszName);
    280     }
     560    rc = rtDirNtConvertCurName(pDir);
     561    if (RT_FAILURE(rc))
     562        return rc;
    281563
    282564    /*
     
    294576     * Setup the returned data.
    295577     */
    296     pDir->fDataUnread  = false;
    297     pDirEntry->cbName  = (uint16_t)cchName;
    298     Assert(pDirEntry->cbName == cchName);
     578    PFILE_BOTH_DIR_INFORMATION pBoth = pDir->uCurData.pBoth;
     579
     580    pDirEntry->cbName  = (uint16_t)cchName;  Assert(pDirEntry->cbName == cchName);
    299581    memcpy(pDirEntry->szName, pszName, cchName + 1);
    300     if (pDir->Data.cAlternateFileName[0])
    301     {
    302         /* copy and calc length */
    303         PCRTUTF16 pwszSrc = (PCRTUTF16)pDir->Data.cAlternateFileName;
    304         PRTUTF16  pwszDst = pDirEntry->wszShortName;
    305         uint32_t  off = 0;
    306         while (pwszSrc[off] && off < RT_ELEMENTS(pDirEntry->wszShortName) - 1U)
     582    memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
     583#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     584    if (pDir->enmInfoClass != FileMaximumInformation)
     585#endif
     586    {
     587        uint8_t cbShort = pBoth->ShortNameLength;
     588        if (cbShort > 0)
    307589        {
    308             pwszDst[off] = pwszSrc[off];
    309             off++;
     590            AssertStmt(cbShort < sizeof(pDirEntry->wszShortName), cbShort = sizeof(pDirEntry->wszShortName) - 2);
     591            memcpy(pDirEntry->wszShortName, pBoth->ShortName, cbShort);
     592            pDirEntry->cwcShortName = cbShort / 2;
    310593        }
    311         pDirEntry->cwcShortName = (uint16_t)off;
    312 
    313         /* zero the rest */
    314         do
    315             pwszDst[off++] = '\0';
    316         while (off < RT_ELEMENTS(pDirEntry->wszShortName));
    317     }
     594        else
     595            pDirEntry->cwcShortName = 0;
     596
     597        pDirEntry->Info.cbObject    = pBoth->EndOfFile.QuadPart;
     598        pDirEntry->Info.cbAllocated = pBoth->AllocationSize.QuadPart;
     599
     600        Assert(sizeof(uint64_t) == sizeof(pBoth->CreationTime));
     601        RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime,         pBoth->CreationTime.QuadPart);
     602        RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime,        pBoth->LastAccessTime.QuadPart);
     603        RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime,  pBoth->LastWriteTime.QuadPart);
     604        RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime,        pBoth->ChangeTime.QuadPart);
     605
     606        pDirEntry->Info.Attr.fMode  = rtFsModeFromDos((pBoth->FileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
     607                                                       pszName, cchName);
     608    }
     609#ifdef IPRT_WITH_NT_PATH_PASSTHRU
    318610    else
    319611    {
    320         memset(pDirEntry->wszShortName, 0, sizeof(pDirEntry->wszShortName));
    321612        pDirEntry->cwcShortName = 0;
    322     }
    323 
    324     pDirEntry->Info.cbObject    = ((uint64_t)pDir->Data.nFileSizeHigh << 32)
    325                                 |  (uint64_t)pDir->Data.nFileSizeLow;
    326     pDirEntry->Info.cbAllocated = pDirEntry->Info.cbObject;
    327 
    328     Assert(sizeof(uint64_t) == sizeof(pDir->Data.ftCreationTime));
    329     RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime,         *(uint64_t *)&pDir->Data.ftCreationTime);
    330     RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime,        *(uint64_t *)&pDir->Data.ftLastAccessTime);
    331     RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime,  *(uint64_t *)&pDir->Data.ftLastWriteTime);
    332     pDirEntry->Info.ChangeTime  = pDirEntry->Info.ModificationTime;
    333 
    334     pDirEntry->Info.Attr.fMode  = rtFsModeFromDos((pDir->Data.dwFileAttributes << RTFS_DOS_SHIFT) & RTFS_DOS_MASK_NT,
    335                                                    pszName, cchName);
     613        pDirEntry->Info.cbObject    = 0;
     614        pDirEntry->Info.cbAllocated = 0;
     615        RTTimeSpecSetNtTime(&pDirEntry->Info.BirthTime,         0);
     616        RTTimeSpecSetNtTime(&pDirEntry->Info.AccessTime,        0);
     617        RTTimeSpecSetNtTime(&pDirEntry->Info.ModificationTime,  0);
     618        RTTimeSpecSetNtTime(&pDirEntry->Info.ChangeTime,        0);
     619
     620        if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
     621                                    RT_STR_TUPLE("Directory")))
     622            pDirEntry->Info.Attr.fMode = RTFS_DOS_DIRECTORY | RTFS_TYPE_DIRECTORY | 0777;
     623        else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
     624                                         RT_STR_TUPLE("SymbolicLink")))
     625            pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_REPARSE_POINT | RTFS_TYPE_SYMLINK | 0777;
     626        else if (rtNtCompWideStrAndAscii(pDir->uCurData.pObjDir->TypeName.Buffer, pDir->uCurData.pObjDir->TypeName.Length,
     627                                         RT_STR_TUPLE("Device")))
     628            pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_DEVICE | RTFS_TYPE_DEV_CHAR | 0666;
     629        else
     630            pDirEntry->Info.Attr.fMode = RTFS_DOS_NT_NORMAL | RTFS_TYPE_FILE | 0666;
     631    }
     632#endif
    336633
    337634    /*
     
    342639        case RTFSOBJATTRADD_EASIZE:
    343640            pDirEntry->Info.Attr.enmAdditional          = RTFSOBJATTRADD_EASIZE;
    344             pDirEntry->Info.Attr.u.EASize.cb            = 0;
     641#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     642            if (pDir->enmInfoClass == FileMaximumInformation)
     643                pDirEntry->Info.Attr.u.EASize.cb        = 0;
     644            else
     645#endif
     646                pDirEntry->Info.Attr.u.EASize.cb        = pBoth->EaSize;
    345647            break;
    346648
     
    378680    }
    379681
    380     return VINF_SUCCESS;
    381 }
    382 
     682    /*
     683     * Follow links if requested.
     684     */
     685    if (   (fFlags & RTPATH_F_FOLLOW_LINK)
     686        && RTFS_IS_SYMLINK(fFlags))
     687    {
     688        /** @todo Symlinks: Find[First|Next]FileW will return info about
     689            the link, so RTPATH_F_FOLLOW_LINK is not handled correctly. */
     690    }
     691
     692    /*
     693     * Finally advance the buffer.
     694     */
     695    return rtDirNtAdvanceBuffer(pDir);
     696}
     697
  • trunk/src/VBox/Runtime/r3/nt/fs-nt.cpp

    r47533 r47535  
    226226
    227227
    228 /**
    229  * Internal helper for comparing a WCHAR string with a char string.
    230  *
    231  * @returns @c true if equal, @c false if not.
    232  * @param   pwsz1               The first string.
    233  * @param   cb1                 The length of the first string, in bytes.
    234  * @param   psz2                The second string.
    235  * @param   cch2                The length of the second string.
    236  */
    237 static bool rtFsCompWideStrAndAscii(WCHAR const *pwsz1, size_t cch1, const char *psz2, size_t cch2)
    238 {
    239     if (cch1 != cch2 * 2)
    240         return false;
    241     while (cch2-- > 0)
    242     {
    243         unsigned ch1 = *pwsz1++;
    244         unsigned ch2 = (unsigned char)*psz2++;
    245         if (ch1 != ch2)
    246             return false;
    247     }
    248     return true;
    249 }
    250 
    251228
    252229RTR3DECL(int) RTFsQueryType(const char *pszFsPath, PRTFSTYPE penmType)
     
    287264        {
    288265#define IS_FS(a_szName) \
    289 rtFsCompWideStrAndAscii(u.FsAttrInfo.FileSystemName, u.FsAttrInfo.FileSystemNameLength, RT_STR_TUPLE(a_szName))
     266    rtNtCompWideStrAndAscii(u.FsAttrInfo.FileSystemName, u.FsAttrInfo.FileSystemNameLength, RT_STR_TUPLE(a_szName))
    290267            if (IS_FS("NTFS"))
    291268                *penmType = RTFSTYPE_NTFS;
  • trunk/src/VBox/Runtime/r3/nt/internal-r3-nt.h

    r47533 r47535  
    4848# include <ntifs.h>
    4949#endif
     50#include "internal/iprt.h"
    5051
    5152
     
    5354*   Defined Constants And Macros                                               *
    5455*******************************************************************************/
     56/** Indicates that we're targetting native NT in the current source. */
     57#define RT_USE_NATIVE_NT                1
    5558/** Initializes a IO_STATUS_BLOCK. */
    5659#define MY_IO_STATUS_BLOCK_INITIALIZER  { STATUS_FAILED_DRIVER_ENTRY, ~(uintptr_t)42 }
    5760/** Similar to INVALID_HANDLE_VALUE in the Windows environment. */
    5861#define MY_INVALID_HANDLE_VALUE         ( (HANDLE)~(uintptr_t)0 )
     62
     63#ifdef DEBUG_bird
     64/** Enables the "\\!\" NT path pass thru as well as hacks for listing NT object
     65 * directories. */
     66# define IPRT_WITH_NT_PATH_PASSTHRU 1
     67#endif
    5968
    6069
     
    6574                  ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
    6675                  PHANDLE phHandle, PULONG_PTR puDisposition);
     76int  rtNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions,
     77                     ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir);
    6778int  rtNtPathClose(HANDLE hHandle);
     79
     80
     81/**
     82 * Internal helper for comparing a WCHAR string with a char string.
     83 *
     84 * @returns @c true if equal, @c false if not.
     85 * @param   pwsz1               The first string.
     86 * @param   cb1                 The length of the first string, in bytes.
     87 * @param   psz2                The second string.
     88 * @param   cch2                The length of the second string.
     89 */
     90DECLINLINE(bool) rtNtCompWideStrAndAscii(WCHAR const *pwsz1, size_t cch1, const char *psz2, size_t cch2)
     91{
     92    if (cch1 != cch2 * 2)
     93        return false;
     94    while (cch2-- > 0)
     95    {
     96        unsigned ch1 = *pwsz1++;
     97        unsigned ch2 = (unsigned char)*psz2++;
     98        if (ch1 != ch2)
     99            return false;
     100    }
     101    return true;
     102}
    68103
    69104
     
    71106*   NT APIs                                                                    *
    72107*******************************************************************************/
     108
     109RT_C_DECLS_BEGIN
    73110
    74111#ifdef IPRT_NT_NEED_API_GROUP_1
     
    86123#endif
    87124
     125NTSTATUS NTAPI NtOpenDirectoryObject(PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES);
     126
     127typedef struct _OBJECT_DIRECTORY_INFORMATION
     128{
     129    UNICODE_STRING Name;
     130    UNICODE_STRING TypeName;
     131} OBJECT_DIRECTORY_INFORMATION;
     132typedef OBJECT_DIRECTORY_INFORMATION *POBJECT_DIRECTORY_INFORMATION;
     133
     134NTSTATUS NTAPI NtQueryDirectoryObject(HANDLE, PVOID, ULONG, BOOLEAN, BOOLEAN, PULONG, PULONG);
     135
     136
     137RT_C_DECLS_END
    88138
    89139#endif
  • trunk/src/VBox/Runtime/r3/nt/pathint-nt.cpp

    r47533 r47535  
    4747 * @param   pszPath             The UTF-8 path.
    4848 */
    49 static int rtNtPathToNativePassThru(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
    50 {
    51     PRTUTF16 pwszPath;
    52     int rc = RTStrToUtf16(pszPath + 1, &pwszPath);
     49static int rtNtPathToNativePassThruWin(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
     50{
     51    PRTUTF16 pwszPath = NULL;
     52    size_t   cwcLen;
     53    int rc = RTStrToUtf16Ex(pszPath + 1, RTSTR_MAX, &pwszPath, 0, &cwcLen);
    5354    if (RT_SUCCESS(rc))
    5455    {
    55         pwszPath[0] = '\\';
    56         pwszPath[1] = '.';
    57         pwszPath[2] = '\\';
    58 
    59         size_t cwcLen = RTUtf16Len(pwszPath);
    6056        if (cwcLen < _32K - 1)
    6157        {
     58            pwszPath[0] = '\\';
     59            pwszPath[1] = '.';
     60            pwszPath[2] = '\\';
     61
    6262            pNtName->Buffer = pwszPath;
    63             pNtName->MaximumLength = pNtName->Length = (uint16_t)((cwcLen + 0) * 2);
     63            pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2);
     64            *phRootDir = NULL;
     65            return VINF_SUCCESS;
     66        }
     67
     68        RTUtf16Free(pwszPath);
     69        rc = VERR_FILENAME_TOO_LONG;
     70    }
     71    return rc;
     72}
     73
     74
     75/**
     76 * Converts the path to UTF-16 and sets all the return values.
     77 *
     78 * @returns IPRT status code.
     79 * @param   pNtName             Where to return the NT name.
     80 * @param   phRootDir           Where to return the root handle, if applicable.
     81 * @param   pszPath             The UTF-8 path.
     82 */
     83static int rtNtPathToNativeToUtf16(struct _UNICODE_STRING *pNtName, PHANDLE phRootDir, const char *pszPath)
     84{
     85    PRTUTF16 pwszPath = NULL;
     86    size_t   cwcLen;
     87    int rc = RTStrToUtf16Ex(pszPath, RTSTR_MAX, &pwszPath, 0, &cwcLen);
     88    if (RT_SUCCESS(rc))
     89    {
     90        if (cwcLen < _32K - 1)
     91        {
     92            pNtName->Buffer = pwszPath;
     93            pNtName->MaximumLength = pNtName->Length = (uint16_t)(cwcLen * 2);
    6494            *phRootDir = NULL;
    6595            return VINF_SUCCESS;
     
    100130        if (   pszPath[2] == '?'
    101131            && RTPATH_IS_SLASH(pszPath[3]))
    102             return rtNtPathToNativePassThru(pNtName, phRootDir, pszPath);
     132            return rtNtPathToNativePassThruWin(pNtName, phRootDir, pszPath);
     133
     134#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     135        /* Special hack: The path starts with "\\\\!\\", we will skip past the bang and pass it thru. */
     136        if (   pszPath[2] == '!'
     137            && RTPATH_IS_SLASH(pszPath[3]))
     138            return rtNtPathToNativeToUtf16(pNtName, phRootDir, pszPath + 3);
     139#endif
    103140
    104141        if (   pszPath[2] == '.'
     
    132169     */
    133170    memcpy(szPath, pszPrefix, cchPrefix);
    134     PRTUTF16 pwszPath;
    135     rc = RTStrToUtf16(szPath, &pwszPath);
    136     if (RT_FAILURE(rc))
    137         return rc;
    138 
    139     size_t cwcLen = RTUtf16Len(pwszPath);
    140     if (cwcLen >= _32K - 1)
    141     {
    142         RTUtf16Free(pwszPath);
    143         return VERR_FILENAME_TOO_LONG;
    144     }
    145 
    146     /*
    147      * Success.
    148      */
    149     pNtName->Buffer = pwszPath;
    150     pNtName->MaximumLength = pNtName->Length = (uint16_t)((cwcLen + 0) * 2);
    151     *phRootDir = NULL;
    152     return VINF_SUCCESS;
     171    return rtNtPathToNativeToUtf16(pNtName, phRootDir, szPath);
    153172}
    154173
     
    227246
    228247/**
     248 * Wrapper around NtCreateFile.
     249 *
     250 * @returns IPRT status code.
     251 * @param   pszPath             The UTF-8 path.
     252 * @param   fDesiredAccess      See NtCreateFile.
     253 * @param   fFileAttribs        See NtCreateFile.
     254 * @param   fShareAccess        See NtCreateFile.
     255 * @param   fCreateDisposition  See NtCreateFile.
     256 * @param   fCreateOptions      See NtCreateFile.
     257 * @param   fObjAttribs         The OBJECT_ATTRIBUTES::Attributes value, see
     258 *                              NtCreateFile and InitializeObjectAttributes.
     259 * @param   phHandle            Where to return the handle.
     260 * @param   pfObjDir            If not NULL, the variable pointed to will be set
     261 *                              to @c true if we opened an object directory and
     262 *                              @c false if we opened an directory file (normal
     263 *                              directory).
     264 */
     265int  rtNtPathOpenDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fShareAccess, ULONG fCreateOptions,
     266                     ULONG fObjAttribs, PHANDLE phHandle, bool *pfObjDir)
     267{
     268    *phHandle = MY_INVALID_HANDLE_VALUE;
     269
     270    HANDLE         hRootDir;
     271    UNICODE_STRING NtName;
     272    int rc = rtNtPathToNative(&NtName, &hRootDir, pszPath);
     273    if (RT_SUCCESS(rc))
     274    {
     275        HANDLE              hFile = MY_INVALID_HANDLE_VALUE;
     276        IO_STATUS_BLOCK     Ios   = MY_IO_STATUS_BLOCK_INITIALIZER;
     277        OBJECT_ATTRIBUTES   ObjAttr;
     278        InitializeObjectAttributes(&ObjAttr, &NtName, fObjAttribs, hRootDir, NULL);
     279
     280        NTSTATUS rcNt = NtCreateFile(&hFile,
     281                                     fDesiredAccess,
     282                                     &ObjAttr,
     283                                     &Ios,
     284                                     NULL /* AllocationSize*/,
     285                                     FILE_ATTRIBUTE_NORMAL,
     286                                     fShareAccess,
     287                                     FILE_OPEN,
     288                                     fCreateOptions,
     289                                     NULL /*EaBuffer*/,
     290                                     0 /*EaLength*/);
     291        if (NT_SUCCESS(rcNt))
     292        {
     293            if (pfObjDir)
     294                *pfObjDir = false;
     295            *phHandle = hFile;
     296            rc = VINF_SUCCESS;
     297        }
     298#ifdef IPRT_WITH_NT_PATH_PASSTHRU
     299        else if (   pfObjDir
     300                 && (rcNt == STATUS_OBJECT_NAME_INVALID || rcNt == STATUS_OBJECT_TYPE_MISMATCH)
     301                 && RTPATH_IS_SLASH(pszPath[0])
     302                 && RTPATH_IS_SLASH(pszPath[1])
     303                 && pszPath[2] == '!'
     304                 && RTPATH_IS_SLASH(pszPath[3]))
     305        {
     306            /* Strip trailing slash. */
     307            if (   NtName.Length > 2
     308                && RTPATH_IS_SLASH(NtName.Buffer[(NtName.Length / 2) - 1]))
     309                NtName.Length -= 2;
     310
     311            /* Rought conversion of the access flags. */
     312            ULONG fObjDesiredAccess = 0;
     313            if (fDesiredAccess & (GENERIC_ALL | STANDARD_RIGHTS_ALL))
     314                fObjDesiredAccess = DIRECTORY_ALL_ACCESS;
     315            else
     316            {
     317                if (fDesiredAccess & (FILE_GENERIC_WRITE | GENERIC_WRITE | STANDARD_RIGHTS_WRITE))
     318                    fObjDesiredAccess |= DIRECTORY_CREATE_OBJECT | DIRECTORY_CREATE_OBJECT;
     319                if (   (fDesiredAccess & (FILE_LIST_DIRECTORY | FILE_GENERIC_READ | GENERIC_READ | STANDARD_RIGHTS_READ))
     320                    || !fObjDesiredAccess)
     321                    fObjDesiredAccess |= DIRECTORY_QUERY | FILE_LIST_DIRECTORY;
     322            }
     323
     324            rcNt = NtOpenDirectoryObject(&hFile, fObjDesiredAccess, &ObjAttr);
     325            if (NT_SUCCESS(rcNt))
     326            {
     327                *pfObjDir = true;
     328                *phHandle = hFile;
     329                rc = VINF_SUCCESS;
     330            }
     331            else
     332                rc = RTErrConvertFromNtStatus(rcNt);
     333        }
     334#endif
     335        else
     336            rc = RTErrConvertFromNtStatus(rcNt);
     337        rtNtPathFreeNative(&NtName, &hRootDir);
     338    }
     339    return rc;
     340}
     341
     342
     343/**
    229344 * Closes an handled open by rtNtPathOpen.
    230345 *
  • trunk/src/VBox/Runtime/r3/posix/dir-posix.cpp

    r43363 r47535  
    193193
    194194
     195size_t rtDirNativeGetStructSize(const char *pszPath)
     196{
     197    long cbNameMax = pathconf(pszPath, _PC_NAME_MAX);
     198# ifdef NAME_MAX
     199    if (cbNameMax < NAME_MAX)           /* This is plain paranoia, but it doesn't hurt. */
     200        cbNameMax = NAME_MAX;
     201# endif
     202# ifdef _XOPEN_NAME_MAX
     203    if (cbNameMax < _XOPEN_NAME_MAX)    /* Ditto. */
     204        cbNameMax = _XOPEN_NAME_MAX;
     205# endif
     206    size_t cbDir = RT_OFFSETOF(RTDIR, Data.d_name[cbNameMax + 1]);
     207    if (cbDir < sizeof(RTDIR))          /* Ditto. */
     208        cbDir = sizeof(RTDIR);
     209    cbDir = RT_ALIGN_Z(cbDir, 8);
     210
     211    return cbDir;
     212}
     213
     214
    195215int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
    196216{
     
    208228        {
    209229            /*
    210              * Init data.
     230             * Init data (allocated as all zeros).
    211231             */
    212             pDir->fDataUnread = false;
    213             memset(&pDir->Data, 0, RT_OFFSETOF(RTDIR, Data.d_name)); /* not strictly necessary */
    214             memset(&pDir->Data.d_name[0], 0, pDir->cbMaxName);
     232            pDir->fDataUnread = false; /* spelling it out */
    215233        }
    216234        else
  • trunk/src/VBox/Runtime/r3/win/direnum-win.cpp

    r47534 r47535  
    4444
    4545
     46size_t rtDirNativeGetStructSize(const char *pszPath)
     47{
     48    NOREF(pszPath);
     49    return sizeof(RTDIR);
     50}
     51
     52
    4653int rtDirNativeOpen(PRTDIR pDir, char *pszPathBuf)
    4754{
     
    7885    if (RT_SUCCESS(rc))
    7986    {
    80         pDir->hDir    = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
     87        pDir->hDir = FindFirstFileW((LPCWSTR)pwszName, &pDir->Data);
    8188        if (pDir->hDir != INVALID_HANDLE_VALUE)
    8289            pDir->fDataUnread = true;
  • trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.c

    r47533 r47535  
    55
    66/*
    7  * Copyright (C) 2010-2012 Oracle Corporation
     7 * Copyright (C) 2010-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3838typedef INT     PROCESSINFOCLASS;
    3939typedef PVOID   POBJECT_ATTRIBUTES;
     40typedef PVOID   PIO_APC_ROUTINE;
     41typedef PVOID   PUNICODE_STRING;
    4042
    4143
     
    5355                                           OUT PULONG MinimumResolution,
    5456                                           OUT PULONG CurrentResolution)
     57{
     58    return -1;
     59}
     60
     61NTSYSAPI LONG NTAPI NtQueryDirectoryFile(IN HANDLE FileHandle,
     62                                         IN HANDLE Event OPTIONAL,
     63                                         IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
     64                                         IN PVOID ApcContext OPTIONAL,
     65                                         OUT PIO_STATUS_BLOCK IoStatusBlock,
     66                                         OUT PVOID FileInformation,
     67                                         IN ULONG Length,
     68                                         IN FILE_INFORMATION_CLASS FileInformationClass,
     69                                         IN BOOLEAN ReturnSingleEntry,
     70                                         IN PUNICODE_STRING FileName OPTIONAL,
     71                                         IN BOOLEAN RestartScan)
     72{
     73    return -1;
     74}
     75
     76NTSYSAPI LONG NTAPI NtQueryDirectoryObject(IN HANDLE ObjectHandle,
     77                                           OUT PVOID Buffer,
     78                                           IN ULONG Length,
     79                                           IN BOOLEAN ReturnSingleEntry,
     80                                           IN BOOLEAN RestartScan,
     81                                           IN OUT PULONG Context,
     82                                           OUT PULONG ReturneLength)
    5583{
    5684    return -1;
     
    132160}
    133161
     162NTSYSAPI NTSTATUS NTAPI NtOpenDirectoryObject(OUT PHANDLE ObjectHandle,
     163                                              IN ACCESS_MASK DesiredAccess,
     164                                              IN POBJECT_ATTRIBUTES ObjectAttributes)
     165{
     166    return -1;
     167}
     168
    134169NTSYSAPI NTSTATUS NTAPI NtClose(IN HANDLE Handle)
    135170{
  • trunk/src/VBox/Runtime/r3/win/ntdll-mini-implib.def

    r47533 r47535  
    2929    RtlNtStatusToDosError
    3030    NtQueryTimerResolution
     31    NtQueryDirectoryFile
    3132    NtQueryInformationFile
    3233    NtQueryInformationProcess
     
    3738    NtCreateFile
    3839    NtClose
     40    NtOpenDirectoryObject
  • trunk/src/VBox/Runtime/testcase/tstDir.cpp

    r44528 r47535  
    4040     * Iterate arguments.
    4141     */
    42     bool fLong = false;
     42    bool fLong      = false;
    4343    bool fShortName = false;
     44    bool fFiltered  = false;
     45    bool fQuiet     = false;
    4446    for (int i = 1; i < argc; i++)
    4547    {
     
    5658                        fShortName = true;
    5759                        break;
     60                    case 'f':
     61                        fFiltered = true;
     62                        break;
     63                    case 'q':
     64                        fQuiet = true;
     65                        break;
    5866                    default:
    5967                        RTPrintf("Unknown option '%c' ignored!\n", argv[i][j]);
     
    6674            /* open */
    6775            PRTDIR pDir;
    68             int rc = RTDirOpen(&pDir, argv[i]);
     76            int rc;
     77            if (!fFiltered)
     78                rc = RTDirOpen(&pDir, argv[i]);
     79            else
     80                rc = RTDirOpenFiltered(&pDir, argv[i], RTDIRFILTER_WINNT, 0);
    6981            if (RT_SUCCESS(rc))
    7082            {
     
    7890                        if (RT_FAILURE(rc))
    7991                            break;
    80                         switch (DirEntry.enmType)
     92                        if (!fQuiet)
    8193                        {
    82                             case RTDIRENTRYTYPE_UNKNOWN:     RTPrintf("u"); break;
    83                             case RTDIRENTRYTYPE_FIFO:        RTPrintf("f"); break;
    84                             case RTDIRENTRYTYPE_DEV_CHAR:    RTPrintf("c"); break;
    85                             case RTDIRENTRYTYPE_DIRECTORY:   RTPrintf("d"); break;
    86                             case RTDIRENTRYTYPE_DEV_BLOCK:   RTPrintf("b"); break;
    87                             case RTDIRENTRYTYPE_FILE:        RTPrintf("-"); break;
    88                             case RTDIRENTRYTYPE_SYMLINK:     RTPrintf("l"); break;
    89                             case RTDIRENTRYTYPE_SOCKET:      RTPrintf("s"); break;
    90                             case RTDIRENTRYTYPE_WHITEOUT:    RTPrintf("w"); break;
    91                             default:
    92                                 rcRet = 1;
    93                                 RTPrintf("?");
    94                                 break;
     94                            switch (DirEntry.enmType)
     95                            {
     96                                case RTDIRENTRYTYPE_UNKNOWN:     RTPrintf("u"); break;
     97                                case RTDIRENTRYTYPE_FIFO:        RTPrintf("f"); break;
     98                                case RTDIRENTRYTYPE_DEV_CHAR:    RTPrintf("c"); break;
     99                                case RTDIRENTRYTYPE_DIRECTORY:   RTPrintf("d"); break;
     100                                case RTDIRENTRYTYPE_DEV_BLOCK:   RTPrintf("b"); break;
     101                                case RTDIRENTRYTYPE_FILE:        RTPrintf("-"); break;
     102                                case RTDIRENTRYTYPE_SYMLINK:     RTPrintf("l"); break;
     103                                case RTDIRENTRYTYPE_SOCKET:      RTPrintf("s"); break;
     104                                case RTDIRENTRYTYPE_WHITEOUT:    RTPrintf("w"); break;
     105                                default:
     106                                    rcRet = 1;
     107                                    RTPrintf("?");
     108                                    break;
     109                            }
     110                            RTPrintf(" %#18llx  %3d %s\n", (uint64_t)DirEntry.INodeId,
     111                                     DirEntry.cbName, DirEntry.szName);
    95112                        }
    96                         RTPrintf(" %#18llx  %3d %s\n", (uint64_t)DirEntry.INodeId,
    97                                  DirEntry.cbName, DirEntry.szName);
    98113                    }
    99114                }
     
    107122                            break;
    108123
    109                         RTFMODE fMode = DirEntry.Info.Attr.fMode;
    110                         switch (fMode & RTFS_TYPE_MASK)
     124                        if (!fQuiet)
    111125                        {
    112                             case RTFS_TYPE_FIFO:        RTPrintf("f"); break;
    113                             case RTFS_TYPE_DEV_CHAR:    RTPrintf("c"); break;
    114                             case RTFS_TYPE_DIRECTORY:   RTPrintf("d"); break;
    115                             case RTFS_TYPE_DEV_BLOCK:   RTPrintf("b"); break;
    116                             case RTFS_TYPE_FILE:        RTPrintf("-"); break;
    117                             case RTFS_TYPE_SYMLINK:     RTPrintf("l"); break;
    118                             case RTFS_TYPE_SOCKET:      RTPrintf("s"); break;
    119                             case RTFS_TYPE_WHITEOUT:    RTPrintf("w"); break;
    120                             default:
    121                                 rcRet = 1;
    122                                 RTPrintf("?");
    123                                 break;
     126                            RTFMODE fMode = DirEntry.Info.Attr.fMode;
     127                            switch (fMode & RTFS_TYPE_MASK)
     128                            {
     129                                case RTFS_TYPE_FIFO:        RTPrintf("f"); break;
     130                                case RTFS_TYPE_DEV_CHAR:    RTPrintf("c"); break;
     131                                case RTFS_TYPE_DIRECTORY:   RTPrintf("d"); break;
     132                                case RTFS_TYPE_DEV_BLOCK:   RTPrintf("b"); break;
     133                                case RTFS_TYPE_FILE:        RTPrintf("-"); break;
     134                                case RTFS_TYPE_SYMLINK:     RTPrintf("l"); break;
     135                                case RTFS_TYPE_SOCKET:      RTPrintf("s"); break;
     136                                case RTFS_TYPE_WHITEOUT:    RTPrintf("w"); break;
     137                                default:
     138                                    rcRet = 1;
     139                                    RTPrintf("?");
     140                                    break;
     141                            }
     142                            /** @todo sticy bits++ */
     143                            RTPrintf("%c%c%c",
     144                                     fMode & RTFS_UNIX_IRUSR ? 'r' : '-',
     145                                     fMode & RTFS_UNIX_IWUSR ? 'w' : '-',
     146                                     fMode & RTFS_UNIX_IXUSR ? 'x' : '-');
     147                            RTPrintf("%c%c%c",
     148                                     fMode & RTFS_UNIX_IRGRP ? 'r' : '-',
     149                                     fMode & RTFS_UNIX_IWGRP ? 'w' : '-',
     150                                     fMode & RTFS_UNIX_IXGRP ? 'x' : '-');
     151                            RTPrintf("%c%c%c",
     152                                     fMode & RTFS_UNIX_IROTH ? 'r' : '-',
     153                                     fMode & RTFS_UNIX_IWOTH ? 'w' : '-',
     154                                     fMode & RTFS_UNIX_IXOTH ? 'x' : '-');
     155                            RTPrintf(" %c%c%c%c%c%c%c%c%c%c%c%c%c%c",
     156                                     fMode & RTFS_DOS_READONLY          ? 'R' : '-',
     157                                     fMode & RTFS_DOS_HIDDEN            ? 'H' : '-',
     158                                     fMode & RTFS_DOS_SYSTEM            ? 'S' : '-',
     159                                     fMode & RTFS_DOS_DIRECTORY         ? 'D' : '-',
     160                                     fMode & RTFS_DOS_ARCHIVED          ? 'A' : '-',
     161                                     fMode & RTFS_DOS_NT_DEVICE         ? 'd' : '-',
     162                                     fMode & RTFS_DOS_NT_NORMAL         ? 'N' : '-',
     163                                     fMode & RTFS_DOS_NT_TEMPORARY      ? 'T' : '-',
     164                                     fMode & RTFS_DOS_NT_SPARSE_FILE    ? 'P' : '-',
     165                                     fMode & RTFS_DOS_NT_REPARSE_POINT  ? 'J' : '-',
     166                                     fMode & RTFS_DOS_NT_COMPRESSED     ? 'C' : '-',
     167                                     fMode & RTFS_DOS_NT_OFFLINE        ? 'O' : '-',
     168                                     fMode & RTFS_DOS_NT_NOT_CONTENT_INDEXED ? 'I' : '-',
     169                                     fMode & RTFS_DOS_NT_ENCRYPTED      ? 'E' : '-');
     170                            RTPrintf(" %d %4d %4d %10lld %10lld %#llx %#llx %#llx %#llx",
     171                                     DirEntry.Info.Attr.u.Unix.cHardlinks,
     172                                     DirEntry.Info.Attr.u.Unix.uid,
     173                                     DirEntry.Info.Attr.u.Unix.gid,
     174                                     DirEntry.Info.cbObject,
     175                                     DirEntry.Info.cbAllocated,
     176                                     DirEntry.Info.BirthTime,
     177                                     DirEntry.Info.ChangeTime,
     178                                     DirEntry.Info.ModificationTime,
     179                                     DirEntry.Info.AccessTime);
     180                            if (fShortName)
     181                                RTPrintf(" %2d %-12ls ", DirEntry.cwcShortName, DirEntry.wszShortName);
     182                            RTPrintf(" %2d %s\n", DirEntry.cbName, DirEntry.szName);
    124183                        }
    125                         /** @todo sticy bits++ */
    126                         RTPrintf("%c%c%c",
    127                                  fMode & RTFS_UNIX_IRUSR ? 'r' : '-',
    128                                  fMode & RTFS_UNIX_IWUSR ? 'w' : '-',
    129                                  fMode & RTFS_UNIX_IXUSR ? 'x' : '-');
    130                         RTPrintf("%c%c%c",
    131                                  fMode & RTFS_UNIX_IRGRP ? 'r' : '-',
    132                                  fMode & RTFS_UNIX_IWGRP ? 'w' : '-',
    133                                  fMode & RTFS_UNIX_IXGRP ? 'x' : '-');
    134                         RTPrintf("%c%c%c",
    135                                  fMode & RTFS_UNIX_IROTH ? 'r' : '-',
    136                                  fMode & RTFS_UNIX_IWOTH ? 'w' : '-',
    137                                  fMode & RTFS_UNIX_IXOTH ? 'x' : '-');
    138                         RTPrintf(" %c%c%c%c%c%c%c%c%c%c%c%c%c%c",
    139                                  fMode & RTFS_DOS_READONLY          ? 'R' : '-',
    140                                  fMode & RTFS_DOS_HIDDEN            ? 'H' : '-',
    141                                  fMode & RTFS_DOS_SYSTEM            ? 'S' : '-',
    142                                  fMode & RTFS_DOS_DIRECTORY         ? 'D' : '-',
    143                                  fMode & RTFS_DOS_ARCHIVED          ? 'A' : '-',
    144                                  fMode & RTFS_DOS_NT_DEVICE         ? 'd' : '-',
    145                                  fMode & RTFS_DOS_NT_NORMAL         ? 'N' : '-',
    146                                  fMode & RTFS_DOS_NT_TEMPORARY      ? 'T' : '-',
    147                                  fMode & RTFS_DOS_NT_SPARSE_FILE    ? 'P' : '-',
    148                                  fMode & RTFS_DOS_NT_REPARSE_POINT  ? 'J' : '-',
    149                                  fMode & RTFS_DOS_NT_COMPRESSED     ? 'C' : '-',
    150                                  fMode & RTFS_DOS_NT_OFFLINE        ? 'O' : '-',
    151                                  fMode & RTFS_DOS_NT_NOT_CONTENT_INDEXED ? 'I' : '-',
    152                                  fMode & RTFS_DOS_NT_ENCRYPTED      ? 'E' : '-');
    153                         RTPrintf(" %d %4d %4d %10lld %10lld %#llx %#llx %#llx %#llx",
    154                                  DirEntry.Info.Attr.u.Unix.cHardlinks,
    155                                  DirEntry.Info.Attr.u.Unix.uid,
    156                                  DirEntry.Info.Attr.u.Unix.gid,
    157                                  DirEntry.Info.cbObject,
    158                                  DirEntry.Info.cbAllocated,
    159                                  DirEntry.Info.BirthTime,
    160                                  DirEntry.Info.ChangeTime,
    161                                  DirEntry.Info.ModificationTime,
    162                                  DirEntry.Info.AccessTime);
    163                         if (fShortName && DirEntry.cwcShortName)
    164                             RTPrintf(" %2d %ls\n", DirEntry.cwcShortName, DirEntry.wszShortName);
    165                         else
    166                             RTPrintf(" %2d %s\n", DirEntry.cbName, DirEntry.szName);
    167184                        if (rc != VINF_SUCCESS)
    168185                            RTPrintf("^^ %Rrc\n", 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