Changeset 2985 for trunk/src/lib/nt


Ignore:
Timestamp:
Nov 1, 2016, 7:26:35 PM (9 years ago)
Author:
bird
Message:

lib/nt: Got fts-nt halfways working, quite a few NT interface changes.

Location:
trunk/src/lib/nt
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/nt/fts-nt.c

    r2982 r2985  
     1/* $Id: $ */
     2/** @file
     3 * Source for the NT port of BSD fts.c.
     4 *
     5 * @copyright   1990, 1993, 1994 The Regents of the University of California.  All rights reserved.
     6 * @copyright   NT modifications Copyright (C) 2016 knut st. osmundsen <bird-klibc-spam-xiv@anduin.net>
     7 * @licenses    BSD3
     8 *
     9 *
     10 * Some hints about how the code works.
     11 *
     12 * The input directories & files are entered into a pseudo root directory and
     13 * processed one after another, depth first.
     14 *
     15 * Directories are completely read into memory first and arranged as linked
     16 * list anchored on FTS::fts_cur.  fts_read does a pop-like operation on that
     17 * list, freeing the nodes after they've been completely processed.
     18 * Subdirectories are returned twice by fts_read, the first time when it
     19 * decends into it (FTS_D), and the second time as it ascends from it (FTS_DP).
     20 *
     21 * In parallel to fts_read, there's the fts_children API that fetches the
     22 * directory content in a similar manner, but for the consumption of the API
     23 * caller rather than FTS itself.  The result hangs on FTS::fts_child so it can
     24 * be freed when the directory changes or used by fts_read when it is called
     25 * upon to enumerate the directory.
     26 *
     27 *
     28 * The NT port of the code does away with the directory changing in favor of
     29 * using directory relative opens (present in NT since for ever, just not
     30 * exposed thru Win32).  A new FTSENT member fts_dirfd has been added to make
     31 * this possible for API users too.
     32 *
     33 * Note! When using Win32 APIs with path input relative to the current
     34 *       directory, the internal DOS <-> NT path converter will expand it to a
     35 *       full path and subject it to the 260 char limit.
     36 *
     37 * The richer NT directory enumeration API allows us to do away with all the
     38 * stat() calls, and not have to do link counting and other interesting things
     39 * to try speed things up.  (You typical stat() implementation on windows is
     40 * actually a directory enum call with the name of the file as filter.)
     41 */
     42
    143/*-
    244 * Copyright (c) 1990, 1993, 1994
     
    3678#endif
    3779
    38 #include <sys/cdefs.h>
    39 __FBSDID("$FreeBSD$");
    40 
    41 #include "namespace.h"
    42 #include <sys/param.h>
    43 #include <sys/mount.h>
    44 #include <sys/stat.h>
    45 
    46 #include <dirent.h>
     80//#include <sys/cdefs.h>
     81//__FBSDID("$FreeBSD$");
     82
     83//#include "namespace.h"
     84//#include <sys/param.h>
     85//#include <sys/mount.h>
     86//#include <sys/stat.h>
     87
     88//#include <dirent.h>
    4789#include <errno.h>
    48 #include <fcntl.h>
    49 #include <fts.h>
     90//#include <fcntl.h>
     91#include "fts-nt.h"
    5092#include <stdlib.h>
    5193#include <string.h>
    52 #include <unistd.h>
    53 #include "un-namespace.h"
    54 
    55 #include "gen-private.h"
     94//#include <unistd.h>
     95//#include "un-namespace.h"
     96//
     97//#include "gen-private.h"
     98#include <assert.h>
     99#include "nthlp.h"
     100#include "ntdir.h"
    56101
    57102static FTSENT   *fts_alloc(FTS *, char *, size_t);
     
    63108static int       fts_palloc(FTS *, size_t);
    64109static FTSENT   *fts_sort(FTS *, FTSENT *, size_t);
    65 static int       fts_stat(FTS *, FTSENT *, int, int);
     110static int       fts_stat(FTS *, FTSENT *, int, HANDLE);
     111static int   fts_process_stats(FTSENT *, BirdStat_T const *);
    66112static int       fts_safe_changedir(FTS *, FTSENT *, int, char *);
    67113static int       fts_ufslinks(FTS *, const FTSENT *);
     
    80126#define BREAD           3               /* fts_read */
    81127
     128/* NT needs these: */
     129#define MAXPATHLEN 260
     130#define MAX(a, b)  ( (a) >= (b) ? (a) : (b) )
     131
     132#define AT_SYMLINK_NOFOLLOW 1
     133#define fstatat(hDir, pszPath, pStat, fFlags) birdStatAt((hDir), (pszPath), (pStat), (fFlags) != 0)
     134#define FTS_NT_DUMMY_SYMFD_VALUE        ((HANDLE)~(intptr_t)(2)) /* current process */
     135#define fchdir(fd) todo_fchdir(fd)
     136extern int todo_fchdir(fts_fd_t fd);
     137
    82138/*
    83139 * Internal representation of an FTS, including extra implementation
     
    87143struct _fts_private {
    88144        FTS             ftsp_fts;
     145#if 0 /* Not needed on NT, see comment on fts_ufslinks */
    89146        struct statfs   ftsp_statfs;
    90147        dev_t           ftsp_dev;
    91148        int             ftsp_linksreliable;
     149#endif
    92150};
    93151
     152#if 0 /* Not needed on NT, see comment on fts_ufslinks */
    94153/*
    95154 * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it
     
    108167        0
    109168};
    110 
    111 FTS *
     169#endif
     170
     171FTS * FTSCALL
    112172fts_open(char * const *argv, int options,
    113173    int (*compar)(const FTSENT * const *, const FTSENT * const *))
     
    159219        /* Allocate/initialize root(s). */
    160220        for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
     221                /* NT: We need to do some small input transformations to make this and
     222                       the API user code happy.  1. Lone drive letters get a dot
     223                       appended so it won't matter if a slash is appended afterwards.
     224                           2. DOS slashes are converted to UNIX ones. */
     225                char *slash;
    161226                len = strlen(*argv);
    162 
    163                 p = fts_alloc(sp, *argv, len);
     227                if (len == 2 && argv[0][1] == ':') {
     228                        char tmp[4];
     229                        tmp[0] = argv[0][0];
     230                        tmp[1] = ':';
     231                        tmp[2] = '.';
     232                        tmp[3] = '\0';
     233                        p = fts_alloc(sp, tmp, 3);
     234                } else {
     235                        p = fts_alloc(sp, *argv, len);
     236                }
     237#if 1 /* bird */
     238                if (p != NULL) { /* likely */ } else { goto mem3; }
     239#endif
     240                slash = strchr(p->fts_name, '\\');
     241                while (slash != NULL) {
     242                        *slash++ = '/';
     243                        slash = strchr(p->fts_name, '\\');
     244                }
    164245                p->fts_level = FTS_ROOTLEVEL;
    165246                p->fts_parent = parent;
    166247                p->fts_accpath = p->fts_name;
    167                 p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), -1);
     248                p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), INVALID_HANDLE_VALUE);
    168249
    169250                /* Command-line "." and ".." are real directories. */
     
    201282        sp->fts_cur->fts_info = FTS_INIT;
    202283
    203         /*
    204          * If using chdir(2), grab a file descriptor pointing to dot to ensure
    205          * that we can get back here; this could be avoided for some paths,
    206          * but almost certainly not worth the effort.  Slashes, symbolic links,
    207          * and ".." are all fairly nasty problems.  Note, if we can't get the
    208          * descriptor we run anyway, just more slowly.
    209          */
    210         if (!ISSET(FTS_NOCHDIR) &&
    211             (sp->fts_rfd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
    212                 SET(FTS_NOCHDIR);
    213 
    214284        return (sp);
    215285
     
    221291}
    222292
     293
    223294static void
    224295fts_load(FTS *sp, FTSENT *p)
     
    236307        len = p->fts_pathlen = p->fts_namelen;
    237308        memmove(sp->fts_path, p->fts_name, len + 1);
     309/** @todo check for ':' and '\\'? */
    238310        if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
    239311                len = strlen(++cp);
     
    245317}
    246318
    247 int
     319int FTSCALL
    248320fts_close(FTS *sp)
    249321{
    250322        FTSENT *freep, *p;
    251         int saved_errno;
     323        /*int saved_errno;*/
    252324
    253325        /*
     
    272344        free(sp->fts_path);
    273345
    274         /* Return to original directory, save errno if necessary. */
    275         if (!ISSET(FTS_NOCHDIR)) {
    276                 saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
    277                 (void)_close(sp->fts_rfd);
    278 
    279                 /* Set errno and return. */
    280                 if (saved_errno != 0) {
    281                         /* Free up the stream pointer. */
    282                         free(sp);
    283                         errno = saved_errno;
    284                         return (-1);
    285                 }
    286         }
    287 
    288346        /* Free up the stream pointer. */
    289347        free(sp);
     
    299357            ? p->fts_pathlen - 1 : p->fts_pathlen)
    300358
    301 FTSENT *
     359static void
     360fts_free_entry(FTSENT *tmp)
     361{
     362    if (tmp != NULL) {
     363                if (tmp->fts_dirfd != INVALID_HANDLE_VALUE) {
     364                        birdCloseFile(tmp->fts_dirfd);
     365                        tmp->fts_dirfd = INVALID_HANDLE_VALUE;
     366                }
     367                free(tmp);
     368    }
     369}
     370
     371FTSENT * FTSCALL
    302372fts_read(FTS *sp)
    303373{
     
    305375        int instr;
    306376        char *t;
    307         int saved_errno;
    308377
    309378        /* If finished or unrecoverable error, return NULL. */
     
    320389        /* Any type of file may be re-visited; re-stat and re-turn. */
    321390        if (instr == FTS_AGAIN) {
    322                 p->fts_info = fts_stat(sp, p, 0, -1);
     391                p->fts_info = fts_stat(sp, p, 0, INVALID_HANDLE_VALUE);
    323392                return (p);
    324393        }
     
    329398         * keep a pointer to current location.  If unable to get that
    330399         * pointer, follow fails.
     400         *
     401         * NT: Since we don't change directory, we just set fts_symfd to a
     402         *     placeholder value handle value here in case a API client
     403         *     checks it. Ditto FTS_SYMFOLLOW.
    331404         */
    332405        if (instr == FTS_FOLLOW &&
    333406            (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
    334                 p->fts_info = fts_stat(sp, p, 1, -1);
    335                 if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
    336                         if ((p->fts_symfd = _open(".", O_RDONLY | O_CLOEXEC,
    337                             0)) < 0) {
    338                                 p->fts_errno = errno;
    339                                 p->fts_info = FTS_ERR;
    340                         } else
    341                                 p->fts_flags |= FTS_SYMFOLLOW;
     407                p->fts_info = fts_stat(sp, p, 1, INVALID_HANDLE_VALUE);
     408                if (p->fts_info == FTS_D /*&& !ISSET(FTS_NOCHDIR)*/) {
     409                        p->fts_symfd = FTS_NT_DUMMY_SYMFD_VALUE;
     410                        p->fts_flags |= FTS_SYMFOLLOW;
    342411                }
    343412                return (p);
     
    349418                if (instr == FTS_SKIP ||
    350419                    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
    351                         if (p->fts_flags & FTS_SYMFOLLOW)
    352                                 (void)_close(p->fts_symfd);
     420                        if (p->fts_flags & FTS_SYMFOLLOW) {
     421                                p->fts_symfd = INVALID_HANDLE_VALUE;
     422                        }
    353423                        if (sp->fts_child) {
    354424                                fts_lfree(sp->fts_child);
     
    405475                 */
    406476                if (p->fts_level == FTS_ROOTLEVEL) {
    407                         if (FCHDIR(sp, sp->fts_rfd)) {
     477                        /*NT: No fchdir: if (FCHDIR(sp, sp->fts_rfd)) {
    408478                                SET(FTS_STOP);
    409479                                return (NULL);
    410                         }
    411                         free(tmp);
     480                        } */
     481                        fts_free_entry(tmp);
    412482                        fts_load(sp, p);
    413483                        return (sp->fts_cur = p);
     
    420490                 */
    421491                if (p->fts_instr == FTS_SKIP) {
    422                         free(tmp);
     492                        fts_free_entry(tmp);
    423493                        goto next;
    424494                }
    425495                if (p->fts_instr == FTS_FOLLOW) {
    426                         p->fts_info = fts_stat(sp, p, 1, -1);
    427                         if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
    428                                 if ((p->fts_symfd =
    429                                     _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) {
    430                                         p->fts_errno = errno;
    431                                         p->fts_info = FTS_ERR;
    432                                 } else
    433                                         p->fts_flags |= FTS_SYMFOLLOW;
     496                        p->fts_info = fts_stat(sp, p, 1, INVALID_HANDLE_VALUE);
     497                        /* NT: See above regarding fts_symfd. */
     498                        if (p->fts_info == FTS_D /*&& !ISSET(FTS_NOCHDIR)*/) {
     499                                p->fts_symfd = FTS_NT_DUMMY_SYMFD_VALUE;
     500                                p->fts_flags |= FTS_SYMFOLLOW;
    434501                        }
    435502                        p->fts_instr = FTS_NOINSTR;
    436503                }
    437504
    438                 free(tmp);
     505                fts_free_entry(tmp);
    439506
    440507name:           t = sp->fts_path + NAPPEND(p->fts_parent);
     
    452519                 * can distinguish between error and EOF.
    453520                 */
    454                 free(tmp);
    455                 free(p);
     521                fts_free_entry(tmp);
     522                fts_free_entry(p);
    456523                errno = 0;
    457524                return (sp->fts_cur = NULL);
     
    465532         * a symlink, go back through the file descriptor.  Otherwise, cd up
    466533         * one directory.
    467          */
    468         if (p->fts_level == FTS_ROOTLEVEL) {
    469                 if (FCHDIR(sp, sp->fts_rfd)) {
    470                         SET(FTS_STOP);
    471                         return (NULL);
    472                 }
    473         } else if (p->fts_flags & FTS_SYMFOLLOW) {
    474                 if (FCHDIR(sp, p->fts_symfd)) {
    475                         saved_errno = errno;
    476                         (void)_close(p->fts_symfd);
    477                         errno = saved_errno;
    478                         SET(FTS_STOP);
    479                         return (NULL);
    480                 }
    481                 (void)_close(p->fts_symfd);
    482         } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
    483             fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
    484                 SET(FTS_STOP);
    485                 return (NULL);
    486         }
    487         free(tmp);
     534         *
     535         * NT: We're doing no fchdir, but we need to close the directory handle
     536         *     and clear fts_symfd now.
     537         */
     538        if (p->fts_flags & FTS_SYMFOLLOW) {
     539                p->fts_symfd = INVALID_HANDLE_VALUE;
     540        }
     541    if (p->fts_dirfd != INVALID_HANDLE_VALUE) {
     542                birdCloseFile(p->fts_dirfd);
     543                p->fts_dirfd = INVALID_HANDLE_VALUE;
     544    }
     545    fts_free_entry(tmp);
    488546        p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
    489547        return (sp->fts_cur = p);
     
    497555 */
    498556/* ARGSUSED */
    499 int
     557int FTSCALL
    500558fts_set(FTS *sp, FTSENT *p, int instr)
    501559{
     
    509567}
    510568
    511 FTSENT *
     569#if 0
     570FTSENT * FTSCALL
    512571fts_children(FTS *sp, int instr)
    513572{
     
    579638        return (sp->fts_child);
    580639}
     640#endif /* PORTME */
    581641
    582642#ifndef fts_get_clientptr
     
    585645
    586646void *
    587 (fts_get_clientptr)(FTS *sp)
     647(FTSCALL fts_get_clientptr)(FTS *sp)
    588648{
    589649
     
    596656
    597657FTS *
    598 (fts_get_stream)(FTSENT *p)
     658(FTSCALL fts_get_stream)(FTSENT *p)
    599659{
    600660        return (fts_get_stream(p));
    601661}
    602662
    603 void
     663void FTSCALL
    604664fts_set_clientptr(FTS *sp, void *clientptr)
    605665{
     
    621681 * directories and for any files after the subdirectories in the directory have
    622682 * been found, cutting the stat calls by about 2/3.
     683 *
     684 * NT: We do not do any link counting or stat avoiding, which invalidates the
     685 *     above warnings.  This function is very simple for us.
    623686 */
    624687static FTSENT *
    625688fts_build(FTS *sp, int type)
    626689{
    627         struct dirent *dp;
     690        BirdDirEntry_T *dp;
    628691        FTSENT *p, *head;
    629692        FTSENT *cur, *tail;
     
    631694        void *oldaddr;
    632695        char *cp;
    633         int cderrno, descend, oflag, saved_errno, nostat, doadjust;
     696        int saved_errno, doadjust;
    634697        long level;
    635         long nlinks;    /* has to be signed because -1 is a magic value */
    636698        size_t dnamlen, len, maxlen, nitems;
     699        unsigned fDirOpenFlags;
    637700
    638701        /* Set current node pointer. */
     
    642705         * Open the directory for reading.  If this fails, we're done.
    643706         * If being called from fts_read, set the fts_info field.
    644          */
    645 #ifdef FTS_WHITEOUT
    646         if (ISSET(FTS_WHITEOUT))
    647                 oflag = DTF_NODUP | DTF_REWIND;
    648         else
    649                 oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND;
    650 #else
    651 #define __opendir2(path, flag) opendir(path)
    652 #endif
    653         if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
     707         *
     708         * NT: We do a two stage open so we can keep the directory handle around
     709         *     after we've enumerated the directory.  The dir handle is used by
     710         *     us here and by the API users to more efficiently and safely open
     711         *     members of the directory.
     712         */
     713        fDirOpenFlags = BIRDDIR_F_EXTRA_INFO | BIRDDIR_F_KEEP_HANDLE;
     714    if (cur->fts_dirfd == INVALID_HANDLE_VALUE) {
     715                if (cur->fts_parent->fts_dirfd != INVALID_HANDLE_VALUE) {
     716                        /* (This works fine for symlinks too, since we follow them.) */
     717                        cur->fts_dirfd = birdOpenFileEx(cur->fts_parent->fts_dirfd,
     718                                                                                        cur->fts_name,
     719                                                                                        FILE_READ_DATA | SYNCHRONIZE,
     720                                                                                        FILE_ATTRIBUTE_NORMAL,
     721                                                                                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     722                                                                                        FILE_OPEN,
     723                                                                                        FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     724                                                                                        OBJ_CASE_INSENSITIVE);
     725                } else {
     726                        cur->fts_dirfd = birdOpenFile(cur->fts_accpath,
     727                                                                                  FILE_READ_DATA | SYNCHRONIZE,
     728                                                                                  FILE_ATTRIBUTE_NORMAL,
     729                                                                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     730                                                                                  FILE_OPEN,
     731                                                                                  FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     732                                                                                  OBJ_CASE_INSENSITIVE);
     733                }
     734    } else {
     735                fDirOpenFlags |= BIRDDIR_F_RESTART_SCAN;
     736        }
     737        dirp = birdDirOpenFromHandle(cur->fts_dirfd, NULL, fDirOpenFlags);
     738        if (dirp == NULL) {
    654739                if (type == BREAD) {
    655740                        cur->fts_info = FTS_DNR;
     
    658743                return (NULL);
    659744        }
    660 
    661         /*
    662          * Nlinks is the number of possible entries of type directory in the
    663          * directory if we're cheating on stat calls, 0 if we're not doing
    664          * any stat calls at all, -1 if we're doing stats on everything.
    665          */
    666         if (type == BNAMES) {
    667                 nlinks = 0;
    668                 /* Be quiet about nostat, GCC. */
    669                 nostat = 0;
    670         } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
    671                 if (fts_ufslinks(sp, cur))
    672                         nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
    673                 else
    674                         nlinks = -1;
    675                 nostat = 1;
    676         } else {
    677                 nlinks = -1;
    678                 nostat = 0;
    679         }
    680 
    681 #ifdef notdef
    682         (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
    683         (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
    684             ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
    685 #endif
    686         /*
    687          * If we're going to need to stat anything or we want to descend
    688          * and stay in the directory, chdir.  If this fails we keep going,
    689          * but set a flag so we don't chdir after the post-order visit.
    690          * We won't be able to stat anything, but we can still return the
    691          * names themselves.  Note, that since fts_read won't be able to
    692          * chdir into the directory, it will have to return different path
    693          * names than before, i.e. "a/b" instead of "b".  Since the node
    694          * has already been visited in pre-order, have to wait until the
    695          * post-order visit to return the error.  There is a special case
    696          * here, if there was nothing to stat then it's not an error to
    697          * not be able to stat.  This is all fairly nasty.  If a program
    698          * needed sorted entries or stat information, they had better be
    699          * checking FTS_NS on the returned nodes.
    700          */
    701         cderrno = 0;
    702         if (nlinks || type == BREAD) {
    703                 if (fts_safe_changedir(sp, cur, _dirfd(dirp), NULL)) {
    704                         if (nlinks && type == BREAD)
    705                                 cur->fts_errno = errno;
    706                         cur->fts_flags |= FTS_DONTCHDIR;
    707                         descend = 0;
    708                         cderrno = errno;
    709                 } else
    710                         descend = 1;
    711         } else
    712                 descend = 0;
    713745
    714746        /*
     
    723755         */
    724756        len = NAPPEND(cur);
    725         if (ISSET(FTS_NOCHDIR)) {
    726                 cp = sp->fts_path + len;
    727                 *cp++ = '/';
    728         } else {
    729                 /* GCC, you're too verbose. */
    730                 cp = NULL;
    731         }
     757        cp = sp->fts_path + len;
     758        *cp++ = '/';
    732759        len++;
    733760        maxlen = sp->fts_pathlen - len;
     
    737764        /* Read the directory, attaching each entry to the `link' pointer. */
    738765        doadjust = 0;
    739         for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
     766        for (head = tail = NULL, nitems = 0; dirp && (dp = birdDirRead(dirp));) {
    740767                dnamlen = dp->d_namlen;
    741768                if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
     
    756783                                        free(p);
    757784                                fts_lfree(head);
    758                                 (void)closedir(dirp);
     785                                birdDirClose(dirp);
     786                                birdCloseFile(cur->fts_dirfd);
     787                                cur->fts_dirfd = INVALID_HANDLE_VALUE;
    759788                                cur->fts_info = FTS_ERR;
    760789                                SET(FTS_STOP);
     
    774803                p->fts_parent = sp->fts_cur;
    775804                p->fts_pathlen = len + dnamlen;
    776 
    777 #ifdef FTS_WHITEOUT
    778                 if (dp->d_type == DT_WHT)
    779                         p->fts_flags |= FTS_ISW;
    780 #endif
    781 
    782                 if (cderrno) {
    783                         if (nlinks) {
    784                                 p->fts_info = FTS_NS;
    785                                 p->fts_errno = cderrno;
    786                         } else
    787                                 p->fts_info = FTS_NSOK;
    788                         p->fts_accpath = cur->fts_accpath;
    789                 } else if (nlinks == 0
    790 #ifdef DT_DIR
    791                     || (nostat &&
    792                     dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
    793 #endif
    794                     ) {
    795                         p->fts_accpath =
    796                             ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
    797                         p->fts_info = FTS_NSOK;
    798                 } else {
    799                         /* Build a file name for fts_stat to stat. */
    800                         if (ISSET(FTS_NOCHDIR)) {
    801                                 p->fts_accpath = p->fts_path;
    802                                 memmove(cp, p->fts_name, p->fts_namelen + 1);
    803                                 p->fts_info = fts_stat(sp, p, 0, _dirfd(dirp));
    804                         } else {
    805                                 p->fts_accpath = p->fts_name;
    806                                 p->fts_info = fts_stat(sp, p, 0, -1);
    807                         }
    808 
    809                         /* Decrement link count if applicable. */
    810                         if (nlinks > 0 && (p->fts_info == FTS_D ||
    811                             p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
    812                                 --nlinks;
    813                 }
     805                p->fts_accpath = p->fts_path;
     806                p->fts_stat = dp->d_stat;
     807                p->fts_info = fts_process_stats(p, &dp->d_stat);
    814808
    815809                /* We walk in directory order so "ls -f" doesn't get upset. */
     
    823817                ++nitems;
    824818        }
    825         if (dirp)
    826                 (void)closedir(dirp);
     819
     820        birdDirClose(dirp);
    827821
    828822        /*
     
    834828
    835829        /*
    836          * If not changing directories, reset the path back to original
    837          * state.
    838          */
    839         if (ISSET(FTS_NOCHDIR))
    840                 sp->fts_path[cur->fts_pathlen] = '\0';
    841 
    842         /*
    843          * If descended after called from fts_children or after called from
    844          * fts_read and nothing found, get back.  At the root level we use
    845          * the saved fd; if one of fts_open()'s arguments is a relative path
    846          * to an empty directory, we wind up here with no other way back.  If
    847          * can't get back, we're done.
    848          */
    849         if (descend && (type == BCHILD || !nitems) &&
    850             (cur->fts_level == FTS_ROOTLEVEL ?
    851             FCHDIR(sp, sp->fts_rfd) :
    852             fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
    853                 cur->fts_info = FTS_ERR;
    854                 SET(FTS_STOP);
    855                 return (NULL);
    856         }
     830         * Reset the path back to original state.
     831         */
     832        sp->fts_path[cur->fts_pathlen] = '\0';
    857833
    858834        /* If didn't find anything, return NULL. */
     
    869845}
    870846
     847
     848/**
     849 * @note Only used on NT with input arguments, FTS_AGAIN, and links that needs
     850 *       following.  On link information is generally retrieved during directory
     851 *       enumeration on NT, in line with it's DOS/OS2/FAT API heritage.
     852 */
    871853static int
    872 fts_stat(FTS *sp, FTSENT *p, int follow, int dfd)
    873 {
    874         FTSENT *t;
    875         dev_t dev;
    876         ino_t ino;
    877         struct stat *sbp, sb;
     854fts_stat(FTS *sp, FTSENT *p, int follow, HANDLE dfd)
     855{
    878856        int saved_errno;
    879857        const char *path;
    880858
    881         if (dfd == -1)
    882                 path = p->fts_accpath, dfd = AT_FDCWD;
    883         else
     859        if (dfd == INVALID_HANDLE_VALUE) {
     860                path = p->fts_accpath;
     861        } else {
    884862                path = p->fts_name;
    885 
    886         /* If user needs stat info, stat buffer already allocated. */
    887         sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
    888 
    889 #ifdef FTS_WHITEOUT
    890         /* Check for whiteout. */
    891         if (p->fts_flags & FTS_ISW) {
    892                 if (sbp != &sb) {
    893                         memset(sbp, '\0', sizeof(*sbp));
    894                         sbp->st_mode = S_IFWHT;
    895                 }
    896                 return (FTS_W);
    897         }
    898 #endif
     863        }
    899864
    900865        /*
     
    904869         */
    905870        if (ISSET(FTS_LOGICAL) || follow) {
    906                 if (fstatat(dfd, path, sbp, 0)) {
     871                if (fstatat(dfd, path, &p->fts_stat, 0)) {
    907872                        saved_errno = errno;
    908                         if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) {
     873                        if (fstatat(dfd, path, &p->fts_stat, AT_SYMLINK_NOFOLLOW)) {
    909874                                p->fts_errno = saved_errno;
    910875                                goto err;
    911876                        }
    912877                        errno = 0;
    913                         if (S_ISLNK(sbp->st_mode))
     878                        if (S_ISLNK(p->fts_stat.st_mode))
    914879                                return (FTS_SLNONE);
    915880                }
    916         } else if (fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) {
     881        } else if (fstatat(dfd, path, &p->fts_stat, AT_SYMLINK_NOFOLLOW)) {
    917882                p->fts_errno = errno;
    918 err:            memset(sbp, 0, sizeof(struct stat));
     883err:            memset(&p->fts_stat, 0, sizeof(struct stat));
    919884                return (FTS_NS);
    920885        }
    921 
     886        return fts_process_stats(p, &p->fts_stat);
     887}
     888
     889/* Shared between fts_stat and fts_build. */
     890static int
     891fts_process_stats(FTSENT *p, BirdStat_T const *sbp)
     892{
    922893        if (S_ISDIR(sbp->st_mode)) {
     894                FTSENT *t;
     895                fts_dev_t dev;
     896                fts_ino_t ino;
     897
    923898                /*
    924899                 * Set the device/inode.  Used to find cycles and check for
     
    984959         */
    985960        if (nitems > sp->fts_nitems) {
     961                void *ptr;
    986962                sp->fts_nitems = nitems + 40;
    987                 if ((sp->fts_array = reallocf(sp->fts_array,
    988                     sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
     963                ptr = realloc(sp->fts_array, sp->fts_nitems * sizeof(FTSENT *));
     964                if (ptr != NULL) {
     965                        sp->fts_array = ptr;
     966                } else {
     967                        free(sp->fts_array);
     968                        sp->fts_array = NULL;
    989969                        sp->fts_nitems = 0;
    990970                        return (head);
     
    1012992
    1013993        /*
    1014          * The file name is a variable length array and no stat structure is
    1015          * necessary if the user has set the nostat bit.  Allocate the FTSENT
    1016          * structure, the file name and the stat structure in one chunk, but
    1017          * be careful that the stat structure is reasonably aligned.
    1018          */
    1019         if (ISSET(FTS_NOSTAT))
    1020                 len = sizeof(FTSENT) + namelen + 1;
    1021         else
    1022                 len = sizeof(struct ftsent_withstat) + namelen + 1;
    1023 
     994         * The file name is a variable length array.  Allocate the FTSENT
     995         * structure and the file name.
     996         */
     997        len = sizeof(FTSENT) + namelen + 1;
    1024998        if ((p = malloc(len)) == NULL)
    1025999                return (NULL);
    10261000
    1027         if (ISSET(FTS_NOSTAT)) {
    1028                 p->fts_name = (char *)(p + 1);
    1029                 p->fts_statp = NULL;
    1030         } else {
    1031                 p->fts_name = (char *)((struct ftsent_withstat *)p + 1);
    1032                 p->fts_statp = &((struct ftsent_withstat *)p)->statbuf;
    1033         }
     1001        p->fts_name = (char *)(p + 1);
     1002        p->fts_statp = &p->fts_stat;
    10341003
    10351004        /* Copy the name and guarantee NUL termination. */
     
    10441013        p->fts_pointer = NULL;
    10451014        p->fts_fts = sp;
     1015        p->fts_symfd = INVALID_HANDLE_VALUE;
     1016        p->fts_dirfd = INVALID_HANDLE_VALUE;
    10461017        return (p);
    10471018}
     
    10551026        while ((p = head)) {
    10561027                head = head->fts_link;
     1028                assert(p->fts_dirfd == INVALID_HANDLE_VALUE);
    10571029                free(p);
    10581030        }
     
    10681040fts_palloc(FTS *sp, size_t more)
    10691041{
     1042        void *ptr;
    10701043
    10711044        sp->fts_pathlen += more + 256;
    1072         sp->fts_path = reallocf(sp->fts_path, sp->fts_pathlen);
    1073         return (sp->fts_path == NULL);
     1045        ptr = realloc(sp->fts_path, sp->fts_pathlen);
     1046        if (ptr) {
     1047                /*likely */
     1048        } else {
     1049                free(sp->fts_path);
     1050        }
     1051        sp->fts_path = ptr;
     1052        return (ptr == NULL);
    10741053}
    10751054
     
    11211100fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
    11221101{
     1102#if 0
    11231103        int ret, oerrno, newfd;
    11241104        struct stat sb;
    11251105
    11261106        newfd = fd;
     1107#endif
    11271108        if (ISSET(FTS_NOCHDIR))
    11281109                return (0);
     1110        assert(0);
     1111        return -1;
     1112#if 0
    11291113        if (fd < 0 && (newfd = _open(path, O_RDONLY | O_DIRECTORY |
    11301114            O_CLOEXEC, 0)) < 0)
     
    11461130        errno = oerrno;
    11471131        return (ret);
     1132#endif
    11481133}
    11491134
    11501135/*
    11511136 * Check if the filesystem for "ent" has UFS-style links.
     1137 *
     1138 * bird: NT does not, which is why they need this check.
     1139 *       See comment on r129052 (2004-05-08 15:09:02Z).
    11521140 */
    11531141static int
    11541142fts_ufslinks(FTS *sp, const FTSENT *ent)
    11551143{
     1144#if 0
    11561145        struct _fts_private *priv;
    11571146        const char **cpp;
     
    11801169        }
    11811170        return (priv->ftsp_linksreliable);
    1182 }
     1171#else
     1172        (void)sp; (void)ent;
     1173        return 0;
     1174#endif
     1175}
     1176
  • trunk/src/lib/nt/fts-nt.h

    r2983 r2985  
     1/* $Id: $ */
     2/** @file
     3 * Header for the NT port of BSD fts.h.
     4 *
     5 * @copyright   Copyright (c) 1989, 1993 The Regents of the University of California.  All rights reserved.
     6 * @copyright   NT modifications Copyright (C) 2016 knut st. osmundsen <bird-klibc-spam-xiv@anduin.net>
     7 * @licenses    BSD3
     8 */
     9
    110/*
    211 * Copyright (c) 1989, 1993
     
    2938 *      @(#)fts.h       8.3 (Berkeley) 8/14/94
    3039 * $FreeBSD$
     40 *
    3141 */
    3242
    33 #ifndef _FTS_H_
    34 #define _FTS_H_
     43#ifndef INCLUDED_FTS_NT_H
     44#define INCLUDED_FTS_NT_H
    3545
    36 #include <sys/_types.h>
     46#include <sys/types.h>
     47#include <stdint.h>
     48#include "ntstat.h" /* ensure correct stat structure */
     49
     50typedef uint64_t fts_dev_t;
     51typedef uint64_t fts_ino_t;
     52typedef uint32_t fts_nlink_t;
     53#ifdef _WINNT_
     54typedef HANDLE fts_fd_t;
     55#else
     56typedef void * fts_fd_t;
     57#endif
     58#define FTSCALL __cdecl
    3759
    3860typedef struct {
     
    4062        struct _ftsent *fts_child;      /* linked list of children */
    4163        struct _ftsent **fts_array;     /* sort array */
    42         __dev_t fts_dev;                /* starting device # */
     64        fts_dev_t fts_dev;              /* starting device # */
    4365        char *fts_path;                 /* path for this descent */
    44         int fts_rfd;                    /* fd for root */
    45         __size_t fts_pathlen;           /* sizeof(path) */
    46         __size_t fts_nitems;            /* elements in the sort array */
    47         int (*fts_compar)               /* compare function */
     66        size_t fts_pathlen;             /* sizeof(path) */
     67        size_t fts_nitems;              /* elements in the sort array */
     68        int (FTSCALL *fts_compar)       /* compare function */
    4869            (const struct _ftsent * const *, const struct _ftsent * const *);
    4970
     
    5576#define FTS_SEEDOT      0x020           /* return dot and dot-dot */
    5677#define FTS_XDEV        0x040           /* don't cross devices */
     78#if 0 /* No whiteout on NT. */
    5779#define FTS_WHITEOUT    0x080           /* return whiteout information */
     80#endif
    5881#define FTS_OPTIONMASK  0x0ff           /* valid user option mask */
    5982
     
    6891        struct _ftsent *fts_parent;     /* parent directory */
    6992        struct _ftsent *fts_link;       /* next file in directory */
    70         long long fts_number;           /* local numeric value */
     93        int64_t fts_number;             /* local numeric value */
    7194#define fts_bignum      fts_number      /* XXX non-std, should go away */
    7295        void *fts_pointer;              /* local address value */
     
    7497        char *fts_path;                 /* root path */
    7598        int fts_errno;                  /* errno for this node */
    76         int fts_symfd;                  /* fd for symlink */
    77         __size_t fts_pathlen;           /* strlen(fts_path) */
    78         __size_t fts_namelen;           /* strlen(fts_name) */
     99        fts_fd_t fts_symfd;             /* NT: Normally -1; -2 we followed this symlinked dir */
     100        fts_fd_t fts_dirfd;             /* NT: Handle to the directory */
     101        size_t fts_pathlen;             /* strlen(fts_path) */
     102        size_t fts_namelen;             /* strlen(fts_name) */
    79103
    80         __ino_t fts_ino;                /* inode */
    81         __dev_t fts_dev;                /* device */
    82         __nlink_t fts_nlink;            /* link count */
     104        fts_ino_t fts_ino;              /* inode */
     105        fts_dev_t fts_dev;              /* device */
     106        fts_nlink_t fts_nlink;          /* link count */
    83107
    84108#define FTS_ROOTPARENTLEVEL     -1
     
    99123#define FTS_SL          12              /* symbolic link */
    100124#define FTS_SLNONE      13              /* symbolic link without target */
    101 #define FTS_W           14              /* whiteout object */
     125//#define       FTS_W           14              /* whiteout object */
    102126        int fts_info;                   /* user status for FTSENT structure */
    103127
     
    116140        char *fts_name;                 /* file name */
    117141        FTS *fts_fts;                   /* back pointer to main FTS */
     142        BirdStat_T fts_stat;            /* NT: We always got stat info. */
    118143} FTSENT;
    119144
    120 #include <sys/cdefs.h>
    121145
    122 __BEGIN_DECLS
    123 FTSENT  *fts_children(FTS *, int);
    124 int      fts_close(FTS *);
    125 void    *fts_get_clientptr(FTS *);
     146#ifdef __cplusplus
     147extern "C" {
     148#endif
     149FTSENT  *FTSCALL fts_children(FTS *, int);
     150int      FTSCALL fts_close(FTS *);
     151void    *FTSCALL fts_get_clientptr(FTS *);
    126152#define  fts_get_clientptr(fts) ((fts)->fts_clientptr)
    127 FTS     *fts_get_stream(FTSENT *);
     153FTS     *FTSCALL fts_get_stream(FTSENT *);
    128154#define  fts_get_stream(ftsent) ((ftsent)->fts_fts)
    129 FTS     *fts_open(char * const *, int,
    130             int (*)(const FTSENT * const *, const FTSENT * const *));
    131 FTSENT  *fts_read(FTS *);
    132 int      fts_set(FTS *, FTSENT *, int);
    133 void     fts_set_clientptr(FTS *, void *);
    134 __END_DECLS
     155FTS     *FTSCALL fts_open(char * const *, int,
     156            int (FTSCALL*)(const FTSENT * const *, const FTSENT * const *));
     157FTSENT  *FTSCALL fts_read(FTS *);
     158int      FTSCALL fts_set(FTS *, FTSENT *, int);
     159void     FTSCALL fts_set_clientptr(FTS *, void *);
     160#ifdef __cplusplus
     161}
     162#endif
    135163
    136 #endif /* !_FTS_H_ */
     164#endif /* !INCLUDED_FTS_NT_H */
     165
  • trunk/src/lib/nt/kFsCache.c

    r2969 r2985  
    21712171        HANDLE      hDir;
    21722172        MY_NTSTATUS rcNt;
    2173         rcNt = birdOpenFileUniStr(&NtPath,
     2173        rcNt = birdOpenFileUniStr(NULL /*hRoot*/,
     2174                                  &NtPath,
    21742175                                  FILE_READ_DATA  | FILE_LIST_DIRECTORY | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
    21752176                                  FILE_ATTRIBUTE_NORMAL,
  • trunk/src/lib/nt/ntdir.c

    r2708 r2985  
    55
    66/*
    7  * Copyright (c) 2005-2013 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
     7 * Copyright (c) 2005-2016 knut st. osmundsen <bird-kBuild-spamx@anduin.net>
    88 *
    99 * Permission is hereby granted, free of charge, to any person obtaining a
     
    3636#include <errno.h>
    3737#include <malloc.h>
     38#include <assert.h>
    3839
    3940#include "ntstuff.h"
     
    4344
    4445/**
     46 * Implements opendir.
     47 */
     48BirdDir_T *birdDirOpen(const char *pszPath)
     49{
     50    HANDLE hDir = birdOpenFile(pszPath,
     51                               FILE_READ_DATA | SYNCHRONIZE,
     52                               FILE_ATTRIBUTE_NORMAL,
     53                               FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     54                               FILE_OPEN,
     55                               FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     56                               OBJ_CASE_INSENSITIVE);
     57    if (hDir != INVALID_HANDLE_VALUE)
     58    {
     59        BirdDir_T *pDir = birdDirOpenFromHandle((void *)hDir, NULL, BIRDDIR_F_CLOSE_HANDLE);
     60        if (pDir)
     61            return pDir;
     62        birdCloseFile(hDir);
     63    }
     64    return NULL;
     65}
     66
     67
     68/**
     69 * Alternative opendir, with extra stat() info returned by readdir().
     70 */
     71BirdDir_T *birdDirOpenExtraInfo(const char *pszPath)
     72{
     73    HANDLE hDir = birdOpenFile(pszPath,
     74                               FILE_READ_DATA | SYNCHRONIZE,
     75                               FILE_ATTRIBUTE_NORMAL,
     76                               FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     77                               FILE_OPEN,
     78                               FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     79                               OBJ_CASE_INSENSITIVE);
     80    if (hDir != INVALID_HANDLE_VALUE)
     81    {
     82        BirdDir_T *pDir = birdDirOpenFromHandle((void *)hDir, NULL, BIRDDIR_F_CLOSE_HANDLE | BIRDDIR_F_EXTRA_INFO);
     83        if (pDir)
     84            return pDir;
     85        birdCloseFile(hDir);
     86    }
     87    return NULL;
     88}
     89
     90
     91BirdDir_T *birdDirOpenExW(void *hRoot, const wchar_t *pwszPath, const wchar_t *pwszFilter, unsigned fFlags)
     92{
     93    HANDLE hDir = birdOpenFileExW((HANDLE)hRoot,
     94                                  pwszPath,
     95                                  FILE_READ_DATA | SYNCHRONIZE,
     96                                  FILE_ATTRIBUTE_NORMAL,
     97                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     98                                  FILE_OPEN,
     99                                  FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     100                                  OBJ_CASE_INSENSITIVE);
     101    if (hDir != INVALID_HANDLE_VALUE)
     102    {
     103        BirdDir_T *pDir = birdDirOpenFromHandle((void *)hDir, pwszFilter, fFlags | BIRDDIR_F_CLOSE_HANDLE);
     104        if (pDir)
     105            return pDir;
     106        birdCloseFile(hDir);
     107    }
     108    return NULL;
     109}
     110
     111
     112/**
    45113 * Internal worker for birdStatModTimeOnly.
    46114 */
    47 static BirdDir_T *birdDirOpenInternal(const char *pszPath, const char *pszFilter, int fMinimalInfo)
    48 {
    49     HANDLE hFile = birdOpenFile(pszPath,
    50                                 FILE_READ_DATA | SYNCHRONIZE,
    51                                 FILE_ATTRIBUTE_NORMAL,
    52                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    53                                 FILE_OPEN,
    54                                 FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
    55                                 OBJ_CASE_INSENSITIVE);
    56     if (hFile != INVALID_HANDLE_VALUE)
     115BirdDir_T *birdDirOpenFromHandle(void *pvHandle, const void *pvReserved, unsigned fFlags)
     116{
     117    if (!pvReserved)
    57118    {
    58119        /*
    59          * Allocate a handle.
     120         * Allocate and initialize the directory enum handle.
    60121         */
    61122        BirdDir_T *pDir = (BirdDir_T *)birdMemAlloc(sizeof(*pDir));
    62123        if (pDir)
    63124        {
    64             pDir->uMagic     = BIRD_DIR_MAGIC;
    65             pDir->pvHandle   = (void *)hFile;
    66             pDir->uDev       = 0;
    67             pDir->offPos     = 0;
    68             pDir->fHaveData  = 0;
    69             pDir->fFirst     = 1;
    70             pDir->iInfoClass = fMinimalInfo ? MyFileNamesInformation : MyFileIdFullDirectoryInformation;
    71             pDir->offBuf     = 0;
    72             pDir->cbBuf      = 0;
    73             pDir->pabBuf     = NULL;
     125            pDir->uMagic        = BIRD_DIR_MAGIC;
     126            pDir->fFlags        = fFlags;
     127            pDir->pvHandle      = pvHandle;
     128            pDir->uDev          = 0;
     129            pDir->offPos        = 0;
     130            pDir->fHaveData     = 0;
     131            pDir->fFirst        = 1;
     132            pDir->iInfoClass    = fFlags & BIRDDIR_F_EXTRA_INFO ? MyFileIdFullDirectoryInformation : MyFileNamesInformation;
     133            pDir->offBuf        = 0;
     134            pDir->cbBuf         = 0;
     135            pDir->pabBuf        = NULL;
    74136            return pDir;
    75137        }
    76 
    77         birdCloseFile(hFile);
    78         birdSetErrnoToNoMem();
    79     }
    80 
     138    }
     139    else
     140        assert(pvReserved == NULL);
     141    birdSetErrnoToNoMem();
    81142    return NULL;
    82 }
    83 
    84 
    85 /**
    86  * Implements opendir.
    87  */
    88 BirdDir_T *birdDirOpen(const char *pszPath)
    89 {
    90     return birdDirOpenInternal(pszPath, NULL, 1 /*fMinimalInfo*/);
    91 }
    92 
    93 
    94 /**
    95  * Alternative opendir, with extra stat() info returned by readdir().
    96  */
    97 BirdDir_T *birdDirOpenExtraInfo(const char *pszPath)
    98 {
    99     return birdDirOpenInternal(pszPath, NULL, 0 /*fMinimalInfo*/);
    100143}
    101144
     
    158201                                     FALSE,     /* fReturnSingleEntry */
    159202                                     NULL,      /* Filter / restart pos. */
    160                                      FALSE);    /* fRestartScan */
     203                                     pDir->fFlags & BIRDDIR_F_RESTART_SCAN ? TRUE : FALSE); /* fRestartScan */
    161204    if (!MY_NT_SUCCESS(rcNt))
    162205    {
     
    173216    pDir->offBuf    = 0;
    174217    pDir->fHaveData = 1;
     218    pDir->fFlags    &= ~BIRDDIR_F_RESTART_SCAN;
    175219
    176220    return 0;
     
    355399
    356400    pDir->uMagic++;
    357     birdCloseFile((HANDLE)pDir->pvHandle);
     401    if (pDir->fFlags & BIRDDIR_F_CLOSE_HANDLE)
     402        birdCloseFile((HANDLE)pDir->pvHandle);
    358403    pDir->pvHandle = (void *)INVALID_HANDLE_VALUE;
    359404    birdMemFree(pDir->pabBuf);
  • trunk/src/lib/nt/ntdir.h

    r2708 r2985  
    6565/** @}  */
    6666
     67/** @name BIRDDIR_F_XXX - birdDirOpenFromHandle & BirdDir_T::fFlags
     68 * @{ */
     69/** birdDirClose should also close pvHandle.  */
     70#define BIRDDIR_F_CLOSE_HANDLE  1U
     71/** birdDirClose should not close the handle.  */
     72#define BIRDDIR_F_KEEP_HANDLE   0U
     73/** Provide extra info (stat). */
     74#define BIRDDIR_F_EXTRA_INFO    2U
     75/** Whether to restart the scan. */
     76#define BIRDDIR_F_RESTART_SCAN  4U
     77/** @} */
     78
    6779typedef struct BirdDir
    6880{
    6981    /** Magic value. */
    7082    unsigned            uMagic;
     83    /** Flags. */
     84    unsigned            fFlags;
    7185    /** The directory handle. */
    7286    void               *pvHandle;
     
    98112BirdDir_T      *birdDirOpen(const char *pszPath);
    99113BirdDir_T      *birdDirOpenExtraInfo(const char *pszPath);
     114BirdDir_T      *birdDirOpenExW(void *hRoot, const wchar_t *pwszPath, const wchar_t *pwszFilter, unsigned fFlags);
     115BirdDir_T      *birdDirOpenFromHandle(void *hDir, const void *pvReserved, unsigned fFlags);
    100116BirdDirEntry_T *birdDirRead(BirdDir_T *pDir);
    101117long            birdDirTell(BirdDir_T *pDir);
  • trunk/src/lib/nt/nthlp.h

    r2862 r2985  
    5555
    5656
    57 HANDLE      birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
    58                          ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs);
    59 HANDLE      birdOpenParentDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
    60                               ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
     57HANDLE      birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     58                         ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs);
     59HANDLE      birdOpenFileW(const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     60                          ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs);
     61HANDLE      birdOpenFileEx(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     62                           ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs);
     63HANDLE      birdOpenFileExW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     64                            ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs);
     65HANDLE      birdOpenParentDir(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     66                              ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
    6167                              MY_UNICODE_STRING *pNameUniStr);
    62 MY_NTSTATUS birdOpenFileUniStr(MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     68HANDLE      birdOpenParentDirW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     69                               ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
     70                               MY_UNICODE_STRING *pNameUniStr);
     71MY_NTSTATUS birdOpenFileUniStr(HANDLE hRoot, MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
    6372                               ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
    6473                               HANDLE *phFile);
     74HANDLE      birdOpenCurrentDirectory(void);
    6575void        birdCloseFile(HANDLE hFile);
    6676int         birdDosToNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath);
  • trunk/src/lib/nt/nthlpcore.c

    r2913 r2985  
    4646                                        PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
    4747MY_NTSTATUS (WINAPI *g_pfnNtDeleteFile)(MY_OBJECT_ATTRIBUTES *);
     48MY_NTSTATUS (WINAPI *g_pfnNtDuplicateObject)(HANDLE hSrcProc, HANDLE hSrc, HANDLE hDstProc, HANDLE *phRet,
     49                                             MY_ACCESS_MASK fDesiredAccess, ULONG fAttribs, ULONG fOptions);
    4850MY_NTSTATUS (WINAPI *g_pfnNtReadFile)(HANDLE hFile, HANDLE hEvent, MY_IO_APC_ROUTINE *pfnApc, PVOID pvApcCtx,
    4951                                      MY_IO_STATUS_BLOCK *, PVOID pvBuf, ULONG cbToRead, PLARGE_INTEGER poffFile,
     
    6365UCHAR       (WINAPI *g_pfnRtlUpperChar)(UCHAR uch);
    6466ULONG       (WINAPI *g_pfnRtlNtStatusToDosError)(MY_NTSTATUS rcNt);
     67VOID        (WINAPI *g_pfnRtlAcquirePebLock)(VOID);
     68VOID        (WINAPI *g_pfnRtlReleasePebLock)(VOID);
    6569
    6670
     
    7478    { (FARPROC *)&g_pfnNtCreateFile,                    "NtCreateFile" },
    7579    { (FARPROC *)&g_pfnNtDeleteFile,                    "NtDeleteFile" },
     80    { (FARPROC *)&g_pfnNtDuplicateObject,               "NtDuplicateObject" },
    7681    { (FARPROC *)&g_pfnNtReadFile,                      "NtReadFile" },
    7782    { (FARPROC *)&g_pfnNtQueryInformationFile,          "NtQueryInformationFile" },
     
    8792    { (FARPROC *)&g_pfnRtlUpperChar,                    "RtlUpperChar" },
    8893    { (FARPROC *)&g_pfnRtlNtStatusToDosError,           "RtlNtStatusToDosError" },
     94    { (FARPROC *)&g_pfnRtlAcquirePebLock,               "RtlAcquirePebLock" },
     95    { (FARPROC *)&g_pfnRtlReleasePebLock,               "RtlReleasePebLock" },
    8996};
    9097/** Set to 1 if we've successfully resolved the imports, otherwise 0. */
  • trunk/src/lib/nt/nthlpfs.c

    r2713 r2985  
    3434*******************************************************************************/
    3535#include "nthlp.h"
     36#include <stddef.h>
     37#include <string.h>
     38#include <wchar.h>
     39#include <errno.h>
    3640
    3741
     
    6165
    6266
     67static int birdHasTrailingSlashW(const wchar_t *pwszPath)
     68{
     69    wchar_t wc, wc2;
     70
     71    /* Skip leading slashes. */
     72    while ((wc = *pwszPath) == '/' || wc == '\\')
     73        pwszPath++;
     74    if (wc == '\0')
     75        return 0;
     76
     77    /* Find the last char. */
     78    while ((wc2 = *++pwszPath) != '\0')
     79        wc = wc2;
     80
     81    return wc == '/' || wc == '\\' || wc == ':';
     82}
     83
     84
    6385static int birdIsPathDirSpec(const char *pszPath)
    6486{
     
    7597
    7698    return ch == '/' || ch == '\\' || ch == ':';
     99}
     100
     101
     102static int birdIsPathDirSpecW(const wchar_t *pwszPath)
     103{
     104    wchar_t wc, wc2;
     105
     106    /* Check for empty string. */
     107    wc = *pwszPath;
     108    if (wc == '\0')
     109        return 0;
     110
     111    /* Find the last char. */
     112    while ((wc2 = *++pwszPath) != '\0')
     113        wc = wc2;
     114
     115    return wc == '/' || wc == '\\' || wc == ':';
    77116}
    78117
     
    119158
    120159
     160int birdDosToNtPathW(const wchar_t *pwszPath, MY_UNICODE_STRING *pNtPath)
     161{
     162    birdResolveImports();
     163
     164    pNtPath->Length = pNtPath->MaximumLength = 0;
     165    pNtPath->Buffer = NULL;
     166
     167    /*
     168     * Convert the wide DOS path to an NT path.
     169     */
     170    if (g_pfnRtlDosPathNameToNtPathName_U(pwszPath, pNtPath, NULL, FALSE))
     171        return 0;
     172    return birdSetErrnoFromNt(STATUS_NO_MEMORY);
     173}
     174
     175
     176/**
     177 * Converts UNIX slashes to DOS ones and trims trailing ones.
     178 *
     179 * @returns 0
     180 * @param   pNtPath     The relative NT path to fix up.
     181 */
     182static int birdFixRelativeNtPathSlashesAndReturn0(MY_UNICODE_STRING *pNtPath)
     183{
     184    size_t   cwcLeft  = pNtPath->Length / sizeof(wchar_t);
     185    wchar_t *pwcStart = pNtPath->Buffer;
     186    wchar_t *pwcHit;
     187
     188    /* Convert slashes. */
     189    while ((pwcHit = wmemchr(pwcStart,  '/', cwcLeft)) != NULL)
     190    {
     191        *pwcHit = '\\';
     192        cwcLeft -= pwcHit - pwcStart;
     193        pwcHit = pwcStart;
     194    }
     195
     196    /* Strip trailing slashes (NT doesn't like them). */
     197    while (   pNtPath->Length >= sizeof(wchar_t)
     198           && pNtPath->Buffer[(pNtPath->Length - sizeof(wchar_t)) / sizeof(wchar_t)] == '\\')
     199    {
     200        pNtPath->Length -= sizeof(wchar_t);
     201        pNtPath->Buffer[pNtPath->Length / sizeof(wchar_t)] = '\0';
     202    }
     203
     204    /* If it was all trailing slashes we convert it to a dot path. */
     205    if (   pNtPath->Length == 0
     206        && pNtPath->MaximumLength >= sizeof(wchar_t) * 2)
     207    {
     208        pNtPath->Length = sizeof(wchar_t);
     209        pNtPath->Buffer[0] = '.';
     210        pNtPath->Buffer[1] = '\0';
     211    }
     212
     213    return 0;
     214}
     215
     216
     217/**
     218 * Similar to birdDosToNtPath, but it does call RtlDosPathNameToNtPathName_U.
     219 *
     220 * @returns 0 on success, -1 + errno on failure.
     221 * @param   pszPath     The relative path.
     222 * @param   pNtPath     Where to return the NT path.  Call birdFreeNtPath when done.
     223 */
     224int birdDosToRelativeNtPath(const char *pszPath, MY_UNICODE_STRING *pNtPath)
     225{
     226    MY_NTSTATUS         rcNt;
     227    MY_ANSI_STRING      Src;
     228
     229    birdResolveImports();
     230
     231    /*
     232     * Just convert to wide char.
     233     */
     234    pNtPath->Length   = pNtPath->MaximumLength = 0;
     235    pNtPath->Buffer   = NULL;
     236
     237    Src.Buffer        = (PCHAR)pszPath;
     238    Src.MaximumLength = Src.Length = (USHORT)strlen(pszPath);
     239
     240    rcNt = g_pfnRtlAnsiStringToUnicodeString(pNtPath, &Src, TRUE /* Allocate */);
     241    if (MY_NT_SUCCESS(rcNt))
     242        return birdFixRelativeNtPathSlashesAndReturn0(pNtPath);
     243    return birdSetErrnoFromNt(rcNt);
     244}
     245
     246
     247/**
     248 * Similar to birdDosToNtPathW, but it does call RtlDosPathNameToNtPathName_U.
     249 *
     250 * @returns 0 on success, -1 + errno on failure.
     251 * @param   pwszPath    The relative path.
     252 * @param   pNtPath     Where to return the NT path.  Call birdFreeNtPath when done.
     253 */
     254int birdDosToRelativeNtPathW(const wchar_t *pwszPath, MY_UNICODE_STRING *pNtPath)
     255{
     256    size_t cwcPath = wcslen(pwszPath);
     257    if (cwcPath < 0xfffe)
     258    {
     259        pNtPath->Length = (USHORT)(cwcPath * sizeof(wchar_t));
     260        pNtPath->MaximumLength = pNtPath->Length + sizeof(wchar_t);
     261        pNtPath->Buffer = HeapAlloc(GetProcessHeap(), 0, pNtPath->MaximumLength);
     262        if (pNtPath->Buffer)
     263        {
     264            memcpy(pNtPath->Buffer, pwszPath, pNtPath->MaximumLength);
     265            return birdFixRelativeNtPathSlashesAndReturn0(pNtPath);
     266        }
     267        errno = ENOMEM;
     268    }
     269    else
     270        errno = ENAMETOOLONG;
     271    return -1;
     272}
     273
     274
     275/**
     276 * Frees a string returned by birdDosToNtPath, birdDosToNtPathW or
     277 * birdDosToRelativeNtPath.
     278 *
     279 * @param   pNtPath             The the NT path to free.
     280 */
    121281void birdFreeNtPath(MY_UNICODE_STRING *pNtPath)
    122282{
     
    128288
    129289
    130 MY_NTSTATUS birdOpenFileUniStr(MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     290MY_NTSTATUS birdOpenFileUniStr(HANDLE hRoot, MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
    131291                               ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
    132292                               HANDLE *phFile)
     
    144304    Ios.Information = -1;
    145305    Ios.u.Status = 0;
    146     MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, NULL /*hRoot*/, NULL /*pSecAttr*/);
     306    MyInitializeObjectAttributes(&ObjAttr, pNtPath, fObjAttribs, hRoot, NULL /*pSecAttr*/);
    147307
    148308    rcNt = g_pfnNtCreateFile(phFile,
     
    185345
    186346
    187 HANDLE birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
    188                     ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
     347HANDLE birdOpenFile(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     348                    ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
    189349{
    190350    MY_UNICODE_STRING   NtPath;
     
    198358
    199359    /*
    200      * Call the NT API directly.
     360     * Convert the path and call birdOpenFileUniStr to do the real work.
    201361     */
    202362    if (birdDosToNtPath(pszPath, &NtPath) == 0)
    203363    {
    204364        HANDLE hFile;
    205         rcNt = birdOpenFileUniStr(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
     365        rcNt = birdOpenFileUniStr(NULL /*hRoot*/, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
    206366                                  fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
     367        birdFreeNtPath(&NtPath);
     368        if (MY_NT_SUCCESS(rcNt))
     369            return hFile;
     370        birdSetErrnoFromNt(rcNt);
     371    }
     372
     373    return INVALID_HANDLE_VALUE;
     374}
     375
     376
     377HANDLE birdOpenFileW(const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     378                     ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
     379{
     380    MY_UNICODE_STRING   NtPath;
     381    MY_NTSTATUS         rcNt;
     382
     383    /*
     384     * Adjust inputs.
     385     */
     386    if (birdIsPathDirSpecW(pwszPath))
     387        fCreateOptions |= FILE_DIRECTORY_FILE;
     388
     389    /*
     390     * Convert the path and call birdOpenFileUniStr to do the real work.
     391     */
     392    if (birdDosToNtPathW(pwszPath, &NtPath) == 0)
     393    {
     394        HANDLE hFile;
     395        rcNt = birdOpenFileUniStr(NULL /*hRoot*/, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
     396                                  fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
     397        birdFreeNtPath(&NtPath);
     398        if (MY_NT_SUCCESS(rcNt))
     399            return hFile;
     400        birdSetErrnoFromNt(rcNt);
     401    }
     402
     403    return INVALID_HANDLE_VALUE;
     404}
     405
     406
     407HANDLE birdOpenFileEx(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     408                      ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
     409{
     410    MY_UNICODE_STRING   NtPath;
     411    MY_NTSTATUS         rcNt;
     412
     413    /*
     414     * Adjust inputs.
     415     */
     416    if (birdIsPathDirSpec(pszPath))
     417        fCreateOptions |= FILE_DIRECTORY_FILE;
     418
     419    /*
     420     * Convert the path and call birdOpenFileUniStr to do the real work.
     421     */
     422    if (hRoot == INVALID_HANDLE_VALUE)
     423        hRoot = NULL;
     424    if ((hRoot != NULL ? birdDosToRelativeNtPath(pszPath, &NtPath) : birdDosToNtPath(pszPath, &NtPath)) == 0)
     425    {
     426        HANDLE hFile;
     427        rcNt = birdOpenFileUniStr(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
     428                                  fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
     429        birdFreeNtPath(&NtPath);
     430        if (MY_NT_SUCCESS(rcNt))
     431            return hFile;
     432        birdSetErrnoFromNt(rcNt);
     433    }
     434
     435    return INVALID_HANDLE_VALUE;
     436}
     437
     438
     439HANDLE birdOpenFileExW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     440                       ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs)
     441{
     442    MY_UNICODE_STRING   NtPath;
     443    MY_NTSTATUS         rcNt;
     444
     445    /*
     446     * Adjust inputs.
     447     */
     448    if (birdIsPathDirSpecW(pwszPath))
     449        fCreateOptions |= FILE_DIRECTORY_FILE;
     450
     451    /*
     452     * Convert the path (could save ourselves this if pwszPath is perfect) and
     453     * call birdOpenFileUniStr to do the real work.
     454     */
     455    if (hRoot == INVALID_HANDLE_VALUE)
     456        hRoot = NULL;
     457    if ((hRoot != NULL ? birdDosToRelativeNtPathW(pwszPath, &NtPath) : birdDosToNtPathW(pwszPath, &NtPath)) == 0)
     458    {
     459        HANDLE hFile;
     460        rcNt = birdOpenFileUniStr(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
     461                                  fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
     462        birdFreeNtPath(&NtPath);
     463        if (MY_NT_SUCCESS(rcNt))
     464            return hFile;
     465        birdSetErrnoFromNt(rcNt);
     466    }
     467
     468    return INVALID_HANDLE_VALUE;
     469}
     470
     471
     472static HANDLE birdOpenParentDirCommon(HANDLE hRoot, MY_UNICODE_STRING *pNtPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     473                                      ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
     474                                      MY_UNICODE_STRING *pNameUniStr)
     475{
     476    MY_NTSTATUS rcNt;
     477
     478    /*
     479     * Strip the path down to the directory.
     480     */
     481    USHORT offName = pNtPath->Length / sizeof(WCHAR);
     482    USHORT cwcName = offName;
     483    WCHAR  wc = 0;
     484    while (   offName > 0
     485           && (wc = pNtPath->Buffer[offName - 1]) != '\\'
     486           && wc != '/'
     487           && wc != ':')
     488        offName--;
     489    if (   offName > 0
     490        || (hRoot != NULL && cwcName > 0))
     491    {
     492        cwcName -= offName;
     493
     494        /* Make a copy of the file name, if requested. */
     495        rcNt = STATUS_SUCCESS;
     496        if (pNameUniStr)
     497        {
     498            pNameUniStr->Length        = cwcName * sizeof(WCHAR);
     499            pNameUniStr->MaximumLength = pNameUniStr->Length + sizeof(WCHAR);
     500            pNameUniStr->Buffer        = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, pNameUniStr->MaximumLength);
     501            if (pNameUniStr->Buffer)
     502            {
     503                memcpy(pNameUniStr->Buffer, &pNtPath->Buffer[offName], pNameUniStr->Length);
     504                pNameUniStr->Buffer[cwcName] = '\0';
     505            }
     506            else
     507                rcNt = STATUS_NO_MEMORY;
     508        }
     509
     510        /* Chop, chop. */
     511        // Bad idea, breaks \\?\c:\pagefile.sys. //while (   offName > 0
     512        // Bad idea, breaks \\?\c:\pagefile.sys. //       && (   (wc = pNtPath->Buffer[offName - 1]) == '\\'
     513        // Bad idea, breaks \\?\c:\pagefile.sys. //           || wc == '/'))
     514        // Bad idea, breaks \\?\c:\pagefile.sys. //    offName--;
     515        if (offName == 0)
     516            pNtPath->Buffer[offName++] = '.'; /* Hack for dir handle + dir entry name. */
     517        pNtPath->Length = offName * sizeof(WCHAR);
     518        pNtPath->Buffer[offName] = '\0';
    207519        if (MY_NT_SUCCESS(rcNt))
    208520        {
    209             birdFreeNtPath(&NtPath);
    210             return hFile;
    211         }
    212 
    213         birdFreeNtPath(&NtPath);
    214         birdSetErrnoFromNt(rcNt);
    215     }
    216 
    217     return INVALID_HANDLE_VALUE;
    218 }
    219 
    220 
    221 HANDLE birdOpenParentDir(const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs, ULONG fShareAccess,
    222                          ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
    223                          MY_UNICODE_STRING *pNameUniStr)
    224 {
    225     MY_UNICODE_STRING   NtPath;
    226     MY_NTSTATUS         rcNt;
    227 
    228     /*
    229      * Adjust inputs.
    230      */
    231     fCreateOptions |= FILE_DIRECTORY_FILE;
    232 
    233     /*
    234      * Convert the path and split off the filename.
    235      */
    236     if (birdDosToNtPath(pszPath, &NtPath) == 0)
    237     {
    238         USHORT offName = NtPath.Length / sizeof(WCHAR);
    239         USHORT cwcName = offName;
    240         WCHAR  wc = 0;
    241 
    242         while (   offName > 0
    243                && (wc = NtPath.Buffer[offName - 1]) != '\\'
    244                && wc != '/'
    245                && wc != ':')
    246             offName--;
    247         if (offName > 0)
    248         {
    249             cwcName -= offName;
    250 
    251             /* Make a copy of the file name, if requested. */
    252             rcNt = STATUS_SUCCESS;
    253             if (pNameUniStr)
    254             {
    255                 pNameUniStr->Length        = cwcName * sizeof(WCHAR);
    256                 pNameUniStr->MaximumLength = pNameUniStr->Length + sizeof(WCHAR);
    257                 pNameUniStr->Buffer        = (WCHAR *)HeapAlloc(GetProcessHeap(), 0, pNameUniStr->MaximumLength);
    258                 if (pNameUniStr->Buffer)
    259                 {
    260                     memcpy(pNameUniStr->Buffer, &NtPath.Buffer[offName],pNameUniStr->Length);
    261                     pNameUniStr->Buffer[cwcName] = '\0';
    262                 }
    263                 else
    264                     rcNt = STATUS_NO_MEMORY;
    265             }
    266 
    267             /* Chop, chop. */
    268             // Bad idea, breaks \\?\c:\pagefile.sys. //while (   offName > 0
    269             // Bad idea, breaks \\?\c:\pagefile.sys. //       && (   (wc = NtPath.Buffer[offName - 1]) == '\\'
    270             // Bad idea, breaks \\?\c:\pagefile.sys. //           || wc == '/'))
    271             // Bad idea, breaks \\?\c:\pagefile.sys. //    offName--;
    272             NtPath.Length = offName * sizeof(WCHAR);
    273             NtPath.Buffer[offName] = '\0';
     521            /*
     522             * Finally, try open the directory.
     523             */
     524            HANDLE hFile;
     525            fCreateOptions |= FILE_DIRECTORY_FILE;
     526            rcNt = birdOpenFileUniStr(hRoot, pNtPath, fDesiredAccess, fFileAttribs, fShareAccess,
     527                                      fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
    274528            if (MY_NT_SUCCESS(rcNt))
    275529            {
    276                 /*
    277                  * Finally, try open the directory.
    278                  */
    279                 HANDLE hFile;
    280                 rcNt = birdOpenFileUniStr(&NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
    281                                           fCreateDisposition, fCreateOptions, fObjAttribs, &hFile);
    282                 if (MY_NT_SUCCESS(rcNt))
    283                 {
    284                     birdFreeNtPath(&NtPath);
    285                     return hFile;
    286                 }
     530                birdFreeNtPath(pNtPath);
     531                return hFile;
    287532            }
    288 
    289             if (pNameUniStr)
    290                 birdFreeNtPath(pNameUniStr);
    291533        }
    292534
    293         birdFreeNtPath(&NtPath);
    294         birdSetErrnoFromNt(rcNt);
    295     }
    296 
     535        if (pNameUniStr)
     536            birdFreeNtPath(pNameUniStr);
     537    }
     538    else
     539        rcNt = STATUS_INVALID_PARAMETER;
     540
     541    birdFreeNtPath(pNtPath);
     542    birdSetErrnoFromNt(rcNt);
    297543    return INVALID_HANDLE_VALUE;
     544}
     545
     546
     547HANDLE birdOpenParentDir(HANDLE hRoot, const char *pszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     548                         ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
     549                         MY_UNICODE_STRING *pNameUniStr)
     550{
     551    /*
     552     * Convert the path and join up with the UTF-16 version (it'll free NtPath).
     553     */
     554    MY_UNICODE_STRING NtPath;
     555    if (hRoot == INVALID_HANDLE_VALUE)
     556        hRoot = NULL;
     557    if (  hRoot == NULL
     558        ? birdDosToNtPath(pszPath, &NtPath) == 0
     559        : birdDosToRelativeNtPath(pszPath, &NtPath) == 0)
     560        return birdOpenParentDirCommon(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
     561                                       fCreateDisposition, fCreateOptions, fObjAttribs, pNameUniStr);
     562    return INVALID_HANDLE_VALUE;
     563}
     564
     565
     566HANDLE birdOpenParentDirW(HANDLE hRoot, const wchar_t *pwszPath, ACCESS_MASK fDesiredAccess, ULONG fFileAttribs,
     567                          ULONG fShareAccess, ULONG fCreateDisposition, ULONG fCreateOptions, ULONG fObjAttribs,
     568                          MY_UNICODE_STRING *pNameUniStr)
     569{
     570    /*
     571     * Convert the path and join up with the ansi version (it'll free NtPath).
     572     */
     573    MY_UNICODE_STRING NtPath;
     574    if (hRoot == INVALID_HANDLE_VALUE)
     575        hRoot = NULL;
     576    if (  hRoot == NULL
     577        ? birdDosToNtPathW(pwszPath, &NtPath) == 0
     578        : birdDosToRelativeNtPathW(pwszPath, &NtPath) == 0)
     579        return birdOpenParentDirCommon(hRoot, &NtPath, fDesiredAccess, fFileAttribs, fShareAccess,
     580                                       fCreateDisposition, fCreateOptions, fObjAttribs, pNameUniStr);
     581    return INVALID_HANDLE_VALUE;
     582}
     583
     584
     585/**
     586 * Returns a handle to the current working directory of the process.
     587 *
     588 * @returns CWD handle with FILE_TRAVERSE and SYNCHRONIZE access.  May return
     589 *          INVALID_HANDLE_VALUE w/ errno for invalid CWD.
     590 */
     591HANDLE birdOpenCurrentDirectory(void)
     592{
     593    PMY_RTL_USER_PROCESS_PARAMETERS pProcParams;
     594    MY_NTSTATUS rcNt;
     595    HANDLE hRet = INVALID_HANDLE_VALUE;
     596
     597    birdResolveImports();
     598
     599    /*
     600     * We'll try get this from the PEB.
     601     */
     602    g_pfnRtlAcquirePebLock();
     603    pProcParams = (PMY_RTL_USER_PROCESS_PARAMETERS)MY_NT_CURRENT_PEB()->ProcessParameters;
     604    if (pProcParams != NULL)
     605        rcNt = g_pfnNtDuplicateObject(MY_NT_CURRENT_PROCESS, pProcParams->CurrentDirectory.Handle,
     606                                      MY_NT_CURRENT_PROCESS, &hRet,
     607                                      FILE_TRAVERSE | SYNCHRONIZE,
     608                                      0 /*fAttribs*/,
     609                                      0 /*fOptions*/);
     610    else
     611        rcNt = STATUS_INVALID_PARAMETER;
     612    g_pfnRtlReleasePebLock();
     613    if (MY_NT_SUCCESS(rcNt))
     614        return hRet;
     615
     616    /*
     617     * Fallback goes thru birdOpenFileW.
     618     */
     619    return birdOpenFileW(L".",
     620                         FILE_TRAVERSE | SYNCHRONIZE,
     621                         FILE_ATTRIBUTE_NORMAL,
     622                         FILE_SHARE_READ | FILE_SHARE_WRITE,
     623                         FILE_OPEN,
     624                         FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     625                         OBJ_CASE_INSENSITIVE);
    298626}
    299627
  • trunk/src/lib/nt/ntstat.c

    r2880 r2985  
    9393
    9494
    95 static int birdIsFileExecutableW(WCHAR const *pwcName, ULONG cwcName)
     95/**
     96 * @a pwcName could be the full path.
     97 */
     98static int birdIsFileExecutableW(WCHAR const *pwcName, size_t cwcName)
    9699{
    97100    char            szExt[8];
     
    128131
    129132static unsigned short birdFileInfoToMode(HANDLE hFile, ULONG fAttribs, const char *pszName,
    130                                          MY_FILE_NAME_INFORMATION *pNameInfo, __int16 *pfIsDirSymlink)
     133                                         const wchar_t *pwszName, size_t cbNameW, __int16 *pfIsDirSymlink)
    131134{
    132135    unsigned short fMode;
     
    169172        || (pszName
    170173            ? birdIsFileExecutable(pszName)
    171             : birdIsFileExecutableW(pNameInfo->FileName, pNameInfo->FileNameLength)) )
     174            : birdIsFileExecutableW(pwszName, cbNameW)) )
    172175        fMode |= S_IXOTH | S_IXGRP | S_IXUSR;
    173176
     
    186189void birdStatFillFromFileIdFullDirInfo(BirdStat_T *pStat, MY_FILE_ID_FULL_DIR_INFORMATION const *pBuf, const char *pszPath)
    187190{
    188     pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes, pszPath,
    189                                                  NULL, &pStat->st_dirsymlink);
     191    pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes,
     192                                                 pszPath, pBuf->FileName, pBuf->FileNameLength, &pStat->st_dirsymlink);
    190193    pStat->st_padding0[0]   = 0;
    191194    pStat->st_padding0[1]   = 0;
     
    218221void birdStatFillFromFileIdBothDirInfo(BirdStat_T *pStat, MY_FILE_ID_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath)
    219222{
    220     pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes, pszPath,
    221                                                  NULL, &pStat->st_dirsymlink);
     223    pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes,
     224                                                 pszPath, pBuf->FileName, pBuf->FileNameLength, &pStat->st_dirsymlink);
    222225    pStat->st_padding0[0]   = 0;
    223226    pStat->st_padding0[1]   = 0;
     
    250253void birdStatFillFromFileBothDirInfo(BirdStat_T *pStat, MY_FILE_BOTH_DIR_INFORMATION const *pBuf, const char *pszPath)
    251254{
    252     pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes, pszPath,
    253                                                  NULL, &pStat->st_dirsymlink);
     255    pStat->st_mode          = birdFileInfoToMode(INVALID_HANDLE_VALUE, pBuf->FileAttributes,
     256                                                 pszPath, pBuf->FileName, pBuf->FileNameLength, &pStat->st_dirsymlink);
    254257    pStat->st_padding0[0]   = 0;
    255258    pStat->st_padding0[1]   = 0;
     
    272275
    273276
    274 int birdStatHandle(HANDLE hFile, BirdStat_T *pStat, const char *pszPath)
     277int birdStatHandle2(HANDLE hFile, BirdStat_T *pStat, const char *pszPath, const wchar_t *pwszPath)
    275278{
    276279    int                      rc;
     
    290293        {
    291294            pStat->st_mode          = birdFileInfoToMode(hFile, pAll->BasicInformation.FileAttributes, pszPath,
    292                                                          &pAll->NameInformation, &pStat->st_dirsymlink);
     295                                                         pAll->NameInformation.FileNamepAll->NameInformation.FileNameLength,
     296                                                         &pStat->st_dirsymlink);
    293297            pStat->st_padding0[0]   = 0;
    294298            pStat->st_padding0[1]   = 0;
     
    352356    if (MY_NT_SUCCESS(rcNt))
    353357        rcNt = Ios.u.Status;
    354     if (MY_NT_SUCCESS(rcNt) && !pszPath)
     358    if (MY_NT_SUCCESS(rcNt) && !pszPath && !pwszPath)
    355359    {
    356360        cbNameInfo = 0x10020;
     
    364368    {
    365369        pStat->st_mode          = birdFileInfoToMode(hFile, BasicInfo.FileAttributes, pszPath,
    366                                                      pNameInfo, &pStat->st_dirsymlink);
     370                                                     pNameInfo ? pNameInfo->FileName : pwszPath,
     371                                                     pNameInfo ? pNameInfo->FileNameLength
     372                                                     : pwszPath ? wcslen(pwszPath) * sizeof(wchar_t) : 0,
     373                                                     &pStat->st_dirsymlink);
    367374        pStat->st_padding0[0]   = 0;
    368375        pStat->st_padding0[1]   = 0;
     
    413420
    414421
     422int birdStatHandle(HANDLE hFile, BirdStat_T *pStat, const char *pszPath)
     423{
     424    return birdStatHandle2(hFile, pStat, pszPath, NULL);
     425}
     426
     427
    415428/**
    416429 * Generates a device number from the volume information.
     
    460473
    461474
    462 static int birdStatInternal(const char *pszPath, BirdStat_T *pStat, int fFollow)
     475static int birdStatInternal(HANDLE hRoot, const char *pszPath, BirdStat_T *pStat, int fFollow)
    463476{
    464477    int rc;
    465     HANDLE hFile = birdOpenFile(pszPath,
    466                                 FILE_READ_ATTRIBUTES,
    467                                 FILE_ATTRIBUTE_NORMAL,
    468                                 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
    469                                 FILE_OPEN,
    470                                 FILE_OPEN_FOR_BACKUP_INTENT | (fFollow ? 0 : FILE_OPEN_REPARSE_POINT),
    471                                 OBJ_CASE_INSENSITIVE);
     478    HANDLE hFile = birdOpenFileEx(hRoot, pszPath,
     479                                  FILE_READ_ATTRIBUTES,
     480                                  FILE_ATTRIBUTE_NORMAL,
     481                                  FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     482                                  FILE_OPEN,
     483                                  FILE_OPEN_FOR_BACKUP_INTENT | (fFollow ? 0 : FILE_OPEN_REPARSE_POINT),
     484                                  OBJ_CASE_INSENSITIVE);
    472485    if (hFile != INVALID_HANDLE_VALUE)
    473486    {
    474         rc = birdStatHandle(hFile, pStat, pszPath);
     487        rc = birdStatHandle2(hFile, pStat, pszPath, NULL);
    475488        birdCloseFile(hFile);
    476489
     
    500513        {
    501514            MY_UNICODE_STRING NameUniStr;
    502             hFile = birdOpenParentDir(pszPath,
     515            hFile = birdOpenParentDir(hRoot, pszPath,
    503516                                      FILE_READ_DATA | SYNCHRONIZE,
    504517                                      FILE_ATTRIBUTE_NORMAL,
     
    552565
    553566
     567static int birdStatInternalW(HANDLE hRoot, const wchar_t *pwszPath, BirdStat_T *pStat, int fFollow)
     568{
     569    int rc;
     570    HANDLE hFile = birdOpenFileExW(hRoot, pwszPath,
     571                                   FILE_READ_ATTRIBUTES,
     572                                   FILE_ATTRIBUTE_NORMAL,
     573                                   FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     574                                   FILE_OPEN,
     575                                   FILE_OPEN_FOR_BACKUP_INTENT | (fFollow ? 0 : FILE_OPEN_REPARSE_POINT),
     576                                   OBJ_CASE_INSENSITIVE);
     577    if (hFile != INVALID_HANDLE_VALUE)
     578    {
     579        rc = birdStatHandle2(hFile, pStat, NULL, pwszPath);
     580        birdCloseFile(hFile);
     581    }
     582    else
     583    {
     584        /*
     585         * On things like pagefile.sys we may get sharing violation.  We fall
     586         * back on directory enumeration for dealing with that.
     587         */
     588        if (   errno == ETXTBSY
     589            && wcschr(pwszPath, '*') == NULL /* Serious paranoia... */
     590            && wcschr(pwszPath, '?') == NULL)
     591        {
     592            MY_UNICODE_STRING NameUniStr;
     593            hFile = birdOpenParentDirW(hRoot, pwszPath,
     594                                       FILE_READ_DATA | SYNCHRONIZE,
     595                                       FILE_ATTRIBUTE_NORMAL,
     596                                       FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
     597                                       FILE_OPEN,
     598                                       FILE_DIRECTORY_FILE | FILE_OPEN_FOR_BACKUP_INTENT | FILE_SYNCHRONOUS_IO_NONALERT,
     599                                       OBJ_CASE_INSENSITIVE,
     600                                       &NameUniStr);
     601            if (hFile != INVALID_HANDLE_VALUE)
     602            {
     603                MY_FILE_ID_FULL_DIR_INFORMATION *pBuf;
     604                ULONG               cbBuf = sizeof(*pBuf) + NameUniStr.MaximumLength + 1024;
     605                MY_IO_STATUS_BLOCK  Ios;
     606                MY_NTSTATUS         rcNt;
     607
     608                pBuf = (MY_FILE_ID_FULL_DIR_INFORMATION *)alloca(cbBuf);
     609                Ios.u.Status    = -1;
     610                Ios.Information = -1;
     611                rcNt = g_pfnNtQueryDirectoryFile(hFile, NULL, NULL, NULL, &Ios, pBuf, cbBuf,
     612                                                 MyFileIdFullDirectoryInformation, FALSE, &NameUniStr, TRUE);
     613                if (MY_NT_SUCCESS(rcNt))
     614                    rcNt = Ios.u.Status;
     615                if (MY_NT_SUCCESS(rcNt))
     616                {
     617                    /*
     618                     * Convert the data.
     619                     */
     620                    birdStatFillFromFileIdFullDirInfo(pStat, pBuf, NULL);
     621
     622                    /* Get the serial number, reusing the buffer from above. */
     623                    rcNt = birdQueryVolumeDeviceNumber(hFile, (MY_FILE_FS_VOLUME_INFORMATION *)pBuf, cbBuf, &pStat->st_dev);
     624                    if (MY_NT_SUCCESS(rcNt))
     625                        rc = 0;
     626                    else
     627                        rc = birdSetErrnoFromNt(rcNt);
     628                }
     629
     630                birdFreeNtPath(&NameUniStr);
     631                birdCloseFile(hFile);
     632
     633                if (MY_NT_SUCCESS(rcNt))
     634                    return 0;
     635                birdSetErrnoFromNt(rcNt);
     636            }
     637        }
     638        rc = -1;
     639    }
     640
     641    return rc;
     642}
     643
     644
    554645/**
    555646 * Implements UNIX fstat().
     
    570661        {
    571662            case FILE_TYPE_DISK:
    572                 rc = birdStatHandle(hFile, pStat, NULL);
     663                rc = birdStatHandle2(hFile, pStat, NULL, NULL);
    573664                break;
    574665
     
    657748int birdStatFollowLink(const char *pszPath, BirdStat_T *pStat)
    658749{
    659     return birdStatInternal(pszPath, pStat, 1 /*fFollow*/);
     750    return birdStatInternal(NULL, pszPath, pStat, 1 /*fFollow*/);
     751}
     752
     753
     754/**
     755 * Implements UNIX stat().
     756 */
     757int birdStatFollowLinkW(const wchar_t *pwszPath, BirdStat_T *pStat)
     758{
     759    return birdStatInternalW(NULL, pwszPath, pStat, 1 /*fFollow*/);
    660760}
    661761
     
    666766int birdStatOnLink(const char *pszPath, BirdStat_T *pStat)
    667767{
    668     return birdStatInternal(pszPath, pStat, 0 /*fFollow*/);
     768    return birdStatInternal(NULL, pszPath, pStat, 0 /*fFollow*/);
     769}
     770
     771
     772/**
     773 * Implements UNIX lstat().
     774 */
     775int birdStatOnLinkW(const wchar_t *pwszPath, BirdStat_T *pStat)
     776{
     777    return birdStatInternalW(NULL, pwszPath, pStat, 0 /*fFollow*/);
     778}
     779
     780
     781/**
     782 * Implements an API like UNIX fstatat().
     783 *
     784 * @returns 0 on success, -1 and errno on failure.
     785 * @param   hRoot               NT handle pwszPath is relative to.
     786 * @param   pszPath             The path.
     787 * @param   pStat               Where to return stats.
     788 * @param   fFollowLink         Whether to follow links.
     789 */
     790int birdStatAt(HANDLE hRoot, const char *pszPath, BirdStat_T *pStat, int fFollowLink)
     791{
     792    return birdStatInternal(hRoot, pszPath, pStat, fFollowLink != 0);
     793}
     794
     795
     796/**
     797 * Implements an API like UNIX fstatat().
     798 *
     799 * @returns 0 on success, -1 and errno on failure.
     800 * @param   hRoot               NT handle pwszPath is relative to.
     801 * @param   pwszPath            The path.
     802 * @param   pStat               Where to return stats.
     803 * @param   fFollowLink         Whether to follow links.
     804 */
     805int birdStatAtW(HANDLE hRoot, const wchar_t *pwszPath, BirdStat_T *pStat, int fFollowLink)
     806{
     807    return birdStatInternalW(hRoot, pwszPath, pStat, fFollowLink != 0);
    669808}
    670809
  • trunk/src/lib/nt/ntstat.h

    r2858 r2985  
    7777
    7878int birdStatFollowLink(const char *pszPath, BirdStat_T *pStat);
     79int birdStatFollowLinkW(const wchar_t *pwszPath, BirdStat_T *pStat);
    7980int birdStatOnLink(const char *pszPath, BirdStat_T *pStat);
     81int birdStatOnLinkW(const wchar_t *pwszPath, BirdStat_T *pStat);
     82int birdStatAt(void *hRoot, const char *pszPath, BirdStat_T *pStat, int fFollowLink);
     83int birdStatAtW(void *hRoot, const wchar_t *pwszPath, BirdStat_T *pStat, int fFollowLink);
    8084int birdStatOnFd(int fd, BirdStat_T *pStat);
    8185int birdStatOnFdJustSize(int fd, __int64 *pcbFile);
  • trunk/src/lib/nt/ntstuff.h

    r2913 r2985  
    4040#include <ntstatus.h>
    4141#undef timeval
     42
     43#include <k/kTypes.h>
    4244
    4345
     
    467469#endif
    468470
     471#ifndef DUPLICATE_CLOSE_SOURCE /* For the misnomer NtDuplicateObject. */
     472# define DUPLICATE_CLOSE_SOURCE             0x00000001U
     473# define DUPLICATE_SAME_ACCESS              0x00000002U
     474#endif
     475#ifndef DUPLICATE_SAME_ATTRIBUTES
     476# define DUPLICATE_SAME_ATTRIBUTES          0x00000004U
     477#endif
     478
    469479
    470480/** @name NT status codes and associated macros.
     
    480490/** @}  */
    481491
     492/** The pseudohandle for the current process. */
     493#define MY_NT_CURRENT_PROCESS               ((HANDLE)~(uintptr_t)0)
     494/** The pseudohandle for the current thread. */
     495#define MY_NT_CURRENT_THREAD                ((HANDLE)~(uintptr_t)1)
     496
     497typedef struct MY_CLIENT_ID
     498{
     499    HANDLE UniqueProcess;
     500    HANDLE UniqueThread;
     501} MY_CLIENT_ID;
     502
     503/** Partial TEB.   */
     504typedef struct MY_PARTIAL_TEB
     505{
     506    NT_TIB          NtTib;
     507    PVOID           EnvironmentPointer;
     508    MY_CLIENT_ID    ClientId;
     509    PVOID           ActiveRpcHandle;
     510    PVOID           ThreadLocalStoragePointer;
     511    PPEB            ProcessEnvironmentBlock;
     512    KU32            LastErrorValue;
     513    KU32            CountOfOwnedCriticalSections;
     514    PVOID           CsrClientThread;
     515    PVOID           Win32ThreadInfo;
     516} MY_PARTIAL_TEB;
     517
     518/** Internal macro for reading uintptr_t sized TEB members. */
     519#if K_ARCH == K_ARCH_AMD64
     520# define MY_NT_READ_TEB_WORKER(a_offTebMember) ( __readgsqword(a_offTebMember) )
     521#elif K_ARCH == K_ARCH_X86
     522# define MY_NT_READ_TEB_WORKER(a_offTebMember) ( __readfsdword(a_offTebMember) )
     523#else
     524# else "Port me!"
     525#endif
     526/** Get the PEB pointer.
     527 * @remark Needs stddef.h. */
     528#define MY_NT_CURRENT_PEB()  ( (PPEB)MY_NT_READ_TEB_WORKER(offsetof(MY_PARTIAL_TEB, ProcessEnvironmentBlock)) )
     529/** Get the TEB pointer.
     530 * @remark Needs stddef.h. */
     531#define MY_NT_CURRENT_TEB()  ( (PTEB)MY_NT_READ_TEB_WORKER(offsetof(NT_TIB, Self)) )
     532
    482533
    483534/*******************************************************************************
     
    488539                                                PLARGE_INTEGER, ULONG, ULONG, ULONG, ULONG, PVOID, ULONG);
    489540extern MY_NTSTATUS (WINAPI * g_pfnNtDeleteFile)(MY_OBJECT_ATTRIBUTES *);
     541extern MY_NTSTATUS (WINAPI * g_pfnNtDuplicateObject)(HANDLE hSrcProc, HANDLE hSrc, HANDLE hDstProc, HANDLE *phRet,
     542                                                     MY_ACCESS_MASK fDesiredAccess, ULONG fAttribs, ULONG fOptions);
    490543extern MY_NTSTATUS (WINAPI * g_pfnNtReadFile)(HANDLE hFile, HANDLE hEvent, MY_IO_APC_ROUTINE *pfnApc, PVOID pvApcCtx,
    491544                                              MY_IO_STATUS_BLOCK *, PVOID pvBuf, ULONG cbToRead, PLARGE_INTEGER poffFile,
     
    509562extern UCHAR       (WINAPI * g_pfnRtlUpperChar)(UCHAR uch);
    510563extern ULONG       (WINAPI * g_pfnRtlNtStatusToDosError)(MY_NTSTATUS rcNt);
     564extern VOID        (WINAPI * g_pfnRtlAcquirePebLock)(VOID);
     565extern VOID        (WINAPI * g_pfnRtlReleasePebLock)(VOID);
    511566
    512567
  • trunk/src/lib/nt/ntunlink.c

    r2713 r2985  
    4646    HANDLE      hFile;
    4747
    48     rcNt = birdOpenFileUniStr(pNtPath,
     48    rcNt = birdOpenFileUniStr(NULL /*hRoot*/,
     49                              pNtPath,
    4950                              FILE_WRITE_ATTRIBUTES | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
    5051                              FILE_ATTRIBUTE_NORMAL,
     
    112113            for (;;)
    113114            {
    114                 rcNt = birdOpenFileUniStr(&NtPath,
     115                rcNt = birdOpenFileUniStr(NULL /*hRoot*/,
     116                                          &NtPath,
    115117                                          DELETE,
    116118                                          FILE_ATTRIBUTE_NORMAL,
Note: See TracChangeset for help on using the changeset viewer.