VirtualBox

Changeset 2852 in kBuild for trunk/src/lib/nt


Ignore:
Timestamp:
Aug 31, 2016 8:46:34 PM (8 years ago)
Author:
bird
Message:

updates

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

Legend:

Unmodified
Added
Removed
  • trunk/src/lib/nt/ntdircache.c

    r2851 r2852  
    3939
    4040#include <stdio.h>
     41#include <mbstring.h>
     42#include <wchar.h>
    4143//#include <intrin.h>
    4244//#include <setjmp.h>
     
    834836 * @param   cchPath             The length of the path.
    835837 */
    836 static KBOOL kFsCacheHasDotDot(const char *pszPath, KSIZE cchPath)
     838static KBOOL kFsCacheHasDotDotA(const char *pszPath, KSIZE cchPath)
    837839{
    838840    const char *pchDot = (const char *)kHlpMemChr(pszPath, '.', cchPath);
     
    863865
    864866/**
     867 * Looks for '..' in the path.
     868 *
     869 * @returns K_TRUE if '..' component found, K_FALSE if not.
     870 * @param   pwszPath            The path.
     871 * @param   cwcPath             The length of the path (in wchar_t's).
     872 */
     873static KBOOL kFsCacheHasDotDotW(const wchar_t *pwszPath, KSIZE cwcPath)
     874{
     875    const wchar_t *pwcDot = wmemchr(pwszPath, '.', cwcPath);
     876    while (pwcDot)
     877    {
     878        if (pwcDot[1] != '.')
     879            pwcDot = wmemchr(pwcDot + 1, '.', &pwszPath[cwcPath] - pwcDot - 1);
     880        else
     881        {
     882            wchar_t wch;
     883            if (   (wch = pwcDot[2]) == '\0'
     884                && IS_SLASH(wch))
     885            {
     886                if (pwcDot == pwszPath)
     887                    return K_TRUE;
     888                wch = pwcDot[-1];
     889                if (   IS_SLASH(wch)
     890                    || wch == ':')
     891                    return K_TRUE;
     892            }
     893            pwcDot = wmemchr(pwcDot + 2, '.', &pwszPath[cwcPath] - pwcDot - 2);
     894        }
     895    }
     896
     897    return K_FALSE;
     898}
     899
     900
     901/**
    865902 * Creates an ANSI hash table entry for the given path.
    866903 *
     
    900937            pCache->cAnsiPathCollisions++;
    901938    }
     939    return pHashEntry;
     940}
     941
     942
     943/**
     944 * Creates an UTF-16 hash table entry for the given path.
     945 *
     946 * @returns The hash table entry or NULL if out of memory.
     947 * @param   pCache              The hash
     948 * @param   pFsObj              The resulting object.
     949 * @param   pwszPath            The path.
     950 * @param   cwcPath             The length of the path (in wchar_t's).
     951 * @param   uHashPath           The hash of the path.
     952 * @param   idxHashTab          The hash table index of the path.
     953 * @param   enmError            The lookup error.
     954 */
     955static PKFSHASHW kFsCacheCreatePathHashTabEntryW(PKFSCACHE pCache, PKFSOBJ pFsObj, const wchar_t *pwszPath, KU32 cwcPath,
     956                                                 KU32 uHashPath, KU32 idxHashTab, KFSLOOKUPERROR enmError)
     957{
     958    PKFSHASHW pHashEntry = (PKFSHASHW)kHlpAlloc(sizeof(*pHashEntry) + (cwcPath + 1) * sizeof(wchar_t));
     959    if (pHashEntry)
     960    {
     961        pHashEntry->uHashPath   = uHashPath;
     962        pHashEntry->cwcPath     = cwcPath;
     963        pHashEntry->pwszPath    = (const wchar_t *)kHlpMemCopy(pHashEntry + 1, pwszPath, (cwcPath + 1) * sizeof(wchar_t));
     964        pHashEntry->pFsObj      = pFsObj;
     965        pHashEntry->enmError    = enmError;
     966        if (pFsObj)
     967            pHashEntry->uCacheGen = pCache->uGeneration;
     968        else if (enmError != KFSLOOKUPERROR_UNSUPPORTED)
     969            pHashEntry->uCacheGen = pCache->uGenerationMissing;
     970        else
     971            pHashEntry->uCacheGen = KFSWOBJ_CACHE_GEN_IGNORE;
     972
     973        pHashEntry->pNext = pCache->apUtf16Paths[idxHashTab];
     974        pCache->apUtf16Paths[idxHashTab] = pHashEntry;
     975
     976        pCache->cbUtf16Paths += sizeof(*pHashEntry) + (cwcPath + 1) * sizeof(wchar_t);
     977        pCache->cUtf16Paths++;
     978        if (pHashEntry->pNext)
     979            pCache->cAnsiPathCollisions++;
     980    }
     981    return pHashEntry;
    902982}
    903983
     
    11491229
    11501230/**
     1231 * Creates a missing object, UTF-16 version.
     1232 *
     1233 * This is used for caching negative results.
     1234 *
     1235 * @returns Pointer to the newly created object on success (already linked into
     1236 *          pParent).  No reference.
     1237 *
     1238 *          NULL on failure.
     1239 *
     1240 * @param   pCache              The cache.
     1241 * @param   pParent             The parent directory.
     1242 * @param   pwcName             The name.
     1243 * @param   cwcName             The length of the name.
     1244 * @param   penmError           Where to return failure explanations.
     1245 */
     1246static PKFSOBJ kFsCacheCreateMissingW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwcName, KU32 cwcName,
     1247                                      KFSLOOKUPERROR *penmError)
     1248{
     1249    /** @todo check that it actually doesn't exists before we add it.  We should not
     1250     *        trust the directory enumeration here, or maybe we should?? */
     1251    PKFSOBJ pMissing = kFsCacheCreateObjectW(pCache, pParent, pwcName, cwcName,
     1252#ifdef KFSCACHE_CFG_SHORT_NAMES
     1253                                             NULL, 0,
     1254#endif
     1255                                             KFSOBJ_TYPE_MISSING, penmError);
     1256    if (pMissing)
     1257    {
     1258        KBOOL fRc = kFsCacheDirAddChild(pCache, pParent, pMissing, penmError);
     1259        kFsCacheObjRelease(pCache, pMissing);
     1260        return fRc ? pMissing : NULL;
     1261    }
     1262    return NULL;
     1263}
     1264
     1265
     1266/**
    11511267 * Does the initial directory populating or refreshes it if it has been
    11521268 * invalidated.
     
    11661282     *        ones with file ID on all file systems. */
    11671283#ifdef KFSCACHE_CFG_SHORT_NAMES
    1168     MY_FILE_INFORMATION_CLASS   enmInfoClass = MyFileIdBothDirectoryInformation;
     1284    MY_FILE_INFORMATION_CLASS const enmInfoClassWithId = MyFileIdBothDirectoryInformation;
     1285    MY_FILE_INFORMATION_CLASS       enmInfoClass = MyFileIdBothDirectoryInformation;
    11691286#else
    1170     MY_FILE_INFORMATION_CLASS   enmInfoClass = MyFileIdFullDirectoryInformation;
     1287    MY_FILE_INFORMATION_CLASS const enmInfoClassWithId = MyFileIdFullDirectoryInformation;
     1288    MY_FILE_INFORMATION_CLASS       enmInfoClass = MyFileIdFullDirectoryInformation;
    11711289#endif
    11721290    MY_NTSTATUS                 rcNt;
     
    12731391            /* ASSUME only the FileName member differs between the two structures. */
    12741392            uPtr.pb = &uBuf.abBuf[offBuf];
    1275 #ifdef KFSCACHE_CFG_SHORT_NAMES
    1276             pwszFilename = enmInfoClass == MyFileIdBothDirectoryInformation
    1277                          ? &uPtr.pWithId->FileName[0] :  &uPtr.pNoId->FileName[0];
    1278 #else
    1279             pwszFilename = enmInfoClass == MyFileIdFullDirectoryInformation
    1280                          ? &uPtr.pWithId->FileName[0] :  &uPtr.pNoId->FileName[0];
    1281 #endif
     1393            if (enmInfoClass == enmInfoClassWithId)
     1394            {
     1395                pwszFilename = &uPtr.pWithId->FileName[0];
     1396                cbMinCur  = (KU32)((uintptr_t)&uPtr.pWithId->FileName[0] - (uintptr_t)uPtr.pWithId);
     1397                cbMinCur += uPtr.pNoId->FileNameLength;
     1398            }
     1399            else
     1400            {
     1401                pwszFilename = &uPtr.pNoId->FileName[0];
     1402                cbMinCur  = (KU32)((uintptr_t)&uPtr.pNoId->FileName[0] - (uintptr_t)uPtr.pNoId);
     1403                cbMinCur += uPtr.pNoId->FileNameLength;
     1404            }
     1405
    12821406            /*
    12831407             * Create the entry (not linked yet).
     
    12961420
    12971421#ifdef KFSCACHE_CFG_SHORT_NAMES
    1298             if (enmInfoClass == MyFileIdBothDirectoryInformation)
     1422            if (enmInfoClass == enmInfoClassWithId)
    12991423                birdStatFillFromFileIdBothDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName);
    13001424            else
    13011425                birdStatFillFromFileBothDirInfo(&pCur->Stats, uPtr.pNoId, pCur->pszName);
    13021426#else
    1303             if (enmInfoClass == MyFileIdBothDirectoryInformation)
     1427            if (enmInfoClass == enmInfoClassWithId)
    13041428                birdStatFillFromFileIdFullDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName);
    13051429            else
     
    13811505}
    13821506
    1383 
    1384 /**
    1385  * Refreshes a path hash that has expired.
    1386  *
    1387  * @returns pHash on success, NULL if removed.
    1388  * @param   pCache              The cache.
    1389  * @param   pHashEntry          The path hash.
    1390  * @param   idxHashTab          The hash table entry.
    1391  */
    1392 static PKFSHASHA kFsCacheRefreshPathA(PKFSCACHE pCache, PKFSHASHA pHashEntry, KU32 idxHashTab)
    1393 {
    1394     /** @todo implement once we've start inserting uCacheGen nodes. */
    1395     __debugbreak();
    1396     K_NOREF(pCache);
    1397     K_NOREF(idxHashTab);
    1398     return pHashEntry;
    1399 }
    1400 
    1401 
    1402 /**
    1403  * Look up a child node, ANSI version.
    1404  *
    1405  * @returns Pointer to the child if found, NULL if not.
    1406  * @param   pCache              The cache.
    1407  * @param   pParent             The parent directory to search.
    1408  * @param   pchName             The child name to search for (not terminated).
    1409  * @param   cchName             The length of the child name.
    1410  */
    1411 static PKFSOBJ kFsCacheFindChildA(PKFSCACHE pCache, PKFSDIR pParent, const char *pchName, KU32 cchName)
    1412 {
    1413     /* Check for '.' first. */
    1414     if (cchName != 1 || *pchName != '.')
    1415     {
    1416         KU32        cLeft;
    1417         PKFSOBJ    *ppCur;
    1418 
    1419         if (pParent->paHashTab != NULL)
    1420         {
    1421             /** @todo directory hash table lookup.   */
    1422         }
    1423 
    1424         /* Linear search. */
    1425         cLeft = pParent->cChildren;
    1426         ppCur = pParent->papChildren;
    1427         while (cLeft-- > 0)
    1428         {
    1429             PKFSOBJ pCur = *ppCur++;
    1430             if (   (   pCur->cchName == cchName
    1431                     && _memicmp(pCur->pszName, pchName, cchName) == 0)
    1432 #ifdef KFSCACHE_CFG_SHORT_NAMES
    1433                 || (   pCur->cchShortName == cchName
    1434                     && pCur->pszShortName != pCur->pszName
    1435                     && _memicmp(pCur->pszName, pchName, cchName) == 0)
    1436 #endif
    1437                )
    1438                 return pCur;
    1439         }
    1440         return NULL;
    1441     }
    1442     return &pParent->Obj;
    1443 }
    1444 
    1445 
    1446 /**
    1447  * Looks up a UNC share, ANSI version.
    1448  *
    1449  * We keep both the server and share in the root directory entry.  This means we
    1450  * have to clean up the entry name before we can insert it.
    1451  *
    1452  * @returns Pointer to the share root directory or an update-to-date missing
    1453  *          node.
    1454  * @param   pCache              The cache.
    1455  * @param   pszPath             The path.
    1456  * @param   poff                Where to return the root dire.
    1457  * @param   penmError           Where to return details as to why the lookup
    1458  *                              failed.
    1459  */
    1460 static PKFSOBJ kFswCacheLookupUncShareA(PKFSCACHE pCache, const char *pszPath, KU32 *poff, KFSLOOKUPERROR *penmError)
    1461 {
    1462 #if 0 /* later */
    1463     KU32 offStartServer;
    1464     KU32 offEndServer;
    1465     KU32 offStartShare;
    1466 
    1467     KU32 offEnd = 2;
    1468     while (IS_SLASH(pszPath[offEnd]))
    1469         offEnd++;
    1470 
    1471     offStartServer = offEnd;
    1472     while (   (ch = pszPath[offEnd]) != '\0'
    1473            && !IS_SLASH(ch))
    1474         offEnd++;
    1475     offEndServer = offEnd;
    1476 
    1477     if (ch != '\0')
    1478     { /* likely */ }
    1479     else
    1480     {
    1481         *penmError = KFSLOOKUPERROR_NOT_FOUND;
    1482         return NULL;
    1483     }
    1484 
    1485     while (IS_SLASH(pszPath[offEnd]))
    1486         offEnd++;
    1487     offStartServer = offEnd;
    1488     while (   (ch = pszPath[offEnd]) != '\0'
    1489            && !IS_SLASH(ch))
    1490         offEnd++;
    1491 #endif
    1492     *penmError = KFSLOOKUPERROR_UNSUPPORTED;
    1493     return NULL;
    1494 }
    14951507
    14961508
     
    16811693
    16821694/**
     1695 * Look up a child node, ANSI version.
     1696 *
     1697 * @returns Pointer to the child if found, NULL if not.
     1698 * @param   pCache              The cache.
     1699 * @param   pParent             The parent directory to search.
     1700 * @param   pchName             The child name to search for (not terminated).
     1701 * @param   cchName             The length of the child name.
     1702 */
     1703static PKFSOBJ kFsCacheFindChildA(PKFSCACHE pCache, PKFSDIR pParent, const char *pchName, KU32 cchName)
     1704{
     1705    /* Check for '.' first. */
     1706    if (cchName != 1 || *pchName != '.')
     1707    {
     1708        KU32        cLeft;
     1709        PKFSOBJ    *ppCur;
     1710
     1711        if (pParent->paHashTab != NULL)
     1712        {
     1713            /** @todo directory hash table lookup.   */
     1714        }
     1715
     1716        /* Linear search. */
     1717        cLeft = pParent->cChildren;
     1718        ppCur = pParent->papChildren;
     1719        while (cLeft-- > 0)
     1720        {
     1721            PKFSOBJ pCur = *ppCur++;
     1722            if (   (   pCur->cchName == cchName
     1723                    && _mbsnicmp(pCur->pszName, pchName, cchName) == 0)
     1724#ifdef KFSCACHE_CFG_SHORT_NAMES
     1725                || (   pCur->cchShortName == cchName
     1726                    && pCur->pszShortName != pCur->pszName
     1727                    && _mbsnicmp(pCur->pszShortName, pchName, cchName) == 0)
     1728#endif
     1729               )
     1730                return pCur;
     1731        }
     1732        return NULL;
     1733    }
     1734    return &pParent->Obj;
     1735}
     1736
     1737
     1738/**
     1739 * For use when kFsCacheIAreEqualW hit's something non-trivial.
     1740 *
     1741 * @returns K_TRUE if equal, K_FALSE if different.
     1742 * @param   pwcName1            The first string.
     1743 * @param   pwcName2            The second string.
     1744 * @param   cwcName             The length of the two strings (in wchar_t's).
     1745 */
     1746KBOOL kFsCacheIAreEqualSlowW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU16 cwcName)
     1747{
     1748    MY_UNICODE_STRING UniStr1 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName1 };
     1749    MY_UNICODE_STRING UniStr2 = { cwcName * sizeof(wchar_t), cwcName * sizeof(wchar_t), (wchar_t *)pwcName2 };
     1750    return g_pfnRtlEqualUnicodeString(&UniStr1, &UniStr2, TRUE /*fCaseInsensitive*/);
     1751}
     1752
     1753
     1754/**
     1755 * Compares two UTF-16 strings in a case-insensitive fashion.
     1756 *
     1757 * You would think we should be using _wscnicmp here instead, however it is
     1758 * locale dependent and defaults to ASCII upper/lower handling setlocale hasn't
     1759 * been called.
     1760 *
     1761 * @returns K_TRUE if equal, K_FALSE if different.
     1762 * @param   pwcName1            The first string.
     1763 * @param   pwcName2            The second string.
     1764 * @param   cwcName             The length of the two strings (in wchar_t's).
     1765 */
     1766K_INLINE KBOOL kFsCacheIAreEqualW(const wchar_t *pwcName1, const wchar_t *pwcName2, KU32 cwcName)
     1767{
     1768    while (cwcName > 0)
     1769    {
     1770        wchar_t wc1 = *pwcName1;
     1771        wchar_t wc2 = *pwcName2;
     1772        if (wc1 == wc2)
     1773        { /* not unlikely */ }
     1774        else if (  (KU16)wc1 < (KU16)0xc0 /* U+00C0 is the first upper/lower letter after 'z'. */
     1775                && (KU16)wc2 < (KU16)0xc0)
     1776        {
     1777            /* ASCII upper case. */
     1778            if ((KU16)wc1 - (KU16)0x61 < (KU16)26)
     1779                wc1 &= ~(wchar_t)0x20;
     1780            if ((KU16)wc2 - (KU16)0x61 < (KU16)26)
     1781                wc2 &= ~(wchar_t)0x20;
     1782            if (wc1 != wc2)
     1783                return K_FALSE;
     1784        }
     1785        else
     1786            return kFsCacheIAreEqualSlowW(pwcName1, pwcName2, (KU16)cwcName);
     1787
     1788        pwcName2++;
     1789        pwcName1++;
     1790        cwcName--;
     1791    }
     1792
     1793    return K_TRUE;
     1794}
     1795
     1796
     1797/**
     1798 * Look up a child node, UTF-16 version.
     1799 *
     1800 * @returns Pointer to the child if found, NULL if not.
     1801 * @param   pCache              The cache.
     1802 * @param   pParent             The parent directory to search.
     1803 * @param   pwcName             The child name to search for (not terminated).
     1804 * @param   cwcName             The length of the child name (in wchar_t's).
     1805 */
     1806static PKFSOBJ kFsCacheFindChildW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwcName, KU32 cwcName)
     1807{
     1808    /* Check for '.' first. */
     1809    if (cwcName != 1 || *pwcName != '.')
     1810    {
     1811        KU32        cLeft;
     1812        PKFSOBJ    *ppCur;
     1813
     1814        if (pParent->paHashTab != NULL)
     1815        {
     1816            /** @todo directory hash table lookup.   */
     1817        }
     1818
     1819        /* Linear search. */
     1820        cLeft = pParent->cChildren;
     1821        ppCur = pParent->papChildren;
     1822        while (cLeft-- > 0)
     1823        {
     1824            PKFSOBJ pCur = *ppCur++;
     1825            if (   (   pCur->cwcName == cwcName
     1826                    && kFsCacheIAreEqualW(pCur->pwszName, pwcName, cwcName))
     1827#ifdef KFSCACHE_CFG_SHORT_NAMES
     1828                || (   pCur->cwcShortName == cwcName
     1829                    && pCur->pwszShortName != pCur->pwszName
     1830                    && kFsCacheIAreEqualW(pCur->pwszShortName, pwcName, cwcName))
     1831#endif
     1832               )
     1833                return pCur;
     1834        }
     1835        return NULL;
     1836    }
     1837    return &pParent->Obj;
     1838}
     1839
     1840
     1841/**
     1842 * Looks up a UNC share, ANSI version.
     1843 *
     1844 * We keep both the server and share in the root directory entry.  This means we
     1845 * have to clean up the entry name before we can insert it.
     1846 *
     1847 * @returns Pointer to the share root directory or an update-to-date missing
     1848 *          node.
     1849 * @param   pCache              The cache.
     1850 * @param   pszPath             The path.
     1851 * @param   poff                Where to return the root dire.
     1852 * @param   penmError           Where to return details as to why the lookup
     1853 *                              failed.
     1854 */
     1855static PKFSOBJ kFswCacheLookupUncShareA(PKFSCACHE pCache, const char *pszPath, KU32 *poff, KFSLOOKUPERROR *penmError)
     1856{
     1857#if 0 /* later */
     1858    KU32 offStartServer;
     1859    KU32 offEndServer;
     1860    KU32 offStartShare;
     1861
     1862    KU32 offEnd = 2;
     1863    while (IS_SLASH(pszPath[offEnd]))
     1864        offEnd++;
     1865
     1866    offStartServer = offEnd;
     1867    while (   (ch = pszPath[offEnd]) != '\0'
     1868           && !IS_SLASH(ch))
     1869        offEnd++;
     1870    offEndServer = offEnd;
     1871
     1872    if (ch != '\0')
     1873    { /* likely */ }
     1874    else
     1875    {
     1876        *penmError = KFSLOOKUPERROR_NOT_FOUND;
     1877        return NULL;
     1878    }
     1879
     1880    while (IS_SLASH(pszPath[offEnd]))
     1881        offEnd++;
     1882    offStartServer = offEnd;
     1883    while (   (ch = pszPath[offEnd]) != '\0'
     1884           && !IS_SLASH(ch))
     1885        offEnd++;
     1886#endif
     1887    *penmError = KFSLOOKUPERROR_UNSUPPORTED;
     1888    return NULL;
     1889}
     1890
     1891
     1892/**
     1893 * Looks up a UNC share, UTF-16 version.
     1894 *
     1895 * We keep both the server and share in the root directory entry.  This means we
     1896 * have to clean up the entry name before we can insert it.
     1897 *
     1898 * @returns Pointer to the share root directory or an update-to-date missing
     1899 *          node.
     1900 * @param   pCache              The cache.
     1901 * @param   pwszPath            The path.
     1902 * @param   poff                Where to return the root dire.
     1903 * @param   penmError           Where to return details as to why the lookup
     1904 *                              failed.
     1905 */
     1906static PKFSOBJ kFswCacheLookupUncShareW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 *poff, KFSLOOKUPERROR *penmError)
     1907{
     1908#if 0 /* later */
     1909    KU32 offStartServer;
     1910    KU32 offEndServer;
     1911    KU32 offStartShare;
     1912
     1913    KU32 offEnd = 2;
     1914    while (IS_SLASH(pwszPath[offEnd]))
     1915        offEnd++;
     1916
     1917    offStartServer = offEnd;
     1918    while (   (ch = pwszPath[offEnd]) != '\0'
     1919           && !IS_SLASH(ch))
     1920        offEnd++;
     1921    offEndServer = offEnd;
     1922
     1923    if (ch != '\0')
     1924    { /* likely */ }
     1925    else
     1926    {
     1927        *penmError = KFSLOOKUPERROR_NOT_FOUND;
     1928        return NULL;
     1929    }
     1930
     1931    while (IS_SLASH(pwszPath[offEnd]))
     1932        offEnd++;
     1933    offStartServer = offEnd;
     1934    while (   (ch = pwszPath[offEnd]) != '\0'
     1935           && !IS_SLASH(ch))
     1936        offEnd++;
     1937#endif
     1938    *penmError = KFSLOOKUPERROR_UNSUPPORTED;
     1939    return NULL;
     1940}
     1941
     1942
     1943/**
    16831944 * Walk the file system tree for the given absolute path, entering it into the
    16841945 * hash table.
     
    17011962    PKFSOBJ     pChild;
    17021963    KU32        off;
    1703     char        ch;
    17041964    KU32        cchSlashes;
    17051965    KU32        offEnd;
     
    17762036         * Find the end of the component, counting trailing slashes.
    17772037         */
     2038        char ch;
    17782039        cchSlashes = 0;
    17792040        offEnd     = off + 1;
     
    18702131
    18712132/**
     2133 * Walk the file system tree for the given absolute path, UTF-16 version.
     2134 *
     2135 * This will create any missing nodes while walking.
     2136 *
     2137 * The caller will have to do the path hash table insertion of the result.
     2138 *
     2139 * @returns Pointer to the tree node corresponding to @a pszPath.
     2140 *          NULL on lookup failure, see @a penmError for details.
     2141 * @param   pCache              The cache.
     2142 * @param   pwszPath            The path to walk.
     2143 * @param   cwcPath             The length of the path (in wchar_t's).
     2144 * @param   penmError           Where to return details as to why the lookup
     2145 *                              failed.
     2146 */
     2147static PKFSOBJ kFsCacheLookupAbsoluteW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 cwcPath, KFSLOOKUPERROR *penmError)
     2148{
     2149    PKFSDIR     pParent = &pCache->RootDir;
     2150    PKFSOBJ     pChild;
     2151    KU32        off;
     2152    KU32        cwcSlashes;
     2153    KU32        offEnd;
     2154
     2155    KFSCACHE_LOG(("kFsCacheLookupAbsoluteW(%ls)\n", pwszPath));
     2156
     2157    /*
     2158     * The root "directory" needs special handling, so we keep it outside the
     2159     * main search loop. (Special: Cannot enumerate it, UNCs, ++.)
     2160     */
     2161    cwcSlashes = 0;
     2162    off        = 0;
     2163    if (   pwszPath[1] == ':'
     2164        && IS_ALPHA(pwszPath[0]))
     2165    {
     2166        /* Drive letter. */
     2167        offEnd = 2;
     2168        kHlpAssert(IS_SLASH(pwszPath[2]));
     2169        pChild = kFswCacheLookupDrive(pCache, toupper(pwszPath[0]), penmError);
     2170    }
     2171    else if (   IS_SLASH(pwszPath[0])
     2172             && IS_SLASH(pwszPath[1]) )
     2173        pChild = kFswCacheLookupUncShareW(pCache, pwszPath, &offEnd, penmError);
     2174    else
     2175    {
     2176        *penmError = KFSLOOKUPERROR_UNSUPPORTED;
     2177        return NULL;
     2178    }
     2179    if (pChild)
     2180    { /* likely */ }
     2181    else
     2182        return NULL;
     2183
     2184    /* Count slashes trailing the root spec. */
     2185    if (offEnd < cwcPath)
     2186    {
     2187        kHlpAssert(IS_SLASH(pwszPath[offEnd]));
     2188        do
     2189            cwcSlashes++;
     2190        while (IS_SLASH(pwszPath[offEnd + cwcSlashes]));
     2191    }
     2192
     2193    /* Done already? */
     2194    if (offEnd >= cwcPath)
     2195    {
     2196        if (   pChild->uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE
     2197            || pChild->uCacheGen == (pChild->bObjType != KFSOBJ_TYPE_MISSING ? pCache->uGeneration : pCache->uGenerationMissing)
     2198            || kFsCacheRefreshObj(pCache, pChild, penmError))
     2199            return kFsCacheObjRetainInternal(pChild);
     2200        return NULL;
     2201    }
     2202
     2203    /* Check that we've got a valid result and not a cached negative one. */
     2204    if (pChild->bObjType == KFSOBJ_TYPE_DIR)
     2205    { /* likely */ }
     2206    else
     2207    {
     2208        kHlpAssert(pChild->bObjType == KFSOBJ_TYPE_MISSING);
     2209        kHlpAssert(pChild->uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE || pChild->uCacheGen == pCache->uGenerationMissing);
     2210        return pChild;
     2211    }
     2212
     2213    /* Next component. */
     2214    pParent = (PKFSDIR)pChild;
     2215    off     = offEnd + cwcSlashes;
     2216
     2217
     2218    /*
     2219     * Walk loop.
     2220     */
     2221    for (;;)
     2222    {
     2223        /*
     2224         * Find the end of the component, counting trailing slashes.
     2225         */
     2226        wchar_t wc;
     2227        cwcSlashes = 0;
     2228        offEnd     = off + 1;
     2229        while ((wc = pwszPath[offEnd]) != '\0')
     2230        {
     2231            if (!IS_SLASH(wc))
     2232                offEnd++;
     2233            else
     2234            {
     2235                do
     2236                    cwcSlashes++;
     2237                while (IS_SLASH(pwszPath[offEnd + cwcSlashes]));
     2238                break;
     2239            }
     2240        }
     2241
     2242        /*
     2243         * Do we need to populate or refresh this directory first?
     2244         */
     2245        if (   pParent->fPopulated
     2246            && (   pParent->Obj.uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE
     2247                || pParent->Obj.uCacheGen == pCache->uGeneration) )
     2248        { /* likely */ }
     2249        else if (kFsCachePopuplateOrRefreshDir(pCache, pParent, penmError))
     2250        { /* likely */ }
     2251        else
     2252            return NULL;
     2253
     2254        /*
     2255         * Search the current node for the name.
     2256         *
     2257         * If we don't find it, we may insert a missing node depending on
     2258         * the cache configuration.
     2259         */
     2260        pChild = kFsCacheFindChildW(pCache, pParent, &pwszPath[off], offEnd - off);
     2261        if (pChild != NULL)
     2262        { /* probably likely */ }
     2263        else
     2264        {
     2265            if (pCache->fFlags & KFSCACHE_F_MISSING_OBJECTS)
     2266                pChild = kFsCacheCreateMissingW(pCache, pParent, &pwszPath[off], offEnd - off, penmError);
     2267            if (cwcSlashes == 0 || offEnd + cwcSlashes >= cwcPath)
     2268            {
     2269                if (pChild)
     2270                    return pChild;
     2271                *penmError = KFSLOOKUPERROR_NOT_FOUND;
     2272            }
     2273            else
     2274                *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
     2275            return NULL;
     2276        }
     2277
     2278        /* Advance off and check if we're done already. */
     2279        off = offEnd + cwcSlashes;
     2280        if (   cwcSlashes == 0
     2281            || off >= cwcPath)
     2282        {
     2283            if (   pChild->bObjType != KFSOBJ_TYPE_MISSING
     2284                || pChild->uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE
     2285                || pChild->uCacheGen == pCache->uGenerationMissing
     2286                || kFsCacheRefreshMissing(pCache, pChild, penmError) )
     2287            { /* likely */ }
     2288            else
     2289                return NULL;
     2290            return pChild;
     2291        }
     2292
     2293        /*
     2294         * Check that it's a directory.  If a missing entry, we may have to
     2295         * refresh it and re-examin it.
     2296         */
     2297        if (pChild->bObjType == KFSOBJ_TYPE_DIR)
     2298            pParent = (PKFSDIR)pChild;
     2299        else if (pChild->bObjType != KFSOBJ_TYPE_MISSING)
     2300        {
     2301            *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_DIR;
     2302            return NULL;
     2303        }
     2304        else if (   pChild->uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE
     2305                 || pChild->uCacheGen == pCache->uGenerationMissing)
     2306        {
     2307            *penmError = KFSLOOKUPERROR_PATH_COMP_NOT_FOUND;
     2308            return NULL;
     2309        }
     2310        else if (kFsCacheRefreshMissingIntermediateDir(pCache, pChild, penmError))
     2311            pParent = (PKFSDIR)pChild;
     2312        else
     2313            return NULL;
     2314    }
     2315
     2316    return NULL;
     2317}
     2318
     2319
     2320/**
    18722321 * This deals with paths that are relative and paths that contains '..'
    1873  * elements.
     2322 * elements, ANSI version.
    18742323 *
    18752324 * @returns Pointer to object corresponding to @a pszPath on success.
     
    19192368
    19202369/**
     2370 * This deals with paths that are relative and paths that contains '..'
     2371 * elements, UTF-16 version.
     2372 *
     2373 * @returns Pointer to object corresponding to @a pszPath on success.
     2374 *          NULL if this isn't a path we care to cache.
     2375 *
     2376 * @param   pCache              The cache.
     2377 * @param   pwszPath            The path.
     2378 * @param   cwcPath             The length of the path (in wchar_t's).
     2379 * @param   penmError           Where to return details as to why the lookup
     2380 *                              failed.
     2381 */
     2382static PKFSOBJ kFsCacheLookupSlowW(PKFSCACHE pCache, const wchar_t *pwszPath, KU32 wcwPath, KFSLOOKUPERROR *penmError)
     2383{
     2384    /*
     2385     * We just call GetFullPathNameA here to do the job as getcwd and _getdcwd
     2386     * ends up calling it anyway.
     2387     */
     2388    wchar_t wszFull[KFSCACHE_CFG_MAX_PATH];
     2389    UINT cwcFull = GetFullPathNameW(pwszPath, KFSCACHE_CFG_MAX_PATH, wszFull, NULL);
     2390    if (   cwcFull >= 3
     2391        && cwcFull < KFSCACHE_CFG_MAX_PATH)
     2392    {
     2393        PKFSOBJ pFsObj;
     2394        KFSCACHE_LOG(("kFsCacheLookupSlowA(%ls)\n", pwszPath));
     2395        pFsObj = kFsCacheLookupAbsoluteW(pCache, wszFull, cwcFull, penmError);
     2396
     2397#if 0 /* No need to do this until it's actually queried. */
     2398        /* Cache the resulting path. */
     2399        if (   pFsObj
     2400            || (pCache->fFlags & KFSCACHE_F_MISSING_PATHS)
     2401            || *penmError == KFSLOOKUPERROR_UNSUPPORTED)
     2402        {
     2403            KU32 uHashPath = kFsCacheStrHash(szFull);
     2404            kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pszPath, cchPath, uHashPath,
     2405                                            uHashPath % K_ELEMENTS(pCache->apAnsiPaths), *penmError);
     2406        }
     2407#endif
     2408        return pFsObj;
     2409    }
     2410
     2411    /* The path is too long! */
     2412    kHlpAssertMsgFailed(("'%ls' -> cwcFull=%u\n", pwszPath, cwcFull));
     2413    *penmError = KFSLOOKUPERROR_PATH_TOO_LONG;
     2414    return NULL;
     2415}
     2416
     2417
     2418/**
     2419 * Refreshes a path hash that has expired, ANSI version.
     2420 *
     2421 * @returns pHash on success, NULL if removed.
     2422 * @param   pCache              The cache.
     2423 * @param   pHashEntry          The path hash.
     2424 * @param   idxHashTab          The hash table entry.
     2425 */
     2426static PKFSHASHA kFsCacheRefreshPathA(PKFSCACHE pCache, PKFSHASHA pHashEntry, KU32 idxHashTab)
     2427{
     2428    /** @todo implement once we've start inserting uCacheGen nodes. */
     2429    __debugbreak();
     2430    K_NOREF(pCache);
     2431    K_NOREF(idxHashTab);
     2432    return pHashEntry;
     2433}
     2434
     2435
     2436/**
     2437 * Refreshes a path hash that has expired, UTF-16 version.
     2438 *
     2439 * @returns pHash on success, NULL if removed.
     2440 * @param   pCache              The cache.
     2441 * @param   pHashEntry          The path hash.
     2442 * @param   idxHashTab          The hash table entry.
     2443 */
     2444static PKFSHASHW kFsCacheRefreshPathW(PKFSCACHE pCache, PKFSHASHW pHashEntry, KU32 idxHashTab)
     2445{
     2446    /** @todo implement once we've start inserting uCacheGen nodes. */
     2447    __debugbreak();
     2448    K_NOREF(pCache);
     2449    K_NOREF(idxHashTab);
     2450    return pHashEntry;
     2451}
     2452
     2453
     2454/**
    19212455 * Looks up a KFSOBJ for the given ANSI path.
    19222456 *
     
    19362470 *                              failed.
    19372471 */
    1938 static PKFSOBJ kFsCacheLookupA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError)
     2472PKFSOBJ kFsCacheLookupA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError)
    19392473{
    19402474    /*
     
    19862520                || (   IS_SLASH(pszPath[0]) /* UNC */
    19872521                    && IS_SLASH(pszPath[1]) ) )
    1988             && !kFsCacheHasDotDot(pszPath, cchPath) )
     2522            && !kFsCacheHasDotDotA(pszPath, cchPath) )
    19892523            pFsObj = kFsCacheLookupAbsoluteA(pCache, pszPath, cchPath, penmError);
    19902524        else
     
    19952529            || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
    19962530            kFsCacheCreatePathHashTabEntryA(pCache, pFsObj, pszPath, cchPath, uHashPath, idxHashTab, *penmError);
     2531
     2532        pCache->cLookups++;
     2533        if (pFsObj)
     2534            pCache->cWalkHits++;
     2535        return pFsObj;
     2536    }
     2537
     2538    *penmError = KFSLOOKUPERROR_PATH_TOO_LONG;
     2539    return NULL;
     2540}
     2541
     2542
     2543/**
     2544 * Looks up a KFSOBJ for the given UTF-16 path.
     2545 *
     2546 * This will first try the hash table.  If not in the hash table, the file
     2547 * system cache tree is walked, missing bits filled in and finally a hash table
     2548 * entry is created.
     2549 *
     2550 * Only drive letter paths are cachable.  We don't do any UNC paths at this
     2551 * point.
     2552 *
     2553 * @returns Reference to object corresponding to @a pszPath on success, this
     2554 *          must be released by kwFsCacheRelease.
     2555 *          NULL if not a path we care to cache.
     2556 * @param   pCache              The cache.
     2557 * @param   pwszPath            The path to lookup.
     2558 * @param   penmError           Where to return details as to why the lookup
     2559 *                              failed.
     2560 */
     2561PKFSOBJ kFsCacheLookupW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError)
     2562{
     2563    /*
     2564     * Do hash table lookup of the path.
     2565     */
     2566    KU32        uHashPath;
     2567    KU32        cwcPath    = (KU32)kFsCacheUtf16HashEx(pwszPath, &uHashPath);
     2568    KU32        idxHashTab = uHashPath % K_ELEMENTS(pCache->apAnsiPaths);
     2569    PKFSHASHW   pHashEntry = pCache->apUtf16Paths[idxHashTab];
     2570    if (pHashEntry)
     2571    {
     2572        do
     2573        {
     2574            if (   pHashEntry->uHashPath == uHashPath
     2575                && pHashEntry->cwcPath   == cwcPath
     2576                && kHlpMemComp(pHashEntry->pwszPath, pwszPath, cwcPath) == 0)
     2577            {
     2578                if (   pHashEntry->uCacheGen == KFSWOBJ_CACHE_GEN_IGNORE
     2579                    || pHashEntry->uCacheGen == pCache->uGeneration
     2580                    || (pHashEntry = kFsCacheRefreshPathW(pCache, pHashEntry, idxHashTab)) )
     2581                {
     2582                    pCache->cLookups++;
     2583                    pCache->cPathHashHits++;
     2584                    KFSCACHE_LOG(("kFsCacheLookupW(%ls) - hit %p\n", pwszPath, pHashEntry->pFsObj));
     2585                    *penmError = pHashEntry->enmError;
     2586                    if (pHashEntry->pFsObj)
     2587                        return kFsCacheObjRetainInternal(pHashEntry->pFsObj);
     2588                    return NULL;
     2589                }
     2590                break;
     2591            }
     2592            pHashEntry = pHashEntry->pNext;
     2593        } while (pHashEntry);
     2594    }
     2595
     2596    /*
     2597     * Create an entry for it by walking the file system cache and filling in the blanks.
     2598     */
     2599    if (   cwcPath > 0
     2600        && cwcPath < KFSCACHE_CFG_MAX_PATH)
     2601    {
     2602        PKFSOBJ pFsObj;
     2603
     2604        /* Is absolute without any '..' bits? */
     2605        if (   cwcPath >= 3
     2606            && (   (   pwszPath[1] == ':'    /* Drive letter */
     2607                    && IS_SLASH(pwszPath[2])
     2608                    && IS_ALPHA(pwszPath[0]) )
     2609                || (   IS_SLASH(pwszPath[0]) /* UNC */
     2610                    && IS_SLASH(pwszPath[1]) ) )
     2611            && !kFsCacheHasDotDotW(pwszPath, cwcPath) )
     2612            pFsObj = kFsCacheLookupAbsoluteW(pCache, pwszPath, cwcPath, penmError);
     2613        else
     2614            pFsObj = kFsCacheLookupSlowW(pCache, pwszPath, cwcPath, penmError);
     2615        if (   pFsObj
     2616            || (   (pCache->fFlags & KFSCACHE_F_MISSING_PATHS)
     2617                && *penmError != KFSLOOKUPERROR_PATH_TOO_LONG)
     2618            || *penmError == KFSLOOKUPERROR_UNSUPPORTED )
     2619            kFsCacheCreatePathHashTabEntryW(pCache, pFsObj, pwszPath, cwcPath, uHashPath, idxHashTab, *penmError);
    19972620
    19982621        pCache->cLookups++;
  • trunk/src/lib/nt/nthlpcore.c

    r2715 r2852  
    5454BOOLEAN     (WINAPI *g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
    5555MY_NTSTATUS (WINAPI *g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
     56BOOLEAN     (WINAPI *g_pfnRtlEqualUnicodeString)(MY_UNICODE_STRING const *, MY_UNICODE_STRING const *, BOOLEAN);
     57BOOLEAN     (WINAPI *g_pfnRtlEqualString)(MY_ANSI_STRING const *, MY_ANSI_STRING const *, BOOLEAN);
     58UCHAR       (WINAPI *g_pfnRtlUpperChar)(UCHAR uch);
    5659
    5760
     
    7174    { (FARPROC *)&g_pfnRtlDosPathNameToNtPathName_U,    "RtlDosPathNameToNtPathName_U" },
    7275    { (FARPROC *)&g_pfnRtlAnsiStringToUnicodeString,    "RtlAnsiStringToUnicodeString" },
     76    { (FARPROC *)&g_pfnRtlEqualUnicodeString,           "RtlEqualUnicodeString" },
     77    { (FARPROC *)&g_pfnRtlEqualString,                  "RtlEqualString" },
     78    { (FARPROC *)&g_pfnRtlUpperChar,                    "RtlUpperChar" },
    7379};
    7480/** Set to 1 if we've successfully resolved the imports, otherwise 0. */
  • trunk/src/lib/nt/ntstuff.h

    r2851 r2852  
    433433extern BOOLEAN     (WINAPI * g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *);
    434434extern MY_NTSTATUS (WINAPI * g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN);
     435extern BOOLEAN     (WINAPI * g_pfnRtlEqualUnicodeString)(MY_UNICODE_STRING const *pUniStr1, MY_UNICODE_STRING const *pUniStr2,
     436                                                         BOOLEAN fCaseInsensitive);
     437extern BOOLEAN     (WINAPI * g_pfnRtlEqualString)(MY_ANSI_STRING const *pAnsiStr1, MY_ANSI_STRING const *pAnsiStr2,
     438                                                  BOOLEAN fCaseInsensitive);
     439extern UCHAR       (WINAPI * g_pfnRtlUpperChar)(UCHAR uch);
    435440
    436441
Note: See TracChangeset for help on using the changeset viewer.

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