Changeset 2858
- Timestamp:
- Sep 1, 2016, 5:12:24 PM (9 years ago)
- Location:
- trunk/src
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kWorker
- Property svn:externals deleted
-
trunk/src/kWorker/Makefile.kmk
r2844 r2858 31 31 PROGRAMS += kWorker 32 32 kWorker_TEMPLATE = BIN-STATIC-THREADED 33 kWorker_INCS = kStuff/include34 33 kWorker_DEFS.debug = K_STRICT 35 34 kWorker_DEFS.release = NASSERT … … 64 63 nt/ntdir.c \ 65 64 nt/ntstat.c \ 66 nt/ntunlink.c 65 nt/ntunlink.c \ 66 nt/kFsCache.c 67 67 kbuild_version.c_DEFS = KBUILD_SVN_REV=$(KBUILD_SVN_REV) 68 68 … … 74 74 kStuff_DEFS.debug = K_STRICT 75 75 kStuff_INCS = kStuff/include 76 kStuff_DEFPATH = $(PATH_ROOT)/src/lib 76 77 77 78 # kLdr -
trunk/src/kWorker/kWorker.c
r2846 r2858 44 44 extern void nt_fullpath(const char *pszPath, char *pszFull, size_t cchFull); 45 45 46 #include <Windows.h>47 #include <winternl.h> 48 46 #include "nt/ntstuff.h" 47 48 #include "nt/kFsCache.h" 49 49 50 50 … … 52 52 * Defined Constants And Macros * 53 53 *********************************************************************************************************************************/ 54 /** Special KWFSOBJ::uCacheGen number indicating that it does not apply. */55 #define KFSWOBJ_CACHE_GEN_IGNORE KU32_MAX56 57 54 /** String constant comma length. */ 58 55 #define TUPLE(a_sz) a_sz, sizeof(a_sz) - 1 … … 95 92 # define KWFS_TEMP_FILE_MAX (64*1024*1024) 96 93 #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) 97 100 98 101 … … 194 197 195 198 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 */ 202 typedef struct KFSWCACHEDFILE 203 { 204 /** The user data core. */ 205 KFSUSERDATA Core; 222 206 223 207 /** Cached file handle. */ … … 227 211 /** Cached file content. */ 228 212 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. */ 219 typedef KFSWCACHEDFILE *PKFSWCACHEDFILE; 298 220 299 221 … … 358 280 { 359 281 /** The file system object. */ 360 PK WFSOBJ pFsObj;282 PKFSWCACHEDFILE pCachedFile; 361 283 /** Temporary file handle or mapping handle. */ 362 284 PKWFSTEMPFILE pTempFile; … … 383 305 } KWTOOLHINT; 384 306 385 typedef struct KWTOOL *PKWTOOL; 307 308 /** 309 * A kWorker tool. 310 */ 386 311 typedef struct KWTOOL 387 312 { 388 /** Pointer to the next in the hash collision chain. */ 389 PKWTOOL pNext; 313 /** The user data core structure. */ 314 KFSUSERDATA Core; 315 390 316 /** The normalized path to the program. */ 391 317 const char *pszPath; 392 /** The hash of the program path. */393 KU32 uHashPath;318 /** UTF-16 version of pszPath. */ 319 wchar_t const *pwszPath; 394 320 /** The kind of tool. */ 395 321 KWTOOLTYPE enmType; 396 /** UTF-16 version of pszPath. */397 wchar_t const *pwszPath;398 322 399 323 union … … 411 335 } u; 412 336 } KWTOOL; 337 /** Pointer to a tool. */ 338 typedef struct KWTOOL *PKWTOOL; 413 339 414 340 … … 507 433 static PKWMODULE g_apModules[127]; 508 434 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. */ 436 static PKFSCACHE g_pFsCache; 437 /** The current directory (referenced). */ 438 static PKFSOBJ g_pCurDirObj = NULL; 555 439 556 440 /** Verbosity level. */ … … 580 464 static FNKLDRMODGETIMPORT kwLdrModuleGetImportCallback; 581 465 static int kwLdrModuleResolveAndLookup(const char *pszName, PKWMODULE pExe, PKWMODULE pImporter, PKWMODULE *ppMod); 582 static PKWFSOBJ kwFsLookupA(const char *pszPath);583 466 static KBOOL kwSandboxHandleTableEnter(PKWSANDBOX pSandbox, PKWHANDLE pHandle); 584 467 … … 683 566 kwErrPrintfV(pszFormat, va); 684 567 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 */ 578 static 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; 685 585 } 686 586 … … 908 808 static int kwPathNormalize(const char *pszPath, char *pszNormPath, KSIZE cbNormPath) 909 809 { 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; 976 822 } 977 823 … … 1061 907 KSIZE idx = pMod->u.Manual.cImpMods; 1062 908 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 } 1067 914 } 1068 915 … … 1566 1413 && (pszPath[cchPath - 1] == 'l' || pszPath[cchPath - 1] == 'L') ) 1567 1414 { 1568 PKWFSOBJ pFsObj = kwFsLookupA(pszPath); 1415 KFSLOOKUPERROR enmError; 1416 PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszPath, &enmError); 1569 1417 if (pFsObj) 1570 1418 { 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; 1573 1422 } 1574 1423 } … … 1762 1611 * 1763 1612 * @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 */ 1619 static 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); 1772 1625 if (pTool) 1773 1626 { 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); 1781 1638 if (!pTool->u.Sandboxed.pExe) 1782 1639 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) 1784 1641 pTool->u.Sandboxed.enmHint = KWTOOLHINT_VISUAL_CPP_CL; 1785 1642 else 1786 1643 pTool->u.Sandboxed.enmHint = KWTOOLHINT_NONE; 1787 1644 1788 /* Link the tool. */ 1789 pTool->pNext = g_apTools[idxHashTab]; 1790 g_apTools[idxHashTab] = pTool; 1645 kFsCacheObjRelease(g_pFsCache, pToolFsObj); 1791 1646 return pTool; 1792 1647 } 1648 kFsCacheObjRelease(g_pFsCache, pToolFsObj); 1793 1649 return NULL; 1794 1650 } … … 1804 1660 { 1805 1661 /* 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. 1807 1663 */ 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) 1818 1672 { 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); 1830 1683 } 1831 1684 return NULL; … … 1842 1695 */ 1843 1696 1844 1845 #define IS_ALPHA(ch) ( ((ch) >= 'A' && (ch) <= 'Z') || ((ch) >= 'a' && (ch) <= 'z') )1846 #define IS_SLASH(ch) ((ch) == '\\' || (ch) == '/')1847 1697 1848 1698 … … 1880 1730 } 1881 1731 } 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 else1899 {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 is1939 * to invalid negative results for each tool execution, in case a include file1940 * or directory has been created since the last time we were active. Assuming1941 * that we'll be stopped together with kmk, there is no need to invalidate1942 * 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 else2003 {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 == cchName2070 && _memicmp(pCur->pszName, pchName, cchName) == 0)2071 {2072 if ( pCur->uCacheGen != KFSWOBJ_CACHE_GEN_IGNORE2073 && 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 the2086 * 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 else2121 {2122 do2123 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 == 02139 || 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 >= 32173 && 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 file2200 * system cache tree is walked, missing bits filled in and finally a hash table2201 * entry is created.2202 *2203 * Only drive letter paths are cachable. We don't do any UNC paths at this2204 * 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 do2223 {2224 if ( pHashEntry->uHashPath == uHashPath2225 && pHashEntry->cchPath == cchPath2226 && 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 > 02239 && cchPath < 1024)2240 {2241 /* Is absolute without any '..' bits? */2242 if ( cchPath >= 32243 && 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 < 22251 || !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 2262 1732 2263 1733 … … 3064 2534 */ 3065 2535 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 */ 2543 static 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 3066 2566 #ifdef WITH_TEMP_MEMORY_FILES 3067 2567 … … 3403 2903 3404 2904 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 */ 2913 static 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) 3416 2958 { 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) 3420 2962 { 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) 3424 2966 { 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())); 3429 2991 } 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); 3432 2996 } 3433 2997 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)); 3437 2999 } 3438 3000 else 3439 KWFS_LOG(("F ailed to allocate %#x bytes for cache!\n", cbCache));3001 KWFS_LOG(("File to big to cache! %#llx\n", cbFile.QuadPart)); 3440 3002 } 3441 3003 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); 3443 3006 } 3444 3007 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 */ 3016 static KBOOL kwFsObjCacheCreateFile(PKFSOBJ pFsObj, DWORD dwDesiredAccess, BOOL fInheritHandle, HANDLE *phFile) 3480 3017 { 3481 3018 *phFile = INVALID_HANDLE_VALUE; 3019 kHlpAssert(pFsObj->fHaveStats); 3482 3020 3483 3021 /* 3484 3022 * At the moment we only handle existing files. 3485 3023 */ 3486 if ( !(pFsObj->fAttribs & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_DEVICE))) /* also checks invalid */3487 { 3488 if ( pFsObj->hCached != INVALID_HANDLE_VALUE3489 || (pwszFilename != NULL && kwFsObjCacheFileW(pFsObj, pwszFilename))3490 || (p szFilename != 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) 3491 3029 { 3492 3030 HANDLE hProcSelf = GetCurrentProcess(); 3493 if (DuplicateHandle(hProcSelf, p FsObj->hCached,3031 if (DuplicateHandle(hProcSelf, pCachedFile->hCached, 3494 3032 hProcSelf, phFile, 3495 3033 dwDesiredAccess, fInheritHandle, … … 3506 3044 pHandle->hHandle = *phFile; 3507 3045 pHandle->dwDesiredAccess = dwDesiredAccess; 3508 pHandle->u.p FsObj = pFsObj;3046 pHandle->u.pCachedFile = pCachedFile; 3509 3047 if (kwSandboxHandleTableEnter(&g_Sandbox, pHandle)) 3510 3048 return K_TRUE; … … 3549 3087 if (kwFsIsCachableExtensionA(pszExt, K_FALSE /*fAttrQuery*/)) 3550 3088 { 3551 PKWFSOBJ pFsObj = kwFsLookupA(pszFilename); 3089 KFSLOOKUPERROR enmError; 3090 PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError); 3552 3091 if (pFsObj) 3553 3092 { 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) 3556 3097 { 3557 3098 KWFS_LOG(("CreateFileA(%s) -> %p [cached]\n", pszFilename, hFile)); … … 3653 3194 { 3654 3195 case KWHANDLETYPE_FSOBJ_READ_CACHE: 3655 cbFile = pHandle->u.p FsObj->cbCached;3196 cbFile = pHandle->u.pCachedFile->cbCached; 3656 3197 break; 3657 3198 #ifdef WITH_TEMP_MEMORY_FILES … … 3733 3274 { 3734 3275 case KWHANDLETYPE_FSOBJ_READ_CACHE: 3735 cbFile = pHandle->u.p FsObj->cbCached;3276 cbFile = pHandle->u.pCachedFile->cbCached; 3736 3277 break; 3737 3278 #ifdef WITH_TEMP_MEMORY_FILES … … 3811 3352 case KWHANDLETYPE_FSOBJ_READ_CACHE: 3812 3353 { 3813 PK WFSOBJ pFsObj = pHandle->u.pFsObj;3814 KU32 cbActually = pFsObj->cbCached - pHandle->offFile;3354 PKFSWCACHEDFILE pCachedFile = pHandle->u.pCachedFile; 3355 KU32 cbActually = pCachedFile->cbCached - pHandle->offFile; 3815 3356 if (cbActually > cbToRead) 3816 3357 cbActually = cbToRead; … … 3818 3359 ((KU8 *)pvBuffer)[cbActually] = '\0'; // hack hack hack 3819 3360 3820 kHlpMemCopy(pvBuffer, &p FsObj->pbCached[pHandle->offFile], cbActually);3361 kHlpMemCopy(pvBuffer, &pCachedFile->pbCached[pHandle->offFile], cbActually); 3821 3362 pHandle->offFile += cbActually; 3822 3363 … … 4169 3710 { 4170 3711 case KWHANDLETYPE_FSOBJ_READ_CACHE: 4171 KWFS_LOG(("GetFileSize(%p) -> %#x [cached]\n", hFile, pHandle->u.p FsObj->cbCached));4172 return pHandle->u.p FsObj->cbCached;3712 KWFS_LOG(("GetFileSize(%p) -> %#x [cached]\n", hFile, pHandle->u.pCachedFile->cbCached)); 3713 return pHandle->u.pCachedFile->cbCached; 4173 3714 4174 3715 case KWHANDLETYPE_TEMP_FILE: … … 4201 3742 { 4202 3743 case KWHANDLETYPE_FSOBJ_READ_CACHE: 4203 KWFS_LOG(("GetFileSizeEx(%p) -> TRUE, %#x [cached]\n", hFile, pHandle->u.p FsObj->cbCached));4204 pcbFile->QuadPart = pHandle->u.p FsObj->cbCached;3744 KWFS_LOG(("GetFileSizeEx(%p) -> TRUE, %#x [cached]\n", hFile, pHandle->u.pCachedFile->cbCached)); 3745 pcbFile->QuadPart = pHandle->u.pCachedFile->cbCached; 4205 3746 return TRUE; 4206 3747 … … 4417 3958 if (kwFsIsCachableExtensionA(pszExt, K_TRUE /*fAttrQuery*/)) 4418 3959 { 4419 PKWFSOBJ pFsObj = kwFsLookupA(pszFilename); 3960 KFSLOOKUPERROR enmError; 3961 PKFSOBJ pFsObj = kFsCacheLookupNoMissingA(g_pFsCache, pszFilename, &enmError); 4420 3962 if (pFsObj) 4421 3963 { 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; 4427 3976 } 4428 3977 … … 4439 3988 if (kwFsIsCachablePathExtensionW(pwszFilename, K_TRUE /*fAttrQuery*/)) 4440 3989 { 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; 4446 4006 } 4447 4007 … … 4460 4020 if (kwFsIsCachablePathExtensionW(pwszLongPath, K_TRUE /*fAttrQuery*/)) 4461 4021 { 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)); 4474 4062 return cwcRet; 4475 4063 } … … 4791 4379 4792 4380 4793 g_uFsCacheGeneration++; 4794 if (g_uFsCacheGeneration == KFSWOBJ_CACHE_GEN_IGNORE) 4795 g_uFsCacheGeneration++; 4381 /** @todo cache generation increment. */ 4796 4382 return 0; 4797 4383 } … … 4968 4554 case KWTOOLTYPE_SANDBOXED: 4969 4555 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)) 4972 4564 { 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; 4983 4567 } 4984 4568 else 4985 4569 { 4986 4570 kwErrPrintf("SetCurrentDirectory failed with %u on '%s'\n", GetLastError(), pszCwd); 4571 kFsCacheObjRelease(g_pFsCache, pNewCurDir); 4987 4572 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; 4988 4586 } 4989 4587 break; 4588 } 4990 4589 4991 4590 case KWTOOLTYPE_EXEC: … … 5237 4836 5238 4837 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 */ 4845 static 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 5239 4916 int main(int argc, char **argv) 5240 4917 { … … 5245 4922 HANDLE hPipe = INVALID_HANDLE_VALUE; 5246 4923 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"); 5247 4930 5248 4931 /* … … 5266 4949 hPipe = (HANDLE)(uintptr_t)u64Value; 5267 4950 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]); 5272 4952 } 5273 4953 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]); 5279 4958 else if ( strcmp(argv[i], "--help") == 0 5280 4959 || strcmp(argv[i], "-h") == 0 … … 5284 4963 "usage: kWorker <--help|-h>\n" 5285 4964 "usage: kWorker <--version|-V>\n" 4965 "usage: kWorker --test [<times> [--chdir <dir>]] -- args\n" 5286 4966 "\n" 5287 4967 "This is an internal kmk program that is used via the builtin_kSubmit.\n"); … … 5292 4972 return kbuild_version(argv[0]); 5293 4973 else 5294 { 5295 kwErrPrintf("Unknown argument '%s'\n", argv[i]); 5296 return 2; 5297 } 4974 return kwErrPrintfRc(2, "Unknown argument '%s'\n", argv[i]); 5298 4975 } 5299 4976 5300 4977 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"); 5305 4979 5306 4980 /* … … 5325 4999 pbMsgBuf = kHlpRealloc(pbMsgBuf, cbMsgBuf); 5326 5000 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); 5331 5002 } 5332 5003 … … 5364 5035 } 5365 5036 else 5366 { 5367 kwErrPrintf("Unknown command: '%s'\n", psz); 5368 rc = -1; 5369 } 5037 rc = kwErrPrintfRc(-1, "Unknown command: '%s'\n", psz); 5370 5038 } 5371 5039 } 5372 5040 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); 5377 5042 } 5378 5043 return rc > 0 ? 0 : 1; -
trunk/src/kmk/kmkbuiltin/kSubmit.c
r2846 r2858 52 52 #ifdef KBUILD_OS_WINDOWS 53 53 # include "sub_proc.h" 54 # include "quote_argv.h"55 54 #endif 56 55 … … 1533 1532 if (pWorker) 1534 1533 { 1535 #ifdef KBUILD_OS_WINDOWS1536 /* 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);1540 1534 if (!pszExecutable) 1541 1535 pszExecutable = argv[iArg]; 1542 memcpy(papszArgsOrg, &argv[iArg], sizeof(argv[0]) * cArgs);1543 quote_argv(cArgs, &argv[iArg], fWatcomBrainDamage, 0 /*fFreeOrLeak*/);1544 #endif1545 1536 1546 1537 rcExit = kSubmitSendJobMessage(pWorker, pvMsg, cbMsg, 0 /*fNoRespawning*/, cVerbosity); … … 1551 1542 if (atexit(kSubmitAtExitCallback) == 0) 1552 1543 g_fAtExitRegistered = 1; 1553 1554 #ifdef KBUILD_OS_WINDOWS1555 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 #endif1563 1544 } 1564 1545 else -
trunk/src/lib/nt/kFsCache.c
r2857 r2858 2220 2220 * 2221 2221 * @returns Reference to object corresponding to @a pszPath on success, this 2222 * must be released by k wFsCacheRelease.2222 * must be released by kFsCacheObjRelease. 2223 2223 * NULL if not a path we care to cache. 2224 2224 * @param pCache The cache. … … 2246 2246 { 2247 2247 if ( pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE 2248 || pHashEntry->uCacheGen == pCache->uGeneration2248 || pHashEntry->uCacheGen == (pHashEntry->pFsObj ? pCache->uGeneration : pCache->uGenerationMissing) 2249 2249 || (pHashEntry = kFsCacheRefreshPathA(pCache, pHashEntry, idxHashTab)) ) 2250 2250 { … … 2310 2310 * 2311 2311 * @returns Reference to object corresponding to @a pszPath on success, this 2312 * must be released by k wFsCacheRelease.2312 * must be released by kFsCacheObjRelease. 2313 2313 * NULL if not a path we care to cache. 2314 2314 * @param pCache The cache. … … 2336 2336 { 2337 2337 if ( pHashEntry->uCacheGen == KFSOBJ_CACHE_GEN_IGNORE 2338 || pHashEntry->uCacheGen == pCache->uGeneration2338 || pHashEntry->uCacheGen == (pHashEntry->pFsObj ? pCache->uGeneration : pCache->uGenerationMissing) 2339 2339 || (pHashEntry = kFsCacheRefreshPathW(pCache, pHashEntry, idxHashTab)) ) 2340 2340 { … … 2390 2390 2391 2391 /** 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 */ 2403 PKFSOBJ 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 */ 2430 PKFSOBJ 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 /** 2392 2446 * Destroys a cache object which has a zero reference count. 2393 2447 * … … 2489 2543 KU32 kFsCacheObjRelease(PKFSCACHE pCache, PKFSOBJ pObj) 2490 2544 { 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; 2499 2557 } 2500 2558 … … 2572 2630 return NULL; 2573 2631 } 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 */ 2643 KBOOL 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 */ 2697 KBOOL 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 */ 2753 KBOOL 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 */ 2807 KBOOL 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 */ 2574 2852 2575 2853 … … 2621 2899 pCache->fFlags = fFlags; 2622 2900 pCache->uGeneration = 1; 2901 pCache->uGenerationMissing = KU32_MAX / 2; 2623 2902 pCache->cObjects = 1; 2624 2903 pCache->cbObjects = sizeof(pCache->RootDir) + pCache->RootDir.cHashTab * sizeof(pCache->RootDir.paHashTab[0]); -
trunk/src/lib/nt/kFsCache.h
r2857 r2858 427 427 PKFSOBJ kFsCacheLookupRelativeToDirW(PKFSCACHE pCache, PKFSDIR pParent, const wchar_t *pwszPath, KU32 cwcPath, 428 428 KFSLOOKUPERROR *penmError); 429 PKFSOBJ kFsCacheLookupNoMissingA(PKFSCACHE pCache, const char *pszPath, KFSLOOKUPERROR *penmError); 430 PKFSOBJ kFsCacheLookupNoMissingW(PKFSCACHE pCache, const wchar_t *pwszPath, KFSLOOKUPERROR *penmError); 431 429 432 430 433 KU32 kFsCacheObjRelease(PKFSCACHE pCache, PKFSOBJ pObj); 431 434 KU32 kFsCacheObjRetain(PKFSOBJ pObj); 432 PKFSUSERDATA kFsCacheObjAddUserData(PKFSCACHE pCache, PKFSOBJ pPathObj, KUPTR uKey, KSIZE cbUserData); 433 PKFSUSERDATA kFsCacheObjGetUserData(PKFSCACHE pCache, PKFSOBJ pPathObj, KUPTR uKey); 435 PKFSUSERDATA kFsCacheObjAddUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey, KSIZE cbUserData); 436 PKFSUSERDATA kFsCacheObjGetUserData(PKFSCACHE pCache, PKFSOBJ pObj, KUPTR uKey); 437 KBOOL kFsCacheObjGetFullPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash); 438 KBOOL kFsCacheObjGetFullPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash); 439 KBOOL kFsCacheObjGetFullShortPathA(PKFSOBJ pObj, char *pszPath, KSIZE cbPath, char chSlash); 440 KBOOL kFsCacheObjGetFullShortPathW(PKFSOBJ pObj, wchar_t *pwszPath, KSIZE cwcPath, wchar_t wcSlash); 434 441 435 442 PKFSCACHE kFsCacheCreate(KU32 fFlags); -
trunk/src/lib/nt/ntstat.c
r2851 r2858 208 208 pStat->st_uid = 0; 209 209 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; 213 212 pStat->st_blksize = 65536; 214 213 pStat->st_blocks = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1) … … 241 240 pStat->st_uid = 0; 242 241 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; 246 244 pStat->st_blksize = 65536; 247 245 pStat->st_blocks = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1) … … 274 272 pStat->st_uid = 0; 275 273 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; 279 276 pStat->st_blksize = 65536; 280 277 pStat->st_blocks = (pBuf->AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1) … … 314 311 pStat->st_uid = 0; 315 312 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; 319 315 pStat->st_blksize = 65536; 320 316 pStat->st_blocks = (pAll->StandardInformation.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1) … … 389 385 pStat->st_uid = 0; 390 386 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; 394 389 pStat->st_blksize = 65536; 395 390 pStat->st_blocks = (StdInfo.AllocationSize.QuadPart + BIRD_STAT_BLOCK_SIZE - 1) … … 608 603 pStat->st_uid = 0; 609 604 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; 613 607 pStat->st_blksize = 512; 614 608 pStat->st_blocks = 0; -
trunk/src/lib/nt/ntstat.h
r2856 r2858 63 63 __int16 st_uid; 64 64 __int16 st_gid; 65 unsigned __int16 st_padding1[3]; 65 unsigned __int16 st_padding1; 66 unsigned __int32 st_attribs; 66 67 unsigned __int32 st_blksize; 67 68 __int64 st_blocks; -
trunk/src/lib/nt/ntstuff.h
r2852 r2858 36 36 #define WIN32_NO_STATUS 37 37 #include <Windows.h> 38 #include <winternl.h> 38 39 #undef WIN32_NO_STATUS 39 40 #include <ntstatus.h>
Note:
See TracChangeset
for help on using the changeset viewer.