Changeset 2852 in kBuild for trunk/src/lib/nt
- Timestamp:
- Aug 31, 2016 8:46:34 PM (8 years ago)
- Location:
- trunk/src/lib/nt
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/lib/nt/ntdircache.c
r2851 r2852 39 39 40 40 #include <stdio.h> 41 #include <mbstring.h> 42 #include <wchar.h> 41 43 //#include <intrin.h> 42 44 //#include <setjmp.h> … … 834 836 * @param cchPath The length of the path. 835 837 */ 836 static KBOOL kFsCacheHasDotDot (const char *pszPath, KSIZE cchPath)838 static KBOOL kFsCacheHasDotDotA(const char *pszPath, KSIZE cchPath) 837 839 { 838 840 const char *pchDot = (const char *)kHlpMemChr(pszPath, '.', cchPath); … … 863 865 864 866 /** 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 */ 873 static 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 /** 865 902 * Creates an ANSI hash table entry for the given path. 866 903 * … … 900 937 pCache->cAnsiPathCollisions++; 901 938 } 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 */ 955 static 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; 902 982 } 903 983 … … 1149 1229 1150 1230 /** 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 */ 1246 static 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 /** 1151 1267 * Does the initial directory populating or refreshes it if it has been 1152 1268 * invalidated. … … 1166 1282 * ones with file ID on all file systems. */ 1167 1283 #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; 1169 1286 #else 1170 MY_FILE_INFORMATION_CLASS enmInfoClass = MyFileIdFullDirectoryInformation; 1287 MY_FILE_INFORMATION_CLASS const enmInfoClassWithId = MyFileIdFullDirectoryInformation; 1288 MY_FILE_INFORMATION_CLASS enmInfoClass = MyFileIdFullDirectoryInformation; 1171 1289 #endif 1172 1290 MY_NTSTATUS rcNt; … … 1273 1391 /* ASSUME only the FileName member differs between the two structures. */ 1274 1392 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 1282 1406 /* 1283 1407 * Create the entry (not linked yet). … … 1296 1420 1297 1421 #ifdef KFSCACHE_CFG_SHORT_NAMES 1298 if (enmInfoClass == MyFileIdBothDirectoryInformation)1422 if (enmInfoClass == enmInfoClassWithId) 1299 1423 birdStatFillFromFileIdBothDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName); 1300 1424 else 1301 1425 birdStatFillFromFileBothDirInfo(&pCur->Stats, uPtr.pNoId, pCur->pszName); 1302 1426 #else 1303 if (enmInfoClass == MyFileIdBothDirectoryInformation)1427 if (enmInfoClass == enmInfoClassWithId) 1304 1428 birdStatFillFromFileIdFullDirInfo(&pCur->Stats, uPtr.pWithId, pCur->pszName); 1305 1429 else … … 1381 1505 } 1382 1506 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 == cchName1431 && _memicmp(pCur->pszName, pchName, cchName) == 0)1432 #ifdef KFSCACHE_CFG_SHORT_NAMES1433 || ( pCur->cchShortName == cchName1434 && pCur->pszShortName != pCur->pszName1435 && _memicmp(pCur->pszName, pchName, cchName) == 0)1436 #endif1437 )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 we1450 * 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 missing1453 * 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 lookup1458 * 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 else1480 {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 #endif1492 *penmError = KFSLOOKUPERROR_UNSUPPORTED;1493 return NULL;1494 }1495 1507 1496 1508 … … 1681 1693 1682 1694 /** 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 */ 1703 static 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 */ 1746 KBOOL 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 */ 1766 K_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 */ 1806 static 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 */ 1855 static 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 */ 1906 static 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 /** 1683 1944 * Walk the file system tree for the given absolute path, entering it into the 1684 1945 * hash table. … … 1701 1962 PKFSOBJ pChild; 1702 1963 KU32 off; 1703 char ch;1704 1964 KU32 cchSlashes; 1705 1965 KU32 offEnd; … … 1776 2036 * Find the end of the component, counting trailing slashes. 1777 2037 */ 2038 char ch; 1778 2039 cchSlashes = 0; 1779 2040 offEnd = off + 1; … … 1870 2131 1871 2132 /** 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 */ 2147 static 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 /** 1872 2321 * This deals with paths that are relative and paths that contains '..' 1873 * elements .2322 * elements, ANSI version. 1874 2323 * 1875 2324 * @returns Pointer to object corresponding to @a pszPath on success. … … 1919 2368 1920 2369 /** 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 */ 2382 static 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 */ 2426 static 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 */ 2444 static 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 /** 1921 2455 * Looks up a KFSOBJ for the given ANSI path. 1922 2456 * … … 1936 2470 * failed. 1937 2471 */ 1938 staticPKFSOBJ kFsCacheLookupA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError)2472 PKFSOBJ kFsCacheLookupA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError) 1939 2473 { 1940 2474 /* … … 1986 2520 || ( IS_SLASH(pszPath[0]) /* UNC */ 1987 2521 && IS_SLASH(pszPath[1]) ) ) 1988 && !kFsCacheHasDotDot (pszPath, cchPath) )2522 && !kFsCacheHasDotDotA(pszPath, cchPath) ) 1989 2523 pFsObj = kFsCacheLookupAbsoluteA(pCache, pszPath, cchPath, penmError); 1990 2524 else … … 1995 2529 || *penmError == KFSLOOKUPERROR_UNSUPPORTED ) 1996 2530 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 */ 2561 PKFSOBJ 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); 1997 2620 1998 2621 pCache->cLookups++; -
trunk/src/lib/nt/nthlpcore.c
r2715 r2852 54 54 BOOLEAN (WINAPI *g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *); 55 55 MY_NTSTATUS (WINAPI *g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN); 56 BOOLEAN (WINAPI *g_pfnRtlEqualUnicodeString)(MY_UNICODE_STRING const *, MY_UNICODE_STRING const *, BOOLEAN); 57 BOOLEAN (WINAPI *g_pfnRtlEqualString)(MY_ANSI_STRING const *, MY_ANSI_STRING const *, BOOLEAN); 58 UCHAR (WINAPI *g_pfnRtlUpperChar)(UCHAR uch); 56 59 57 60 … … 71 74 { (FARPROC *)&g_pfnRtlDosPathNameToNtPathName_U, "RtlDosPathNameToNtPathName_U" }, 72 75 { (FARPROC *)&g_pfnRtlAnsiStringToUnicodeString, "RtlAnsiStringToUnicodeString" }, 76 { (FARPROC *)&g_pfnRtlEqualUnicodeString, "RtlEqualUnicodeString" }, 77 { (FARPROC *)&g_pfnRtlEqualString, "RtlEqualString" }, 78 { (FARPROC *)&g_pfnRtlUpperChar, "RtlUpperChar" }, 73 79 }; 74 80 /** Set to 1 if we've successfully resolved the imports, otherwise 0. */ -
trunk/src/lib/nt/ntstuff.h
r2851 r2852 433 433 extern BOOLEAN (WINAPI * g_pfnRtlDosPathNameToNtPathName_U)(PCWSTR, MY_UNICODE_STRING *, PCWSTR *, MY_RTL_RELATIVE_NAME_U *); 434 434 extern MY_NTSTATUS (WINAPI * g_pfnRtlAnsiStringToUnicodeString)(MY_UNICODE_STRING *, MY_ANSI_STRING const *, BOOLEAN); 435 extern BOOLEAN (WINAPI * g_pfnRtlEqualUnicodeString)(MY_UNICODE_STRING const *pUniStr1, MY_UNICODE_STRING const *pUniStr2, 436 BOOLEAN fCaseInsensitive); 437 extern BOOLEAN (WINAPI * g_pfnRtlEqualString)(MY_ANSI_STRING const *pAnsiStr1, MY_ANSI_STRING const *pAnsiStr2, 438 BOOLEAN fCaseInsensitive); 439 extern UCHAR (WINAPI * g_pfnRtlUpperChar)(UCHAR uch); 435 440 436 441
Note:
See TracChangeset
for help on using the changeset viewer.