Changeset 2858


Ignore:
Timestamp:
Sep 1, 2016, 5:12:24 PM (9 years ago)
Author:
bird
Message:

updates

Location:
trunk/src
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kWorker

    • Property svn:externals deleted
  • trunk/src/kWorker/Makefile.kmk

    r2844 r2858  
    3131PROGRAMS += kWorker
    3232kWorker_TEMPLATE = BIN-STATIC-THREADED
    33 kWorker_INCS = kStuff/include
    3433kWorker_DEFS.debug = K_STRICT
    3534kWorker_DEFS.release = NASSERT
     
    6463       nt/ntdir.c \
    6564       nt/ntstat.c \
    66        nt/ntunlink.c
     65       nt/ntunlink.c \
     66       nt/kFsCache.c
    6767kbuild_version.c_DEFS = KBUILD_SVN_REV=$(KBUILD_SVN_REV)
    6868
     
    7474kStuff_DEFS.debug = K_STRICT
    7575kStuff_INCS = kStuff/include
     76kStuff_DEFPATH = $(PATH_ROOT)/src/lib
    7677
    7778# kLdr
  • trunk/src/kWorker/kWorker.c

    r2846 r2858  
    4444extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull);
    4545
    46 #include <Windows.h>
    47 #include <winternl.h>
    48 
     46#include "nt/ntstuff.h"
     47
     48#include "nt/kFsCache.h"
    4949
    5050
     
    5252*   Defined Constants And Macros                                                                                                 *
    5353*********************************************************************************************************************************/
    54 /** Special KWFSOBJ::uCacheGen number indicating that it does not apply. */
    55 #define KFSWOBJ_CACHE_GEN_IGNORE        KU32_MAX
    56 
    5754/** String constant comma length.   */
    5855#define TUPLE(a_sz)                     a_sz, sizeof(a_sz) - 1
     
    9592# define KWFS_TEMP_FILE_MAX             (64*1024*1024)
    9693#endif
     94
     95
     96/** User data key for tools. */
     97#define KW_DATA_KEY_TOOL                (~(KUPTR)16381)
     98/** User data key for a cached file. */
     99#define KW_DATA_KEY_CACHED_FILE         (~(KUPTR)65521)
    97100
    98101
     
    194197
    195198
    196 typedef struct KWFSOBJ *PKWFSOBJ;
    197 typedef struct KWFSOBJ
    198 {
    199     /** The object name.  (Allocated after the structure.) */
    200     const char         *pszName;
    201     /** The UTF-16 object name.  (Allocated after the structure.) */
    202     const wchar_t      *pwszName;
    203     /** The length of pszName. */
    204     KU16                cchName;
    205     /** The length of UTF-16 (in wchar_t's). */
    206     KU16                cwcName;
    207 
    208     /** The number of child objects. */
    209     KU32                cChildren;
    210     /** Child objects. */
    211     PKWFSOBJ           *papChildren;
    212     /** Pointer to the parent. */
    213     PKWFSOBJ            pParent;
    214 
    215     /** The cache generation, KFSWOBJ_CACHE_GEN_IGNORE. */
    216     KU32                uCacheGen;
    217     /** The GetFileAttributes result for the file.
    218      * FILE_ATTRIBUTE_XXX or INVALID_FILE_ATTRIBUTES. */
    219     KU32                fAttribs;
    220     /** The GetLastError() for INVALI_FILE_ATTRIBUTES. */
    221     KU32                uLastError;
     199/**
     200 * A cached file.
     201 */
     202typedef struct KFSWCACHEDFILE
     203{
     204    /** The user data core. */
     205    KFSUSERDATA         Core;
    222206
    223207    /** Cached file handle. */
     
    227211    /** Cached file content. */
    228212    KU8                *pbCached;
    229 } KWFSOBJ;
    230 
    231 
    232 /** Pointer to an ANSI path hash table entry. */
    233 typedef struct KWFSHASHA *PKWFSHASHA;
    234 /**
    235  * ANSI file system path hash table entry.
    236  * The path hash table allows us to skip parsing and walking a path.
    237  */
    238 typedef struct KWFSHASHA
    239 {
    240     /** Next entry with the same hash table slot. */
    241     PKWFSHASHA          pNext;
    242     /** Path hash value. */
    243     KU32                uHashPath;
    244     /** The path length. */
    245     KU32                cchPath;
    246     /** The path.  (Allocated after the structure.) */
    247     const char         *pszPath;
    248     /** Pointer to the matching FS object. */
    249     PKWFSOBJ            pFsObj;
    250 } KWFSHASHA;
    251 
    252 
    253 /** Pointer to an UTF-16 path hash table entry. */
    254 typedef struct KWFSHASHW *PKWFSHASHW;
    255 /**
    256  * UTF-16 file system path hash table entry. The path hash table allows us
    257  * to skip parsing and walking a path.
    258  */
    259 typedef struct KWFSHASHW
    260 {
    261     /** Next entry with the same hash table slot. */
    262     PKWFSHASHW          pNext;
    263     /** Path hash value. */
    264     KU32                uHashPath;
    265     /** The path length (in wchar_t units). */
    266     KU32                cwcPath;
    267     /** The path.  (Allocated after the structure.) */
    268     const wchar_t      *pwszPath;
    269     /** Pointer to the matching FS object. */
    270     PKWFSOBJ            pFsObj;
    271 } KWFSHASHW;
    272 
    273 
    274 
    275 /** Pointer to a normalized path hash table entry. */
    276 typedef struct KWFSNORMHASHA *PKWFSNORMHASHA;
    277 /**
    278  * Normalized path hash table entry.
    279  *
    280  * Note! This looks like it's duplicating KWFSHASHW/KWFSHASHA/KWFSOBJ, but
    281  *       it also handles paths that not cachable.
    282  */
    283 typedef struct KWFSNORMHASHA
    284 {
    285     /** Next entry with the same hash table slot. */
    286     PKWFSNORMHASHA      pNext;
    287     /** The input path. */
    288     const char         *pszPath;
    289     /** The length of the input path. */
    290     KU16                cchPath;
    291     /** The length of the normalized path. */
    292     KU16                cchNormPath;
    293     /** The hash. */
    294     KU32                uHashPath;
    295     /** The normalized path (variable size). */
    296     char                szNormPath[1];
    297 } KWFSNORMHASHA;
     213
     214    /** Circular self reference. Prevents the object from ever going away and
     215     * keeps it handy for debugging. */
     216    PKFSOBJ             pFsObj;
     217} KFSWCACHEDFILE;
     218/** Pointe to a cached filed. */
     219typedef KFSWCACHEDFILE *PKFSWCACHEDFILE;
    298220
    299221
     
    358280    {
    359281        /** The file system object.   */
    360         PKWFSOBJ            pFsObj;
     282        PKFSWCACHEDFILE     pCachedFile;
    361283        /** Temporary file handle or mapping handle. */
    362284        PKWFSTEMPFILE       pTempFile;
     
    383305} KWTOOLHINT;
    384306
    385 typedef struct KWTOOL *PKWTOOL;
     307
     308/**
     309 * A kWorker tool.
     310 */
    386311typedef struct KWTOOL
    387312{
    388     /** Pointer to the next in the hash collision chain. */
    389     PKWTOOL             pNext;
     313    /** The user data core structure. */
     314    KFSUSERDATA         Core;
     315
    390316    /** The normalized path to the program. */
    391317    const char         *pszPath;
    392     /** The hash of the program path. */
    393     KU32                uHashPath;
     318    /** UTF-16 version of pszPath. */
     319    wchar_t const      *pwszPath;
    394320    /** The kind of tool. */
    395321    KWTOOLTYPE          enmType;
    396     /** UTF-16 version of pszPath. */
    397     wchar_t const      *pwszPath;
    398322
    399323    union
     
    411335    } u;
    412336} KWTOOL;
     337/** Pointer to a tool. */
     338typedef struct KWTOOL *PKWTOOL;
    413339
    414340
     
    507433static PKWMODULE    g_apModules[127];
    508434
    509 /** Tool hash table. */
    510 static PKWTOOL      g_apTools[63];
    511 
    512 /** Special file system root (parent to the drive letters). */
    513 static KWFSOBJ      g_FsRoot =
    514 {
    515     /* .pszName     = */ "",
    516     /* .pwszName    = */ L"",
    517     /* .cchName     = */ 0,
    518     /* .cwcName     = */ 0,
    519     /* .cChildren   = */ 0,
    520     /* .papChildren = */ NULL,
    521     /* .pParent     = */ NULL,
    522     /* .uCacheGen   = */ KFSWOBJ_CACHE_GEN_IGNORE,
    523     /* .fAttribs    = */ FILE_ATTRIBUTE_DIRECTORY,
    524     /* .uLastError  = */ ERROR_PATH_NOT_FOUND,
    525     /* .hCached     = */ INVALID_HANDLE_VALUE,
    526     /* .cbCached    = */ 0,
    527     /* .pbCached    = */ NULL,
    528 };
    529 /** File system hash table for ANSI filename strings. */
    530 static PKWFSHASHA   g_apFsAnsiPaths[1021];
    531 /** File system hash table for UTF-16 filename strings. */
    532 static PKWFSHASHW   g_apFsUtf16Paths[1021];
    533 /** Cached normalized path results. */
    534 static PKWFSNORMHASHA g_apFsNormalizedPathsA[1021];
    535 /** Special file system object returned if the path is invalid. */
    536 static KWFSOBJ      g_FsPathNotFound =
    537 {
    538     /* .pszName     = */ "",
    539     /* .pwszName    = */ L"",
    540     /* .cchName     = */ 0,
    541     /* .cwcName     = */ 0,
    542     /* .cChildren   = */ 0,
    543     /* .papChildren = */ NULL,
    544     /* .pParent     = */ NULL,
    545     /* .uCacheGen   = */ KFSWOBJ_CACHE_GEN_IGNORE,
    546     /* .fAttribs    = */ FILE_ATTRIBUTE_DIRECTORY,
    547     /* .uLastError  = */ ERROR_PATH_NOT_FOUND,
    548     /* .hCached     = */ INVALID_HANDLE_VALUE,
    549     /* .cbCached    = */ 0,
    550     /* .pbCached    = */ NULL,
    551 };
    552 /** The cache generation number, incremented for each sandboxed execution.
    553  * This is used to invalid negative results from parts of the file system. */
    554 static KU32         g_uFsCacheGeneration = 0;
     435/** The file system cache. */
     436static PKFSCACHE    g_pFsCache;
     437/** The current directory (referenced). */
     438static PKFSOBJ      g_pCurDirObj = NULL;
    555439
    556440/** Verbosity level. */
     
    580464static FNKLDRMODGETIMPORT kwLdrModuleGetImportCallback;
    581465static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod);
    582 static PKWFSOBJ kwFsLookupA(const char *pszPath);
    583466static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle);
    584467
     
    683566    kwErrPrintfV(pszFormat, va);
    684567    va_end(va);
     568}
     569
     570
     571/**
     572 * Error printing.
     573 * @return  rc;
     574 * @param   rc                  Return value
     575 * @param   pszFormat           Message format string.
     576 * @param   ...                 Format argument.
     577 */
     578static int kwErrPrintfRc(int rc, const char *pszFormat, ...)
     579{
     580    va_list va;
     581    va_start(va, pszFormat);
     582    kwErrPrintfV(pszFormat, va);
     583    va_end(va);
     584    return rc;
    685585}
    686586
     
    908808static int kwPathNormalize(const char *pszPath, char *pszNormPath, KSIZE cbNormPath)
    909809{
    910     char           *pchSlash;
    911     KSIZE           cchNormPath;
    912 
    913     /*
    914      * We hash these to speed stuff up (nt_fullpath isn't cheap and we're
    915      * gonna have many repeat queries and assume nobody do case changes to
    916      * anything essential while kmk is running).
    917      */
    918     KU32            uHashPath;
    919     KU32            cchPath    = (KU32)kwStrHashEx(pszPath, &uHashPath);
    920     KU32 const      idxHashTab = uHashPath % K_ELEMENTS(g_apFsNormalizedPathsA);
    921     PKWFSNORMHASHA  pHashEntry = g_apFsNormalizedPathsA[idxHashTab];
    922     if (pHashEntry)
    923     {
    924         do
    925         {
    926             if (   pHashEntry->uHashPath == uHashPath
    927                 && pHashEntry->cchPath   == cchPath
    928                 && kHlpMemComp(pHashEntry->pszPath, pszPath, cchPath) == 0)
    929             {
    930                 if (cbNormPath > pHashEntry->cchNormPath)
    931                 {
    932                     KWFS_LOG(("kwPathNormalize(%s) - hit\n", pszPath));
    933                     kHlpMemCopy(pszNormPath, pHashEntry->szNormPath, pHashEntry->cchNormPath + 1);
    934                     return 0;
    935                 }
    936                 return KERR_BUFFER_OVERFLOW;
    937             }
    938             pHashEntry = pHashEntry->pNext;
    939         } while (pHashEntry);
    940     }
    941 
    942     /*
    943      * Do it the slow way.
    944      */
    945     nt_fullpath(pszPath, pszNormPath, cbNormPath);
    946     /** @todo nt_fullpath overflow handling?!?!?   */
    947 
    948     pchSlash = kHlpStrChr(pszNormPath, '/');
    949     while (pchSlash)
    950     {
    951         *pchSlash = '\\';
    952         pchSlash = kHlpStrChr(pchSlash + 1, '/');
    953     }
    954 
    955     /*
    956      * Create a new hash table entry (ignore failures).
    957      */
    958     cchNormPath = kHlpStrLen(pszNormPath);
    959     if (cchNormPath < KU16_MAX && cchPath < KU16_MAX)
    960     {
    961         pHashEntry = (PKWFSNORMHASHA)kHlpAlloc(sizeof(*pHashEntry) + cchNormPath + 1 + cchPath + 1);
    962         if (pHashEntry)
    963         {
    964             pHashEntry->cchNormPath = (KU16)cchNormPath;
    965             pHashEntry->cchPath     = (KU16)cchPath;
    966             pHashEntry->uHashPath   = uHashPath;
    967             pHashEntry->pszPath     = (char *)kHlpMemCopy(&pHashEntry->szNormPath[cchNormPath + 1], pszPath, cchPath + 1);
    968             kHlpMemCopy(pHashEntry->szNormPath, pszNormPath, cchNormPath + 1);
    969 
    970             pHashEntry->pNext = g_apFsNormalizedPathsA[idxHashTab];
    971             g_apFsNormalizedPathsA[idxHashTab] = pHashEntry;
    972         }
    973     }
    974 
    975     return 0;
     810    KFSLOOKUPERROR enmError;
     811    PKFSOBJ pFsObj = kFsCacheLookupA(g_pFsCache, pszPath, &enmError);
     812    if (pFsObj)
     813    {
     814        KBOOL fRc;
     815        fRc = kFsCacheObjGetFullPathA(pFsObj, pszNormPath, cbNormPath, '\\');
     816        kFsCacheObjRelease(g_pFsCache, pFsObj);
     817        if (fRc)
     818            return 0;
     819        return KERR_BUFFER_OVERFLOW;
     820    }
     821    return KERR_FILE_NOT_FOUND;
    976822}
    977823
     
    1061907            KSIZE idx = pMod->u.Manual.cImpMods;
    1062908            while (idx-- > 0)
    1063             {
    1064                 kwLdrModuleRelease(pMod->u.Manual.apImpMods[idx]);
    1065                 pMod->u.Manual.apImpMods[idx] = NULL;
    1066             }
     909                if (pMod->u.Manual.apImpMods[idx])
     910                {
     911                    kwLdrModuleRelease(pMod->u.Manual.apImpMods[idx]);
     912                    pMod->u.Manual.apImpMods[idx] = NULL;
     913                }
    1067914        }
    1068915
     
    15661413        && (pszPath[cchPath - 1] == 'l' || pszPath[cchPath - 1] == 'L') )
    15671414    {
    1568         PKWFSOBJ pFsObj = kwFsLookupA(pszPath);
     1415        KFSLOOKUPERROR enmError;
     1416        PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszPath, &enmError);
    15691417        if (pFsObj)
    15701418        {
    1571             if (!(pFsObj->fAttribs & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE))) /* also checks invalid */
    1572                 return K_TRUE;
     1419            KBOOL fRc = pFsObj->bObjType == KFSOBJ_TYPE_FILE;
     1420            kFsCacheObjRelease(g_pFsCache, pFsObj);
     1421            return fRc;
    15731422        }
    15741423    }
     
    17621611 *
    17631612 * @returns Pointer to the tool entry.  NULL on failure.
    1764  * @param   pszTool             The normalized path to the tool.
    1765  * @param   uHashPath           The hash of the tool path.
    1766  * @param   idxHashTab          The hash table index of the tool.
    1767  */
    1768 static PKWTOOL kwToolEntryCreate(const char *pszTool, KU32 uHashPath, unsigned idxHashTab)
    1769 {
    1770     KSIZE   cbTool = kHlpStrLen(pszTool) + 1;
    1771     PKWTOOL pTool  = (PKWTOOL)kHlpAllocZ(sizeof(*pTool) + cbTool + 1 + cbTool * 2 * sizeof(wchar_t));
     1613 * @param   pToolFsObj          The file object of the tool.  The created tool
     1614 *                              will be associated with it.
     1615 *
     1616 *                              A reference is donated by the caller and must be
     1617 *                              released.
     1618 */
     1619static PKWTOOL kwToolEntryCreate(PKFSOBJ pToolFsObj)
     1620{
     1621    KSIZE   cwcPath = pToolFsObj->cwcParent + pToolFsObj->cwcName + 1;
     1622    KSIZE   cbPath  = pToolFsObj->cchParent + pToolFsObj->cchName + 1;
     1623    PKWTOOL pTool   = (PKWTOOL)kFsCacheObjAddUserData(g_pFsCache, pToolFsObj, KW_DATA_KEY_TOOL,
     1624                                                      sizeof(*pTool) + cwcPath * sizeof(wchar_t) + cbPath);
    17721625    if (pTool)
    17731626    {
    1774         pTool->pszPath   = (char *)kHlpMemCopy(pTool + 1, pszTool, cbTool);
    1775         pTool->pwszPath  = (wchar_t *)(pTool->pszPath + cbTool + (cbTool & 1));
    1776         kwStrToUtf16(pTool->pszPath, (wchar_t *)pTool->pwszPath, cbTool * 2);
    1777         pTool->uHashPath = uHashPath;
    1778         pTool->enmType   = KWTOOLTYPE_SANDBOXED;
    1779 
    1780         pTool->u.Sandboxed.pExe = kwLdrModuleCreateNonNative(pszTool, uHashPath, K_TRUE /*fExe*/, NULL);
     1627        KBOOL fRc;
     1628        pTool->pwszPath = (wchar_t const *)(pTool + 1);
     1629        fRc = kFsCacheObjGetFullPathW(pToolFsObj, (wchar_t *)pTool->pwszPath, cwcPath, '\\');
     1630        kHlpAssert(fRc); K_NOREF(fRc);
     1631
     1632        pTool->pszPath = (char const *)&pTool->pwszPath[cwcPath];
     1633        fRc = kFsCacheObjGetFullPathA(pToolFsObj, (char *)pTool->pszPath, cbPath, '\\');
     1634        kHlpAssert(fRc);
     1635
     1636        pTool->enmType = KWTOOLTYPE_SANDBOXED;
     1637        pTool->u.Sandboxed.pExe = kwLdrModuleCreateNonNative(pTool->pszPath, kwStrHash(pTool->pszPath), K_TRUE /*fExe*/, NULL);
    17811638        if (!pTool->u.Sandboxed.pExe)
    17821639            pTool->enmType = KWTOOLTYPE_EXEC;
    1783         else if (kHlpStrICompAscii(pTool->u.Sandboxed.pExe->pLdrMod->pszName, "cl.exe") == 0)
     1640        else if (kHlpStrICompAscii(pToolFsObj->pszName, "cl.exe") == 0)
    17841641            pTool->u.Sandboxed.enmHint = KWTOOLHINT_VISUAL_CPP_CL;
    17851642        else
    17861643            pTool->u.Sandboxed.enmHint = KWTOOLHINT_NONE;
    17871644
    1788         /* Link the tool. */
    1789         pTool->pNext = g_apTools[idxHashTab];
    1790         g_apTools[idxHashTab] = pTool;
     1645        kFsCacheObjRelease(g_pFsCache, pToolFsObj);
    17911646        return pTool;
    17921647    }
     1648    kFsCacheObjRelease(g_pFsCache, pToolFsObj);
    17931649    return NULL;
    17941650}
     
    18041660{
    18051661    /*
    1806      * Normalize the path and look up the tool in the g_apTools hash table.
     1662     * We associate the tools instances with the file system objects.
    18071663     */
    1808     char szNormPath[4096];
    1809     int rc = kwPathNormalize(pszExe, szNormPath, sizeof(szNormPath));
    1810     if (rc == 0)
    1811     {
    1812         KU32     uHashPath = kwStrHash(szNormPath);
    1813         unsigned idxHash   = uHashPath % K_ELEMENTS(g_apTools);
    1814         PKWTOOL  pTool     = g_apTools[idxHash];
    1815         if (pTool)
    1816         {
    1817             do
     1664    KFSLOOKUPERROR  enmError;
     1665    PKFSOBJ         pToolFsObj = kFsCacheLookupA(g_pFsCache, pszExe, &enmError);
     1666    if (pToolFsObj)
     1667    {
     1668        if (pToolFsObj->bObjType == KFSOBJ_TYPE_FILE)
     1669        {
     1670            PKWTOOL pTool = (PKWTOOL)kFsCacheObjGetUserData(g_pFsCache, pToolFsObj, KW_DATA_KEY_TOOL);
     1671            if (pTool)
    18181672            {
    1819                 if (   pTool->uHashPath == uHashPath
    1820                     && kHlpStrComp(pTool->pszPath, szNormPath) == 0)
    1821                     return pTool;
    1822                 pTool = pTool->pNext;
    1823             } while (pTool);
    1824         }
    1825 
    1826         /*
    1827          * Not found, create new entry.
    1828          */
    1829        return kwToolEntryCreate(szNormPath, uHashPath, idxHash);
     1673                kFsCacheObjRelease(g_pFsCache, pToolFsObj);
     1674                return pTool;
     1675            }
     1676
     1677            /*
     1678             * Need to create a new tool.
     1679             */
     1680            return kwToolEntryCreate(pToolFsObj);
     1681        }
     1682        kFsCacheObjRelease(g_pFsCache, pToolFsObj);
    18301683    }
    18311684    return NULL;
     
    18421695 */
    18431696
    1844 
    1845 #define IS_ALPHA(ch) ( ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') )
    1846 #define IS_SLASH(ch) ((ch) == '\\' || (ch) == '/')
    18471697
    18481698
     
    18801730    }
    18811731}
    1882 
    1883 
    1884 /**
    1885  * Looks for '..' in the path.
    1886  *
    1887  * @returns K_TRUE if '..' component found, K_FALSE if not.
    1888  * @param   pszPath             The path.
    1889  * @param   cchPath             The length of the path.
    1890  */
    1891 static KBOOL kwFsHasDotDot(const char *pszPath, KSIZE cchPath)
    1892 {
    1893     const char *pchDot = (const char *)kHlpMemChr(pszPath, '.', cchPath);
    1894     while (pchDot)
    1895     {
    1896         if (pchDot[1] != '.')
    1897             pchDot = (const char *)kHlpMemChr(pchDot + 1, '.', &pszPath[cchPath] - pchDot - 1);
    1898         else
    1899         {
    1900             char ch;
    1901             if (   (ch = pchDot[2]) == '\0'
    1902                 && IS_SLASH(ch))
    1903             {
    1904                 if (pchDot == pszPath)
    1905                     return K_TRUE;
    1906                 ch = pchDot[-1];
    1907                 if (   IS_SLASH(ch)
    1908                     || ch == ':')
    1909                     return K_TRUE;
    1910             }
    1911             pchDot = (const char *)kHlpMemChr(pchDot + 2, '.', &pszPath[cchPath] - pchDot - 2);
    1912         }
    1913     }
    1914 
    1915     return K_FALSE;
    1916 }
    1917 
    1918 
    1919 static void kwFsCreateHashTabEntryA(PKWFSOBJ pFsObj, const char *pszPath, KU32 cchPath, KU32 uHashPath, KU32 idxHashTab)
    1920 {
    1921     PKWFSHASHA pHashEntry = (PKWFSHASHA)kHlpAlloc(sizeof(*pHashEntry) + cchPath + 1);
    1922     if (pHashEntry)
    1923     {
    1924         pHashEntry->uHashPath   = uHashPath;
    1925         pHashEntry->cchPath     = cchPath;
    1926         pHashEntry->pszPath     = (const char *)kHlpMemCopy(pHashEntry + 1, pszPath, cchPath + 1);
    1927         pHashEntry->pFsObj      = pFsObj;
    1928 
    1929         pHashEntry->pNext = g_apFsAnsiPaths[idxHashTab];
    1930         g_apFsAnsiPaths[idxHashTab] = pHashEntry;
    1931     }
    1932 }
    1933 
    1934 
    1935 /**
    1936  * Refreshes a node that hash expired.
    1937  *
    1938  * This is for files and directories in the output directory tree.  The plan is
    1939  * to invalid negative results for each tool execution, in case a include file
    1940  * or directory has been created since the last time we were active.  Assuming
    1941  * that we'll be stopped together with kmk, there is no need to invalidate
    1942  * positive results.
    1943  *
    1944  * @param   pNode               The FS node.
    1945  */
    1946 static void kwFsRefreshNode(PKWFSOBJ pNode)
    1947 {
    1948     /** @todo implement once we've start inserting uCacheGen nodes. */
    1949     __debugbreak();
    1950 }
    1951 
    1952 
    1953 /**
    1954  * Links the child in under the parent.
    1955  *
    1956  * @returns K_TRUE on success, K_FALSE if out of memory.
    1957  * @param   pParent             The parent node.
    1958  * @param   pChild              The child node.
    1959  */
    1960 static KBOOL kwFsLinkChild(PKWFSOBJ pParent, PKWFSOBJ pChild)
    1961 {
    1962     if ((pParent->cChildren % 16) == 0)
    1963     {
    1964         void *pvNew = kHlpRealloc(pParent->papChildren, (pParent->cChildren + 16) * sizeof(pParent->papChildren[0]));
    1965         if (!pvNew)
    1966             return K_FALSE;
    1967         pParent->papChildren = (PKWFSOBJ *)pvNew;
    1968     }
    1969     pParent->papChildren[pParent->cChildren++] = pChild;
    1970     return K_TRUE;
    1971 }
    1972 
    1973 
    1974 /**
    1975  * Creates a child node for an ANSI path.
    1976  *
    1977  * @returns Pointer to the child tree node on success.
    1978  *          NULL on failure (out of memory).
    1979  * @param   pParent             The parent node.
    1980  * @param   pchPath             The path.
    1981  * @param   offName             The offset of the child name into pchPath.
    1982  * @param   cchName             The length of the child name.
    1983  */
    1984 static PKWFSOBJ kwFsCreateChildA(PKWFSOBJ pParent, const char *pchPath, KU32 offName, KU32 cchName)
    1985 {
    1986     char        szTmp[2048];
    1987     DWORD const dwSavedErr = GetLastError();
    1988     DWORD       dwAttr;
    1989     DWORD       dwErr;
    1990     PKWFSOBJ    pChild;
    1991 
    1992     /*
    1993      * Get attributes.
    1994      */
    1995     if (pchPath[offName + cchName])
    1996     {
    1997         if (cchName + offName >= sizeof(szTmp))
    1998             return NULL;
    1999         memcpy(szTmp, pchPath, offName + cchName);
    2000         if (offName != 0 || cchName != 2 || pchPath[1] != ':')
    2001             szTmp[offName + cchName] = '\0';
    2002         else
    2003         {
    2004             /* Change 'E:' to 'E:\\.' so that it's actually absolute. */
    2005             szTmp[2] = '\\';
    2006             szTmp[3] = '.';
    2007             szTmp[4] = '\0';
    2008         }
    2009         pchPath = szTmp;
    2010     }
    2011 
    2012     SetLastError(NO_ERROR);
    2013     dwAttr = GetFileAttributesA(pchPath);
    2014     dwErr  = GetLastError();
    2015 
    2016     /*
    2017      * Create the entry.
    2018      */
    2019     pChild = (PKWFSOBJ)kHlpAlloc(sizeof(*pChild) + cchName + 1 + (cchName + 1) * sizeof(wchar_t) * 2);
    2020     SetLastError(dwSavedErr);
    2021     if (pChild)
    2022     {
    2023         pChild->pwszName    = (const wchar_t *)(pChild + 1);
    2024         pChild->pszName     = (const char *)kHlpMemCopy((void *)&pChild->pwszName[(cchName + 1) * 2],
    2025                                                         &pchPath[offName], cchName);
    2026         ((char *)pChild->pszName)[cchName] = '\0';
    2027         pChild->cwcName     = (KU16)kwStrToUtf16(pChild->pszName, (wchar_t *)pChild->pwszName, (cchName + 1) * 2);
    2028 
    2029         pChild->cchName     = cchName;
    2030         pChild->cChildren   = 0;
    2031         pChild->papChildren = NULL;
    2032         pChild->pParent     = pParent;
    2033 
    2034         pChild->uCacheGen   = pParent->uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE ? KFSWOBJ_CACHE_GEN_IGNORE : g_uFsCacheGeneration;
    2035         pChild->fAttribs    = dwAttr;
    2036         pChild->uLastError  = dwErr;
    2037 
    2038         pChild->hCached     = INVALID_HANDLE_VALUE;
    2039         pChild->cbCached    = 0;
    2040         pChild->pbCached    = NULL;
    2041 
    2042         if (kwFsLinkChild(pParent, pChild))
    2043             return pChild;
    2044 
    2045         kHlpFree(pChild);
    2046     }
    2047     return NULL;
    2048 }
    2049 
    2050 
    2051 /**
    2052  * Look up a child node, ANSI version.
    2053  *
    2054  * @returns Pointer to the child if found, NULL if not.
    2055  * @param   pParent             The parent to search the children of.
    2056  * @param   pchName             The child name to search for (not terminated).
    2057  * @param   cchName             The length of the child name.
    2058  */
    2059 static PKWFSOBJ kwFsFindChildA(PKWFSOBJ pParent, const char *pchName, KU32 cchName)
    2060 {
    2061     /* Check for '.' first. */
    2062     if (cchName != 1 || *pchName != '.')
    2063     {
    2064         KU32        cLeft = pParent->cChildren;
    2065         PKWFSOBJ   *ppCur = pParent->papChildren;
    2066         while (cLeft-- > 0)
    2067         {
    2068             PKWFSOBJ pCur = *ppCur++;
    2069             if (   pCur->cchName == cchName
    2070                 && _memicmp(pCur->pszName, pchName, cchName) == 0)
    2071             {
    2072                 if (   pCur->uCacheGen != KFSWOBJ_CACHE_GEN_IGNORE
    2073                     && pCur->uCacheGen != g_uFsCacheGeneration)
    2074                     kwFsRefreshNode(pCur);
    2075                 return pCur;
    2076             }
    2077         }
    2078         return NULL;
    2079     }
    2080     return pParent;
    2081 }
    2082 
    2083 
    2084 /**
    2085  * Walk the file system tree for the given absolute path, entering it into the
    2086  * hash table.
    2087  *
    2088  * This will create any missing nodes while walking.
    2089  *
    2090  * @returns Pointer to the tree node corresponding to @a pszPath.
    2091  *          NULL if we ran out of memory.
    2092  * @param   pszPath             The path to walk.
    2093  * @param   cchPath             The length of the path.
    2094  * @param   uHashPath           The hash of the path.
    2095  * @param   idxHashTab          Index into the hash table.
    2096  */
    2097 static PKWFSOBJ kwFsLookupAbsoluteA(const char *pszPath, KU32 cchPath, KU32 uHashPath, KU32 idxHashTab)
    2098 {
    2099     PKWFSOBJ    pParent = &g_FsRoot;
    2100     KU32        off;
    2101     KWFS_LOG(("kwFsLookupAbsoluteA(%s)\n", pszPath));
    2102 
    2103     kHlpAssert(IS_ALPHA(pszPath[0]));
    2104     kHlpAssert(pszPath[1] == ':');
    2105     kHlpAssert(IS_SLASH(pszPath[2]));
    2106 
    2107     off = 0;
    2108     for (;;)
    2109     {
    2110         PKWFSOBJ    pChild;
    2111 
    2112         /* Find the end of the component. */
    2113         char        ch;
    2114         KU32        cchSlashes = 0;
    2115         KU32        offEnd = off + 1;
    2116         while ((ch = pszPath[offEnd]) != '\0')
    2117         {
    2118             if (!IS_SLASH(ch))
    2119                 offEnd++;
    2120             else
    2121             {
    2122                 do
    2123                     cchSlashes++;
    2124                 while (IS_SLASH(pszPath[offEnd + cchSlashes]));
    2125                 break;
    2126             }
    2127         }
    2128 
    2129         /* Search the current node for the name. */
    2130         pChild = kwFsFindChildA(pParent, &pszPath[off], offEnd - off);
    2131         if (!pChild)
    2132         {
    2133             pChild = kwFsCreateChildA(pParent, pszPath, off, offEnd - off);
    2134             if (!pChild)
    2135                 break;
    2136         }
    2137         off = offEnd + cchSlashes;
    2138         if (   cchSlashes == 0
    2139             || off >= cchPath)
    2140         {
    2141             kwFsCreateHashTabEntryA(pChild, pszPath, cchPath, uHashPath, idxHashTab);
    2142             return pChild;
    2143         }
    2144 
    2145         /* Check that it's a directory (won't match INVALID_FILE_ATTRIBUTES). */
    2146         if (!(pChild->fAttribs & FILE_ATTRIBUTE_DIRECTORY))
    2147             return &g_FsPathNotFound;
    2148 
    2149         pParent = pChild;
    2150     }
    2151 
    2152     return NULL;
    2153 }
    2154 
    2155 
    2156 /**
    2157  * This deals with paths that are relative and paths that contains '..'
    2158  * elements.
    2159  *
    2160  * @returns Pointer to object corresponding to @a pszPath on success.
    2161  *          NULL if this isn't a path we care to cache.
    2162  * @param   pszPath             The path.
    2163  * @param   cchPath             The length of the path.
    2164  * @param   uHashPath           The hash of the path.
    2165  * @param   idxHashTab          The path table index.
    2166  */
    2167 static PKWFSOBJ kwFsLookupSlowA(const char *pszPath, KU32 cchPath, KU32 uHashPath, KU32 idxHashTab)
    2168 {
    2169     /* Turns out getcwd/_getdcwd uses GetFullPathName internall, so just call it directly here. */
    2170     char szFull[2048];
    2171     UINT cchFull = GetFullPathNameA(pszPath, sizeof(szFull), szFull, NULL);
    2172     if (   cchFull >= 3
    2173         && cchFull < sizeof(szFull))
    2174     {
    2175         KWFS_LOG(("kwFsLookupSlowA(%s)\n", pszPath));
    2176         if (   szFull[1] == ':'
    2177             && IS_SLASH(szFull[2])
    2178             && IS_ALPHA(szFull[0]) )
    2179         {
    2180             KU32     uHashPath2  = kwStrHash(szFull);
    2181             PKWFSOBJ pFsObj = kwFsLookupAbsoluteA(szFull, cchFull, uHashPath2, uHashPath2 % K_ELEMENTS(g_apFsAnsiPaths));
    2182             if (pFsObj)
    2183             {
    2184                 kwFsCreateHashTabEntryA(pFsObj, pszPath, cchPath, uHashPath, idxHashTab);
    2185                 return pFsObj;
    2186             }
    2187         }
    2188 
    2189         /* It's worth remembering uncacheable paths in the hash table. */
    2190         kwFsCreateHashTabEntryA(NULL /*pFsObj*/, pszPath, cchPath, uHashPath, idxHashTab);
    2191     }
    2192     return NULL;
    2193 }
    2194 
    2195 
    2196 /**
    2197  * Looks up a KWFSOBJ for the given ANSI path.
    2198  *
    2199  * This will first try the hash table.  If not in the hash table, the file
    2200  * system cache tree is walked, missing bits filled in and finally a hash table
    2201  * entry is created.
    2202  *
    2203  * Only drive letter paths are cachable.  We don't do any UNC paths at this
    2204  * point.
    2205  *
    2206  *
    2207  * @returns Pointer to object corresponding to @a pszPath on success.
    2208  *          NULL if not a path we care to cache.
    2209  * @param   pszPath             The path to lookup.
    2210  */
    2211 static PKWFSOBJ kwFsLookupA(const char *pszPath)
    2212 {
    2213     /*
    2214      * Do hash table lookup of the path.
    2215      */
    2216     KU32        uHashPath;
    2217     KU32        cchPath    = (KU32)kwStrHashEx(pszPath, &uHashPath);
    2218     KU32        idxHashTab = uHashPath % K_ELEMENTS(g_apFsAnsiPaths);
    2219     PKWFSHASHA  pHashEntry = g_apFsAnsiPaths[idxHashTab];
    2220     if (pHashEntry)
    2221     {
    2222         do
    2223         {
    2224             if (   pHashEntry->uHashPath == uHashPath
    2225                 && pHashEntry->cchPath   == cchPath
    2226                 && kHlpMemComp(pHashEntry->pszPath, pszPath, cchPath) == 0)
    2227             {
    2228                 KWFS_LOG(("kwFsLookupA(%s) - hit %p\n", pszPath, pHashEntry->pFsObj));
    2229                 return pHashEntry->pFsObj;
    2230             }
    2231             pHashEntry = pHashEntry->pNext;
    2232         } while (pHashEntry);
    2233     }
    2234 
    2235     /*
    2236      * Create an entry for it by walking the file system cache and filling in the blanks.
    2237      */
    2238     if (   cchPath > 0
    2239         && cchPath < 1024)
    2240     {
    2241         /* Is absolute without any '..' bits? */
    2242         if (   cchPath >= 3
    2243             && pszPath[1] == ':'
    2244             && IS_SLASH(pszPath[2])
    2245             && IS_ALPHA(pszPath[0])
    2246             && !kwFsHasDotDot(pszPath, cchPath) )
    2247             return kwFsLookupAbsoluteA(pszPath, cchPath, uHashPath, idxHashTab);
    2248 
    2249         /* Not UNC? */
    2250         if (   cchPath < 2
    2251             || !IS_SLASH(pszPath[0])
    2252             || !IS_SLASH(pszPath[1]) )
    2253             return kwFsLookupSlowA(pszPath, cchPath, uHashPath, idxHashTab);
    2254 
    2255 
    2256         /* It's worth remembering uncacheable paths in the hash table. */
    2257         kwFsCreateHashTabEntryA(NULL /*pFsObj*/, pszPath, cchPath, uHashPath, idxHashTab);
    2258     }
    2259     return NULL;
    2260 }
    2261 
    22621732
    22631733
     
    30642534 */
    30652535
     2536
     2537/**
     2538 * Converts a lookup error to a windows error code.
     2539 *
     2540 * @returns The windows error code.
     2541 * @param   enmError            The lookup error.
     2542 */
     2543static DWORD kwFsLookupErrorToWindowsError(KFSLOOKUPERROR enmError)
     2544{
     2545    switch (enmError)
     2546    {
     2547        case KFSLOOKUPERROR_NOT_FOUND:
     2548        case KFSLOOKUPERROR_NOT_DIR:
     2549            return ERROR_FILE_NOT_FOUND;
     2550
     2551        case KFSLOOKUPERROR_PATH_COMP_NOT_FOUND:
     2552        case KFSLOOKUPERROR_PATH_COMP_NOT_DIR:
     2553            return ERROR_PATH_NOT_FOUND;
     2554
     2555        case KFSLOOKUPERROR_PATH_TOO_LONG:
     2556            return ERROR_FILENAME_EXCED_RANGE;
     2557
     2558        case KFSLOOKUPERROR_OUT_OF_MEMORY:
     2559            return ERROR_NOT_ENOUGH_MEMORY;
     2560
     2561        default:
     2562            return ERROR_PATH_NOT_FOUND;
     2563    }
     2564}
     2565
    30662566#ifdef WITH_TEMP_MEMORY_FILES
    30672567
     
    34032903
    34042904
    3405 static KBOOL kwFsObjCacheFileCommon(PKWFSOBJ pFsObj, HANDLE hFile)
    3406 {
    3407     LARGE_INTEGER cbFile;
    3408     if (GetFileSizeEx(hFile, &cbFile))
    3409     {
    3410         if (   cbFile.QuadPart >= 0
    3411             && cbFile.QuadPart < 16*1024*1024)
    3412         {
    3413             KU32 cbCache = (KU32)cbFile.QuadPart;
    3414             KU8 *pbCache = (KU8 *)kHlpAlloc(cbCache);
    3415             if (pbCache)
     2905
     2906/**
     2907 * Creates a new
     2908 *
     2909 * @returns
     2910 * @param   pFsObj          .
     2911 * @param   pwszFilename    .
     2912 */
     2913static PKFSWCACHEDFILE kwFsObjCacheNewFile(PKFSOBJ pFsObj)
     2914{
     2915    HANDLE                  hFile;
     2916    MY_IO_STATUS_BLOCK      Ios;
     2917    MY_OBJECT_ATTRIBUTES    ObjAttr;
     2918    MY_UNICODE_STRING       UniStr;
     2919    MY_NTSTATUS             rcNt;
     2920
     2921    /*
     2922     * Open the file relative to the parent directory.
     2923     */
     2924    kHlpAssert(pFsObj->bObjType == KFSOBJ_TYPE_FILE);
     2925    kHlpAssert(pFsObj->pParent);
     2926    kHlpAssertReturn(pFsObj->pParent->hDir != INVALID_HANDLE_VALUE, NULL);
     2927
     2928    Ios.Information = -1;
     2929    Ios.u.Status    = -1;
     2930
     2931    UniStr.Buffer        = (wchar_t *)pFsObj->pwszName;
     2932    UniStr.Length        = (USHORT)(pFsObj->cwcName * sizeof(wchar_t));
     2933    UniStr.MaximumLength = UniStr.Length + sizeof(wchar_t);
     2934
     2935    MyInitializeObjectAttributes(&ObjAttr, &UniStr, OBJ_CASE_INSENSITIVE, pFsObj->pParent->hDir, NULL /*pSecAttr*/);
     2936
     2937    rcNt = g_pfnNtCreateFile(&hFile,
     2938                             GENERIC_READ | SYNCHRONIZE,
     2939                             &ObjAttr,
     2940                             &Ios,
     2941                             NULL, /*cbFileInitialAlloc */
     2942                             FILE_ATTRIBUTE_NORMAL,
     2943                             FILE_SHARE_READ,
     2944                             FILE_OPEN,
     2945                             FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
     2946                             NULL, /*pEaBuffer*/
     2947                             0);   /*cbEaBuffer*/
     2948    if (MY_NT_SUCCESS(rcNt))
     2949    {
     2950        /*
     2951         * Read the whole file into memory.
     2952         */
     2953        LARGE_INTEGER cbFile;
     2954        if (GetFileSizeEx(hFile, &cbFile))
     2955        {
     2956            if (   cbFile.QuadPart >= 0
     2957                && cbFile.QuadPart < 16*1024*1024)
    34162958            {
    3417                 DWORD cbActually = 0;
    3418                 if (   ReadFile(hFile, pbCache, cbCache, &cbActually, NULL)
    3419                     && cbActually == cbCache)
     2959                KU32 cbCache = (KU32)cbFile.QuadPart;
     2960                KU8 *pbCache = (KU8 *)kHlpAlloc(cbCache);
     2961                if (pbCache)
    34202962                {
    3421                     LARGE_INTEGER offZero;
    3422                     offZero.QuadPart = 0;
    3423                     if (SetFilePointerEx(hFile, offZero, NULL /*poffNew*/, FILE_BEGIN))
     2963                    DWORD cbActually = 0;
     2964                    if (   ReadFile(hFile, pbCache, cbCache, &cbActually, NULL)
     2965                        && cbActually == cbCache)
    34242966                    {
    3425                         pFsObj->hCached  = hFile;
    3426                         pFsObj->cbCached = cbCache;
    3427                         pFsObj->pbCached = pbCache;
    3428                         return K_TRUE;
     2967                        LARGE_INTEGER offZero;
     2968                        offZero.QuadPart = 0;
     2969                        if (SetFilePointerEx(hFile, offZero, NULL /*poffNew*/, FILE_BEGIN))
     2970                        {
     2971                            /*
     2972                             * Create the cached file object.
     2973                             */
     2974                            PKFSWCACHEDFILE pCachedFile;
     2975                            pCachedFile = (PKFSWCACHEDFILE)kFsCacheObjAddUserData(g_pFsCache, pFsObj, KW_DATA_KEY_CACHED_FILE,
     2976                                                                                  sizeof(*pCachedFile));
     2977                            if (pCachedFile)
     2978                            {
     2979                                pCachedFile->hCached  = hFile;
     2980                                pCachedFile->cbCached = cbCache;
     2981                                pCachedFile->pbCached = pbCache;
     2982                                pCachedFile->pFsObj   = pFsObj;
     2983                                kFsCacheObjRetain(pFsObj);
     2984                                return pCachedFile;
     2985                            }
     2986
     2987                            KWFS_LOG(("Failed to allocate KFSWCACHEDFILE structure!\n"));
     2988                        }
     2989                        else
     2990                            KWFS_LOG(("Failed to seek to start of cached file! err=%u\n", GetLastError()));
    34292991                    }
    3430 
    3431                     KWFS_LOG(("Failed to seek to start of cached file! err=%u\n", GetLastError()));
     2992                    else
     2993                        KWFS_LOG(("Failed to read %#x bytes into cache! err=%u cbActually=%#x\n",
     2994                                  cbCache, GetLastError(), cbActually));
     2995                    kHlpFree(pbCache);
    34322996                }
    34332997                else
    3434                     KWFS_LOG(("Failed to read %#x bytes into cache! err=%u cbActually=%#x\n",
    3435                               cbCache, GetLastError(), cbActually));
    3436                 kHlpFree(pbCache);
     2998                    KWFS_LOG(("Failed to allocate %#x bytes for cache!\n", cbCache));
    34372999            }
    34383000            else
    3439                 KWFS_LOG(("Failed to allocate %#x bytes for cache!\n", cbCache));
     3001                KWFS_LOG(("File to big to cache! %#llx\n", cbFile.QuadPart));
    34403002        }
    34413003        else
    3442             KWFS_LOG(("File to big to cache! %#llx\n", cbFile.QuadPart));
     3004            KWFS_LOG(("File to get file size! err=%u\n", GetLastError()));
     3005        g_pfnNtClose(hFile);
    34433006    }
    34443007    else
    3445         KWFS_LOG(("File to get file size! err=%u\n", GetLastError()));
    3446     CloseHandle(hFile);
    3447     return K_FALSE;
    3448 }
    3449 
    3450 
    3451 static KBOOL kwFsObjCacheFileA(PKWFSOBJ pFsObj, const char *pszFilename)
    3452 {
    3453     HANDLE hFile;
    3454     kHlpAssert(pFsObj->hCached == INVALID_HANDLE_VALUE);
    3455 
    3456     hFile = CreateFileA(pszFilename, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecAttrs*/,
    3457                         FILE_OPEN_IF, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
    3458     if (hFile != INVALID_HANDLE_VALUE)
    3459         return kwFsObjCacheFileCommon(pFsObj, hFile);
    3460     return K_FALSE;
    3461 }
    3462 
    3463 
    3464 static KBOOL kwFsObjCacheFileW(PKWFSOBJ pFsObj, const wchar_t *pwszFilename)
    3465 {
    3466     HANDLE hFile;
    3467     kHlpAssert(pFsObj->hCached == INVALID_HANDLE_VALUE);
    3468 
    3469     hFile = CreateFileW(pwszFilename, GENERIC_READ, FILE_SHARE_READ, NULL /*pSecAttrs*/,
    3470                         FILE_OPEN_IF, FILE_ATTRIBUTE_NORMAL, NULL /*hTemplateFile*/);
    3471     if (hFile != INVALID_HANDLE_VALUE)
    3472         return kwFsObjCacheFileCommon(pFsObj, hFile);
    3473     return K_FALSE;
    3474 }
    3475 
    3476 
    3477 /** Kernel32 - Common code for CreateFileW and CreateFileA.   */
    3478 static KBOOL kwFsObjCacheCreateFile(PKWFSOBJ pFsObj, DWORD dwDesiredAccess, BOOL fInheritHandle,
    3479                                     const char *pszFilename, const wchar_t *pwszFilename, HANDLE *phFile)
     3008        KWFS_LOG(("Error opening '%ls' for caching: %#x\n", pFsObj->pwszName, rcNt));
     3009    return NULL;
     3010}
     3011
     3012
     3013/**
     3014 * Kernel32 - Common code for CreateFileW and CreateFileA.
     3015 */
     3016static KBOOL kwFsObjCacheCreateFile(PKFSOBJ pFsObj, DWORD dwDesiredAccess, BOOL fInheritHandle, HANDLE *phFile)
    34803017{
    34813018    *phFile = INVALID_HANDLE_VALUE;
     3019    kHlpAssert(pFsObj->fHaveStats);
    34823020
    34833021    /*
    34843022     * At the moment we only handle existing files.
    34853023     */
    3486     if (!(pFsObj->fAttribs & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE))) /* also checks invalid */
    3487     {
    3488         if (   pFsObj->hCached != INVALID_HANDLE_VALUE
    3489             || (pwszFilename != NULL && kwFsObjCacheFileW(pFsObj, pwszFilename))
    3490             || (pszFilename  != NULL && kwFsObjCacheFileA(pFsObj, pszFilename)) )
     3024    if (pFsObj->bObjType == KFSOBJ_TYPE_FILE)
     3025    {
     3026        PKFSWCACHEDFILE pCachedFile = (PKFSWCACHEDFILE)kFsCacheObjGetUserData(g_pFsCache, pFsObj, KW_DATA_KEY_CACHED_FILE);
     3027        if (   pCachedFile != NULL
     3028            || (pCachedFile = kwFsObjCacheNewFile(pFsObj)) != NULL)
    34913029        {
    34923030            HANDLE hProcSelf = GetCurrentProcess();
    3493             if (DuplicateHandle(hProcSelf, pFsObj->hCached,
     3031            if (DuplicateHandle(hProcSelf, pCachedFile->hCached,
    34943032                                hProcSelf, phFile,
    34953033                                dwDesiredAccess, fInheritHandle,
     
    35063044                    pHandle->hHandle            = *phFile;
    35073045                    pHandle->dwDesiredAccess    = dwDesiredAccess;
    3508                     pHandle->u.pFsObj           = pFsObj;
     3046                    pHandle->u.pCachedFile      = pCachedFile;
    35093047                    if (kwSandboxHandleTableEnter(&g_Sandbox, pHandle))
    35103048                        return K_TRUE;
     
    35493087                    if (kwFsIsCachableExtensionA(pszExt, K_FALSE /*fAttrQuery*/))
    35503088                    {
    3551                         PKWFSOBJ pFsObj = kwFsLookupA(pszFilename);
     3089                        KFSLOOKUPERROR enmError;
     3090                        PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
    35523091                        if (pFsObj)
    35533092                        {
    3554                             if (kwFsObjCacheCreateFile(pFsObj, dwDesiredAccess, pSecAttrs && pSecAttrs->bInheritHandle,
    3555                                                        pszFilename, NULL /*pwszFilename*/, &hFile))
     3093                            KBOOL fRc = kwFsObjCacheCreateFile(pFsObj, dwDesiredAccess, pSecAttrs && pSecAttrs->bInheritHandle,
     3094                                                               &hFile);
     3095                            kFsCacheObjRelease(g_pFsCache, pFsObj);
     3096                            if (fRc)
    35563097                            {
    35573098                                KWFS_LOG(("CreateFileA(%s) -> %p [cached]\n", pszFilename, hFile));
     
    36533194            {
    36543195                case KWHANDLETYPE_FSOBJ_READ_CACHE:
    3655                     cbFile = pHandle->u.pFsObj->cbCached;
     3196                    cbFile = pHandle->u.pCachedFile->cbCached;
    36563197                    break;
    36573198#ifdef WITH_TEMP_MEMORY_FILES
     
    37333274            {
    37343275                case KWHANDLETYPE_FSOBJ_READ_CACHE:
    3735                     cbFile = pHandle->u.pFsObj->cbCached;
     3276                    cbFile = pHandle->u.pCachedFile->cbCached;
    37363277                    break;
    37373278#ifdef WITH_TEMP_MEMORY_FILES
     
    38113352                case KWHANDLETYPE_FSOBJ_READ_CACHE:
    38123353                {
    3813                     PKWFSOBJ    pFsObj     = pHandle->u.pFsObj;
    3814                     KU32        cbActually = pFsObj->cbCached - pHandle->offFile;
     3354                    PKFSWCACHEDFILE pCachedFile = pHandle->u.pCachedFile;
     3355                    KU32            cbActually = pCachedFile->cbCached - pHandle->offFile;
    38153356                    if (cbActually > cbToRead)
    38163357                        cbActually = cbToRead;
     
    38183359                        ((KU8 *)pvBuffer)[cbActually] = '\0'; // hack hack hack
    38193360
    3820                     kHlpMemCopy(pvBuffer, &pFsObj->pbCached[pHandle->offFile], cbActually);
     3361                    kHlpMemCopy(pvBuffer, &pCachedFile->pbCached[pHandle->offFile], cbActually);
    38213362                    pHandle->offFile += cbActually;
    38223363
     
    41693710            {
    41703711                case KWHANDLETYPE_FSOBJ_READ_CACHE:
    4171                     KWFS_LOG(("GetFileSize(%p) -> %#x [cached]\n", hFile, pHandle->u.pFsObj->cbCached));
    4172                     return pHandle->u.pFsObj->cbCached;
     3712                    KWFS_LOG(("GetFileSize(%p) -> %#x [cached]\n", hFile, pHandle->u.pCachedFile->cbCached));
     3713                    return pHandle->u.pCachedFile->cbCached;
    41733714
    41743715                case KWHANDLETYPE_TEMP_FILE:
     
    42013742            {
    42023743                case KWHANDLETYPE_FSOBJ_READ_CACHE:
    4203                     KWFS_LOG(("GetFileSizeEx(%p) -> TRUE, %#x [cached]\n", hFile, pHandle->u.pFsObj->cbCached));
    4204                     pcbFile->QuadPart = pHandle->u.pFsObj->cbCached;
     3744                    KWFS_LOG(("GetFileSizeEx(%p) -> TRUE, %#x [cached]\n", hFile, pHandle->u.pCachedFile->cbCached));
     3745                    pcbFile->QuadPart = pHandle->u.pCachedFile->cbCached;
    42053746                    return TRUE;
    42063747
     
    44173958    if (kwFsIsCachableExtensionA(pszExt, K_TRUE /*fAttrQuery*/))
    44183959    {
    4419         PKWFSOBJ pFsObj = kwFsLookupA(pszFilename);
     3960        KFSLOOKUPERROR enmError;
     3961        PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError);
    44203962        if (pFsObj)
    44213963        {
    4422             if (pFsObj->fAttribs == INVALID_FILE_ATTRIBUTES)
    4423                 SetLastError(pFsObj->uLastError);
    4424             KWFS_LOG(("GetFileAttributesA(%s) -> %#x [cached]\n", pszFilename, pFsObj->fAttribs));
    4425             return pFsObj->fAttribs;
    4426         }
     3964            kHlpAssert(pFsObj->fHaveStats);
     3965            fRet = pFsObj->Stats.st_attribs;
     3966            kFsCacheObjRelease(g_pFsCache, pFsObj);
     3967        }
     3968        else
     3969        {
     3970            SetLastError(kwFsLookupErrorToWindowsError(enmError));
     3971            fRet = INVALID_FILE_ATTRIBUTES;
     3972        }
     3973
     3974        KWFS_LOG(("GetFileAttributesA(%s) -> %#x [cached]\n", pszFilename, fRet));
     3975        return fRet;
    44273976    }
    44283977
     
    44393988    if (kwFsIsCachablePathExtensionW(pwszFilename, K_TRUE /*fAttrQuery*/))
    44403989    {
    4441         /** @todo rewrite to pure UTF-16. */
    4442         char szTmp[2048];
    4443         KSIZE cch = kwUtf16ToStr(pwszFilename, szTmp, sizeof(szTmp));
    4444         if (cch < sizeof(szTmp))
    4445             return kwSandbox_Kernel32_GetFileAttributesA(szTmp);
     3990        KFSLOOKUPERROR enmError;
     3991        PKFSOBJ pFsObj = kFsCacheLookupNoMissingW(g_pFsCache, pwszFilename, &enmError);
     3992        if (pFsObj)
     3993        {
     3994            kHlpAssert(pFsObj->fHaveStats);
     3995            fRet = pFsObj->Stats.st_attribs;
     3996            kFsCacheObjRelease(g_pFsCache, pFsObj);
     3997        }
     3998        else
     3999        {
     4000            SetLastError(kwFsLookupErrorToWindowsError(enmError));
     4001            fRet = INVALID_FILE_ATTRIBUTES;
     4002        }
     4003
     4004        KWFS_LOG(("GetFileAttributesW(%ls) -> %#x [cached]\n", pwszFilename, fRet));
     4005        return fRet;
    44464006    }
    44474007
     
    44604020    if (kwFsIsCachablePathExtensionW(pwszLongPath, K_TRUE /*fAttrQuery*/))
    44614021    {
    4462         /** @todo proper implementation later, for now just copy it over as it. */
    4463         KSIZE cwcLongPath = kwUtf16Len(pwszLongPath);
    4464         cwcRet = kwUtf16CopyStyle1(pwszLongPath, pwszShortPath, cwcShortPath);
    4465         KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x [cached]\n",
    4466                   pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
    4467     }
    4468     else
    4469     {
    4470         cwcRet = GetShortPathNameW(pwszLongPath, pwszShortPath, cwcShortPath);
    4471         KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x\n",
    4472                   pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
    4473     }
     4022        KFSLOOKUPERROR enmError;
     4023        PKFSOBJ pObj = kFsCacheLookupW(g_pFsCache, pwszLongPath, &enmError);
     4024        if (pObj)
     4025        {
     4026            if (pObj->bObjType != KFSOBJ_TYPE_MISSING)
     4027            {
     4028                if (kFsCacheObjGetFullShortPathW(pObj, pwszShortPath, cwcShortPath, '\\'))
     4029                {
     4030                    cwcRet = (DWORD)kwUtf16Len(pwszShortPath);
     4031
     4032                    /* Should preserve trailing slash on directory paths. */
     4033                    if (pObj->bObjType == KFSOBJ_TYPE_DIR)
     4034                    {
     4035                        if (   cwcRet + 1 < cwcShortPath
     4036                            && pwszShortPath[cwcRet - 1] != '\\')
     4037                        {
     4038                            KSIZE cwcIn = kwUtf16Len(pwszLongPath);
     4039                            if (   cwcIn > 0
     4040                                && (pwszLongPath[cwcIn - 1] == '\\' || pwszLongPath[cwcIn - 1] == '/') )
     4041                            {
     4042                                pwszShortPath[cwcRet++] = '\\';
     4043                                pwszShortPath[cwcRet]   = '\0';
     4044                            }
     4045                        }
     4046                    }
     4047
     4048                    KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x [cached]\n",
     4049                              pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
     4050                    kFsCacheObjRelease(g_pFsCache, pObj);
     4051                    return cwcRet;
     4052                }
     4053
     4054                /* fall back for complicated cases. */
     4055            }
     4056            kFsCacheObjRelease(g_pFsCache, pObj);
     4057        }
     4058    }
     4059    cwcRet = GetShortPathNameW(pwszLongPath, pwszShortPath, cwcShortPath);
     4060    KWFS_LOG(("GetShortPathNameW(%ls) -> '%*.*ls' & %#x\n",
     4061              pwszLongPath, K_MIN(cwcShortPath, cwcRet), K_MIN(cwcShortPath, cwcRet), pwszShortPath, cwcRet));
    44744062    return cwcRet;
    44754063}
     
    47914379
    47924380
    4793     g_uFsCacheGeneration++;
    4794     if (g_uFsCacheGeneration == KFSWOBJ_CACHE_GEN_IGNORE)
    4795         g_uFsCacheGeneration++;
     4381/** @todo cache generation increment.   */
    47964382    return 0;
    47974383}
     
    49684554            case KWTOOLTYPE_SANDBOXED:
    49694555            case KWTOOLTYPE_WATCOM:
    4970                 /** @todo cache this   */
    4971                 if (SetCurrentDirectoryA(pszCwd))
     4556            {
     4557                /* Change dir. */
     4558                KFSLOOKUPERROR  enmError;
     4559                PKFSOBJ         pNewCurDir = kFsCacheLookupA(g_pFsCache, pszCwd, &enmError);
     4560                if (   pNewCurDir           == g_pCurDirObj
     4561                    && pNewCurDir->bObjType == KFSOBJ_TYPE_DIR)
     4562                    kFsCacheObjRelease(g_pFsCache, pNewCurDir);
     4563                else if (SetCurrentDirectoryA(pszCwd))
    49724564                {
    4973                     if (pTool->enmType == KWTOOLTYPE_SANDBOXED)
    4974                     {
    4975                         KW_LOG(("Sandboxing tool %s\n", pTool->pszPath));
    4976                         rcExit = kwSandboxExec(pTool, cArgs, papszArgs, cbArgs, cEnvVars, papszEnvVars);
    4977                     }
    4978                     else
    4979                     {
    4980                         kwErrPrintf("TODO: Watcom style tool %s\n", pTool->pszPath);
    4981                         rcExit = 42 + 2;
    4982                     }
     4565                    kFsCacheObjRelease(g_pFsCache, g_pCurDirObj);
     4566                    g_pCurDirObj = pNewCurDir;
    49834567                }
    49844568                else
    49854569                {
    49864570                    kwErrPrintf("SetCurrentDirectory failed with %u on '%s'\n", GetLastError(), pszCwd);
     4571                    kFsCacheObjRelease(g_pFsCache, pNewCurDir);
    49874572                    rcExit = 42 + 1;
     4573                    break;
     4574                }
     4575
     4576                /* Call specific handler. */
     4577                if (pTool->enmType == KWTOOLTYPE_SANDBOXED)
     4578                {
     4579                    KW_LOG(("Sandboxing tool %s\n", pTool->pszPath));
     4580                    rcExit = kwSandboxExec(pTool, cArgs, papszArgs, cbArgs, cEnvVars, papszEnvVars);
     4581                }
     4582                else
     4583                {
     4584                    kwErrPrintf("TODO: Watcom style tool %s\n", pTool->pszPath);
     4585                    rcExit = 42 + 2;
    49884586                }
    49894587                break;
     4588            }
    49904589
    49914590            case KWTOOLTYPE_EXEC:
     
    52374836
    52384837
     4838/**
     4839 * Handles what comes after --test.
     4840 *
     4841 * @returns Exit code.
     4842 * @param   argc                Number of arguments after --test.
     4843 * @param   argv                Arguments after --test.
     4844 */
     4845static int kwTestRun(int argc, char **argv)
     4846{
     4847    int         i;
     4848    int         j;
     4849    int         rcExit;
     4850    int         cRepeats;
     4851    char        szCwd[MAX_PATH];
     4852    const char *pszCwd = getcwd(szCwd, sizeof(szCwd));
     4853    KU32        cbArgs;
     4854    KU32        cEnvVars;
     4855
     4856    /*
     4857     * Parse arguments.
     4858     */
     4859    /* Repeat count. */
     4860    i = 0;
     4861    if (i >= argc)
     4862        return kwErrPrintfRc(2, "--test takes an repeat count argument or '--'!\n");
     4863    if (strcmp(argv[i], "--") != 0)
     4864    {
     4865        cRepeats = atoi(argv[i]);
     4866        if (cRepeats <= 0)
     4867            return kwErrPrintfRc(2, "The repeat count '%s' is zero, negative or invalid!\n", argv[i]);
     4868        i++;
     4869
     4870        /* Optional directory change. */
     4871        if (   i < argc
     4872            && strcmp(argv[i], "--chdir") == 0)
     4873        {
     4874            i++;
     4875            if (i >= argc)
     4876                return kwErrPrintfRc(2, "--chdir takes an argument!\n");
     4877            pszCwd = argv[i++];
     4878        }
     4879
     4880        /* Check for '--'. */
     4881        if (i >= argc)
     4882            return kwErrPrintfRc(2, "Missing '--'\n");
     4883        if (strcmp(argv[i], "--") != 0)
     4884            return kwErrPrintfRc(2, "Expected '--' found '%s'\n", argv[i]);
     4885        i++;
     4886    }
     4887    else
     4888    {
     4889        cRepeats = 1;
     4890        i++;
     4891    }
     4892    if (i >= argc)
     4893        return kwErrPrintfRc(2, "Nothing to execute after '--'!\n");
     4894
     4895    /*
     4896     * Do the job.
     4897     */
     4898    cbArgs = 0;
     4899    for (j = i; j < argc; j++)
     4900        cbArgs += (KU32)strlen(argv[j]) + 1;
     4901
     4902    cEnvVars = 0;
     4903    while (environ[cEnvVars] != NULL)
     4904        cEnvVars++;
     4905
     4906    for (j = 0; j < cRepeats; j++)
     4907    {
     4908        rcExit = kSubmitHandleJobUnpacked(argv[i], pszCwd, argc - i, &argv[i], cbArgs, cEnvVars, environ);
     4909    }
     4910
     4911    return rcExit;
     4912}
     4913
     4914
     4915
    52394916int main(int argc, char **argv)
    52404917{
     
    52454922    HANDLE  hPipe = INVALID_HANDLE_VALUE;
    52464923
     4924    /*
     4925     * Create the cache.
     4926     */
     4927    g_pFsCache = kFsCacheCreate(KFSCACHE_F_MISSING_OBJECTS | KFSCACHE_F_MISSING_PATHS);
     4928    if (!g_pFsCache)
     4929        return kwErrPrintfRc(3, "kFsCacheCreate failed!\n");
    52474930
    52484931    /*
     
    52664949                    hPipe = (HANDLE)(uintptr_t)u64Value;
    52674950                else
    5268                 {
    5269                     kwErrPrintf("Invalid --pipe argument: %s\n", argv[i]);
    5270                     return 2;
    5271                 }
     4951                    return kwErrPrintfRc(2, "Invalid --pipe argument: %s\n", argv[i]);
    52724952            }
    52734953            else
    5274             {
    5275                 kwErrPrintf("--pipe takes an argument!\n");
    5276                 return 2;
    5277             }
    5278         }
     4954                return kwErrPrintfRc(2, "--pipe takes an argument!\n");
     4955        }
     4956        else if (strcmp(argv[i], "--test") == 0)
     4957            return kwTestRun(argc - i - 1, &argv[i + 1]);
    52794958        else if (   strcmp(argv[i], "--help") == 0
    52804959                 || strcmp(argv[i], "-h") == 0
     
    52844963                   "usage: kWorker <--help|-h>\n"
    52854964                   "usage: kWorker <--version|-V>\n"
     4965                   "usage: kWorker --test [<times> [--chdir <dir>]] -- args\n"
    52864966                   "\n"
    52874967                   "This is an internal kmk program that is used via the builtin_kSubmit.\n");
     
    52924972            return kbuild_version(argv[0]);
    52934973        else
    5294         {
    5295             kwErrPrintf("Unknown argument '%s'\n", argv[i]);
    5296             return 2;
    5297         }
     4974            return kwErrPrintfRc(2, "Unknown argument '%s'\n", argv[i]);
    52984975    }
    52994976
    53004977    if (hPipe == INVALID_HANDLE_VALUE)
    5301     {
    5302         kwErrPrintf("Missing --pipe <pipe-handle> argument!\n");
    5303         return 2;
    5304     }
     4978        return kwErrPrintfRc(2, "Missing --pipe <pipe-handle> argument!\n");
    53054979
    53064980    /*
     
    53254999                    pbMsgBuf = kHlpRealloc(pbMsgBuf, cbMsgBuf);
    53265000                    if (!pbMsgBuf)
    5327                     {
    5328                         kwErrPrintf("Failed to allocate %u bytes for a message buffer!\n", cbMsgBuf);
    5329                         return 1;
    5330                     }
     5001                        return kwErrPrintfRc(1, "Failed to allocate %u bytes for a message buffer!\n", cbMsgBuf);
    53315002                }
    53325003
     
    53645035                    }
    53655036                    else
    5366                     {
    5367                         kwErrPrintf("Unknown command: '%s'\n", psz);
    5368                         rc = -1;
    5369                     }
     5037                        rc = kwErrPrintfRc(-1, "Unknown command: '%s'\n", psz);
    53705038                }
    53715039            }
    53725040            else
    5373             {
    5374                 kwErrPrintf("Bogus message length: %u (%#x)\n", cbMsg, cbMsg);
    5375                 rc = -1;
    5376             }
     5041                rc = kwErrPrintfRc(-1, "Bogus message length: %u (%#x)\n", cbMsg, cbMsg);
    53775042        }
    53785043        return rc > 0 ? 0 : 1;
  • trunk/src/kmk/kmkbuiltin/kSubmit.c

    r2846 r2858  
    5252#ifdef KBUILD_OS_WINDOWS
    5353# include "sub_proc.h"
    54 # include "quote_argv.h"
    5554#endif
    5655
     
    15331532        if (pWorker)
    15341533        {
    1535 #ifdef KBUILD_OS_WINDOWS
    1536             /* Quote the argv elements, but first we need unquoted pszExecute. */
    1537             int const cArgs = argc - iArg;
    1538             int iArg2;
    1539             char **papszArgsOrg = (char **)xmalloc(sizeof(argv[0]) * cArgs);
    15401534            if (!pszExecutable)
    15411535                pszExecutable = argv[iArg];
    1542             memcpy(papszArgsOrg, &argv[iArg], sizeof(argv[0]) * cArgs);
    1543             quote_argv(cArgs, &argv[iArg], fWatcomBrainDamage, 0 /*fFreeOrLeak*/);
    1544 #endif
    15451536
    15461537            rcExit = kSubmitSendJobMessage(pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity);
     
    15511542                if (atexit(kSubmitAtExitCallback) == 0)
    15521543                    g_fAtExitRegistered = 1;
    1553 
    1554 #ifdef KBUILD_OS_WINDOWS
    1555             for (iArg2 = 0; iArg2 < cArgs; iArg2++)
    1556                 if (argv[iArg2 + iArg] != papszArgsOrg[iArg2])
    1557                 {
    1558                     free(argv[iArg2 + iArg]);
    1559                     argv[iArg2 + iArg] = papszArgsOrg[iArg2];
    1560                 }
    1561             free(papszArgsOrg);
    1562 #endif
    15631544        }
    15641545        else
  • trunk/src/lib/nt/kFsCache.c

    r2857 r2858  
    22202220 *
    22212221 * @returns Reference to object corresponding to @a pszPath on success, this
    2222  *          must be released by kwFsCacheRelease.
     2222 *          must be released by kFsCacheObjRelease.
    22232223 *          NULL if not a path we care to cache.
    22242224 * @param   pCache              The cache.
     
    22462246            {
    22472247                if (   pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
    2248                     || pHashEntry->uCacheGen == pCache->uGeneration
     2248                    || pHashEntry->uCacheGen == (pHashEntry->pFsObj ? pCache->uGeneration : pCache->uGenerationMissing)
    22492249                    || (pHashEntry = kFsCacheRefreshPathA(pCache, pHashEntry, idxHashTab)) )
    22502250                {
     
    23102310 *
    23112311 * @returns Reference to object corresponding to @a pszPath on success, this
    2312  *          must be released by kwFsCacheRelease.
     2312 *          must be released by kFsCacheObjRelease.
    23132313 *          NULL if not a path we care to cache.
    23142314 * @param   pCache              The cache.
     
    23362336            {
    23372337                if (   pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE
    2338                     || pHashEntry->uCacheGen == pCache->uGeneration
     2338                    || pHashEntry->uCacheGen == (pHashEntry->pFsObj ? pCache->uGeneration : pCache->uGenerationMissing)
    23392339                    || (pHashEntry = kFsCacheRefreshPathW(pCache, pHashEntry, idxHashTab)) )
    23402340                {
     
    23902390
    23912391/**
     2392 * Wrapper around kFsCacheLookupA that drops KFSOBJ_TYPE_MISSING and returns
     2393 * KFSLOOKUPERROR_NOT_FOUND instead.
     2394 *
     2395 * @returns Reference to object corresponding to @a pszPath on success, this
     2396 *          must be released by kFsCacheObjRelease.
     2397 *          NULL if not a path we care to cache.
     2398 * @param   pCache              The cache.
     2399 * @param   pszPath             The path to lookup.
     2400 * @param   penmError           Where to return details as to why the lookup
     2401 *                              failed.
     2402 */
     2403PKFSOBJ kFsCacheLookupNoMissingA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError)
     2404{
     2405    PKFSOBJ pObj = kFsCacheLookupA(pCache, pszPath, penmError);
     2406    if (pObj)
     2407    {
     2408        if (pObj->bObjType != KFSOBJ_TYPE_MISSING)
     2409            return pObj;
     2410
     2411        kFsCacheObjRelease(pCache, pObj);
     2412        *penmError = KFSLOOKUPERROR_NOT_FOUND;
     2413    }
     2414    return NULL;
     2415}
     2416
     2417
     2418/**
     2419 * Wrapper around kFsCacheLookupW that drops KFSOBJ_TYPE_MISSING and returns
     2420 * KFSLOOKUPERROR_NOT_FOUND instead.
     2421 *
     2422 * @returns Reference to object corresponding to @a pszPath on success, this
     2423 *          must be released by kFsCacheObjRelease.
     2424 *          NULL if not a path we care to cache.
     2425 * @param   pCache              The cache.
     2426 * @param   pwszPath            The path to lookup.
     2427 * @param   penmError           Where to return details as to why the lookup
     2428 *                              failed.
     2429 */
     2430PKFSOBJ kFsCacheLookupNoMissingW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError)
     2431{
     2432    PKFSOBJ pObj = kFsCacheLookupW(pCache, pwszPath, penmError);
     2433    if (pObj)
     2434    {
     2435        if (pObj->bObjType != KFSOBJ_TYPE_MISSING)
     2436            return pObj;
     2437
     2438        kFsCacheObjRelease(pCache, pObj);
     2439        *penmError = KFSLOOKUPERROR_NOT_FOUND;
     2440    }
     2441    return NULL;
     2442}
     2443
     2444
     2445/**
    23922446 * Destroys a cache object which has a zero reference count.
    23932447 *
     
    24892543KU32 kFsCacheObjRelease(PKFSCACHE pCache, PKFSOBJ pObj)
    24902544{
    2491     KU32 cRefs;
    2492     kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
    2493     kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
    2494 
    2495     cRefs = --pObj->cRefs;
    2496     if (cRefs)
    2497         return cRefs;
    2498     return kFsCacheObjDestroy(pCache, pObj);
     2545    if (pObj)
     2546    {
     2547        KU32 cRefs;
     2548        kHlpAssert(pCache->u32Magic == KFSCACHE_MAGIC);
     2549        kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
     2550
     2551        cRefs = --pObj->cRefs;
     2552        if (cRefs)
     2553            return cRefs;
     2554        return kFsCacheObjDestroy(pCache, pObj);
     2555    }
     2556    return 0;
    24992557}
    25002558
     
    25722630    return NULL;
    25732631}
     2632
     2633
     2634/**
     2635 * Gets the full path to @a pObj, ANSI version.
     2636 *
     2637 * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
     2638 * @param   pObj                The object to get the full path to.
     2639 * @param   pszPath             Where to return the path
     2640 * @param   cbPath              The size of the output buffer.
     2641 * @param   chSlash             The slash to use.
     2642 */
     2643KBOOL kFsCacheObjGetFullPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash)
     2644{
     2645    KSIZE off = pObj->cchParent;
     2646    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
     2647    if (off > 0)
     2648    {
     2649        KSIZE offEnd = off + pObj->cchName;
     2650        if (offEnd < cbPath)
     2651        {
     2652            PKFSDIR pAncestor;
     2653
     2654            pszPath[off + pObj->cchName] = '\0';
     2655            memcpy(&pszPath[off], pObj->pszName, pObj->cchName);
     2656
     2657            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
     2658            {
     2659                kHlpAssert(off > 1);
     2660                kHlpAssert(pAncestor != NULL);
     2661                kHlpAssert(pAncestor->Obj.cchName > 0);
     2662                pszPath[--off] = chSlash;
     2663                off -= pAncestor->Obj.cchName;
     2664                kHlpAssert(pAncestor->Obj.cchParent == off);
     2665                memcpy(&pszPath[off], pAncestor->Obj.pszName, pAncestor->Obj.cchName);
     2666            }
     2667            return K_TRUE;
     2668        }
     2669    }
     2670    else
     2671    {
     2672        KBOOL const fDriveLetter = pObj->cchName == 2 && pObj->pszName[2] == ':';
     2673        off = pObj->cchName;
     2674        if (off + fDriveLetter < cbPath)
     2675        {
     2676            memcpy(pszPath, pObj->pszName, off);
     2677            if (fDriveLetter)
     2678                pszPath[off++] = chSlash;
     2679            pszPath[off] = '\0';
     2680            return K_TRUE;
     2681        }
     2682    }
     2683
     2684    return K_FALSE;
     2685}
     2686
     2687
     2688/**
     2689 * Gets the full path to @a pObj, UTF-16 version.
     2690 *
     2691 * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
     2692 * @param   pObj                The object to get the full path to.
     2693 * @param   pszPath             Where to return the path
     2694 * @param   cbPath              The size of the output buffer.
     2695 * @param   wcSlash             The slash to use.
     2696 */
     2697KBOOL kFsCacheObjGetFullPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash)
     2698{
     2699    KSIZE off = pObj->cwcParent;
     2700    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
     2701    if (off > 0)
     2702    {
     2703        KSIZE offEnd = off + pObj->cwcName;
     2704        if (offEnd < cwcPath)
     2705        {
     2706            PKFSDIR pAncestor;
     2707
     2708            pwszPath[off + pObj->cwcName] = '\0';
     2709            memcpy(&pwszPath[off], pObj->pwszName, pObj->cwcName * sizeof(wchar_t));
     2710
     2711            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
     2712            {
     2713                kHlpAssert(off > 1);
     2714                kHlpAssert(pAncestor != NULL);
     2715                kHlpAssert(pAncestor->Obj.cwcName > 0);
     2716                pwszPath[--off] = wcSlash;
     2717                off -= pAncestor->Obj.cwcName;
     2718                kHlpAssert(pAncestor->Obj.cwcParent == off);
     2719                memcpy(&pwszPath[off], pAncestor->Obj.pwszName, pAncestor->Obj.cwcName * sizeof(wchar_t));
     2720            }
     2721            return K_TRUE;
     2722        }
     2723    }
     2724    else
     2725    {
     2726        KBOOL const fDriveLetter = pObj->cchName == 2 && pObj->pszName[2] == ':';
     2727        off = pObj->cwcName;
     2728        if (off + fDriveLetter < cwcPath)
     2729        {
     2730            memcpy(pwszPath, pObj->pwszName, off * sizeof(wchar_t));
     2731            if (fDriveLetter)
     2732                pwszPath[off++] = wcSlash;
     2733            pwszPath[off] = '\0';
     2734            return K_TRUE;
     2735        }
     2736    }
     2737
     2738    return K_FALSE;
     2739}
     2740
     2741
     2742#ifdef KFSCACHE_CFG_SHORT_NAMES
     2743
     2744/**
     2745 * Gets the full short path to @a pObj, ANSI version.
     2746 *
     2747 * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
     2748 * @param   pObj                The object to get the full path to.
     2749 * @param   pszPath             Where to return the path
     2750 * @param   cbPath              The size of the output buffer.
     2751 * @param   chSlash             The slash to use.
     2752 */
     2753KBOOL kFsCacheObjGetFullShortPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash)
     2754{
     2755    KSIZE off = pObj->cchShortParent;
     2756    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
     2757    if (off > 0)
     2758    {
     2759        KSIZE offEnd = off + pObj->cchShortName;
     2760        if (offEnd < cbPath)
     2761        {
     2762            PKFSDIR pAncestor;
     2763
     2764            pszPath[off + pObj->cchShortName] = '\0';
     2765            memcpy(&pszPath[off], pObj->pszShortName, pObj->cchShortName);
     2766
     2767            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
     2768            {
     2769                kHlpAssert(off > 1);
     2770                kHlpAssert(pAncestor != NULL);
     2771                kHlpAssert(pAncestor->Obj.cchShortName > 0);
     2772                pszPath[--off] = chSlash;
     2773                off -= pAncestor->Obj.cchShortName;
     2774                kHlpAssert(pAncestor->Obj.cchShortParent == off);
     2775                memcpy(&pszPath[off], pAncestor->Obj.pszShortName, pAncestor->Obj.cchShortName);
     2776            }
     2777            return K_TRUE;
     2778        }
     2779    }
     2780    else
     2781    {
     2782        KBOOL const fDriveLetter = pObj->cchShortName == 2 && pObj->pszShortName[2] == ':';
     2783        off = pObj->cchShortName;
     2784        if (off + fDriveLetter < cbPath)
     2785        {
     2786            memcpy(pszPath, pObj->pszShortName, off);
     2787            if (fDriveLetter)
     2788                pszPath[off++] = chSlash;
     2789            pszPath[off] = '\0';
     2790            return K_TRUE;
     2791        }
     2792    }
     2793
     2794    return K_FALSE;
     2795}
     2796
     2797
     2798/**
     2799 * Gets the full short path to @a pObj, UTF-16 version.
     2800 *
     2801 * @returns K_TRUE on success, K_FALSE on buffer overflow (nothing stored).
     2802 * @param   pObj                The object to get the full path to.
     2803 * @param   pszPath             Where to return the path
     2804 * @param   cbPath              The size of the output buffer.
     2805 * @param   wcSlash             The slash to use.
     2806 */
     2807KBOOL kFsCacheObjGetFullShortPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash)
     2808{
     2809    KSIZE off = pObj->cwcShortParent;
     2810    kHlpAssert(pObj->u32Magic == KFSOBJ_MAGIC);
     2811    if (off > 0)
     2812    {
     2813        KSIZE offEnd = off + pObj->cwcShortName;
     2814        if (offEnd < cwcPath)
     2815        {
     2816            PKFSDIR pAncestor;
     2817
     2818            pwszPath[off + pObj->cwcShortName] = '\0';
     2819            memcpy(&pwszPath[off], pObj->pwszShortName, pObj->cwcShortName * sizeof(wchar_t));
     2820
     2821            for (pAncestor = pObj->pParent; off > 0; pAncestor = pAncestor->Obj.pParent)
     2822            {
     2823                kHlpAssert(off > 1);
     2824                kHlpAssert(pAncestor != NULL);
     2825                kHlpAssert(pAncestor->Obj.cwcShortName > 0);
     2826                pwszPath[--off] = wcSlash;
     2827                off -= pAncestor->Obj.cwcShortName;
     2828                kHlpAssert(pAncestor->Obj.cwcShortParent == off);
     2829                memcpy(&pwszPath[off], pAncestor->Obj.pwszShortName, pAncestor->Obj.cwcShortName * sizeof(wchar_t));
     2830            }
     2831            return K_TRUE;
     2832        }
     2833    }
     2834    else
     2835    {
     2836        KBOOL const fDriveLetter = pObj->cchShortName == 2 && pObj->pszShortName[2] == ':';
     2837        off = pObj->cwcShortName;
     2838        if (off + fDriveLetter < cwcPath)
     2839        {
     2840            memcpy(pwszPath, pObj->pwszShortName, off * sizeof(wchar_t));
     2841            if (fDriveLetter)
     2842                pwszPath[off++] = wcSlash;
     2843            pwszPath[off] = '\0';
     2844            return K_TRUE;
     2845        }
     2846    }
     2847
     2848    return K_FALSE;
     2849}
     2850
     2851#endif /* KFSCACHE_CFG_SHORT_NAMES */
    25742852
    25752853
     
    26212899            pCache->fFlags          = fFlags;
    26222900            pCache->uGeneration     = 1;
     2901            pCache->uGenerationMissing = KU32_MAX / 2;
    26232902            pCache->cObjects        = 1;
    26242903            pCache->cbObjects       = sizeof(pCache->RootDir) + pCache->RootDir.cHashTab * sizeof(pCache->RootDir.paHashTab[0]);
  • trunk/src/lib/nt/kFsCache.h

    r2857 r2858  
    427427PKFSOBJ     kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath,
    428428                                         KFSLOOKUPERROR *penmError);
     429PKFSOBJ     kFsCacheLookupNoMissingA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError);
     430PKFSOBJ     kFsCacheLookupNoMissingW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError);
     431
    429432
    430433KU32        kFsCacheObjRelease(PKFSCACHE pCache, PKFSOBJ pObj);
    431434KU32        kFsCacheObjRetain(PKFSOBJ pObj);
    432 PKFSUSERDATA kFsCacheObjAddUserData(PKFSCACHE pCache, PKFSOBJ pPathObj, KUPTR uKey, KSIZE cbUserData);
    433 PKFSUSERDATA kFsCacheObjGetUserData(PKFSCACHE pCache, PKFSOBJ pPathObj, KUPTR uKey);
     435PKFSUSERDATA kFsCacheObjAddUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey, KSIZE cbUserData);
     436PKFSUSERDATA kFsCacheObjGetUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey);
     437KBOOL       kFsCacheObjGetFullPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash);
     438KBOOL       kFsCacheObjGetFullPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash);
     439KBOOL       kFsCacheObjGetFullShortPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash);
     440KBOOL       kFsCacheObjGetFullShortPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash);
    434441
    435442PKFSCACHE   kFsCacheCreate(KU32 fFlags);
  • trunk/src/lib/nt/ntstat.c

    r2851 r2858  
    208208    pStat->st_uid           = 0;
    209209    pStat->st_gid           = 0;
    210     pStat->st_padding1[0]   = 0;
    211     pStat->st_padding1[1]   = 0;
    212     pStat->st_padding1[2]   = 0;
     210    pStat->st_padding1      = 0;
     211    pStat->st_attribs       = pBuf->FileAttributes;
    213212    pStat->st_blksize       = 65536;
    214213    pStat->st_blocks        = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
     
    241240    pStat->st_uid           = 0;
    242241    pStat->st_gid           = 0;
    243     pStat->st_padding1[0]   = 0;
    244     pStat->st_padding1[1]   = 0;
    245     pStat->st_padding1[2]   = 0;
     242    pStat->st_padding1      = 0;
     243    pStat->st_attribs       = pBuf->FileAttributes;
    246244    pStat->st_blksize       = 65536;
    247245    pStat->st_blocks        = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
     
    274272    pStat->st_uid           = 0;
    275273    pStat->st_gid           = 0;
    276     pStat->st_padding1[0]   = 0;
    277     pStat->st_padding1[1]   = 0;
    278     pStat->st_padding1[2]   = 0;
     274    pStat->st_padding1      = 0;
     275    pStat->st_attribs       = pBuf->FileAttributes;
    279276    pStat->st_blksize       = 65536;
    280277    pStat->st_blocks        = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
     
    314311            pStat->st_uid           = 0;
    315312            pStat->st_gid           = 0;
    316             pStat->st_padding1[0]   = 0;
    317             pStat->st_padding1[1]   = 0;
    318             pStat->st_padding1[2]   = 0;
     313            pStat->st_padding1      = 0;
     314            pStat->st_attribs       = pAll->StandardInformation.FileAttributes;
    319315            pStat->st_blksize       = 65536;
    320316            pStat->st_blocks        = (pAll->StandardInformation.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
     
    389385        pStat->st_uid           = 0;
    390386        pStat->st_gid           = 0;
    391         pStat->st_padding1[0]   = 0;
    392         pStat->st_padding1[1]   = 0;
    393         pStat->st_padding1[2]   = 0;
     387        pStat->st_padding1      = 0;
     388        pStat->st_attribs       = BasicInfo.FileAttributes;
    394389        pStat->st_blksize       = 65536;
    395390        pStat->st_blocks        = (StdInfo.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1)
     
    608603                pStat->st_uid               = 0;
    609604                pStat->st_gid               = 0;
    610                 pStat->st_padding1[0]       = 0;
    611                 pStat->st_padding1[1]       = 0;
    612                 pStat->st_padding1[2]       = 0;
     605                pStat->st_padding1          = 0;
     606                pStat->st_attribs           = fFileType == FILE_TYPE_PIPE ? FILE_ATTRIBUTE_NORMAL : FILE_ATTRIBUTE_DEVICE;
    613607                pStat->st_blksize           = 512;
    614608                pStat->st_blocks            = 0;
  • trunk/src/lib/nt/ntstat.h

    r2856 r2858  
    6363    __int16             st_uid;
    6464    __int16             st_gid;
    65     unsigned __int16    st_padding1[3];
     65    unsigned __int16    st_padding1;
     66    unsigned __int32    st_attribs;
    6667    unsigned __int32    st_blksize;
    6768    __int64             st_blocks;
  • trunk/src/lib/nt/ntstuff.h

    r2852 r2858  
    3636#define WIN32_NO_STATUS
    3737#include <Windows.h>
     38#include <winternl.h>
    3839#undef WIN32_NO_STATUS
    3940#include <ntstatus.h>
Note: See TracChangeset for help on using the changeset viewer.